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
This commit is contained in:
mcmartin
2003-09-14 02:23:08 +00:00
parent e9c78782e7
commit c967decff0
9 changed files with 211 additions and 224 deletions
+1
View File
@@ -1,4 +1,5 @@
Changes towards version 0.4: Changes towards version 0.4:
- Abstracted the recursive mutexes in MixSDL and DCQ code -Michael
- Introduced a new synchronization construct (CrossThreadMutex) and - Introduced a new synchronization construct (CrossThreadMutex) and
migrated the GraphicsSem and clock_sem over to it (#359) -Michael migrated the GraphicsSem and clock_sem over to it (#359) -Michael
- Replaced thread-local Semaphores with Mutexes (#359) -Michael - Replaced thread-local Semaphores with Mutexes (#359) -Michael
+3 -1
View File
@@ -142,7 +142,9 @@ typedef struct tfb_drawcommandqueue
volatile int Size; volatile int Size;
} TFB_DrawCommandQueue; } TFB_DrawCommandQueue;
void TFB_DrawCommandQueue_Create (void); void Init_DrawCommandQueue (void);
void Uninit_DrawCommandQueue (void);
void TFB_BatchGraphics (void); void TFB_BatchGraphics (void);
@@ -36,8 +36,6 @@ InitGraphics (int argc, char* argv[], COUNT KbytesRequired)
{ {
BOOLEAN ret; BOOLEAN ret;
TFB_DrawCommandQueue_Create ();
LoadDisplay (&_pCurDisplay); LoadDisplay (&_pCurDisplay);
ActivateDisplay (); ActivateDisplay ();
+31 -66
View File
@@ -24,37 +24,12 @@
#include "libs/graphics/drawcmd.h" #include "libs/graphics/drawcmd.h"
#include "libs/graphics/sdl/dcqueue.h" #include "libs/graphics/sdl/dcqueue.h"
static Mutex DCQ_lock; static RecursiveMutex DCQ_Mutex;
// variables for making the DCQ lock re-entrant
static int DCQ_locking_depth = 0;
static Uint32 DCQ_locking_thread = 0;
TFB_DrawCommand DCQ[DCQ_MAX]; TFB_DrawCommand DCQ[DCQ_MAX];
TFB_DrawCommandQueue DrawCommandQueue; 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. // Wait for the queue to be emptied.
static void static void
TFB_WaitForSpace (int requested_slots) TFB_WaitForSpace (int requested_slots)
@@ -64,19 +39,19 @@ TFB_WaitForSpace (int requested_slots)
// Restore the DCQ locking level. I *think* this is // Restore the DCQ locking level. I *think* this is
// always 1, but... // always 1, but...
TFB_BatchReset (); TFB_BatchReset ();
old_depth = DCQ_locking_depth; old_depth = GetRecursiveMutexDepth (DCQ_Mutex);
for (i = 0; i < old_depth; i++) for (i = 0; i < old_depth; i++)
Unlock_DCQ (); UnlockRecursiveMutex (DCQ_Mutex);
WaitCondVar (RenderingCond); WaitCondVar (RenderingCond);
for (i = 0; i < old_depth; i++) 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); fprintf (stderr, "DCQ clear (Size = %d, FullSize = %d). Continuing.\n", DrawCommandQueue.Size, DrawCommandQueue.FullSize);
} }
void void
Lock_DCQ (int slots) Lock_DCQ (int slots)
{ {
_lock (); LockRecursiveMutex (DCQ_Mutex);
while (DrawCommandQueue.FullSize >= DCQ_MAX - slots) while (DrawCommandQueue.FullSize >= DCQ_MAX - slots)
{ {
TFB_WaitForSpace (slots); TFB_WaitForSpace (slots);
@@ -86,21 +61,7 @@ Lock_DCQ (int slots)
void void
Unlock_DCQ (void) Unlock_DCQ (void)
{ {
Uint32 current_thread = SDL_ThreadID (); UnlockRecursiveMutex (DCQ_Mutex);
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);
}
}
} }
// Always have the DCQ locked when calling this. // Always have the DCQ locked when calling this.
@@ -127,21 +88,21 @@ Synchronize_DCQ (void)
void void
TFB_BatchGraphics (void) TFB_BatchGraphics (void)
{ {
_lock (); LockRecursiveMutex (DCQ_Mutex);
DrawCommandQueue.Batching++; DrawCommandQueue.Batching++;
Unlock_DCQ (); UnlockRecursiveMutex (DCQ_Mutex);
} }
void void
TFB_UnbatchGraphics (void) TFB_UnbatchGraphics (void)
{ {
_lock (); LockRecursiveMutex (DCQ_Mutex);
if (DrawCommandQueue.Batching) if (DrawCommandQueue.Batching)
{ {
DrawCommandQueue.Batching--; DrawCommandQueue.Batching--;
} }
Synchronize_DCQ (); Synchronize_DCQ ();
Unlock_DCQ (); UnlockRecursiveMutex (DCQ_Mutex);
} }
// Cancel all pending batch operations, making them unbatched. This will // Cancel all pending batch operations, making them unbatched. This will
@@ -150,28 +111,32 @@ TFB_UnbatchGraphics (void)
void void
TFB_BatchReset (void) TFB_BatchReset (void)
{ {
_lock (); LockRecursiveMutex (DCQ_Mutex);
DrawCommandQueue.Batching = 0; DrawCommandQueue.Batching = 0;
Synchronize_DCQ (); Synchronize_DCQ ();
Unlock_DCQ (); UnlockRecursiveMutex (DCQ_Mutex);
} }
// Draw Command Queue Stuff // Draw Command Queue Stuff
void void
TFB_DrawCommandQueue_Create() Init_DrawCommandQueue (void)
{ {
DrawCommandQueue.Back = 0; DrawCommandQueue.Back = 0;
DrawCommandQueue.Front = 0; DrawCommandQueue.Front = 0;
DrawCommandQueue.InsertionPoint = 0; DrawCommandQueue.InsertionPoint = 0;
DrawCommandQueue.Batching = 0; DrawCommandQueue.Batching = 0;
DrawCommandQueue.FullSize = 0; DrawCommandQueue.FullSize = 0;
DrawCommandQueue.Size = 0; DrawCommandQueue.Size = 0;
DCQ_locking_depth = 0;
DCQ_locking_thread = 0;
DCQ_lock = CreateMutex (); DCQ_Mutex = CreateRecursiveMutex ("DCQ");
}
void
Uninit_DrawCommandQueue (void)
{
DestroyRecursiveMutex (DCQ_Mutex);
} }
void void
@@ -188,7 +153,7 @@ TFB_DrawCommandQueue_Push (TFB_DrawCommand* Command)
int int
TFB_DrawCommandQueue_Pop (TFB_DrawCommand *target) TFB_DrawCommandQueue_Pop (TFB_DrawCommand *target)
{ {
_lock (); LockRecursiveMutex (DCQ_Mutex);
if (DrawCommandQueue.Size == 0) if (DrawCommandQueue.Size == 0)
{ {
@@ -209,7 +174,7 @@ TFB_DrawCommandQueue_Pop (TFB_DrawCommand *target)
DrawCommandQueue.Size--; DrawCommandQueue.Size--;
DrawCommandQueue.FullSize--; DrawCommandQueue.FullSize--;
Unlock_DCQ (); UnlockRecursiveMutex (DCQ_Mutex);
return 1; return 1;
} }
@@ -217,14 +182,14 @@ TFB_DrawCommandQueue_Pop (TFB_DrawCommand *target)
void void
TFB_DrawCommandQueue_Clear () TFB_DrawCommandQueue_Clear ()
{ {
_lock (); LockRecursiveMutex (DCQ_Mutex);
DrawCommandQueue.Size = 0; DrawCommandQueue.Size = 0;
DrawCommandQueue.Front = 0; DrawCommandQueue.Front = 0;
DrawCommandQueue.Back = 0; DrawCommandQueue.Back = 0;
DrawCommandQueue.Batching = 0; DrawCommandQueue.Batching = 0;
DrawCommandQueue.FullSize = 0; DrawCommandQueue.FullSize = 0;
DrawCommandQueue.InsertionPoint = 0; DrawCommandQueue.InsertionPoint = 0;
Unlock_DCQ (); UnlockRecursiveMutex (DCQ_Mutex);
} }
void void
@@ -93,6 +93,8 @@ TFB_InitGraphics (int driver, int flags, int width, int height, int bpp)
if (flags & TFB_GFXFLAGS_FULLSCREEN) if (flags & TFB_GFXFLAGS_FULLSCREEN)
SDL_ShowCursor (SDL_DISABLE); SDL_ShowCursor (SDL_DISABLE);
Init_DrawCommandQueue ();
TFB_FlushPaletteCache (); TFB_FlushPaletteCache ();
TFB_DrawCanvas_Initialize (); TFB_DrawCanvas_Initialize ();
@@ -102,6 +104,7 @@ TFB_InitGraphics (int driver, int flags, int width, int height, int bpp)
void void
TFB_UninitGraphics (void) TFB_UninitGraphics (void)
{ {
Uninit_DrawCommandQueue ();
SDL_Quit (); SDL_Quit ();
} }
+82 -133
View File
@@ -61,13 +61,12 @@ static mixSDL_Quality mixer_quality;
static uint32 mixer_datasize; static uint32 mixer_datasize;
static sint32 *mixer_data = 0; static sint32 *mixer_data = 0;
mixSDL_Mutex_info mixer_mutexes[3];
/* when locking more than one mutex /* when locking more than one mutex
* you must lock them in this order * you must lock them in this order
*/ */
static mixSDL_Mutex src_mutex = mixer_mutexes + 0; static RecursiveMutex src_mutex;
static mixSDL_Mutex buf_mutex = mixer_mutexes + 1; static RecursiveMutex buf_mutex;
static mixSDL_Mutex act_mutex = mixer_mutexes + 2; static RecursiveMutex act_mutex;
#define MAX_SOURCES 8 #define MAX_SOURCES 8
mixSDL_Source *active_sources[MAX_SOURCES]; mixSDL_Source *active_sources[MAX_SOURCES];
@@ -77,56 +76,6 @@ mixSDL_Source *active_sources[MAX_SOURCES];
* Internals * 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 static void
mixSDL_SetError (uint32 error) 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_datasize = samples_buf * mixer_spec.channels * 2;
mixer_data = (sint32 *) HMalloc (sizeof (uint32) * mixer_datasize); mixer_data = (sint32 *) HMalloc (sizeof (uint32) * mixer_datasize);
mixSDL_InitMutex (src_mutex, "mixSDL_SourceMutex"); src_mutex = CreateRecursiveMutex("mixSDL_SourceMutex");
mixSDL_InitMutex (buf_mutex, "mixSDL_BufferMutex"); buf_mutex = CreateRecursiveMutex("mixSDL_BufferMutex");
mixSDL_InitMutex (act_mutex, "mixSDL_ActiveMutex"); act_mutex = CreateRecursiveMutex("mixSDL_ActiveMutex");
audio_opened = 1; audio_opened = 1;
mixer_driver->PauseAudio (0); mixer_driver->PauseAudio (0);
@@ -286,9 +235,9 @@ mixSDL_CloseAudio (void)
mixer_data = 0; mixer_data = 0;
} }
mixSDL_TermMutex (src_mutex); DestroyRecursiveMutex (src_mutex);
mixSDL_TermMutex (buf_mutex); DestroyRecursiveMutex (buf_mutex);
mixSDL_TermMutex (act_mutex); DestroyRecursiveMutex (act_mutex);
} }
--audio_opened; --audio_opened;
} }
@@ -378,7 +327,7 @@ mixSDL_DeleteSources (uint32 n, mixSDL_Object *psrcobj)
return; return;
} }
mixSDL_LockMutex (src_mutex); LockRecursiveMutex (src_mutex);
/* check to make sure we can delete all sources */ /* check to make sure we can delete all sources */
for (i = n, pcurobj = psrcobj; i && pcurobj; i--, pcurobj++) 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 */ /* check if really is a source */
@@ -436,9 +385,9 @@ mixSDL_IsSource (mixSDL_Object srcobj)
if (!src) if (!src)
return false; return false;
mixSDL_LockMutex (src_mutex); LockRecursiveMutex (src_mutex);
ret = src->magic == mixSDL_srcMagic; ret = src->magic == mixSDL_srcMagic;
mixSDL_UnlockMutex (src_mutex); UnlockRecursiveMutex (src_mutex);
return ret; return ret;
} }
@@ -459,7 +408,7 @@ mixSDL_Sourcei (mixSDL_Object srcobj, mixSDL_SourceProp pname,
return; return;
} }
mixSDL_LockMutex (src_mutex); LockRecursiveMutex (src_mutex);
if (src->magic != mixSDL_srcMagic) 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 */ /* set source float property */
@@ -530,7 +479,7 @@ mixSDL_Sourcef (mixSDL_Object srcobj, mixSDL_SourceProp pname, float value)
return; return;
} }
mixSDL_LockMutex (src_mutex); LockRecursiveMutex (src_mutex);
if (src->magic != mixSDL_srcMagic) 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) */ /* set source float array property (CURRENTLY NOT IMPLEMENTED) */
@@ -580,7 +529,7 @@ mixSDL_GetSourcei (mixSDL_Object srcobj, mixSDL_SourceProp pname,
return; return;
} }
mixSDL_LockMutex (src_mutex); LockRecursiveMutex (src_mutex);
if (src->magic != mixSDL_srcMagic) 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 */ /* get source float property */
@@ -634,7 +583,7 @@ mixSDL_GetSourcef (mixSDL_Object srcobj, mixSDL_SourceProp pname,
return; return;
} }
mixSDL_LockMutex (src_mutex); LockRecursiveMutex (src_mutex);
if (src->magic != mixSDL_srcMagic) 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 */ /* start the source; add it to active array */
@@ -674,7 +623,7 @@ mixSDL_SourcePlay (mixSDL_Object srcobj)
return; return;
} }
mixSDL_LockMutex (src_mutex); LockRecursiveMutex (src_mutex);
if (src->magic != mixSDL_srcMagic) if (src->magic != mixSDL_srcMagic)
{ {
@@ -694,7 +643,7 @@ mixSDL_SourcePlay (mixSDL_Object srcobj)
src->state = MIX_PLAYING; src->state = MIX_PLAYING;
} }
mixSDL_UnlockMutex (src_mutex); UnlockRecursiveMutex (src_mutex);
} }
/* stop the source; remove it from active array and requeue buffers */ /* stop the source; remove it from active array and requeue buffers */
@@ -712,7 +661,7 @@ mixSDL_SourceRewind (mixSDL_Object srcobj)
return; return;
} }
mixSDL_LockMutex (src_mutex); LockRecursiveMutex (src_mutex);
if (src->magic != mixSDL_srcMagic) if (src->magic != mixSDL_srcMagic)
{ {
@@ -726,7 +675,7 @@ mixSDL_SourceRewind (mixSDL_Object srcobj)
mixSDL_SourceRewind_internal (src); mixSDL_SourceRewind_internal (src);
} }
mixSDL_UnlockMutex (src_mutex); UnlockRecursiveMutex (src_mutex);
} }
/* pause the source; keep in active array */ /* pause the source; keep in active array */
@@ -744,7 +693,7 @@ mixSDL_SourcePause (mixSDL_Object srcobj)
return; return;
} }
mixSDL_LockMutex (src_mutex); LockRecursiveMutex (src_mutex);
if (src->magic != mixSDL_srcMagic) if (src->magic != mixSDL_srcMagic)
{ {
@@ -760,7 +709,7 @@ mixSDL_SourcePause (mixSDL_Object srcobj)
src->state = MIX_PAUSED; src->state = MIX_PAUSED;
} }
mixSDL_UnlockMutex (src_mutex); UnlockRecursiveMutex (src_mutex);
} }
/* stop the source; remove it from active array /* stop the source; remove it from active array
@@ -780,7 +729,7 @@ mixSDL_SourceStop (mixSDL_Object srcobj)
return; return;
} }
mixSDL_LockMutex (src_mutex); LockRecursiveMutex (src_mutex);
if (src->magic != mixSDL_srcMagic) if (src->magic != mixSDL_srcMagic)
{ {
@@ -797,7 +746,7 @@ mixSDL_SourceStop (mixSDL_Object srcobj)
src->state = MIX_STOPPED; src->state = MIX_STOPPED;
} }
mixSDL_UnlockMutex (src_mutex); UnlockRecursiveMutex (src_mutex);
} }
/* queue buffers on the source */ /* queue buffers on the source */
@@ -819,7 +768,7 @@ mixSDL_SourceQueueBuffers (mixSDL_Object srcobj, uint32 n,
return; return;
} }
mixSDL_LockMutex (buf_mutex); LockRecursiveMutex (buf_mutex);
/* check to make sure we can safely queue all buffers */ /* check to make sure we can safely queue all buffers */
for (i = n, pobj = pbufobj; i; i--, pobj++) for (i = n, pobj = pbufobj; i; i--, pobj++)
{ {
@@ -830,12 +779,12 @@ mixSDL_SourceQueueBuffers (mixSDL_Object srcobj, uint32 n,
break; break;
} }
} }
mixSDL_UnlockMutex (buf_mutex); UnlockRecursiveMutex (buf_mutex);
if (i == 0) if (i == 0)
{ /* all buffers checked out */ { /* all buffers checked out */
mixSDL_LockMutex (src_mutex); LockRecursiveMutex (src_mutex);
mixSDL_LockMutex (buf_mutex); LockRecursiveMutex (buf_mutex);
if (src->magic != mixSDL_srcMagic) if (src->magic != mixSDL_srcMagic)
{ {
@@ -866,8 +815,8 @@ mixSDL_SourceQueueBuffers (mixSDL_Object srcobj, uint32 n,
} }
} }
mixSDL_UnlockMutex (buf_mutex); UnlockRecursiveMutex (buf_mutex);
mixSDL_UnlockMutex (src_mutex); UnlockRecursiveMutex (src_mutex);
} }
} }
@@ -890,7 +839,7 @@ mixSDL_SourceUnqueueBuffers (mixSDL_Object srcobj, uint32 n,
return; return;
} }
mixSDL_LockMutex (src_mutex); LockRecursiveMutex (src_mutex);
if (src->magic != mixSDL_srcMagic) if (src->magic != mixSDL_srcMagic)
{ {
@@ -905,7 +854,7 @@ mixSDL_SourceUnqueueBuffers (mixSDL_Object srcobj, uint32 n,
} }
else else
{ {
mixSDL_LockMutex (buf_mutex); LockRecursiveMutex (buf_mutex);
/* check to make sure we can unqueue all buffers */ /* check to make sure we can unqueue all buffers */
for (i = n, curbuf = src->firstqueued; 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; return;
} }
mixSDL_LockMutex (buf_mutex); LockRecursiveMutex (buf_mutex);
for (buf = src->firstqueued; buf; buf = nextbuf) for (buf = src->firstqueued; buf; buf = nextbuf)
{ {
@@ -987,7 +936,7 @@ mixSDL_SourceUnqueueAll (mixSDL_Source *src)
buf->next = 0; buf->next = 0;
} }
mixSDL_UnlockMutex (buf_mutex); UnlockRecursiveMutex (buf_mutex);
src->firstqueued = 0; src->firstqueued = 0;
src->nextqueued = 0; src->nextqueued = 0;
@@ -1005,7 +954,7 @@ mixSDL_SourceActivate (mixSDL_Source* src)
{ {
uint32 i; uint32 i;
mixSDL_LockMutex (act_mutex); LockRecursiveMutex (act_mutex);
#ifdef DEBUG #ifdef DEBUG
/* check active sources, see if this source is there already */ /* check active sources, see if this source is there already */
@@ -1015,7 +964,7 @@ mixSDL_SourceActivate (mixSDL_Source* src)
{ /* source found */ { /* source found */
fprintf (stderr, "mixSDL_SourceActivate(): " fprintf (stderr, "mixSDL_SourceActivate(): "
"source already active in slot %u\n", i); "source already active in slot %u\n", i);
mixSDL_UnlockMutex (act_mutex); UnlockRecursiveMutex (act_mutex);
return; return;
} }
#endif #endif
@@ -1035,7 +984,7 @@ mixSDL_SourceActivate (mixSDL_Source* src)
} }
#endif #endif
mixSDL_UnlockMutex (act_mutex); UnlockRecursiveMutex (act_mutex);
} }
/* remove the source from the active array */ /* remove the source from the active array */
@@ -1044,7 +993,7 @@ mixSDL_SourceDeactivate (mixSDL_Source* src)
{ {
uint32 i; uint32 i;
mixSDL_LockMutex (act_mutex); LockRecursiveMutex (act_mutex);
/* check active sources, see if this source is there */ /* check active sources, see if this source is there */
for (i = 0; i < MAX_SOURCES && active_sources[i] != src; i++) for (i = 0; i < MAX_SOURCES && active_sources[i] != src; i++)
@@ -1060,7 +1009,7 @@ mixSDL_SourceDeactivate (mixSDL_Source* src)
} }
#endif #endif
mixSDL_UnlockMutex (act_mutex); UnlockRecursiveMutex (act_mutex);
} }
static void static void
@@ -1082,7 +1031,7 @@ mixSDL_SourceStop_internal (mixSDL_Source *src)
} }
#endif #endif
mixSDL_LockMutex (buf_mutex); LockRecursiveMutex (buf_mutex);
/* find last 'processed' buffer */ /* find last 'processed' buffer */
for (buf = src->firstqueued; for (buf = src->firstqueued;
@@ -1112,7 +1061,7 @@ mixSDL_SourceStop_internal (mixSDL_Source *src)
src->curbufofs = 0; src->curbufofs = 0;
src->curbufdelta = 0; src->curbufdelta = 0;
mixSDL_UnlockMutex (buf_mutex); UnlockRecursiveMutex (buf_mutex);
} }
static void static void
@@ -1124,7 +1073,7 @@ mixSDL_SourceRewind_internal (mixSDL_Source *src)
if (src->state >= MIX_PLAYING) if (src->state >= MIX_PLAYING)
mixSDL_SourceDeactivate (src); mixSDL_SourceDeactivate (src);
mixSDL_LockMutex (buf_mutex); LockRecursiveMutex (buf_mutex);
for (buf = src->firstqueued; for (buf = src->firstqueued;
buf && buf->state != MIX_BUF_QUEUED; buf && buf->state != MIX_BUF_QUEUED;
@@ -1133,7 +1082,7 @@ mixSDL_SourceRewind_internal (mixSDL_Source *src)
buf->state = MIX_BUF_QUEUED; buf->state = MIX_BUF_QUEUED;
} }
mixSDL_UnlockMutex (buf_mutex); UnlockRecursiveMutex (buf_mutex);
src->curbufofs = 0; src->curbufofs = 0;
src->curbufdelta = 0; src->curbufdelta = 0;
@@ -1360,7 +1309,7 @@ mixSDL_DeleteBuffers (uint32 n, mixSDL_Object *pbufobj)
return; return;
} }
mixSDL_LockMutex (buf_mutex); LockRecursiveMutex (buf_mutex);
/* check to make sure we can delete all buffers */ /* check to make sure we can delete all buffers */
for (i = n, pcurobj = pbufobj; i && pcurobj; i--, pcurobj++) for (i = n, pcurobj = pbufobj; i && pcurobj; i--, pcurobj++)
@@ -1414,7 +1363,7 @@ mixSDL_DeleteBuffers (uint32 n, mixSDL_Object *pbufobj)
*pbufobj = 0; *pbufobj = 0;
} }
} }
mixSDL_UnlockMutex (buf_mutex); UnlockRecursiveMutex (buf_mutex);
} }
/* check if really a buffer object */ /* check if really a buffer object */
@@ -1427,9 +1376,9 @@ mixSDL_IsBuffer (mixSDL_Object bufobj)
if (!buf) if (!buf)
return false; return false;
mixSDL_LockMutex (buf_mutex); LockRecursiveMutex (buf_mutex);
ret = buf->magic == mixSDL_bufMagic; ret = buf->magic == mixSDL_bufMagic;
mixSDL_UnlockMutex (buf_mutex); UnlockRecursiveMutex (buf_mutex);
return ret; return ret;
} }
@@ -1450,11 +1399,11 @@ mixSDL_GetBufferi (mixSDL_Object bufobj, mixSDL_BufferProp pname,
return; return;
} }
mixSDL_LockMutex (buf_mutex); LockRecursiveMutex (buf_mutex);
if (buf->locked) if (buf->locked)
{ {
mixSDL_UnlockMutex (buf_mutex); UnlockRecursiveMutex (buf_mutex);
mixSDL_SetError (MIX_INVALID_OPERATION); mixSDL_SetError (MIX_INVALID_OPERATION);
#ifdef DEBUG #ifdef DEBUG
fprintf (stderr, "mixSDL_GetBufferi() called with locked buffer\n"); 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 */ /* fill buffer with external data */
@@ -1518,11 +1467,11 @@ mixSDL_BufferData (mixSDL_Object bufobj, uint32 format, void* data,
return; return;
} }
mixSDL_LockMutex (buf_mutex); LockRecursiveMutex (buf_mutex);
if (buf->locked) if (buf->locked)
{ {
mixSDL_UnlockMutex (buf_mutex); UnlockRecursiveMutex (buf_mutex);
mixSDL_SetError (MIX_INVALID_OPERATION); mixSDL_SetError (MIX_INVALID_OPERATION);
#ifdef DEBUG #ifdef DEBUG
fprintf (stderr, "mixSDL_BufferData() called " fprintf (stderr, "mixSDL_BufferData() called "
@@ -1582,7 +1531,7 @@ mixSDL_BufferData (mixSDL_Object bufobj, uint32 format, void* data,
{ {
/* format identical to internal */ /* format identical to internal */
buf->locked = true; buf->locked = true;
mixSDL_UnlockMutex (buf_mutex); UnlockRecursiveMutex (buf_mutex);
memcpy (buf->data, data, size); memcpy (buf->data, data, size);
if (MIX_FORMAT_SAMPSIZE (mixer_format) == 1) if (MIX_FORMAT_SAMPSIZE (mixer_format) == 1)
@@ -1593,7 +1542,7 @@ mixSDL_BufferData (mixSDL_Object bufobj, uint32 format, void* data,
*dst ^= 0x80; *dst ^= 0x80;
} }
mixSDL_LockMutex (buf_mutex); LockRecursiveMutex (buf_mutex);
buf->locked = false; buf->locked = false;
} }
else else
@@ -1607,11 +1556,11 @@ mixSDL_BufferData (mixSDL_Object bufobj, uint32 format, void* data,
conv.dstsize = dstsize; conv.dstsize = dstsize;
buf->locked = true; buf->locked = true;
mixSDL_UnlockMutex (buf_mutex); UnlockRecursiveMutex (buf_mutex);
mixSDL_ConvertBuffer_internal (&conv); mixSDL_ConvertBuffer_internal (&conv);
mixSDL_LockMutex (buf_mutex); LockRecursiveMutex (buf_mutex);
buf->locked = false; 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 */ /* keep this order or die */
mixSDL_LockMutex (src_mutex); LockRecursiveMutex (src_mutex);
mixSDL_LockMutex (buf_mutex); LockRecursiveMutex (buf_mutex);
mixSDL_LockMutex (act_mutex); LockRecursiveMutex (act_mutex);
/* first, collect data from sources and put into work-buffer */ /* first, collect data from sources and put into work-buffer */
for (data = mixer_data; data < end_data; ++data) 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 */ /* keep this order or die */
mixSDL_UnlockMutex (act_mutex); UnlockRecursiveMutex (act_mutex);
mixSDL_UnlockMutex (buf_mutex); UnlockRecursiveMutex (buf_mutex);
mixSDL_UnlockMutex (src_mutex); UnlockRecursiveMutex (src_mutex);
(void) userdata; // satisfying compiler - unused arg (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); uint32 chans = MIX_FORMAT_CHANS (mixer_format);
/* keep this order or die */ /* keep this order or die */
mixSDL_LockMutex (src_mutex); LockRecursiveMutex (src_mutex);
mixSDL_LockMutex (buf_mutex); LockRecursiveMutex (buf_mutex);
mixSDL_LockMutex (act_mutex); LockRecursiveMutex (act_mutex);
for (; stream < end_stream; stream += mixer_chansize) 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 */ /* keep this order or die */
mixSDL_UnlockMutex (act_mutex); UnlockRecursiveMutex (act_mutex);
mixSDL_UnlockMutex (buf_mutex); UnlockRecursiveMutex (buf_mutex);
mixSDL_UnlockMutex (src_mutex); UnlockRecursiveMutex (src_mutex);
(void) userdata; // satisfying compiler - unused arg (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); uint32 chans = MIX_FORMAT_CHANS (mixer_format);
/* keep this order or die */ /* keep this order or die */
mixSDL_LockMutex (src_mutex); LockRecursiveMutex (src_mutex);
mixSDL_LockMutex (buf_mutex); LockRecursiveMutex (buf_mutex);
mixSDL_LockMutex (act_mutex); LockRecursiveMutex (act_mutex);
for (; stream < end_stream; stream += mixer_chansize) 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 */ /* keep this order or die */
mixSDL_UnlockMutex (act_mutex); UnlockRecursiveMutex (act_mutex);
mixSDL_UnlockMutex (buf_mutex); UnlockRecursiveMutex (buf_mutex);
mixSDL_UnlockMutex (src_mutex); UnlockRecursiveMutex (src_mutex);
(void) userdata; // satisfying compiler - unused arg (void) userdata; // satisfying compiler - unused arg
} }
@@ -82,21 +82,6 @@ static void mixSDL_SourceDeactivate (mixSDL_Source* src);
static __inline__ bool mixSDL_CheckBufferState (mixSDL_Buffer *buf, static __inline__ bool mixSDL_CheckBufferState (mixSDL_Buffer *buf,
const char* FuncName); 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 */ /* Clipping boundaries */
#define MIX_S16_MAX ((double) SINT16_MAX) #define MIX_S16_MAX ((double) SINT16_MAX)
#define MIX_S16_MIN ((double) SINT16_MIN) #define MIX_S16_MIN ((double) SINT16_MIN)
+7
View File
@@ -133,6 +133,13 @@ void DestroyMutex (Mutex sem);
int LockMutex (Mutex sem); int LockMutex (Mutex sem);
void UnlockMutex (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; typedef void *CrossThreadMutex;
CrossThreadMutex CreateCrossThreadMutex (const char *name); CrossThreadMutex CreateCrossThreadMutex (const char *name);
void DestroyCrossThreadMutex (CrossThreadMutex ctm); void DestroyCrossThreadMutex (CrossThreadMutex ctm);
+84 -7
View File
@@ -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. */ /* Code for cross-thread mutexes. The prototypes for these functions are in threadlib.h. */
typedef struct _ctm { typedef struct _ctm {
SDL_mutex *mutex; SDL_mutex *mutex;
SDL_cond *cond; SDL_cond *cond;
const char *name; const char *name;
BOOLEAN locked; Uint32 locker;
} _NativeCTM; } _NativeCTM;
CrossThreadMutex CrossThreadMutex
@@ -103,7 +176,7 @@ CreateCrossThreadMutex (const char *name)
result->mutex = SDL_CreateMutex (); result->mutex = SDL_CreateMutex ();
result->cond = SDL_CreateCond (); result->cond = SDL_CreateCond ();
result->name = name; result->name = name;
result->locked = FALSE; result->locker = 0;
return (CrossThreadMutex)result; return (CrossThreadMutex)result;
} }
@@ -128,13 +201,13 @@ LockCrossThreadMutex (CrossThreadMutex val)
fprintf (stderr, "LockCrossThreadMutex failed to lock internal mutex in %s!\n", ctm->name); fprintf (stderr, "LockCrossThreadMutex failed to lock internal mutex in %s!\n", ctm->name);
return -1; return -1;
} }
while (ctm->locked) while (ctm->locker)
{ {
// fprintf (stderr, "Thread %8x goes to sleep, waiting on %s\n", SDL_ThreadID (), ctm->name); // fprintf (stderr, "Thread %8x goes to sleep, waiting on %s\n", SDL_ThreadID (), ctm->name);
SDL_CondWait (ctm->cond, ctm->mutex); 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); SDL_mutexV (ctm->mutex);
return 0; /* success */ return 0; /* success */
} }
@@ -148,9 +221,13 @@ UnlockCrossThreadMutex (CrossThreadMutex val)
fprintf (stderr, "UnlockCrossThreadMutex failed to lock internal mutex in %s!\n", ctm->name); fprintf (stderr, "UnlockCrossThreadMutex failed to lock internal mutex in %s!\n", ctm->name);
return; 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); SDL_CondSignal (ctm->cond);
} }
else else