reimplemented semaphore debuging code -PhracturedBlue

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@470 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
ghaushe
2002-12-23 02:27:06 +00:00
parent 114efa6ac1
commit e0aad4e54a
9 changed files with 235 additions and 51 deletions
+1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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");
}
+1 -1
View File
@@ -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
+1 -1
View File
@@ -382,7 +382,7 @@ mem_init (void)
{
int i;
_MemorySem = CreateSemaphore (1);
_MemorySem = CreateSemaphore (1, "Memory");
SetSemaphore (_MemorySem);
freeListHead = &extents[0];
+19 -1
View File
@@ -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);
@@ -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) \
+205 -45
View File
@@ -27,14 +27,26 @@
#include <unistd.h>
#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 <string.h>
// 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 <numSems; i++)
if (SemMon[i].Sem == sem)
{
SemMon[i].Sem = 0;
break;
}
NativeClearSemaphore (SemMutex);
#endif
NativeDestroySemaphore ((NativeSemaphore) sem);
}
#ifdef DEBUG_TRACK_SEM
static void debug_set_sem (Semaphore sem
#if defined (THREAD_QUEUE) && defined (THREAD_NAMES)
, char *name
#endif
)
{
int i;
for (i = 0; i < numSems; i++)
{
if (SemMon[i].Sem == sem)
{
SemMon[i].Thread = NativeThreadID ();
#if defined (THREAD_QUEUE) && defined (THREAD_NAMES)
if (name != NULL)
{
strncpy(SemMon[i].ThreadName,name,20);
SemMon[i].ThreadName[19] = 0;
}
#endif
break;
}
}
}
#endif
int
SetSemaphore (Semaphore sem)
{
int i;
#if defined (DEBUG_TRACK_SEM) && defined (THREAD_QUEUE) \
&& defined (THREAD_NAMES)
char *name = ThreadNameNative (NativeThreadID ());
#endif
#if defined (DEBUG_TRACK_SEM) && defined (DEBUG_SEM_DEADLOCK)
do
{
i = NativeTimeoutSetSemaphore ((NativeSemaphore) sem, SEM_TIMEOUT);
if (i == NATIVE_MUTEX_TIMEOUT)
{
int j = -1;
for (j = 0; j < numSems; j++)
{
if (SemMon[j].Sem == sem)
break;
}
if (j != -1)
#if defined (THREAD_QUEUE) && defined (THREAD_NAMES)
fprintf (stderr, "Failed to acquire '%s' semaphore in thread '%s'.\n\tIt is held by thread '%s'. Retrying\n",
SemMon[j].Name,
name,
SemMon[j].ThreadName);
#else
fprintf (stderr, "Failed to acquire '%s' semaphore. Retrying\n",
SemMon[j].Name);
#endif /* THREAD_NAMES */
}
} while (i == NATIVE_MUTEX_TIMEOUT);
#else
i = NativeSetSemaphore ((NativeSemaphore) sem);
#endif /* DEBUG_SEM_DEADLOCK */
#ifdef DEBUG_TRACK_SEM
if (i != 0)
fprintf(stderr, "WARNING: SetSemaphore did not return 0, this could be bad!\n");
for (i = 0; SemList[i] != NULL; i++)
if (*SemList[i] == sem)
{
semthread[i] = SDL_ThreadID ();
break;
}
#endif
#if defined (THREAD_QUEUE) && defined (THREAD_NAMES)
debug_set_sem (sem, name);
#else
debug_set_sem (sem);
#endif /* THREAD_NAMES */
#endif /* DEBUG_TRACK_SEM */
return i;
}
@@ -339,16 +477,20 @@ TrySetSemaphore (Semaphore sem)
{
int i;
#if defined (DEBUG_TRACK_SEM) && defined (THREAD_QUEUE) \
&& defined (THREAD_NAMES)
char *name = ThreadNameNative (NativeThreadID ());
#endif
i = NativeTrySetSemaphore ((NativeSemaphore) sem);
#ifdef DEBUG_TRACK_SEM
if (i == 0)
for (i = 0; SemList[i] != NULL; i++)
if (*SemList[i] == sem)
{
semthread[i] = SDL_ThreadID ();
break;
}
#endif
#if defined (THREAD_QUEUE) && defined (THREAD_NAMES)
debug_set_sem (sem, name);
#else
debug_set_sem (sem);
#endif /* THREAD_NAMES */
#endif /* DEBUG_TRACK_SEM */
return (i);
}
@@ -357,39 +499,57 @@ TimeoutSetSemaphore (Semaphore sem, TimePeriod timeout)
{
int i;
#if defined (DEBUG_TRACK_SEM) && defined (THREAD_QUEUE) \
&& defined (THREAD_NAMES)
char *name = ThreadNameNative (NativeThreadID ());
#endif
i = NativeTimeoutSetSemaphore ((NativeSemaphore) sem, timeout);
#ifdef DEBUG_TRACK_SEM
if (i == 0)
for (i = 0; SemList[i] != NULL; i++)
if (*SemList[i] == sem)
{
semthread[i] = SDL_ThreadID ();
break;
}
#endif
#if defined (THREAD_QUEUE) && defined (THREAD_NAMES)
debug_set_sem (sem, name);
#else
debug_set_sem (sem);
#endif /* THREAD_NAMES */
#endif /* DEBUG_TRACK_SEM */
return (i);
}
void
ClearSemaphore (Semaphore sem)
{
int i;
#ifdef DEBUG_TRACK_SEM
Uint32 semval = SDL_SemValue (sem);
if (semval != 0)
int i;
Uint32 semval = NativeSemValue (sem);
char *sem_name = NULL;
for (i = 0; i < numSems; i++)
if (SemMon[i].Sem == sem)
{
fprintf (stderr, "WARNING: trying to clear a free semaphore (value=%d)\n", semval);
// Should we unset the Semaphore twice? Perhaps not.
return;
}
for (i = 0;SemList[i] != NULL; i++)
if (*SemList[i] == sem)
{
if (! semthread[i] && semthread[i] != SDL_ThreadID ())
fprintf( stderr, "WARNING: tried to free a Semaphore held by another thread!\n");
semthread[i] = 0;
sem_name = SemMon[i].Name;
if (SemMon[i].Thread && SemMon[i].Thread != NativeThreadID ())
#if defined (THREAD_QUEUE) && defined (THREAD_NAMES)
if (ThreadNameNative (SemMon[i].Thread) == NULL)
fprintf( stderr, "Freeing %s Semaphore in '%s' set by defunct thread '%s'!\n",
sem_name,
ThreadNameNative (NativeThreadID ()),
SemMon[i].ThreadName);
else
fprintf( stderr, "Freeing %s Semaphore in '%s' set by thread '%s'!\n",
sem_name,
ThreadNameNative (NativeThreadID ()),
ThreadNameNative (SemMon[i].Thread));
SemMon[i].ThreadName[0] = 0;
#else
fprintf (stderr, "Freeing %s Semaphore that was set by a different thread\n",
sem_name);
#endif
SemMon[i].Thread = 0;
break;
}
if (semval != 0)
fprintf (stderr, "Incrementing semaphore '%s' (newvalue=%d)\n", sem_name, semval + 1);
#endif
NativeClearSemaphore ((NativeSemaphore) sem);
}
+1 -1
View File
@@ -219,7 +219,7 @@ main (int argc, char *argv[])
InitTaskSystem ();
mem_init ();
GraphicsSem = CreateSemaphore (1);
GraphicsSem = CreateSemaphore (1, "Graphics");
RenderingCond = CreateCondVar ();
init_xform_control ();