From 3fc56dbe4ad7e9deaeaef8c209a68e1de986f6fa Mon Sep 17 00:00:00 2001 From: "SND\\weimingzhi_cp" Date: Sat, 19 Feb 2011 02:25:15 +0000 Subject: -Reverted some changes to make the code build again on Tiger. -Removed x86_64 from Deployment configuration. -macosx: Use SDL for sound plugin, removed Carbon backend. -(MaddTheSane)Fixed memory leaks (Patch #8427). git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@63548 e17a0e51-4ae3-4d35-97c3-1a29b211df97 --- macosx/plugins/Common/SDL/src/thread/SDL_thread.c | 291 ++++++++++++++++++++++ 1 file changed, 291 insertions(+) create mode 100644 macosx/plugins/Common/SDL/src/thread/SDL_thread.c (limited to 'macosx/plugins/Common/SDL/src/thread/SDL_thread.c') diff --git a/macosx/plugins/Common/SDL/src/thread/SDL_thread.c b/macosx/plugins/Common/SDL/src/thread/SDL_thread.c new file mode 100644 index 00000000..4d43a8e1 --- /dev/null +++ b/macosx/plugins/Common/SDL/src/thread/SDL_thread.c @@ -0,0 +1,291 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2010 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* System independent thread management routines for SDL */ + +#include "SDL_mutex.h" +#include "SDL_thread.h" +#include "SDL_thread_c.h" +#include "SDL_systhread.h" + +#define ARRAY_CHUNKSIZE 32 +/* The array of threads currently active in the application + (except the main thread) + The manipulation of an array here is safer than using a linked list. +*/ +static int SDL_maxthreads = 0; +static int SDL_numthreads = 0; +static SDL_Thread **SDL_Threads = NULL; +static SDL_mutex *thread_lock = NULL; + +static int +SDL_ThreadsInit(void) +{ + int retval; + + retval = 0; + thread_lock = SDL_CreateMutex(); + if (thread_lock == NULL) { + retval = -1; + } + return (retval); +} + +/* Routines for manipulating the thread list */ +static void +SDL_AddThread(SDL_Thread * thread) +{ + /* 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) { + if (SDL_ThreadsInit() < 0) { + return; + } + } + SDL_mutexP(thread_lock); + + /* Expand the list of threads, if necessary */ +#ifdef DEBUG_THREADS + printf("Adding thread (%d already - %d max)\n", + SDL_numthreads, SDL_maxthreads); +#endif + if (SDL_numthreads == SDL_maxthreads) { + SDL_Thread **threads; + threads = (SDL_Thread **) SDL_realloc(SDL_Threads, + (SDL_maxthreads + + ARRAY_CHUNKSIZE) * + (sizeof *threads)); + if (threads == NULL) { + SDL_OutOfMemory(); + goto done; + } + SDL_maxthreads += ARRAY_CHUNKSIZE; + SDL_Threads = threads; + } + SDL_Threads[SDL_numthreads++] = thread; + done: + SDL_mutexV(thread_lock); +} + +static void +SDL_DelThread(SDL_Thread * thread) +{ + int i; + + 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; + } +#ifdef DEBUG_THREADS + printf("Deleting thread (%d left - %d max)\n", + SDL_numthreads, SDL_maxthreads); +#endif + } + SDL_mutexV(thread_lock); + +#if 0 /* There could be memory corruption if another thread is starting */ + if (SDL_Threads == NULL) { + SDL_ThreadsQuit(); + } +#endif +} + +/* The default (non-thread-safe) global error variable */ +static SDL_error SDL_global_error; + +/* Routine to get the thread-specific error variable */ +SDL_error * +SDL_GetErrBuf(void) +{ + SDL_error *errbuf; + + errbuf = &SDL_global_error; + if (SDL_Threads) { + int i; + SDL_threadID this_thread; + + this_thread = SDL_ThreadID(); + SDL_mutexP(thread_lock); + for (i = 0; i < SDL_numthreads; ++i) { + if (this_thread == SDL_Threads[i]->threadid) { + errbuf = &SDL_Threads[i]->errbuf; + break; + } + } + SDL_mutexV(thread_lock); + } + return (errbuf); +} + + +/* Arguments and callback to setup and run the user thread function */ +typedef struct +{ + int (SDLCALL * func) (void *); + void *data; + SDL_Thread *info; + SDL_sem *wait; +} thread_args; + +void +SDL_RunThread(void *data) +{ + thread_args *args; + int (SDLCALL * userfunc) (void *); + void *userdata; + int *statusloc; + + /* Perform any system-dependent setup + - this function cannot fail, and cannot use SDL_SetError() + */ + SDL_SYS_SetupThread(); + + /* Get the thread id */ + args = (thread_args *) data; + args->info->threadid = SDL_ThreadID(); + + /* Figure out what function to run */ + userfunc = args->func; + userdata = args->data; + statusloc = &args->info->status; + + /* Wake up the parent thread */ + SDL_SemPost(args->wait); + + /* Run the function */ + *statusloc = userfunc(userdata); +} + +#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD +#undef SDL_CreateThread +DECLSPEC SDL_Thread *SDLCALL +SDL_CreateThread(int (SDLCALL * fn) (void *), void *data, + pfnSDL_CurrentBeginThread pfnBeginThread, + pfnSDL_CurrentEndThread pfnEndThread) +#else +DECLSPEC SDL_Thread *SDLCALL +SDL_CreateThread(int (SDLCALL * fn) (void *), void *data) +#endif +{ + SDL_Thread *thread; + thread_args *args; + int ret; + + /* Allocate memory for the thread info structure */ + thread = (SDL_Thread *) SDL_malloc(sizeof(*thread)); + if (thread == NULL) { + SDL_OutOfMemory(); + return (NULL); + } + SDL_memset(thread, 0, (sizeof *thread)); + thread->status = -1; + + /* Set up the arguments for the thread */ + args = (thread_args *) SDL_malloc(sizeof(*args)); + if (args == NULL) { + SDL_OutOfMemory(); + SDL_free(thread); + return (NULL); + } + args->func = fn; + args->data = data; + args->info = thread; + args->wait = SDL_CreateSemaphore(0); + if (args->wait == NULL) { + SDL_free(thread); + SDL_free(args); + return (NULL); + } + + /* Add the thread to the list of available threads */ + SDL_AddThread(thread); + + /* Create the thread and go! */ +#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD + ret = SDL_SYS_CreateThread(thread, args, pfnBeginThread, pfnEndThread); +#else + ret = SDL_SYS_CreateThread(thread, args); +#endif + if (ret >= 0) { + /* Wait for the thread function to use arguments */ + SDL_SemWait(args->wait); + } else { + /* Oops, failed. Gotta free everything */ + SDL_DelThread(thread); + SDL_free(thread); + thread = NULL; + } + SDL_DestroySemaphore(args->wait); + SDL_free(args); + + /* Everything is running now */ + return (thread); +} + +void +SDL_WaitThread(SDL_Thread * thread, int *status) +{ + if (thread) { + SDL_SYS_WaitThread(thread); + if (status) { + *status = thread->status; + } + SDL_DelThread(thread); + SDL_free(thread); + } +} + +SDL_threadID +SDL_GetThreadID(SDL_Thread * thread) +{ + SDL_threadID id; + + if (thread) { + id = thread->threadid; + } else { + id = SDL_ThreadID(); + } + return id; +} + +/* vi: set ts=4 sw=4 expandtab: */ -- cgit v1.2.3