Threadlib refactoring, phase 2.
This is a near-total reorganization. Full details will appear in doc/devel/threads when that document is completed. git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@1257 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
Changes towards version 0.4:
|
||||
- Major refactoring of threadlib; see doc/devel/threads -Michael
|
||||
- Downgraded the GraphicsLock to an ordinary Mutex -Michael
|
||||
- Added movie player; only movies defined are intro and ending;
|
||||
only .duk decoder present (.duk audio decoder mostly derived
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
The UQM Threading and Synchronization library
|
||||
|
||||
This document is woefully incomplete at the moment. It will be filled
|
||||
in later. It's just that the ChangeLog refers to it so I want the
|
||||
file to be here. --Michael
|
||||
|
||||
#defines
|
||||
|
||||
NAMED_SYNCHRO: When #defined, all synchronization objects are named.
|
||||
This should be kept on all the time, at least until 1.0.
|
||||
|
||||
TRACK_CONTENTION: implies NAMED_SYNCHRO. Spits out status messages
|
||||
whenever a thread goes to sleep because of an object matching
|
||||
TRACK_CONTENTION_CLASSES.
|
||||
|
||||
TRACK_CONTENTION_CLASSES: This is an ORring of enums defined in
|
||||
threadlib.h.
|
||||
|
||||
Constructs
|
||||
|
||||
- Task
|
||||
|
||||
- Thread
|
||||
|
||||
- ThreadLocal
|
||||
|
||||
- Mutex
|
||||
|
||||
- Semaphore
|
||||
|
||||
- CondVar
|
||||
|
||||
- RecursiveMutex
|
||||
@@ -783,10 +783,6 @@ SOURCE=..\sc2code\libs\threads\thrcommon.c
|
||||
|
||||
SOURCE=..\sc2code\libs\threads\thrcommon.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\sc2code\libs\threads\condbank.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "time"
|
||||
|
||||
|
||||
@@ -177,7 +177,7 @@ InitGameClock (void)
|
||||
{
|
||||
if (!InitQueue (&GLOBAL (GameClock.event_q), NUM_EVENTS, sizeof (EVENT)))
|
||||
return (FALSE);
|
||||
clock_mutex = CreateMutex ();
|
||||
clock_mutex = CreateMutex ("Clock Mutex", SYNC_CLASS_TOPLEVEL);
|
||||
GLOBAL (GameClock.month_index) = 2;
|
||||
GLOBAL (GameClock.day_index) = 17;
|
||||
GLOBAL (GameClock.year_index) = START_YEAR; /* Feb 17, START_YEAR */
|
||||
|
||||
@@ -488,7 +488,7 @@ init_xform_control (void)
|
||||
{
|
||||
XFormControl.XFormCurrent = XFormControl.XFormInsertPoint = 0;
|
||||
XFormControl.XFormsPending = FALSE;
|
||||
XFormControl.XFormLock = CreateMutex ();
|
||||
XFormControl.XFormLock = CreateMutex ("Transform Lock", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -521,7 +521,7 @@ init_communication (void)
|
||||
{
|
||||
TFB_Canvas canvas;
|
||||
|
||||
subtitle_mutex = CreateMutex ();
|
||||
subtitle_mutex = CreateMutex ("Subtitle Lock", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
|
||||
init_xform_control ();
|
||||
|
||||
canvas = TFB_DrawCanvas_New_TrueColor (SIS_SCREEN_WIDTH,
|
||||
|
||||
@@ -272,7 +272,7 @@ InitGlobData (void)
|
||||
// but it is always cleared before set, so it toggled between
|
||||
// 2 and 1, which doesn't actually do anything.
|
||||
|
||||
GLOBAL (GameClock.clock_sem) = CreateSemaphore(0, "Clock");
|
||||
GLOBAL (GameClock.clock_sem) = CreateSemaphore(0, "Clock", SYNC_CLASS_TOPLEVEL);
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -109,7 +109,7 @@ typedef struct tfb_dc_delimg
|
||||
|
||||
typedef struct tfb_dc_signal
|
||||
{
|
||||
DWORD thread;
|
||||
Semaphore sem;
|
||||
} TFB_DrawCommand_SendSignal;
|
||||
|
||||
typedef struct tfb_drawcommand
|
||||
|
||||
@@ -130,7 +130,7 @@ Init_DrawCommandQueue (void)
|
||||
DrawCommandQueue.FullSize = 0;
|
||||
DrawCommandQueue.Size = 0;
|
||||
|
||||
DCQ_Mutex = CreateRecursiveMutex ("DCQ");
|
||||
DCQ_Mutex = CreateRecursiveMutex ("DCQ", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -200,9 +200,6 @@ TFB_EnqueueDrawCommand (TFB_DrawCommand* DrawCommand)
|
||||
return;
|
||||
}
|
||||
|
||||
if (DrawCommand->Type == TFB_DRAWCOMMANDTYPE_SENDSIGNAL)
|
||||
DrawCommand->data.sendsignal.thread = CurrentThreadID ();
|
||||
|
||||
if (DrawCommand->Type <= TFB_DRAWCOMMANDTYPE_COPYTOIMAGE
|
||||
&& TYPE_GET (_CurFramePtr->TypeIndexAndFlags) == SCREEN_DRAWABLE)
|
||||
{
|
||||
|
||||
@@ -669,7 +669,7 @@ TFB_FlushGraphics () // Only call from main thread!!
|
||||
break;
|
||||
}
|
||||
case TFB_DRAWCOMMANDTYPE_SENDSIGNAL:
|
||||
SignalThread (DC.data.sendsignal.thread);
|
||||
ClearSemaphore (DC.data.sendsignal.sem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,14 +197,15 @@ void
|
||||
TFB_DrawScreen_WaitForSignal (void)
|
||||
{
|
||||
TFB_DrawCommand DrawCommand;
|
||||
int channel;
|
||||
Semaphore s;
|
||||
s = GetMyThreadLocal ()->flushSem;
|
||||
DrawCommand.Type = TFB_DRAWCOMMANDTYPE_SENDSIGNAL;
|
||||
DrawCommand.data.sendsignal.sem = s;
|
||||
Lock_DCQ (1);
|
||||
channel = FindSignalChannel ();
|
||||
TFB_BatchReset ();
|
||||
TFB_EnqueueDrawCommand(&DrawCommand);
|
||||
Unlock_DCQ();
|
||||
WaitForSignal (channel);
|
||||
SetSemaphore (s);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -247,7 +248,7 @@ TFB_Image *
|
||||
TFB_DrawImage_New (TFB_Canvas canvas)
|
||||
{
|
||||
TFB_Image *img = HMalloc (sizeof (TFB_Image));
|
||||
img->mutex = CreateMutex ();
|
||||
img->mutex = CreateMutex ("image lock", SYNC_CLASS_VIDEO);
|
||||
img->ScaledImg = NULL;
|
||||
img->MipmapImg = NULL;
|
||||
img->colormap_index = -1;
|
||||
|
||||
@@ -382,7 +382,7 @@ mem_init (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
_MemoryLock = CreateMutex ();
|
||||
_MemoryLock = CreateMutex ("memory lock", SYNC_CLASS_RESOURCE);
|
||||
LockMutex (_MemoryLock);
|
||||
|
||||
freeListHead = &extents[0];
|
||||
|
||||
@@ -209,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);
|
||||
|
||||
src_mutex = CreateRecursiveMutex("mixSDL_SourceMutex");
|
||||
buf_mutex = CreateRecursiveMutex("mixSDL_BufferMutex");
|
||||
act_mutex = CreateRecursiveMutex("mixSDL_ActiveMutex");
|
||||
src_mutex = CreateRecursiveMutex("mixSDL_SourceMutex", SYNC_CLASS_AUDIO);
|
||||
buf_mutex = CreateRecursiveMutex("mixSDL_BufferMutex", SYNC_CLASS_AUDIO);
|
||||
act_mutex = CreateRecursiveMutex("mixSDL_ActiveMutex", SYNC_CLASS_AUDIO);
|
||||
|
||||
audio_opened = 1;
|
||||
mixer_driver->PauseAudio (0);
|
||||
|
||||
@@ -129,7 +129,7 @@ TFB_mixSDL_InitSound (int driver, int flags)
|
||||
|
||||
soundSource[i].sample = NULL;
|
||||
soundSource[i].stream_should_be_playing = FALSE;
|
||||
soundSource[i].stream_mutex = CreateMutex ();
|
||||
soundSource[i].stream_mutex = CreateMutex ("MixSDL stream mutex", SYNC_CLASS_AUDIO);
|
||||
soundSource[i].sbuffer = NULL;
|
||||
soundSource[i].sbuf_start = 0;
|
||||
soundSource[i].sbuf_size = 0;
|
||||
@@ -241,7 +241,7 @@ TFB_NoSound_InitSound (int driver, int flags)
|
||||
|
||||
soundSource[i].sample = NULL;
|
||||
soundSource[i].stream_should_be_playing = FALSE;
|
||||
soundSource[i].stream_mutex = CreateMutex ();
|
||||
soundSource[i].stream_mutex = CreateMutex ("MixSDL stream mutex", SYNC_CLASS_AUDIO);
|
||||
soundSource[i].sbuffer = NULL;
|
||||
soundSource[i].sbuf_start = 0;
|
||||
soundSource[i].sbuf_size = 0;
|
||||
|
||||
@@ -89,7 +89,7 @@ TFB_alInitSound (int driver, int flags)
|
||||
|
||||
soundSource[i].sample = NULL;
|
||||
soundSource[i].stream_should_be_playing = FALSE;
|
||||
soundSource[i].stream_mutex = CreateMutex ();
|
||||
soundSource[i].stream_mutex = CreateMutex ("OpenAL stream mutex", SYNC_CLASS_AUDIO);
|
||||
soundSource[i].sbuffer = NULL;
|
||||
soundSource[i].sbuf_start = 0;
|
||||
soundSource[i].sbuf_size = 0;
|
||||
|
||||
@@ -583,7 +583,7 @@ SpliceTrack (UNICODE *TrackName, UNICODE *TrackText, UNICODE *TimeStamp, TFB_Tra
|
||||
TFB_SoundDecoder *decoder;
|
||||
TFB_SoundChainData* scd;
|
||||
|
||||
track_mutex = CreateMutex();
|
||||
track_mutex = CreateMutex("trackplayer mutex", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_AUDIO);
|
||||
sound_sample = (TFB_SoundSample *) HMalloc (sizeof (TFB_SoundSample));
|
||||
scd = (TFB_SoundChainData *) HCalloc (sizeof (TFB_SoundChainData));
|
||||
sound_sample->data = scd;
|
||||
|
||||
@@ -121,7 +121,7 @@ InitTaskSystem (void)
|
||||
int i;
|
||||
for (i = 0; i < TASK_MAX; ++i)
|
||||
{
|
||||
task_array[i].state_mutex = CreateMutex ();
|
||||
task_array[i].state_mutex = CreateMutex ("task manager lock", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_RESOURCE);
|
||||
}
|
||||
atexit (CleanupTaskSystem);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#define NAMED_SYNCHRO /* Should synchronizable objects have names? */
|
||||
// #define TRACK_CONTENTION /* Should we report when a thread sleeps on synchronize? */
|
||||
|
||||
/* TRACK_CONTENTION implies NAMED_SYNCHRO. */
|
||||
#ifdef TRACK_CONTENTION
|
||||
# ifndef NAMED_SYNCHRO
|
||||
# define NAMED_SYNCHRO
|
||||
@@ -38,12 +39,6 @@
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
# ifndef THREAD_QUEUE
|
||||
# define THREAD_QUEUE
|
||||
# endif
|
||||
# ifndef THREAD_NAMES
|
||||
# define THREAD_NAMES
|
||||
# endif
|
||||
# ifndef PROFILE_THREADS
|
||||
# define PROFILE_THREADS
|
||||
# endif
|
||||
@@ -56,25 +51,8 @@
|
||||
#define THREAD_NAMES
|
||||
#endif
|
||||
|
||||
#if defined (PROFILE_THREADS)
|
||||
# if !defined (THREAD_QUEUE)
|
||||
# define THREAD_QUEUE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined (DEBUG_TRACK_SEM)
|
||||
# if !defined (THREAD_QUEUE)
|
||||
# define THREAD_QUEUE
|
||||
# endif
|
||||
# if !defined (THREAD_NAMES)
|
||||
# define THREAD_NAMES
|
||||
# endif
|
||||
#endif
|
||||
|
||||
void InitThreadSystem (void);
|
||||
void UnInitThreadSystem (void);
|
||||
void init_cond_bank (void);
|
||||
void uninit_cond_bank (void);
|
||||
|
||||
typedef int (*ThreadFunction) (void *);
|
||||
|
||||
@@ -84,27 +62,45 @@ typedef void *Semaphore;
|
||||
typedef void *RecursiveMutex;
|
||||
typedef void *CondVar;
|
||||
|
||||
/* Local data associated with each thread */
|
||||
typedef struct _threadLocal {
|
||||
Semaphore flushSem;
|
||||
} ThreadLocal;
|
||||
|
||||
/* The classes of synchronization objects */
|
||||
|
||||
enum
|
||||
{
|
||||
SYNC_CLASS_TOPLEVEL = (1 << 0), /* Exposed to the game logic */
|
||||
SYNC_CLASS_AUDIO = (1 << 1), /* Involves the audio system */
|
||||
SYNC_CLASS_VIDEO = (1 << 2), /* Involves the video system. Very noisy because of FlushGraphics(). */
|
||||
SYNC_CLASS_RESOURCE = (1 << 3) /* Involves system resources (_MemoryLock) */
|
||||
};
|
||||
|
||||
#ifdef NAMED_SYNCHRO
|
||||
/* Logical OR of all classes we want to track. */
|
||||
#define TRACK_CONTENTION_CLASSES (SYNC_CLASS_TOPLEVEL)
|
||||
|
||||
/* Prototypes with the "name" field */
|
||||
|
||||
Thread CreateThread_Core (ThreadFunction func, void *data, SDWORD stackSize, const char *name);
|
||||
Semaphore CreateSemaphore_Core (DWORD initial, const char *name);
|
||||
Mutex CreateMutex_Core (void);
|
||||
RecursiveMutex CreateRecursiveMutex_Core (const char *name);
|
||||
CondVar CreateCondVar_Core (const char *name);
|
||||
Semaphore CreateSemaphore_Core (DWORD initial, const char *name, DWORD syncClass);
|
||||
Mutex CreateMutex_Core (const char *name, DWORD syncClass);
|
||||
RecursiveMutex CreateRecursiveMutex_Core (const char *name, DWORD syncClass);
|
||||
CondVar CreateCondVar_Core (const char *name, DWORD syncClass);
|
||||
|
||||
/* Preprocessor directives to forward to the appropriate routines */
|
||||
|
||||
#define CreateThread(func, data, stackSize, name) \
|
||||
CreateThread_Core ((func), (data), (stackSize), (name))
|
||||
#define CreateSemaphore(initial, name) \
|
||||
CreateSemaphore_Core ((initial), (name))
|
||||
#define CreateMutex() \
|
||||
CreateMutex_Core ()
|
||||
#define CreateRecursiveMutex(name) \
|
||||
CreateRecursiveMutex_Core((name))
|
||||
#define CreateCondVar(name) \
|
||||
CreateCondVar_Core ((name))
|
||||
#define CreateSemaphore(initial, name, syncClass) \
|
||||
CreateSemaphore_Core ((initial), (name), (syncClass))
|
||||
#define CreateMutex(name, syncClass) \
|
||||
CreateMutex_Core ((name), (syncClass))
|
||||
#define CreateRecursiveMutex(name, syncClass) \
|
||||
CreateRecursiveMutex_Core((name), (syncClass))
|
||||
#define CreateCondVar(name, syncClass) \
|
||||
CreateCondVar_Core ((name), (syncClass))
|
||||
|
||||
#else
|
||||
|
||||
@@ -119,19 +115,23 @@ CondVar CreateCondVar_Core (void);
|
||||
/* Preprocessor directives to forward to the appropriate routines.
|
||||
The "name" field is stripped away in preprocessing. */
|
||||
|
||||
#define CreateThread(func, data, stackSize, name) \
|
||||
#define CreateThread(func, data, stackSize, name, syncClass) \
|
||||
CreateThread_Core ((func), (data), (stackSize))
|
||||
#define CreateSemaphore(initial, name) \
|
||||
#define CreateSemaphore(initial, name, syncClass) \
|
||||
CreateSemaphore_Core ((initial))
|
||||
#define CreateMutex() \
|
||||
#define CreateMutex(name, syncClass) \
|
||||
CreateMutex_Core ()
|
||||
#define CreateRecursiveMutex(name) \
|
||||
#define CreateRecursiveMutex(name, syncClass) \
|
||||
CreateRecursiveMutex_Core()
|
||||
#define CreateCondVar(name) \
|
||||
#define CreateCondVar(name, syncClass) \
|
||||
CreateCondVar_Core ()
|
||||
|
||||
#endif
|
||||
|
||||
ThreadLocal *CreateThreadLocal (void);
|
||||
void DestroyThreadLocal (ThreadLocal *tl);
|
||||
ThreadLocal *GetMyThreadLocal (void);
|
||||
|
||||
void SleepThread (TimePeriod timePeriod);
|
||||
void SleepThreadUntil (TimeCount wakeTime);
|
||||
void TaskSwitch (void);
|
||||
@@ -157,15 +157,8 @@ int GetRecursiveMutexDepth (RecursiveMutex m);
|
||||
|
||||
void DestroyCondVar (CondVar);
|
||||
void WaitCondVar (CondVar);
|
||||
void WaitProtectedCondVar (CondVar, Mutex);
|
||||
void SignalCondVar (CondVar);
|
||||
void BroadcastCondVar (CondVar);
|
||||
|
||||
DWORD CurrentThreadID (void);
|
||||
|
||||
int FindSignalChannel ();
|
||||
void WaitForSignal (int);
|
||||
void SignalThread (DWORD);
|
||||
|
||||
#endif /* _THREADLIB_H */
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
uqm_SUBDIRS="sdl"
|
||||
uqm_CFILES="condbank.c thrcommon.c"
|
||||
uqm_CFILES="thrcommon.c"
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
//Copyright Paul Reiche, Fred Ford. 1992-2002
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* This defines the Condition Variable Bank. Individual threads may
|
||||
sleep until they are signaled by their Thread ID. If the Condition
|
||||
Variable Bank is exhausted (unlikely!) it will wait on the DCQ's
|
||||
condition variable. This may produce stuttering. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "starcon.h"
|
||||
#include "libs/threadlib.h"
|
||||
|
||||
/* The Condition Variable Bank. */
|
||||
|
||||
#define CONDVAR_BANK_SIZE 10
|
||||
|
||||
static Mutex bank_mutex;
|
||||
|
||||
static struct {
|
||||
CondVar var;
|
||||
DWORD id;
|
||||
int used;
|
||||
Mutex control;
|
||||
} bank[CONDVAR_BANK_SIZE];
|
||||
|
||||
void
|
||||
init_cond_bank ()
|
||||
{
|
||||
int i;
|
||||
bank_mutex = CreateMutex ();
|
||||
for (i = 0; i < CONDVAR_BANK_SIZE; i++)
|
||||
{
|
||||
bank[i].var = CreateCondVar ("FlushGraphics Bank");
|
||||
bank[i].id = bank[i].used = 0;
|
||||
bank[i].control = CreateMutex ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
uninit_cond_bank ()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < CONDVAR_BANK_SIZE; i++)
|
||||
{
|
||||
DestroyCondVar (bank[i].var);
|
||||
DestroyMutex (bank[i].control);
|
||||
}
|
||||
DestroyMutex (bank_mutex);
|
||||
}
|
||||
|
||||
int
|
||||
FindSignalChannel ()
|
||||
{
|
||||
int i;
|
||||
|
||||
LockMutex (bank_mutex);
|
||||
for (i = 0; i < CONDVAR_BANK_SIZE; i++)
|
||||
{
|
||||
if (!bank[i].used)
|
||||
{
|
||||
LockMutex (bank[i].control);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
WaitForSignal (int i)
|
||||
{
|
||||
DWORD me = CurrentThreadID ();
|
||||
|
||||
if (i == -1)
|
||||
{
|
||||
/* The bank is full! */
|
||||
fprintf(stderr, "Condvar bank is full, %lu is waiting on DCQ.\n", me);
|
||||
UnlockMutex (bank_mutex);
|
||||
WaitCondVar (RenderingCond);
|
||||
}
|
||||
else
|
||||
{
|
||||
bank[i].used = 1;
|
||||
bank[i].id = me;
|
||||
UnlockMutex (bank_mutex);
|
||||
// fprintf (stderr, "Thread %lu waiting on cond var %d (control: %p)\n", me, i, bank[i].control);
|
||||
WaitProtectedCondVar (bank[i].var, bank[i].control);
|
||||
// fprintf (stderr, "Thread %lu signaled via cond var %d\n", me, i);
|
||||
UnlockMutex (bank[i].control);
|
||||
LockMutex (bank_mutex);
|
||||
bank[i].used = bank[i].id = 0;
|
||||
UnlockMutex (bank_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SignalThread (DWORD id)
|
||||
{
|
||||
int i;
|
||||
LockMutex (bank_mutex);
|
||||
for (i = 0; i < CONDVAR_BANK_SIZE; i++)
|
||||
{
|
||||
if (bank[i].used && bank[i].id == id)
|
||||
{
|
||||
UnlockMutex (bank_mutex);
|
||||
// fprintf (stderr, "Blocking on var %d's control: %p\n", i, bank[i].control);
|
||||
LockMutex (bank[i].control);
|
||||
// fprintf (stderr, "Signaling var %d, thread %lu, control %p\n", i, id, bank[i].control);
|
||||
SignalCondVar (bank[i].var);
|
||||
UnlockMutex (bank[i].control);
|
||||
return;
|
||||
}
|
||||
}
|
||||
fprintf (stderr, "Warning: Couldn't find thread to signal!\n");
|
||||
UnlockMutex (bank_mutex);
|
||||
}
|
||||
@@ -38,6 +38,7 @@ typedef struct _thread {
|
||||
#ifdef PROFILE_THREADS
|
||||
int startTime;
|
||||
#endif /* PROFILE_THREADS */
|
||||
ThreadLocal *localData;
|
||||
struct _thread *next;
|
||||
} *TrueThread;
|
||||
|
||||
@@ -117,13 +118,11 @@ InitThreadSystem_SDL (void)
|
||||
#ifdef PROFILE_THREADS
|
||||
signal(SIGUSR1, SigUSR1Handler);
|
||||
#endif
|
||||
init_cond_bank ();
|
||||
}
|
||||
|
||||
void
|
||||
UnInitThreadSystem_SDL (void)
|
||||
{
|
||||
uninit_cond_bank ();
|
||||
#ifdef PROFILE_THREADS
|
||||
signal(SIGUSR1, SIG_DFL);
|
||||
#endif
|
||||
@@ -220,7 +219,7 @@ ThreadHelper (void *startInfo) {
|
||||
#endif
|
||||
|
||||
UnQueueThread (thread);
|
||||
|
||||
DestroyThreadLocal (thread->localData);
|
||||
HFree (thread);
|
||||
return result;
|
||||
}
|
||||
@@ -243,6 +242,8 @@ CreateThread_SDL (ThreadFunction func, void *data, SDWORD stackSize
|
||||
thread->startTime = GetTimeCounter ();
|
||||
#endif
|
||||
|
||||
thread->localData = CreateThreadLocal ();
|
||||
|
||||
startInfo = (struct ThreadStartInfo *) HMalloc (sizeof (*startInfo));
|
||||
startInfo->func = func;
|
||||
startInfo->data = data;
|
||||
@@ -252,6 +253,7 @@ CreateThread_SDL (ThreadFunction func, void *data, SDWORD stackSize
|
||||
thread->native = SDL_CreateThread (ThreadHelper, (void *) startInfo);
|
||||
if (!(thread->native))
|
||||
{
|
||||
DestroyThreadLocal (thread->localData);
|
||||
HFree (startInfo);
|
||||
HFree (thread);
|
||||
return NULL;
|
||||
@@ -301,13 +303,112 @@ WaitThread_SDL (Thread thread, int *status) {
|
||||
SDL_WaitThread (((TrueThread)thread)->native, status);
|
||||
}
|
||||
|
||||
ThreadLocal *
|
||||
GetMyThreadLocal_SDL (void)
|
||||
{
|
||||
TrueThread t = FindThreadInfo (SDL_ThreadID ());
|
||||
return t ? t->localData : NULL;
|
||||
}
|
||||
|
||||
/* These are the SDL implementations of the UQM synchronization objects. */
|
||||
/* TODO: Remove the names of the following data types when compiling
|
||||
* under release mode. */
|
||||
|
||||
/* Mutexes. */
|
||||
/* TODO. The w_memlib uses Mutexes right now, so we can't use HMalloc
|
||||
* or HFree. */
|
||||
* or HFree. Once that goes, this needs to change. */
|
||||
|
||||
typedef struct _mutex {
|
||||
SDL_mutex *mutex;
|
||||
#ifdef TRACK_CONTENTION
|
||||
Uint32 owner;
|
||||
#endif
|
||||
#ifdef NAMED_SYNCHRO
|
||||
const char *name;
|
||||
DWORD syncClass;
|
||||
#endif
|
||||
} Mut;
|
||||
|
||||
|
||||
Mutex
|
||||
#ifdef NAMED_SYNCHRO
|
||||
CreateMutex_SDL (const char *name, DWORD syncClass)
|
||||
#else
|
||||
CreateMutex_SDL (void)
|
||||
#endif
|
||||
{
|
||||
Mut *mutex = malloc (sizeof (Mut));
|
||||
if (mutex != NULL)
|
||||
{
|
||||
mutex->mutex = SDL_CreateMutex();
|
||||
#ifdef TRACK_CONTENTION
|
||||
mutex->owner = 0;
|
||||
#endif
|
||||
#ifdef NAMED_SYNCHRO
|
||||
mutex->name = name;
|
||||
mutex->syncClass = syncClass;
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((mutex == NULL) || (mutex->mutex == NULL))
|
||||
{
|
||||
#ifdef NAMED_SYNCHRO
|
||||
fprintf (stderr, "Could not initialize mutex '%s': aborting.\n", name);
|
||||
#else
|
||||
fprintf (stderr, "Could not initialize mutex: aborting.\n");
|
||||
#endif
|
||||
abort ();
|
||||
}
|
||||
|
||||
return mutex;
|
||||
}
|
||||
|
||||
void
|
||||
DestroyMutex_SDL (Mutex m)
|
||||
{
|
||||
Mut *mutex = (Mut *)m;
|
||||
SDL_DestroyMutex (mutex->mutex);
|
||||
free (mutex);
|
||||
}
|
||||
|
||||
void
|
||||
LockMutex_SDL (Mutex m)
|
||||
{
|
||||
Mut *mutex = (Mut *)m;
|
||||
#ifdef TRACK_CONTENTION
|
||||
/* This code isn't really quite right; race conditions between
|
||||
* check and lock remain and can produce reports of contention
|
||||
* where the thread never sleeps, or fail to report in
|
||||
* situations where it does. If tracking with perfect
|
||||
* accuracy becomes important, the TRACK_CONTENTION mutex will
|
||||
* need to handle its own wake/sleep cycles with condition
|
||||
* variables (check the history of this file for the
|
||||
* CrossThreadMutex code). This almost-measure is being added
|
||||
* because for the most part it should suffice. */
|
||||
if (mutex->owner && (mutex->syncClass & TRACK_CONTENTION_CLASSES))
|
||||
{
|
||||
fprintf (stderr, "Thread '%s' blocking on mutex '%s'\n", MyThreadName (), mutex->name);
|
||||
}
|
||||
#endif
|
||||
while (SDL_mutexP (mutex->mutex) != 0)
|
||||
{
|
||||
TaskSwitch_SDL ();
|
||||
}
|
||||
#ifdef TRACK_CONTENTION
|
||||
mutex->owner = SDL_ThreadID ();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
UnlockMutex_SDL (Mutex m)
|
||||
{
|
||||
Mut *mutex = (Mut *)m;
|
||||
#ifdef TRACK_CONTENTION
|
||||
mutex->owner = 0;
|
||||
#endif
|
||||
while (SDL_mutexV (mutex->mutex) != 0)
|
||||
{
|
||||
TaskSwitch_SDL ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Semaphores. */
|
||||
|
||||
@@ -315,21 +416,32 @@ typedef struct _sem {
|
||||
SDL_sem *sem;
|
||||
#ifdef NAMED_SYNCHRO
|
||||
const char *name;
|
||||
DWORD syncClass;
|
||||
#endif
|
||||
} Sem;
|
||||
|
||||
Semaphore
|
||||
CreateSemaphore_SDL (DWORD initial
|
||||
#ifdef NAMED_SYNCHRO
|
||||
, const char *name
|
||||
, const char *name, DWORD syncClass
|
||||
#endif
|
||||
)
|
||||
{
|
||||
Sem *sem = (Sem *) HMalloc (sizeof (struct _sem));
|
||||
#ifdef NAMED_SYNCHRO
|
||||
sem->name = name;
|
||||
sem->syncClass = syncClass;
|
||||
#endif
|
||||
sem->sem = SDL_CreateSemaphore (initial);
|
||||
if (sem->sem == NULL)
|
||||
{
|
||||
#ifdef NAMED_SYNCHRO
|
||||
fprintf (stderr, "Could not initialize semaphore '%s': aborting.\n", name);
|
||||
#else
|
||||
fprintf (stderr, "Could not initialize semaphore: aborting.\n");
|
||||
#endif
|
||||
abort ();
|
||||
}
|
||||
return sem;
|
||||
}
|
||||
|
||||
@@ -347,9 +459,9 @@ SetSemaphore_SDL (Semaphore s)
|
||||
Sem *sem = (Sem *)s;
|
||||
#ifdef TRACK_CONTENTION
|
||||
BOOLEAN contention = !(SDL_SemValue (sem->sem));
|
||||
if (contention)
|
||||
if (contention && (sem->syncClass & TRACK_CONTENTION_CLASSES))
|
||||
{
|
||||
fprintf (stderr, "Thread '%s' goes to sleep, waiting on semaphore '%s'\n", MyThreadName (), sem->name);
|
||||
fprintf (stderr, "Thread '%s' blocking on semaphore '%s'\n", MyThreadName (), sem->name);
|
||||
}
|
||||
#endif
|
||||
while (SDL_SemWait (sem->sem) == -1)
|
||||
@@ -357,7 +469,7 @@ SetSemaphore_SDL (Semaphore s)
|
||||
TaskSwitch_SDL ();
|
||||
}
|
||||
#ifdef TRACK_CONTENTION
|
||||
if (contention)
|
||||
if (contention && (sem->syncClass & TRACK_CONTENTION_CLASSES))
|
||||
{
|
||||
fprintf (stderr, "Thread '%s' awakens, released from semaphore '%s'\n", MyThreadName (), sem->name);
|
||||
}
|
||||
@@ -383,12 +495,13 @@ typedef struct _recm {
|
||||
Uint32 locks;
|
||||
#ifdef NAMED_SYNCHRO
|
||||
const char *name;
|
||||
DWORD syncClass;
|
||||
#endif
|
||||
} RecM;
|
||||
|
||||
RecursiveMutex
|
||||
#ifdef NAMED_SYNCHRO
|
||||
CreateRecursiveMutex_SDL (const char *name)
|
||||
CreateRecursiveMutex_SDL (const char *name, DWORD syncClass)
|
||||
#else
|
||||
CreateRecursiveMutex_SDL (void)
|
||||
#endif
|
||||
@@ -397,8 +510,18 @@ CreateRecursiveMutex_SDL (void)
|
||||
|
||||
mtx->thread_id = 0;
|
||||
mtx->mutex = SDL_CreateMutex ();
|
||||
if (mtx->mutex == NULL)
|
||||
{
|
||||
#ifdef NAMED_SYNCHRO
|
||||
fprintf (stderr, "Could not initialize recursive mutex '%s': aborting.\n", name);
|
||||
#else
|
||||
fprintf (stderr, "Could not initialize recursive mutex: aborting.\n");
|
||||
#endif
|
||||
abort ();
|
||||
}
|
||||
#ifdef NAMED_SYNCHRO
|
||||
mtx->name = name;
|
||||
mtx->syncClass = syncClass;
|
||||
#endif
|
||||
mtx->locks = 0;
|
||||
return (RecursiveMutex) mtx;
|
||||
@@ -420,7 +543,7 @@ LockRecursiveMutex_SDL (RecursiveMutex val)
|
||||
if (mtx->thread_id != thread_id)
|
||||
{
|
||||
#ifdef TRACK_CONTENTION
|
||||
if (mtx->thread_id)
|
||||
if (mtx->thread_id && (mtx->syncClass & TRACK_CONTENTION_CLASSES))
|
||||
{
|
||||
fprintf (stderr, "Thread '%s' blocking on '%s'\n", MyThreadName (), mtx->name);
|
||||
}
|
||||
@@ -466,12 +589,13 @@ typedef struct _cond {
|
||||
SDL_mutex *mutex;
|
||||
#ifdef NAMED_SYNCHRO
|
||||
const char *name;
|
||||
DWORD syncClass;
|
||||
#endif
|
||||
} cvar;
|
||||
|
||||
CondVar
|
||||
#ifdef NAMED_SYNCHRO
|
||||
CreateCondVar_SDL (const char *name)
|
||||
CreateCondVar_SDL (const char *name, DWORD syncClass)
|
||||
#else
|
||||
CreateCondVar_SDL (void)
|
||||
#endif
|
||||
@@ -479,8 +603,18 @@ CreateCondVar_SDL (void)
|
||||
cvar *cv = (cvar *) HMalloc (sizeof (cvar));
|
||||
cv->cond = SDL_CreateCond ();
|
||||
cv->mutex = SDL_CreateMutex ();
|
||||
if ((cv->cond == NULL) || (cv->mutex == NULL))
|
||||
{
|
||||
#ifdef NAMED_SYNCHRO
|
||||
fprintf (stderr, "Could not initialize condition variable '%s': aborting.\n", name);
|
||||
#else
|
||||
fprintf (stderr, "Could not initialize condition variable: aborting.\n");
|
||||
#endif
|
||||
abort ();
|
||||
}
|
||||
#ifdef NAMED_SYNCHRO
|
||||
cv->name = name;
|
||||
cv->syncClass = syncClass;
|
||||
#endif
|
||||
return cv;
|
||||
}
|
||||
@@ -500,33 +634,24 @@ WaitCondVar_SDL (CondVar c)
|
||||
cvar *cv = (cvar *) c;
|
||||
SDL_mutexP (cv->mutex);
|
||||
#ifdef TRACK_CONTENTION
|
||||
if (cv->syncClass & TRACK_CONTENTION_CLASSES)
|
||||
{
|
||||
fprintf (stderr, "Thread '%s' waiting for signal from '%s'\n", MyThreadName (), cv->name);
|
||||
}
|
||||
#endif
|
||||
while (SDL_CondWait (cv->cond, cv->mutex) != 0)
|
||||
{
|
||||
TaskSwitch_SDL ();
|
||||
}
|
||||
#ifdef TRACK_CONTENTION
|
||||
if (cv->syncClass & TRACK_CONTENTION_CLASSES)
|
||||
{
|
||||
fprintf (stderr, "Thread '%s' received signal from '%s', awakening.\n", MyThreadName (), cv->name);
|
||||
}
|
||||
#endif
|
||||
SDL_mutexV (cv->mutex);
|
||||
}
|
||||
|
||||
void
|
||||
WaitProtectedCondVar_SDL (CondVar c, Mutex m)
|
||||
{
|
||||
cvar *cv = (cvar *) c;
|
||||
#ifdef TRACK_CONTENTION
|
||||
fprintf (stderr, "Thread '%s' waiting for signal from '%s'\n", MyThreadName (), cv->name);
|
||||
#endif
|
||||
if (SDL_CondWait (cv->cond, m) != 0) {
|
||||
TaskSwitch_SDL ();
|
||||
}
|
||||
#ifdef TRACK_CONTENTION
|
||||
fprintf (stderr, "Thread '%s' received signal from '%s', awakening.\n", MyThreadName (), cv->name);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
SignalCondVar_SDL (CondVar c)
|
||||
{
|
||||
|
||||
@@ -25,51 +25,42 @@
|
||||
#include "libs/threadlib.h"
|
||||
#include "libs/timelib.h"
|
||||
|
||||
#define NativeGetThreadID(thread) SDL_GetThreadID ((thread))
|
||||
#define NativeThreadID() SDL_ThreadID ()
|
||||
|
||||
typedef SDL_mutex *NativeMutex;
|
||||
#define NativeCreateMutex() \
|
||||
SDL_CreateMutex ()
|
||||
#define NativeDestroyMutex(mutex) \
|
||||
SDL_DestroyMutex ((mutex))
|
||||
#define NativeLockMutex(mutex) \
|
||||
SDL_mutexP ((mutex))
|
||||
#define NativeUnlockMutex(mutex) \
|
||||
SDL_mutexV ((mutex))
|
||||
|
||||
#define NativeCurrentThreadID() \
|
||||
SDL_ThreadID ()
|
||||
|
||||
void InitThreadSystem_SDL (void);
|
||||
void UnInitThreadSystem_SDL (void);
|
||||
|
||||
#ifdef NAMED_SYNCHRO
|
||||
/* Prototypes with the "name" field */
|
||||
Thread CreateThread_SDL (ThreadFunction func, void *data, SDWORD stackSize, const char *name);
|
||||
Semaphore CreateSemaphore_SDL (DWORD initial, const char *name);
|
||||
RecursiveMutex CreateRecursiveMutex_SDL (const char *name);
|
||||
CondVar CreateCondVar_SDL (const char *name);
|
||||
Mutex CreateMutex_SDL (const char *name, DWORD syncClass);
|
||||
Semaphore CreateSemaphore_SDL (DWORD initial, const char *name, DWORD syncClass);
|
||||
RecursiveMutex CreateRecursiveMutex_SDL (const char *name, DWORD syncClass);
|
||||
CondVar CreateCondVar_SDL (const char *name, DWORD syncClass);
|
||||
#else
|
||||
/* Prototypes without the "name" field. */
|
||||
Thread CreateThread_SDL (ThreadFunction func, void *data, SDWORD stackSize);
|
||||
Mutex CreateMutex_SDL (void);
|
||||
Semaphore CreateSemaphore_SDL (DWORD initial);
|
||||
RecursiveMutex CreateRecursiveMutex_SDL (void);
|
||||
CondVar CreateCondVar_SDL (void);
|
||||
#endif
|
||||
|
||||
ThreadLocal *GetMyThreadLocal_SDL (void);
|
||||
|
||||
void SleepThread_SDL (TimeCount sleepTime);
|
||||
void SleepThreadUntil_SDL (TimeCount wakeTime);
|
||||
void TaskSwitch_SDL (void);
|
||||
void WaitThread_SDL (Thread thread, int *status);
|
||||
|
||||
void DestroyMutex_SDL (Mutex m);
|
||||
void LockMutex_SDL (Mutex m);
|
||||
void UnlockMutex_SDL (Mutex m);
|
||||
|
||||
void DestroySemaphore_SDL (Semaphore sem);
|
||||
void SetSemaphore_SDL (Semaphore sem);
|
||||
void ClearSemaphore_SDL (Semaphore sem);
|
||||
|
||||
void DestroyCondVar_SDL (CondVar c);
|
||||
void WaitCondVar_SDL (CondVar c);
|
||||
void WaitProtectedCondVar_SDL (CondVar c, Mutex m);
|
||||
void SignalCondVar_SDL (CondVar c);
|
||||
void BroadcastCondVar_SDL (CondVar c);
|
||||
|
||||
@@ -81,12 +72,19 @@ int GetRecursiveMutexDepth_SDL (RecursiveMutex m);
|
||||
#define NativeInitThreadSystem InitThreadSystem_SDL
|
||||
#define NativeUnInitThreadSystem UnInitThreadSystem_SDL
|
||||
|
||||
#define NativeGetMyThreadLocal GetMyThreadLocal_SDL
|
||||
|
||||
#define NativeCreateThread CreateThread_SDL
|
||||
#define NativeSleepThread SleepThread_SDL
|
||||
#define NativeSleepThreadUntil SleepThreadUntil_SDL
|
||||
#define NativeTaskSwitch TaskSwitch_SDL
|
||||
#define NativeWaitThread WaitThread_SDL
|
||||
|
||||
#define NativeCreateMutex CreateMutex_SDL
|
||||
#define NativeDestroyMutex DestroyMutex_SDL
|
||||
#define NativeLockMutex LockMutex_SDL
|
||||
#define NativeUnlockMutex UnlockMutex_SDL
|
||||
|
||||
#define NativeCreateSemaphore CreateSemaphore_SDL
|
||||
#define NativeDestroySemaphore DestroySemaphore_SDL
|
||||
#define NativeSetSemaphore SetSemaphore_SDL
|
||||
@@ -95,7 +93,6 @@ int GetRecursiveMutexDepth_SDL (RecursiveMutex m);
|
||||
#define NativeCreateCondVar CreateCondVar_SDL
|
||||
#define NativeDestroyCondVar DestroyCondVar_SDL
|
||||
#define NativeWaitCondVar WaitCondVar_SDL
|
||||
#define NativeWaitProtectedCondVar WaitProtectedCondVar_SDL
|
||||
#define NativeSignalCondVar SignalCondVar_SDL
|
||||
#define NativeBroadcastCondVar BroadcastCondVar_SDL
|
||||
|
||||
|
||||
@@ -46,27 +46,27 @@ CreateThread_Core (ThreadFunction func, void *data, SDWORD stackSize, const char
|
||||
}
|
||||
|
||||
Mutex
|
||||
CreateMutex_Core (void)
|
||||
CreateMutex_Core (const char *name, DWORD syncClass)
|
||||
{
|
||||
return (Mutex) NativeCreateMutex ();
|
||||
return NativeCreateMutex (name, syncClass);
|
||||
}
|
||||
|
||||
Semaphore
|
||||
CreateSemaphore_Core (DWORD initial, const char *name)
|
||||
CreateSemaphore_Core (DWORD initial, const char *name, DWORD syncClass)
|
||||
{
|
||||
return NativeCreateSemaphore (initial, name);
|
||||
return NativeCreateSemaphore (initial, name, syncClass);
|
||||
}
|
||||
|
||||
RecursiveMutex
|
||||
CreateRecursiveMutex_Core (const char *name)
|
||||
CreateRecursiveMutex_Core (const char *name, DWORD syncClass)
|
||||
{
|
||||
return NativeCreateRecursiveMutex (name);
|
||||
return NativeCreateRecursiveMutex (name, syncClass);
|
||||
}
|
||||
|
||||
CondVar
|
||||
CreateCondVar_Core (const char *name)
|
||||
CreateCondVar_Core (const char *name, DWORD syncClass)
|
||||
{
|
||||
return NativeCreateCondVar (name);
|
||||
return NativeCreateCondVar (name, syncClass);
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -80,7 +80,7 @@ CreateThread_Core (ThreadFunction func, void *data, SDWORD stackSize)
|
||||
Mutex
|
||||
CreateMutex_Core (void)
|
||||
{
|
||||
return (Mutex) NativeCreateMutex ();
|
||||
return NativeCreateMutex ();
|
||||
}
|
||||
|
||||
Semaphore
|
||||
@@ -102,6 +102,27 @@ CreateCondVar_Core (void)
|
||||
}
|
||||
#endif
|
||||
|
||||
ThreadLocal *
|
||||
CreateThreadLocal (void)
|
||||
{
|
||||
ThreadLocal *tl = HMalloc (sizeof (ThreadLocal));
|
||||
tl->flushSem = CreateSemaphore (0, "FlushGraphics", SYNC_CLASS_VIDEO);
|
||||
return tl;
|
||||
}
|
||||
|
||||
void
|
||||
DestroyThreadLocal (ThreadLocal *tl)
|
||||
{
|
||||
DestroySemaphore (tl->flushSem);
|
||||
HFree (tl);
|
||||
}
|
||||
|
||||
ThreadLocal *
|
||||
GetMyThreadLocal (void)
|
||||
{
|
||||
return NativeGetMyThreadLocal ();
|
||||
}
|
||||
|
||||
void
|
||||
WaitThread (Thread thread, int *status)
|
||||
{
|
||||
@@ -129,22 +150,19 @@ TaskSwitch (void)
|
||||
void
|
||||
DestroyMutex (Mutex sem)
|
||||
{
|
||||
NativeDestroyMutex ((NativeMutex) sem);
|
||||
NativeDestroyMutex (sem);
|
||||
}
|
||||
|
||||
void
|
||||
LockMutex (Mutex sem)
|
||||
{
|
||||
while (NativeLockMutex ((NativeMutex) sem) == -1)
|
||||
{
|
||||
TaskSwitch ();
|
||||
}
|
||||
NativeLockMutex (sem);
|
||||
}
|
||||
|
||||
void
|
||||
UnlockMutex (Mutex sem)
|
||||
{
|
||||
NativeUnlockMutex ((NativeMutex) sem);
|
||||
NativeUnlockMutex (sem);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -177,12 +195,6 @@ WaitCondVar (CondVar cv)
|
||||
NativeWaitCondVar (cv);
|
||||
}
|
||||
|
||||
void
|
||||
WaitProtectedCondVar (CondVar cv, Mutex m)
|
||||
{
|
||||
NativeWaitProtectedCondVar (cv, m);
|
||||
}
|
||||
|
||||
void
|
||||
SignalCondVar (CondVar cv)
|
||||
{
|
||||
@@ -195,12 +207,6 @@ BroadcastCondVar (CondVar cv)
|
||||
NativeBroadcastCondVar (cv);
|
||||
}
|
||||
|
||||
DWORD
|
||||
CurrentThreadID ()
|
||||
{
|
||||
return (DWORD)NativeThreadID ();
|
||||
}
|
||||
|
||||
void
|
||||
DestroyRecursiveMutex (RecursiveMutex mutex)
|
||||
{
|
||||
|
||||
@@ -37,7 +37,7 @@ TFB_CreateVideoImage (int w, int h)
|
||||
SDL_PixelFormat* fmt = SDL_Video->format;
|
||||
|
||||
img = HMalloc (sizeof (TFB_Image));
|
||||
img->mutex = CreateMutex ();
|
||||
img->mutex = CreateMutex ("vid image lock", SYNC_CLASS_VIDEO);
|
||||
img->ScaledImg = NULL;
|
||||
img->MipmapImg = NULL;
|
||||
img->colormap_index = -1;
|
||||
|
||||
@@ -127,8 +127,8 @@ _init_video_file(PVOID pStr)
|
||||
vid->length = dec->length;
|
||||
vid->w = vid->decoder->w;
|
||||
vid->h = vid->decoder->h;
|
||||
vid->guard = CreateMutex ();
|
||||
vid->frame_lock = CreateCondVar ("frame lock");
|
||||
vid->guard = CreateMutex ("video guard", SYNC_CLASS_VIDEO);
|
||||
vid->frame_lock = CreateCondVar ("frame lock", SYNC_CLASS_VIDEO);
|
||||
|
||||
return (VIDEO_REF) vid;
|
||||
}
|
||||
|
||||
@@ -295,7 +295,7 @@ TFB_PlayVideo (VIDEO_REF VidRef, uint32 x, uint32 y)
|
||||
|
||||
// creation probably needs better handling
|
||||
if (!vp_interthread_lock)
|
||||
vp_interthread_lock = CreateSemaphore (1, "inter-thread param lock");
|
||||
vp_interthread_lock = CreateSemaphore (1, "inter-thread param lock", SYNC_CLASS_VIDEO);
|
||||
SetSemaphore (vp_interthread_lock);
|
||||
vp_interthread_clip = vid;
|
||||
|
||||
|
||||
@@ -1354,7 +1354,7 @@ SetFlashRect (PRECT pRect, FRAME f)
|
||||
int create_flash = 0;
|
||||
|
||||
if (! flash_mutex)
|
||||
flash_mutex = CreateMutex ();
|
||||
flash_mutex = CreateMutex ("FlashRect Lock", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
|
||||
|
||||
old_r = flash_rect;
|
||||
old_f = flash_frame;
|
||||
|
||||
+2
-2
@@ -350,8 +350,8 @@ main (int argc, char *argv[])
|
||||
InitTimeSystem ();
|
||||
InitTaskSystem ();
|
||||
|
||||
GraphicsLock = CreateMutex (/*"Graphics"*/);
|
||||
RenderingCond = CreateCondVar ("DCQ empty");
|
||||
GraphicsLock = CreateMutex ("Graphics", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
|
||||
RenderingCond = CreateCondVar ("DCQ empty", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
|
||||
|
||||
TFB_InitGraphics (gfxdriver, gfxflags, width, height, bpp);
|
||||
init_communication ();
|
||||
|
||||
Reference in New Issue
Block a user