diff options
| author | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2011-02-19 02:25:15 +0000 |
|---|---|---|
| committer | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2011-02-19 02:25:15 +0000 |
| commit | 3fc56dbe4ad7e9deaeaef8c209a68e1de986f6fa (patch) | |
| tree | c27c3a79fb402b0b3e47f23b434baddc4ce8a5c6 /macosx/plugins/Common/SDL/src/thread | |
| parent | bc54761a4332b875e1962a21f2858db598fa7c18 (diff) | |
| download | pcsxr-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')
9 files changed, 1113 insertions, 0 deletions
diff --git a/macosx/plugins/Common/SDL/src/thread/SDL_systhread.h b/macosx/plugins/Common/SDL/src/thread/SDL_systhread.h new file mode 100644 index 00000000..584f20db --- /dev/null +++ b/macosx/plugins/Common/SDL/src/thread/SDL_systhread.h @@ -0,0 +1,53 @@ +/* + 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" + +/* These are functions that need to be implemented by a port of SDL */ + +#ifndef _SDL_systhread_h +#define _SDL_systhread_h + +#include "SDL_thread.h" + +/* This function creates a thread, passing args to SDL_RunThread(), + saves a system-dependent thread id in thread->id, and returns 0 + on success. +*/ +#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD +extern int SDL_SYS_CreateThread(SDL_Thread * thread, void *args, + pfnSDL_CurrentBeginThread pfnBeginThread, + pfnSDL_CurrentEndThread pfnEndThread); +#else +extern int SDL_SYS_CreateThread(SDL_Thread * thread, void *args); +#endif + +/* This function does any necessary setup in the child thread */ +extern void SDL_SYS_SetupThread(void); + +/* This function waits for the thread to finish and frees any data + allocated by SDL_SYS_CreateThread() + */ +extern void SDL_SYS_WaitThread(SDL_Thread * thread); + +#endif /* _SDL_systhread_h */ + +/* vi: set ts=4 sw=4 expandtab: */ 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: */ diff --git a/macosx/plugins/Common/SDL/src/thread/SDL_thread_c.h b/macosx/plugins/Common/SDL/src/thread/SDL_thread_c.h new file mode 100644 index 00000000..4b670580 --- /dev/null +++ b/macosx/plugins/Common/SDL/src/thread/SDL_thread_c.h @@ -0,0 +1,45 @@ +/* + 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" + +#ifndef _SDL_thread_c_h +#define _SDL_thread_c_h + +/* Need the definitions of SYS_ThreadHandle */ +#include "pthread/SDL_systhread_c.h" +#include "../SDL_error_c.h" + +/* This is the system-independent thread info structure */ +struct SDL_Thread +{ + SDL_threadID threadid; + SYS_ThreadHandle handle; + int status; + SDL_error errbuf; + void *data; +}; + +/* This is the function called to run a thread */ +extern void SDL_RunThread(void *data); + +#endif /* _SDL_thread_c_h */ +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/macosx/plugins/Common/SDL/src/thread/pthread/SDL_syscond.c b/macosx/plugins/Common/SDL/src/thread/pthread/SDL_syscond.c new file mode 100644 index 00000000..547daa71 --- /dev/null +++ b/macosx/plugins/Common/SDL/src/thread/pthread/SDL_syscond.c @@ -0,0 +1,163 @@ +/* + 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" + +#include <sys/time.h> +#include <unistd.h> +#include <errno.h> +#include <pthread.h> + +#include "SDL_thread.h" +#include "SDL_sysmutex_c.h" + +struct SDL_cond +{ + pthread_cond_t cond; +}; + +/* Create a condition variable */ +SDL_cond * +SDL_CreateCond(void) +{ + SDL_cond *cond; + + cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); + if (cond) { + if (pthread_cond_init(&cond->cond, NULL) < 0) { + SDL_SetError("pthread_cond_init() failed"); + SDL_free(cond); + cond = NULL; + } + } + return (cond); +} + +/* Destroy a condition variable */ +void +SDL_DestroyCond(SDL_cond * cond) +{ + if (cond) { + pthread_cond_destroy(&cond->cond); + SDL_free(cond); + } +} + +/* Restart one of the threads that are waiting on the condition variable */ +int +SDL_CondSignal(SDL_cond * cond) +{ + int retval; + + if (!cond) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + retval = 0; + if (pthread_cond_signal(&cond->cond) != 0) { + SDL_SetError("pthread_cond_signal() failed"); + retval = -1; + } + return retval; +} + +/* Restart all threads that are waiting on the condition variable */ +int +SDL_CondBroadcast(SDL_cond * cond) +{ + int retval; + + if (!cond) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + retval = 0; + if (pthread_cond_broadcast(&cond->cond) != 0) { + SDL_SetError("pthread_cond_broadcast() failed"); + retval = -1; + } + return retval; +} + +int +SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms) +{ + int retval; + struct timeval delta; + struct timespec abstime; + + if (!cond) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + gettimeofday(&delta, NULL); + + abstime.tv_sec = delta.tv_sec + (ms / 1000); + abstime.tv_nsec = (delta.tv_usec + (ms % 1000) * 1000) * 1000; + if (abstime.tv_nsec > 1000000000) { + abstime.tv_sec += 1; + abstime.tv_nsec -= 1000000000; + } + + tryagain: + retval = pthread_cond_timedwait(&cond->cond, &mutex->id, &abstime); + switch (retval) { + case EINTR: + goto tryagain; + break; + case ETIMEDOUT: + retval = SDL_MUTEX_TIMEDOUT; + break; + case 0: + break; + default: + SDL_SetError("pthread_cond_timedwait() failed"); + retval = -1; + break; + } + return retval; +} + +/* Wait on the condition variable, unlocking the provided mutex. + The mutex must be locked before entering this function! + */ +int +SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex) +{ + int retval; + + if (!cond) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + retval = 0; + if (pthread_cond_wait(&cond->cond, &mutex->id) != 0) { + SDL_SetError("pthread_cond_wait() failed"); + retval = -1; + } + return retval; +} + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/macosx/plugins/Common/SDL/src/thread/pthread/SDL_sysmutex.c b/macosx/plugins/Common/SDL/src/thread/pthread/SDL_sysmutex.c new file mode 100644 index 00000000..701c7f60 --- /dev/null +++ b/macosx/plugins/Common/SDL/src/thread/pthread/SDL_sysmutex.c @@ -0,0 +1,161 @@ +/* + 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" + +#define _GNU_SOURCE +#include <pthread.h> + +#include "SDL_thread.h" + +#if !SDL_THREAD_PTHREAD_RECURSIVE_MUTEX && \ + !SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP +#define FAKE_RECURSIVE_MUTEX +#endif + +struct SDL_mutex +{ + pthread_mutex_t id; +#ifdef FAKE_RECURSIVE_MUTEX + int recursive; + pthread_t owner; +#endif +}; + +SDL_mutex * +SDL_CreateMutex(void) +{ + SDL_mutex *mutex; + pthread_mutexattr_t attr; + + /* Allocate the structure */ + mutex = (SDL_mutex *) SDL_calloc(1, sizeof(*mutex)); + if (mutex) { + pthread_mutexattr_init(&attr); +#if SDL_THREAD_PTHREAD_RECURSIVE_MUTEX + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); +#elif SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP + pthread_mutexattr_setkind_np(&attr, PTHREAD_MUTEX_RECURSIVE_NP); +#else + /* No extra attributes necessary */ +#endif + if (pthread_mutex_init(&mutex->id, &attr) != 0) { + SDL_SetError("pthread_mutex_init() failed"); + SDL_free(mutex); + mutex = NULL; + } + } else { + SDL_OutOfMemory(); + } + return (mutex); +} + +void +SDL_DestroyMutex(SDL_mutex * mutex) +{ + if (mutex) { + pthread_mutex_destroy(&mutex->id); + SDL_free(mutex); + } +} + +/* Lock the mutex */ +int +SDL_mutexP(SDL_mutex * mutex) +{ + int retval; +#ifdef FAKE_RECURSIVE_MUTEX + pthread_t this_thread; +#endif + + if (mutex == NULL) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + retval = 0; +#ifdef FAKE_RECURSIVE_MUTEX + this_thread = pthread_self(); + if (mutex->owner == this_thread) { + ++mutex->recursive; + } else { + /* The order of operations is important. + We set the locking thread id after we obtain the lock + so unlocks from other threads will fail. + */ + if (pthread_mutex_lock(&mutex->id) == 0) { + mutex->owner = this_thread; + mutex->recursive = 0; + } else { + SDL_SetError("pthread_mutex_lock() failed"); + retval = -1; + } + } +#else + if (pthread_mutex_lock(&mutex->id) < 0) { + SDL_SetError("pthread_mutex_lock() failed"); + retval = -1; + } +#endif + return retval; +} + +int +SDL_mutexV(SDL_mutex * mutex) +{ + int retval; + + if (mutex == NULL) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + retval = 0; +#ifdef FAKE_RECURSIVE_MUTEX + /* We can only unlock the mutex if we own it */ + if (pthread_self() == mutex->owner) { + if (mutex->recursive) { + --mutex->recursive; + } else { + /* The order of operations is important. + First reset the owner so another thread doesn't lock + the mutex and set the ownership before we reset it, + then release the lock semaphore. + */ + mutex->owner = 0; + pthread_mutex_unlock(&mutex->id); + } + } else { + SDL_SetError("mutex not owned by this thread"); + retval = -1; + } + +#else + if (pthread_mutex_unlock(&mutex->id) < 0) { + SDL_SetError("pthread_mutex_unlock() failed"); + retval = -1; + } +#endif /* FAKE_RECURSIVE_MUTEX */ + + return retval; +} + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/macosx/plugins/Common/SDL/src/thread/pthread/SDL_sysmutex_c.h b/macosx/plugins/Common/SDL/src/thread/pthread/SDL_sysmutex_c.h new file mode 100644 index 00000000..e28b1190 --- /dev/null +++ b/macosx/plugins/Common/SDL/src/thread/pthread/SDL_sysmutex_c.h @@ -0,0 +1,33 @@ +/* + 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" + +#ifndef _SDL_mutex_c_h +#define _SDL_mutex_c_h + +struct SDL_mutex +{ + pthread_mutex_t id; +}; + +#endif /* _SDL_mutex_c_h */ +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/macosx/plugins/Common/SDL/src/thread/pthread/SDL_syssem.c b/macosx/plugins/Common/SDL/src/thread/pthread/SDL_syssem.c new file mode 100644 index 00000000..adc38a65 --- /dev/null +++ b/macosx/plugins/Common/SDL/src/thread/pthread/SDL_syssem.c @@ -0,0 +1,225 @@ +/* + 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" + +/* An implementation of semaphores using mutexes and condition variables */ + +#include "SDL_thread.h" +#include "SDL_systhread_c.h" + + +#if SDL_THREADS_DISABLED + +SDL_sem * +SDL_CreateSemaphore(Uint32 initial_value) +{ + SDL_SetError("SDL not configured with thread support"); + return (SDL_sem *) 0; +} + +void +SDL_DestroySemaphore(SDL_sem * sem) +{ + return; +} + +int +SDL_SemTryWait(SDL_sem * sem) +{ + SDL_SetError("SDL not configured with thread support"); + return -1; +} + +int +SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout) +{ + SDL_SetError("SDL not configured with thread support"); + return -1; +} + +int +SDL_SemWait(SDL_sem * sem) +{ + SDL_SetError("SDL not configured with thread support"); + return -1; +} + +Uint32 +SDL_SemValue(SDL_sem * sem) +{ + return 0; +} + +int +SDL_SemPost(SDL_sem * sem) +{ + SDL_SetError("SDL not configured with thread support"); + return -1; +} + +#else + +struct SDL_semaphore +{ + Uint32 count; + Uint32 waiters_count; + SDL_mutex *count_lock; + SDL_cond *count_nonzero; +}; + +SDL_sem * +SDL_CreateSemaphore(Uint32 initial_value) +{ + SDL_sem *sem; + + sem = (SDL_sem *) SDL_malloc(sizeof(*sem)); + if (!sem) { + SDL_OutOfMemory(); + return NULL; + } + sem->count = initial_value; + sem->waiters_count = 0; + + sem->count_lock = SDL_CreateMutex(); + sem->count_nonzero = SDL_CreateCond(); + if (!sem->count_lock || !sem->count_nonzero) { + SDL_DestroySemaphore(sem); + return NULL; + } + + return sem; +} + +/* WARNING: + You cannot call this function when another thread is using the semaphore. +*/ +void +SDL_DestroySemaphore(SDL_sem * sem) +{ + if (sem) { + sem->count = 0xFFFFFFFF; + while (sem->waiters_count > 0) { + SDL_CondSignal(sem->count_nonzero); + //SDL_Delay(10); + } + SDL_DestroyCond(sem->count_nonzero); + if (sem->count_lock) { + SDL_mutexP(sem->count_lock); + SDL_mutexV(sem->count_lock); + SDL_DestroyMutex(sem->count_lock); + } + SDL_free(sem); + } +} + +int +SDL_SemTryWait(SDL_sem * sem) +{ + int retval; + + if (!sem) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + retval = SDL_MUTEX_TIMEDOUT; + SDL_LockMutex(sem->count_lock); + if (sem->count > 0) { + --sem->count; + retval = 0; + } + SDL_UnlockMutex(sem->count_lock); + + return retval; +} + +int +SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout) +{ + int retval; + + if (!sem) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + /* A timeout of 0 is an easy case */ + if (timeout == 0) { + return SDL_SemTryWait(sem); + } + + SDL_LockMutex(sem->count_lock); + ++sem->waiters_count; + retval = 0; + while ((sem->count == 0) && (retval != SDL_MUTEX_TIMEDOUT)) { + retval = SDL_CondWaitTimeout(sem->count_nonzero, + sem->count_lock, timeout); + } + --sem->waiters_count; + if (retval == 0) { + --sem->count; + } + SDL_UnlockMutex(sem->count_lock); + + return retval; +} + +int +SDL_SemWait(SDL_sem * sem) +{ + return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT); +} + +Uint32 +SDL_SemValue(SDL_sem * sem) +{ + Uint32 value; + + value = 0; + if (sem) { + SDL_LockMutex(sem->count_lock); + value = sem->count; + SDL_UnlockMutex(sem->count_lock); + } + return value; +} + +int +SDL_SemPost(SDL_sem * sem) +{ + if (!sem) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + SDL_LockMutex(sem->count_lock); + if (sem->waiters_count > 0) { + SDL_CondSignal(sem->count_nonzero); + } + ++sem->count; + SDL_UnlockMutex(sem->count_lock); + + return 0; +} + +#endif /* SDL_THREADS_DISABLED */ +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/macosx/plugins/Common/SDL/src/thread/pthread/SDL_systhread.c b/macosx/plugins/Common/SDL/src/thread/pthread/SDL_systhread.c new file mode 100644 index 00000000..c4f694fb --- /dev/null +++ b/macosx/plugins/Common/SDL/src/thread/pthread/SDL_systhread.c @@ -0,0 +1,114 @@ +/* + 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" + +#include <pthread.h> +#include <signal.h> + +#include "SDL_thread.h" +#include "../SDL_thread_c.h" +#include "../SDL_systhread.h" + +/* List of signals to mask in the subthreads */ +static const int sig_list[] = { + SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH, + SIGVTALRM, SIGPROF, 0 +}; + +#ifdef __RISCOS__ +/* RISC OS needs to know the main thread for + * it's timer and event processing. */ +int riscos_using_threads = 0; +SDL_threadID riscos_main_thread = 0; /* Thread running events */ +#endif + + +static void * +RunThread(void *data) +{ + SDL_RunThread(data); + pthread_exit((void *) 0); + return ((void *) 0); /* Prevent compiler warning */ +} + +int +SDL_SYS_CreateThread(SDL_Thread * thread, void *args) +{ + pthread_attr_t type; + + /* Set the thread attributes */ + if (pthread_attr_init(&type) != 0) { + SDL_SetError("Couldn't initialize pthread attributes"); + return (-1); + } + pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE); + + /* Create the thread and go! */ + if (pthread_create(&thread->handle, &type, RunThread, args) != 0) { + SDL_SetError("Not enough resources to create thread"); + return (-1); + } +#ifdef __RISCOS__ + if (riscos_using_threads == 0) { + riscos_using_threads = 1; + riscos_main_thread = SDL_ThreadID(); + } +#endif + + return (0); +} + +void +SDL_SYS_SetupThread(void) +{ + int i; + sigset_t mask; + + /* Mask asynchronous signals for this thread */ + sigemptyset(&mask); + for (i = 0; sig_list[i]; ++i) { + sigaddset(&mask, sig_list[i]); + } + pthread_sigmask(SIG_BLOCK, &mask, 0); + +#ifdef PTHREAD_CANCEL_ASYNCHRONOUS + /* Allow ourselves to be asynchronously cancelled */ + { + int oldstate; + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); + } +#endif +} + +SDL_threadID +SDL_ThreadID(void) +{ + return ((SDL_threadID) pthread_self()); +} + +void +SDL_SYS_WaitThread(SDL_Thread * thread) +{ + pthread_join(thread->handle, 0); +} + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/macosx/plugins/Common/SDL/src/thread/pthread/SDL_systhread_c.h b/macosx/plugins/Common/SDL/src/thread/pthread/SDL_systhread_c.h new file mode 100644 index 00000000..8da81da1 --- /dev/null +++ b/macosx/plugins/Common/SDL/src/thread/pthread/SDL_systhread_c.h @@ -0,0 +1,28 @@ +/* + 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" + +#include <pthread.h> + +typedef pthread_t SYS_ThreadHandle; + +/* vi: set ts=4 sw=4 expandtab: */ |
