Replaced CondVar with a Semaphore in the new Signalling code.

This removes the race between releasing the bank semaphore and starting the
WaitCondVar (which was causing deadlocks in Windows)


git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@529 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
ghaushe
2003-01-04 16:55:31 +00:00
parent c043017049
commit 7f0251ba4d
6 changed files with 57 additions and 12 deletions
+1
View File
@@ -1,4 +1,5 @@
Changes towards version 0.2:
- Fixed deadlock races in new FlushGraphics method -PhracturedBlue
- FlushGraphics now waits and notifies on a per-thread level
- No longer using SHGetFolderPath on Windows - SvdB
- Key repeat is now enabled when typing text, from slayne
@@ -80,6 +80,8 @@ FlushGraphics (void)
TFB_BatchReset ();
DrawCommand.Type = TFB_DRAWCOMMANDTYPE_FLUSHGRAPHICS;
DrawCommand.image = 0;
// We need to lock the mutex before quein the DC to prevent races
LockSignalMutex ();
TFB_EnqueueDrawCommand(&DrawCommand);
WaitForSignal ();
}
+6
View File
@@ -104,11 +104,16 @@ typedef void *Semaphore;
extern Semaphore CreateSemaphoreAux (DWORD initial, char *sem_name);
# define CreateSemaphore(initial,sem_name) \
CreateSemaphoreAux ((initial), (sem_name))
extern void ResetSemaphoreOwnerAux (Semaphore sem);
# define ResetSemaphoreOwner(sem_name) \
ResetSemaphoreOwnerAux (sem_name)
#else
extern Semaphore CreateSemaphoreAux (DWORD initial);
# define CreateSemaphore(initial,sem_name) \
CreateSemaphoreAux ((initial))
# define ResetSemaphoreOwner(sem_name)
#endif
extern DWORD SemaphoreValue (Semaphore sem);
extern void DestroySemaphore (Semaphore sem);
extern int SetSemaphore (Semaphore sem);
extern int TrySetSemaphore (Semaphore sem);
@@ -133,6 +138,7 @@ extern void BroadcastCondVar (CondVar);
extern DWORD CurrentThreadID (void);
extern void LockSignalMutex(void);
extern void WaitForSignal (void);
extern void SignalThread (DWORD);
+26 -12
View File
@@ -29,10 +29,11 @@
#define CONDVAR_BANK_SIZE 10
static Semaphore bank_sem;
static Mutex bank_mutex;
static int wait = 0, signal = 0;
static struct {
CondVar var;
Semaphore var;
DWORD id;
int used;
} bank[CONDVAR_BANK_SIZE];
@@ -41,10 +42,12 @@ void
init_cond_bank ()
{
int i;
bank_sem = CreateSemaphore (1, "CondVar Bank Semaphore");
bank_mutex = CreateMutex ();
for (i = 0; i < CONDVAR_BANK_SIZE; i++)
{
bank[i].var = CreateCondVar ();
char str[20];
sprintf (str, "bank sem %d", i);
bank[i].var = CreateSemaphore (0, str);
bank[i].id = bank[i].used = 0;
}
}
@@ -57,16 +60,20 @@ uninit_cond_bank ()
{
DestroyCondVar (bank[i].var);
}
DestroySemaphore (bank_sem);
DestroyMutex (bank_mutex);
}
void
LockSignalMutex ()
{
LockMutex (bank_mutex);
}
void
WaitForSignal ()
{
int i;
int index = -1;
DWORD me = CurrentThreadID ();
SetSemaphore (bank_sem);
for (i = 0; i < CONDVAR_BANK_SIZE; i++)
{
if (!bank[i].used)
@@ -79,15 +86,19 @@ WaitForSignal ()
{
/* The bank is full! */
fprintf(stderr, "Condvar bank is full, %ul is waiting on DCQ.", me);
ClearSemaphore (bank_sem);
UnlockMutex (bank_mutex);
WaitCondVar (RenderingCond);
}
else
{
bank[i].used = 1;
bank[i].id = me;
ClearSemaphore (bank_sem);
WaitCondVar (bank[i].var);
// Initialize the Semaphore to a value of '0' in case it isn't already
while (SemaphoreValue (bank[i].var))
SetSemaphore (bank[i].var);
UnlockMutex (bank_mutex);
// Block on Semaphore until it is cleared by the Signal
SetSemaphore (bank[i].var);
}
}
@@ -95,16 +106,19 @@ void
SignalThread (DWORD id)
{
int i;
SetSemaphore (bank_sem);
LockMutex (bank_mutex);
for (i = 0; i < CONDVAR_BANK_SIZE; i++)
{
if (bank[i].used && bank[i].id == id)
{
bank[i].id = bank[i].used = 0;
SignalCondVar (bank[i].var);
ResetSemaphoreOwner (bank[i].var);
ClearSemaphore (bank[i].var);
break;
}
}
ClearSemaphore (bank_sem);
if (i == CONDVAR_BANK_SIZE)
fprintf (stderr, "Warning: Couldn't find thread to signal!\n");
UnlockMutex (bank_mutex);
}
@@ -87,6 +87,7 @@ typedef SDL_cond *NativeCondVar;
SDL_CreateCond ()
#define NativeDestroyCondVar(condvar) \
SDL_DestroyCond ((condvar))
extern void SDLWrapper_WaitCondVar (CondVar candvar);
#define NativeWaitCondVar(condvar) \
SDLWrapper_WaitCondVar ((condvar))
#define NativeSignalCondVar(condvar) \
+21
View File
@@ -518,6 +518,27 @@ TimeoutSetSemaphore (Semaphore sem, TimePeriod timeout)
return (i);
}
DWORD
SemaphoreValue (Semaphore sem)
{
return NativeSemValue (sem);
}
#ifdef DEBUG_TRACK_SEM
// Use this function to prevent messages when it is known that
// a semaphore will be cleared by a different thread than set it
void
ResetSemaphoreOwnerAux (Semaphore sem)
{
int i;
for (i = 0; i < numSems; i++)
if (SemMon[i].Sem == sem)
{
SemMon[i].Thread = 0;
break;
}
}
#endif
void
ClearSemaphore (Semaphore sem)
{