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:
@@ -1,4 +1,5 @@
|
|||||||
Changes towards version 0.2:
|
Changes towards version 0.2:
|
||||||
|
- Fixed deadlock races in new FlushGraphics method -PhracturedBlue
|
||||||
- FlushGraphics now waits and notifies on a per-thread level
|
- FlushGraphics now waits and notifies on a per-thread level
|
||||||
- No longer using SHGetFolderPath on Windows - SvdB
|
- No longer using SHGetFolderPath on Windows - SvdB
|
||||||
- Key repeat is now enabled when typing text, from slayne
|
- Key repeat is now enabled when typing text, from slayne
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ FlushGraphics (void)
|
|||||||
TFB_BatchReset ();
|
TFB_BatchReset ();
|
||||||
DrawCommand.Type = TFB_DRAWCOMMANDTYPE_FLUSHGRAPHICS;
|
DrawCommand.Type = TFB_DRAWCOMMANDTYPE_FLUSHGRAPHICS;
|
||||||
DrawCommand.image = 0;
|
DrawCommand.image = 0;
|
||||||
|
// We need to lock the mutex before quein the DC to prevent races
|
||||||
|
LockSignalMutex ();
|
||||||
TFB_EnqueueDrawCommand(&DrawCommand);
|
TFB_EnqueueDrawCommand(&DrawCommand);
|
||||||
WaitForSignal ();
|
WaitForSignal ();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,11 +104,16 @@ typedef void *Semaphore;
|
|||||||
extern Semaphore CreateSemaphoreAux (DWORD initial, char *sem_name);
|
extern Semaphore CreateSemaphoreAux (DWORD initial, char *sem_name);
|
||||||
# define CreateSemaphore(initial,sem_name) \
|
# define CreateSemaphore(initial,sem_name) \
|
||||||
CreateSemaphoreAux ((initial), (sem_name))
|
CreateSemaphoreAux ((initial), (sem_name))
|
||||||
|
extern void ResetSemaphoreOwnerAux (Semaphore sem);
|
||||||
|
# define ResetSemaphoreOwner(sem_name) \
|
||||||
|
ResetSemaphoreOwnerAux (sem_name)
|
||||||
#else
|
#else
|
||||||
extern Semaphore CreateSemaphoreAux (DWORD initial);
|
extern Semaphore CreateSemaphoreAux (DWORD initial);
|
||||||
# define CreateSemaphore(initial,sem_name) \
|
# define CreateSemaphore(initial,sem_name) \
|
||||||
CreateSemaphoreAux ((initial))
|
CreateSemaphoreAux ((initial))
|
||||||
|
# define ResetSemaphoreOwner(sem_name)
|
||||||
#endif
|
#endif
|
||||||
|
extern DWORD SemaphoreValue (Semaphore sem);
|
||||||
extern void DestroySemaphore (Semaphore sem);
|
extern void DestroySemaphore (Semaphore sem);
|
||||||
extern int SetSemaphore (Semaphore sem);
|
extern int SetSemaphore (Semaphore sem);
|
||||||
extern int TrySetSemaphore (Semaphore sem);
|
extern int TrySetSemaphore (Semaphore sem);
|
||||||
@@ -133,6 +138,7 @@ extern void BroadcastCondVar (CondVar);
|
|||||||
|
|
||||||
extern DWORD CurrentThreadID (void);
|
extern DWORD CurrentThreadID (void);
|
||||||
|
|
||||||
|
extern void LockSignalMutex(void);
|
||||||
extern void WaitForSignal (void);
|
extern void WaitForSignal (void);
|
||||||
extern void SignalThread (DWORD);
|
extern void SignalThread (DWORD);
|
||||||
|
|
||||||
|
|||||||
@@ -29,10 +29,11 @@
|
|||||||
|
|
||||||
#define CONDVAR_BANK_SIZE 10
|
#define CONDVAR_BANK_SIZE 10
|
||||||
|
|
||||||
static Semaphore bank_sem;
|
static Mutex bank_mutex;
|
||||||
|
static int wait = 0, signal = 0;
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
CondVar var;
|
Semaphore var;
|
||||||
DWORD id;
|
DWORD id;
|
||||||
int used;
|
int used;
|
||||||
} bank[CONDVAR_BANK_SIZE];
|
} bank[CONDVAR_BANK_SIZE];
|
||||||
@@ -41,10 +42,12 @@ void
|
|||||||
init_cond_bank ()
|
init_cond_bank ()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
bank_sem = CreateSemaphore (1, "CondVar Bank Semaphore");
|
bank_mutex = CreateMutex ();
|
||||||
for (i = 0; i < CONDVAR_BANK_SIZE; i++)
|
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;
|
bank[i].id = bank[i].used = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,16 +60,20 @@ uninit_cond_bank ()
|
|||||||
{
|
{
|
||||||
DestroyCondVar (bank[i].var);
|
DestroyCondVar (bank[i].var);
|
||||||
}
|
}
|
||||||
DestroySemaphore (bank_sem);
|
DestroyMutex (bank_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LockSignalMutex ()
|
||||||
|
{
|
||||||
|
LockMutex (bank_mutex);
|
||||||
|
}
|
||||||
void
|
void
|
||||||
WaitForSignal ()
|
WaitForSignal ()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int index = -1;
|
int index = -1;
|
||||||
DWORD me = CurrentThreadID ();
|
DWORD me = CurrentThreadID ();
|
||||||
SetSemaphore (bank_sem);
|
|
||||||
for (i = 0; i < CONDVAR_BANK_SIZE; i++)
|
for (i = 0; i < CONDVAR_BANK_SIZE; i++)
|
||||||
{
|
{
|
||||||
if (!bank[i].used)
|
if (!bank[i].used)
|
||||||
@@ -79,15 +86,19 @@ WaitForSignal ()
|
|||||||
{
|
{
|
||||||
/* The bank is full! */
|
/* The bank is full! */
|
||||||
fprintf(stderr, "Condvar bank is full, %ul is waiting on DCQ.", me);
|
fprintf(stderr, "Condvar bank is full, %ul is waiting on DCQ.", me);
|
||||||
ClearSemaphore (bank_sem);
|
UnlockMutex (bank_mutex);
|
||||||
WaitCondVar (RenderingCond);
|
WaitCondVar (RenderingCond);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bank[i].used = 1;
|
bank[i].used = 1;
|
||||||
bank[i].id = me;
|
bank[i].id = me;
|
||||||
ClearSemaphore (bank_sem);
|
// Initialize the Semaphore to a value of '0' in case it isn't already
|
||||||
WaitCondVar (bank[i].var);
|
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)
|
SignalThread (DWORD id)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
SetSemaphore (bank_sem);
|
LockMutex (bank_mutex);
|
||||||
for (i = 0; i < CONDVAR_BANK_SIZE; i++)
|
for (i = 0; i < CONDVAR_BANK_SIZE; i++)
|
||||||
{
|
{
|
||||||
if (bank[i].used && bank[i].id == id)
|
if (bank[i].used && bank[i].id == id)
|
||||||
{
|
{
|
||||||
bank[i].id = bank[i].used = 0;
|
bank[i].id = bank[i].used = 0;
|
||||||
SignalCondVar (bank[i].var);
|
ResetSemaphoreOwner (bank[i].var);
|
||||||
|
ClearSemaphore (bank[i].var);
|
||||||
break;
|
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 ()
|
SDL_CreateCond ()
|
||||||
#define NativeDestroyCondVar(condvar) \
|
#define NativeDestroyCondVar(condvar) \
|
||||||
SDL_DestroyCond ((condvar))
|
SDL_DestroyCond ((condvar))
|
||||||
|
extern void SDLWrapper_WaitCondVar (CondVar candvar);
|
||||||
#define NativeWaitCondVar(condvar) \
|
#define NativeWaitCondVar(condvar) \
|
||||||
SDLWrapper_WaitCondVar ((condvar))
|
SDLWrapper_WaitCondVar ((condvar))
|
||||||
#define NativeSignalCondVar(condvar) \
|
#define NativeSignalCondVar(condvar) \
|
||||||
|
|||||||
@@ -518,6 +518,27 @@ TimeoutSetSemaphore (Semaphore sem, TimePeriod timeout)
|
|||||||
return (i);
|
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
|
void
|
||||||
ClearSemaphore (Semaphore sem)
|
ClearSemaphore (Semaphore sem)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user