Previous 199869 Revisions Next

r34197 Monday 5th January, 2015 at 18:50:36 UTC by Couriersud
Moved sync related osd stuff to osd/modules/sync. (nw)
[src/emu]luaengine.c luaengine.h video.c
[src/mame]mame.mak
[src/mame/drivers]gts80a.c
[src/mame/layout]gts80a_caveman.lay
[src/osd/modules/sync]osdsync.h* sync_mini.c* sync_ntc.c* sync_os2.c* sync_sdl.c* sync_tc.c* sync_windows.c*
[src/osd/osdmini]miniwork.c
[src/osd/sdl]sdl.mak sdlsync.h sdlsync_mini.c sdlsync_ntc.c sdlsync_os2.c sdlsync_sdl.c sdlsync_tc.c sdlsync_win32.c sdlwork.c watchdog.h window.h
[src/osd/windows]osinline.h windows.mak winmain.c winsync.c winsync.h winwork.c

trunk/src/emu/luaengine.c
r242708r242709
1717#include "emuopts.h"
1818#include "osdepend.h"
1919#include "drivenum.h"
20#include "ui/ui.h"
2120#include "web/mongoose.h"
2221
2322//**************************************************************************
r242708r242709
337336   return 0;
338337}
339338
340int lua_engine::l_emu_set_hook(lua_State *L)
341{
342   luaThis->emu_set_hook(L);
343   return 0;
344}
345
346void lua_engine::emu_set_hook(lua_State *L)
347{
348   luaL_argcheck(L, lua_isfunction(L, 1) || lua_isnil(L, 1), 1, "callback function expected");
349   luaL_argcheck(L, lua_isstring(L, 2), 2, "message (string) expected");
350   const char *hookname = luaL_checkstring(L,2);
351
352   if (strcmp(hookname, "output") == 0) {
353      hook_output_cb.set(L, 1);
354      if (!output_notifier_set) {
355         output_set_notifier(NULL, s_output_notifier, this);
356         output_notifier_set = true;
357      }
358   } else if (strcmp(hookname, "frame") == 0) {
359      hook_frame_cb.set(L, 1);
360   } else {
361      luai_writestringerror("%s", "Unknown hook name, aborting.\n");
362   }
363}
364
365339//-------------------------------------------------
366//  machine_get_screens - return table of available screens userdata
367//  -> manager:machine().screens[":screen"]
368//-------------------------------------------------
369
370luabridge::LuaRef lua_engine::l_machine_get_screens(const running_machine *r)
371{
372   lua_State *L = luaThis->m_lua_state;
373   luabridge::LuaRef screens_table = luabridge::LuaRef::newTable(L);
374
375   for (device_t *dev = r->first_screen(); dev != NULL; dev = dev->next()) {
376      screen_device *sc = dynamic_cast<screen_device *>(dev);
377      if (sc && sc->configured() && sc->started() && sc->type()) {
378         screens_table[sc->tag()] = sc;
379      }
380   }
381
382   return screens_table;
383}
384
385//-------------------------------------------------
386340//  machine_get_devices - return table of available devices userdata
387341//  -> manager:machine().devices[":maincpu"]
388342//-------------------------------------------------
r242708r242709
484438
485439}
486440
487//-------------------------------------------------
488//  draw_box - draw a box on a screen container
489//  -> manager:machine().screens[":screen"]:draw_box(x1, y1, x2, y2, bgcolor, linecolor)
490//-------------------------------------------------
491
492int lua_engine::lua_screen::l_draw_box(lua_State *L)
493{
494   screen_device *sc = luabridge::Stack<screen_device *>::get(L, 1);
495   if(!sc) {
496      return 0;
497   }
498
499   // ensure that we got 6 numerical parameters
500   luaL_argcheck(L, lua_isnumber(L, 2), 2, "x1 (integer) expected");
501   luaL_argcheck(L, lua_isnumber(L, 3), 3, "y1 (integer) expected");
502   luaL_argcheck(L, lua_isnumber(L, 4), 4, "x2 (integer) expected");
503   luaL_argcheck(L, lua_isnumber(L, 5), 5, "y2 (integer) expected");
504   luaL_argcheck(L, lua_isnumber(L, 6), 6, "background color (integer) expected");
505   luaL_argcheck(L, lua_isnumber(L, 7), 7, "outline color (integer) expected");
506
507   // retrieve all parameters
508   float x1, y1, x2, y2;
509   x1 = MIN(lua_tounsigned(L, 2) / static_cast<float>(sc->width()) , 1.0f);
510   y1 = MIN(lua_tounsigned(L, 3) / static_cast<float>(sc->height()), 1.0f);
511   x2 = MIN(lua_tounsigned(L, 4) / static_cast<float>(sc->width()) , 1.0f);
512   y2 = MIN(lua_tounsigned(L, 5) / static_cast<float>(sc->height()), 1.0f);
513   UINT32 bgcolor = lua_tounsigned(L, 6);
514   UINT32 fgcolor = lua_tounsigned(L, 7);
515
516   // draw the box
517   render_container &rc = sc->container();
518   ui_manager &ui = sc->machine().ui();
519   ui.draw_outlined_box(&rc, x1, y1, x2, y2, fgcolor, bgcolor);
520
521   return 0;
522}
523
524//-------------------------------------------------
525//  draw_line - draw a line on a screen container
526//  -> manager:machine().screens[":screen"]:draw_line(x1, y1, x2, y2, linecolor)
527//-------------------------------------------------
528
529int lua_engine::lua_screen::l_draw_line(lua_State *L)
530{
531   screen_device *sc = luabridge::Stack<screen_device *>::get(L, 1);
532   if(!sc) {
533      return 0;
534   }
535
536   // ensure that we got 5 numerical parameters
537   luaL_argcheck(L, lua_isnumber(L, 2), 2, "x1 (integer) expected");
538   luaL_argcheck(L, lua_isnumber(L, 3), 3, "y1 (integer) expected");
539   luaL_argcheck(L, lua_isnumber(L, 4), 4, "x2 (integer) expected");
540   luaL_argcheck(L, lua_isnumber(L, 5), 5, "y2 (integer) expected");
541   luaL_argcheck(L, lua_isnumber(L, 6), 6, "color (integer) expected");
542
543   // retrieve all parameters
544   float x1, y1, x2, y2;
545   x1 = MIN(lua_tounsigned(L, 2) / static_cast<float>(sc->width()) , 1.0f);
546   y1 = MIN(lua_tounsigned(L, 3) / static_cast<float>(sc->height()), 1.0f);
547   x2 = MIN(lua_tounsigned(L, 4) / static_cast<float>(sc->width()) , 1.0f);
548   y2 = MIN(lua_tounsigned(L, 5) / static_cast<float>(sc->height()), 1.0f);
549   UINT32 color = lua_tounsigned(L, 6);
550
551   // draw the line
552   sc->container().add_line(x1, y1, x2, y2, UI_LINE_WIDTH, rgb_t(color), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
553   return 0;
554}
555
556//-------------------------------------------------
557//  draw_text - draw text on a screen container
558//  -> manager:machine().screens[":screen"]:draw_text(x, y, message)
559//-------------------------------------------------
560
561int lua_engine::lua_screen::l_draw_text(lua_State *L)
562{
563   screen_device *sc = luabridge::Stack<screen_device *>::get(L, 1);
564   if(!sc) {
565      return 0;
566   }
567
568   // ensure that we got proper parameters
569   luaL_argcheck(L, lua_isnumber(L, 2), 2, "x (integer) expected");
570   luaL_argcheck(L, lua_isnumber(L, 3), 3, "y (integer) expected");
571   luaL_argcheck(L, lua_isstring(L, 4), 4, "message (string) expected");
572
573   // retrieve all parameters
574   float x = MIN(lua_tounsigned(L, 2) / static_cast<float>(sc->width()) , 1.0f);
575   float y = MIN(lua_tounsigned(L, 3) / static_cast<float>(sc->height()), 1.0f);
576   const char *msg = luaL_checkstring(L,4);
577   // TODO: add optional parameters (colors, etc.)
578
579   // draw the text
580   render_container &rc = sc->container();
581   ui_manager &ui = sc->machine().ui();
582   ui.draw_text_full(&rc, msg, x, y , (1.0f - x),
583                  JUSTIFY_LEFT, WRAP_WORD, DRAW_NORMAL, UI_TEXT_COLOR,
584                  UI_TEXT_BG_COLOR, NULL, NULL);
585
586   return 0;
587}
588
589441void *lua_engine::checkparam(lua_State *L, int idx, const char *tname)
590442{
591443   const char *name;
r242708r242709
798650         .addCFunction ("romname",     l_emu_romname )
799651         .addCFunction ("keypost",     l_emu_keypost )
800652         .addCFunction ("hook_output", l_emu_hook_output )
801         .addCFunction ("sethook",     l_emu_set_hook )
802653         .addCFunction ("time",        l_emu_time )
803654         .addCFunction ("wait",        l_emu_wait )
804655         .addCFunction ("after",       l_emu_after )
r242708r242709
816667            .addFunction ("soft_reset", &running_machine::schedule_soft_reset)
817668            .addFunction ("system", &running_machine::system)
818669            .addProperty <luabridge::LuaRef, void> ("devices", &lua_engine::l_machine_get_devices)
819            .addProperty <luabridge::LuaRef, void> ("screens", &lua_engine::l_machine_get_screens)
820670         .endClass ()
821671         .beginClass <game_driver> ("game_driver")
822672            .addData ("name", &game_driver::name)
r242708r242709
841691         .deriveClass <address_space, lua_addr_space> ("addr_space")
842692            .addFunction("name", &address_space::name)
843693         .endClass()
844         .beginClass <lua_screen> ("lua_screen_dev")
845            .addCFunction ("draw_box",  &lua_screen::l_draw_box)
846            .addCFunction ("draw_line", &lua_screen::l_draw_line)
847            .addCFunction ("draw_text", &lua_screen::l_draw_text)
848         .endClass()
849         .deriveClass <screen_device, lua_screen> ("screen_dev")
850            .addFunction ("name", &screen_device::name)
851            .addFunction ("height", &screen_device::height)
852            .addFunction ("width", &screen_device::width)
853         .endClass()
854      .endNamespace();
694      .endNamespace ();
855695
856696   luabridge::push (m_lua_state, machine_manager::instance());
857697   lua_setglobal(m_lua_state, "manager");
r242708r242709
862702   mg_start_thread(::serve_lua, this);
863703}
864704
865//-------------------------------------------------
866//  frame_hook - called at each frame refresh, used to draw a HUD
867//-------------------------------------------------
868bool lua_engine::frame_hook()
869{
870   bool is_cb_hooked = false;
871   if (m_machine != NULL) {
872      // invoke registered callback (if any)
873      is_cb_hooked = hook_frame_cb.active();
874      if (is_cb_hooked) {
875         lua_State *L = hook_frame_cb.precall();
876         hook_frame_cb.call(this, L, 0);
877      }
878   }
879   return is_cb_hooked;
880}
881
882705void lua_engine::periodic_check()
883706{
884707   osd_lock_acquire(lock);
trunk/src/emu/luaengine.h
r242708r242709
4444
4545   void serve_lua();
4646   void periodic_check();
47   bool frame_hook();
4847
4948   void resume(lua_State *L, int nparam = 0, lua_State *root = NULL);
5049   void set_machine(running_machine *machine) { m_machine = machine; update_machine(); }
r242708r242709
6968   hook hook_output_cb;
7069   bool output_notifier_set;
7170
72   hook hook_frame_cb;
73
7471   static lua_engine*  luaThis;
7572
7673   std::map<lua_State *, std::pair<lua_State *, int> > thread_registry;
r242708r242709
8582   int emu_after(lua_State *L);
8683   int emu_wait(lua_State *L);
8784   void emu_hook_output(lua_State *L);
88   void emu_set_hook(lua_State *L);
8985
9086   static int l_ioport_write(lua_State *L);
9187   static int l_emu_after(lua_State *L);
r242708r242709
10197   static int l_emu_start(lua_State *L);
10298   static int l_emu_pause(lua_State *L);
10399   static int l_emu_unpause(lua_State *L);
104   static int l_emu_set_hook(lua_State *L);
105100
106101   // "emu.machine" namespace
107102   static luabridge::LuaRef l_machine_get_devices(const running_machine *r);
r242708r242709
110105   struct lua_addr_space {
111106      template<typename T> int l_mem_read(lua_State *L);
112107   };
113   static luabridge::LuaRef l_machine_get_screens(const running_machine *r);
114   struct lua_screen {
115      int l_draw_box(lua_State *L);
116      int l_draw_line(lua_State *L);
117      int l_draw_text(lua_State *L);
118   };
119108
120109   void resume(void *L, INT32 param);
121110   void report_errors(int status);
trunk/src/emu/video.c
r242708r242709
655655      if (screen->update_quads())
656656         anything_changed = true;
657657
658   // draw HUD from LUA callback (if any)
659   anything_changed |= machine().manager().lua()->frame_hook();
660
661658   // update our movie recording and burn-in state
662659   if (!machine().paused())
663660   {
trunk/src/mame/drivers/gts80a.c
r242708r242709
1515#include "audio/gottlieb.h"
1616#include "cpu/i86/i86.h"
1717#include "gts80a.lh"
18#include "gts80a_caveman.lh"
1918
2019class gts80a_state : public genpin_class
2120{
r242708r242709
385384   caveman_state(const machine_config &mconfig, device_type type, const char *tag)
386385      : gts80a_state(mconfig, type, tag)
387386      , m_videocpu(*this, "video_cpu")
388      , m_vram(*this, "vram")
389
390387   { }
391388
392
393   UINT32 screen_update_caveman(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
394
395389private:
396390   required_device<cpu_device> m_videocpu;
397   required_shared_ptr<UINT8> m_vram;
398391};
399392
400UINT32 caveman_state::screen_update_caveman(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
401{
402   int count = 0;
403   for (int y = 0; y < 256; y++)
404   {
405      for (int x = 0; x < 256; x += 4)
406      {
407         UINT8 pix = m_vram[count];
408
409         bitmap.pix16(y, x+0) = (pix >> 6)&0x3;
410         bitmap.pix16(y, x+1) = (pix >> 4)&0x3;
411         bitmap.pix16(y, x+2) = (pix >> 2)&0x3;
412         bitmap.pix16(y, x+3) = (pix >> 0)&0x3;
413
414         count++;
415      }
416   }
417
418   return 0;
419}
420
421
422393static ADDRESS_MAP_START( video_map, AS_PROGRAM, 8, caveman_state )
423394   ADDRESS_MAP_GLOBAL_MASK(0xffff)
424   AM_RANGE(0x0000, 0x07ff) AM_RAM
425   AM_RANGE(0x2000, 0x5fff) AM_RAM AM_SHARE("vram")
395   AM_RANGE(0x0000, 0x5fff) AM_RAM
426396   AM_RANGE(0x8000, 0xffff) AM_ROM
427397ADDRESS_MAP_END
428398
429399static ADDRESS_MAP_START( video_io_map, AS_IO, 8, caveman_state )
430//   AM_RANGE(0x000, 0x002) AM_READWRITE() // 8259 irq controller
431//   AM_RANGE(0x100, 0x102) AM_READWRITE() // HD46505
432//   AM_RANGE(0x200, 0x200) AM_READWRITE() // 8212 in, ?? out
433//   AM_RANGE(0x300, 0x300) AM_READWRITE() // soundlatch (command?) in, ?? out
434
435//   AM_RANGE(0x400, 0x400) AM_READ() // joystick inputs
436//   AM_RANGE(0x500, 0x506) AM_WRITE() // palette
437
438400ADDRESS_MAP_END
439401
440static MACHINE_CONFIG_DERIVED_CLASS( caveman, gts80a_ss, caveman_state )
402static MACHINE_CONFIG_DERIVED( caveman, gts80a_ss )
441403   MCFG_CPU_ADD("video_cpu", I8088, 5000000)
442404   MCFG_CPU_PROGRAM_MAP(video_map)
443405   MCFG_CPU_IO_MAP(video_io_map)
444
445   MCFG_SCREEN_ADD("screen", RASTER)
446   MCFG_SCREEN_REFRESH_RATE(60)
447   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
448   MCFG_SCREEN_SIZE(256, 256)
449   MCFG_SCREEN_VISIBLE_AREA(0, 256-1, 0, 248-1)
450   MCFG_SCREEN_UPDATE_DRIVER(caveman_state, screen_update_caveman)
451   MCFG_SCREEN_PALETTE("palette")
452
453   MCFG_PALETTE_ADD("palette", 16)
454
455   MCFG_DEFAULT_LAYOUT(layout_gts80a_caveman)
456
457406MACHINE_CONFIG_END
458407
459408static INPUT_PORTS_START( caveman )
trunk/src/mame/layout/gts80a_caveman.lay
r242708r242709
1<!-- GTS80A copied from gts80.lay -->
2
3<!-- 2014-10-10: Initial version.  [Robbbert] -->
4
5<mamelayout version="2">
6
7   <element name="digit" defstate="0">
8      <led14seg>
9         <color red="0.0" green="0.75" blue="1.0" />
10      </led14seg>
11   </element>
12   <element name="digit7" defstate="0">
13      <led7seg>
14         <color red="0.0" green="0.75" blue="1.0" />
15      </led7seg>
16   </element>
17   <element name="red_led">
18      <disk><color red="1.0" green="0.0" blue="0.0" /></disk>
19   </element>
20   <element name="background">
21      <rect>
22         <bounds left="0" top="0" right="1" bottom="1" />
23         <color red="0.0" green="0.0" blue="0.0" />
24      </rect>
25   </element>
26   <element name="P0"><text string="Ball / Match"><color red="1.0" green="1.0" blue="1.0" /></text></element>
27   <element name="P1"><text string="Credits"><color red="1.0" green="1.0" blue="1.0" /></text></element>
28   <element name="P3"><text string="Player 1"><color red="1.0" green="1.0" blue="1.0" /></text></element>
29   <element name="P4"><text string="Player 2"><color red="1.0" green="1.0" blue="1.0" /></text></element>
30   <element name="P5"><text string="Player 3"><color red="1.0" green="1.0" blue="1.0" /></text></element>
31   <element name="P6"><text string="Player 4"><color red="1.0" green="1.0" blue="1.0" /></text></element>
32
33   <view name="Default Layout">
34
35      <!-- Background -->
36      <backdrop element="background">
37         <bounds left="0" top="20" right="318" bottom="394" />
38      </backdrop>
39
40      <!-- LEDs -->
41
42      <!-- Player 1 Score -->
43
44      <bezel name="digit15" element="digit">
45         <bounds left="10" top="45" right="44" bottom="84" />
46      </bezel>
47      <bezel name="digit5" element="digit">
48         <bounds left="54" top="45" right="88" bottom="84" />
49      </bezel>
50      <bezel name="digit4" element="digit">
51         <bounds left="98" top="45" right="132" bottom="84" />
52      </bezel>
53      <bezel name="digit3" element="digit">
54         <bounds left="142" top="45" right="176" bottom="84" />
55      </bezel>
56      <bezel name="digit2" element="digit">
57         <bounds left="186" top="45" right="220" bottom="84" />
58      </bezel>
59      <bezel name="digit1" element="digit">
60         <bounds left="230" top="45" right="264" bottom="84" />
61      </bezel>
62      <bezel name="digit0" element="digit">
63         <bounds left="274" top="45" right="308" bottom="84" />
64      </bezel>
65
66      <!-- Player 2 Score -->
67      <bezel name="digit12" element="digit">
68         <bounds left="10" top="105" right="44" bottom="144" />
69      </bezel>
70      <bezel name="digit11" element="digit">
71         <bounds left="54" top="105" right="88" bottom="144" />
72      </bezel>
73      <bezel name="digit10" element="digit">
74         <bounds left="98" top="105" right="132" bottom="144" />
75      </bezel>
76      <bezel name="digit9" element="digit">
77         <bounds left="142" top="105" right="176" bottom="144" />
78      </bezel>
79      <bezel name="digit8" element="digit">
80         <bounds left="186" top="105" right="220" bottom="144" />
81      </bezel>
82      <bezel name="digit7" element="digit">
83         <bounds left="230" top="105" right="264" bottom="144" />
84      </bezel>
85      <bezel name="digit6" element="digit">
86         <bounds left="274" top="105" right="308" bottom="144" />
87      </bezel>
88
89      <!-- Player 3 Score -->
90      <bezel name="digit35" element="digit">
91         <bounds left="10" top="165" right="44" bottom="204" />
92      </bezel>
93      <bezel name="digit25" element="digit">
94         <bounds left="54" top="165" right="88" bottom="204" />
95      </bezel>
96      <bezel name="digit24" element="digit">
97         <bounds left="98" top="165" right="132" bottom="204" />
98      </bezel>
99      <bezel name="digit23" element="digit">
100         <bounds left="142" top="165" right="176" bottom="204" />
101      </bezel>
102      <bezel name="digit22" element="digit">
103         <bounds left="186" top="165" right="220" bottom="204" />
104      </bezel>
105      <bezel name="digit21" element="digit">
106         <bounds left="230" top="165" right="264" bottom="204" />
107      </bezel>
108      <bezel name="digit20" element="digit">
109         <bounds left="274" top="165" right="308" bottom="204" />
110      </bezel>
111
112      <!-- Player 4 Score -->
113      <bezel name="digit32" element="digit">
114         <bounds left="10" top="225" right="44" bottom="264" />
115      </bezel>
116      <bezel name="digit31" element="digit">
117         <bounds left="54" top="225" right="88" bottom="264" />
118      </bezel>
119      <bezel name="digit30" element="digit">
120         <bounds left="98" top="225" right="132" bottom="264" />
121      </bezel>
122      <bezel name="digit29" element="digit">
123         <bounds left="142" top="225" right="176" bottom="264" />
124      </bezel>
125      <bezel name="digit28" element="digit">
126         <bounds left="186" top="225" right="220" bottom="264" />
127      </bezel>
128      <bezel name="digit27" element="digit">
129         <bounds left="230" top="225" right="264" bottom="264" />
130      </bezel>
131      <bezel name="digit26" element="digit">
132         <bounds left="274" top="225" right="308" bottom="264" />
133      </bezel>
134
135      <!-- Credits and Balls -->
136      <bezel name="digit55" element="digit7">
137         <bounds left="30" top="345" right="64" bottom="384" />
138      </bezel>
139      <bezel name="digit54" element="digit7">
140         <bounds left="69" top="345" right="103" bottom="384" />
141      </bezel>
142      <bezel name="digit53" element="digit7">
143         <bounds left="171" top="345" right="205" bottom="384" />
144      </bezel>
145      <bezel name="digit52" element="digit7">
146         <bounds left="210" top="345" right="244" bottom="384" />
147      </bezel>
148      <bezel element="P0"><bounds left="200" right="258" top="330" bottom="342" /></bezel>
149      <bezel element="P1"><bounds left="50" right="108" top="330" bottom="342" /></bezel>
150      <bezel name="text3" element="P3"><bounds left="100" right="180" top="30" bottom="42" /></bezel>
151      <bezel name="text2" element="P4"><bounds left="100" right="180" top="90" bottom="102" /></bezel>
152      <bezel name="text1" element="P5"><bounds left="100" right="180" top="150" bottom="162" /></bezel>
153      <bezel name="text0" element="P6"><bounds left="100" right="180" top="210" bottom="222" /></bezel>
154   
155      <screen index="0">
156         <bounds x="320" y="0" width="320" height="240" />
157      </screen>
158    </view>
159</mamelayout>
trunk/src/mame/mame.mak
r242708r242709
26612661$(DRIVERS)/gts1.o:      $(LAYOUT)/gts1.lh
26622662$(DRIVERS)/gts3.o:      $(LAYOUT)/gts3.lh
26632663$(DRIVERS)/gts80.o:     $(LAYOUT)/gts80.lh
2664$(DRIVERS)/gts80a.o:    $(LAYOUT)/gts80a.lh \
2665         $(LAYOUT)/gts80a_caveman.lh
2664$(DRIVERS)/gts80a.o:    $(LAYOUT)/gts80a.lh
26662665$(DRIVERS)/gts80b.o:    $(LAYOUT)/gts80b.lh
26672666
26682667$(DRIVERS)/lbeach.o:    $(LAYOUT)/lbeach.lh
trunk/src/osd/modules/sync/osdsync.h
r0r242709
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 __OSDSYNC__
11#define __OSDSYNC__
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  /* __OSDSYNC__ */
trunk/src/osd/modules/sync/sync_mini.c
r0r242709
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles
3//============================================================
4//
5//  sdlsync_mini.c - Minimal core synchronization functions
6//
7//============================================================
8
9#include "osdcore.h"
10#include "osdsync.h"
11
12struct _osd_event
13{
14   void *  ptr;
15};
16
17struct _osd_thread {
18   void *  ptr;
19};
20
21
22//============================================================
23//  osd_lock_alloc
24//============================================================
25
26osd_lock *osd_lock_alloc(void)
27{
28   // the minimal implementation does not support threading
29   // just return a dummy value here
30   return (osd_lock *)1;
31}
32
33
34//============================================================
35//  osd_lock_acquire
36//============================================================
37
38void osd_lock_acquire(osd_lock *lock)
39{
40   // the minimal implementation does not support threading
41   // the acquire always "succeeds"
42}
43
44
45//============================================================
46//  osd_lock_try
47//============================================================
48
49int osd_lock_try(osd_lock *lock)
50{
51   // the minimal implementation does not support threading
52   // the acquire always "succeeds"
53   return TRUE;
54}
55
56
57//============================================================
58//  osd_lock_release
59//============================================================
60
61void osd_lock_release(osd_lock *lock)
62{
63   // the minimal implementation does not support threading
64   // do nothing here
65}
66
67
68//============================================================
69//  osd_lock_free
70//============================================================
71
72void osd_lock_free(osd_lock *lock)
73{
74   // the minimal implementation does not support threading
75   // do nothing here
76}
77
78
79//============================================================
80//  osd_event_alloc
81//============================================================
82
83osd_event *osd_event_alloc(int manualreset, int initialstate)
84{
85   return NULL;
86}
87
88
89//============================================================
90//  osd_event_free
91//============================================================
92
93void osd_event_free(osd_event *event)
94{
95}
96
97
98//============================================================
99//  osd_event_set
100//============================================================
101
102void osd_event_set(osd_event *event)
103{
104}
105
106
107//============================================================
108//  osd_event_reset
109//============================================================
110
111void osd_event_reset(osd_event *event)
112{
113}
114
115
116//============================================================
117//  osd_event_wait
118//============================================================
119
120int osd_event_wait(osd_event *event, osd_ticks_t timeout)
121{
122   return TRUE;
123}
124
125
126//============================================================
127//  osd_thread_create
128//============================================================
129
130osd_thread *osd_thread_create(osd_thread_callback callback, void *cbparam)
131{
132   return NULL;
133}
134
135
136//============================================================
137//  osd_thread_adjust_priority
138//============================================================
139
140int osd_thread_adjust_priority(osd_thread *thread, int adjust)
141{
142   return FALSE;
143}
144
145
146//============================================================
147//  osd_thread_cpu_affinity
148//============================================================
149
150int osd_thread_cpu_affinity(osd_thread *thread, UINT32 mask)
151{
152   return TRUE;
153}
154
155
156//============================================================
157//  osd_thread_wait_free
158//============================================================
159
160void osd_thread_wait_free(osd_thread *thread)
161{
162}
163
164
165//============================================================
166//  osd_process_kill
167//============================================================
168
169void osd_process_kill(void)
170{
171}
trunk/src/osd/modules/sync/sync_ntc.c
r0r242709
1//============================================================
2//
3//  sdlsync.c - SDL core synchronization functions
4//
5//  Copyright (c) 1996-2011, Nicola Salmoria and the MAME Team.
6//  Visit http://mamedev.org for licensing and usage restrictions.
7//
8//  SDLMAME by Olivier Galibert and R. Belmont
9//
10//============================================================
11
12#ifndef _GNU_SOURCE
13#define _GNU_SOURCE     // for PTHREAD_MUTEX_RECURSIVE; needs to be here before other glibc headers are included
14#endif
15
16#include "sdlinc.h"
17
18#ifdef SDLMAME_MACOSX
19#include <mach/mach.h>
20#include <signal.h>
21#endif
22
23#if defined(SDLMAME_NETBSD) || defined(SDLMAME_OPENBSD)
24/* for SIGKILL */
25#include <signal.h>
26#endif
27
28// standard C headers
29#include <math.h>
30#include <unistd.h>
31
32// MAME headers
33#include "osdcore.h"
34#include "osinline.h"
35#include "osdsync.h"
36
37#include "eminline.h"
38
39#include <pthread.h>
40#include <errno.h>
41#include <sys/time.h>
42
43struct osd_lock {
44   volatile pthread_t  holder;
45   INT32               count;
46#ifdef PTR64
47   INT8                padding[52];    // Fill a 64-byte cache line
48#else
49   INT8                padding[56];    // A bit more padding
50#endif
51};
52
53struct osd_event {
54   pthread_mutex_t     mutex;
55   pthread_cond_t      cond;
56   volatile INT32      autoreset;
57   volatile INT32      signalled;
58#ifdef PTR64
59   INT8                padding[40];    // Fill a 64-byte cache line
60#else
61   INT8                padding[48];    // A bit more padding
62#endif
63};
64
65
66//============================================================
67//  TYPE DEFINITIONS
68//============================================================
69
70struct osd_thread {
71   pthread_t           thread;
72};
73
74struct osd_scalable_lock
75{
76   struct
77   {
78      volatile INT32  haslock;        // do we have the lock?
79      INT32           filler[64/4-1]; // assumes a 64-byte cache line
80   } slot[WORK_MAX_THREADS];           // one slot per thread
81   volatile INT32      nextindex;      // index of next slot to use
82};
83
84
85//============================================================
86//  Scalable Locks
87//============================================================
88
89osd_scalable_lock *osd_scalable_lock_alloc(void)
90{
91   osd_scalable_lock *lock;
92
93   lock = (osd_scalable_lock *)calloc(1, sizeof(*lock));
94
95   memset(lock, 0, sizeof(*lock));
96   lock->slot[0].haslock = TRUE;
97   return lock;
98}
99
100
101INT32 osd_scalable_lock_acquire(osd_scalable_lock *lock)
102{
103   INT32 myslot = (atomic_increment32(&lock->nextindex) - 1) & (WORK_MAX_THREADS - 1);
104
105#if defined(__i386__) || defined(__x86_64__)
106   register INT32 tmp;
107   __asm__ __volatile__ (
108      "1: clr    %[tmp]             ;"
109      "   xchg   %[haslock], %[tmp] ;"
110      "   test   %[tmp], %[tmp]     ;"
111      "   jne    3f                 ;"
112      "2: mov    %[haslock], %[tmp] ;"
113      "   test   %[tmp], %[tmp]     ;"
114      "   jne    1b                 ;"
115      "   pause                     ;"
116      "   jmp    2b                 ;"
117      "3:                            "
118      : [haslock] "+m"  (lock->slot[myslot].haslock)
119      , [tmp]     "=&r" (tmp)
120      :
121      : "cc"
122   );
123#elif defined(__ppc__) || defined (__PPC__) || defined(__ppc64__) || defined(__PPC64__)
124   register INT32 tmp;
125   __asm__ __volatile__ (
126      "1: lwarx   %[tmp], 0, %[haslock] \n"
127      "   cmpwi   %[tmp], 0             \n"
128      "   bne     3f                    \n"
129      "2: lwzx    %[tmp], 0, %[haslock] \n"
130      "   cmpwi   %[tmp], 0             \n"
131      "   bne     1b                    \n"
132      "   nop                           \n"
133      "   nop                           \n"
134      "   b       2b                    \n"
135      "3: li      %[tmp], 0             \n"
136      "   sync                          \n"
137      "   stwcx.  %[tmp], 0, %[haslock] \n"
138      "   bne-    1b                    \n"
139      "   eieio                         \n"
140      : [tmp]     "=&r" (tmp)
141      : [haslock] "r"   (&lock->slot[myslot].haslock)
142      : "cr0"
143   );
144#else
145   INT32 backoff = 1;
146   while (!osd_compare_exchange32(&lock->slot[myslot].haslock, TRUE, FALSE))
147   {
148      INT32 backcount;
149      for (backcount = 0; backcount < backoff; backcount++)
150         osd_yield_processor();
151      backoff <<= 1;
152   }
153#endif
154   return myslot;
155}
156
157
158void osd_scalable_lock_release(osd_scalable_lock *lock, INT32 myslot)
159{
160#if defined(__i386__) || defined(__x86_64__)
161   register INT32 tmp = TRUE;
162   __asm__ __volatile__ (
163      " xchg   %[haslock], %[tmp] ;"
164      : [haslock] "+m" (lock->slot[(myslot + 1) & (WORK_MAX_THREADS - 1)].haslock)
165      , [tmp]     "+r" (tmp)
166      :
167   );
168#elif defined(__ppc__) || defined (__PPC__) || defined(__ppc64__) || defined(__PPC64__)
169   lock->slot[(myslot + 1) & (WORK_MAX_THREADS - 1)].haslock = TRUE;
170   __asm__ __volatile__ ( " eieio " : : );
171#else
172   osd_exchange32(&lock->slot[(myslot + 1) & (WORK_MAX_THREADS - 1)].haslock, TRUE);
173#endif
174}
175
176void osd_scalable_lock_free(osd_scalable_lock *lock)
177{
178   free(lock);
179}
180
181INLINE pthread_t osd_compare_exchange_pthread_t(pthread_t volatile *ptr, pthread_t compare, pthread_t exchange)
182{
183#ifdef PTR64
184   INT64 result = compare_exchange64((INT64 volatile *)ptr, (INT64)compare, (INT64)exchange);
185#else
186   INT32 result = compare_exchange32((INT32 volatile *)ptr, (INT32)compare, (INT32)exchange);
187#endif
188   return (pthread_t)result;
189}
190
191INLINE pthread_t osd_exchange_pthread_t(pthread_t volatile *ptr, pthread_t exchange)
192{
193#ifdef PTR64
194   INT64 result = osd_exchange64((INT64 volatile *)ptr, (INT64)exchange);
195#else
196   INT32 result = atomic_exchange32((INT32 volatile *)ptr, (INT32)exchange);
197#endif
198   return (pthread_t)result;
199}
200
201
202//============================================================
203//  osd_lock_alloc
204//============================================================
205
206osd_lock *osd_lock_alloc(void)
207{
208   osd_lock *lock;
209
210   lock = (osd_lock *)calloc(1, sizeof(osd_lock));
211
212   lock->holder = 0;
213   lock->count = 0;
214
215   return lock;
216}
217
218//============================================================
219//  osd_lock_acquire
220//============================================================
221
222void osd_lock_acquire(osd_lock *lock)
223{
224   pthread_t current, prev;
225
226   current = pthread_self();
227   prev = osd_compare_exchange_pthread_t(&lock->holder, 0, current);
228   if (prev != (size_t)NULL && prev != current)
229   {
230      do {
231         register INT32 spin = 10000; // Convenient spin count
232         register pthread_t tmp;
233#if defined(__i386__) || defined(__x86_64__)
234         __asm__ __volatile__ (
235            "1: pause                    ;"
236            "   mov    %[holder], %[tmp] ;"
237            "   test   %[tmp], %[tmp]    ;"
238            "   loopne 1b                ;"
239            : [spin]   "+c"  (spin)
240            , [tmp]    "=&r" (tmp)
241            : [holder] "m"   (lock->holder)
242            : "cc"
243         );
244#elif defined(__ppc__) || defined(__PPC__)
245         __asm__ __volatile__ (
246            "1: nop                        \n"
247            "   nop                        \n"
248            "   lwzx  %[tmp], 0, %[holder] \n"
249            "   cmpwi %[tmp], 0            \n"
250            "   bdnzt eq, 1b               \n"
251            : [spin]   "+c"  (spin)
252            , [tmp]    "=&r" (tmp)
253            : [holder] "r"   (&lock->holder)
254            : "cr0"
255         );
256#elif defined(__ppc64__) || defined(__PPC64__)
257         __asm__ __volatile__ (
258            "1: nop                        \n"
259            "   nop                        \n"
260            "   ldx   %[tmp], 0, %[holder] \n"
261            "   cmpdi %[tmp], 0            \n"
262            "   bdnzt eq, 1b               \n"
263            : [spin]   "+c"  (spin)
264            , [tmp]    "=&r" (tmp)
265            : [holder] "r"   (&lock->holder)
266            : "cr0"
267         );
268#else
269         while (--spin > 0 && lock->holder != NULL)
270            osd_yield_processor();
271#endif
272#if 0
273         /* If you mean to use locks as a blocking mechanism for extended
274          * periods of time, you should do something like this.  However,
275          * it kills the performance of gaelco3d.
276          */
277         if (spin == 0)
278         {
279            struct timespec sleep = { 0, 100000 }, remaining;
280            nanosleep(&sleep, &remaining); // sleep for 100us
281         }
282#endif
283      } while (osd_compare_exchange_pthread_t(&lock->holder, 0, current) != (size_t)NULL);
284   }
285   lock->count++;
286}
287
288//============================================================
289//  osd_lock_try
290//============================================================
291
292int osd_lock_try(osd_lock *lock)
293{
294   pthread_t current, prev;
295
296   current = pthread_self();
297   prev = osd_compare_exchange_pthread_t(&lock->holder, 0, current);
298   if (prev == (size_t)NULL || prev == current)
299   {
300      lock->count++;
301      return 1;
302   }
303   return 0;
304}
305
306//============================================================
307//  osd_lock_release
308//============================================================
309
310void osd_lock_release(osd_lock *lock)
311{
312   pthread_t current;
313
314   current = pthread_self();
315   if (lock->holder == current)
316   {
317      if (--lock->count == 0)
318#if defined(__ppc__) || defined(__PPC__) || defined(__ppc64__) || defined(__PPC64__)
319      lock->holder = 0;
320      __asm__ __volatile__( " eieio " : : );
321#else
322      osd_exchange_pthread_t(&lock->holder, 0);
323#endif
324      return;
325   }
326
327   // trying to release a lock you don't hold is bad!
328//  assert(lock->holder == pthread_self());
329}
330
331//============================================================
332//  osd_lock_free
333//============================================================
334
335void osd_lock_free(osd_lock *lock)
336{
337   free(lock);
338}
339
340//============================================================
341//  osd_event_alloc
342//============================================================
343
344osd_event *osd_event_alloc(int manualreset, int initialstate)
345{
346   osd_event *ev;
347   pthread_mutexattr_t mtxattr;
348
349   ev = (osd_event *)calloc(1, sizeof(osd_event));
350
351   pthread_mutexattr_init(&mtxattr);
352   pthread_mutex_init(&ev->mutex, &mtxattr);
353   pthread_cond_init(&ev->cond, NULL);
354   ev->signalled = initialstate;
355   ev->autoreset = !manualreset;
356
357   return ev;
358}
359
360//============================================================
361//  osd_event_free
362//============================================================
363
364void osd_event_free(osd_event *event)
365{
366   pthread_mutex_destroy(&event->mutex);
367   pthread_cond_destroy(&event->cond);
368   free(event);
369}
370
371//============================================================
372//  osd_event_set
373//============================================================
374
375void osd_event_set(osd_event *event)
376{
377   pthread_mutex_lock(&event->mutex);
378   if (event->signalled == FALSE)
379   {
380      event->signalled = TRUE;
381      if (event->autoreset)
382         pthread_cond_signal(&event->cond);
383      else
384         pthread_cond_broadcast(&event->cond);
385   }
386   pthread_mutex_unlock(&event->mutex);
387}
388
389//============================================================
390//  osd_event_reset
391//============================================================
392
393void osd_event_reset(osd_event *event)
394{
395   pthread_mutex_lock(&event->mutex);
396   event->signalled = FALSE;
397   pthread_mutex_unlock(&event->mutex);
398}
399
400//============================================================
401//  osd_event_wait
402//============================================================
403
404int osd_event_wait(osd_event *event, osd_ticks_t timeout)
405{
406   pthread_mutex_lock(&event->mutex);
407   if (!timeout)
408   {
409      if (!event->signalled)
410      {
411            pthread_mutex_unlock(&event->mutex);
412            return FALSE;
413      }
414   }
415   else
416   {
417      if (!event->signalled)
418      {
419         struct timespec   ts;
420         struct timeval    tp;
421         UINT64 msec = timeout * 1000 / osd_ticks_per_second();
422         UINT64 nsec;
423
424         gettimeofday(&tp, NULL);
425
426         ts.tv_sec  = tp.tv_sec;
427         nsec = (UINT64) tp.tv_usec * (UINT64) 1000 + (msec * (UINT64) 1000000);
428         ts.tv_nsec = nsec % (UINT64) 1000000000;
429         ts.tv_sec += nsec / (UINT64) 1000000000;
430
431         do {
432            int ret = pthread_cond_timedwait(&event->cond, &event->mutex, &ts);
433            if ( ret == ETIMEDOUT )
434            {
435               if (!event->signalled)
436               {
437                  pthread_mutex_unlock(&event->mutex);
438                  return FALSE;
439               }
440               else
441                  break;
442            }
443            if (ret == 0)
444               break;
445            if ( ret != EINTR)
446            {
447               printf("Error %d while waiting for pthread_cond_timedwait:  %s\n", ret, strerror(ret));
448            }
449
450         } while (TRUE);
451      }
452   }
453
454   if (event->autoreset)
455      event->signalled = 0;
456
457   pthread_mutex_unlock(&event->mutex);
458
459   return TRUE;
460}
461
462//============================================================
463//  osd_thread_create
464//============================================================
465
466osd_thread *osd_thread_create(osd_thread_callback callback, void *cbparam)
467{
468   osd_thread *thread;
469   pthread_attr_t  attr;
470
471   thread = (osd_thread *)calloc(1, sizeof(osd_thread));
472   pthread_attr_init(&attr);
473#ifndef SDLMAME_HAIKU
474   pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
475#endif
476   if ( pthread_create(&thread->thread, &attr, callback, cbparam) != 0 )
477   {
478      free(thread);
479      return NULL;
480   }
481   return thread;
482}
483
484//============================================================
485//  osd_thread_adjust_priority
486//============================================================
487
488int osd_thread_adjust_priority(osd_thread *thread, int adjust)
489{
490   struct sched_param  sched;
491   int                 policy;
492
493   if ( pthread_getschedparam( thread->thread, &policy, &sched ) == 0 )
494   {
495      sched.sched_priority += adjust;
496      if ( pthread_setschedparam(thread->thread, policy, &sched ) == 0)
497         return TRUE;
498      else
499         return FALSE;
500   }
501   else
502      return FALSE;
503}
504
505//============================================================
506//  osd_thread_cpu_affinity
507//============================================================
508
509int osd_thread_cpu_affinity(osd_thread *thread, UINT32 mask)
510{
511   return TRUE;
512}
513
514//============================================================
515//  osd_thread_wait_free
516//============================================================
517
518void osd_thread_wait_free(osd_thread *thread)
519{
520   pthread_join(thread->thread, NULL);
521   free(thread);
522}
523
524//============================================================
525//  osd_process_kill
526//============================================================
527
528void osd_process_kill(void)
529{
530   kill(getpid(), SIGKILL);
531}
trunk/src/osd/modules/sync/sync_os2.c
r0r242709
1//============================================================
2//
3//  sdlsync.c - SDL core synchronization functions
4//
5//  Copyright (c) 1996-2010, Nicola Salmoria and the MAME Team.
6//  Visit http://mamedev.org for licensing and usage restrictions.
7//
8//  SDLMAME by Olivier Galibert and R. Belmont
9//
10//============================================================
11
12#ifndef _GNU_SOURCE
13#define _GNU_SOURCE     // for PTHREAD_MUTEX_RECURSIVE; needs to be here before other glibc headers are included
14#endif
15
16#include "sdlinc.h"
17
18// standard C headers
19#include <math.h>
20#include <unistd.h>
21
22// MAME headers
23#include "osdcore.h"
24#include "osinline.h"
25#include "osdsync.h"
26
27#include "eminline.h"
28
29#define INCL_DOS
30#include <os2.h>
31
32#include <stdlib.h>
33#define pthread_t       int
34#define pthread_self    _gettid
35
36struct osd_lock {
37   volatile pthread_t  holder;
38   INT32               count;
39#ifdef PTR64
40   INT8                padding[52];    // Fill a 64-byte cache line
41#else
42   INT8                padding[56];    // A bit more padding
43#endif
44};
45
46struct osd_event {
47   HMTX                hmtx;
48   HEV                 hev;
49   volatile INT32      autoreset;
50   INT8                padding[52];    // Fill a 64-byte cache line
51};
52
53//============================================================
54//  TYPE DEFINITIONS
55//============================================================
56
57struct osd_thread {
58   pthread_t           thread;
59   osd_thread_callback callback;
60   void *param;
61};
62
63struct osd_scalable_lock
64{
65   struct
66   {
67      volatile INT32  haslock;        // do we have the lock?
68      INT32           filler[64/4-1]; // assumes a 64-byte cache line
69   } slot[WORK_MAX_THREADS];           // one slot per thread
70   volatile INT32      nextindex;      // index of next slot to use
71};
72
73
74//============================================================
75//  Scalable Locks
76//============================================================
77
78osd_scalable_lock *osd_scalable_lock_alloc(void)
79{
80   osd_scalable_lock *lock;
81
82   lock = (osd_scalable_lock *)calloc(1, sizeof(*lock));
83
84   memset(lock, 0, sizeof(*lock));
85   lock->slot[0].haslock = TRUE;
86   return lock;
87}
88
89
90INT32 osd_scalable_lock_acquire(osd_scalable_lock *lock)
91{
92   INT32 myslot = (atomic_increment32(&lock->nextindex) - 1) & (WORK_MAX_THREADS - 1);
93
94#if defined(__i386__) || defined(__x86_64__)
95   register INT32 tmp;
96   __asm__ __volatile__ (
97      "1: clr    %[tmp]             ;"
98      "   xchg   %[haslock], %[tmp] ;"
99      "   test   %[tmp], %[tmp]     ;"
100      "   jne    3f                 ;"
101      "2: mov    %[haslock], %[tmp] ;"
102      "   test   %[tmp], %[tmp]     ;"
103      "   jne    1b                 ;"
104      "   pause                     ;"
105      "   jmp    2b                 ;"
106      "3:                            "
107      : [haslock] "+m"  (lock->slot[myslot].haslock)
108      , [tmp]     "=&r" (tmp)
109      :
110      : "%cc"
111   );
112#elif defined(__ppc__) || defined (__PPC__) || defined(__ppc64__) || defined(__PPC64__)
113   register INT32 tmp;
114   __asm__ __volatile__ (
115      "1: lwarx   %[tmp], 0, %[haslock] \n"
116      "   cmpwi   %[tmp], 0             \n"
117      "   bne     3f                    \n"
118      "2: lwzx    %[tmp], 0, %[haslock] \n"
119      "   cmpwi   %[tmp], 0             \n"
120      "   bne     1b                    \n"
121      "   nop                           \n"
122      "   nop                           \n"
123      "   b       2b                    \n"
124      "3: li      %[tmp], 0             \n"
125      "   sync                          \n"
126      "   stwcx.  %[tmp], 0, %[haslock] \n"
127      "   bne-    1b                    \n"
128      "   eieio                         \n"
129      : [tmp]     "=&r" (tmp)
130      : [haslock] "r"   (&lock->slot[myslot].haslock)
131      : "cr0"
132   );
133#else
134   INT32 backoff = 1;
135   while (!osd_compare_exchange32(&lock->slot[myslot].haslock, TRUE, FALSE))
136   {
137      INT32 backcount;
138      for (backcount = 0; backcount < backoff; backcount++)
139         osd_yield_processor();
140      backoff <<= 1;
141   }
142#endif
143   return myslot;
144}
145
146
147void osd_scalable_lock_release(osd_scalable_lock *lock, INT32 myslot)
148{
149#if defined(__i386__) || defined(__x86_64__)
150   register INT32 tmp = TRUE;
151   __asm__ __volatile__ (
152      " xchg   %[haslock], %[tmp] ;"
153      : [haslock] "+m" (lock->slot[(myslot + 1) & (WORK_MAX_THREADS - 1)].haslock)
154      , [tmp]     "+r" (tmp)
155      :
156   );
157#elif defined(__ppc__) || defined (__PPC__) || defined(__ppc64__) || defined(__PPC64__)
158   lock->slot[(myslot + 1) & (WORK_MAX_THREADS - 1)].haslock = TRUE;
159   __asm__ __volatile__ ( " eieio " : : );
160#else
161   osd_exchange32(&lock->slot[(myslot + 1) & (WORK_MAX_THREADS - 1)].haslock, TRUE);
162#endif
163}
164
165void osd_scalable_lock_free(osd_scalable_lock *lock)
166{
167   free(lock);
168}
169
170INLINE pthread_t osd_compare_exchange_pthread_t(pthread_t volatile *ptr, pthread_t compare, pthread_t exchange)
171{
172#ifdef PTR64
173   INT64 result = compare_exchange64((INT64 volatile *)ptr, (INT64)compare, (INT64)exchange);
174#else
175   INT32 result = compare_exchange32((INT32 volatile *)ptr, (INT32)compare, (INT32)exchange);
176#endif
177   return (pthread_t)result;
178}
179
180INLINE pthread_t osd_exchange_pthread_t(pthread_t volatile *ptr, pthread_t exchange)
181{
182#ifdef PTR64
183   INT64 result = osd_exchange64((INT64 volatile *)ptr, (INT64)exchange);
184#else
185   INT32 result = atomic_exchange32((INT32 volatile *)ptr, (INT32)exchange);
186#endif
187   return (pthread_t)result;
188}
189
190
191//============================================================
192//  osd_lock_alloc
193//============================================================
194
195osd_lock *osd_lock_alloc(void)
196{
197   osd_lock *lock;
198
199   lock = (osd_lock *)calloc(1, sizeof(osd_lock));
200
201   lock->holder = 0;
202   lock->count = 0;
203
204   return lock;
205}
206
207//============================================================
208//  osd_lock_acquire
209//============================================================
210
211void osd_lock_acquire(osd_lock *lock)
212{
213   pthread_t current, prev;
214
215   current = pthread_self();
216   prev = osd_compare_exchange_pthread_t(&lock->holder, 0, current);
217   if (prev != (size_t)NULL && prev != current)
218   {
219      do {
220         register INT32 spin = 10000; // Convenient spin count
221         register pthread_t tmp;
222#if defined(__i386__) || defined(__x86_64__)
223         __asm__ __volatile__ (
224            "1: pause                    ;"
225            "   mov    %[holder], %[tmp] ;"
226            "   test   %[tmp], %[tmp]    ;"
227            "   loopne 1b                ;"
228            : [spin]   "+c"  (spin)
229            , [tmp]    "=&r" (tmp)
230            : [holder] "m"   (lock->holder)
231            : "%cc"
232         );
233#elif defined(__ppc__) || defined(__PPC__)
234         __asm__ __volatile__ (
235            "1: nop                        \n"
236            "   nop                        \n"
237            "   lwzx  %[tmp], 0, %[holder] \n"
238            "   cmpwi %[tmp], 0            \n"
239            "   bdnzt eq, 1b               \n"
240            : [spin]   "+c"  (spin)
241            , [tmp]    "=&r" (tmp)
242            : [holder] "r"   (&lock->holder)
243            : "cr0"
244         );
245#elif defined(__ppc64__) || defined(__PPC64__)
246         __asm__ __volatile__ (
247            "1: nop                        \n"
248            "   nop                        \n"
249            "   ldx   %[tmp], 0, %[holder] \n"
250            "   cmpdi %[tmp], 0            \n"
251            "   bdnzt eq, 1b               \n"
252            : [spin]   "+c"  (spin)
253            , [tmp]    "=&r" (tmp)
254            : [holder] "r"   (&lock->holder)
255            : "cr0"
256         );
257#else
258         while (--spin > 0 && lock->holder != NULL)
259            osd_yield_processor();
260#endif
261#if 0
262         /* If you mean to use locks as a blocking mechanism for extended
263          * periods of time, you should do something like this.  However,
264          * it kills the performance of gaelco3d.
265          */
266         if (spin == 0)
267         {
268            struct timespec sleep = { 0, 100000 }, remaining;
269            nanosleep(&sleep, &remaining); // sleep for 100us
270         }
271#endif
272      } while (osd_compare_exchange_pthread_t(&lock->holder, 0, current) != (size_t)NULL);
273   }
274   lock->count++;
275}
276
277//============================================================
278//  osd_lock_try
279//============================================================
280
281int osd_lock_try(osd_lock *lock)
282{
283   pthread_t current, prev;
284
285   current = pthread_self();
286   prev = osd_compare_exchange_pthread_t(&lock->holder, 0, current);
287   if (prev == (size_t)NULL || prev == current)
288   {
289      lock->count++;
290      return 1;
291   }
292   return 0;
293}
294
295//============================================================
296//  osd_lock_release
297//============================================================
298
299void osd_lock_release(osd_lock *lock)
300{
301   pthread_t current;
302
303   current = pthread_self();
304   if (lock->holder == current)
305   {
306      if (--lock->count == 0)
307#if defined(__ppc__) || defined(__PPC__) || defined(__ppc64__) || defined(__PPC64__)
308      lock->holder = 0;
309      __asm__ __volatile__( " eieio " : : );
310#else
311      osd_exchange_pthread_t(&lock->holder, 0);
312#endif
313      return;
314   }
315
316   // trying to release a lock you don't hold is bad!
317//  assert(lock->holder == pthread_self());
318}
319
320//============================================================
321//  osd_lock_free
322//============================================================
323
324void osd_lock_free(osd_lock *lock)
325{
326   free(lock);
327}
328
329//============================================================
330//  osd_event_alloc
331//============================================================
332
333osd_event *osd_event_alloc(int manualreset, int initialstate)
334{
335   osd_event *ev;
336
337   ev = (osd_event *)calloc(1, sizeof(osd_event));
338
339   DosCreateMutexSem(NULL, &ev->hmtx, 0, FALSE);
340   DosCreateEventSem(NULL, &ev->hev, 0, initialstate);
341   ev->autoreset = !manualreset;
342
343   return ev;
344}
345
346//============================================================
347//  osd_event_free
348//============================================================
349
350void osd_event_free(osd_event *event)
351{
352   DosCloseMutexSem(event->hmtx);
353   DosCloseEventSem(event->hev);
354   free(event);
355}
356
357//============================================================
358//  osd_event_set
359//============================================================
360
361void osd_event_set(osd_event *event)
362{
363   DosPostEventSem(event->hev);
364}
365
366//============================================================
367//  osd_event_reset
368//============================================================
369
370void osd_event_reset(osd_event *event)
371{
372   ULONG ulCount;
373
374   DosResetEventSem(event->hev, &ulCount);
375}
376
377//============================================================
378//  osd_event_wait
379//============================================================
380
381int osd_event_wait(osd_event *event, osd_ticks_t timeout)
382{
383   ULONG rc;
384
385   if(event->autoreset)
386      DosRequestMutexSem(event->hmtx, -1);
387
388   rc = DosWaitEventSem(event->hev, timeout * 1000 / osd_ticks_per_second());
389
390   if(event->autoreset)
391   {
392      ULONG ulCount;
393
394      if(rc == 0)
395         DosResetEventSem(event->hev, &ulCount);
396
397      DosReleaseMutexSem(event->hmtx);
398   }
399
400   return (rc == 0);
401}
402
403//============================================================
404//  osd_thread_create
405//============================================================
406
407static void worker_thread_entry(void *param)
408{
409      osd_thread *thread = (osd_thread *) param;
410
411      thread->callback(thread->param);
412}
413
414osd_thread *osd_thread_create(osd_thread_callback callback, void *cbparam)
415{
416   osd_thread *thread;
417
418   thread = (osd_thread *)calloc(1, sizeof(osd_thread));
419   thread->callback = callback;
420   thread->param = cbparam;
421   thread->thread = _beginthread(worker_thread_entry, NULL, 65535, thread);
422   if ( thread->thread == -1 )
423   {
424      free(thread);
425      return NULL;
426   }
427   return thread;
428}
429
430//============================================================
431//  osd_thread_adjust_priority
432//============================================================
433
434int osd_thread_adjust_priority(osd_thread *thread, int adjust)
435{
436   PTIB ptib;
437
438   DosGetInfoBlocks(&ptib, NULL);
439
440   if ( DosSetPriority(PRTYS_THREAD, PRTYC_NOCHANGE,
441                  ((BYTE)ptib->tib_ptib2->tib2_ulpri) + adjust, thread->thread ))
442      return FALSE;
443
444
445   return TRUE;
446}
447
448//============================================================
449//  osd_thread_cpu_affinity
450//============================================================
451
452int osd_thread_cpu_affinity(osd_thread *thread, UINT32 mask)
453{
454   return TRUE;
455}
456
457//============================================================
458//  osd_thread_wait_free
459//============================================================
460
461void osd_thread_wait_free(osd_thread *thread)
462{
463   TID tid = thread->thread;
464
465   DosWaitThread(&tid, 0);
466   free(thread);
467}
468
469//============================================================
470//  osd_process_kill
471//============================================================
472
473void osd_process_kill(void)
474{
475   PPIB ppib;
476
477   DosGetInfoBlocks(NULL, &ppib);
478   DosKillProcess(DKP_PROCESSTREE, ppib->pib_ulpid);
479}
trunk/src/osd/modules/sync/sync_sdl.c
r0r242709
1//============================================================
2//
3//  sdlsync.c - SDL core synchronization functions
4//
5//  Copyright (c) 1996-2010, Nicola Salmoria and the MAME Team.
6//  Visit http://mamedev.org for licensing and usage restrictions.
7//
8//  SDLMAME by Olivier Galibert and R. Belmont
9//
10//============================================================
11
12#include "sdlinc.h"
13
14// standard C headers
15#include <unistd.h>
16
17// MAME headers
18#include "osdcore.h"
19#include "osinline.h"
20#include "osdsync.h"
21
22#include "eminline.h"
23
24#define VERBOSE     (0)
25
26#if VERBOSE
27#define LOG( x ) do { printf x; printf("\n"); } while (0)
28#else
29#define LOG( x )
30#endif
31struct hidden_mutex_t {
32   SDL_mutex *         id;
33   volatile INT32      locked;
34   volatile INT32      threadid;
35};
36
37struct osd_event {
38   SDL_mutex *         mutex;
39   SDL_cond *          cond;
40   volatile INT32      autoreset;
41   volatile INT32      signalled;
42};
43
44//============================================================
45//  TYPE DEFINITIONS
46//============================================================
47
48struct osd_thread {
49   SDL_Thread *        thread;
50   osd_thread_callback callback;
51   void *param;
52};
53
54struct osd_scalable_lock
55{
56   SDL_mutex *         mutex;
57};
58
59//============================================================
60//  Scalable Locks
61//============================================================
62
63osd_scalable_lock *osd_scalable_lock_alloc(void)
64{
65   osd_scalable_lock *lock;
66
67   lock = (osd_scalable_lock *)calloc(1, sizeof(*lock));
68
69   lock->mutex = SDL_CreateMutex();
70   return lock;
71}
72
73
74INT32 osd_scalable_lock_acquire(osd_scalable_lock *lock)
75{
76   SDL_mutexP(lock->mutex);
77   return 0;
78}
79
80
81void osd_scalable_lock_release(osd_scalable_lock *lock, INT32 myslot)
82{
83   SDL_mutexV(lock->mutex);
84}
85
86void osd_scalable_lock_free(osd_scalable_lock *lock)
87{
88   SDL_DestroyMutex(lock->mutex);
89   free(lock);
90}
91
92//============================================================
93//  osd_lock_alloc
94//============================================================
95
96osd_lock *osd_lock_alloc(void)
97{
98   hidden_mutex_t *mutex;
99
100   mutex = (hidden_mutex_t *)calloc(1, sizeof(hidden_mutex_t));
101
102   mutex->id = SDL_CreateMutex();
103
104   return (osd_lock *)mutex;
105}
106
107//============================================================
108//  osd_lock_acquire
109//============================================================
110
111void osd_lock_acquire(osd_lock *lock)
112{
113   hidden_mutex_t *mutex = (hidden_mutex_t *) lock;
114
115   LOG(("osd_lock_acquire"));
116   /* get the lock */
117   mutex->locked++; /* signal that we are *about* to lock - prevent osd_lock_try */
118   SDL_mutexP(mutex->id);
119   mutex->threadid = SDL_ThreadID();
120}
121
122//============================================================
123//  osd_lock_try
124//============================================================
125
126int osd_lock_try(osd_lock *lock)
127{
128   hidden_mutex_t *mutex = (hidden_mutex_t *) lock;
129
130   LOG(("osd_lock_try"));
131   if (mutex->locked && mutex->threadid == SDL_ThreadID())
132   {
133      /* get the lock */
134      SDL_mutexP(mutex->id);
135      mutex->locked++;
136      mutex->threadid = SDL_ThreadID();
137      return 1;
138   }
139   else if ((mutex->locked == 0))
140   {
141      /* get the lock */
142      mutex->locked++;
143      SDL_mutexP(mutex->id);
144      mutex->threadid = SDL_ThreadID();
145      return 1;
146   }
147   else
148   {
149      /* fail */
150      return 0;
151   }
152}
153
154//============================================================
155//  osd_lock_release
156//============================================================
157
158void osd_lock_release(osd_lock *lock)
159{
160   hidden_mutex_t *mutex = (hidden_mutex_t *) lock;
161
162   LOG(("osd_lock_release"));
163   mutex->locked--;
164   if (mutex->locked == 0)
165      mutex->threadid = -1;
166   SDL_mutexV(mutex->id);
167}
168
169//============================================================
170//  osd_lock_free
171//============================================================
172
173void osd_lock_free(osd_lock *lock)
174{
175   hidden_mutex_t *mutex = (hidden_mutex_t *) lock;
176
177   LOG(("osd_lock_free"));
178   //osd_lock_release(lock);
179   SDL_DestroyMutex(mutex->id);
180   free(mutex);
181}
182
183//============================================================
184//  osd_event_alloc
185//============================================================
186
187osd_event *osd_event_alloc(int manualreset, int initialstate)
188{
189   osd_event *ev;
190
191   ev = (osd_event *)calloc(1, sizeof(osd_event));
192
193   ev->mutex = SDL_CreateMutex();
194   ev->cond = SDL_CreateCond();
195   ev->signalled = initialstate;
196   ev->autoreset = !manualreset;
197
198   return ev;
199}
200
201//============================================================
202//  osd_event_free
203//============================================================
204
205void osd_event_free(osd_event *event)
206{
207   SDL_DestroyMutex(event->mutex);
208   SDL_DestroyCond(event->cond);
209   free(event);
210}
211
212//============================================================
213//  osd_event_set
214//============================================================
215
216void osd_event_set(osd_event *event)
217{
218   LOG(("osd_event_set"));
219   SDL_mutexP(event->mutex);
220   if (event->signalled == FALSE)
221   {
222      event->signalled = TRUE;
223      if (event->autoreset)
224         SDL_CondSignal(event->cond);
225      else
226         SDL_CondBroadcast(event->cond);
227   }
228   SDL_mutexV(event->mutex);
229}
230
231//============================================================
232//  osd_event_reset
233//============================================================
234
235void osd_event_reset(osd_event *event)
236{
237   LOG(("osd_event_reset"));
238   SDL_mutexP(event->mutex);
239   event->signalled = FALSE;
240   SDL_mutexV(event->mutex);
241}
242
243//============================================================
244//  osd_event_wait
245//============================================================
246
247int osd_event_wait(osd_event *event, osd_ticks_t timeout)
248{
249   LOG(("osd_event_wait"));
250   SDL_mutexP(event->mutex);
251   if (!timeout)
252   {
253      if (!event->signalled)
254      {
255         SDL_mutexV(event->mutex);
256            return FALSE;
257      }
258   }
259   else
260   {
261      if (!event->signalled)
262      {
263         UINT64 msec = (timeout * 1000) / osd_ticks_per_second();
264
265         do {
266            int ret = SDL_CondWaitTimeout(event->cond, event->mutex, msec);
267            if ( ret == SDL_MUTEX_TIMEDOUT )
268            {
269               if (!event->signalled)
270               {
271                  SDL_mutexV(event->mutex);
272                  return FALSE;
273               }
274               else
275                  break;
276            }
277            if (ret == 0)
278               break;
279            printf("Error %d while waiting for pthread_cond_timedwait:  %s\n", ret, strerror(ret));
280         } while (TRUE);
281      }
282   }
283
284   if (event->autoreset)
285      event->signalled = 0;
286
287   SDL_mutexV(event->mutex);
288
289   return TRUE;
290}
291
292//============================================================
293//  osd_thread_create
294//============================================================
295
296static int worker_thread_entry(void *param)
297{
298   osd_thread *thread = (osd_thread *) param;
299   void *res;
300
301   res = thread->callback(thread->param);
302#ifdef PTR64
303   return (int) (INT64) res;
304#else
305   return (int) res;
306#endif
307}
308
309osd_thread *osd_thread_create(osd_thread_callback callback, void *cbparam)
310{
311   osd_thread *thread;
312
313   thread = (osd_thread *)calloc(1, sizeof(osd_thread));
314   thread->callback = callback;
315   thread->param = cbparam;
316   thread->thread = SDL_CreateThread(worker_thread_entry, thread);
317   if ( thread->thread == NULL )
318   {
319      free(thread);
320      return NULL;
321   }
322   return thread;
323}
324
325//============================================================
326//  osd_thread_adjust_priority
327//============================================================
328
329int osd_thread_adjust_priority(osd_thread *thread, int adjust)
330{
331   return TRUE;
332}
333
334//============================================================
335//  osd_thread_cpu_affinity
336//============================================================
337
338int osd_thread_cpu_affinity(osd_thread *thread, UINT32 mask)
339{
340   return TRUE;
341}
342
343//============================================================
344//  osd_thread_wait_free
345//============================================================
346
347void osd_thread_wait_free(osd_thread *thread)
348{
349   int status;
350   SDL_WaitThread(thread->thread, &status);
351   free(thread);
352}
trunk/src/osd/modules/sync/sync_tc.c
r0r242709
1//============================================================
2//
3//  sdlsync.c - SDL core synchronization functions
4//
5//  Copyright (c) 1996-2010, Nicola Salmoria and the MAME Team.
6//  Visit http://mamedev.org for licensing and usage restrictions.
7//
8//  SDLMAME by Olivier Galibert and R. Belmont
9//
10//============================================================
11
12#ifndef _GNU_SOURCE
13#define _GNU_SOURCE     // for PTHREAD_MUTEX_RECURSIVE; needs to be here before other glibc headers are included
14#endif
15
16#include "sdlinc.h"
17
18#ifdef SDLMAME_MACOSX
19#include <mach/mach.h>
20#endif
21
22// standard C headers
23#include <math.h>
24#include <stdlib.h>
25#include <unistd.h>
26
27// MAME headers
28#include "osdcomm.h"
29#include "osdcore.h"
30
31#include "osdsync.h"
32
33#include <pthread.h>
34#include <errno.h>
35#include <signal.h>
36#include <sys/time.h>
37
38struct hidden_mutex_t {
39   pthread_mutex_t id;
40};
41
42struct osd_event {
43   pthread_mutex_t     mutex;
44   pthread_cond_t      cond;
45   volatile INT32      autoreset;
46   volatile INT32      signalled;
47#ifdef PTR64
48   INT8                padding[40];    // Fill a 64-byte cache line
49#else
50   INT8                padding[48];    // A bit more padding
51#endif
52};
53
54//============================================================
55//  TYPE DEFINITIONS
56//============================================================
57
58struct osd_thread {
59   pthread_t           thread;
60};
61
62struct osd_scalable_lock
63{
64   osd_lock            *lock;
65};
66
67//============================================================
68//  Scalable Locks
69//============================================================
70
71osd_scalable_lock *osd_scalable_lock_alloc(void)
72{
73   osd_scalable_lock *lock;
74
75   lock = (osd_scalable_lock *)calloc(1, sizeof(*lock));
76
77   lock->lock = osd_lock_alloc();
78   return lock;
79}
80
81
82INT32 osd_scalable_lock_acquire(osd_scalable_lock *lock)
83{
84   osd_lock_acquire(lock->lock);
85   return 0;
86}
87
88
89void osd_scalable_lock_release(osd_scalable_lock *lock, INT32 myslot)
90{
91   osd_lock_release(lock->lock);
92}
93
94void osd_scalable_lock_free(osd_scalable_lock *lock)
95{
96   osd_lock_free(lock->lock);
97   free(lock);
98}
99
100
101//============================================================
102//  osd_lock_alloc
103//============================================================
104
105osd_lock *osd_lock_alloc(void)
106{
107   hidden_mutex_t *mutex;
108   pthread_mutexattr_t mtxattr;
109
110   mutex = (hidden_mutex_t *)calloc(1, sizeof(hidden_mutex_t));
111
112   pthread_mutexattr_init(&mtxattr);
113   pthread_mutexattr_settype(&mtxattr, PTHREAD_MUTEX_RECURSIVE);
114   pthread_mutex_init(&mutex->id, &mtxattr);
115
116   return (osd_lock *)mutex;
117}
118
119//============================================================
120//  osd_lock_acquire
121//============================================================
122
123void osd_lock_acquire(osd_lock *lock)
124{
125   hidden_mutex_t *mutex = (hidden_mutex_t *) lock;
126   int r;
127
128   r = pthread_mutex_lock(&mutex->id);
129   if (r==0)
130      return;
131   //osd_printf_error("Error on lock: %d: %s\n", r, strerror(r));
132}
133
134//============================================================
135//  osd_lock_try
136//============================================================
137
138int osd_lock_try(osd_lock *lock)
139{
140   hidden_mutex_t *mutex = (hidden_mutex_t *) lock;
141   int r;
142
143   r = pthread_mutex_trylock(&mutex->id);
144   if (r==0)
145      return 1;
146   //if (r!=EBUSY)
147   //  osd_printf_error("Error on trylock: %d: %s\n", r, strerror(r));
148   return 0;
149}
150
151//============================================================
152//  osd_lock_release
153//============================================================
154
155void osd_lock_release(osd_lock *lock)
156{
157   hidden_mutex_t *mutex = (hidden_mutex_t *) lock;
158
159   pthread_mutex_unlock(&mutex->id);
160}
161
162//============================================================
163//  osd_lock_free
164//============================================================
165
166void osd_lock_free(osd_lock *lock)
167{
168   hidden_mutex_t *mutex = (hidden_mutex_t *) lock;
169
170   //pthread_mutex_unlock(&mutex->id);
171   pthread_mutex_destroy(&mutex->id);
172   free(mutex);
173}
174
175//============================================================
176//  osd_event_alloc
177//============================================================
178
179osd_event *osd_event_alloc(int manualreset, int initialstate)
180{
181   osd_event *ev;
182   pthread_mutexattr_t mtxattr;
183
184   ev = (osd_event *)calloc(1, sizeof(osd_event));
185
186   pthread_mutexattr_init(&mtxattr);
187   pthread_mutex_init(&ev->mutex, &mtxattr);
188   pthread_cond_init(&ev->cond, NULL);
189   ev->signalled = initialstate;
190   ev->autoreset = !manualreset;
191
192   return ev;
193}
194
195//============================================================
196//  osd_event_free
197//============================================================
198
199void osd_event_free(osd_event *event)
200{
201   pthread_mutex_destroy(&event->mutex);
202   pthread_cond_destroy(&event->cond);
203   free(event);
204}
205
206//============================================================
207//  osd_event_set
208//============================================================
209
210void osd_event_set(osd_event *event)
211{
212   pthread_mutex_lock(&event->mutex);
213   if (event->signalled == FALSE)
214   {
215      event->signalled = TRUE;
216      if (event->autoreset)
217         pthread_cond_signal(&event->cond);
218      else
219         pthread_cond_broadcast(&event->cond);
220   }
221   pthread_mutex_unlock(&event->mutex);
222}
223
224//============================================================
225//  osd_event_reset
226//============================================================
227
228void osd_event_reset(osd_event *event)
229{
230   pthread_mutex_lock(&event->mutex);
231   event->signalled = FALSE;
232   pthread_mutex_unlock(&event->mutex);
233}
234
235//============================================================
236//  osd_event_wait
237//============================================================
238
239int osd_event_wait(osd_event *event, osd_ticks_t timeout)
240{
241   pthread_mutex_lock(&event->mutex);
242   if (!timeout)
243   {
244      if (!event->signalled)
245      {
246            pthread_mutex_unlock(&event->mutex);
247            return FALSE;
248      }
249   }
250   else
251   {
252      if (!event->signalled)
253      {
254         struct timespec   ts;
255         struct timeval    tp;
256         UINT64 msec = timeout * 1000 / osd_ticks_per_second();
257         UINT64 nsec;
258
259         gettimeofday(&tp, NULL);
260
261         ts.tv_sec  = tp.tv_sec;
262         nsec = (UINT64) tp.tv_usec * (UINT64) 1000 + (msec * (UINT64) 1000000);
263         ts.tv_nsec = nsec % (UINT64) 1000000000;
264         ts.tv_sec += nsec / (UINT64) 1000000000;
265
266         do {
267            int ret = pthread_cond_timedwait(&event->cond, &event->mutex, &ts);
268            if ( ret == ETIMEDOUT )
269            {
270               if (!event->signalled)
271               {
272                  pthread_mutex_unlock(&event->mutex);
273                  return FALSE;
274               }
275               else
276                  break;
277            }
278            if (ret == 0)
279               break;
280            if ( ret != EINTR)
281            {
282               printf("Error %d while waiting for pthread_cond_timedwait:  %s\n", ret, strerror(ret));
283            }
284
285         } while (TRUE);
286      }
287   }
288
289   if (event->autoreset)
290      event->signalled = 0;
291
292   pthread_mutex_unlock(&event->mutex);
293
294   return TRUE;
295}
296
297//============================================================
298//  osd_thread_create
299//============================================================
300
301osd_thread *osd_thread_create(osd_thread_callback callback, void *cbparam)
302{
303   osd_thread *thread;
304   pthread_attr_t  attr;
305
306   thread = (osd_thread *)calloc(1, sizeof(osd_thread));
307   pthread_attr_init(&attr);
308   pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
309   if ( pthread_create(&thread->thread, &attr, callback, cbparam) != 0 )
310   {
311      free(thread);
312      return NULL;
313   }
314   return thread;
315}
316
317//============================================================
318//  osd_thread_adjust_priority
319//============================================================
320
321int osd_thread_adjust_priority(osd_thread *thread, int adjust)
322{
323   struct sched_param  sched;
324   int                 policy;
325
326   if ( pthread_getschedparam( thread->thread, &policy, &sched ) == 0 )
327   {
328      sched.sched_priority += adjust;
329      if ( pthread_setschedparam(thread->thread, policy, &sched ) == 0)
330         return TRUE;
331      else
332         return FALSE;
333   }
334   else
335      return FALSE;
336}
337
338//============================================================
339//  osd_thread_cpu_affinity
340//============================================================
341
342int osd_thread_cpu_affinity(osd_thread *thread, UINT32 mask)
343{
344#if !defined(NO_AFFINITY_NP)
345   cpu_set_t   cmask;
346   pthread_t   lthread;
347   int         bitnum;
348
349   CPU_ZERO(&cmask);
350   for (bitnum=0; bitnum<32; bitnum++)
351      if (mask & (1<<bitnum))
352         CPU_SET(bitnum, &cmask);
353
354   if (thread == NULL)
355      lthread = pthread_self();
356   else
357      lthread = thread->thread;
358
359   if (pthread_setaffinity_np(lthread, sizeof(cmask), &cmask) <0)
360   {
361      /* Not available during link in all targets */
362      fprintf(stderr, "error %d setting cpu affinity to mask %08x", errno, mask);
363      return FALSE;
364   }
365   else
366      return TRUE;
367#else
368   return TRUE;
369#endif
370}
371
372//============================================================
373//  osd_thread_wait_free
374//============================================================
375
376void osd_thread_wait_free(osd_thread *thread)
377{
378   pthread_join(thread->thread, NULL);
379   free(thread);
380}
381
382//============================================================
383//  osd_process_kill
384//============================================================
385
386void osd_process_kill(void)
387{
388   kill(getpid(), SIGKILL);
389}
trunk/src/osd/modules/sync/sync_windows.c
r0r242709
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles
3//============================================================
4//
5//  winsync.c - Win32 OSD core synchronization functions
6//
7//============================================================
8
9// standard windows headers
10#define WIN32_LEAN_AND_MEAN
11#include <windows.h>
12#include <stdlib.h>
13#include <process.h>
14
15// MAME headers
16#include "osdcore.h"
17#include "osinline.h"
18#include "osdsync.h"
19
20
21//============================================================
22//  DEBUGGING
23//============================================================
24
25#define DEBUG_SLOW_LOCKS    0
26#define USE_SCALABLE_LOCKS      (0)
27
28
29
30//============================================================
31//  TYPE DEFINITIONS
32//============================================================
33
34typedef BOOL (WINAPI *try_enter_critical_section_ptr)(LPCRITICAL_SECTION lpCriticalSection);
35
36struct osd_lock
37{
38   CRITICAL_SECTION    critsect;
39};
40
41struct osd_event
42{
43   void *  ptr;
44};
45
46struct osd_thread {
47   HANDLE handle;
48   osd_thread_callback callback;
49   void *param;
50};
51
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
67//============================================================
68//  GLOBAL VARIABLES
69//============================================================
70
71static try_enter_critical_section_ptr try_enter_critical_section = NULL;
72static int checked_for_try_enter = FALSE;
73
74
75
76//============================================================
77//  osd_lock_alloc
78//============================================================
79
80osd_lock *osd_lock_alloc(void)
81{
82   osd_lock *lock = (osd_lock *)malloc(sizeof(*lock));
83   if (lock == NULL)
84      return NULL;
85   InitializeCriticalSection(&lock->critsect);
86   return lock;
87}
88
89
90//============================================================
91//  osd_lock_acquire
92//============================================================
93
94void osd_lock_acquire(osd_lock *lock)
95{
96#if DEBUG_SLOW_LOCKS
97   osd_ticks_t ticks = osd_ticks();
98#endif
99
100   // block until we can acquire the lock
101   EnterCriticalSection(&lock->critsect);
102
103#if DEBUG_SLOW_LOCKS
104   // log any locks that take more than 1ms
105   ticks = osd_ticks() - ticks;
106   if (ticks > osd_ticks_per_second() / 1000) osd_printf_debug("Blocked %d ticks on lock acquire\n", (int)ticks);
107#endif
108}
109
110
111//============================================================
112//  osd_lock_try
113//============================================================
114
115int osd_lock_try(osd_lock *lock)
116{
117   int result = TRUE;
118
119   // if we haven't yet checked for the TryEnter API, do it now
120   if (!checked_for_try_enter)
121   {
122      // see if we can use TryEnterCriticalSection
123      HMODULE library = LoadLibrary(TEXT("kernel32.dll"));
124      if (library != NULL)
125         try_enter_critical_section = (try_enter_critical_section_ptr)GetProcAddress(library, "TryEnterCriticalSection");
126      checked_for_try_enter = TRUE;
127   }
128
129   // if we have it, use it, otherwise just block
130   if (try_enter_critical_section != NULL)
131      result = (*try_enter_critical_section)(&lock->critsect);
132   else
133      EnterCriticalSection(&lock->critsect);
134   return result;
135}
136
137
138//============================================================
139//  osd_lock_release
140//============================================================
141
142void osd_lock_release(osd_lock *lock)
143{
144   LeaveCriticalSection(&lock->critsect);
145}
146
147
148//============================================================
149//  osd_lock_free
150//============================================================
151
152void osd_lock_free(osd_lock *lock)
153{
154   DeleteCriticalSection(&lock->critsect);
155   free(lock);
156}
157
158
159//============================================================
160//  win_compare_exchange32
161//============================================================
162
163INT32 win_compare_exchange32(INT32 volatile *ptr, INT32 compare, INT32 exchange)
164{
165   return InterlockedCompareExchange((LPLONG)ptr, (LONG)exchange, (LONG)compare);
166}
167
168
169//============================================================
170//  win_compare_exchange64
171//============================================================
172
173#ifdef PTR64
174INT64 win_compare_exchange64(INT64 volatile *ptr, INT64 compare, INT64 exchange)
175{
176   return InterlockedCompareExchange64((LONGLONG*)ptr, (LONGLONG)exchange, (LONGLONG)compare);
177}
178#endif
179
180
181//============================================================
182//  win_atomic_exchange32
183//============================================================
184
185INT32 win_atomic_exchange32(INT32 volatile *ptr, INT32 exchange)
186{
187   return InterlockedExchange((LONG *) ptr, exchange);
188}
189
190
191//============================================================
192//  win_atomic_add32
193//============================================================
194
195INT32 win_atomic_add32(INT32 volatile *ptr, INT32 delta)
196{
197   return InterlockedExchangeAdd((LONG *) ptr, delta) + delta;
198}
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}
trunk/src/osd/osdmini/miniwork.c
r242708r242709
1919   void *result;
2020};
2121
22//============================================================
23//  GLOBAL VARIABLES
24//============================================================
2225
26int osd_num_processors = 0;
2327
2428//============================================================
2529//  osd_work_queue_alloc
trunk/src/osd/sdl/sdl.mak
r242708r242709
322322
323323ifeq ($(TARGETOS),win32)
324324BASE_TARGETOS = win32
325SYNC_IMPLEMENTATION = win32
325SYNC_IMPLEMENTATION = windows
326326NO_X11 = 1
327327NO_USE_XINPUT = 1
328328DEFS += -DSDLMAME_WIN32 -DX64_WINDOWS_ABI
r242708r242709
391391SDLSRC = $(SRC)/osd/$(OSD)
392392SDLOBJ = $(OBJ)/osd/$(OSD)
393393
394OBJDIRS += $(SDLOBJ)
394OBJDIRS += $(SDLOBJ) $(OSDOBJ)/modules/sync
395395
396396#-------------------------------------------------
397397# OSD core library
r242708r242709
405405   $(SDLOBJ)/sdlsocket.o   \
406406   $(SDLOBJ)/sdlmisc_$(BASE_TARGETOS).o    \
407407   $(SDLOBJ)/sdlos_$(SDLOS_TARGETOS).o \
408   $(SDLOBJ)/sdlsync_$(SYNC_IMPLEMENTATION).o     \
408   $(OSDOBJ)/modules/sync/sync_$(SYNC_IMPLEMENTATION).o     \
409409   $(SDLOBJ)/sdlwork.o
410410
411411# any "main" must be in LIBOSD or else the build will fail!
trunk/src/osd/sdl/sdlsync.h
r242708r242709
1//============================================================
2//
3//  sdlsync.h - SDL core synchronization functions
4//
5//  Copyright (c) 1996-2007, Nicola Salmoria and the MAME Team.
6//  Visit http://mamedev.org for licensing and usage restrictions.
7//
8//  SDLMAME by Olivier Galibert and R. Belmont
9//
10//============================================================
11
12#ifndef __SDLSYNC__
13#define __SDLSYNC__
14
15/***************************************************************************
16    SYNCHRONIZATION INTERFACES - Events
17***************************************************************************/
18
19/* osd_event is an opaque type which represents a setable/resetable event */
20
21struct osd_event;
22
23
24/*-----------------------------------------------------------------------------
25    osd_lock_event_alloc: allocate a new event
26
27    Parameters:
28
29        manualreset  - boolean. If true, the event will be automatically set
30                       to non-signalled after a thread successfully waited for
31                       it.
32        initialstate - boolean. If true, the event is signalled initially.
33
34    Return value:
35
36        A pointer to the allocated event.
37-----------------------------------------------------------------------------*/
38osd_event *osd_event_alloc(int manualreset, int initialstate);
39
40
41/*-----------------------------------------------------------------------------
42    osd_event_wait: wait for an event to be signalled
43
44    Parameters:
45
46        event - The event to wait for. If the event is in signalled state, the
47                function returns immediately. If not it will wait for the event
48                to become signalled.
49        timeout - timeout in osd_ticks
50
51    Return value:
52
53        TRUE:  The event was signalled
54        FALSE: A timeout occurred
55-----------------------------------------------------------------------------*/
56int osd_event_wait(osd_event *event, osd_ticks_t timeout);
57
58
59/*-----------------------------------------------------------------------------
60    osd_event_reset: reset an event to non-signalled state
61
62    Parameters:
63
64        event - The event to set to non-signalled state
65
66    Return value:
67
68        None
69-----------------------------------------------------------------------------*/
70void osd_event_reset(osd_event *event);
71
72
73/*-----------------------------------------------------------------------------
74    osd_event_set: set an event to signalled state
75
76    Parameters:
77
78        event - The event to set to signalled state
79
80    Return value:
81
82        None
83
84    Notes:
85
86        All threads waiting for the event will be signalled.
87-----------------------------------------------------------------------------*/
88void osd_event_set(osd_event *event);
89
90
91/*-----------------------------------------------------------------------------
92    osd_event_free: free the memory and resources associated with an osd_event
93
94    Parameters:
95
96        event - a pointer to a previously allocated osd_event.
97
98    Return value:
99
100        None.
101-----------------------------------------------------------------------------*/
102void osd_event_free(osd_event *event);
103
104
105/***************************************************************************
106    SYNCHRONIZATION INTERFACES - Threads
107***************************************************************************/
108
109/* osd_thread is an opaque type which represents a thread */
110struct osd_thread;
111
112
113/* osd_thread_callback is a callback function that will be called from the thread */
114typedef void *(*osd_thread_callback)(void *param);
115
116
117/*-----------------------------------------------------------------------------
118    osd_thread_create: create a new thread
119
120    Parameters:
121
122        callback - The callback function to be called once the thread is up
123        cbparam  - The parameter to pass to the callback function.
124
125    Return value:
126
127        A pointer to the created thread.
128-----------------------------------------------------------------------------*/
129osd_thread *osd_thread_create(osd_thread_callback callback, void *cbparam);
130
131
132/*-----------------------------------------------------------------------------
133    osd_thread_adjust_priority: adjust priority of a thread
134
135    Parameters:
136
137        thread - A pointer to a previously created thread.
138        adjust - signed integer to add to the thread priority
139
140    Return value:
141
142        TRUE on success, FALSE on failure
143-----------------------------------------------------------------------------*/
144int osd_thread_adjust_priority(osd_thread *thread, int adjust);
145
146
147/*-----------------------------------------------------------------------------
148    osd_thread_cpu_affinity: change cpu affinity of a thread
149
150    Parameters:
151
152        thread - A pointer to a previously created thread
153                 or NULL for main thread
154        mask   - bitmask to which cpus to bind
155                 i.e. 0x01 1st cpu, 0x02, 2nd cpu, 0x04 3rd cpu
156
157    Return value:
158
159        TRUE on success, FALSE on failure
160-----------------------------------------------------------------------------*/
161int osd_thread_cpu_affinity(osd_thread *thread, UINT32 mask);
162
163
164/*-----------------------------------------------------------------------------
165    osd_thread_wait_free: wait for thread to finish and free resources
166
167    Parameters:
168
169        thread - A pointer to a previously created thread.
170
171    Return value:
172
173        None.
174-----------------------------------------------------------------------------*/
175void osd_thread_wait_free(osd_thread *thread);
176
177/*-----------------------------------------------------------------------------
178    osd_process_kill: kill the current process
179
180    Parameters:
181
182        None.
183
184    Return value:
185
186        None.
187-----------------------------------------------------------------------------*/
188void osd_process_kill(void);
189
190//============================================================
191//  Scalable Locks
192//============================================================
193
194struct osd_scalable_lock;
195
196osd_scalable_lock *osd_scalable_lock_alloc(void);
197
198INT32 osd_scalable_lock_acquire(osd_scalable_lock *lock);
199
200void osd_scalable_lock_release(osd_scalable_lock *lock, INT32 myslot);
201
202void osd_scalable_lock_free(osd_scalable_lock *lock);
203
204#endif  /* __SDLSYNC__ */
trunk/src/osd/sdl/sdlsync_mini.c
r242708r242709
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles
3//============================================================
4//
5//  sdlsync_mini.c - Minimal core synchronization functions
6//
7//============================================================
8
9#include "osdcore.h"
10#include "sdlsync.h"
11
12#define USE_SCALABLE_LOCKS      (0)
13
14struct _osd_event
15{
16   void *  ptr;
17};
18
19struct _osd_thread {
20   void *  ptr;
21};
22
23
24//============================================================
25//  osd_lock_alloc
26//============================================================
27
28osd_lock *osd_lock_alloc(void)
29{
30   // the minimal implementation does not support threading
31   // just return a dummy value here
32   return (osd_lock *)1;
33}
34
35
36//============================================================
37//  osd_lock_acquire
38//============================================================
39
40void osd_lock_acquire(osd_lock *lock)
41{
42   // the minimal implementation does not support threading
43   // the acquire always "succeeds"
44}
45
46
47//============================================================
48//  osd_lock_try
49//============================================================
50
51int osd_lock_try(osd_lock *lock)
52{
53   // the minimal implementation does not support threading
54   // the acquire always "succeeds"
55   return TRUE;
56}
57
58
59//============================================================
60//  osd_lock_release
61//============================================================
62
63void osd_lock_release(osd_lock *lock)
64{
65   // the minimal implementation does not support threading
66   // do nothing here
67}
68
69
70//============================================================
71//  osd_lock_free
72//============================================================
73
74void osd_lock_free(osd_lock *lock)
75{
76   // the minimal implementation does not support threading
77   // do nothing here
78}
79
80
81//============================================================
82//  osd_event_alloc
83//============================================================
84
85osd_event *osd_event_alloc(int manualreset, int initialstate)
86{
87   return NULL;
88}
89
90
91//============================================================
92//  osd_event_free
93//============================================================
94
95void osd_event_free(osd_event *event)
96{
97}
98
99
100//============================================================
101//  osd_event_set
102//============================================================
103
104void osd_event_set(osd_event *event)
105{
106}
107
108
109//============================================================
110//  osd_event_reset
111//============================================================
112
113void osd_event_reset(osd_event *event)
114{
115}
116
117
118//============================================================
119//  osd_event_wait
120//============================================================
121
122int osd_event_wait(osd_event *event, osd_ticks_t timeout)
123{
124   return TRUE;
125}
126
127
128//============================================================
129//  osd_thread_create
130//============================================================
131
132osd_thread *osd_thread_create(osd_thread_callback callback, void *cbparam)
133{
134   return NULL;
135}
136
137
138//============================================================
139//  osd_thread_adjust_priority
140//============================================================
141
142int osd_thread_adjust_priority(osd_thread *thread, int adjust)
143{
144   return FALSE;
145}
146
147
148//============================================================
149//  osd_thread_cpu_affinity
150//============================================================
151
152int osd_thread_cpu_affinity(osd_thread *thread, UINT32 mask)
153{
154   return TRUE;
155}
156
157
158//============================================================
159//  osd_thread_wait_free
160//============================================================
161
162void osd_thread_wait_free(osd_thread *thread)
163{
164}
165
166
167//============================================================
168//  osd_process_kill
169//============================================================
170
171void osd_process_kill(void)
172{
173}
trunk/src/osd/sdl/sdlsync_ntc.c
r242708r242709
1//============================================================
2//
3//  sdlsync.c - SDL core synchronization functions
4//
5//  Copyright (c) 1996-2011, Nicola Salmoria and the MAME Team.
6//  Visit http://mamedev.org for licensing and usage restrictions.
7//
8//  SDLMAME by Olivier Galibert and R. Belmont
9//
10//============================================================
11
12#ifndef _GNU_SOURCE
13#define _GNU_SOURCE     // for PTHREAD_MUTEX_RECURSIVE; needs to be here before other glibc headers are included
14#endif
15
16#include "sdlinc.h"
17
18#ifdef SDLMAME_MACOSX
19#include <mach/mach.h>
20#include <signal.h>
21#endif
22
23#if defined(SDLMAME_NETBSD) || defined(SDLMAME_OPENBSD)
24/* for SIGKILL */
25#include <signal.h>
26#endif
27
28// standard C headers
29#include <math.h>
30#include <unistd.h>
31
32// MAME headers
33#include "osdcore.h"
34#include "osinline.h"
35#include "sdlsync.h"
36
37#include "eminline.h"
38
39#include <pthread.h>
40#include <errno.h>
41#include <sys/time.h>
42
43struct osd_lock {
44   volatile pthread_t  holder;
45   INT32               count;
46#ifdef PTR64
47   INT8                padding[52];    // Fill a 64-byte cache line
48#else
49   INT8                padding[56];    // A bit more padding
50#endif
51};
52
53struct osd_event {
54   pthread_mutex_t     mutex;
55   pthread_cond_t      cond;
56   volatile INT32      autoreset;
57   volatile INT32      signalled;
58#ifdef PTR64
59   INT8                padding[40];    // Fill a 64-byte cache line
60#else
61   INT8                padding[48];    // A bit more padding
62#endif
63};
64
65
66//============================================================
67//  TYPE DEFINITIONS
68//============================================================
69
70struct osd_thread {
71   pthread_t           thread;
72};
73
74struct osd_scalable_lock
75{
76   struct
77   {
78      volatile INT32  haslock;        // do we have the lock?
79      INT32           filler[64/4-1]; // assumes a 64-byte cache line
80   } slot[WORK_MAX_THREADS];           // one slot per thread
81   volatile INT32      nextindex;      // index of next slot to use
82};
83
84
85//============================================================
86//  Scalable Locks
87//============================================================
88
89osd_scalable_lock *osd_scalable_lock_alloc(void)
90{
91   osd_scalable_lock *lock;
92
93   lock = (osd_scalable_lock *)calloc(1, sizeof(*lock));
94
95   memset(lock, 0, sizeof(*lock));
96   lock->slot[0].haslock = TRUE;
97   return lock;
98}
99
100
101INT32 osd_scalable_lock_acquire(osd_scalable_lock *lock)
102{
103   INT32 myslot = (atomic_increment32(&lock->nextindex) - 1) & (WORK_MAX_THREADS - 1);
104
105#if defined(__i386__) || defined(__x86_64__)
106   register INT32 tmp;
107   __asm__ __volatile__ (
108      "1: clr    %[tmp]             ;"
109      "   xchg   %[haslock], %[tmp] ;"
110      "   test   %[tmp], %[tmp]     ;"
111      "   jne    3f                 ;"
112      "2: mov    %[haslock], %[tmp] ;"
113      "   test   %[tmp], %[tmp]     ;"
114      "   jne    1b                 ;"
115      "   pause                     ;"
116      "   jmp    2b                 ;"
117      "3:                            "
118      : [haslock] "+m"  (lock->slot[myslot].haslock)
119      , [tmp]     "=&r" (tmp)
120      :
121      : "cc"
122   );
123#elif defined(__ppc__) || defined (__PPC__) || defined(__ppc64__) || defined(__PPC64__)
124   register INT32 tmp;
125   __asm__ __volatile__ (
126      "1: lwarx   %[tmp], 0, %[haslock] \n"
127      "   cmpwi   %[tmp], 0             \n"
128      "   bne     3f                    \n"
129      "2: lwzx    %[tmp], 0, %[haslock] \n"
130      "   cmpwi   %[tmp], 0             \n"
131      "   bne     1b                    \n"
132      "   nop                           \n"
133      "   nop                           \n"
134      "   b       2b                    \n"
135      "3: li      %[tmp], 0             \n"
136      "   sync                          \n"
137      "   stwcx.  %[tmp], 0, %[haslock] \n"
138      "   bne-    1b                    \n"
139      "   eieio                         \n"
140      : [tmp]     "=&r" (tmp)
141      : [haslock] "r"   (&lock->slot[myslot].haslock)
142      : "cr0"
143   );
144#else
145   INT32 backoff = 1;
146   while (!osd_compare_exchange32(&lock->slot[myslot].haslock, TRUE, FALSE))
147   {
148      INT32 backcount;
149      for (backcount = 0; backcount < backoff; backcount++)
150         osd_yield_processor();
151      backoff <<= 1;
152   }
153#endif
154   return myslot;
155}
156
157
158void osd_scalable_lock_release(osd_scalable_lock *lock, INT32 myslot)
159{
160#if defined(__i386__) || defined(__x86_64__)
161   register INT32 tmp = TRUE;
162   __asm__ __volatile__ (
163      " xchg   %[haslock], %[tmp] ;"
164      : [haslock] "+m" (lock->slot[(myslot + 1) & (WORK_MAX_THREADS - 1)].haslock)
165      , [tmp]     "+r" (tmp)
166      :
167   );
168#elif defined(__ppc__) || defined (__PPC__) || defined(__ppc64__) || defined(__PPC64__)
169   lock->slot[(myslot + 1) & (WORK_MAX_THREADS - 1)].haslock = TRUE;
170   __asm__ __volatile__ ( " eieio " : : );
171#else
172   osd_exchange32(&lock->slot[(myslot + 1) & (WORK_MAX_THREADS - 1)].haslock, TRUE);
173#endif
174}
175
176void osd_scalable_lock_free(osd_scalable_lock *lock)
177{
178   free(lock);
179}
180
181INLINE pthread_t osd_compare_exchange_pthread_t(pthread_t volatile *ptr, pthread_t compare, pthread_t exchange)
182{
183#ifdef PTR64
184   INT64 result = compare_exchange64((INT64 volatile *)ptr, (INT64)compare, (INT64)exchange);
185#else
186   INT32 result = compare_exchange32((INT32 volatile *)ptr, (INT32)compare, (INT32)exchange);
187#endif
188   return (pthread_t)result;
189}
190
191INLINE pthread_t osd_exchange_pthread_t(pthread_t volatile *ptr, pthread_t exchange)
192{
193#ifdef PTR64
194   INT64 result = osd_exchange64((INT64 volatile *)ptr, (INT64)exchange);
195#else
196   INT32 result = atomic_exchange32((INT32 volatile *)ptr, (INT32)exchange);
197#endif
198   return (pthread_t)result;
199}
200
201
202//============================================================
203//  osd_lock_alloc
204//============================================================
205
206osd_lock *osd_lock_alloc(void)
207{
208   osd_lock *lock;
209
210   lock = (osd_lock *)calloc(1, sizeof(osd_lock));
211
212   lock->holder = 0;
213   lock->count = 0;
214
215   return lock;
216}
217
218//============================================================
219//  osd_lock_acquire
220//============================================================
221
222void osd_lock_acquire(osd_lock *lock)
223{
224   pthread_t current, prev;
225
226   current = pthread_self();
227   prev = osd_compare_exchange_pthread_t(&lock->holder, 0, current);
228   if (prev != (size_t)NULL && prev != current)
229   {
230      do {
231         register INT32 spin = 10000; // Convenient spin count
232         register pthread_t tmp;
233#if defined(__i386__) || defined(__x86_64__)
234         __asm__ __volatile__ (
235            "1: pause                    ;"
236            "   mov    %[holder], %[tmp] ;"
237            "   test   %[tmp], %[tmp]    ;"
238            "   loopne 1b                ;"
239            : [spin]   "+c"  (spin)
240            , [tmp]    "=&r" (tmp)
241            : [holder] "m"   (lock->holder)
242            : "cc"
243         );
244#elif defined(__ppc__) || defined(__PPC__)
245         __asm__ __volatile__ (
246            "1: nop                        \n"
247            "   nop                        \n"
248            "   lwzx  %[tmp], 0, %[holder] \n"
249            "   cmpwi %[tmp], 0            \n"
250            "   bdnzt eq, 1b               \n"
251            : [spin]   "+c"  (spin)
252            , [tmp]    "=&r" (tmp)
253            : [holder] "r"   (&lock->holder)
254            : "cr0"
255         );
256#elif defined(__ppc64__) || defined(__PPC64__)
257         __asm__ __volatile__ (
258            "1: nop                        \n"
259            "   nop                        \n"
260            "   ldx   %[tmp], 0, %[holder] \n"
261            "   cmpdi %[tmp], 0            \n"
262            "   bdnzt eq, 1b               \n"
263            : [spin]   "+c"  (spin)
264            , [tmp]    "=&r" (tmp)
265            : [holder] "r"   (&lock->holder)
266            : "cr0"
267         );
268#else
269         while (--spin > 0 && lock->holder != NULL)
270            osd_yield_processor();
271#endif
272#if 0
273         /* If you mean to use locks as a blocking mechanism for extended
274          * periods of time, you should do something like this.  However,
275          * it kills the performance of gaelco3d.
276          */
277         if (spin == 0)
278         {
279            struct timespec sleep = { 0, 100000 }, remaining;
280            nanosleep(&sleep, &remaining); // sleep for 100us
281         }
282#endif
283      } while (osd_compare_exchange_pthread_t(&lock->holder, 0, current) != (size_t)NULL);
284   }
285   lock->count++;
286}
287
288//============================================================
289//  osd_lock_try
290//============================================================
291
292int osd_lock_try(osd_lock *lock)
293{
294   pthread_t current, prev;
295
296   current = pthread_self();
297   prev = osd_compare_exchange_pthread_t(&lock->holder, 0, current);
298   if (prev == (size_t)NULL || prev == current)
299   {
300      lock->count++;
301      return 1;
302   }
303   return 0;
304}
305
306//============================================================
307//  osd_lock_release
308//============================================================
309
310void osd_lock_release(osd_lock *lock)
311{
312   pthread_t current;
313
314   current = pthread_self();
315   if (lock->holder == current)
316   {
317      if (--lock->count == 0)
318#if defined(__ppc__) || defined(__PPC__) || defined(__ppc64__) || defined(__PPC64__)
319      lock->holder = 0;
320      __asm__ __volatile__( " eieio " : : );
321#else
322      osd_exchange_pthread_t(&lock->holder, 0);
323#endif
324      return;
325   }
326
327   // trying to release a lock you don't hold is bad!
328//  assert(lock->holder == pthread_self());
329}
330
331//============================================================
332//  osd_lock_free
333//============================================================
334
335void osd_lock_free(osd_lock *lock)
336{
337   free(lock);
338}
339
340//============================================================
341//  osd_event_alloc
342//============================================================
343
344osd_event *osd_event_alloc(int manualreset, int initialstate)
345{
346   osd_event *ev;
347   pthread_mutexattr_t mtxattr;
348
349   ev = (osd_event *)calloc(1, sizeof(osd_event));
350
351   pthread_mutexattr_init(&mtxattr);
352   pthread_mutex_init(&ev->mutex, &mtxattr);
353   pthread_cond_init(&ev->cond, NULL);
354   ev->signalled = initialstate;
355   ev->autoreset = !manualreset;
356
357   return ev;
358}
359
360//============================================================
361//  osd_event_free
362//============================================================
363
364void osd_event_free(osd_event *event)
365{
366   pthread_mutex_destroy(&event->mutex);
367   pthread_cond_destroy(&event->cond);
368   free(event);
369}
370
371//============================================================
372//  osd_event_set
373//============================================================
374
375void osd_event_set(osd_event *event)
376{
377   pthread_mutex_lock(&event->mutex);
378   if (event->signalled == FALSE)
379   {
380      event->signalled = TRUE;
381      if (event->autoreset)
382         pthread_cond_signal(&event->cond);
383      else
384         pthread_cond_broadcast(&event->cond);
385   }
386   pthread_mutex_unlock(&event->mutex);
387}
388
389//============================================================
390//  osd_event_reset
391//============================================================
392
393void osd_event_reset(osd_event *event)
394{
395   pthread_mutex_lock(&event->mutex);
396   event->signalled = FALSE;
397   pthread_mutex_unlock(&event->mutex);
398}
399
400//============================================================
401//  osd_event_wait
402//============================================================
403
404int osd_event_wait(osd_event *event, osd_ticks_t timeout)
405{
406   pthread_mutex_lock(&event->mutex);
407   if (!timeout)
408   {
409      if (!event->signalled)
410      {
411            pthread_mutex_unlock(&event->mutex);
412            return FALSE;
413      }
414   }
415   else
416   {
417      if (!event->signalled)
418      {
419         struct timespec   ts;
420         struct timeval    tp;
421         UINT64 msec = timeout * 1000 / osd_ticks_per_second();
422         UINT64 nsec;
423
424         gettimeofday(&tp, NULL);
425
426         ts.tv_sec  = tp.tv_sec;
427         nsec = (UINT64) tp.tv_usec * (UINT64) 1000 + (msec * (UINT64) 1000000);
428         ts.tv_nsec = nsec % (UINT64) 1000000000;
429         ts.tv_sec += nsec / (UINT64) 1000000000;
430
431         do {
432            int ret = pthread_cond_timedwait(&event->cond, &event->mutex, &ts);
433            if ( ret == ETIMEDOUT )
434            {
435               if (!event->signalled)
436               {
437                  pthread_mutex_unlock(&event->mutex);
438                  return FALSE;
439               }
440               else
441                  break;
442            }
443            if (ret == 0)
444               break;
445            if ( ret != EINTR)
446            {
447               printf("Error %d while waiting for pthread_cond_timedwait:  %s\n", ret, strerror(ret));
448            }
449
450         } while (TRUE);
451      }
452   }
453
454   if (event->autoreset)
455      event->signalled = 0;
456
457   pthread_mutex_unlock(&event->mutex);
458
459   return TRUE;
460}
461
462//============================================================
463//  osd_thread_create
464//============================================================
465
466osd_thread *osd_thread_create(osd_thread_callback callback, void *cbparam)
467{
468   osd_thread *thread;
469   pthread_attr_t  attr;
470
471   thread = (osd_thread *)calloc(1, sizeof(osd_thread));
472   pthread_attr_init(&attr);
473#ifndef SDLMAME_HAIKU
474   pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
475#endif
476   if ( pthread_create(&thread->thread, &attr, callback, cbparam) != 0 )
477   {
478      free(thread);
479      return NULL;
480   }
481   return thread;
482}
483
484//============================================================
485//  osd_thread_adjust_priority
486//============================================================
487
488int osd_thread_adjust_priority(osd_thread *thread, int adjust)
489{
490   struct sched_param  sched;
491   int                 policy;
492
493   if ( pthread_getschedparam( thread->thread, &policy, &sched ) == 0 )
494   {
495      sched.sched_priority += adjust;
496      if ( pthread_setschedparam(thread->thread, policy, &sched ) == 0)
497         return TRUE;
498      else
499         return FALSE;
500   }
501   else
502      return FALSE;
503}
504
505//============================================================
506//  osd_thread_cpu_affinity
507//============================================================
508
509int osd_thread_cpu_affinity(osd_thread *thread, UINT32 mask)
510{
511   return TRUE;
512}
513
514//============================================================
515//  osd_thread_wait_free
516//============================================================
517
518void osd_thread_wait_free(osd_thread *thread)
519{
520   pthread_join(thread->thread, NULL);
521   free(thread);
522}
523
524//============================================================
525//  osd_process_kill
526//============================================================
527
528void osd_process_kill(void)
529{
530   kill(getpid(), SIGKILL);
531}
trunk/src/osd/sdl/sdlsync_os2.c
r242708r242709
1//============================================================
2//
3//  sdlsync.c - SDL core synchronization functions
4//
5//  Copyright (c) 1996-2010, Nicola Salmoria and the MAME Team.
6//  Visit http://mamedev.org for licensing and usage restrictions.
7//
8//  SDLMAME by Olivier Galibert and R. Belmont
9//
10//============================================================
11
12#ifndef _GNU_SOURCE
13#define _GNU_SOURCE     // for PTHREAD_MUTEX_RECURSIVE; needs to be here before other glibc headers are included
14#endif
15
16#include "sdlinc.h"
17
18// standard C headers
19#include <math.h>
20#include <unistd.h>
21
22// MAME headers
23#include "osdcore.h"
24#include "osinline.h"
25#include "sdlsync.h"
26
27#include "eminline.h"
28
29#define INCL_DOS
30#include <os2.h>
31
32#include <stdlib.h>
33#define pthread_t       int
34#define pthread_self    _gettid
35
36struct osd_lock {
37   volatile pthread_t  holder;
38   INT32               count;
39#ifdef PTR64
40   INT8                padding[52];    // Fill a 64-byte cache line
41#else
42   INT8                padding[56];    // A bit more padding
43#endif
44};
45
46struct osd_event {
47   HMTX                hmtx;
48   HEV                 hev;
49   volatile INT32      autoreset;
50   INT8                padding[52];    // Fill a 64-byte cache line
51};
52
53//============================================================
54//  TYPE DEFINITIONS
55//============================================================
56
57struct osd_thread {
58   pthread_t           thread;
59   osd_thread_callback callback;
60   void *param;
61};
62
63struct osd_scalable_lock
64{
65   struct
66   {
67      volatile INT32  haslock;        // do we have the lock?
68      INT32           filler[64/4-1]; // assumes a 64-byte cache line
69   } slot[WORK_MAX_THREADS];           // one slot per thread
70   volatile INT32      nextindex;      // index of next slot to use
71};
72
73
74//============================================================
75//  Scalable Locks
76//============================================================
77
78osd_scalable_lock *osd_scalable_lock_alloc(void)
79{
80   osd_scalable_lock *lock;
81
82   lock = (osd_scalable_lock *)calloc(1, sizeof(*lock));
83
84   memset(lock, 0, sizeof(*lock));
85   lock->slot[0].haslock = TRUE;
86   return lock;
87}
88
89
90INT32 osd_scalable_lock_acquire(osd_scalable_lock *lock)
91{
92   INT32 myslot = (atomic_increment32(&lock->nextindex) - 1) & (WORK_MAX_THREADS - 1);
93
94#if defined(__i386__) || defined(__x86_64__)
95   register INT32 tmp;
96   __asm__ __volatile__ (
97      "1: clr    %[tmp]             ;"
98      "   xchg   %[haslock], %[tmp] ;"
99      "   test   %[tmp], %[tmp]     ;"
100      "   jne    3f                 ;"
101      "2: mov    %[haslock], %[tmp] ;"
102      "   test   %[tmp], %[tmp]     ;"
103      "   jne    1b                 ;"
104      "   pause                     ;"
105      "   jmp    2b                 ;"
106      "3:                            "
107      : [haslock] "+m"  (lock->slot[myslot].haslock)
108      , [tmp]     "=&r" (tmp)
109      :
110      : "%cc"
111   );
112#elif defined(__ppc__) || defined (__PPC__) || defined(__ppc64__) || defined(__PPC64__)
113   register INT32 tmp;
114   __asm__ __volatile__ (
115      "1: lwarx   %[tmp], 0, %[haslock] \n"
116      "   cmpwi   %[tmp], 0             \n"
117      "   bne     3f                    \n"
118      "2: lwzx    %[tmp], 0, %[haslock] \n"
119      "   cmpwi   %[tmp], 0             \n"
120      "   bne     1b                    \n"
121      "   nop                           \n"
122      "   nop                           \n"
123      "   b       2b                    \n"
124      "3: li      %[tmp], 0             \n"
125      "   sync                          \n"
126      "   stwcx.  %[tmp], 0, %[haslock] \n"
127      "   bne-    1b                    \n"
128      "   eieio                         \n"
129      : [tmp]     "=&r" (tmp)
130      : [haslock] "r"   (&lock->slot[myslot].haslock)
131      : "cr0"
132   );
133#else
134   INT32 backoff = 1;
135   while (!osd_compare_exchange32(&lock->slot[myslot].haslock, TRUE, FALSE))
136   {
137      INT32 backcount;
138      for (backcount = 0; backcount < backoff; backcount++)
139         osd_yield_processor();
140      backoff <<= 1;
141   }
142#endif
143   return myslot;
144}
145
146
147void osd_scalable_lock_release(osd_scalable_lock *lock, INT32 myslot)
148{
149#if defined(__i386__) || defined(__x86_64__)
150   register INT32 tmp = TRUE;
151   __asm__ __volatile__ (
152      " xchg   %[haslock], %[tmp] ;"
153      : [haslock] "+m" (lock->slot[(myslot + 1) & (WORK_MAX_THREADS - 1)].haslock)
154      , [tmp]     "+r" (tmp)
155      :
156   );
157#elif defined(__ppc__) || defined (__PPC__) || defined(__ppc64__) || defined(__PPC64__)
158   lock->slot[(myslot + 1) & (WORK_MAX_THREADS - 1)].haslock = TRUE;
159   __asm__ __volatile__ ( " eieio " : : );
160#else
161   osd_exchange32(&lock->slot[(myslot + 1) & (WORK_MAX_THREADS - 1)].haslock, TRUE);
162#endif
163}
164
165void osd_scalable_lock_free(osd_scalable_lock *lock)
166{
167   free(lock);
168}
169
170INLINE pthread_t osd_compare_exchange_pthread_t(pthread_t volatile *ptr, pthread_t compare, pthread_t exchange)
171{
172#ifdef PTR64
173   INT64 result = compare_exchange64((INT64 volatile *)ptr, (INT64)compare, (INT64)exchange);
174#else
175   INT32 result = compare_exchange32((INT32 volatile *)ptr, (INT32)compare, (INT32)exchange);
176#endif
177   return (pthread_t)result;
178}
179
180INLINE pthread_t osd_exchange_pthread_t(pthread_t volatile *ptr, pthread_t exchange)
181{
182#ifdef PTR64
183   INT64 result = osd_exchange64((INT64 volatile *)ptr, (INT64)exchange);
184#else
185   INT32 result = atomic_exchange32((INT32 volatile *)ptr, (INT32)exchange);
186#endif
187   return (pthread_t)result;
188}
189
190
191//============================================================
192//  osd_lock_alloc
193//============================================================
194
195osd_lock *osd_lock_alloc(void)
196{
197   osd_lock *lock;
198
199   lock = (osd_lock *)calloc(1, sizeof(osd_lock));
200
201   lock->holder = 0;
202   lock->count = 0;
203
204   return lock;
205}
206
207//============================================================
208//  osd_lock_acquire
209//============================================================
210
211void osd_lock_acquire(osd_lock *lock)
212{
213   pthread_t current, prev;
214
215   current = pthread_self();
216   prev = osd_compare_exchange_pthread_t(&lock->holder, 0, current);
217   if (prev != (size_t)NULL && prev != current)
218   {
219      do {
220         register INT32 spin = 10000; // Convenient spin count
221         register pthread_t tmp;
222#if defined(__i386__) || defined(__x86_64__)
223         __asm__ __volatile__ (
224            "1: pause                    ;"
225            "   mov    %[holder], %[tmp] ;"
226            "   test   %[tmp], %[tmp]    ;"
227            "   loopne 1b                ;"
228            : [spin]   "+c"  (spin)
229            , [tmp]    "=&r" (tmp)
230            : [holder] "m"   (lock->holder)
231            : "%cc"
232         );
233#elif defined(__ppc__) || defined(__PPC__)
234         __asm__ __volatile__ (
235            "1: nop                        \n"
236            "   nop                        \n"
237            "   lwzx  %[tmp], 0, %[holder] \n"
238            "   cmpwi %[tmp], 0            \n"
239            "   bdnzt eq, 1b               \n"
240            : [spin]   "+c"  (spin)
241            , [tmp]    "=&r" (tmp)
242            : [holder] "r"   (&lock->holder)
243            : "cr0"
244         );
245#elif defined(__ppc64__) || defined(__PPC64__)
246         __asm__ __volatile__ (
247            "1: nop                        \n"
248            "   nop                        \n"
249            "   ldx   %[tmp], 0, %[holder] \n"
250            "   cmpdi %[tmp], 0            \n"
251            "   bdnzt eq, 1b               \n"
252            : [spin]   "+c"  (spin)
253            , [tmp]    "=&r" (tmp)
254            : [holder] "r"   (&lock->holder)
255            : "cr0"
256         );
257#else
258         while (--spin > 0 && lock->holder != NULL)
259            osd_yield_processor();
260#endif
261#if 0
262         /* If you mean to use locks as a blocking mechanism for extended
263          * periods of time, you should do something like this.  However,
264          * it kills the performance of gaelco3d.
265          */
266         if (spin == 0)
267         {
268            struct timespec sleep = { 0, 100000 }, remaining;
269            nanosleep(&sleep, &remaining); // sleep for 100us
270         }
271#endif
272      } while (osd_compare_exchange_pthread_t(&lock->holder, 0, current) != (size_t)NULL);
273   }
274   lock->count++;
275}
276
277//============================================================
278//  osd_lock_try
279//============================================================
280
281int osd_lock_try(osd_lock *lock)
282{
283   pthread_t current, prev;
284
285   current = pthread_self();
286   prev = osd_compare_exchange_pthread_t(&lock->holder, 0, current);
287   if (prev == (size_t)NULL || prev == current)
288   {
289      lock->count++;
290      return 1;
291   }
292   return 0;
293}
294
295//============================================================
296//  osd_lock_release
297//============================================================
298
299void osd_lock_release(osd_lock *lock)
300{
301   pthread_t current;
302
303   current = pthread_self();
304   if (lock->holder == current)
305   {
306      if (--lock->count == 0)
307#if defined(__ppc__) || defined(__PPC__) || defined(__ppc64__) || defined(__PPC64__)
308      lock->holder = 0;
309      __asm__ __volatile__( " eieio " : : );
310#else
311      osd_exchange_pthread_t(&lock->holder, 0);
312#endif
313      return;
314   }
315
316   // trying to release a lock you don't hold is bad!
317//  assert(lock->holder == pthread_self());
318}
319
320//============================================================
321//  osd_lock_free
322//============================================================
323
324void osd_lock_free(osd_lock *lock)
325{
326   free(lock);
327}
328
329//============================================================
330//  osd_event_alloc
331//============================================================
332
333osd_event *osd_event_alloc(int manualreset, int initialstate)
334{
335   osd_event *ev;
336
337   ev = (osd_event *)calloc(1, sizeof(osd_event));
338
339   DosCreateMutexSem(NULL, &ev->hmtx, 0, FALSE);
340   DosCreateEventSem(NULL, &ev->hev, 0, initialstate);
341   ev->autoreset = !manualreset;
342
343   return ev;
344}
345
346//============================================================
347//  osd_event_free
348//============================================================
349
350void osd_event_free(osd_event *event)
351{
352   DosCloseMutexSem(event->hmtx);
353   DosCloseEventSem(event->hev);
354   free(event);
355}
356
357//============================================================
358//  osd_event_set
359//============================================================
360
361void osd_event_set(osd_event *event)
362{
363   DosPostEventSem(event->hev);
364}
365
366//============================================================
367//  osd_event_reset
368//============================================================
369
370void osd_event_reset(osd_event *event)
371{
372   ULONG ulCount;
373
374   DosResetEventSem(event->hev, &ulCount);
375}
376
377//============================================================
378//  osd_event_wait
379//============================================================
380
381int osd_event_wait(osd_event *event, osd_ticks_t timeout)
382{
383   ULONG rc;
384
385   if(event->autoreset)
386      DosRequestMutexSem(event->hmtx, -1);
387
388   rc = DosWaitEventSem(event->hev, timeout * 1000 / osd_ticks_per_second());
389
390   if(event->autoreset)
391   {
392      ULONG ulCount;
393
394      if(rc == 0)
395         DosResetEventSem(event->hev, &ulCount);
396
397      DosReleaseMutexSem(event->hmtx);
398   }
399
400   return (rc == 0);
401}
402
403//============================================================
404//  osd_thread_create
405//============================================================
406
407static void worker_thread_entry(void *param)
408{
409      osd_thread *thread = (osd_thread *) param;
410
411      thread->callback(thread->param);
412}
413
414osd_thread *osd_thread_create(osd_thread_callback callback, void *cbparam)
415{
416   osd_thread *thread;
417
418   thread = (osd_thread *)calloc(1, sizeof(osd_thread));
419   thread->callback = callback;
420   thread->param = cbparam;
421   thread->thread = _beginthread(worker_thread_entry, NULL, 65535, thread);
422   if ( thread->thread == -1 )
423   {
424      free(thread);
425      return NULL;
426   }
427   return thread;
428}
429
430//============================================================
431//  osd_thread_adjust_priority
432//============================================================
433
434int osd_thread_adjust_priority(osd_thread *thread, int adjust)
435{
436   PTIB ptib;
437
438   DosGetInfoBlocks(&ptib, NULL);
439
440   if ( DosSetPriority(PRTYS_THREAD, PRTYC_NOCHANGE,
441                  ((BYTE)ptib->tib_ptib2->tib2_ulpri) + adjust, thread->thread ))
442      return FALSE;
443
444
445   return TRUE;
446}
447
448//============================================================
449//  osd_thread_cpu_affinity
450//============================================================
451
452int osd_thread_cpu_affinity(osd_thread *thread, UINT32 mask)
453{
454   return TRUE;
455}
456
457//============================================================
458//  osd_thread_wait_free
459//============================================================
460
461void osd_thread_wait_free(osd_thread *thread)
462{
463   TID tid = thread->thread;
464
465   DosWaitThread(&tid, 0);
466   free(thread);
467}
468
469//============================================================
470//  osd_process_kill
471//============================================================
472
473void osd_process_kill(void)
474{
475   PPIB ppib;
476
477   DosGetInfoBlocks(NULL, &ppib);
478   DosKillProcess(DKP_PROCESSTREE, ppib->pib_ulpid);
479}
trunk/src/osd/sdl/sdlsync_sdl.c
r242708r242709
1//============================================================
2//
3//  sdlsync.c - SDL core synchronization functions
4//
5//  Copyright (c) 1996-2010, Nicola Salmoria and the MAME Team.
6//  Visit http://mamedev.org for licensing and usage restrictions.
7//
8//  SDLMAME by Olivier Galibert and R. Belmont
9//
10//============================================================
11
12#include "sdlinc.h"
13
14// standard C headers
15#include <unistd.h>
16
17// MAME headers
18#include "osdcore.h"
19#include "osinline.h"
20#include "sdlsync.h"
21
22#include "eminline.h"
23
24#define VERBOSE     (0)
25
26#if VERBOSE
27#define LOG( x ) do { printf x; printf("\n"); } while (0)
28#else
29#define LOG( x )
30#endif
31struct hidden_mutex_t {
32   SDL_mutex *         id;
33   volatile INT32      locked;
34   volatile INT32      threadid;
35};
36
37struct osd_event {
38   SDL_mutex *         mutex;
39   SDL_cond *          cond;
40   volatile INT32      autoreset;
41   volatile INT32      signalled;
42};
43
44//============================================================
45//  TYPE DEFINITIONS
46//============================================================
47
48struct osd_thread {
49   SDL_Thread *        thread;
50   osd_thread_callback callback;
51   void *param;
52};
53
54struct osd_scalable_lock
55{
56   SDL_mutex *         mutex;
57};
58
59//============================================================
60//  Scalable Locks
61//============================================================
62
63osd_scalable_lock *osd_scalable_lock_alloc(void)
64{
65   osd_scalable_lock *lock;
66
67   lock = (osd_scalable_lock *)calloc(1, sizeof(*lock));
68
69   lock->mutex = SDL_CreateMutex();
70   return lock;
71}
72
73
74INT32 osd_scalable_lock_acquire(osd_scalable_lock *lock)
75{
76   SDL_mutexP(lock->mutex);
77   return 0;
78}
79
80
81void osd_scalable_lock_release(osd_scalable_lock *lock, INT32 myslot)
82{
83   SDL_mutexV(lock->mutex);
84}
85
86void osd_scalable_lock_free(osd_scalable_lock *lock)
87{
88   SDL_DestroyMutex(lock->mutex);
89   free(lock);
90}
91
92//============================================================
93//  osd_lock_alloc
94//============================================================
95
96osd_lock *osd_lock_alloc(void)
97{
98   hidden_mutex_t *mutex;
99
100   mutex = (hidden_mutex_t *)calloc(1, sizeof(hidden_mutex_t));
101
102   mutex->id = SDL_CreateMutex();
103
104   return (osd_lock *)mutex;
105}
106
107//============================================================
108//  osd_lock_acquire
109//============================================================
110
111void osd_lock_acquire(osd_lock *lock)
112{
113   hidden_mutex_t *mutex = (hidden_mutex_t *) lock;
114
115   LOG(("osd_lock_acquire"));
116   /* get the lock */
117   mutex->locked++; /* signal that we are *about* to lock - prevent osd_lock_try */
118   SDL_mutexP(mutex->id);
119   mutex->threadid = SDL_ThreadID();
120}
121
122//============================================================
123//  osd_lock_try
124//============================================================
125
126int osd_lock_try(osd_lock *lock)
127{
128   hidden_mutex_t *mutex = (hidden_mutex_t *) lock;
129
130   LOG(("osd_lock_try"));
131   if (mutex->locked && mutex->threadid == SDL_ThreadID())
132   {
133      /* get the lock */
134      SDL_mutexP(mutex->id);
135      mutex->locked++;
136      mutex->threadid = SDL_ThreadID();
137      return 1;
138   }
139   else if ((mutex->locked == 0))
140   {
141      /* get the lock */
142      mutex->locked++;
143      SDL_mutexP(mutex->id);
144      mutex->threadid = SDL_ThreadID();
145      return 1;
146   }
147   else
148   {
149      /* fail */
150      return 0;
151   }
152}
153
154//============================================================
155//  osd_lock_release
156//============================================================
157
158void osd_lock_release(osd_lock *lock)
159{
160   hidden_mutex_t *mutex = (hidden_mutex_t *) lock;
161
162   LOG(("osd_lock_release"));
163   mutex->locked--;
164   if (mutex->locked == 0)
165      mutex->threadid = -1;
166   SDL_mutexV(mutex->id);
167}
168
169//============================================================
170//  osd_lock_free
171//============================================================
172
173void osd_lock_free(osd_lock *lock)
174{
175   hidden_mutex_t *mutex = (hidden_mutex_t *) lock;
176
177   LOG(("osd_lock_free"));
178   //osd_lock_release(lock);
179   SDL_DestroyMutex(mutex->id);
180   free(mutex);
181}
182
183//============================================================
184//  osd_event_alloc
185//============================================================
186
187osd_event *osd_event_alloc(int manualreset, int initialstate)
188{
189   osd_event *ev;
190
191   ev = (osd_event *)calloc(1, sizeof(osd_event));
192
193   ev->mutex = SDL_CreateMutex();
194   ev->cond = SDL_CreateCond();
195   ev->signalled = initialstate;
196   ev->autoreset = !manualreset;
197
198   return ev;
199}
200
201//============================================================
202//  osd_event_free
203//============================================================
204
205void osd_event_free(osd_event *event)
206{
207   SDL_DestroyMutex(event->mutex);
208   SDL_DestroyCond(event->cond);
209   free(event);
210}
211
212//============================================================
213//  osd_event_set
214//============================================================
215
216void osd_event_set(osd_event *event)
217{
218   LOG(("osd_event_set"));
219   SDL_mutexP(event->mutex);
220   if (event->signalled == FALSE)
221   {
222      event->signalled = TRUE;
223      if (event->autoreset)
224         SDL_CondSignal(event->cond);
225      else
226         SDL_CondBroadcast(event->cond);
227   }
228   SDL_mutexV(event->mutex);
229}
230
231//============================================================
232//  osd_event_reset
233//============================================================
234
235void osd_event_reset(osd_event *event)
236{
237   LOG(("osd_event_reset"));
238   SDL_mutexP(event->mutex);
239   event->signalled = FALSE;
240   SDL_mutexV(event->mutex);
241}
242
243//============================================================
244//  osd_event_wait
245//============================================================
246
247int osd_event_wait(osd_event *event, osd_ticks_t timeout)
248{
249   LOG(("osd_event_wait"));
250   SDL_mutexP(event->mutex);
251   if (!timeout)
252   {
253      if (!event->signalled)
254      {
255         SDL_mutexV(event->mutex);
256            return FALSE;
257      }
258   }
259   else
260   {
261      if (!event->signalled)
262      {
263         UINT64 msec = (timeout * 1000) / osd_ticks_per_second();
264
265         do {
266            int ret = SDL_CondWaitTimeout(event->cond, event->mutex, msec);
267            if ( ret == SDL_MUTEX_TIMEDOUT )
268            {
269               if (!event->signalled)
270               {
271                  SDL_mutexV(event->mutex);
272                  return FALSE;
273               }
274               else
275                  break;
276            }
277            if (ret == 0)
278               break;
279            printf("Error %d while waiting for pthread_cond_timedwait:  %s\n", ret, strerror(ret));
280         } while (TRUE);
281      }
282   }
283
284   if (event->autoreset)
285      event->signalled = 0;
286
287   SDL_mutexV(event->mutex);
288
289   return TRUE;
290}
291
292//============================================================
293//  osd_thread_create
294//============================================================
295
296static int worker_thread_entry(void *param)
297{
298   osd_thread *thread = (osd_thread *) param;
299   void *res;
300
301   res = thread->callback(thread->param);
302#ifdef PTR64
303   return (int) (INT64) res;
304#else
305   return (int) res;
306#endif
307}
308
309osd_thread *osd_thread_create(osd_thread_callback callback, void *cbparam)
310{
311   osd_thread *thread;
312
313   thread = (osd_thread *)calloc(1, sizeof(osd_thread));
314   thread->callback = callback;
315   thread->param = cbparam;
316   thread->thread = SDL_CreateThread(worker_thread_entry, thread);
317   if ( thread->thread == NULL )
318   {
319      free(thread);
320      return NULL;
321   }
322   return thread;
323}
324
325//============================================================
326//  osd_thread_adjust_priority
327//============================================================
328
329int osd_thread_adjust_priority(osd_thread *thread, int adjust)
330{
331   return TRUE;
332}
333
334//============================================================
335//  osd_thread_cpu_affinity
336//============================================================
337
338int osd_thread_cpu_affinity(osd_thread *thread, UINT32 mask)
339{
340   return TRUE;
341}
342
343//============================================================
344//  osd_thread_wait_free
345//============================================================
346
347void osd_thread_wait_free(osd_thread *thread)
348{
349   int status;
350   SDL_WaitThread(thread->thread, &status);
351   free(thread);
352}
trunk/src/osd/sdl/sdlsync_tc.c
r242708r242709
1//============================================================
2//
3//  sdlsync.c - SDL core synchronization functions
4//
5//  Copyright (c) 1996-2010, Nicola Salmoria and the MAME Team.
6//  Visit http://mamedev.org for licensing and usage restrictions.
7//
8//  SDLMAME by Olivier Galibert and R. Belmont
9//
10//============================================================
11
12#ifndef _GNU_SOURCE
13#define _GNU_SOURCE     // for PTHREAD_MUTEX_RECURSIVE; needs to be here before other glibc headers are included
14#endif
15
16#include "sdlinc.h"
17
18#ifdef SDLMAME_MACOSX
19#include <mach/mach.h>
20#endif
21
22// standard C headers
23#include <math.h>
24#include <stdlib.h>
25#include <unistd.h>
26
27// MAME headers
28#include "osdcomm.h"
29#include "osdcore.h"
30
31#include "sdlsync.h"
32
33#include <pthread.h>
34#include <errno.h>
35#include <signal.h>
36#include <sys/time.h>
37
38struct hidden_mutex_t {
39   pthread_mutex_t id;
40};
41
42struct osd_event {
43   pthread_mutex_t     mutex;
44   pthread_cond_t      cond;
45   volatile INT32      autoreset;
46   volatile INT32      signalled;
47#ifdef PTR64
48   INT8                padding[40];    // Fill a 64-byte cache line
49#else
50   INT8                padding[48];    // A bit more padding
51#endif
52};
53
54//============================================================
55//  TYPE DEFINITIONS
56//============================================================
57
58struct osd_thread {
59   pthread_t           thread;
60};
61
62struct osd_scalable_lock
63{
64   osd_lock            *lock;
65};
66
67//============================================================
68//  Scalable Locks
69//============================================================
70
71osd_scalable_lock *osd_scalable_lock_alloc(void)
72{
73   osd_scalable_lock *lock;
74
75   lock = (osd_scalable_lock *)calloc(1, sizeof(*lock));
76
77   lock->lock = osd_lock_alloc();
78   return lock;
79}
80
81
82INT32 osd_scalable_lock_acquire(osd_scalable_lock *lock)
83{
84   osd_lock_acquire(lock->lock);
85   return 0;
86}
87
88
89void osd_scalable_lock_release(osd_scalable_lock *lock, INT32 myslot)
90{
91   osd_lock_release(lock->lock);
92}
93
94void osd_scalable_lock_free(osd_scalable_lock *lock)
95{
96   osd_lock_free(lock->lock);
97   free(lock);
98}
99
100
101//============================================================
102//  osd_lock_alloc
103//============================================================
104
105osd_lock *osd_lock_alloc(void)
106{
107   hidden_mutex_t *mutex;
108   pthread_mutexattr_t mtxattr;
109
110   mutex = (hidden_mutex_t *)calloc(1, sizeof(hidden_mutex_t));
111
112   pthread_mutexattr_init(&mtxattr);
113   pthread_mutexattr_settype(&mtxattr, PTHREAD_MUTEX_RECURSIVE);
114   pthread_mutex_init(&mutex->id, &mtxattr);
115
116   return (osd_lock *)mutex;
117}
118
119//============================================================
120//  osd_lock_acquire
121//============================================================
122
123void osd_lock_acquire(osd_lock *lock)
124{
125   hidden_mutex_t *mutex = (hidden_mutex_t *) lock;
126   int r;
127
128   r = pthread_mutex_lock(&mutex->id);
129   if (r==0)
130      return;
131   //osd_printf_error("Error on lock: %d: %s\n", r, strerror(r));
132}
133
134//============================================================
135//  osd_lock_try
136//============================================================
137
138int osd_lock_try(osd_lock *lock)
139{
140   hidden_mutex_t *mutex = (hidden_mutex_t *) lock;
141   int r;
142
143   r = pthread_mutex_trylock(&mutex->id);
144   if (r==0)
145      return 1;
146   //if (r!=EBUSY)
147   //  osd_printf_error("Error on trylock: %d: %s\n", r, strerror(r));
148   return 0;
149}
150
151//============================================================
152//  osd_lock_release
153//============================================================
154
155void osd_lock_release(osd_lock *lock)
156{
157   hidden_mutex_t *mutex = (hidden_mutex_t *) lock;
158
159   pthread_mutex_unlock(&mutex->id);
160}
161
162//============================================================
163//  osd_lock_free
164//============================================================
165
166void osd_lock_free(osd_lock *lock)
167{
168   hidden_mutex_t *mutex = (hidden_mutex_t *) lock;
169
170   //pthread_mutex_unlock(&mutex->id);
171   pthread_mutex_destroy(&mutex->id);
172   free(mutex);
173}
174
175//============================================================
176//  osd_event_alloc
177//============================================================
178
179osd_event *osd_event_alloc(int manualreset, int initialstate)
180{
181   osd_event *ev;
182   pthread_mutexattr_t mtxattr;
183
184   ev = (osd_event *)calloc(1, sizeof(osd_event));
185
186   pthread_mutexattr_init(&mtxattr);
187   pthread_mutex_init(&ev->mutex, &mtxattr);
188   pthread_cond_init(&ev->cond, NULL);
189   ev->signalled = initialstate;
190   ev->autoreset = !manualreset;
191
192   return ev;
193}
194
195//============================================================
196//  osd_event_free
197//============================================================
198
199void osd_event_free(osd_event *event)
200{
201   pthread_mutex_destroy(&event->mutex);
202   pthread_cond_destroy(&event->cond);
203   free(event);
204}
205
206//============================================================
207//  osd_event_set
208//============================================================
209
210void osd_event_set(osd_event *event)
211{
212   pthread_mutex_lock(&event->mutex);
213   if (event->signalled == FALSE)
214   {
215      event->signalled = TRUE;
216      if (event->autoreset)
217         pthread_cond_signal(&event->cond);
218      else
219         pthread_cond_broadcast(&event->cond);
220   }
221   pthread_mutex_unlock(&event->mutex);
222}
223
224//============================================================
225//  osd_event_reset
226//============================================================
227
228void osd_event_reset(osd_event *event)
229{
230   pthread_mutex_lock(&event->mutex);
231   event->signalled = FALSE;
232   pthread_mutex_unlock(&event->mutex);
233}
234
235//============================================================
236//  osd_event_wait
237//============================================================
238
239int osd_event_wait(osd_event *event, osd_ticks_t timeout)
240{
241   pthread_mutex_lock(&event->mutex);
242   if (!timeout)
243   {
244      if (!event->signalled)
245      {
246            pthread_mutex_unlock(&event->mutex);
247            return FALSE;
248      }
249   }
250   else
251   {
252      if (!event->signalled)
253      {
254         struct timespec   ts;
255         struct timeval    tp;
256         UINT64 msec = timeout * 1000 / osd_ticks_per_second();
257         UINT64 nsec;
258
259         gettimeofday(&tp, NULL);
260
261         ts.tv_sec  = tp.tv_sec;
262         nsec = (UINT64) tp.tv_usec * (UINT64) 1000 + (msec * (UINT64) 1000000);
263         ts.tv_nsec = nsec % (UINT64) 1000000000;
264         ts.tv_sec += nsec / (UINT64) 1000000000;
265
266         do {
267            int ret = pthread_cond_timedwait(&event->cond, &event->mutex, &ts);
268            if ( ret == ETIMEDOUT )
269            {
270               if (!event->signalled)
271               {
272                  pthread_mutex_unlock(&event->mutex);
273                  return FALSE;
274               }
275               else
276                  break;
277            }
278            if (ret == 0)
279               break;
280            if ( ret != EINTR)
281            {
282               printf("Error %d while waiting for pthread_cond_timedwait:  %s\n", ret, strerror(ret));
283            }
284
285         } while (TRUE);
286      }
287   }
288
289   if (event->autoreset)
290      event->signalled = 0;
291
292   pthread_mutex_unlock(&event->mutex);
293
294   return TRUE;
295}
296
297//============================================================
298//  osd_thread_create
299//============================================================
300
301osd_thread *osd_thread_create(osd_thread_callback callback, void *cbparam)
302{
303   osd_thread *thread;
304   pthread_attr_t  attr;
305
306   thread = (osd_thread *)calloc(1, sizeof(osd_thread));
307   pthread_attr_init(&attr);
308   pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
309   if ( pthread_create(&thread->thread, &attr, callback, cbparam) != 0 )
310   {
311      free(thread);
312      return NULL;
313   }
314   return thread;
315}
316
317//============================================================
318//  osd_thread_adjust_priority
319//============================================================
320
321int osd_thread_adjust_priority(osd_thread *thread, int adjust)
322{
323   struct sched_param  sched;
324   int                 policy;
325
326   if ( pthread_getschedparam( thread->thread, &policy, &sched ) == 0 )
327   {
328      sched.sched_priority += adjust;
329      if ( pthread_setschedparam(thread->thread, policy, &sched ) == 0)
330         return TRUE;
331      else
332         return FALSE;
333   }
334   else
335      return FALSE;
336}
337
338//============================================================
339//  osd_thread_cpu_affinity
340//============================================================
341
342int osd_thread_cpu_affinity(osd_thread *thread, UINT32 mask)
343{
344#if !defined(NO_AFFINITY_NP)
345   cpu_set_t   cmask;
346   pthread_t   lthread;
347   int         bitnum;
348
349   CPU_ZERO(&cmask);
350   for (bitnum=0; bitnum<32; bitnum++)
351      if (mask & (1<<bitnum))
352         CPU_SET(bitnum, &cmask);
353
354   if (thread == NULL)
355      lthread = pthread_self();
356   else
357      lthread = thread->thread;
358
359   if (pthread_setaffinity_np(lthread, sizeof(cmask), &cmask) <0)
360   {
361      /* Not available during link in all targets */
362      fprintf(stderr, "error %d setting cpu affinity to mask %08x", errno, mask);
363      return FALSE;
364   }
365   else
366      return TRUE;
367#else
368   return TRUE;
369#endif
370}
371
372//============================================================
373//  osd_thread_wait_free
374//============================================================
375
376void osd_thread_wait_free(osd_thread *thread)
377{
378   pthread_join(thread->thread, NULL);
379   free(thread);
380}
381
382//============================================================
383//  osd_process_kill
384//============================================================
385
386void osd_process_kill(void)
387{
388   kill(getpid(), SIGKILL);
389}
trunk/src/osd/sdl/sdlsync_win32.c
r242708r242709
1//============================================================
2//
3//  sdlsync.c - SDL core synchronization functions
4//
5//  Copyright (c) 1996-2010, Nicola Salmoria and the MAME Team.
6//  Visit http://mamedev.org for licensing and usage restrictions.
7//
8//  SDLMAME by Olivier Galibert and R. Belmont
9//
10//============================================================
11
12#include "../windows/winsync.c"
trunk/src/osd/sdl/sdlwork.c
r242708r242709
1111
1212#if defined(SDLMAME_NOASM)
1313
14/* must be exported
15 * FIXME: NOASM should be taken care of in sdlsync.c
16 *        This is not really a sound solution.
17 */
18
19int osd_num_processors = 0;
20
2114#include "../osdmini/miniwork.c"
2215
2316#else
r242708r242709
2518#include "osdcore.h"
2619#include "osinline.h"
2720
28#include "sdlsync.h"
21#include "modules/sync/osdsync.h"
2922#include "sdlos.h"
3023
3124#include "eminline.h"
r242708r242709
6558#define end_timing(v)           do { } while (0)
6659#endif
6760
68
69
7061//============================================================
7162//  TYPE DEFINITIONS
7263//============================================================
trunk/src/osd/sdl/watchdog.h
r242708r242709
1111//
1212//============================================================
1313
14#include "sdlsync.h"
14#include "modules/sync/osdsync.h"
1515
1616class watchdog
1717{
trunk/src/osd/sdl/window.h
r242708r242709
1515#include "sdlinc.h"
1616#include "video.h"
1717#include "render.h"
18#include "sdlsync.h"
18#include "modules/sync/osdsync.h"
1919
2020#include "osd_opengl.h"
2121#include "osdsdl.h"
trunk/src/osd/windows/osinline.h
r242708r242709
1919#include "eivc.h"
2020#endif
2121
22#if __GNUC__ && defined(__i386__) && !defined(__x86_64)
23#undef YieldProcessor
24#endif
25
26#ifndef YieldProcessor
27#ifdef __GNUC__
28INLINE void osd_yield_processor(void)
29{
30    __asm__ __volatile__ ( "rep; nop" );
31}
32#else
33INLINE void osd_yield_processor(void)
34{
35    __asm { rep nop }
36}
37#endif
38#else
39#define osd_yield_processor YieldProcessor
40#endif
41
2242INT32 win_compare_exchange32(INT32 volatile *ptr, INT32 compare, INT32 exchange);
2343INT32 win_atomic_exchange32(INT32 volatile *ptr, INT32 exchange);
2444INT32 win_atomic_add32(INT32 volatile *ptr, INT32 delta);
trunk/src/osd/windows/windows.mak
r242708r242709
8484OSDSRC = $(SRC)/osd
8585OSDOBJ = $(OBJ)/osd
8686
87OBJDIRS += $(WINOBJ)
87OBJDIRS += $(WINOBJ) $(OSDOBJ)/modules/sync
8888
8989ifdef USE_QTDEBUG
9090OBJDIRS += $(OSDOBJ)/modules/debugger/qt
r242708r242709
302302include $(SRC)/build/cc_detection.mak
303303
304304# ensure we statically link the gcc runtime lib
305LDFLAGS += -static-libgcc
305LDFLAGS += -static-libgcc -static
306306
307ifeq ($(CROSS_BUILD),1)
308   LDFLAGS += -static
309endif   
310
311307# TODO: needs to use $(CC)
312308TEST_GCC := $(shell gcc --version)
313309ifeq ($(findstring 4.4.,$(TEST_GCC)),)
r242708r242709
343339   $(WINOBJ)/windir.o \
344340   $(WINOBJ)/winfile.o \
345341   $(WINOBJ)/winmisc.o \
346   $(WINOBJ)/winsync.o \
342   $(OSDOBJ)/modules/sync/sync_windows.o \
347343   $(WINOBJ)/wintime.o \
348344   $(WINOBJ)/winutf8.o \
349345   $(WINOBJ)/winutil.o \
trunk/src/osd/windows/winmain.c
r242708r242709
219219// this line prevents globbing on the command line
220220int _CRT_glob = 0;
221221
222
223
224222//**************************************************************************
225223//  LOCAL VARIABLES
226224//**************************************************************************
trunk/src/osd/windows/winsync.c
r242708r242709
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles
3//============================================================
4//
5//  winsync.c - Win32 OSD core synchronization functions
6//
7//============================================================
8
9// standard windows headers
10#define WIN32_LEAN_AND_MEAN
11#include <windows.h>
12#include <stdlib.h>
13#include <process.h>
14
15// MAME headers
16#include "osdcore.h"
17#include "osinline.h"
18#include "winsync.h"
19
20
21//============================================================
22//  DEBUGGING
23//============================================================
24
25#define DEBUG_SLOW_LOCKS    0
26#define USE_SCALABLE_LOCKS      (0)
27
28
29
30//============================================================
31//  TYPE DEFINITIONS
32//============================================================
33
34typedef BOOL (WINAPI *try_enter_critical_section_ptr)(LPCRITICAL_SECTION lpCriticalSection);
35
36struct osd_lock
37{
38   CRITICAL_SECTION    critsect;
39};
40
41struct osd_event
42{
43   void *  ptr;
44};
45
46struct osd_thread {
47   HANDLE handle;
48   osd_thread_callback callback;
49   void *param;
50};
51
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
67//============================================================
68//  GLOBAL VARIABLES
69//============================================================
70
71static try_enter_critical_section_ptr try_enter_critical_section = NULL;
72static int checked_for_try_enter = FALSE;
73
74
75
76//============================================================
77//  osd_lock_alloc
78//============================================================
79
80osd_lock *osd_lock_alloc(void)
81{
82   osd_lock *lock = (osd_lock *)malloc(sizeof(*lock));
83   if (lock == NULL)
84      return NULL;
85   InitializeCriticalSection(&lock->critsect);
86   return lock;
87}
88
89
90//============================================================
91//  osd_lock_acquire
92//============================================================
93
94void osd_lock_acquire(osd_lock *lock)
95{
96#if DEBUG_SLOW_LOCKS
97   osd_ticks_t ticks = osd_ticks();
98#endif
99
100   // block until we can acquire the lock
101   EnterCriticalSection(&lock->critsect);
102
103#if DEBUG_SLOW_LOCKS
104   // log any locks that take more than 1ms
105   ticks = osd_ticks() - ticks;
106   if (ticks > osd_ticks_per_second() / 1000) osd_printf_debug("Blocked %d ticks on lock acquire\n", (int)ticks);
107#endif
108}
109
110
111//============================================================
112//  osd_lock_try
113//============================================================
114
115int osd_lock_try(osd_lock *lock)
116{
117   int result = TRUE;
118
119   // if we haven't yet checked for the TryEnter API, do it now
120   if (!checked_for_try_enter)
121   {
122      // see if we can use TryEnterCriticalSection
123      HMODULE library = LoadLibrary(TEXT("kernel32.dll"));
124      if (library != NULL)
125         try_enter_critical_section = (try_enter_critical_section_ptr)GetProcAddress(library, "TryEnterCriticalSection");
126      checked_for_try_enter = TRUE;
127   }
128
129   // if we have it, use it, otherwise just block
130   if (try_enter_critical_section != NULL)
131      result = (*try_enter_critical_section)(&lock->critsect);
132   else
133      EnterCriticalSection(&lock->critsect);
134   return result;
135}
136
137
138//============================================================
139//  osd_lock_release
140//============================================================
141
142void osd_lock_release(osd_lock *lock)
143{
144   LeaveCriticalSection(&lock->critsect);
145}
146
147
148//============================================================
149//  osd_lock_free
150//============================================================
151
152void osd_lock_free(osd_lock *lock)
153{
154   DeleteCriticalSection(&lock->critsect);
155   free(lock);
156}
157
158
159//============================================================
160//  win_compare_exchange32
161//============================================================
162
163INT32 win_compare_exchange32(INT32 volatile *ptr, INT32 compare, INT32 exchange)
164{
165   return InterlockedCompareExchange((LPLONG)ptr, (LONG)exchange, (LONG)compare);
166}
167
168
169//============================================================
170//  win_compare_exchange64
171//============================================================
172
173#ifdef PTR64
174INT64 win_compare_exchange64(INT64 volatile *ptr, INT64 compare, INT64 exchange)
175{
176   return InterlockedCompareExchange64((LONGLONG*)ptr, (LONGLONG)exchange, (LONGLONG)compare);
177}
178#endif
179
180
181//============================================================
182//  win_atomic_exchange32
183//============================================================
184
185INT32 win_atomic_exchange32(INT32 volatile *ptr, INT32 exchange)
186{
187   return InterlockedExchange((LONG *) ptr, exchange);
188}
189
190
191//============================================================
192//  win_atomic_add32
193//============================================================
194
195INT32 win_atomic_add32(INT32 volatile *ptr, INT32 delta)
196{
197   return InterlockedExchangeAdd((LONG *) ptr, delta) + delta;
198}
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}
trunk/src/osd/windows/winsync.h
r242708r242709
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__ */
trunk/src/osd/windows/winwork.c
r242708r242709
2020// MAME headers
2121#include "osdcore.h"
2222
23#include "winsync.h"
23#include "modules/sync/osdsync.h"
2424#include "winos.h"
2525
2626#include "eminline.h"
2727
28#include "osinline.h"
2829
30
2931//============================================================
3032//  DEBUGGING
3133//============================================================
r242708r242709
5759#define end_timing(v)           do { } while (0)
5860#endif
5961
60#if __GNUC__ && defined(__i386__) && !defined(__x86_64)
61#undef YieldProcessor
62#endif
63
64#ifndef YieldProcessor
65#ifdef __GNUC__
66INLINE void osd_yield_processor(void)
67{
68   __asm__ __volatile__ ( "rep; nop" );
69}
70#else
71INLINE void osd_yield_processor(void)
72{
73   __asm { rep nop }
74}
75#endif
76#else
77#define osd_yield_processor YieldProcessor
78#endif
79
80
81
8262//============================================================
8363//  TYPE DEFINITIONS
8464//============================================================


Previous 199869 Revisions Next


© 1997-2024 The MAME Team