summaryrefslogtreecommitdiff
path: root/macosx/plugins/Common/SDL/src/thread/SDL_thread.c
diff options
context:
space:
mode:
authorSND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97>2011-02-19 02:25:15 +0000
committerSND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97>2011-02-19 02:25:15 +0000
commit3fc56dbe4ad7e9deaeaef8c209a68e1de986f6fa (patch)
treec27c3a79fb402b0b3e47f23b434baddc4ce8a5c6 /macosx/plugins/Common/SDL/src/thread/SDL_thread.c
parentbc54761a4332b875e1962a21f2858db598fa7c18 (diff)
downloadpcsxr-3fc56dbe4ad7e9deaeaef8c209a68e1de986f6fa.tar.gz
-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
Diffstat (limited to 'macosx/plugins/Common/SDL/src/thread/SDL_thread.c')
-rw-r--r--macosx/plugins/Common/SDL/src/thread/SDL_thread.c291
1 files changed, 291 insertions, 0 deletions
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: */