Previous 199869 Revisions Next

r32171 Thursday 18th September, 2014 at 08:09:18 UTC by Miodrag Milanović
(OSD BRANCH) Sync OSD with main branch
[/branches/osd/src/osd/modules/sound]direct_sound.c
[/branches/osd/src/osd/sdl]SDLMain_tmpl.m sdl.mak sdlfile.c sdlmain.c sdlos_win32.c sdlsync_win32.c sdlwork.c video.c
[/branches/osd/src/osd/windows]windows.mak winos.c* winos.h* winsync.c winsync.h* winwork.c

branches/osd/src/osd/sdl/video.c
r32170r32171
487487static sdl_monitor_info *pick_monitor(sdl_options &options, int index)
488488{
489489   sdl_monitor_info *monitor;
490   const char *scrname;
490   const char *scrname, *scrname2;
491491   int moncount = 0;
492492   float aspect;
493493
494494   // get the screen option
495   scrname = options.screen(index);
495   scrname = options.screen();
496   scrname2 = options.screen(index);
496497
498   // decide which one we want to use
499   if (strcmp(scrname2, "auto") != 0)
500      scrname = scrname2;
501
497502   // get the aspect ratio
498503   aspect = get_aspect(options.aspect(), options.aspect(index), TRUE);
499504
500505   // look for a match in the name first
501506   if (scrname != NULL)
507   {
502508      for (monitor = sdl_monitor_list; monitor != NULL; monitor = monitor->next)
503509      {
504510         moncount++;
505511         if (strcmp(scrname, monitor->monitor_device) == 0)
506512            goto finishit;
507513      }
514   }
508515
509516   // didn't find it; alternate monitors until we hit the jackpot
510517   index %= moncount;
branches/osd/src/osd/sdl/sdlfile.c
r32170r32171
307307         *actual = result;
308308
309309         return FILERR_NONE;
310         break;
311310
312311      case SDLFILE_SOCKET:
313312         return sdl_read_socket(file, buffer, offset, count, actual);
314         break;
315313
316314      case SDLFILE_PTTY:
317315         return sdl_read_ptty(file, buffer, offset, count, actual);
318         break;
319316
320317      default:
321318         return FILERR_FAILURE;
r32170r32171
352349         if (actual != NULL)
353350         *actual = result;
354351         return FILERR_NONE;
355         break;
356352
357353      case SDLFILE_SOCKET:
358354         return sdl_write_socket(file, buffer, offset, count, actual);
359         break;
360355
361356      case SDLFILE_PTTY:
362357         return sdl_write_ptty(file, buffer, offset, count, actual);
363         break;
364358
365359      default:
366360         return FILERR_FAILURE;
r32170r32171
383377         if (!result)
384378            return error_to_file_error(errno);
385379         return FILERR_NONE;
386         break;
387380
388381      default:
389382         return FILERR_FAILURE;
r32170r32171
404397         close(file->handle);
405398         osd_free(file);
406399         return FILERR_NONE;
407         break;
408400
409401      case SDLFILE_SOCKET:
410402         return sdl_close_socket(file);
411         break;
412403
413404      case SDLFILE_PTTY:
414405         return sdl_close_ptty(file);
415         break;
416406
417407      default:
418408         return FILERR_FAILURE;
branches/osd/src/osd/sdl/sdlwork.c
r32170r32171
4444//  PARAMETERS
4545//============================================================
4646
47#define SDLENV_PROCESSORS               "OSDPROCESSORS"
48#define SDLENV_CPUMASKS                 "OSDCPUMASKS"
47#define ENV_PROCESSORS               "OSDPROCESSORS"
48#define ENV_CPUMASKS                 "OSDCPUMASKS"
49#define ENV_WORKQUEUEMAXTHREADS      "OSDWORKQUEUEMAXTHREADS"
4950
5051#define INFINITE                (osd_ticks_per_second() *  (osd_ticks_t) 10000)
5152#define SPIN_LOOP_TIME          (osd_ticks_per_second() / 10000)
r32170r32171
151152   int numprocs = effective_num_processors();
152153   osd_work_queue *queue;
153154   int threadnum;
155   char *osdworkqueuemaxthreads = osd_getenv("OSDWORKQUEUEMAXTHREADS");
154156
155157   // allocate a new queue
156158   queue = (osd_work_queue *)osd_malloc(sizeof(*queue));
r32170r32171
181183   else
182184      queue->threads = (flags & WORK_QUEUE_FLAG_MULTI) ? (numprocs - 1) : 1;
183185
186   if (osdworkqueuemaxthreads != NULL && sscanf(osdworkqueuemaxthreads, "%d", &threadnum) == 1 && queue->threads > threadnum)
187      queue->threads = threadnum;
188
189
184190   // clamp to the maximum
185191   queue->threads = MIN(queue->threads, WORK_MAX_THREADS);
186192
r32170r32171
564570
565571static int effective_num_processors(void)
566572{
567   char *procsoverride;
568   int numprocs = 0;
569573   int physprocs = osd_get_num_processors();
570574
571575   // osd_num_processors == 0 for 'auto'
572576   if (osd_num_processors > 0)
577   {
573578      return MIN(4 * physprocs, osd_num_processors);
579   }
574580   else
575581   {
582      char *procsoverride;
583      int numprocs = 0;
584
576585      // if the OSDPROCESSORS environment variable is set, use that value if valid
577      procsoverride = osd_getenv(SDLENV_PROCESSORS);
586      // note that we permit more than the real number of processors for testing
587      procsoverride = osd_getenv(ENV_PROCESSORS);
578588      if (procsoverride != NULL && sscanf(procsoverride, "%d", &numprocs) == 1 && numprocs > 0)
579589         return MIN(4 * physprocs, numprocs);
580590
r32170r32171
593603   char    buf[5];
594604   UINT32  mask = 0xFFFF;
595605
596   s = osd_getenv(SDLENV_CPUMASKS);
606   s = osd_getenv(ENV_CPUMASKS);
597607   if (s != NULL && strcmp(s,"none"))
598608   {
599609      if (!strcmp(s,"auto"))
branches/osd/src/osd/sdl/sdlmain.c
r32170r32171
1313#ifdef SDLMAME_UNIX
1414#if (!defined(SDLMAME_MACOSX)) && (!defined(SDLMAME_EMSCRIPTEN))
1515#if (SDLMAME_SDL2)
16//#include <SDL2/SDL_ttf.h>
16#include <SDL2/SDL_ttf.h>
1717#else
1818#include <SDL/SDL_ttf.h>
1919#endif
r32170r32171
5353#if defined(SDLMAME_EMSCRIPTEN)
5454#include "modules/sound/js_sound.h"
5555#endif
56#if defined(SDLMAME_WIN32)
57#include "modules/sound/direct_sound.h"
58#endif
5659#if !defined(NO_DEBUGGER)
5760#include "modules/debugger/debugqt.h"
5861#endif
r32170r32171
7073
7174#include "watchdog.h"
7275
76#define DEFAULT_FONT_HEIGHT (200)
77
7378//============================================================
7479//  OPTIONS
7580//============================================================
r32170r32171
291296   #ifdef SDLMAME_UNIX
292297   sdl_entered_debugger = 0;
293298   #if (!defined(SDLMAME_MACOSX)) && (!defined(SDLMAME_HAIKU)) && (!defined(SDLMAME_EMSCRIPTEN))
294#if !(SDLMAME_SDL2)
295299   if (TTF_Init() == -1)
296300   {
297301      printf("SDL_ttf failed: %s\n", TTF_GetError());
298302   }
299#endif
300303   FcInit();
301304   #endif
302305   #endif
r32170r32171
344347
345348   #ifdef SDLMAME_UNIX
346349   #if (!defined(SDLMAME_MACOSX)) && (!defined(SDLMAME_HAIKU)) && (!defined(SDLMAME_EMSCRIPTEN))
347#if !(SDLMAME_SDL2)
348350   TTF_Quit();
349#endif
350351   if (!sdl_entered_debugger)
351352   {
352353      FcFini();
r32170r32171
355356   #endif
356357
357358   exit(res);
358
359   return res;
360359}
361360
362361
r32170r32171
542541void sdl_osd_interface::sound_register()
543542{
544543   sound_options_add("sdl", OSD_SOUND_SDL);
544#if defined(SDLMAME_WIN32)
545   sound_options_add("dsound", OSD_SOUND_DIRECT_SOUND);
546#endif
547
545548#if defined(SDLMAME_EMSCRIPTEN)
546549   sound_options_add("js", OSD_SOUND_JS);
547550   sound_options_add("auto", OSD_SOUND_JS); // making JS audio default one
r32170r32171
854857}
855858#else // UNIX but not OSX
856859
857#if !(SDLMAME_SDL2)
858860static TTF_Font * TTF_OpenFont_Magic(astring name, int fsize)
859861{
860862   emu_file file(OPEN_FLAG_READ);
r32170r32171
994996   return font;
995997}
996998#endif
997#endif
998999
9991000//-------------------------------------------------
10001001//  font_open - attempt to "open" a handle to the
r32170r32171
10031004
10041005osd_font sdl_osd_interface::font_open(const char *_name, int &height)
10051006{
1006#if !(SDLMAME_SDL2)
10071007   TTF_Font *font = (TTF_Font *)NULL;
10081008   bool bakedstyles = false;
10091009   int style = 0;
r32170r32171
10751075   height = TTF_FontLineSkip(font);
10761076
10771077   return (osd_font)font;
1078#else
1079   return (osd_font)NULL;
1080#endif
10811078}
10821079
10831080//-------------------------------------------------
r32170r32171
10871084
10881085void sdl_osd_interface::font_close(osd_font font)
10891086{
1090#if !(SDLMAME_SDL2)
10911087   TTF_Font *ttffont;
10921088
10931089   ttffont = (TTF_Font *)font;
10941090
10951091   TTF_CloseFont(ttffont);
1096#endif
10971092}
10981093
10991094//-------------------------------------------------
r32170r32171
11061101
11071102bool sdl_osd_interface::font_get_bitmap(osd_font font, unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs)
11081103{
1109#if !(SDLMAME_SDL2)
11101104   TTF_Font *ttffont;
11111105   SDL_Surface *drawsurf;
11121106   SDL_Color fcol = { 0xff, 0xff, 0xff };
r32170r32171
11461140   }
11471141
11481142   return bitmap.valid();
1149#else
1150   return false;
1151#endif
11521143}
11531144#endif  // not OSX
11541145#else   // not UNIX
1146#ifdef SDLMAME_WIN32
1147
1148//============================================================
1149//  wstring_from_utf8
1150//============================================================
1151
1152WCHAR *wstring_from_utf8(const char *utf8string)
1153{
1154   int char_count;
1155   WCHAR *result;
1156
1157   // convert MAME string (UTF-8) to UTF-16
1158   char_count = MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, NULL, 0);
1159   result = (WCHAR *)osd_malloc_array(char_count * sizeof(*result));
1160   if (result != NULL)
1161      MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, result, char_count);
1162
1163   return result;
1164}
1165
1166
1167//============================================================
1168//  utf8_from_wstring
1169//============================================================
1170
1171char *utf8_from_wstring(const WCHAR *wstring)
1172{
1173   int char_count;
1174   char *result;
1175
1176   // convert UTF-16 to MAME string (UTF-8)
1177   char_count = WideCharToMultiByte(CP_UTF8, 0, wstring, -1, NULL, 0, NULL, NULL);
1178   result = (char *)osd_malloc_array(char_count * sizeof(*result));
1179   if (result != NULL)
1180      WideCharToMultiByte(CP_UTF8, 0, wstring, -1, result, char_count, NULL, NULL);
1181
1182   return result;
1183}
1184
1185osd_font sdl_osd_interface::font_open(const char *_name, int &height)
1186{
1187   // accept qualifiers from the name
1188   astring name(_name);
1189   if (name == "default") name = "Tahoma";
1190   bool bold = (name.replace(0, "[B]", "") + name.replace(0, "[b]", "") > 0);
1191   bool italic = (name.replace(0, "[I]", "") + name.replace(0, "[i]", "") > 0);
1192
1193   // build a basic LOGFONT description of what we want
1194   LOGFONT logfont;
1195   logfont.lfHeight = DEFAULT_FONT_HEIGHT;
1196   logfont.lfWidth = 0;
1197   logfont.lfEscapement = 0;
1198   logfont.lfOrientation = 0;
1199   logfont.lfWeight = bold ? FW_BOLD : FW_MEDIUM;
1200   logfont.lfItalic = italic;
1201   logfont.lfUnderline = FALSE;
1202   logfont.lfStrikeOut = FALSE;
1203   logfont.lfCharSet = ANSI_CHARSET;
1204   logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
1205   logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1206   logfont.lfQuality = NONANTIALIASED_QUALITY;
1207   logfont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
1208
1209   // copy in the face name
1210   TCHAR *face = wstring_from_utf8(name);
1211   wcsncpy(logfont.lfFaceName, face, sizeof(logfont.lfFaceName) / sizeof(TCHAR));
1212   logfont.lfFaceName[sizeof(logfont.lfFaceName) / sizeof(TCHAR)-1] = 0;
1213   osd_free(face);
1214
1215   // create the font
1216   height = logfont.lfHeight;
1217   osd_font font = reinterpret_cast<osd_font>(CreateFontIndirect(&logfont));
1218   if (font == NULL)
1219      return NULL;
1220
1221   // select it into a temp DC and get the real font name
1222   HDC dummyDC = CreateCompatibleDC(NULL);
1223   HGDIOBJ oldfont = SelectObject(dummyDC, reinterpret_cast<HGDIOBJ>(font));
1224   TCHAR realname[100];
1225   GetTextFace(dummyDC, ARRAY_LENGTH(realname), realname);
1226   SelectObject(dummyDC, oldfont);
1227   DeleteDC(dummyDC);
1228
1229   // if it doesn't match our request, fail
1230   char *utf = utf8_from_wstring(realname);
1231   int result = core_stricmp(utf, name);
1232   osd_free(utf);
1233
1234   // if we didn't match, nuke our font and fall back
1235   if (result != 0)
1236   {
1237      DeleteObject(reinterpret_cast<HFONT>(font));
1238      font = NULL;
1239   }
1240   return font;
1241}
1242
1243
11551244//-------------------------------------------------
1245//  font_close - release resources associated with
1246//  a given OSD font
1247//-------------------------------------------------
1248
1249void sdl_osd_interface::font_close(osd_font font)
1250{
1251   // delete the font ojbect
1252   if (font != NULL)
1253      DeleteObject(reinterpret_cast<HFONT>(font));
1254}
1255
1256
1257//-------------------------------------------------
1258//  font_get_bitmap - allocate and populate a
1259//  BITMAP_FORMAT_ARGB32 bitmap containing the
1260//  pixel values rgb_t(0xff,0xff,0xff,0xff)
1261//  or rgb_t(0x00,0xff,0xff,0xff) for each
1262//  pixel of a black & white font
1263//-------------------------------------------------
1264
1265bool sdl_osd_interface::font_get_bitmap(osd_font font, unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs)
1266{
1267   // create a dummy DC to work with
1268   HDC dummyDC = CreateCompatibleDC(NULL);
1269   HGDIOBJ oldfont = SelectObject(dummyDC, reinterpret_cast<HGDIOBJ>(font));
1270
1271   // get the text metrics
1272   TEXTMETRIC metrics = { 0 };
1273   GetTextMetrics(dummyDC, &metrics);
1274
1275   // get the width of this character
1276   ABC abc;
1277   if (!GetCharABCWidths(dummyDC, chnum, chnum, &abc))
1278   {
1279      abc.abcA = 0;
1280      abc.abcC = 0;
1281      GetCharWidth32(dummyDC, chnum, chnum, reinterpret_cast<LPINT>(&abc.abcB));
1282   }
1283   width = abc.abcA + abc.abcB + abc.abcC;
1284
1285   // determine desired bitmap size
1286   int bmwidth = (50 + abc.abcA + abc.abcB + abc.abcC + 50 + 31) & ~31;
1287   int bmheight = 50 + metrics.tmHeight + 50;
1288
1289   // describe the bitmap we want
1290   BYTE bitmapinfodata[sizeof(BITMAPINFOHEADER)+2 * sizeof(RGBQUAD)] = { 0 };
1291   BITMAPINFO &info = *reinterpret_cast<BITMAPINFO *>(bitmapinfodata);
1292   info.bmiHeader.biSize = sizeof(info.bmiHeader);
1293   info.bmiHeader.biWidth = bmwidth;
1294   info.bmiHeader.biHeight = -bmheight;
1295   info.bmiHeader.biPlanes = 1;
1296   info.bmiHeader.biBitCount = 1;
1297   info.bmiHeader.biCompression = BI_RGB;
1298   info.bmiHeader.biSizeImage = 0;
1299   info.bmiHeader.biXPelsPerMeter = GetDeviceCaps(dummyDC, HORZRES) / GetDeviceCaps(dummyDC, HORZSIZE);
1300   info.bmiHeader.biYPelsPerMeter = GetDeviceCaps(dummyDC, VERTRES) / GetDeviceCaps(dummyDC, VERTSIZE);
1301   info.bmiHeader.biClrUsed = 0;
1302   info.bmiHeader.biClrImportant = 0;
1303   RGBQUAD col1 = info.bmiColors[0];
1304   RGBQUAD col2 = info.bmiColors[1];
1305   col1.rgbBlue = col1.rgbGreen = col1.rgbRed = 0x00;
1306   col2.rgbBlue = col2.rgbGreen = col2.rgbRed = 0xff;
1307
1308   // create a DIB to render to
1309   BYTE *bits;
1310   HBITMAP dib = CreateDIBSection(dummyDC, &info, DIB_RGB_COLORS, reinterpret_cast<VOID **>(&bits), NULL, 0);
1311   HGDIOBJ oldbitmap = SelectObject(dummyDC, dib);
1312
1313   // clear the bitmap
1314   int rowbytes = bmwidth / 8;
1315   memset(bits, 0, rowbytes * bmheight);
1316
1317   // now draw the character
1318   WCHAR tempchar = chnum;
1319   SetTextColor(dummyDC, RGB(0xff, 0xff, 0xff));
1320   SetBkColor(dummyDC, RGB(0x00, 0x00, 0x00));
1321   ExtTextOutW(dummyDC, 50 + abc.abcA, 50, ETO_OPAQUE, NULL, &tempchar, 1, NULL);
1322
1323   // characters are expected to be full-height
1324   rectangle actbounds;
1325   actbounds.min_y = 50;
1326   actbounds.max_y = 50 + metrics.tmHeight - 1;
1327
1328   // determine the actual left of the character
1329   for (actbounds.min_x = 0; actbounds.min_x < rowbytes; actbounds.min_x++)
1330   {
1331      BYTE *offs = bits + actbounds.min_x;
1332      UINT8 summary = 0;
1333      for (int y = 0; y < bmheight; y++)
1334         summary |= offs[y * rowbytes];
1335      if (summary != 0)
1336      {
1337         actbounds.min_x *= 8;
1338         if (!(summary & 0x80)) actbounds.min_x++;
1339         if (!(summary & 0xc0)) actbounds.min_x++;
1340         if (!(summary & 0xe0)) actbounds.min_x++;
1341         if (!(summary & 0xf0)) actbounds.min_x++;
1342         if (!(summary & 0xf8)) actbounds.min_x++;
1343         if (!(summary & 0xfc)) actbounds.min_x++;
1344         if (!(summary & 0xfe)) actbounds.min_x++;
1345         break;
1346      }
1347   }
1348
1349   // determine the actual right of the character
1350   for (actbounds.max_x = rowbytes - 1; actbounds.max_x >= 0; actbounds.max_x--)
1351   {
1352      BYTE *offs = bits + actbounds.max_x;
1353      UINT8 summary = 0;
1354      for (int y = 0; y < bmheight; y++)
1355         summary |= offs[y * rowbytes];
1356      if (summary != 0)
1357      {
1358         actbounds.max_x *= 8;
1359         if (summary & 0x7f) actbounds.max_x++;
1360         if (summary & 0x3f) actbounds.max_x++;
1361         if (summary & 0x1f) actbounds.max_x++;
1362         if (summary & 0x0f) actbounds.max_x++;
1363         if (summary & 0x07) actbounds.max_x++;
1364         if (summary & 0x03) actbounds.max_x++;
1365         if (summary & 0x01) actbounds.max_x++;
1366         break;
1367      }
1368   }
1369
1370   // allocate a new bitmap
1371   if (actbounds.max_x >= actbounds.min_x && actbounds.max_y >= actbounds.min_y)
1372   {
1373      bitmap.allocate(actbounds.max_x + 1 - actbounds.min_x, actbounds.max_y + 1 - actbounds.min_y);
1374
1375      // copy the bits into it
1376      for (int y = 0; y < bitmap.height(); y++)
1377      {
1378         UINT32 *dstrow = &bitmap.pix32(y);
1379         UINT8 *srcrow = &bits[(y + actbounds.min_y) * rowbytes];
1380         for (int x = 0; x < bitmap.width(); x++)
1381         {
1382            int effx = x + actbounds.min_x;
1383            dstrow[x] = ((srcrow[effx / 8] << (effx % 8)) & 0x80) ? rgb_t(0xff, 0xff, 0xff, 0xff) : rgb_t(0x00, 0xff, 0xff, 0xff);
1384         }
1385      }
1386
1387      // set the final offset values
1388      xoffs = actbounds.min_x - (50 + abc.abcA);
1389      yoffs = actbounds.max_y - (50 + metrics.tmAscent);
1390   }
1391
1392   // de-select the font and release the DC
1393   SelectObject(dummyDC, oldbitmap);
1394   DeleteObject(dib);
1395   SelectObject(dummyDC, oldfont);
1396   DeleteDC(dummyDC);
1397   return bitmap.valid();
1398}
1399
1400#else
1401
1402//-------------------------------------------------
11561403//  font_open - attempt to "open" a handle to the
11571404//  font with the given name
11581405//-------------------------------------------------
r32170r32171
11841431   return false;
11851432}
11861433#endif
1434#endif
branches/osd/src/osd/sdl/sdlsync_win32.c
r32170r32171
99//
1010//============================================================
1111
12#define WIN32_LEAN_AND_MEAN
13#include <windows.h>
14#include <process.h>
15#include <tchar.h>
16
17#ifdef __GNUC__
18#include <stdint.h>
19#endif
20
21// MAME headers
22#include "osdcore.h"
23#include "osinline.h"
24#include "sdlsync.h"
25
26#include "../windows/winsync.c"
27
28
29//============================================================
30//  DEBUGGING
31//============================================================
32
33#define USE_SCALABLE_LOCKS      (0)
34
35struct osd_event
36{
37   void *  ptr;
38};
39
40struct osd_thread {
41   HANDLE handle;
42   osd_thread_callback callback;
43   void *param;
44};
45
46//============================================================
47//  osd_event_alloc
48//============================================================
49
50osd_event *osd_event_alloc(int manualreset, int initialstate)
51{
52   return (osd_event *) CreateEvent(NULL, manualreset, initialstate, NULL);
53}
54
55//============================================================
56//  osd_event_free
57//============================================================
58
59void osd_event_free(osd_event *event)
60{
61   CloseHandle((HANDLE) event);
62}
63
64//============================================================
65//  osd_event_set
66//============================================================
67
68void osd_event_set(osd_event *event)
69{
70   SetEvent((HANDLE) event);
71}
72
73//============================================================
74//  osd_event_reset
75//============================================================
76
77void osd_event_reset(osd_event *event)
78{
79   ResetEvent((HANDLE) event);
80}
81
82//============================================================
83//  osd_event_wait
84//============================================================
85
86int osd_event_wait(osd_event *event, osd_ticks_t timeout)
87{
88   int ret = WaitForSingleObject((HANDLE) event, timeout * 1000 / osd_ticks_per_second());
89   return ( ret == WAIT_OBJECT_0);
90}
91
92//============================================================
93//  Scalable Locks
94//============================================================
95
96struct osd_scalable_lock
97{
98#if USE_SCALABLE_LOCKS
99   struct
100   {
101      volatile INT32  haslock;        // do we have the lock?
102      INT32           filler[64/4-1]; // assumes a 64-byte cache line
103   } slot[WORK_MAX_THREADS];           // one slot per thread
104   volatile INT32      nextindex;      // index of next slot to use
105#else
106   CRITICAL_SECTION    section;
107#endif
108};
109
110osd_scalable_lock *osd_scalable_lock_alloc(void)
111{
112   osd_scalable_lock *lock;
113
114   lock = (osd_scalable_lock *)calloc(1, sizeof(*lock));
115
116   memset(lock, 0, sizeof(*lock));
117#if USE_SCALABLE_LOCKS
118   lock->slot[0].haslock = TRUE;
119#else
120   InitializeCriticalSection(&lock->section);
121#endif
122   return lock;
123}
124
125
126INT32 osd_scalable_lock_acquire(osd_scalable_lock *lock)
127{
128#if USE_SCALABLE_LOCKS
129   INT32 myslot = (interlocked_increment(&lock->nextindex) - 1) & (WORK_MAX_THREADS - 1);
130   INT32 backoff = 1;
131
132   while (!lock->slot[myslot].haslock)
133   {
134      INT32 backcount;
135      for (backcount = 0; backcount < backoff; backcount++)
136         YieldProcessor();
137      backoff <<= 1;
138   }
139   lock->slot[myslot].haslock = FALSE;
140   return myslot;
141#else
142   EnterCriticalSection(&lock->section);
143   return 0;
144#endif
145}
146
147
148void osd_scalable_lock_release(osd_scalable_lock *lock, INT32 myslot)
149{
150#if USE_SCALABLE_LOCKS
151   interlocked_exchange32(&lock->slot[(myslot + 1) & (WORK_MAX_THREADS - 1)].haslock, TRUE);
152#else
153   LeaveCriticalSection(&lock->section);
154#endif
155}
156
157void osd_scalable_lock_free(osd_scalable_lock *lock)
158{
159   free(lock);
160}
161
162//============================================================
163//  osd_thread_create
164//============================================================
165
166static unsigned __stdcall worker_thread_entry(void *param)
167{
168   osd_thread *thread = (osd_thread *) param;
169   void *res;
170   res = thread->callback(thread->param);
171#ifdef PTR64
172   return (unsigned) (long long) res;
173#else
174   return (unsigned) res;
175#endif
176}
177
178osd_thread *osd_thread_create(osd_thread_callback callback, void *cbparam)
179{
180   osd_thread *thread;
181   uintptr_t handle;
182
183   thread = (osd_thread *)calloc(1, sizeof(osd_thread));
184   thread->callback = callback;
185   thread->param = cbparam;
186   handle = _beginthreadex(NULL, 0, worker_thread_entry, thread, 0, NULL);
187   thread->handle = (HANDLE) handle;
188   return thread;
189}
190
191//============================================================
192//  osd_thread_wait_free
193//============================================================
194
195void osd_thread_wait_free(osd_thread *thread)
196{
197   WaitForSingleObject(thread->handle, INFINITE);
198   CloseHandle(thread->handle);
199   free(thread);
200}
201
202//============================================================
203//  osd_thread_adjust_priority
204//============================================================
205
206int osd_thread_adjust_priority(osd_thread *thread, int adjust)
207{
208   if (adjust)
209      SetThreadPriority(thread->handle, THREAD_PRIORITY_ABOVE_NORMAL);
210   else
211      SetThreadPriority(thread->handle, GetThreadPriority(GetCurrentThread()));
212   return TRUE;
213}
214
215//============================================================
216//  osd_thread_cpu_affinity
217//============================================================
218
219int osd_thread_cpu_affinity(osd_thread *thread, UINT32 mask)
220{
221   return TRUE;
222}
223
224//============================================================
225//  osd_process_kill
226//============================================================
227
228void osd_process_kill(void)
229{
230   TerminateProcess(GetCurrentProcess(), -1);
231}
12#include "../windows/winsync.c"
No newline at end of file
branches/osd/src/osd/sdl/sdlos_win32.c
r32170r32171
2020#include "osdcore.h"
2121#include "strconv.h"
2222
23#include "../windows/winos.c"
24
2325//============================================================
2426//  PROTOTYPES
2527//============================================================
r32170r32171
158160}
159161
160162//============================================================
161//  osd_num_processors
162//============================================================
163
164int osd_get_num_processors(void)
165{
166   SYSTEM_INFO info;
167
168   // otherwise, fetch the info from the system
169   GetSystemInfo(&info);
170
171   // max out at 4 for now since scaling above that seems to do poorly
172   return MIN(info.dwNumberOfProcessors, 4);
173}
174
175//============================================================
176163//  osd_malloc
177164//============================================================
178165
r32170r32171
254241}
255242
256243//============================================================
257//  osd_getenv
258//============================================================
259
260char *osd_getenv(const char *name)
261{
262   return getenv(name);
263}
264
265//============================================================
266244//  osd_setenv
267245//============================================================
268246
branches/osd/src/osd/sdl/sdl.mak
r32170r32171
5959# active development on sdlmame or SDL.
6060
6161# uncomment the next line to compile and link against SDL2.0
62#SDL_LIBVER = sdl2
62# SDL_LIBVER = sdl2
6363
6464# uncomment the next line to use couriersud's multi-keyboard patch for SDL 2.1? (this API was removed prior to the 2.0 release)
6565# SDL2_MULTIAPI = 1
r32170r32171
272272endif
273273
274274SYNC_IMPLEMENTATION = ntc
275
276# SDLMain_tmpl isn't necessary for SDL2
277ifneq ($(SDL_LIBVER),sdl2)
275278SDLMAIN = $(SDLOBJ)/SDLMain_tmpl.o
276279SDLUTILMAIN = $(SDLOBJ)/SDLMain_tmpl.o
280endif
281
277282SDL_NETWORK = pcap
278283MAINLDFLAGS = -Xlinker -all_load
279284NO_X11 = 1
r32170r32171
404409   $(SDLOBJ)/output.o \
405410   $(SDLOBJ)/watchdog.o \
406411
412ifeq ($(BASE_TARGETOS),win32)
413   OSDOBJS += $(OSDOBJ)/modules/sound/direct_sound.o
414endif
415
407416ifdef NO_USE_MIDI
408417DEFS += -DDISABLE_MIDI=1
409418endif
r32170r32171
477486
478487ifndef MACOSX_USE_LIBSDL
479488# Compile using framework (compile using libSDL is the exception)
489ifeq ($(SDL_LIBVER),sdl2)
490LIBS += -F$(SDL_FRAMEWORK_PATH) -framework SDL2 -framework Cocoa -framework OpenGL -lpthread
491else
480492LIBS += -F$(SDL_FRAMEWORK_PATH) -framework SDL -framework Cocoa -framework OpenGL -lpthread
493endif
481494INCPATH += -F$(SDL_FRAMEWORK_PATH)
482495else
483496# Compile using installed libSDL (Fink or MacPorts):
r32170r32171
549562LIBS += `pkg-config --libs fontconfig`
550563
551564ifeq ($(SDL_LIBVER),sdl2)
552#LIBS += -lSDL2_ttf
565LIBS += -lSDL2_ttf
553566else
554567LIBS += -lSDL_ttf
555568endif
branches/osd/src/osd/sdl/SDLMain_tmpl.m
r32170r32171
77    Feel free to customize this file to suit your needs
88*/
99
10#import "SDL/SDL.h"
10#import "sdlinc.h"
1111#import "SDLMain_tmpl.h"
1212#import <sys/param.h> /* for MAXPATHLEN */
1313#import <unistd.h>
branches/osd/src/osd/modules/sound/direct_sound.c
r32170r32171
2323
2424// MAMEOS headers
2525#include "direct_sound.h"
26
27#ifdef SDLMAME_WIN32
28#include "../../sdl/osdsdl.h"
29#if (SDLMAME_SDL2)
30#include <SDL2/SDL_syswm.h>
31#else
32#include <SDL/SDL_syswm.h>
33#endif
34#include "../../sdl/window.h"
35#else
2636#include "winmain.h"
2737#include "window.h"
38#endif
2839
2940//============================================================
3041//  DEBUGGING
r32170r32171
234245   }
235246
236247   // set the cooperative level
248   #ifdef SDLMAME_WIN32
249   SDL_SysWMinfo wminfo;
250   SDL_VERSION(&wminfo.version);
251#if (SDLMAME_SDL2)
252   SDL_GetWindowWMInfo(sdl_window_list->sdl_window, &wminfo);
253   result = IDirectSound_SetCooperativeLevel(dsound, wminfo.info.win.window, DSSCL_PRIORITY);
254#else
255   SDL_GetWMInfo(&wminfo);
256   result = IDirectSound_SetCooperativeLevel(dsound, wminfo.window, DSSCL_PRIORITY);
257#endif
258   #else
237259   result = IDirectSound_SetCooperativeLevel(dsound, win_window_list->m_hwnd, DSSCL_PRIORITY);
260   #endif
238261   if (result != DS_OK)
239262   {
240263      osd_printf_error("Error setting DirectSound cooperative level: %08x\n", (UINT32)result);
r32170r32171
249272   stream_format.nBlockAlign       = stream_format.wBitsPerSample * stream_format.nChannels / 8;
250273   stream_format.nAvgBytesPerSec   = stream_format.nSamplesPerSec * stream_format.nBlockAlign;
251274
275
252276   // compute the buffer size based on the output sample rate
253   stream_buffer_size = stream_format.nSamplesPerSec * stream_format.nBlockAlign * downcast<windows_options &>(m_osd.machine().options()).audio_latency() / 10;
277   int audio_latency;
278   #ifdef SDLMAME_WIN32
279   audio_latency = downcast<sdl_options &>(m_osd.machine().options()).audio_latency();
280   #else
281   audio_latency = downcast<windows_options &>(m_osd.machine().options()).audio_latency();
282   #endif
283   stream_buffer_size = stream_format.nSamplesPerSec * stream_format.nBlockAlign * audio_latency / 10;
254284   stream_buffer_size = (stream_buffer_size / 1024) * 1024;
255285   if (stream_buffer_size < 1024)
256286      stream_buffer_size = 1024;
branches/osd/src/osd/windows/winwork.c
r32170r32171
1919
2020// MAME headers
2121#include "osdcore.h"
22
23#include "winsync.h"
24#include "winos.h"
25
2226#include "eminline.h"
2327
2428
r32170r32171
2731//============================================================
2832
2933#define KEEP_STATISTICS         (0)
30#define USE_SCALABLE_LOCKS      (0)
3134
32
33
3435//============================================================
3536//  PARAMETERS
3637//============================================================
3738
39#define ENV_PROCESSORS               "OSDPROCESSORS"
40#define ENV_WORKQUEUEMAXTHREADS      "OSDWORKQUEUEMAXTHREADS"
41
3842#define SPIN_LOOP_TIME          (osd_ticks_per_second() / 1000)
3943
4044
r32170r32171
5963
6064#ifndef YieldProcessor
6165#ifdef __GNUC__
62INLINE void YieldProcessor(void)
66INLINE void osd_yield_processor(void)
6367{
6468   __asm__ __volatile__ ( "rep; nop" );
6569}
6670#else
67INLINE void YieldProcessor(void)
71INLINE void osd_yield_processor(void)
6872{
6973   __asm { rep nop }
7074}
7175#endif
76#else
77#define osd_yield_processor YieldProcessor
7278#endif
7379
7480
r32170r32171
7783//  TYPE DEFINITIONS
7884//============================================================
7985
80struct scalable_lock
81{
82#if USE_SCALABLE_LOCKS
83   struct
84   {
85      volatile INT32  haslock;        // do we have the lock?
86      INT32           filler[64/4-1]; // assumes a 64-byte cache line
87   } slot[WORK_MAX_THREADS];           // one slot per thread
88   volatile INT32      nextindex;      // index of next slot to use
89#else
90   CRITICAL_SECTION    section;
91#endif
92};
93
94
9586struct work_thread_info
9687{
9788   osd_work_queue *    queue;          // pointer back to the queue
98   HANDLE              handle;         // handle to the thread
99   HANDLE              wakeevent;      // wake event for the thread
89   osd_thread *        handle;         // handle to the thread
90   osd_event *         wakeevent;      // wake event for the thread
10091   volatile INT32      active;         // are we actively processing work?
10192
10293#if KEEP_STATISTICS
r32170r32171
111102
112103struct osd_work_queue
113104{
114   scalable_lock       lock;           // lock for protecting the queue
105   osd_scalable_lock * lock;           // lock for protecting the queue
115106   osd_work_item * volatile list;      // list of items in the queue
116107   osd_work_item ** volatile tailptr;  // pointer to the tail pointer of work items in the queue
117108   osd_work_item * volatile free;      // free list of work items
r32170r32171
122113   UINT32              threads;        // number of threads in this queue
123114   UINT32              flags;          // creation flags
124115   work_thread_info *  thread;         // array of thread information
125   HANDLE              doneevent;      // event signalled when work is complete
116   osd_event   *       doneevent;      // event signalled when work is complete
126117
127118#if KEEP_STATISTICS
128119   volatile INT32      itemsqueued;    // total items queued
r32170r32171
140131   osd_work_callback   callback;       // callback function
141132   void *              param;          // callback parameter
142133   void *              result;         // callback result
143   HANDLE              event;          // event signalled when complete
134   osd_event *         event;          // event signalled when complete
144135   UINT32              flags;          // creation flags
145136   volatile INT32      done;           // is the item done?
146137};
r32170r32171
156147//============================================================
157148
158149static int effective_num_processors(void);
159static unsigned __stdcall worker_thread_entry(void *param);
150static void * worker_thread_entry(void *param);
160151static void worker_thread_process(osd_work_queue *queue, work_thread_info *thread);
161152
162153
163
164154//============================================================
165//  Scalable Locks
166//============================================================
167
168INLINE void scalable_lock_init(scalable_lock *lock)
169{
170   memset(lock, 0, sizeof(*lock));
171#if USE_SCALABLE_LOCKS
172   lock->slot[0].haslock = TRUE;
173#else
174   InitializeCriticalSection(&lock->section);
175#endif
176}
177
178
179INLINE INT32 scalable_lock_acquire(scalable_lock *lock)
180{
181#if USE_SCALABLE_LOCKS
182   INT32 myslot = (atomic_increment32(&lock->nextindex) - 1) & (WORK_MAX_THREADS - 1);
183   INT32 backoff = 1;
184
185   while (!lock->slot[myslot].haslock)
186   {
187      INT32 backcount;
188      for (backcount = 0; backcount < backoff; backcount++)
189         YieldProcessor();
190      backoff <<= 1;
191   }
192   lock->slot[myslot].haslock = FALSE;
193   return myslot;
194#else
195   EnterCriticalSection(&lock->section);
196   return 0;
197#endif
198}
199
200
201INLINE void scalable_lock_release(scalable_lock *lock, INT32 myslot)
202{
203#if USE_SCALABLE_LOCKS
204   atomic_exchange32(&lock->slot[(myslot + 1) & (WORK_MAX_THREADS - 1)].haslock, TRUE);
205#else
206   LeaveCriticalSection(&lock->section);
207#endif
208}
209
210
211INLINE void scalable_lock_delete(scalable_lock *lock)
212{
213#if USE_SCALABLE_LOCKS
214#else
215   DeleteCriticalSection(&lock->section);
216#endif
217}
218
219
220//============================================================
221155//  osd_work_queue_alloc
222156//============================================================
223157
r32170r32171
226160   int numprocs = effective_num_processors();
227161   osd_work_queue *queue;
228162   int threadnum;
229   TCHAR *osdworkqueuemaxthreads = _tgetenv(_T("OSDWORKQUEUEMAXTHREADS"));
163   char *osdworkqueuemaxthreads = osd_getenv("OSDWORKQUEUEMAXTHREADS");
230164
231165   // allocate a new queue
232   queue = (osd_work_queue *)malloc(sizeof(*queue));
166   queue = (osd_work_queue *)osd_malloc(sizeof(*queue));
233167   if (queue == NULL)
234168      goto error;
235169   memset(queue, 0, sizeof(*queue));
r32170r32171
239173   queue->flags = flags;
240174
241175   // allocate events for the queue
242   queue->doneevent = CreateEvent(NULL, TRUE, TRUE, NULL);     // manual reset, signalled
176   queue->doneevent = osd_event_alloc(TRUE, TRUE);     // manual reset, signalled
243177   if (queue->doneevent == NULL)
244178      goto error;
245179
246180   // initialize the critical section
247   scalable_lock_init(&queue->lock);
181   queue->lock = osd_scalable_lock_alloc();
182   if (queue->lock == NULL)
183      goto error;
248184
249185   // determine how many threads to create...
250186   // on a single-CPU system, create 1 thread for I/O queues, and 0 threads for everything else
r32170r32171
255191   else
256192      queue->threads = (flags & WORK_QUEUE_FLAG_MULTI) ? numprocs : 1;
257193
258   if (osdworkqueuemaxthreads != NULL && _stscanf(osdworkqueuemaxthreads, _T("%d"), &threadnum) == 1 && queue->threads > threadnum)
194   if (osdworkqueuemaxthreads != NULL && sscanf(osdworkqueuemaxthreads, "%d", &threadnum) == 1 && queue->threads > threadnum)
259195      queue->threads = threadnum;
260196
261197   // multi-queues with high frequency items should top out at 4 for now
r32170r32171
267203   queue->threads = MIN(queue->threads, WORK_MAX_THREADS);
268204
269205   // allocate memory for thread array (+1 to count the calling thread)
270   queue->thread = (work_thread_info *)malloc((queue->threads + 1) * sizeof(queue->thread[0]));
206   queue->thread = (work_thread_info *)osd_malloc_array((queue->threads + 1) * sizeof(queue->thread[0]));
271207   if (queue->thread == NULL)
272208      goto error;
273209   memset(queue->thread, 0, (queue->threads + 1) * sizeof(queue->thread[0]));
r32170r32171
276212   for (threadnum = 0; threadnum < queue->threads; threadnum++)
277213   {
278214      work_thread_info *thread = &queue->thread[threadnum];
279      uintptr_t handle;
280215
281216      // set a pointer back to the queue
282217      thread->queue = queue;
283218
284219      // create the per-thread wake event
285      thread->wakeevent = CreateEvent(NULL, FALSE, FALSE, NULL);  // auto-reset, not signalled
220      thread->wakeevent = osd_event_alloc(FALSE, FALSE);  // auto-reset, not signalled
286221      if (thread->wakeevent == NULL)
287222         goto error;
288223
289224      // create the thread
290      handle = _beginthreadex(NULL, 0, worker_thread_entry, thread, 0, NULL);
291      thread->handle = (HANDLE)handle;
225      thread->handle = osd_thread_create(worker_thread_entry, thread);
292226      if (thread->handle == NULL)
293227         goto error;
294228
295229      // set its priority: I/O threads get high priority because they are assumed to be
296230      // blocked most of the time; other threads just match the creator's priority
297231      if (flags & WORK_QUEUE_FLAG_IO)
298         SetThreadPriority(thread->handle, THREAD_PRIORITY_ABOVE_NORMAL);
232         osd_thread_adjust_priority(thread->handle, 1);
299233      else
300         SetThreadPriority(thread->handle, GetThreadPriority(GetCurrentThread()));
234         osd_thread_adjust_priority(thread->handle, 0);
301235   }
302236
303237   // start a timer going for "waittime" on the main thread
r32170r32171
339273   if (queue->flags & WORK_QUEUE_FLAG_MULTI)
340274   {
341275      work_thread_info *thread = &queue->thread[queue->threads];
342      osd_ticks_t stopspin = osd_ticks() + timeout;
343276
344277      end_timing(thread->waittime);
345278
r32170r32171
349282      // if we're a high frequency queue, spin until done
350283      if (queue->flags & WORK_QUEUE_FLAG_HIGH_FREQ)
351284      {
285         osd_ticks_t stopspin = osd_ticks() + timeout;
286
352287         // spin until we're done
353288         begin_timing(thread->spintime);
354289         while (queue->items != 0 && osd_ticks() < stopspin)
355            YieldProcessor();
290            osd_yield_processor();
356291         end_timing(thread->spintime);
357292
358293         begin_timing(thread->waittime);
r32170r32171
362297   }
363298
364299   // reset our done event and double-check the items before waiting
365   ResetEvent(queue->doneevent);
300   osd_event_reset(queue->doneevent);
366301   atomic_exchange32(&queue->waiting, TRUE);
367302   if (queue->items != 0)
368      WaitForSingleObject(queue->doneevent, timeout * 1000 / osd_ticks_per_second());
303      osd_event_wait(queue->doneevent, timeout);
369304   atomic_exchange32(&queue->waiting, FALSE);
370305
371306   // return TRUE if we actually hit 0
r32170r32171
393328      {
394329         work_thread_info *thread = &queue->thread[threadnum];
395330         if (thread->wakeevent != NULL)
396            SetEvent(thread->wakeevent);
331            osd_event_set(thread->wakeevent);
397332      }
398333
399334      // wait for all the threads to go away
r32170r32171
404339         // block on the thread going away, then close the handle
405340         if (thread->handle != NULL)
406341         {
407            WaitForSingleObject(thread->handle, INFINITE);
408            CloseHandle(thread->handle);
342            osd_thread_wait_free(thread->handle);
409343         }
410344
411345         // clean up the wake event
412346         if (thread->wakeevent != NULL)
413            CloseHandle(thread->wakeevent);
347            osd_event_free(thread->wakeevent);
414348      }
415349
416350#if KEEP_STATISTICS
r32170r32171
419353      {
420354         work_thread_info *thread = &queue->thread[threadnum];
421355         osd_ticks_t total = thread->runtime + thread->waittime + thread->spintime;
422         printf("Thread %d:  items=%9d run=%5.2f%% (%5.2f%%)  spin=%5.2f%%  wait/other=%5.2f%%\n",
356         printf("Thread %d:  items=%9d run=%5.2f%% (%5.2f%%)  spin=%5.2f%%  wait/other=%5.2f%% total=%9d\n",
423357               threadnum, thread->itemsdone,
424358               (double)thread->runtime * 100.0 / (double)total,
425359               (double)thread->actruntime * 100.0 / (double)total,
426360               (double)thread->spintime * 100.0 / (double)total,
427               (double)thread->waittime * 100.0 / (double)total);
361               (double)thread->waittime * 100.0 / (double)total,
362               (UINT32) total);
428363      }
429364#endif
430365   }
431366
432367   // free the list
433368   if (queue->thread != NULL)
434      free(queue->thread);
369      osd_free(queue->thread);
435370
436   scalable_lock_delete(&queue->lock);
437
438371   // free all the events
439372   if (queue->doneevent != NULL)
440      CloseHandle(queue->doneevent);
373      osd_event_free(queue->doneevent);
441374
442375   // free all items in the free list
443376   while (queue->free != NULL)
r32170r32171
445378      osd_work_item *item = (osd_work_item *)queue->free;
446379      queue->free = item->next;
447380      if (item->event != NULL)
448         CloseHandle(item->event);
449      free(item);
381         osd_event_free(item->event);
382      osd_free(item);
450383   }
451384
452385   // free all items in the active list
r32170r32171
455388      osd_work_item *item = (osd_work_item *)queue->list;
456389      queue->list = item->next;
457390      if (item->event != NULL)
458         CloseHandle(item->event);
459      free(item);
391         osd_event_free(item->event);
392      osd_free(item);
460393   }
461394
462395#if KEEP_STATISTICS
r32170r32171
466399   printf("Spin loops     = %9d\n", queue->spinloops);
467400#endif
468401
402   osd_scalable_lock_free(queue->lock);
469403   // free the queue itself
470   free(queue);
404   osd_free(queue);
471405}
472406
473407
r32170r32171
497431      if (item == NULL)
498432      {
499433         // allocate the item
500         item = (osd_work_item *)malloc(sizeof(*item));
434         item = (osd_work_item *)osd_malloc(sizeof(*item));
501435         if (item == NULL)
502436            return NULL;
503437         item->event = NULL;
r32170r32171
520454   }
521455
522456   // enqueue the whole thing within the critical section
523   lockslot = scalable_lock_acquire(&queue->lock);
457   lockslot = osd_scalable_lock_acquire(queue->lock);
524458   *queue->tailptr = itemlist;
525459   queue->tailptr = item_tailptr;
526   scalable_lock_release(&queue->lock, lockslot);
460   osd_scalable_lock_release(queue->lock, lockslot);
527461
528462   // increment the number of items in the queue
529463   atomic_add32(&queue->items, numitems);
r32170r32171
542476         // if this thread is not active, wake him up
543477         if (!thread->active)
544478         {
545            SetEvent(thread->wakeevent);
479            osd_event_set(thread->wakeevent);
546480            add_to_stat(&queue->setevents, 1);
547481
548482            // for non-shared, the first one we find is good enough
r32170r32171
573507
574508   // if we don't have an event, create one
575509   if (item->event == NULL)
576      item->event = CreateEvent(NULL, TRUE, FALSE, NULL);     // manual reset, not signalled
510      item->event = osd_event_alloc(TRUE, FALSE);     // manual reset, not signalled
577511   else
578      ResetEvent(item->event);
512         osd_event_reset(item->event);
579513
580514   // if we don't have an event, we need to spin (shouldn't ever really happen)
581515   if (item->event == NULL)
582516   {
583517      osd_ticks_t stopspin = osd_ticks() + timeout;
584518      while (!item->done && osd_ticks() < stopspin)
585         YieldProcessor();
519         osd_yield_processor();
586520   }
587521
588522   // otherwise, block on the event until done
589523   else if (!item->done)
590      WaitForSingleObject(item->event, timeout * 1000 / osd_ticks_per_second());
524      osd_event_wait(item->event, timeout);
591525
592526   // return TRUE if the refcount actually hit 0
593527   return item->done;
r32170r32171
630564
631565static int effective_num_processors(void)
632566{
633   SYSTEM_INFO info;
634   // fetch the info from the system
635   GetSystemInfo(&info);
567   int physprocs = osd_get_num_processors();
636568
569   // osd_num_processors == 0 for 'auto'
637570   if (osd_num_processors > 0)
638571   {
639      return MIN(info.dwNumberOfProcessors * 4, osd_num_processors);
572      return MIN(4 * physprocs, osd_num_processors);
640573   }
641574   else
642575   {
643      TCHAR *procsoverride;
576      char *procsoverride;
644577      int numprocs = 0;
645578
646579      // if the OSDPROCESSORS environment variable is set, use that value if valid
647580      // note that we permit more than the real number of processors for testing
648      procsoverride = _tgetenv(_T("OSDPROCESSORS"));
649      if (procsoverride != NULL && _stscanf(procsoverride, _T("%d"), &numprocs) == 1 && numprocs > 0)
650         return MIN(info.dwNumberOfProcessors * 4, numprocs);
581      procsoverride = osd_getenv(ENV_PROCESSORS);
582      if (procsoverride != NULL && sscanf(procsoverride, "%d", &numprocs) == 1 && numprocs > 0)
583         return MIN(4 * physprocs, numprocs);
651584
652      return info.dwNumberOfProcessors;
585      // otherwise, return the info from the system
586      return physprocs;
653587   }
654588}
655589
r32170r32171
658592//  worker_thread_entry
659593//============================================================
660594
661static unsigned __stdcall worker_thread_entry(void *param)
595static void *worker_thread_entry(void *param)
662596{
663597   work_thread_info *thread = (work_thread_info *)param;
664598   osd_work_queue *queue = thread->queue;
r32170r32171
666600   // loop until we exit
667601   for ( ;; )
668602   {
603      // block waiting for work or exit
669604      // bail on exit, and only wait if there are no pending items in queue
670605      if (!queue->exiting && queue->list == NULL)
671606      {
672607         begin_timing(thread->waittime);
673         WaitForSingleObject(thread->wakeevent, INFINITE);
608         osd_event_wait(thread->wakeevent, INFINITE);
674609         end_timing(thread->waittime);
675610      }
676611      if (queue->exiting)
r32170r32171
695630            begin_timing(thread->spintime);
696631            stopspin = osd_ticks() + SPIN_LOOP_TIME;
697632            while (queue->list == NULL && osd_ticks() < stopspin)
698               YieldProcessor();
633               osd_yield_processor();
699634            end_timing(thread->spintime);
700635         }
701636
r32170r32171
709644      atomic_exchange32(&thread->active, FALSE);
710645      atomic_decrement32(&queue->livethreads);
711646   }
712   return 0;
647   return NULL;
713648}
714649
715650
r32170r32171
730665      INT32 lockslot;
731666
732667      // use a critical section to synchronize the removal of items
733      lockslot = scalable_lock_acquire(&queue->lock);
668      lockslot = osd_scalable_lock_acquire(queue->lock);
734669      {
735670         // pull the item from the queue
736671         item = (osd_work_item *)queue->list;
r32170r32171
741676               queue->tailptr = (osd_work_item **)&queue->list;
742677         }
743678      }
744      scalable_lock_release(&queue->lock, lockslot);
679      osd_scalable_lock_release(queue->lock, lockslot);
745680
746681      // process non-NULL items
747682      if (item != NULL)
r32170r32171
763698         // set the result and signal the event
764699         else if (item->event != NULL)
765700         {
766            SetEvent(item->event);
701            osd_event_set(item->event);
767702            add_to_stat(&item->queue->setevents, 1);
768703         }
769704
r32170r32171
776711   // we don't need to set the doneevent for multi queues because they spin
777712   if (queue->waiting)
778713   {
779      SetEvent(queue->doneevent);
714      osd_event_set(queue->doneevent);
780715      add_to_stat(&queue->setevents, 1);
781716   }
782717
branches/osd/src/osd/windows/winos.c
r0r32171
1//============================================================
2//
3//  winos.c - Win32 OS specific low level code
4//
5//============================================================
6
7#define WIN32_LEAN_AND_MEAN
8#include <windows.h>
9
10// MAME headers
11#include "osdcore.h"
12
13//============================================================
14//  osd_num_processors
15//============================================================
16
17int osd_get_num_processors(void)
18{
19   SYSTEM_INFO info;
20
21   // otherwise, fetch the info from the system
22   GetSystemInfo(&info);
23
24   // max out at 4 for now since scaling above that seems to do poorly
25   return MIN(info.dwNumberOfProcessors, 4);
26}
27
28//============================================================
29//  osd_getenv
30//============================================================
31
32char *osd_getenv(const char *name)
33{
34   return getenv(name);
35}
No newline at end of file
Property changes on: branches/osd/src/osd/windows/winos.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
branches/osd/src/osd/windows/winos.h
r0r32171
1//============================================================
2//
3//  winos.h - Win32 OS specific low level code
4//
5//============================================================
6
7/*-----------------------------------------------------------------------------
8    osd_num_processors: return the number of processors
9
10    Parameters:
11
12        None.
13
14    Return value:
15
16        Number of processors
17-----------------------------------------------------------------------------*/
18int osd_get_num_processors(void);
19
20
21/*-----------------------------------------------------------------------------
22    osd_getenv: return pointer to environment variable
23
24    Parameters:
25
26        name  - name of environment variable
27
28    Return value:
29
30        pointer to value
31-----------------------------------------------------------------------------*/
32char *osd_getenv(const char *name);
No newline at end of file
Property changes on: branches/osd/src/osd/windows/winos.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
branches/osd/src/osd/windows/windows.mak
r32170r32171
340340   $(WINOBJ)/winsocket.o \
341341   $(WINOBJ)/winwork.o \
342342   $(WINOBJ)/winptty.o \
343   $(WINOBJ)/winos.o \
343344
344345
345346#-------------------------------------------------
branches/osd/src/osd/windows/winsync.c
r32170r32171
1010#define WIN32_LEAN_AND_MEAN
1111#include <windows.h>
1212#include <stdlib.h>
13#include <process.h>
1314
1415// MAME headers
1516#include "osdcore.h"
1617#include "osinline.h"
18#include "winsync.h"
1719
1820
1921//============================================================
r32170r32171
2123//============================================================
2224
2325#define DEBUG_SLOW_LOCKS    0
26#define USE_SCALABLE_LOCKS      (0)
2427
2528
2629
r32170r32171
3538   CRITICAL_SECTION    critsect;
3639};
3740
41struct osd_event
42{
43   void *  ptr;
44};
3845
46struct osd_thread {
47   HANDLE handle;
48   osd_thread_callback callback;
49   void *param;
50};
3951
52struct osd_scalable_lock
53{
54#if USE_SCALABLE_LOCKS
55   struct
56   {
57      volatile INT32  haslock;        // do we have the lock?
58      INT32           filler[64/4-1]; // assumes a 64-byte cache line
59   } slot[WORK_MAX_THREADS];           // one slot per thread
60   volatile INT32      nextindex;      // index of next slot to use
61#else
62   CRITICAL_SECTION    section;
63#endif
64};
65
66
4067//============================================================
4168//  GLOBAL VARIABLES
4269//============================================================
r32170r32171
169196{
170197   return InterlockedExchangeAdd((LONG *) ptr, delta) + delta;
171198}
199
200//============================================================
201//  osd_event_alloc
202//============================================================
203
204osd_event *osd_event_alloc(int manualreset, int initialstate)
205{
206   return (osd_event *) CreateEvent(NULL, manualreset, initialstate, NULL);
207}
208
209//============================================================
210//  osd_event_free
211//============================================================
212
213void osd_event_free(osd_event *event)
214{
215   CloseHandle((HANDLE) event);
216}
217
218//============================================================
219//  osd_event_set
220//============================================================
221
222void osd_event_set(osd_event *event)
223{
224   SetEvent((HANDLE) event);
225}
226
227//============================================================
228//  osd_event_reset
229//============================================================
230
231void osd_event_reset(osd_event *event)
232{
233   ResetEvent((HANDLE) event);
234}
235
236//============================================================
237//  osd_event_wait
238//============================================================
239
240int osd_event_wait(osd_event *event, osd_ticks_t timeout)
241{
242   int ret = WaitForSingleObject((HANDLE) event, timeout * 1000 / osd_ticks_per_second());
243   return ( ret == WAIT_OBJECT_0);
244}
245
246//============================================================
247//  osd_thread_create
248//============================================================
249
250static unsigned __stdcall worker_thread_entry(void *param)
251{
252   osd_thread *thread = (osd_thread *) param;
253   void *res;
254   res = thread->callback(thread->param);
255#ifdef PTR64
256   return (unsigned) (long long) res;
257#else
258   return (unsigned) res;
259#endif
260}
261
262osd_thread *osd_thread_create(osd_thread_callback callback, void *cbparam)
263{
264   osd_thread *thread;
265   uintptr_t handle;
266
267   thread = (osd_thread *)calloc(1, sizeof(osd_thread));
268   thread->callback = callback;
269   thread->param = cbparam;
270   handle = _beginthreadex(NULL, 0, worker_thread_entry, thread, 0, NULL);
271   thread->handle = (HANDLE) handle;
272   return thread;
273}
274
275//============================================================
276//  osd_thread_wait_free
277//============================================================
278
279void osd_thread_wait_free(osd_thread *thread)
280{
281   WaitForSingleObject(thread->handle, INFINITE);
282   CloseHandle(thread->handle);
283   free(thread);
284}
285
286//============================================================
287//  osd_thread_adjust_priority
288//============================================================
289
290int osd_thread_adjust_priority(osd_thread *thread, int adjust)
291{
292   if (adjust)
293      SetThreadPriority(thread->handle, THREAD_PRIORITY_ABOVE_NORMAL);
294   else
295      SetThreadPriority(thread->handle, GetThreadPriority(GetCurrentThread()));
296   return TRUE;
297}
298
299//============================================================
300//  osd_thread_cpu_affinity
301//============================================================
302
303int osd_thread_cpu_affinity(osd_thread *thread, UINT32 mask)
304{
305   return TRUE;
306}
307
308//============================================================
309//  osd_process_kill
310//============================================================
311
312void osd_process_kill(void)
313{
314   TerminateProcess(GetCurrentProcess(), -1);
315}
316
317//============================================================
318//  Scalable Locks
319//============================================================
320
321osd_scalable_lock *osd_scalable_lock_alloc(void)
322{
323   osd_scalable_lock *lock;
324
325   lock = (osd_scalable_lock *)calloc(1, sizeof(*lock));
326
327   memset(lock, 0, sizeof(*lock));
328#if USE_SCALABLE_LOCKS
329   lock->slot[0].haslock = TRUE;
330#else
331   InitializeCriticalSection(&lock->section);
332#endif
333   return lock;
334}
335
336
337INT32 osd_scalable_lock_acquire(osd_scalable_lock *lock)
338{
339#if USE_SCALABLE_LOCKS
340   INT32 myslot = (atomic_increment32(&lock->nextindex) - 1) & (WORK_MAX_THREADS - 1);
341   INT32 backoff = 1;
342
343   while (!lock->slot[myslot].haslock)
344   {
345      INT32 backcount;
346      for (backcount = 0; backcount < backoff; backcount++)
347         osd_yield_processor();
348      backoff <<= 1;
349   }
350   lock->slot[myslot].haslock = FALSE;
351   return myslot;
352#else
353   EnterCriticalSection(&lock->section);
354   return 0;
355#endif
356}
357
358
359void osd_scalable_lock_release(osd_scalable_lock *lock, INT32 myslot)
360{
361#if USE_SCALABLE_LOCKS
362   atomic_exchange32(&lock->slot[(myslot + 1) & (WORK_MAX_THREADS - 1)].haslock, TRUE);
363#else
364   LeaveCriticalSection(&lock->section);
365#endif
366}
367
368
369void osd_scalable_lock_free(osd_scalable_lock *lock)
370{
371#if USE_SCALABLE_LOCKS
372#else
373   DeleteCriticalSection(&lock->section);
374#endif
375   free(lock);
376}
No newline at end of file
branches/osd/src/osd/windows/winsync.h
r0r32171
1//============================================================
2//
3//  winsync.h - Windows core synchronization functions
4//
5//  Copyright (c) 1996-2014, Nicola Salmoria and the MAME Team.
6//  Visit http://mamedev.org for licensing and usage restrictions.
7//
8//============================================================
9
10#ifndef __WINSYNC__
11#define __WINSYNC__
12
13/***************************************************************************
14    SYNCHRONIZATION INTERFACES - Events
15***************************************************************************/
16
17/* osd_event is an opaque type which represents a setable/resetable event */
18
19struct osd_event;
20
21
22/*-----------------------------------------------------------------------------
23    osd_lock_event_alloc: allocate a new event
24
25    Parameters:
26
27        manualreset  - boolean. If true, the event will be automatically set
28                       to non-signalled after a thread successfully waited for
29                       it.
30        initialstate - boolean. If true, the event is signalled initially.
31
32    Return value:
33
34        A pointer to the allocated event.
35-----------------------------------------------------------------------------*/
36osd_event *osd_event_alloc(int manualreset, int initialstate);
37
38
39/*-----------------------------------------------------------------------------
40    osd_event_wait: wait for an event to be signalled
41
42    Parameters:
43
44        event - The event to wait for. If the event is in signalled state, the
45                function returns immediately. If not it will wait for the event
46                to become signalled.
47        timeout - timeout in osd_ticks
48
49    Return value:
50
51        TRUE:  The event was signalled
52        FALSE: A timeout occurred
53-----------------------------------------------------------------------------*/
54int osd_event_wait(osd_event *event, osd_ticks_t timeout);
55
56
57/*-----------------------------------------------------------------------------
58    osd_event_reset: reset an event to non-signalled state
59
60    Parameters:
61
62        event - The event to set to non-signalled state
63
64    Return value:
65
66        None
67-----------------------------------------------------------------------------*/
68void osd_event_reset(osd_event *event);
69
70
71/*-----------------------------------------------------------------------------
72    osd_event_set: set an event to signalled state
73
74    Parameters:
75
76        event - The event to set to signalled state
77
78    Return value:
79
80        None
81
82    Notes:
83
84        All threads waiting for the event will be signalled.
85-----------------------------------------------------------------------------*/
86void osd_event_set(osd_event *event);
87
88
89/*-----------------------------------------------------------------------------
90    osd_event_free: free the memory and resources associated with an osd_event
91
92    Parameters:
93
94        event - a pointer to a previously allocated osd_event.
95
96    Return value:
97
98        None.
99-----------------------------------------------------------------------------*/
100void osd_event_free(osd_event *event);
101
102/***************************************************************************
103    SYNCHRONIZATION INTERFACES - Threads
104***************************************************************************/
105
106/* osd_thread is an opaque type which represents a thread */
107struct osd_thread;
108
109
110/* osd_thread_callback is a callback function that will be called from the thread */
111typedef void *(*osd_thread_callback)(void *param);
112
113
114/*-----------------------------------------------------------------------------
115    osd_thread_create: create a new thread
116
117    Parameters:
118
119        callback - The callback function to be called once the thread is up
120        cbparam  - The parameter to pass to the callback function.
121
122    Return value:
123
124        A pointer to the created thread.
125-----------------------------------------------------------------------------*/
126osd_thread *osd_thread_create(osd_thread_callback callback, void *cbparam);
127
128/*-----------------------------------------------------------------------------
129    osd_thread_adjust_priority: adjust priority of a thread
130
131    Parameters:
132
133        thread - A pointer to a previously created thread.
134        adjust - signed integer to add to the thread priority
135
136    Return value:
137
138        TRUE on success, FALSE on failure
139-----------------------------------------------------------------------------*/
140int osd_thread_adjust_priority(osd_thread *thread, int adjust);
141
142
143/*-----------------------------------------------------------------------------
144    osd_thread_cpu_affinity: change cpu affinity of a thread
145
146    Parameters:
147
148        thread - A pointer to a previously created thread
149                 or NULL for main thread
150        mask   - bitmask to which cpus to bind
151                 i.e. 0x01 1st cpu, 0x02, 2nd cpu, 0x04 3rd cpu
152
153    Return value:
154
155        TRUE on success, FALSE on failure
156-----------------------------------------------------------------------------*/
157int osd_thread_cpu_affinity(osd_thread *thread, UINT32 mask);
158
159
160/*-----------------------------------------------------------------------------
161    osd_thread_wait_free: wait for thread to finish and free resources
162
163    Parameters:
164
165        thread - A pointer to a previously created thread.
166
167    Return value:
168
169        None.
170-----------------------------------------------------------------------------*/
171void osd_thread_wait_free(osd_thread *thread);
172
173/*-----------------------------------------------------------------------------
174    osd_process_kill: kill the current process
175
176    Parameters:
177
178        None.
179
180    Return value:
181
182        None.
183-----------------------------------------------------------------------------*/
184void osd_process_kill(void);
185
186//============================================================
187//  Scalable Locks
188//============================================================
189
190struct osd_scalable_lock;
191
192osd_scalable_lock *osd_scalable_lock_alloc(void);
193
194INT32 osd_scalable_lock_acquire(osd_scalable_lock *lock);
195
196void osd_scalable_lock_release(osd_scalable_lock *lock, INT32 myslot);
197
198void osd_scalable_lock_free(osd_scalable_lock *lock);
199
200#endif  /* __WINSYNC__ */
No newline at end of file
Property changes on: branches/osd/src/osd/windows/winsync.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native

Previous 199869 Revisions Next


© 1997-2024 The MAME Team