From c967decff033d6e227a7d4897ca92b15b1bcde9e Mon Sep 17 00:00:00 2001 From: mcmartin Date: Sun, 14 Sep 2003 02:23:08 +0000 Subject: [PATCH] Unified the recursive mutex implementations in MixSDL and DCQ code git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@1233 8092fc87-c524-0410-9efc-e669fe64eaf9 --- sc2/ChangeLog | 1 + sc2/src/sc2code/libs/graphics/drawcmd.h | 4 +- sc2/src/sc2code/libs/graphics/sdl/3do_funcs.c | 2 - sc2/src/sc2code/libs/graphics/sdl/dcqueue.c | 97 +++----- .../sc2code/libs/graphics/sdl/sdl_common.c | 3 + sc2/src/sc2code/libs/sound/mixsdl/mixer.c | 215 +++++++----------- sc2/src/sc2code/libs/sound/mixsdl/mixerint.h | 15 -- sc2/src/sc2code/libs/threadlib.h | 7 + sc2/src/sc2code/libs/threads/sdl/sdlthreads.c | 91 +++++++- 9 files changed, 211 insertions(+), 224 deletions(-) diff --git a/sc2/ChangeLog b/sc2/ChangeLog index a351c8d3f..5c26cd0f3 100644 --- a/sc2/ChangeLog +++ b/sc2/ChangeLog @@ -1,4 +1,5 @@ Changes towards version 0.4: +- Abstracted the recursive mutexes in MixSDL and DCQ code -Michael - Introduced a new synchronization construct (CrossThreadMutex) and migrated the GraphicsSem and clock_sem over to it (#359) -Michael - Replaced thread-local Semaphores with Mutexes (#359) -Michael diff --git a/sc2/src/sc2code/libs/graphics/drawcmd.h b/sc2/src/sc2code/libs/graphics/drawcmd.h index 4836d1308..26de281a8 100644 --- a/sc2/src/sc2code/libs/graphics/drawcmd.h +++ b/sc2/src/sc2code/libs/graphics/drawcmd.h @@ -142,7 +142,9 @@ typedef struct tfb_drawcommandqueue volatile int Size; } TFB_DrawCommandQueue; -void TFB_DrawCommandQueue_Create (void); +void Init_DrawCommandQueue (void); + +void Uninit_DrawCommandQueue (void); void TFB_BatchGraphics (void); diff --git a/sc2/src/sc2code/libs/graphics/sdl/3do_funcs.c b/sc2/src/sc2code/libs/graphics/sdl/3do_funcs.c index de17f1f43..c046ecf23 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/3do_funcs.c +++ b/sc2/src/sc2code/libs/graphics/sdl/3do_funcs.c @@ -36,8 +36,6 @@ InitGraphics (int argc, char* argv[], COUNT KbytesRequired) { BOOLEAN ret; - TFB_DrawCommandQueue_Create (); - LoadDisplay (&_pCurDisplay); ActivateDisplay (); diff --git a/sc2/src/sc2code/libs/graphics/sdl/dcqueue.c b/sc2/src/sc2code/libs/graphics/sdl/dcqueue.c index 7b3e2bef7..0f2e1d609 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/dcqueue.c +++ b/sc2/src/sc2code/libs/graphics/sdl/dcqueue.c @@ -24,37 +24,12 @@ #include "libs/graphics/drawcmd.h" #include "libs/graphics/sdl/dcqueue.h" -static Mutex DCQ_lock; - -// variables for making the DCQ lock re-entrant -static int DCQ_locking_depth = 0; -static Uint32 DCQ_locking_thread = 0; +static RecursiveMutex DCQ_Mutex; TFB_DrawCommand DCQ[DCQ_MAX]; TFB_DrawCommandQueue DrawCommandQueue; -// DCQ Synchronization: SDL-specific implementation of re-entrant -// locks to protect the Draw Command Queue. Lock is re-entrant to -// allow livelock deterrence to be written much more cleanly. - -static void -_lock (void) -{ - Uint32 current_thread = SDL_ThreadID (); - if (DCQ_locking_thread != current_thread) - { - if (LockMutex (DCQ_lock)) - { - fprintf (stderr, "DCQ lock attempt failed!\n"); - return; - } - DCQ_locking_thread = current_thread; - } - ++DCQ_locking_depth; - // fprintf (stderr, "DCQ_lock locking depth: %i\n", DCQ_locking_depth); -} - // Wait for the queue to be emptied. static void TFB_WaitForSpace (int requested_slots) @@ -64,19 +39,19 @@ TFB_WaitForSpace (int requested_slots) // Restore the DCQ locking level. I *think* this is // always 1, but... TFB_BatchReset (); - old_depth = DCQ_locking_depth; + old_depth = GetRecursiveMutexDepth (DCQ_Mutex); for (i = 0; i < old_depth; i++) - Unlock_DCQ (); + UnlockRecursiveMutex (DCQ_Mutex); WaitCondVar (RenderingCond); for (i = 0; i < old_depth; i++) - _lock (); + LockRecursiveMutex (DCQ_Mutex); fprintf (stderr, "DCQ clear (Size = %d, FullSize = %d). Continuing.\n", DrawCommandQueue.Size, DrawCommandQueue.FullSize); } void Lock_DCQ (int slots) { - _lock (); + LockRecursiveMutex (DCQ_Mutex); while (DrawCommandQueue.FullSize >= DCQ_MAX - slots) { TFB_WaitForSpace (slots); @@ -86,21 +61,7 @@ Lock_DCQ (int slots) void Unlock_DCQ (void) { - Uint32 current_thread = SDL_ThreadID (); - if (DCQ_locking_thread != current_thread) - { - fprintf (stderr, "%8x attempted to unlock the DCQ when it didn't hold it!\n", current_thread); - } - else - { - --DCQ_locking_depth; - // fprintf (stderr, "DCQ_lock locking depth: %i\n", DCQ_locking_depth); - if (!DCQ_locking_depth) - { - DCQ_locking_thread = 0; - UnlockMutex (DCQ_lock); - } - } + UnlockRecursiveMutex (DCQ_Mutex); } // Always have the DCQ locked when calling this. @@ -127,21 +88,21 @@ Synchronize_DCQ (void) void TFB_BatchGraphics (void) { - _lock (); + LockRecursiveMutex (DCQ_Mutex); DrawCommandQueue.Batching++; - Unlock_DCQ (); + UnlockRecursiveMutex (DCQ_Mutex); } void TFB_UnbatchGraphics (void) -{ - _lock (); +{ + LockRecursiveMutex (DCQ_Mutex); if (DrawCommandQueue.Batching) { DrawCommandQueue.Batching--; } Synchronize_DCQ (); - Unlock_DCQ (); + UnlockRecursiveMutex (DCQ_Mutex); } // Cancel all pending batch operations, making them unbatched. This will @@ -150,28 +111,32 @@ TFB_UnbatchGraphics (void) void TFB_BatchReset (void) { - _lock (); + LockRecursiveMutex (DCQ_Mutex); DrawCommandQueue.Batching = 0; Synchronize_DCQ (); - Unlock_DCQ (); + UnlockRecursiveMutex (DCQ_Mutex); } // Draw Command Queue Stuff void -TFB_DrawCommandQueue_Create() +Init_DrawCommandQueue (void) { - DrawCommandQueue.Back = 0; - DrawCommandQueue.Front = 0; - DrawCommandQueue.InsertionPoint = 0; - DrawCommandQueue.Batching = 0; - DrawCommandQueue.FullSize = 0; - DrawCommandQueue.Size = 0; - DCQ_locking_depth = 0; - DCQ_locking_thread = 0; + DrawCommandQueue.Back = 0; + DrawCommandQueue.Front = 0; + DrawCommandQueue.InsertionPoint = 0; + DrawCommandQueue.Batching = 0; + DrawCommandQueue.FullSize = 0; + DrawCommandQueue.Size = 0; - DCQ_lock = CreateMutex (); + DCQ_Mutex = CreateRecursiveMutex ("DCQ"); +} + +void +Uninit_DrawCommandQueue (void) +{ + DestroyRecursiveMutex (DCQ_Mutex); } void @@ -188,7 +153,7 @@ TFB_DrawCommandQueue_Push (TFB_DrawCommand* Command) int TFB_DrawCommandQueue_Pop (TFB_DrawCommand *target) { - _lock (); + LockRecursiveMutex (DCQ_Mutex); if (DrawCommandQueue.Size == 0) { @@ -209,7 +174,7 @@ TFB_DrawCommandQueue_Pop (TFB_DrawCommand *target) DrawCommandQueue.Size--; DrawCommandQueue.FullSize--; - Unlock_DCQ (); + UnlockRecursiveMutex (DCQ_Mutex); return 1; } @@ -217,14 +182,14 @@ TFB_DrawCommandQueue_Pop (TFB_DrawCommand *target) void TFB_DrawCommandQueue_Clear () { - _lock (); + LockRecursiveMutex (DCQ_Mutex); DrawCommandQueue.Size = 0; DrawCommandQueue.Front = 0; DrawCommandQueue.Back = 0; DrawCommandQueue.Batching = 0; DrawCommandQueue.FullSize = 0; DrawCommandQueue.InsertionPoint = 0; - Unlock_DCQ (); + UnlockRecursiveMutex (DCQ_Mutex); } void diff --git a/sc2/src/sc2code/libs/graphics/sdl/sdl_common.c b/sc2/src/sc2code/libs/graphics/sdl/sdl_common.c index 7eacd1bb1..3ac96f12d 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/sdl_common.c +++ b/sc2/src/sc2code/libs/graphics/sdl/sdl_common.c @@ -93,6 +93,8 @@ TFB_InitGraphics (int driver, int flags, int width, int height, int bpp) if (flags & TFB_GFXFLAGS_FULLSCREEN) SDL_ShowCursor (SDL_DISABLE); + Init_DrawCommandQueue (); + TFB_FlushPaletteCache (); TFB_DrawCanvas_Initialize (); @@ -102,6 +104,7 @@ TFB_InitGraphics (int driver, int flags, int width, int height, int bpp) void TFB_UninitGraphics (void) { + Uninit_DrawCommandQueue (); SDL_Quit (); } diff --git a/sc2/src/sc2code/libs/sound/mixsdl/mixer.c b/sc2/src/sc2code/libs/sound/mixsdl/mixer.c index defe8dff5..82c7a9c8e 100644 --- a/sc2/src/sc2code/libs/sound/mixsdl/mixer.c +++ b/sc2/src/sc2code/libs/sound/mixsdl/mixer.c @@ -61,13 +61,12 @@ static mixSDL_Quality mixer_quality; static uint32 mixer_datasize; static sint32 *mixer_data = 0; -mixSDL_Mutex_info mixer_mutexes[3]; /* when locking more than one mutex * you must lock them in this order */ -static mixSDL_Mutex src_mutex = mixer_mutexes + 0; -static mixSDL_Mutex buf_mutex = mixer_mutexes + 1; -static mixSDL_Mutex act_mutex = mixer_mutexes + 2; +static RecursiveMutex src_mutex; +static RecursiveMutex buf_mutex; +static RecursiveMutex act_mutex; #define MAX_SOURCES 8 mixSDL_Source *active_sources[MAX_SOURCES]; @@ -77,56 +76,6 @@ mixSDL_Source *active_sources[MAX_SOURCES]; * Internals */ -static void -mixSDL_InitMutex (mixSDL_Mutex mtx, char* name) -{ - mtx->thread_id = 0; - mtx->sem = CreateSemaphore (1, name); - mtx->locks = 0; -} - -static void -mixSDL_TermMutex (mixSDL_Mutex mtx) -{ - DestroySemaphore (mtx->sem); - mtx->sem = 0; - mtx->thread_id = 0; -} - -static void -mixSDL_LockMutex (mixSDL_Mutex mtx) -{ - uint32 thread_id = SDL_ThreadID(); - if (mtx->thread_id != thread_id) - { - SetSemaphore (mtx->sem); - mtx->thread_id = thread_id; - } - mtx->locks++; -} - -static void -mixSDL_UnlockMutex (mixSDL_Mutex mtx) -{ - uint32 thread_id = SDL_ThreadID(); - if (mtx->thread_id != thread_id) - { -#ifdef DEBUG - fprintf (stderr, "%8x attempted to unlock the mutex " - "when it didn't hold it\n", thread_id); -#endif - } - else - { - mtx->locks--; - if (!mtx->locks) - { - mtx->thread_id = 0; - ClearSemaphore (mtx->sem); - } - } -} - static void mixSDL_SetError (uint32 error) { @@ -260,9 +209,9 @@ mixSDL_OpenAudio (uint32 frequency, uint32 format, uint32 samples_buf, mixer_datasize = samples_buf * mixer_spec.channels * 2; mixer_data = (sint32 *) HMalloc (sizeof (uint32) * mixer_datasize); - mixSDL_InitMutex (src_mutex, "mixSDL_SourceMutex"); - mixSDL_InitMutex (buf_mutex, "mixSDL_BufferMutex"); - mixSDL_InitMutex (act_mutex, "mixSDL_ActiveMutex"); + src_mutex = CreateRecursiveMutex("mixSDL_SourceMutex"); + buf_mutex = CreateRecursiveMutex("mixSDL_BufferMutex"); + act_mutex = CreateRecursiveMutex("mixSDL_ActiveMutex"); audio_opened = 1; mixer_driver->PauseAudio (0); @@ -286,9 +235,9 @@ mixSDL_CloseAudio (void) mixer_data = 0; } - mixSDL_TermMutex (src_mutex); - mixSDL_TermMutex (buf_mutex); - mixSDL_TermMutex (act_mutex); + DestroyRecursiveMutex (src_mutex); + DestroyRecursiveMutex (buf_mutex); + DestroyRecursiveMutex (act_mutex); } --audio_opened; } @@ -378,7 +327,7 @@ mixSDL_DeleteSources (uint32 n, mixSDL_Object *psrcobj) return; } - mixSDL_LockMutex (src_mutex); + LockRecursiveMutex (src_mutex); /* check to make sure we can delete all sources */ for (i = n, pcurobj = psrcobj; i && pcurobj; i--, pcurobj++) @@ -423,7 +372,7 @@ mixSDL_DeleteSources (uint32 n, mixSDL_Object *psrcobj) } } - mixSDL_UnlockMutex (src_mutex); + UnlockRecursiveMutex (src_mutex); } /* check if really is a source */ @@ -436,9 +385,9 @@ mixSDL_IsSource (mixSDL_Object srcobj) if (!src) return false; - mixSDL_LockMutex (src_mutex); + LockRecursiveMutex (src_mutex); ret = src->magic == mixSDL_srcMagic; - mixSDL_UnlockMutex (src_mutex); + UnlockRecursiveMutex (src_mutex); return ret; } @@ -459,7 +408,7 @@ mixSDL_Sourcei (mixSDL_Object srcobj, mixSDL_SourceProp pname, return; } - mixSDL_LockMutex (src_mutex); + LockRecursiveMutex (src_mutex); if (src->magic != mixSDL_srcMagic) { @@ -512,7 +461,7 @@ mixSDL_Sourcei (mixSDL_Object srcobj, mixSDL_SourceProp pname, } } - mixSDL_UnlockMutex (src_mutex); + UnlockRecursiveMutex (src_mutex); } /* set source float property */ @@ -530,7 +479,7 @@ mixSDL_Sourcef (mixSDL_Object srcobj, mixSDL_SourceProp pname, float value) return; } - mixSDL_LockMutex (src_mutex); + LockRecursiveMutex (src_mutex); if (src->magic != mixSDL_srcMagic) { @@ -552,7 +501,7 @@ mixSDL_Sourcef (mixSDL_Object srcobj, mixSDL_SourceProp pname, float value) } } - mixSDL_UnlockMutex (src_mutex); + UnlockRecursiveMutex (src_mutex); } /* set source float array property (CURRENTLY NOT IMPLEMENTED) */ @@ -580,7 +529,7 @@ mixSDL_GetSourcei (mixSDL_Object srcobj, mixSDL_SourceProp pname, return; } - mixSDL_LockMutex (src_mutex); + LockRecursiveMutex (src_mutex); if (src->magic != mixSDL_srcMagic) { @@ -615,7 +564,7 @@ mixSDL_GetSourcei (mixSDL_Object srcobj, mixSDL_SourceProp pname, } } - mixSDL_UnlockMutex (src_mutex); + UnlockRecursiveMutex (src_mutex); } /* get source float property */ @@ -634,7 +583,7 @@ mixSDL_GetSourcef (mixSDL_Object srcobj, mixSDL_SourceProp pname, return; } - mixSDL_LockMutex (src_mutex); + LockRecursiveMutex (src_mutex); if (src->magic != mixSDL_srcMagic) { @@ -656,7 +605,7 @@ mixSDL_GetSourcef (mixSDL_Object srcobj, mixSDL_SourceProp pname, } } - mixSDL_UnlockMutex (src_mutex); + UnlockRecursiveMutex (src_mutex); } /* start the source; add it to active array */ @@ -674,7 +623,7 @@ mixSDL_SourcePlay (mixSDL_Object srcobj) return; } - mixSDL_LockMutex (src_mutex); + LockRecursiveMutex (src_mutex); if (src->magic != mixSDL_srcMagic) { @@ -694,7 +643,7 @@ mixSDL_SourcePlay (mixSDL_Object srcobj) src->state = MIX_PLAYING; } - mixSDL_UnlockMutex (src_mutex); + UnlockRecursiveMutex (src_mutex); } /* stop the source; remove it from active array and requeue buffers */ @@ -712,7 +661,7 @@ mixSDL_SourceRewind (mixSDL_Object srcobj) return; } - mixSDL_LockMutex (src_mutex); + LockRecursiveMutex (src_mutex); if (src->magic != mixSDL_srcMagic) { @@ -726,7 +675,7 @@ mixSDL_SourceRewind (mixSDL_Object srcobj) mixSDL_SourceRewind_internal (src); } - mixSDL_UnlockMutex (src_mutex); + UnlockRecursiveMutex (src_mutex); } /* pause the source; keep in active array */ @@ -744,7 +693,7 @@ mixSDL_SourcePause (mixSDL_Object srcobj) return; } - mixSDL_LockMutex (src_mutex); + LockRecursiveMutex (src_mutex); if (src->magic != mixSDL_srcMagic) { @@ -760,7 +709,7 @@ mixSDL_SourcePause (mixSDL_Object srcobj) src->state = MIX_PAUSED; } - mixSDL_UnlockMutex (src_mutex); + UnlockRecursiveMutex (src_mutex); } /* stop the source; remove it from active array @@ -780,7 +729,7 @@ mixSDL_SourceStop (mixSDL_Object srcobj) return; } - mixSDL_LockMutex (src_mutex); + LockRecursiveMutex (src_mutex); if (src->magic != mixSDL_srcMagic) { @@ -797,7 +746,7 @@ mixSDL_SourceStop (mixSDL_Object srcobj) src->state = MIX_STOPPED; } - mixSDL_UnlockMutex (src_mutex); + UnlockRecursiveMutex (src_mutex); } /* queue buffers on the source */ @@ -819,7 +768,7 @@ mixSDL_SourceQueueBuffers (mixSDL_Object srcobj, uint32 n, return; } - mixSDL_LockMutex (buf_mutex); + LockRecursiveMutex (buf_mutex); /* check to make sure we can safely queue all buffers */ for (i = n, pobj = pbufobj; i; i--, pobj++) { @@ -830,12 +779,12 @@ mixSDL_SourceQueueBuffers (mixSDL_Object srcobj, uint32 n, break; } } - mixSDL_UnlockMutex (buf_mutex); + UnlockRecursiveMutex (buf_mutex); if (i == 0) { /* all buffers checked out */ - mixSDL_LockMutex (src_mutex); - mixSDL_LockMutex (buf_mutex); + LockRecursiveMutex (src_mutex); + LockRecursiveMutex (buf_mutex); if (src->magic != mixSDL_srcMagic) { @@ -866,8 +815,8 @@ mixSDL_SourceQueueBuffers (mixSDL_Object srcobj, uint32 n, } } - mixSDL_UnlockMutex (buf_mutex); - mixSDL_UnlockMutex (src_mutex); + UnlockRecursiveMutex (buf_mutex); + UnlockRecursiveMutex (src_mutex); } } @@ -890,7 +839,7 @@ mixSDL_SourceUnqueueBuffers (mixSDL_Object srcobj, uint32 n, return; } - mixSDL_LockMutex (src_mutex); + LockRecursiveMutex (src_mutex); if (src->magic != mixSDL_srcMagic) { @@ -905,7 +854,7 @@ mixSDL_SourceUnqueueBuffers (mixSDL_Object srcobj, uint32 n, } else { - mixSDL_LockMutex (buf_mutex); + LockRecursiveMutex (buf_mutex); /* check to make sure we can unqueue all buffers */ for (i = n, curbuf = src->firstqueued; @@ -946,10 +895,10 @@ mixSDL_SourceUnqueueBuffers (mixSDL_Object srcobj, uint32 n, } } - mixSDL_UnlockMutex (buf_mutex); + UnlockRecursiveMutex (buf_mutex); } - mixSDL_UnlockMutex (src_mutex); + UnlockRecursiveMutex (src_mutex); } /************************************************* @@ -971,7 +920,7 @@ mixSDL_SourceUnqueueAll (mixSDL_Source *src) return; } - mixSDL_LockMutex (buf_mutex); + LockRecursiveMutex (buf_mutex); for (buf = src->firstqueued; buf; buf = nextbuf) { @@ -987,7 +936,7 @@ mixSDL_SourceUnqueueAll (mixSDL_Source *src) buf->next = 0; } - mixSDL_UnlockMutex (buf_mutex); + UnlockRecursiveMutex (buf_mutex); src->firstqueued = 0; src->nextqueued = 0; @@ -1005,7 +954,7 @@ mixSDL_SourceActivate (mixSDL_Source* src) { uint32 i; - mixSDL_LockMutex (act_mutex); + LockRecursiveMutex (act_mutex); #ifdef DEBUG /* check active sources, see if this source is there already */ @@ -1015,7 +964,7 @@ mixSDL_SourceActivate (mixSDL_Source* src) { /* source found */ fprintf (stderr, "mixSDL_SourceActivate(): " "source already active in slot %u\n", i); - mixSDL_UnlockMutex (act_mutex); + UnlockRecursiveMutex (act_mutex); return; } #endif @@ -1035,7 +984,7 @@ mixSDL_SourceActivate (mixSDL_Source* src) } #endif - mixSDL_UnlockMutex (act_mutex); + UnlockRecursiveMutex (act_mutex); } /* remove the source from the active array */ @@ -1044,7 +993,7 @@ mixSDL_SourceDeactivate (mixSDL_Source* src) { uint32 i; - mixSDL_LockMutex (act_mutex); + LockRecursiveMutex (act_mutex); /* check active sources, see if this source is there */ for (i = 0; i < MAX_SOURCES && active_sources[i] != src; i++) @@ -1060,7 +1009,7 @@ mixSDL_SourceDeactivate (mixSDL_Source* src) } #endif - mixSDL_UnlockMutex (act_mutex); + UnlockRecursiveMutex (act_mutex); } static void @@ -1082,7 +1031,7 @@ mixSDL_SourceStop_internal (mixSDL_Source *src) } #endif - mixSDL_LockMutex (buf_mutex); + LockRecursiveMutex (buf_mutex); /* find last 'processed' buffer */ for (buf = src->firstqueued; @@ -1112,7 +1061,7 @@ mixSDL_SourceStop_internal (mixSDL_Source *src) src->curbufofs = 0; src->curbufdelta = 0; - mixSDL_UnlockMutex (buf_mutex); + UnlockRecursiveMutex (buf_mutex); } static void @@ -1124,7 +1073,7 @@ mixSDL_SourceRewind_internal (mixSDL_Source *src) if (src->state >= MIX_PLAYING) mixSDL_SourceDeactivate (src); - mixSDL_LockMutex (buf_mutex); + LockRecursiveMutex (buf_mutex); for (buf = src->firstqueued; buf && buf->state != MIX_BUF_QUEUED; @@ -1133,7 +1082,7 @@ mixSDL_SourceRewind_internal (mixSDL_Source *src) buf->state = MIX_BUF_QUEUED; } - mixSDL_UnlockMutex (buf_mutex); + UnlockRecursiveMutex (buf_mutex); src->curbufofs = 0; src->curbufdelta = 0; @@ -1360,7 +1309,7 @@ mixSDL_DeleteBuffers (uint32 n, mixSDL_Object *pbufobj) return; } - mixSDL_LockMutex (buf_mutex); + LockRecursiveMutex (buf_mutex); /* check to make sure we can delete all buffers */ for (i = n, pcurobj = pbufobj; i && pcurobj; i--, pcurobj++) @@ -1414,7 +1363,7 @@ mixSDL_DeleteBuffers (uint32 n, mixSDL_Object *pbufobj) *pbufobj = 0; } } - mixSDL_UnlockMutex (buf_mutex); + UnlockRecursiveMutex (buf_mutex); } /* check if really a buffer object */ @@ -1427,9 +1376,9 @@ mixSDL_IsBuffer (mixSDL_Object bufobj) if (!buf) return false; - mixSDL_LockMutex (buf_mutex); + LockRecursiveMutex (buf_mutex); ret = buf->magic == mixSDL_bufMagic; - mixSDL_UnlockMutex (buf_mutex); + UnlockRecursiveMutex (buf_mutex); return ret; } @@ -1450,11 +1399,11 @@ mixSDL_GetBufferi (mixSDL_Object bufobj, mixSDL_BufferProp pname, return; } - mixSDL_LockMutex (buf_mutex); + LockRecursiveMutex (buf_mutex); if (buf->locked) { - mixSDL_UnlockMutex (buf_mutex); + UnlockRecursiveMutex (buf_mutex); mixSDL_SetError (MIX_INVALID_OPERATION); #ifdef DEBUG fprintf (stderr, "mixSDL_GetBufferi() called with locked buffer\n"); @@ -1497,7 +1446,7 @@ mixSDL_GetBufferi (mixSDL_Object bufobj, mixSDL_BufferProp pname, } } - mixSDL_UnlockMutex (buf_mutex); + UnlockRecursiveMutex (buf_mutex); } /* fill buffer with external data */ @@ -1518,11 +1467,11 @@ mixSDL_BufferData (mixSDL_Object bufobj, uint32 format, void* data, return; } - mixSDL_LockMutex (buf_mutex); + LockRecursiveMutex (buf_mutex); if (buf->locked) { - mixSDL_UnlockMutex (buf_mutex); + UnlockRecursiveMutex (buf_mutex); mixSDL_SetError (MIX_INVALID_OPERATION); #ifdef DEBUG fprintf (stderr, "mixSDL_BufferData() called " @@ -1582,7 +1531,7 @@ mixSDL_BufferData (mixSDL_Object bufobj, uint32 format, void* data, { /* format identical to internal */ buf->locked = true; - mixSDL_UnlockMutex (buf_mutex); + UnlockRecursiveMutex (buf_mutex); memcpy (buf->data, data, size); if (MIX_FORMAT_SAMPSIZE (mixer_format) == 1) @@ -1593,7 +1542,7 @@ mixSDL_BufferData (mixSDL_Object bufobj, uint32 format, void* data, *dst ^= 0x80; } - mixSDL_LockMutex (buf_mutex); + LockRecursiveMutex (buf_mutex); buf->locked = false; } else @@ -1607,11 +1556,11 @@ mixSDL_BufferData (mixSDL_Object bufobj, uint32 format, void* data, conv.dstsize = dstsize; buf->locked = true; - mixSDL_UnlockMutex (buf_mutex); + UnlockRecursiveMutex (buf_mutex); mixSDL_ConvertBuffer_internal (&conv); - mixSDL_LockMutex (buf_mutex); + LockRecursiveMutex (buf_mutex); buf->locked = false; } } @@ -1620,7 +1569,7 @@ mixSDL_BufferData (mixSDL_Object bufobj, uint32 format, void* data, } } - mixSDL_UnlockMutex (buf_mutex); + UnlockRecursiveMutex (buf_mutex); } @@ -2015,9 +1964,9 @@ mixSDL_mix_channels (void *userdata, uint8 *stream, sint32 len) } /* keep this order or die */ - mixSDL_LockMutex (src_mutex); - mixSDL_LockMutex (buf_mutex); - mixSDL_LockMutex (act_mutex); + LockRecursiveMutex (src_mutex); + LockRecursiveMutex (buf_mutex); + LockRecursiveMutex (act_mutex); /* first, collect data from sources and put into work-buffer */ for (data = mixer_data; data < end_data; ++data) @@ -2068,9 +2017,9 @@ mixSDL_mix_channels (void *userdata, uint8 *stream, sint32 len) } /* keep this order or die */ - mixSDL_UnlockMutex (act_mutex); - mixSDL_UnlockMutex (buf_mutex); - mixSDL_UnlockMutex (src_mutex); + UnlockRecursiveMutex (act_mutex); + UnlockRecursiveMutex (buf_mutex); + UnlockRecursiveMutex (src_mutex); (void) userdata; // satisfying compiler - unused arg } @@ -2167,9 +2116,9 @@ mixSDL_mix_lowq (void *userdata, uint8 *stream, sint32 len) uint32 chans = MIX_FORMAT_CHANS (mixer_format); /* keep this order or die */ - mixSDL_LockMutex (src_mutex); - mixSDL_LockMutex (buf_mutex); - mixSDL_LockMutex (act_mutex); + LockRecursiveMutex (src_mutex); + LockRecursiveMutex (buf_mutex); + LockRecursiveMutex (act_mutex); for (; stream < end_stream; stream += mixer_chansize) { @@ -2222,9 +2171,9 @@ mixSDL_mix_lowq (void *userdata, uint8 *stream, sint32 len) } /* keep this order or die */ - mixSDL_UnlockMutex (act_mutex); - mixSDL_UnlockMutex (buf_mutex); - mixSDL_UnlockMutex (src_mutex); + UnlockRecursiveMutex (act_mutex); + UnlockRecursiveMutex (buf_mutex); + UnlockRecursiveMutex (src_mutex); (void) userdata; // satisfying compiler - unused arg } @@ -2238,9 +2187,9 @@ mixSDL_mix_fake (void *userdata, uint8 *stream, sint32 len) uint32 chans = MIX_FORMAT_CHANS (mixer_format); /* keep this order or die */ - mixSDL_LockMutex (src_mutex); - mixSDL_LockMutex (buf_mutex); - mixSDL_LockMutex (act_mutex); + LockRecursiveMutex (src_mutex); + LockRecursiveMutex (buf_mutex); + LockRecursiveMutex (act_mutex); for (; stream < end_stream; stream += mixer_chansize) { @@ -2264,9 +2213,9 @@ mixSDL_mix_fake (void *userdata, uint8 *stream, sint32 len) } /* keep this order or die */ - mixSDL_UnlockMutex (act_mutex); - mixSDL_UnlockMutex (buf_mutex); - mixSDL_UnlockMutex (src_mutex); + UnlockRecursiveMutex (act_mutex); + UnlockRecursiveMutex (buf_mutex); + UnlockRecursiveMutex (src_mutex); (void) userdata; // satisfying compiler - unused arg } diff --git a/sc2/src/sc2code/libs/sound/mixsdl/mixerint.h b/sc2/src/sc2code/libs/sound/mixsdl/mixerint.h index 1ca48ff3b..e242c9e8f 100644 --- a/sc2/src/sc2code/libs/sound/mixsdl/mixerint.h +++ b/sc2/src/sc2code/libs/sound/mixsdl/mixerint.h @@ -82,21 +82,6 @@ static void mixSDL_SourceDeactivate (mixSDL_Source* src); static __inline__ bool mixSDL_CheckBufferState (mixSDL_Buffer *buf, const char* FuncName); -/* Reentrant mutex */ -typedef struct -{ - Semaphore sem; - uint32 thread_id; - uint32 locks; - -} mixSDL_Mutex_info; -typedef mixSDL_Mutex_info *mixSDL_Mutex; - -static void mixSDL_InitMutex (mixSDL_Mutex mtx, char* name); -static void mixSDL_TermMutex (mixSDL_Mutex mtx); -static void mixSDL_LockMutex (mixSDL_Mutex mtx); -static void mixSDL_UnlockMutex (mixSDL_Mutex mtx); - /* Clipping boundaries */ #define MIX_S16_MAX ((double) SINT16_MAX) #define MIX_S16_MIN ((double) SINT16_MIN) diff --git a/sc2/src/sc2code/libs/threadlib.h b/sc2/src/sc2code/libs/threadlib.h index 9ca91a644..4f0af8190 100644 --- a/sc2/src/sc2code/libs/threadlib.h +++ b/sc2/src/sc2code/libs/threadlib.h @@ -133,6 +133,13 @@ void DestroyMutex (Mutex sem); int LockMutex (Mutex sem); void UnlockMutex (Mutex sem); +typedef void *RecursiveMutex; +RecursiveMutex CreateRecursiveMutex (const char *name); +void DestroyRecursiveMutex (RecursiveMutex m); +void LockRecursiveMutex (RecursiveMutex m); +void UnlockRecursiveMutex (RecursiveMutex m); +int GetRecursiveMutexDepth (RecursiveMutex m); + typedef void *CrossThreadMutex; CrossThreadMutex CreateCrossThreadMutex (const char *name); void DestroyCrossThreadMutex (CrossThreadMutex ctm); diff --git a/sc2/src/sc2code/libs/threads/sdl/sdlthreads.c b/sc2/src/sc2code/libs/threads/sdl/sdlthreads.c index 3fbd2c31b..49ebc3c88 100644 --- a/sc2/src/sc2code/libs/threads/sdl/sdlthreads.c +++ b/sc2/src/sc2code/libs/threads/sdl/sdlthreads.c @@ -87,13 +87,86 @@ SDLWrapper_WaitCondVar (CondVar cv) { } } +/* Code for recursive mutexes. Adapted from mixSDL code, which was adapted from the + original DCQ code. */ +/* TODO: Make these be forwarded calls instead of just implementations of threadlib.h functions. */ +/* TODO: Remove the names when compiling under release mode. */ + +typedef struct _recm { + SDL_mutex *mutex; + Uint32 thread_id; + Uint32 locks; + const char *name; +} RecM; + +RecursiveMutex +CreateRecursiveMutex (const char *name) +{ + RecM *mtx = (RecM *) HMalloc (sizeof (struct _recm)); + + mtx->thread_id = 0; + mtx->mutex = SDL_CreateMutex (); + mtx->name = name; + mtx->locks = 0; + return (RecursiveMutex) mtx; +} + +void +DestroyRecursiveMutex (RecursiveMutex val) +{ + RecM *mtx = (RecM *)val; + SDL_DestroyMutex (mtx->mutex); + HFree (mtx); +} + +void +LockRecursiveMutex (RecursiveMutex val) +{ + RecM *mtx = (RecM *)val; + Uint32 thread_id = SDL_ThreadID(); + if (mtx->thread_id != thread_id) + { + while (SDL_mutexP (mtx->mutex)) + TaskSwitch (); + mtx->thread_id = thread_id; + } + mtx->locks++; +} + +void +UnlockRecursiveMutex (RecursiveMutex val) +{ + RecM *mtx = (RecM *)val; + Uint32 thread_id = SDL_ThreadID(); + if (mtx->thread_id != thread_id) + { + fprintf (stderr, "%8x attempted to unlock %s when it didn't hold it\n", thread_id, mtx->name); + } + else + { + mtx->locks--; + if (!mtx->locks) + { + mtx->thread_id = 0; + SDL_mutexV (mtx->mutex); + } + } +} + +int +GetRecursiveMutexDepth (RecursiveMutex val) +{ + RecM *mtx = (RecM *)val; + return mtx->locks; +} + /* Code for cross-thread mutexes. The prototypes for these functions are in threadlib.h. */ typedef struct _ctm { SDL_mutex *mutex; SDL_cond *cond; const char *name; - BOOLEAN locked; + Uint32 locker; } _NativeCTM; CrossThreadMutex @@ -103,7 +176,7 @@ CreateCrossThreadMutex (const char *name) result->mutex = SDL_CreateMutex (); result->cond = SDL_CreateCond (); result->name = name; - result->locked = FALSE; + result->locker = 0; return (CrossThreadMutex)result; } @@ -128,13 +201,13 @@ LockCrossThreadMutex (CrossThreadMutex val) fprintf (stderr, "LockCrossThreadMutex failed to lock internal mutex in %s!\n", ctm->name); return -1; } - while (ctm->locked) + while (ctm->locker) { // fprintf (stderr, "Thread %8x goes to sleep, waiting on %s\n", SDL_ThreadID (), ctm->name); SDL_CondWait (ctm->cond, ctm->mutex); - // fprintf (stderr, "Thread %8x awakens.\n", SDL_ThreadID ()); + // fprintf (stderr, "Thread %8x awakens, acquires %s.\n", SDL_ThreadID (), ctm->name); } - ctm->locked = TRUE; + ctm->locker = SDL_ThreadID (); SDL_mutexV (ctm->mutex); return 0; /* success */ } @@ -148,9 +221,13 @@ UnlockCrossThreadMutex (CrossThreadMutex val) fprintf (stderr, "UnlockCrossThreadMutex failed to lock internal mutex in %s!\n", ctm->name); return; } - if (ctm->locked) + if (ctm->locker) { - ctm->locked = FALSE; + if (ctm->locker != SDL_ThreadID ()) + { + fprintf (stderr, "Cross-thread unlock on %s.\n", ctm->name); + } + ctm->locker = 0; SDL_CondSignal (ctm->cond); } else