Previous 199869 Revisions Next

r32096 Saturday 13th September, 2014 at 10:04:16 UTC by Oliver Stöneberg
some refactoring to make SDL and Windows OSD code match / Windows SDL code did not delete the critical section in osd_scalable_lock_free() (nw)
[src/osd/sdl]sdlsync_win32.c
[src/osd/windows]winsync.c winsync.h* winwork.c

trunk/src/osd/sdl/sdlsync_win32.c
r32095r32096
156156
157157void osd_scalable_lock_free(osd_scalable_lock *lock)
158158{
159#if USE_SCALABLE_LOCKS
160#else
161   DeleteCriticalSection(&lock->section);
162#endif
159163   free(lock);
160164}
161165
trunk/src/osd/windows/winsync.c
r32095r32096
2121//============================================================
2222
2323#define DEBUG_SLOW_LOCKS    0
24#define USE_SCALABLE_LOCKS      (0)
2425
2526
2627
r32095r32096
3536   CRITICAL_SECTION    critsect;
3637};
3738
39struct osd_scalable_lock
40{
41#if USE_SCALABLE_LOCKS
42   struct
43   {
44      volatile INT32  haslock;        // do we have the lock?
45      INT32           filler[64/4-1]; // assumes a 64-byte cache line
46   } slot[WORK_MAX_THREADS];           // one slot per thread
47   volatile INT32      nextindex;      // index of next slot to use
48#else
49   CRITICAL_SECTION    section;
50#endif
51};
3852
3953
4054//============================================================
r32095r32096
169183{
170184   return InterlockedExchangeAdd((LONG *) ptr, delta) + delta;
171185}
186
187//============================================================
188//  Scalable Locks
189//============================================================
190
191osd_scalable_lock *osd_scalable_lock_alloc(void)
192{
193   osd_scalable_lock *lock;
194
195   lock = (osd_scalable_lock *)calloc(1, sizeof(*lock));
196
197   memset(lock, 0, sizeof(*lock));
198#if USE_SCALABLE_LOCKS
199   lock->slot[0].haslock = TRUE;
200#else
201   InitializeCriticalSection(&lock->section);
202#endif
203   return lock;
204}
205
206
207INT32 osd_scalable_lock_acquire(osd_scalable_lock *lock)
208{
209#if USE_SCALABLE_LOCKS
210   INT32 myslot = (atomic_increment32(&lock->nextindex) - 1) & (WORK_MAX_THREADS - 1);
211   INT32 backoff = 1;
212
213   while (!lock->slot[myslot].haslock)
214   {
215      INT32 backcount;
216      for (backcount = 0; backcount < backoff; backcount++)
217         osd_yield_processor();
218      backoff <<= 1;
219   }
220   lock->slot[myslot].haslock = FALSE;
221   return myslot;
222#else
223   EnterCriticalSection(&lock->section);
224   return 0;
225#endif
226}
227
228
229void osd_scalable_lock_release(osd_scalable_lock *lock, INT32 myslot)
230{
231#if USE_SCALABLE_LOCKS
232   atomic_exchange32(&lock->slot[(myslot + 1) & (WORK_MAX_THREADS - 1)].haslock, TRUE);
233#else
234   LeaveCriticalSection(&lock->section);
235#endif
236}
237
238
239void osd_scalable_lock_free(osd_scalable_lock *lock)
240{
241#if USE_SCALABLE_LOCKS
242#else
243   DeleteCriticalSection(&lock->section);
244#endif
245   free(lock);
246}
No newline at end of file
trunk/src/osd/windows/winsync.h
r0r32096
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//  Scalable Locks
15//============================================================
16
17struct osd_scalable_lock;
18
19osd_scalable_lock *osd_scalable_lock_alloc(void);
20
21INT32 osd_scalable_lock_acquire(osd_scalable_lock *lock);
22
23void osd_scalable_lock_release(osd_scalable_lock *lock, INT32 myslot);
24
25void osd_scalable_lock_free(osd_scalable_lock *lock);
26
27#endif  /* __WINSYNC__ */
No newline at end of file
Property changes on: trunk/src/osd/windows/winsync.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/osd/windows/winwork.c
r32095r32096
1919
2020// MAME headers
2121#include "osdcore.h"
22
23#include "winsync.h"
24
2225#include "eminline.h"
2326
2427
r32095r32096
2730//============================================================
2831
2932#define KEEP_STATISTICS         (0)
30#define USE_SCALABLE_LOCKS      (0)
3133
32
33
3434//============================================================
3535//  PARAMETERS
3636//============================================================
r32095r32096
7979//  TYPE DEFINITIONS
8080//============================================================
8181
82struct scalable_lock
83{
84#if USE_SCALABLE_LOCKS
85   struct
86   {
87      volatile INT32  haslock;        // do we have the lock?
88      INT32           filler[64/4-1]; // assumes a 64-byte cache line
89   } slot[WORK_MAX_THREADS];           // one slot per thread
90   volatile INT32      nextindex;      // index of next slot to use
91#else
92   CRITICAL_SECTION    section;
93#endif
94};
95
96
9782struct work_thread_info
9883{
9984   osd_work_queue *    queue;          // pointer back to the queue
r32095r32096
11398
11499struct osd_work_queue
115100{
116   scalable_lock       lock;           // lock for protecting the queue
101   osd_scalable_lock * lock;           // lock for protecting the queue
117102   osd_work_item * volatile list;      // list of items in the queue
118103   osd_work_item ** volatile tailptr;  // pointer to the tail pointer of work items in the queue
119104   osd_work_item * volatile free;      // free list of work items
r32095r32096
162147static void worker_thread_process(osd_work_queue *queue, work_thread_info *thread);
163148
164149
165
166150//============================================================
167//  Scalable Locks
168//============================================================
169
170INLINE void scalable_lock_init(scalable_lock *lock)
171{
172   memset(lock, 0, sizeof(*lock));
173#if USE_SCALABLE_LOCKS
174   lock->slot[0].haslock = TRUE;
175#else
176   InitializeCriticalSection(&lock->section);
177#endif
178}
179
180
181INLINE INT32 scalable_lock_acquire(scalable_lock *lock)
182{
183#if USE_SCALABLE_LOCKS
184   INT32 myslot = (atomic_increment32(&lock->nextindex) - 1) & (WORK_MAX_THREADS - 1);
185   INT32 backoff = 1;
186
187   while (!lock->slot[myslot].haslock)
188   {
189      INT32 backcount;
190      for (backcount = 0; backcount < backoff; backcount++)
191         osd_yield_processor();
192      backoff <<= 1;
193   }
194   lock->slot[myslot].haslock = FALSE;
195   return myslot;
196#else
197   EnterCriticalSection(&lock->section);
198   return 0;
199#endif
200}
201
202
203INLINE void scalable_lock_release(scalable_lock *lock, INT32 myslot)
204{
205#if USE_SCALABLE_LOCKS
206   atomic_exchange32(&lock->slot[(myslot + 1) & (WORK_MAX_THREADS - 1)].haslock, TRUE);
207#else
208   LeaveCriticalSection(&lock->section);
209#endif
210}
211
212
213INLINE void scalable_lock_delete(scalable_lock *lock)
214{
215#if USE_SCALABLE_LOCKS
216#else
217   DeleteCriticalSection(&lock->section);
218#endif
219}
220
221
222//============================================================
223151//  osd_work_queue_alloc
224152//============================================================
225153
r32095r32096
246174      goto error;
247175
248176   // initialize the critical section
249   scalable_lock_init(&queue->lock);
177   queue->lock = osd_scalable_lock_alloc();
178   if (queue->lock == NULL)
179      goto error;
250180
251181   // determine how many threads to create...
252182   // on a single-CPU system, create 1 thread for I/O queues, and 0 threads for everything else
r32095r32096
341271   if (queue->flags & WORK_QUEUE_FLAG_MULTI)
342272   {
343273      work_thread_info *thread = &queue->thread[queue->threads];
344      osd_ticks_t stopspin = osd_ticks() + timeout;
345274
346275      end_timing(thread->waittime);
347276
r32095r32096
351280      // if we're a high frequency queue, spin until done
352281      if (queue->flags & WORK_QUEUE_FLAG_HIGH_FREQ)
353282      {
283         osd_ticks_t stopspin = osd_ticks() + timeout;
284
354285         // spin until we're done
355286         begin_timing(thread->spintime);
356287         while (queue->items != 0 && osd_ticks() < stopspin)
r32095r32096
435366   if (queue->thread != NULL)
436367      free(queue->thread);
437368
438   scalable_lock_delete(&queue->lock);
439
440369   // free all the events
441370   if (queue->doneevent != NULL)
442371      CloseHandle(queue->doneevent);
r32095r32096
468397   printf("Spin loops     = %9d\n", queue->spinloops);
469398#endif
470399
400   osd_scalable_lock_free(queue->lock);
471401   // free the queue itself
472402   free(queue);
473403}
r32095r32096
522452   }
523453
524454   // enqueue the whole thing within the critical section
525   lockslot = scalable_lock_acquire(&queue->lock);
455   lockslot = osd_scalable_lock_acquire(queue->lock);
526456   *queue->tailptr = itemlist;
527457   queue->tailptr = item_tailptr;
528   scalable_lock_release(&queue->lock, lockslot);
458   osd_scalable_lock_release(queue->lock, lockslot);
529459
530460   // increment the number of items in the queue
531461   atomic_add32(&queue->items, numitems);
r32095r32096
732662      INT32 lockslot;
733663
734664      // use a critical section to synchronize the removal of items
735      lockslot = scalable_lock_acquire(&queue->lock);
665      lockslot = osd_scalable_lock_acquire(queue->lock);
736666      {
737667         // pull the item from the queue
738668         item = (osd_work_item *)queue->list;
r32095r32096
743673               queue->tailptr = (osd_work_item **)&queue->list;
744674         }
745675      }
746      scalable_lock_release(&queue->lock, lockslot);
676      osd_scalable_lock_release(queue->lock, lockslot);
747677
748678      // process non-NULL items
749679      if (item != NULL)

Previous 199869 Revisions Next


© 1997-2024 The MAME Team