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:
@@ -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
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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 ();
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user