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 int SDL_numthreads = 0;
|
||||||
static SDL_Thread **SDL_Threads = NULL;
|
static SDL_Thread **SDL_Threads = NULL;
|
||||||
static SDL_mutex *thread_lock = NULL;
|
static SDL_mutex *thread_lock = NULL;
|
||||||
int _creating_thread_lock = 0;
|
|
||||||
|
|
||||||
int SDL_ThreadsInit(void)
|
int SDL_ThreadsInit(void)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
retval = 0;
|
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();
|
thread_lock = SDL_CreateMutex();
|
||||||
_creating_thread_lock = 0;
|
|
||||||
if ( thread_lock == NULL ) {
|
if ( thread_lock == NULL ) {
|
||||||
retval = -1;
|
retval = -1;
|
||||||
}
|
}
|
||||||
|
@ -76,15 +69,13 @@ void SDL_ThreadsQuit()
|
||||||
/* Routines for manipulating the thread list */
|
/* Routines for manipulating the thread list */
|
||||||
static void SDL_AddThread(SDL_Thread *thread)
|
static void SDL_AddThread(SDL_Thread *thread)
|
||||||
{
|
{
|
||||||
SDL_Thread **threads;
|
|
||||||
|
|
||||||
/* WARNING:
|
/* WARNING:
|
||||||
If the very first threads are created simultaneously, then
|
If the very first threads are created simultaneously, then
|
||||||
there could be a race condition causing memory corruption.
|
there could be a race condition causing memory corruption.
|
||||||
In practice, this isn't a problem because by definition there
|
In practice, this isn't a problem because by definition there
|
||||||
is only one thread running the first time this is called.
|
is only one thread running the first time this is called.
|
||||||
*/
|
*/
|
||||||
if ( thread_lock == NULL ) {
|
if ( !thread_lock ) {
|
||||||
if ( SDL_ThreadsInit() < 0 ) {
|
if ( SDL_ThreadsInit() < 0 ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -97,17 +88,14 @@ static void SDL_AddThread(SDL_Thread *thread)
|
||||||
SDL_numthreads, SDL_maxthreads);
|
SDL_numthreads, SDL_maxthreads);
|
||||||
#endif
|
#endif
|
||||||
if ( SDL_numthreads == SDL_maxthreads ) {
|
if ( SDL_numthreads == SDL_maxthreads ) {
|
||||||
threads=(SDL_Thread **)SDL_malloc((SDL_maxthreads+ARRAY_CHUNKSIZE)*
|
SDL_Thread **threads;
|
||||||
(sizeof *threads));
|
threads = (SDL_Thread **)SDL_realloc(SDL_Threads,
|
||||||
|
(SDL_maxthreads+ARRAY_CHUNKSIZE)*(sizeof *threads));
|
||||||
if ( threads == NULL ) {
|
if ( threads == NULL ) {
|
||||||
SDL_OutOfMemory();
|
SDL_OutOfMemory();
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
SDL_memcpy(threads, SDL_Threads, SDL_numthreads*(sizeof *threads));
|
|
||||||
SDL_maxthreads += ARRAY_CHUNKSIZE;
|
SDL_maxthreads += ARRAY_CHUNKSIZE;
|
||||||
if ( SDL_Threads ) {
|
|
||||||
SDL_free(SDL_Threads);
|
|
||||||
}
|
|
||||||
SDL_Threads = threads;
|
SDL_Threads = threads;
|
||||||
}
|
}
|
||||||
SDL_Threads[SDL_numthreads++] = thread;
|
SDL_Threads[SDL_numthreads++] = thread;
|
||||||
|
@ -119,7 +107,9 @@ static void SDL_DelThread(SDL_Thread *thread)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if ( thread_lock ) {
|
if ( !thread_lock ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
SDL_mutexP(thread_lock);
|
SDL_mutexP(thread_lock);
|
||||||
for ( i=0; i<SDL_numthreads; ++i ) {
|
for ( i=0; i<SDL_numthreads; ++i ) {
|
||||||
if ( thread == SDL_Threads[i] ) {
|
if ( thread == SDL_Threads[i] ) {
|
||||||
|
@ -143,6 +133,9 @@ static void SDL_DelThread(SDL_Thread *thread)
|
||||||
#endif
|
#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 */
|
extern int _creating_thread_lock; /* SDL_threads.c */
|
||||||
SDL_sem *sem;
|
SDL_sem *sem;
|
||||||
union semun init;
|
union semun init;
|
||||||
key_t key;
|
|
||||||
|
|
||||||
sem = (SDL_sem *)SDL_malloc(sizeof(*sem));
|
sem = (SDL_sem *)SDL_malloc(sizeof(*sem));
|
||||||
if ( sem == NULL ) {
|
if ( sem == NULL ) {
|
||||||
SDL_OutOfMemory();
|
SDL_OutOfMemory();
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
/* This flag is true if we are creating the thread manager sem,
|
sem->id = semget(IPC_PRIVATE, 1, (0600|IPC_CREAT));
|
||||||
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 */
|
|
||||||
if ( sem->id < 0 ) {
|
if ( sem->id < 0 ) {
|
||||||
SDL_SetError("Couldn't create semaphore");
|
SDL_SetError("Couldn't create semaphore");
|
||||||
SDL_free(sem);
|
SDL_free(sem);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue