Fixed bug #150
memory leak in SDL_thread.c --HG-- extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%401503
This commit is contained in:
parent
ee03e10187
commit
fa0e211021
2 changed files with 30 additions and 54 deletions
|
@ -37,20 +37,13 @@ static int SDL_maxthreads = 0;
|
|||
static int SDL_numthreads = 0;
|
||||
static SDL_Thread **SDL_Threads = NULL;
|
||||
static SDL_mutex *thread_lock = NULL;
|
||||
int _creating_thread_lock = 0;
|
||||
|
||||
int SDL_ThreadsInit(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = 0;
|
||||
/* Set the thread lock creation flag so that we can reuse an
|
||||
existing lock on the system - since this mutex never gets
|
||||
destroyed (see SDL_ThreadsQuit()), we want to reuse it.
|
||||
*/
|
||||
_creating_thread_lock = 1;
|
||||
thread_lock = SDL_CreateMutex();
|
||||
_creating_thread_lock = 0;
|
||||
if ( thread_lock == NULL ) {
|
||||
retval = -1;
|
||||
}
|
||||
|
@ -76,15 +69,13 @@ void SDL_ThreadsQuit()
|
|||
/* Routines for manipulating the thread list */
|
||||
static void SDL_AddThread(SDL_Thread *thread)
|
||||
{
|
||||
SDL_Thread **threads;
|
||||
|
||||
/* WARNING:
|
||||
If the very first threads are created simultaneously, then
|
||||
there could be a race condition causing memory corruption.
|
||||
In practice, this isn't a problem because by definition there
|
||||
is only one thread running the first time this is called.
|
||||
*/
|
||||
if ( thread_lock == NULL ) {
|
||||
if ( !thread_lock ) {
|
||||
if ( SDL_ThreadsInit() < 0 ) {
|
||||
return;
|
||||
}
|
||||
|
@ -97,17 +88,14 @@ static void SDL_AddThread(SDL_Thread *thread)
|
|||
SDL_numthreads, SDL_maxthreads);
|
||||
#endif
|
||||
if ( SDL_numthreads == SDL_maxthreads ) {
|
||||
threads=(SDL_Thread **)SDL_malloc((SDL_maxthreads+ARRAY_CHUNKSIZE)*
|
||||
(sizeof *threads));
|
||||
SDL_Thread **threads;
|
||||
threads = (SDL_Thread **)SDL_realloc(SDL_Threads,
|
||||
(SDL_maxthreads+ARRAY_CHUNKSIZE)*(sizeof *threads));
|
||||
if ( threads == NULL ) {
|
||||
SDL_OutOfMemory();
|
||||
goto done;
|
||||
}
|
||||
SDL_memcpy(threads, SDL_Threads, SDL_numthreads*(sizeof *threads));
|
||||
SDL_maxthreads += ARRAY_CHUNKSIZE;
|
||||
if ( SDL_Threads ) {
|
||||
SDL_free(SDL_Threads);
|
||||
}
|
||||
SDL_Threads = threads;
|
||||
}
|
||||
SDL_Threads[SDL_numthreads++] = thread;
|
||||
|
@ -119,30 +107,35 @@ static void SDL_DelThread(SDL_Thread *thread)
|
|||
{
|
||||
int i;
|
||||
|
||||
if ( thread_lock ) {
|
||||
SDL_mutexP(thread_lock);
|
||||
for ( i=0; i<SDL_numthreads; ++i ) {
|
||||
if ( thread == SDL_Threads[i] ) {
|
||||
break;
|
||||
}
|
||||
if ( !thread_lock ) {
|
||||
return;
|
||||
}
|
||||
SDL_mutexP(thread_lock);
|
||||
for ( i=0; i<SDL_numthreads; ++i ) {
|
||||
if ( thread == SDL_Threads[i] ) {
|
||||
break;
|
||||
}
|
||||
if ( i < SDL_numthreads ) {
|
||||
if ( --SDL_numthreads > 0 ) {
|
||||
while ( i < SDL_numthreads ) {
|
||||
SDL_Threads[i] = SDL_Threads[i+1];
|
||||
++i;
|
||||
}
|
||||
} else {
|
||||
SDL_maxthreads = 0;
|
||||
SDL_free(SDL_Threads);
|
||||
SDL_Threads = NULL;
|
||||
}
|
||||
if ( i < SDL_numthreads ) {
|
||||
if ( --SDL_numthreads > 0 ) {
|
||||
while ( i < SDL_numthreads ) {
|
||||
SDL_Threads[i] = SDL_Threads[i+1];
|
||||
++i;
|
||||
}
|
||||
} else {
|
||||
SDL_maxthreads = 0;
|
||||
SDL_free(SDL_Threads);
|
||||
SDL_Threads = NULL;
|
||||
}
|
||||
#ifdef DEBUG_THREADS
|
||||
printf("Deleting thread (%d left - %d max)\n",
|
||||
SDL_numthreads, SDL_maxthreads);
|
||||
printf("Deleting thread (%d left - %d max)\n",
|
||||
SDL_numthreads, SDL_maxthreads);
|
||||
#endif
|
||||
}
|
||||
SDL_mutexV(thread_lock);
|
||||
}
|
||||
SDL_mutexV(thread_lock);
|
||||
|
||||
if ( SDL_Threads == NULL ) {
|
||||
SDL_ThreadsQuit();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -67,30 +67,13 @@ SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
|
|||
extern int _creating_thread_lock; /* SDL_threads.c */
|
||||
SDL_sem *sem;
|
||||
union semun init;
|
||||
key_t key;
|
||||
|
||||
sem = (SDL_sem *)SDL_malloc(sizeof(*sem));
|
||||
if ( sem == NULL ) {
|
||||
SDL_OutOfMemory();
|
||||
return(NULL);
|
||||
}
|
||||
/* This flag is true if we are creating the thread manager sem,
|
||||
which is never freed. This allows us to reuse the same sem.
|
||||
*/
|
||||
if ( _creating_thread_lock ) {
|
||||
key = 'S'+'D'+'L';
|
||||
} else {
|
||||
key = IPC_PRIVATE;
|
||||
}
|
||||
/* Keep trying to create sem while we don't own the requested key */
|
||||
do {
|
||||
if ( key != IPC_PRIVATE ) {
|
||||
++key;
|
||||
}
|
||||
sem->id = semget(key, 1, (0600|IPC_CREAT));
|
||||
} while ((sem->id < 0) && (key != IPC_PRIVATE) && (errno == EACCES));
|
||||
|
||||
/* Report the error if we eventually failed */
|
||||
sem->id = semget(IPC_PRIVATE, 1, (0600|IPC_CREAT));
|
||||
if ( sem->id < 0 ) {
|
||||
SDL_SetError("Couldn't create semaphore");
|
||||
SDL_free(sem);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue