Previous 15994 Revisions Next

r2147 Saturday 29th March, 2008 at 20:38:47 UTC by R. Belmont
[SDLMESS] Cleanups and new locking code from Couriersud. SDLMAME/SDLMESS should scale cleanly to at least 8 CPUs/cores now.
[src/osd/sdl]sdlsync.c sdlsync.h sdlwork.c window.c

src/osd/sdl/sdlsync.c
r2146r2147
4141#define pthread_self    _gettid
4242#endif
4343
44#if THREAD_COOPERATIVE
45typedef struct _hidden_mutex_t hidden_mutex_t;
46struct _hidden_mutex_t {
47   pthread_mutex_t id;
48};
49#else
4450struct _osd_lock {
4551    volatile pthread_t   holder;
4652   INT32            count;
r2146r2147
5056   INT8            padding[56];   // A bit more padding
5157#endif
5258};
59#endif
5360 
5461#ifndef SDLMAME_OS2
5562struct _osd_event {
r2146r2147
6976   pthread_t         thread;
7077};
7178
79
80#if THREAD_COOPERATIVE
81
82//============================================================
83//  osd_lock_alloc
84//============================================================
85
86osd_lock *osd_lock_alloc(void)
87{
88   hidden_mutex_t *mutex;
89   pthread_mutexattr_t mtxattr;
90
91   mutex = (hidden_mutex_t *)calloc(1, sizeof(hidden_mutex_t));
92
93   pthread_mutexattr_init(&mtxattr);
94   pthread_mutexattr_settype(&mtxattr, PTHREAD_MUTEX_RECURSIVE);
95   pthread_mutex_init(&mutex->id, &mtxattr);
96
97   return (osd_lock *)mutex;
98}
99
100//============================================================
101//  osd_lock_acquire
102//============================================================
103
104void osd_lock_acquire(osd_lock *lock)
105{
106   hidden_mutex_t *mutex = (hidden_mutex_t *) lock;
107   int r;
108   
109   r =   pthread_mutex_lock(&mutex->id);
110   if (r==0)
111      return;
112   //mame_printf_error("Error on lock: %d: %s\n", r, strerror(r));
113}
114
115//============================================================
116//  osd_lock_try
117//============================================================
118
119int osd_lock_try(osd_lock *lock)
120{
121   hidden_mutex_t *mutex = (hidden_mutex_t *) lock;
122   int r;
123   
124   r = pthread_mutex_trylock(&mutex->id);
125   if (r==0)
126      return 1;
127   //if (r!=EBUSY)
128    //   mame_printf_error("Error on trylock: %d: %s\n", r, strerror(r));
129   return 0;
130}
131
132//============================================================
133//  osd_lock_release
134//============================================================
135
136void osd_lock_release(osd_lock *lock)
137{
138   hidden_mutex_t *mutex = (hidden_mutex_t *) lock;
139
140   pthread_mutex_unlock(&mutex->id);
141}
142
143//============================================================
144//  osd_lock_free
145//============================================================
146
147void osd_lock_free(osd_lock *lock)
148{
149   hidden_mutex_t *mutex = (hidden_mutex_t *) lock;
150
151   pthread_mutex_unlock(&mutex->id);
152   pthread_mutex_destroy(&mutex->id);
153   free(mutex);
154}
155#else
156 
72157INLINE pthread_t osd_compare_exchange_pthread_t(pthread_t volatile *ptr, pthread_t compare, pthread_t exchange)
73158{
74159#ifdef PTR64
r2146r2147
227312{
228313   free(lock);
229314}
315#endif
230316
231
232317//============================================================
233318//  osd_num_processors
234319//============================================================
r2146r2147
486571}
487572
488573//============================================================
574//  osd_thread_cpu_affinity
575//============================================================
576
577int osd_thread_cpu_affinity(osd_thread *thread, UINT32 mask)
578{
579   cpu_set_t   cmask;
580   pthread_t   lthread;
581   int         bitnum;
582
583   CPU_ZERO(&cmask);
584   for (bitnum=0; bitnum<32; bitnum++)
585      if (mask & (1<<bitnum))
586         CPU_SET(bitnum, &cmask);
587   
588   if (thread == NULL)
589      lthread = pthread_self();
590   else
591      lthread = thread->thread;
592   
593   if (pthread_setaffinity_np(lthread, sizeof(cmask), &cmask) <0)
594   {
595      fprintf(stderr, "error %d setting cpu affinity to mask %08x", errno, mask);
596      return FALSE;
597   }
598   else
599      return TRUE;
600}
601
602//============================================================
489603//  osd_thread_wait_free
490604//============================================================
491605
src/osd/sdl/sdlsync.h
r2146r2147
1616
1717#ifndef SDLMAME_OS2
1818
19#define THREAD_COOPERATIVE      (1)
20
1921/***************************************************************************
2022    SYNCHRONIZATION INTERFACES - Events
2123***************************************************************************/
r2146r2147
142144-----------------------------------------------------------------------------*/
143145int osd_thread_adjust_priority(osd_thread *thread, int adjust);
144146
147/*-----------------------------------------------------------------------------
148    osd_thread_cpu_affinity: change cpu affinity of a thread
145149
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
146163/*-----------------------------------------------------------------------------
147164    osd_thread_wait_free: wait for thread to finish and free resources
148165
src/osd/sdl/sdlwork.c
r2146r2147
4040//  PARAMETERS
4141//============================================================
4242
43#define INFINITE            (osd_ticks_per_second()*10000)
43#define INFINITE            (osd_ticks_per_second() *  (osd_ticks_t) 10000)
44#if THREAD_COOPERATIVE
45//FIXME: depends on <THREADS>/<PHYS PROCESSORS>
46#define SPIN_LOOP_TIME         (osd_ticks_per_second() / 10000)
47//#define SPIN_LOOP_TIME         ((osd_ticks_t) 0)
48#else
4449#define SPIN_LOOP_TIME         (osd_ticks_per_second() / 1000)
50#endif
4551
4652
47
4853//============================================================
4954//  MACROS
5055//============================================================
r2146r2147
6873typedef struct _scalable_lock scalable_lock;
6974struct _scalable_lock
7075{
71   struct
72   {
73      volatile INT32    haslock;      // do we have the lock?
74      INT32          filler[64/4-1];   // assumes a 64-byte cache line
75   } slot[WORK_MAX_THREADS];         // one slot per thread
76   volatile INT32       nextindex;      // index of next slot to use
76#if THREAD_COOPERATIVE
77   osd_lock         *lock;
78#else
79   struct
80   {
81      volatile INT32    haslock;      // do we have the lock?
82      INT32          filler[64/4-1];   // assumes a 64-byte cache line
83   } slot[WORK_MAX_THREADS];         // one slot per thread
84   volatile INT32       nextindex;      // index of next slot to use
85#endif
7786};
7887
7988
r2146r2147
138147//============================================================
139148
140149static int effective_num_processors(void);
150#if THREAD_COOPERATIVE
151static UINT32 effective_cpu_mask(int index);
152#endif
141153static void * worker_thread_entry(void *param);
142154static void worker_thread_process(osd_work_queue *queue, work_thread_info *thread);
143155
r2146r2147
175187
176188INLINE void scalable_lock_init(scalable_lock *lock)
177189{
190#if THREAD_COOPERATIVE
191   lock->lock = osd_lock_alloc();
192#else
178193   memset(lock, 0, sizeof(*lock));
179194   lock->slot[0].haslock = TRUE;
195#endif
180196}
181197
182198
183199INLINE INT32 scalable_lock_acquire(scalable_lock *lock)
184200{
201#if THREAD_COOPERATIVE
202   osd_lock_acquire(lock->lock);
203   return 0;
204#else
185205   INT32 myslot = (atomic_increment32(&lock->nextindex) - 1) & (WORK_MAX_THREADS - 1);
186206
187207#if defined(__i386__) || defined(__x86_64__)
r2146r2147
234254   }
235255#endif
236256   return myslot;
257#endif
237258}
238259
239260
240261INLINE void scalable_lock_release(scalable_lock *lock, INT32 myslot)
241262{
263#if THREAD_COOPERATIVE
264   osd_lock_release(lock->lock);
265   return;
266#else
242267#if defined(__i386__) || defined(__x86_64__)
243268   register INT32 tmp = TRUE;
244269   __asm__ __volatile__ (
r2146r2147
253278#else
254279   osd_exchange32(&lock->slot[(myslot + 1) & (WORK_MAX_THREADS - 1)].haslock, TRUE);
255280#endif
281#endif
256282}
257283
284INLINE void scalable_lock_free(scalable_lock *lock)
285{
286#if THREAD_COOPERATIVE
287   osd_lock_free(lock->lock);
288#endif
289}
258290
291
292
259293//============================================================
260294//  osd_work_queue_alloc
261295//============================================================
r2146r2147
326360         osd_thread_adjust_priority(thread->handle, 0);   // TODO: specify appropriate priority
327361      else
328362         osd_thread_adjust_priority(thread->handle, 0);   // TODO: specify appropriate priority
363
364#if THREAD_COOPERATIVE
365      // Bind main thread to cpu 0
366      osd_thread_cpu_affinity(NULL, effective_cpu_mask(0));
367     
368      if (flags & WORK_QUEUE_FLAG_IO)
369         osd_thread_cpu_affinity(thread->handle, effective_cpu_mask(1));
370      else
371         osd_thread_cpu_affinity(thread->handle, effective_cpu_mask(2+threadnum) );
372#endif
329373   }
330374
331375   // start a timer going for "waittime" on the main thread
r2146r2147
380424         // spin until we're done
381425         begin_timing(thread->spintime);
382426         while (queue->items != 0 && osd_ticks() < stopspin)
383            osd_yield_processor();
427         {
428            int spin = 10000;
429            while (--spin && queue->items != 0)
430               osd_yield_processor();
431         }
384432         end_timing(thread->spintime);
385433
386434         begin_timing(thread->waittime);
r2146r2147
491539   printf("Spin loops     = %9d\n", queue->spinloops);
492540#endif
493541
542   scalable_lock_free(&queue->lock);
494543   // free the queue itself
495544   free(queue);
496545}
r2146r2147
668717   return osd_num_processors();
669718}
670719
720//============================================================
721//  effective_cpu_mask
722//============================================================
671723
724#if THREAD_COOPERATIVE
725static UINT32 effective_cpu_mask(int index)
726{
727   char    *s;
728   char   buf[5];
729   UINT32   mask = 0xFFFF;
730
731   s = getenv("OSDCPUMASKS");
732   if (s != NULL && strcmp(s,"none"))
733   {
734      if (!strcmp(s,"auto"))
735      {
736         if (index<2)
737            mask = 0x01; /* main thread and io threads on cpu #0 */
738         else
739            mask = (1 << (((index - 1) % (osd_num_processors() - 1)) + 1));
740      }
741      else
742      {
743         if (strlen(s) % 4 != 0 || strlen(s) < (index+1)*4)
744         {
745            fprintf(stderr,"Invalid cpu mask: %s\n", s);
746         }
747         else
748         {
749            memcpy(buf,s+4*index,4);
750            buf[4] = 0;
751            if (sscanf(buf, "%x", &mask) != 1)
752               fprintf(stderr,"Invalid cpu mask element %d: %s\n", index, buf);
753         }
754      }
755   }
756   return mask;
757}
758#endif
759
672760//============================================================
673761//  worker_thread_entry
674762//============================================================
r2146r2147
711799            begin_timing(thread->spintime);
712800            stopspin = osd_ticks() + SPIN_LOOP_TIME;
713801            while (queue->list == NULL && osd_ticks() < stopspin)
714               osd_yield_processor();
802            {
803               int spin = 10000;
804               while (--spin && queue->list == NULL)
805                  osd_yield_processor();
806            }
715807            end_timing(thread->spintime);
716808         }
717809
src/osd/sdl/window.c
r2146r2147
214214   {
215215      // create a thread to run the windows from
216216#ifndef SDLMAME_OS2
217      work_queue = osd_work_queue_alloc(0);
217      work_queue = osd_work_queue_alloc(WORK_QUEUE_FLAG_IO);
218218#else
219219      work_queue = osd_work_queue_alloc(WORK_QUEUE_FLAG_IO);
220220#endif

Previous 15994 Revisions Next


© 1998-2018 The MESS Team