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:
- 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
+3 -1
View File
@@ -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);
@@ -36,8 +36,6 @@ InitGraphics (int argc, char* argv[], COUNT KbytesRequired)
{
BOOLEAN ret;
TFB_DrawCommandQueue_Create ();
LoadDisplay (&_pCurDisplay);
ActivateDisplay ();
+24 -59
View File
@@ -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,17 +111,17 @@ 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;
@@ -168,10 +129,14 @@ TFB_DrawCommandQueue_Create()
DrawCommandQueue.Batching = 0;
DrawCommandQueue.FullSize = 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
@@ -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
@@ -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 ();
}
+82 -133
View File
@@ -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
}
@@ -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)
+7
View File
@@ -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);
+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. */
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