From e0aad4e54a81a274d655b54b12d32e6290716038 Mon Sep 17 00:00:00 2001 From: ghaushe Date: Mon, 23 Dec 2002 02:27:06 +0000 Subject: [PATCH] reimplemented semaphore debuging code -PhracturedBlue git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@470 8092fc87-c524-0410-9efc-e669fe64eaf9 --- sc2/ChangeLog | 1 + sc2/src/sc2code/comm.c | 2 +- sc2/src/sc2code/init.c | 2 +- sc2/src/sc2code/libs/graphics/sdl/dcqueue.c | 2 +- sc2/src/sc2code/libs/memory/w_memlib.c | 2 +- sc2/src/sc2code/libs/threadlib.h | 20 +- sc2/src/sc2code/libs/threads/sdl/sdlthreads.h | 5 + sc2/src/sc2code/libs/threads/thrcommon.c | 250 ++++++++++++++---- sc2/src/starcon2.c | 2 +- 9 files changed, 235 insertions(+), 51 deletions(-) diff --git a/sc2/ChangeLog b/sc2/ChangeLog index bb1871048..c61dc1c60 100644 --- a/sc2/ChangeLog +++ b/sc2/ChangeLog @@ -1,4 +1,5 @@ 0.2: +- Rewrote Semaphore debugging code to be more useful - PhracturedBlue - Better fix for clearing load/save screen - fOSSiL - Implemented bilinear scaling in pure SDL mode - Mika - Planet surface is now smoothed, from PhracturedBlue diff --git a/sc2/src/sc2code/comm.c b/sc2/src/sc2code/comm.c index 54d44314e..a77b856a3 100644 --- a/sc2/src/sc2code/comm.c +++ b/sc2/src/sc2code/comm.c @@ -378,7 +378,7 @@ init_xform_control () { XFormControl.XFormCurrent = XFormControl.XFormInsertPoint = 0; XFormControl.XFormsPending = FALSE; - XFormControl.XFormSem = CreateSemaphore (1); + XFormControl.XFormSem = CreateSemaphore (1, "XForm"); } void diff --git a/sc2/src/sc2code/init.c b/sc2/src/sc2code/init.c index 8adff4ee3..2cf684185 100644 --- a/sc2/src/sc2code/init.c +++ b/sc2/src/sc2code/init.c @@ -264,6 +264,6 @@ InitGlobData (void) GLOBAL (glob_flags) = (BYTE)i; GLOBAL (DisplayArray) = DisplayArray; - (GLOBAL (GameClock)).clock_sem = CreateSemaphore(1); + (GLOBAL (GameClock)).clock_sem = CreateSemaphore(1, "Clock"); } diff --git a/sc2/src/sc2code/libs/graphics/sdl/dcqueue.c b/sc2/src/sc2code/libs/graphics/sdl/dcqueue.c index c78bb71d4..15eb633e2 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/dcqueue.c +++ b/sc2/src/sc2code/libs/graphics/sdl/dcqueue.c @@ -145,7 +145,7 @@ TFB_DrawCommandQueue_Create() DCQ_locking_depth = 0; DCQ_locking_thread = 0; - DCQ_sem = CreateSemaphore(1); + DCQ_sem = CreateSemaphore(1, "DCQ"); } void diff --git a/sc2/src/sc2code/libs/memory/w_memlib.c b/sc2/src/sc2code/libs/memory/w_memlib.c index 9e6cf158f..757687311 100644 --- a/sc2/src/sc2code/libs/memory/w_memlib.c +++ b/sc2/src/sc2code/libs/memory/w_memlib.c @@ -382,7 +382,7 @@ mem_init (void) { int i; - _MemorySem = CreateSemaphore (1); + _MemorySem = CreateSemaphore (1, "Memory"); SetSemaphore (_MemorySem); freeListHead = &extents[0]; diff --git a/sc2/src/sc2code/libs/threadlib.h b/sc2/src/sc2code/libs/threadlib.h index ea1f4e44b..688916d8f 100644 --- a/sc2/src/sc2code/libs/threadlib.h +++ b/sc2/src/sc2code/libs/threadlib.h @@ -21,6 +21,7 @@ #define _THREADLIB_H #define THREADLIB SDL +#define DEBUG_TRACK_SEM #ifdef DEBUG # ifndef DEBUG_THREADS @@ -53,6 +54,15 @@ # endif #endif +#if defined (DEBUG_TRACK_SEM) +# if !defined (THREAD_QUEUE) +# define THREAD_QUEUE +# endif +# if !defined (THREAD_NAMES) +# define THREAD_NAMES +# endif +#endif + extern void InitThreadSystem (void); extern void UnInitThreadSystem (void); @@ -89,7 +99,15 @@ extern void TaskSwitch (void); extern void WaitThread (Thread thread, int *status); typedef void *Semaphore; -extern Semaphore CreateSemaphore (DWORD initial); +#ifdef DEBUG_TRACK_SEM +extern Semaphore CreateSemaphoreAux (DWORD initial, char *sem_name); +# define CreateSemaphore(initial,sem_name) \ + CreateSemaphoreAux ((initial), (sem_name)) +#else +extern Semaphore CreateSemaphoreAux (DWORD initial); +# define CreateSemaphore(initial,sem_name) \ + CreateSemaphoreAux ((initial)) +#endif extern void DestroySemaphore (Semaphore sem); extern int SetSemaphore (Semaphore sem); extern int TrySetSemaphore (Semaphore sem); diff --git a/sc2/src/sc2code/libs/threads/sdl/sdlthreads.h b/sc2/src/sc2code/libs/threads/sdl/sdlthreads.h index d79b5813d..513850aef 100644 --- a/sc2/src/sc2code/libs/threads/sdl/sdlthreads.h +++ b/sc2/src/sc2code/libs/threads/sdl/sdlthreads.h @@ -43,6 +43,8 @@ extern void SDLWrapper_TaskSwitch (void); SDLWrapper_TaskSwitch() #define NativeWaitThread(thread, status) \ SDL_WaitThread ((thread), (status)) +#define NativeGetThreadID(thread) SDL_GetThreadID ((thread)) +#define NativeThreadID() SDL_ThreadID () #ifdef PROFILE_THREADS extern void SDLWrapper_PrintThreadStats (SDL_Thread *thread); #define NativePrintThreadStats(thread) \ @@ -60,6 +62,9 @@ typedef SDL_sem *NativeSemaphore; SDL_SemWait ((sem)) #define NativeTrySetSemaphore(sem) \ SDL_SemTryWait ((sem)) +#define NativeSemValue(sem) \ + SDL_SemValue ((sem)) +#define NATIVE_MUTEX_TIMEOUT SDL_MUTEX_TIMEDOUT extern int SDLWrapper_TimeoutSetSemaphore (Semaphore sem, TimePeriod timeperiod); #define NativeTimeoutSetSemaphore(sem, timeperiod) \ diff --git a/sc2/src/sc2code/libs/threads/thrcommon.c b/sc2/src/sc2code/libs/threads/thrcommon.c index 4ea7a82e1..7cbd8f327 100644 --- a/sc2/src/sc2code/libs/threads/thrcommon.c +++ b/sc2/src/sc2code/libs/threads/thrcommon.c @@ -27,14 +27,26 @@ #include #endif -#define DEBUG_TRACK_SEM - #ifdef DEBUG_TRACK_SEM -// Define all semaphores to be tracked in SemList. Make sure it is NULL terminated -// Make that semthread is the same length as SemList, and is initialized as all 0's -extern Semaphore GraphicsSem; -static Semaphore *SemList[] = {&GraphicsSem, NULL}; -Uint32 semthread[] = {0, 0}; +#include +// The semaphore tracker looks for possible semaphore issues. +// It will report semaphores cleared by threads other than what set them +// and when the semaphore value is larger than 1 +#define NUM_SEMAPHORES 50 +// Set the timeout to 60 seconds +#define SEM_TIMEOUT 6000 +#undef DEBUG_SEM_DEADLOCK +typedef struct { + Semaphore Sem; + Uint32 Thread; + char Name[20]; +#if defined (THREAD_QUEUE) && defined (THREAD_NAMES) + char ThreadName[20]; +#endif +} MonitorSem; +Semaphore SemMutex; +static MonitorSem SemMon[NUM_SEMAPHORES]; +static UWORD numSems = 0; #endif #ifdef THREAD_QUEUE @@ -71,7 +83,7 @@ void InitThreadSystem (void) { #ifdef THREAD_QUEUE - threadQueueSemaphore = CreateSemaphore (1); + threadQueueSemaphore = CreateSemaphore (1, "ThreadQueue"); #endif /* THREAD_QUEUE */ #ifdef PROFILE_THREADS signal(SIGUSR1, SigUSR1Handler); @@ -127,6 +139,28 @@ UnQueueThread (Thread thread) } #endif /* THREAD_QUEUE */ +#if defined (DEBUG_TRACK_SEM) && defined (THREAD_QUEUE) \ + && defined (THREAD_NAMES) +static char *ThreadNameNative (Uint32 native) +{ + volatile Thread ptr; + + ptr = threadQueue; + if (threadQueueSemaphore) + NativeSetSemaphore (threadQueueSemaphore); + while (ptr && NativeGetThreadID (ptr->native) != native) + { + ptr = ptr->next; + } + if(threadQueueSemaphore) + NativeClearSemaphore (threadQueueSemaphore); + if (ptr) + return ((char *)ptr->name); + else + return (NULL); +} +#endif /* DEBUG_TRACK_SEM */ + #ifdef DEBUG_THREADS static const char * ThreadName(Thread thread) { @@ -194,7 +228,7 @@ CreateThreadAux (ThreadFunction func, void *data, SDWORD stackSize startInfo = (struct ThreadStartInfo *) HMalloc (sizeof (*startInfo)); startInfo->func = func; startInfo->data = data; - startInfo->sem = CreateSemaphore (0); + startInfo->sem = CreateSemaphore (0, "StartThread"); startInfo->thread = thread; thread->native = NativeCreateThread (ThreadHelper, (void *) startInfo, @@ -304,33 +338,137 @@ PrintThreadsStats (void) #endif /* PROFILE_THREADS */ Semaphore -CreateSemaphore (DWORD initial) +CreateSemaphoreAux (DWORD initial +#ifdef DEBUG_TRACK_SEM + , char *sem_name +#endif + ) { - return (Semaphore) NativeCreateSemaphore (initial); + Semaphore sem = (Semaphore)NativeCreateSemaphore (initial); +#ifdef DEBUG_TRACK_SEM + int pos; + if (SemMutex == 0) + SemMutex = NativeCreateSemaphore (0); + else + NativeSetSemaphore (SemMutex); + for (pos = 0; pos < numSems; pos++) + if (SemMon[pos].Sem == 0) + break; + if (pos == numSems) + { + numSems++; + if (numSems == NUM_SEMAPHORES) + { + fprintf(stderr, "Error: We ran out of semaphores. aborting!\n"); + NativeClearSemaphore (SemMutex); + return (0); + } + } + SemMon[pos].Sem = sem; + SemMon[pos].Thread = 0; + strncpy(SemMon[pos].Name, sem_name, 20); + SemMon[pos].Name[19] = 0; +#if defined (THREAD_QUEUE) && defined (THREAD_NAMES) +// fprintf (stderr, "Created Semaphore # %d: %s in thread '%s'\n", +// numSems, SemMon[pos].Name, ThreadNameNative (NativeThreadID ())); +#else +// fprintf (stderr, "Created Semaphore # %d: %s\n", +// numSems, SemMon[pos].Name); +#endif + NativeClearSemaphore (SemMutex); +#endif + return (sem); } void DestroySemaphore (Semaphore sem) { +#ifdef DEBUG_TRACK_SEM + int i; + NativeSetSemaphore (SemMutex); + for (i = 0; i