diff options
Diffstat (limited to '3rdparty/SDL/src/thread')
56 files changed, 6036 insertions, 0 deletions
diff --git a/3rdparty/SDL/src/thread/SDL_systhread.h b/3rdparty/SDL/src/thread/SDL_systhread.h new file mode 100644 index 0000000..a59ac50 --- /dev/null +++ b/3rdparty/SDL/src/thread/SDL_systhread.h @@ -0,0 +1,52 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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); + +/* This function kills the thread and returns */ +extern void SDL_SYS_KillThread(SDL_Thread *thread); + +#endif /* _SDL_systhread_h */ diff --git a/3rdparty/SDL/src/thread/SDL_thread.c b/3rdparty/SDL/src/thread/SDL_thread.c new file mode 100644 index 0000000..250371d --- /dev/null +++ b/3rdparty/SDL/src/thread/SDL_thread.c @@ -0,0 +1,300 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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; + +int SDL_ThreadsInit(void) +{ + int retval; + + retval = 0; + thread_lock = SDL_CreateMutex(); + if ( thread_lock == NULL ) { + retval = -1; + } + return(retval); +} + +/* This should never be called... + If this is called by SDL_Quit(), we don't know whether or not we should + clean up threads here. If any threads are still running after this call, + they will no longer have access to any per-thread data. + */ +void SDL_ThreadsQuit(void) +{ + SDL_mutex *mutex; + + mutex = thread_lock; + thread_lock = NULL; + if ( mutex != NULL ) { + SDL_DestroyMutex(mutex); + } +} + +/* 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; + Uint32 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); + } +} + +Uint32 SDL_GetThreadID(SDL_Thread *thread) +{ + Uint32 id; + + if ( thread ) { + id = thread->threadid; + } else { + id = SDL_ThreadID(); + } + return(id); +} + +void SDL_KillThread(SDL_Thread *thread) +{ + if ( thread ) { + SDL_SYS_KillThread(thread); + SDL_WaitThread(thread, NULL); + } +} + diff --git a/3rdparty/SDL/src/thread/SDL_thread_c.h b/3rdparty/SDL/src/thread/SDL_thread_c.h new file mode 100644 index 0000000..8af6e52 --- /dev/null +++ b/3rdparty/SDL/src/thread/SDL_thread_c.h @@ -0,0 +1,64 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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 */ +#if SDL_THREADS_DISABLED +#include "generic/SDL_systhread_c.h" +#elif SDL_THREAD_BEOS +#include "beos/SDL_systhread_c.h" +#elif SDL_THREAD_DC +#include "dc/SDL_systhread_c.h" +#elif SDL_THREAD_OS2 +#include "os2/SDL_systhread_c.h" +#elif SDL_THREAD_PTH +#include "pth/SDL_systhread_c.h" +#elif SDL_THREAD_PTHREAD +#include "pthread/SDL_systhread_c.h" +#elif SDL_THREAD_SPROC +#include "irix/SDL_systhread_c.h" +#elif SDL_THREAD_WIN32 +#include "win32/SDL_systhread_c.h" +#elif SDL_THREAD_SYMBIAN +#include "symbian/SDL_systhread_c.h" +#else +#error Need thread implementation for this platform +#include "generic/SDL_systhread_c.h" +#endif +#include "../SDL_error_c.h" + +/* This is the system-independent thread info structure */ +struct SDL_Thread { + Uint32 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 */ diff --git a/3rdparty/SDL/src/thread/beos/SDL_syssem.c b/3rdparty/SDL/src/thread/beos/SDL_syssem.c new file mode 100644 index 0000000..eba1944 --- /dev/null +++ b/3rdparty/SDL/src/thread/beos/SDL_syssem.c @@ -0,0 +1,142 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + +/* Semaphores in the BeOS environment */ + +#include <be/kernel/OS.h> + +#include "SDL_thread.h" + + +struct SDL_semaphore { + sem_id id; +}; + +/* Create a counting semaphore */ +SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) +{ + SDL_sem *sem; + + sem = (SDL_sem *)SDL_malloc(sizeof(*sem)); + if ( sem ) { + sem->id = create_sem(initial_value, "SDL semaphore"); + if ( sem->id < B_NO_ERROR ) { + SDL_SetError("create_sem() failed"); + SDL_free(sem); + sem = NULL; + } + } else { + SDL_OutOfMemory(); + } + return(sem); +} + +/* Free the semaphore */ +void SDL_DestroySemaphore(SDL_sem *sem) +{ + if ( sem ) { + if ( sem->id >= B_NO_ERROR ) { + delete_sem(sem->id); + } + SDL_free(sem); + } +} + +int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) +{ + int32 val; + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + tryagain: + if ( timeout == SDL_MUTEX_MAXWAIT ) { + val = acquire_sem(sem->id); + } else { + timeout *= 1000; /* BeOS uses a timeout in microseconds */ + val = acquire_sem_etc(sem->id, 1, B_RELATIVE_TIMEOUT, timeout); + } + switch (val) { + case B_INTERRUPTED: + goto tryagain; + case B_NO_ERROR: + retval = 0; + break; + case B_TIMED_OUT: + retval = SDL_MUTEX_TIMEDOUT; + break; + case B_WOULD_BLOCK: + retval = SDL_MUTEX_TIMEDOUT; + break; + default: + SDL_SetError("acquire_sem() failed"); + retval = -1; + break; + } + + return retval; +} + +int SDL_SemTryWait(SDL_sem *sem) +{ + return SDL_SemWaitTimeout(sem, 0); +} + +int SDL_SemWait(SDL_sem *sem) +{ + return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT); +} + +/* Returns the current count of the semaphore */ +Uint32 SDL_SemValue(SDL_sem *sem) +{ + int32 count; + Uint32 value; + + value = 0; + if ( sem ) { + get_sem_count(sem->id, &count); + if ( count > 0 ) { + value = (Uint32)count; + } + } + return value; +} + +/* Atomically increases the semaphore's count (not blocking) */ +int SDL_SemPost(SDL_sem *sem) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + if ( release_sem(sem->id) != B_NO_ERROR ) { + SDL_SetError("release_sem() failed"); + return -1; + } + return 0; +} diff --git a/3rdparty/SDL/src/thread/beos/SDL_systhread.c b/3rdparty/SDL/src/thread/beos/SDL_systhread.c new file mode 100644 index 0000000..63b5207 --- /dev/null +++ b/3rdparty/SDL/src/thread/beos/SDL_systhread.c @@ -0,0 +1,96 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + +/* BeOS thread management routines for SDL */ + +#include <stdio.h> +#include <signal.h> +#include <be/kernel/OS.h> + +#include "SDL_mutex.h" +#include "SDL_thread.h" +#include "../SDL_thread_c.h" +#include "../SDL_systhread.h" + + +static int sig_list[] = { + SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGWINCH, 0 +}; + +void SDL_MaskSignals(sigset_t *omask) +{ + sigset_t mask; + int i; + + sigemptyset(&mask); + for ( i=0; sig_list[i]; ++i ) { + sigaddset(&mask, sig_list[i]); + } + sigprocmask(SIG_BLOCK, &mask, omask); +} +void SDL_UnmaskSignals(sigset_t *omask) +{ + sigprocmask(SIG_SETMASK, omask, NULL); +} + +static int32 RunThread(void *data) +{ + SDL_RunThread(data); + return(0); +} + +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) +{ + /* Create the thread and go! */ + thread->handle=spawn_thread(RunThread, "SDL", B_NORMAL_PRIORITY, args); + if ( (thread->handle == B_NO_MORE_THREADS) || + (thread->handle == B_NO_MEMORY) ) { + SDL_SetError("Not enough resources to create thread"); + return(-1); + } + resume_thread(thread->handle); + return(0); +} + +void SDL_SYS_SetupThread(void) +{ + /* Mask asynchronous signals for this thread */ + SDL_MaskSignals(NULL); +} + +Uint32 SDL_ThreadID(void) +{ + return((Uint32)find_thread(NULL)); +} + +void SDL_SYS_WaitThread(SDL_Thread *thread) +{ + status_t the_status; + + wait_for_thread(thread->handle, &the_status); +} + +void SDL_SYS_KillThread(SDL_Thread *thread) +{ + kill_thread(thread->handle); +} diff --git a/3rdparty/SDL/src/thread/beos/SDL_systhread_c.h b/3rdparty/SDL/src/thread/beos/SDL_systhread_c.h new file mode 100644 index 0000000..f82548e --- /dev/null +++ b/3rdparty/SDL/src/thread/beos/SDL_systhread_c.h @@ -0,0 +1,31 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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 <signal.h> +#include <be/kernel/OS.h> + +typedef thread_id SYS_ThreadHandle; + +/* Functions needed to work with system threads in other portions of SDL */ +extern void SDL_MaskSignals(sigset_t *omask); +extern void SDL_UnmaskSignals(sigset_t *omask); diff --git a/3rdparty/SDL/src/thread/dc/SDL_syscond.c b/3rdparty/SDL/src/thread/dc/SDL_syscond.c new file mode 100644 index 0000000..f6e7223 --- /dev/null +++ b/3rdparty/SDL/src/thread/dc/SDL_syscond.c @@ -0,0 +1,215 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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 condition variables using semaphores and mutexes */ +/* + This implementation borrows heavily from the BeOS condition variable + implementation, written by Christopher Tate and Owen Smith. Thanks! + */ + +#include "SDL_thread.h" + +struct SDL_cond +{ + SDL_mutex *lock; + int waiting; + int signals; + SDL_sem *wait_sem; + SDL_sem *wait_done; +}; + +/* Create a condition variable */ +SDL_cond * SDL_CreateCond(void) +{ + SDL_cond *cond; + + cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); + if ( cond ) { + cond->lock = SDL_CreateMutex(); + cond->wait_sem = SDL_CreateSemaphore(0); + cond->wait_done = SDL_CreateSemaphore(0); + cond->waiting = cond->signals = 0; + if ( ! cond->lock || ! cond->wait_sem || ! cond->wait_done ) { + SDL_DestroyCond(cond); + cond = NULL; + } + } else { + SDL_OutOfMemory(); + } + return(cond); +} + +/* Destroy a condition variable */ +void SDL_DestroyCond(SDL_cond *cond) +{ + if ( cond ) { + if ( cond->wait_sem ) { + SDL_DestroySemaphore(cond->wait_sem); + } + if ( cond->wait_done ) { + SDL_DestroySemaphore(cond->wait_done); + } + if ( cond->lock ) { + SDL_DestroyMutex(cond->lock); + } + SDL_free(cond); + } +} + +/* Restart one of the threads that are waiting on the condition variable */ +int SDL_CondSignal(SDL_cond *cond) +{ + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + /* If there are waiting threads not already signalled, then + signal the condition and wait for the thread to respond. + */ + SDL_LockMutex(cond->lock); + if ( cond->waiting > cond->signals ) { + ++cond->signals; + SDL_SemPost(cond->wait_sem); + SDL_UnlockMutex(cond->lock); + SDL_SemWait(cond->wait_done); + } else { + SDL_UnlockMutex(cond->lock); + } + + return 0; +} + +/* Restart all threads that are waiting on the condition variable */ +int SDL_CondBroadcast(SDL_cond *cond) +{ + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + /* If there are waiting threads not already signalled, then + signal the condition and wait for the thread to respond. + */ + SDL_LockMutex(cond->lock); + if ( cond->waiting > cond->signals ) { + int i, num_waiting; + + num_waiting = (cond->waiting - cond->signals); + cond->signals = cond->waiting; + for ( i=0; i<num_waiting; ++i ) { + SDL_SemPost(cond->wait_sem); + } + /* Now all released threads are blocked here, waiting for us. + Collect them all (and win fabulous prizes!) :-) + */ + SDL_UnlockMutex(cond->lock); + for ( i=0; i<num_waiting; ++i ) { + SDL_SemWait(cond->wait_done); + } + } else { + SDL_UnlockMutex(cond->lock); + } + + return 0; +} + +/* Wait on the condition variable for at most 'ms' milliseconds. + The mutex must be locked before entering this function! + The mutex is unlocked during the wait, and locked again after the wait. + +Typical use: + +Thread A: + SDL_LockMutex(lock); + while ( ! condition ) { + SDL_CondWait(cond); + } + SDL_UnlockMutex(lock); + +Thread B: + SDL_LockMutex(lock); + ... + condition = true; + ... + SDL_UnlockMutex(lock); + */ +int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) +{ + int retval; + + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + /* Obtain the protection mutex, and increment the number of waiters. + This allows the signal mechanism to only perform a signal if there + are waiting threads. + */ + SDL_LockMutex(cond->lock); + ++cond->waiting; + SDL_UnlockMutex(cond->lock); + + /* Unlock the mutex, as is required by condition variable semantics */ + SDL_UnlockMutex(mutex); + + /* Wait for a signal */ + if ( ms == SDL_MUTEX_MAXWAIT ) { + retval = SDL_SemWait(cond->wait_sem); + } else { + retval = SDL_SemWaitTimeout(cond->wait_sem, ms); + } + + /* Let the signaler know we have completed the wait, otherwise + the signaler can race ahead and get the condition semaphore + if we are stopped between the mutex unlock and semaphore wait, + giving a deadlock. See the following URL for details: + http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html + */ + SDL_LockMutex(cond->lock); + if ( cond->signals > 0 ) { + /* If we timed out, we need to eat a condition signal */ + if ( retval > 0 ) { + SDL_SemWait(cond->wait_sem); + } + /* We always notify the signal thread that we are done */ + SDL_SemPost(cond->wait_done); + + /* Signal handshake complete */ + --cond->signals; + } + --cond->waiting; + SDL_UnlockMutex(cond->lock); + + /* Lock the mutex, as is required by condition variable semantics */ + SDL_LockMutex(mutex); + + return retval; +} + +/* Wait on the condition variable forever */ +int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex) +{ + return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT); +} diff --git a/3rdparty/SDL/src/thread/dc/SDL_syscond_c.h b/3rdparty/SDL/src/thread/dc/SDL_syscond_c.h new file mode 100644 index 0000000..1120b2d --- /dev/null +++ b/3rdparty/SDL/src/thread/dc/SDL_syscond_c.h @@ -0,0 +1,23 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + diff --git a/3rdparty/SDL/src/thread/dc/SDL_sysmutex.c b/3rdparty/SDL/src/thread/dc/SDL_sysmutex.c new file mode 100644 index 0000000..c6c4651 --- /dev/null +++ b/3rdparty/SDL/src/thread/dc/SDL_sysmutex.c @@ -0,0 +1,122 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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 mutexes using semaphores */ + +#include "SDL_thread.h" +#include "SDL_systhread_c.h" + +#include <arch/spinlock.h> + +struct SDL_mutex { + int recursive; + Uint32 owner; + spinlock_t mutex; +}; + +/* Create a mutex */ +SDL_mutex *SDL_CreateMutex(void) +{ + SDL_mutex *mutex; + + /* Allocate mutex memory */ + mutex = (SDL_mutex *)SDL_malloc(sizeof(*mutex)); + if ( mutex ) { + spinlock_init(&mutex->mutex); + mutex->recursive = 0; + mutex->owner = 0; + } else { + SDL_OutOfMemory(); + } + return mutex; +} + +/* Free the mutex */ +void SDL_DestroyMutex(SDL_mutex *mutex) +{ + if ( mutex ) { + SDL_free(mutex); + } +} + +/* Lock the semaphore */ +int SDL_mutexP(SDL_mutex *mutex) +{ +#if SDL_THREADS_DISABLED + return SDL_arraysize(return ),0; +#else + Uint32 this_thread; + + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + this_thread = SDL_ThreadID(); + 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. + */ + spinlock_lock(&mutex->mutex); + mutex->owner = this_thread; + mutex->recursive = 0; + } + + return 0; +#endif /* SDL_THREADS_DISABLED */ +} + +/* Unlock the mutex */ +int SDL_mutexV(SDL_mutex *mutex) +{ +#if SDL_THREADS_DISABLED + return 0; +#else + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + /* If we don't own the mutex, we can't unlock it */ + if ( SDL_ThreadID() != mutex->owner ) { + SDL_SetError("mutex not owned by this thread"); + return -1; + } + + 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; + spinlock_unlock(&mutex->mutex); + } + return 0; +#endif /* SDL_THREADS_DISABLED */ +} diff --git a/3rdparty/SDL/src/thread/dc/SDL_sysmutex_c.h b/3rdparty/SDL/src/thread/dc/SDL_sysmutex_c.h new file mode 100644 index 0000000..1120b2d --- /dev/null +++ b/3rdparty/SDL/src/thread/dc/SDL_sysmutex_c.h @@ -0,0 +1,23 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + diff --git a/3rdparty/SDL/src/thread/dc/SDL_syssem.c b/3rdparty/SDL/src/thread/dc/SDL_syssem.c new file mode 100644 index 0000000..9831ccd --- /dev/null +++ b/3rdparty/SDL/src/thread/dc/SDL_syssem.c @@ -0,0 +1,173 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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 <errno.h> + +#include "SDL_config.h" + +/* An implementation of semaphores using mutexes and condition variables */ + +#include "SDL_timer.h" +#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 + +#include <kos/sem.h> + +struct SDL_semaphore +{ + semaphore_t sem; +}; + +SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) +{ + return (SDL_sem *)sem_create(initial_value); +} + +/* WARNING: + You cannot call this function when another thread is using the semaphore. +*/ +void SDL_DestroySemaphore(SDL_sem *sem) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return; + } + + sem_destroy(&sem->sem); +} + +int SDL_SemTryWait(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + retval = sem_trywait(&sem->sem); + if (retval==0) return 0; + else return SDL_MUTEX_TIMEDOUT; + + 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); + } + + retval = sem_wait_timed(&sem->sem,timeout); + if (retval==-1) retval= SDL_MUTEX_TIMEDOUT; + + return retval; +} + +int SDL_SemWait(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + while ( ((retval = sem_wait(&sem->sem)) == -1) && (errno == EINTR) ) {} + return retval; +} + +Uint32 SDL_SemValue(SDL_sem *sem) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + return sem_count(&sem->sem); +} + +int SDL_SemPost(SDL_sem *sem) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + sem_signal(&sem->sem); + return 0; +} + +#endif /* SDL_THREADS_DISABLED */ diff --git a/3rdparty/SDL/src/thread/dc/SDL_syssem_c.h b/3rdparty/SDL/src/thread/dc/SDL_syssem_c.h new file mode 100644 index 0000000..1120b2d --- /dev/null +++ b/3rdparty/SDL/src/thread/dc/SDL_syssem_c.h @@ -0,0 +1,23 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + diff --git a/3rdparty/SDL/src/thread/dc/SDL_systhread.c b/3rdparty/SDL/src/thread/dc/SDL_systhread.c new file mode 100644 index 0000000..dd26675 --- /dev/null +++ b/3rdparty/SDL/src/thread/dc/SDL_systhread.c @@ -0,0 +1,60 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + +/* Thread management routines for SDL */ + +#include "SDL_thread.h" +#include "../SDL_thread_c.h" +#include "../SDL_systhread.h" + +#include <kos/thread.h> + +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) +{ + thread->handle = thd_create(SDL_RunThread,args); + if (thread->handle == NULL) { + SDL_SetError("Not enough resources to create thread"); + return(-1); + } + return(0); +} + +void SDL_SYS_SetupThread(void) +{ + return; +} + +Uint32 SDL_ThreadID(void) +{ + return (Uint32)thd_get_current(); +} + +void SDL_SYS_WaitThread(SDL_Thread *thread) +{ + thd_wait(thread->handle); +} + +void SDL_SYS_KillThread(SDL_Thread *thread) +{ + thd_destroy(thread->handle); +} diff --git a/3rdparty/SDL/src/thread/dc/SDL_systhread_c.h b/3rdparty/SDL/src/thread/dc/SDL_systhread_c.h new file mode 100644 index 0000000..3cda1a4 --- /dev/null +++ b/3rdparty/SDL/src/thread/dc/SDL_systhread_c.h @@ -0,0 +1,24 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +typedef struct kthread* SYS_ThreadHandle; diff --git a/3rdparty/SDL/src/thread/generic/SDL_syscond.c b/3rdparty/SDL/src/thread/generic/SDL_syscond.c new file mode 100644 index 0000000..f6e7223 --- /dev/null +++ b/3rdparty/SDL/src/thread/generic/SDL_syscond.c @@ -0,0 +1,215 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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 condition variables using semaphores and mutexes */ +/* + This implementation borrows heavily from the BeOS condition variable + implementation, written by Christopher Tate and Owen Smith. Thanks! + */ + +#include "SDL_thread.h" + +struct SDL_cond +{ + SDL_mutex *lock; + int waiting; + int signals; + SDL_sem *wait_sem; + SDL_sem *wait_done; +}; + +/* Create a condition variable */ +SDL_cond * SDL_CreateCond(void) +{ + SDL_cond *cond; + + cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); + if ( cond ) { + cond->lock = SDL_CreateMutex(); + cond->wait_sem = SDL_CreateSemaphore(0); + cond->wait_done = SDL_CreateSemaphore(0); + cond->waiting = cond->signals = 0; + if ( ! cond->lock || ! cond->wait_sem || ! cond->wait_done ) { + SDL_DestroyCond(cond); + cond = NULL; + } + } else { + SDL_OutOfMemory(); + } + return(cond); +} + +/* Destroy a condition variable */ +void SDL_DestroyCond(SDL_cond *cond) +{ + if ( cond ) { + if ( cond->wait_sem ) { + SDL_DestroySemaphore(cond->wait_sem); + } + if ( cond->wait_done ) { + SDL_DestroySemaphore(cond->wait_done); + } + if ( cond->lock ) { + SDL_DestroyMutex(cond->lock); + } + SDL_free(cond); + } +} + +/* Restart one of the threads that are waiting on the condition variable */ +int SDL_CondSignal(SDL_cond *cond) +{ + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + /* If there are waiting threads not already signalled, then + signal the condition and wait for the thread to respond. + */ + SDL_LockMutex(cond->lock); + if ( cond->waiting > cond->signals ) { + ++cond->signals; + SDL_SemPost(cond->wait_sem); + SDL_UnlockMutex(cond->lock); + SDL_SemWait(cond->wait_done); + } else { + SDL_UnlockMutex(cond->lock); + } + + return 0; +} + +/* Restart all threads that are waiting on the condition variable */ +int SDL_CondBroadcast(SDL_cond *cond) +{ + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + /* If there are waiting threads not already signalled, then + signal the condition and wait for the thread to respond. + */ + SDL_LockMutex(cond->lock); + if ( cond->waiting > cond->signals ) { + int i, num_waiting; + + num_waiting = (cond->waiting - cond->signals); + cond->signals = cond->waiting; + for ( i=0; i<num_waiting; ++i ) { + SDL_SemPost(cond->wait_sem); + } + /* Now all released threads are blocked here, waiting for us. + Collect them all (and win fabulous prizes!) :-) + */ + SDL_UnlockMutex(cond->lock); + for ( i=0; i<num_waiting; ++i ) { + SDL_SemWait(cond->wait_done); + } + } else { + SDL_UnlockMutex(cond->lock); + } + + return 0; +} + +/* Wait on the condition variable for at most 'ms' milliseconds. + The mutex must be locked before entering this function! + The mutex is unlocked during the wait, and locked again after the wait. + +Typical use: + +Thread A: + SDL_LockMutex(lock); + while ( ! condition ) { + SDL_CondWait(cond); + } + SDL_UnlockMutex(lock); + +Thread B: + SDL_LockMutex(lock); + ... + condition = true; + ... + SDL_UnlockMutex(lock); + */ +int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) +{ + int retval; + + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + /* Obtain the protection mutex, and increment the number of waiters. + This allows the signal mechanism to only perform a signal if there + are waiting threads. + */ + SDL_LockMutex(cond->lock); + ++cond->waiting; + SDL_UnlockMutex(cond->lock); + + /* Unlock the mutex, as is required by condition variable semantics */ + SDL_UnlockMutex(mutex); + + /* Wait for a signal */ + if ( ms == SDL_MUTEX_MAXWAIT ) { + retval = SDL_SemWait(cond->wait_sem); + } else { + retval = SDL_SemWaitTimeout(cond->wait_sem, ms); + } + + /* Let the signaler know we have completed the wait, otherwise + the signaler can race ahead and get the condition semaphore + if we are stopped between the mutex unlock and semaphore wait, + giving a deadlock. See the following URL for details: + http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html + */ + SDL_LockMutex(cond->lock); + if ( cond->signals > 0 ) { + /* If we timed out, we need to eat a condition signal */ + if ( retval > 0 ) { + SDL_SemWait(cond->wait_sem); + } + /* We always notify the signal thread that we are done */ + SDL_SemPost(cond->wait_done); + + /* Signal handshake complete */ + --cond->signals; + } + --cond->waiting; + SDL_UnlockMutex(cond->lock); + + /* Lock the mutex, as is required by condition variable semantics */ + SDL_LockMutex(mutex); + + return retval; +} + +/* Wait on the condition variable forever */ +int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex) +{ + return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT); +} diff --git a/3rdparty/SDL/src/thread/generic/SDL_sysmutex.c b/3rdparty/SDL/src/thread/generic/SDL_sysmutex.c new file mode 100644 index 0000000..ecfea87 --- /dev/null +++ b/3rdparty/SDL/src/thread/generic/SDL_sysmutex.c @@ -0,0 +1,129 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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 mutexes using semaphores */ + +#include "SDL_thread.h" +#include "SDL_systhread_c.h" + + +struct SDL_mutex { + int recursive; + Uint32 owner; + SDL_sem *sem; +}; + +/* Create a mutex */ +SDL_mutex *SDL_CreateMutex(void) +{ + SDL_mutex *mutex; + + /* Allocate mutex memory */ + mutex = (SDL_mutex *)SDL_malloc(sizeof(*mutex)); + if ( mutex ) { + /* Create the mutex semaphore, with initial value 1 */ + mutex->sem = SDL_CreateSemaphore(1); + mutex->recursive = 0; + mutex->owner = 0; + if ( ! mutex->sem ) { + SDL_free(mutex); + mutex = NULL; + } + } else { + SDL_OutOfMemory(); + } + return mutex; +} + +/* Free the mutex */ +void SDL_DestroyMutex(SDL_mutex *mutex) +{ + if ( mutex ) { + if ( mutex->sem ) { + SDL_DestroySemaphore(mutex->sem); + } + SDL_free(mutex); + } +} + +/* Lock the semaphore */ +int SDL_mutexP(SDL_mutex *mutex) +{ +#if SDL_THREADS_DISABLED + return 0; +#else + Uint32 this_thread; + + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + this_thread = SDL_ThreadID(); + 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. + */ + SDL_SemWait(mutex->sem); + mutex->owner = this_thread; + mutex->recursive = 0; + } + + return 0; +#endif /* SDL_THREADS_DISABLED */ +} + +/* Unlock the mutex */ +int SDL_mutexV(SDL_mutex *mutex) +{ +#if SDL_THREADS_DISABLED + return 0; +#else + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + /* If we don't own the mutex, we can't unlock it */ + if ( SDL_ThreadID() != mutex->owner ) { + SDL_SetError("mutex not owned by this thread"); + return -1; + } + + 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; + SDL_SemPost(mutex->sem); + } + return 0; +#endif /* SDL_THREADS_DISABLED */ +} diff --git a/3rdparty/SDL/src/thread/generic/SDL_sysmutex_c.h b/3rdparty/SDL/src/thread/generic/SDL_sysmutex_c.h new file mode 100644 index 0000000..1120b2d --- /dev/null +++ b/3rdparty/SDL/src/thread/generic/SDL_sysmutex_c.h @@ -0,0 +1,23 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + diff --git a/3rdparty/SDL/src/thread/generic/SDL_syssem.c b/3rdparty/SDL/src/thread/generic/SDL_syssem.c new file mode 100644 index 0000000..1d289c0 --- /dev/null +++ b/3rdparty/SDL/src/thread/generic/SDL_syssem.c @@ -0,0 +1,211 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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_timer.h" +#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 */ diff --git a/3rdparty/SDL/src/thread/generic/SDL_systhread.c b/3rdparty/SDL/src/thread/generic/SDL_systhread.c new file mode 100644 index 0000000..c380121 --- /dev/null +++ b/3rdparty/SDL/src/thread/generic/SDL_systhread.c @@ -0,0 +1,54 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + +/* Thread management routines for SDL */ + +#include "SDL_thread.h" +#include "../SDL_systhread.h" + +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) +{ + SDL_SetError("Threads are not supported on this platform"); + return(-1); +} + +void SDL_SYS_SetupThread(void) +{ + return; +} + +Uint32 SDL_ThreadID(void) +{ + return(0); +} + +void SDL_SYS_WaitThread(SDL_Thread *thread) +{ + return; +} + +void SDL_SYS_KillThread(SDL_Thread *thread) +{ + return; +} + diff --git a/3rdparty/SDL/src/thread/generic/SDL_systhread_c.h b/3rdparty/SDL/src/thread/generic/SDL_systhread_c.h new file mode 100644 index 0000000..1535b50 --- /dev/null +++ b/3rdparty/SDL/src/thread/generic/SDL_systhread_c.h @@ -0,0 +1,25 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Stub until we implement threads on this platform */ +typedef int SYS_ThreadHandle; diff --git a/3rdparty/SDL/src/thread/irix/SDL_syssem.c b/3rdparty/SDL/src/thread/irix/SDL_syssem.c new file mode 100644 index 0000000..208c379 --- /dev/null +++ b/3rdparty/SDL/src/thread/irix/SDL_syssem.c @@ -0,0 +1,219 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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 "SDL_thread.h" +#include "SDL_timer.h" + + +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/sem.h> +#include <errno.h> + +#include "SDL_error.h" +#include "SDL_thread.h" + + +struct SDL_semaphore { + int id; +}; + +/* Not defined by many operating systems, use configure to detect */ +/* +#if !defined(HAVE_SEMUN) +union semun { + int val; + struct semid_ds *buf; + ushort *array; +}; +#endif +*/ + +static struct sembuf op_trywait[2] = { + { 0, -1, (IPC_NOWAIT|SEM_UNDO) } /* Decrement semaphore, no block */ +}; +static struct sembuf op_wait[2] = { + { 0, -1, SEM_UNDO } /* Decrement semaphore */ +}; +static struct sembuf op_post[1] = { + { 0, 1, (IPC_NOWAIT|SEM_UNDO) } /* Increment semaphore */ +}; + +/* Create a blockable semaphore */ +SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) +{ + extern int _creating_thread_lock; /* SDL_threads.c */ + SDL_sem *sem; + union semun init; + + sem = (SDL_sem *)SDL_malloc(sizeof(*sem)); + if ( sem == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + sem->id = semget(IPC_PRIVATE, 1, (0600|IPC_CREAT)); + if ( sem->id < 0 ) { + SDL_SetError("Couldn't create semaphore"); + SDL_free(sem); + return(NULL); + } + init.val = initial_value; /* Initialize semaphore */ + semctl(sem->id, 0, SETVAL, init); + return(sem); +} + +void SDL_DestroySemaphore(SDL_sem *sem) +{ + if ( sem ) { +#ifdef __IRIX__ + semctl(sem->id, 0, IPC_RMID); +#else + union semun dummy; + dummy.val = 0; + semctl(sem->id, 0, IPC_RMID, dummy); +#endif + SDL_free(sem); + } +} + +int SDL_SemTryWait(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + retval = 0; + tryagain: + if ( semop(sem->id, op_trywait, 1) < 0 ) { + if ( errno == EINTR ) { + goto tryagain; + } + retval = SDL_MUTEX_TIMEDOUT; + } + return retval; +} + +int SDL_SemWait(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + retval = 0; + tryagain: + if ( semop(sem->id, op_wait, 1) < 0 ) { + if ( errno == EINTR ) { + goto tryagain; + } + SDL_SetError("Semaphore operation error"); + retval = -1; + } + return retval; +} + +int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + /* Try the easy cases first */ + if ( timeout == 0 ) { + return SDL_SemTryWait(sem); + } + if ( timeout == SDL_MUTEX_MAXWAIT ) { + return SDL_SemWait(sem); + } + + /* Ack! We have to busy wait... */ + timeout += SDL_GetTicks(); + do { + retval = SDL_SemTryWait(sem); + if ( retval == 0 ) { + break; + } + SDL_Delay(1); + } while ( SDL_GetTicks() < timeout ); + + return retval; +} + +Uint32 SDL_SemValue(SDL_sem *sem) +{ + int semval; + Uint32 value; + + value = 0; + if ( sem ) { + tryagain: +#ifdef __IRIX__ + semval = semctl(sem->id, 0, GETVAL); +#else + { + union semun arg; + arg.val = 0; + semval = semctl(sem->id, 0, GETVAL, arg); + } +#endif + if ( semval < 0 ) { + if ( errno == EINTR ) { + goto tryagain; + } + } else { + value = (Uint32)semval; + } + } + return value; +} + +int SDL_SemPost(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + retval = 0; + tryagain: + if ( semop(sem->id, op_post, 1) < 0 ) { + if ( errno == EINTR ) { + goto tryagain; + } + SDL_SetError("Semaphore operation error"); + retval = -1; + } + return retval; +} diff --git a/3rdparty/SDL/src/thread/irix/SDL_systhread.c b/3rdparty/SDL/src/thread/irix/SDL_systhread.c new file mode 100644 index 0000000..7ae7fc6 --- /dev/null +++ b/3rdparty/SDL/src/thread/irix/SDL_systhread.c @@ -0,0 +1,85 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + +/* IRIX thread management routines for SDL */ + +#include <errno.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/prctl.h> + +#include "SDL_thread.h" +#include "../SDL_systhread.h" + + +static int sig_list[] = { + SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCLD, SIGWINCH, + SIGVTALRM, SIGPROF, 0 +}; + + +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) +{ + /* Create the thread and go! */ + if ( sproc(SDL_RunThread, PR_SALL, args) < 0 ) { + SDL_SetError("Not enough resources to create thread"); + return(-1); + } + 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]); + } + sigprocmask(SIG_BLOCK, &mask, NULL); +} + +/* WARNING: This may not work for systems with 64-bit pid_t */ +Uint32 SDL_ThreadID(void) +{ + return((Uint32)getpid()); +} + +/* WARNING: This may not work for systems with 64-bit pid_t */ +void SDL_WaitThread(SDL_Thread *thread, int *status) +{ + errno = 0; + while ( errno != ECHILD ) { + waitpid(thread->handle, NULL, 0); + } +} + +/* WARNING: This may not work for systems with 64-bit pid_t */ +void SDL_KillThread(SDL_Thread *thread) +{ + kill(thread->handle, SIGKILL); +} + diff --git a/3rdparty/SDL/src/thread/irix/SDL_systhread_c.h b/3rdparty/SDL/src/thread/irix/SDL_systhread_c.h new file mode 100644 index 0000000..ee28634 --- /dev/null +++ b/3rdparty/SDL/src/thread/irix/SDL_systhread_c.h @@ -0,0 +1,27 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <sys/types.h> + +typedef pid_t SYS_ThreadHandle; + diff --git a/3rdparty/SDL/src/thread/os2/SDL_syscond.c b/3rdparty/SDL/src/thread/os2/SDL_syscond.c new file mode 100644 index 0000000..3e80594 --- /dev/null +++ b/3rdparty/SDL/src/thread/os2/SDL_syscond.c @@ -0,0 +1,215 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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 condition variables using semaphores and mutexes */ +/* + This implementation borrows heavily from the BeOS condition variable + implementation, written by Christopher Tate and Owen Smith. Thanks! + */ + +#include "SDL_thread.h" + +struct SDL_cond +{ + SDL_mutex *lock; + int waiting; + int signals; + SDL_sem *wait_sem; + SDL_sem *wait_done; +}; + +/* Create a condition variable */ +DECLSPEC SDL_cond * SDLCALL SDL_CreateCond(void) +{ + SDL_cond *cond; + + cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); + if ( cond ) { + cond->lock = SDL_CreateMutex(); + cond->wait_sem = SDL_CreateSemaphore(0); + cond->wait_done = SDL_CreateSemaphore(0); + cond->waiting = cond->signals = 0; + if ( ! cond->lock || ! cond->wait_sem || ! cond->wait_done ) { + SDL_DestroyCond(cond); + cond = NULL; + } + } else { + SDL_OutOfMemory(); + } + return(cond); +} + +/* Destroy a condition variable */ +DECLSPEC void SDLCALL SDL_DestroyCond(SDL_cond *cond) +{ + if ( cond ) { + if ( cond->wait_sem ) { + SDL_DestroySemaphore(cond->wait_sem); + } + if ( cond->wait_done ) { + SDL_DestroySemaphore(cond->wait_done); + } + if ( cond->lock ) { + SDL_DestroyMutex(cond->lock); + } + SDL_free(cond); + } +} + +/* Restart one of the threads that are waiting on the condition variable */ +DECLSPEC int SDLCALL SDL_CondSignal(SDL_cond *cond) +{ + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + /* If there are waiting threads not already signalled, then + signal the condition and wait for the thread to respond. + */ + SDL_LockMutex(cond->lock); + if ( cond->waiting > cond->signals ) { + ++cond->signals; + SDL_SemPost(cond->wait_sem); + SDL_UnlockMutex(cond->lock); + SDL_SemWait(cond->wait_done); + } else { + SDL_UnlockMutex(cond->lock); + } + + return 0; +} + +/* Restart all threads that are waiting on the condition variable */ +DECLSPEC int SDLCALL SDL_CondBroadcast(SDL_cond *cond) +{ + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + /* If there are waiting threads not already signalled, then + signal the condition and wait for the thread to respond. + */ + SDL_LockMutex(cond->lock); + if ( cond->waiting > cond->signals ) { + int i, num_waiting; + + num_waiting = (cond->waiting - cond->signals); + cond->signals = cond->waiting; + for ( i=0; i<num_waiting; ++i ) { + SDL_SemPost(cond->wait_sem); + } + /* Now all released threads are blocked here, waiting for us. + Collect them all (and win fabulous prizes!) :-) + */ + SDL_UnlockMutex(cond->lock); + for ( i=0; i<num_waiting; ++i ) { + SDL_SemWait(cond->wait_done); + } + } else { + SDL_UnlockMutex(cond->lock); + } + + return 0; +} + +/* Wait on the condition variable for at most 'ms' milliseconds. + The mutex must be locked before entering this function! + The mutex is unlocked during the wait, and locked again after the wait. + +Typical use: + +Thread A: + SDL_LockMutex(lock); + while ( ! condition ) { + SDL_CondWait(cond); + } + SDL_UnlockMutex(lock); + +Thread B: + SDL_LockMutex(lock); + ... + condition = true; + ... + SDL_UnlockMutex(lock); + */ +DECLSPEC int SDLCALL SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) +{ + int retval; + + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + /* Obtain the protection mutex, and increment the number of waiters. + This allows the signal mechanism to only perform a signal if there + are waiting threads. + */ + SDL_LockMutex(cond->lock); + ++cond->waiting; + SDL_UnlockMutex(cond->lock); + + /* Unlock the mutex, as is required by condition variable semantics */ + SDL_UnlockMutex(mutex); + + /* Wait for a signal */ + if ( ms == SDL_MUTEX_MAXWAIT ) { + retval = SDL_SemWait(cond->wait_sem); + } else { + retval = SDL_SemWaitTimeout(cond->wait_sem, ms); + } + + /* Let the signaler know we have completed the wait, otherwise + the signaler can race ahead and get the condition semaphore + if we are stopped between the mutex unlock and semaphore wait, + giving a deadlock. See the following URL for details: + http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html + */ + SDL_LockMutex(cond->lock); + if ( cond->signals > 0 ) { + /* If we timed out, we need to eat a condition signal */ + if ( retval > 0 ) { + SDL_SemWait(cond->wait_sem); + } + /* We always notify the signal thread that we are done */ + SDL_SemPost(cond->wait_done); + + /* Signal handshake complete */ + --cond->signals; + } + --cond->waiting; + SDL_UnlockMutex(cond->lock); + + /* Lock the mutex, as is required by condition variable semantics */ + SDL_LockMutex(mutex); + + return retval; +} + +/* Wait on the condition variable forever */ +DECLSPEC int SDLCALL SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex) +{ + return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT); +} diff --git a/3rdparty/SDL/src/thread/os2/SDL_syscond_c.h b/3rdparty/SDL/src/thread/os2/SDL_syscond_c.h new file mode 100644 index 0000000..1120b2d --- /dev/null +++ b/3rdparty/SDL/src/thread/os2/SDL_syscond_c.h @@ -0,0 +1,23 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + diff --git a/3rdparty/SDL/src/thread/os2/SDL_sysmutex.c b/3rdparty/SDL/src/thread/os2/SDL_sysmutex.c new file mode 100644 index 0000000..1e21897 --- /dev/null +++ b/3rdparty/SDL/src/thread/os2/SDL_sysmutex.c @@ -0,0 +1,108 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + +/* Mutex functions using the OS/2 API */ + +#define INCL_DOSERRORS +#define INCL_DOSSEMAPHORES +#include <os2.h> + +#include "SDL_mutex.h" + + +struct SDL_mutex { + HMTX hmtxID; +}; + +/* Create a mutex */ +DECLSPEC SDL_mutex * SDLCALL SDL_CreateMutex(void) +{ + SDL_mutex *mutex; + APIRET ulrc; + + /* Allocate mutex memory */ + mutex = (SDL_mutex *)SDL_malloc(sizeof(*mutex)); + if (mutex) + { + /* Create the mutex, with initial value signaled */ + ulrc = DosCreateMutexSem(NULL, // Create unnamed semaphore + &(mutex->hmtxID), // Pointer to handle + 0L, // Flags: create it private (not shared) + FALSE); // Initial value: unowned + if (ulrc!=NO_ERROR) + { + SDL_SetError("Couldn't create mutex"); + SDL_free(mutex); + mutex = NULL; + } + } else { + SDL_OutOfMemory(); + } + return(mutex); +} + +/* Free the mutex */ +DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_mutex *mutex) +{ + if ( mutex ) + { + if ( mutex->hmtxID ) + { + DosCloseMutexSem(mutex->hmtxID); + mutex->hmtxID = 0; + } + SDL_free(mutex); + } +} + +/* Lock the mutex */ +DECLSPEC int SDLCALL SDL_mutexP(SDL_mutex *mutex) +{ + if ( mutex == NULL ) + { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + if ( DosRequestMutexSem(mutex->hmtxID, SEM_INDEFINITE_WAIT) != NO_ERROR ) + { + SDL_SetError("Couldn't wait on mutex"); + return -1; + } + return(0); +} + +/* Unlock the mutex */ +DECLSPEC int SDLCALL SDL_mutexV(SDL_mutex *mutex) +{ + if ( mutex == NULL ) + { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + if ( DosReleaseMutexSem(mutex->hmtxID) != NO_ERROR ) + { + SDL_SetError("Couldn't release mutex"); + return -1; + } + return(0); +} diff --git a/3rdparty/SDL/src/thread/os2/SDL_syssem.c b/3rdparty/SDL/src/thread/os2/SDL_syssem.c new file mode 100644 index 0000000..d6dfba6 --- /dev/null +++ b/3rdparty/SDL/src/thread/os2/SDL_syssem.c @@ -0,0 +1,192 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + +/* Semaphore functions using the OS/2 API */ + +#define INCL_DOS +#define INCL_DOSERRORS +#define INCL_DOSSEMAPHORES +#include <os2.h> + +#include "SDL_thread.h" +#include "SDL_timer.h" + + +struct SDL_semaphore { + HMTX id; + HEV changed; + Uint32 value; +}; + + +/* Create a semaphore */ +DECLSPEC SDL_sem * SDLCALL SDL_CreateSemaphore(Uint32 initial_value) +{ + SDL_sem *sem; + ULONG ulrc; + + /* Allocate sem memory */ + sem = (SDL_sem *)SDL_malloc(sizeof(*sem)); + if ( sem ) { + /* Create the mutex semaphore */ + ulrc = DosCreateMutexSem(NULL,&(sem->id),0,TRUE); + if ( ulrc ) { + SDL_SetError("Couldn't create semaphore"); + SDL_free(sem); + sem = NULL; + } else + { + DosCreateEventSem(NULL, &(sem->changed), 0, FALSE); + sem->value = initial_value; + DosReleaseMutexSem(sem->id); + } + } else { + SDL_OutOfMemory(); + } + return(sem); +} + +/* Free the semaphore */ +DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_sem *sem) +{ + if ( sem ) { + if ( sem->id ) { + DosCloseEventSem(sem->changed); + DosCloseMutexSem(sem->id); + sem->id = 0; + } + SDL_free(sem); + } +} + +DECLSPEC int SDLCALL SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) +{ + ULONG ulrc; + + if ( ! sem ) { + SDL_SetError("Passed a NULL sem"); + return -1; + } + + if ( timeout == SDL_MUTEX_MAXWAIT ) { + while (1) { + ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT); + if (ulrc) { + /* if error waiting mutex */ + SDL_SetError("DosRequestMutexSem() failed"); + return -1; + } else if (sem->value) { + sem->value--; + DosReleaseMutexSem(sem->id); + return 0; + } else { + ULONG ulPostCount; + DosResetEventSem(sem->changed, &ulPostCount); + DosReleaseMutexSem(sem->id); + /* continue waiting until somebody posts the semaphore */ + DosWaitEventSem(sem->changed, SEM_INDEFINITE_WAIT); + } + } + } else + if ( timeout == 0 ) + { + ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT); + if (ulrc==NO_ERROR) + { + if (sem->value) + { + sem->value--; + DosReleaseMutexSem(sem->id); + return 0; + } else + { + DosReleaseMutexSem(sem->id); + return SDL_MUTEX_TIMEDOUT; + } + } else + { + SDL_SetError("DosRequestMutexSem() failed"); + return -1; + } + } else { + ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT); + if (ulrc) { + /* if error waiting mutex */ + SDL_SetError("DosRequestMutexSem() failed"); + return -1; + } else + if (sem->value) { + sem->value--; + DosReleaseMutexSem(sem->id); + return 0; + } else { + ULONG ulPostCount; + DosResetEventSem(sem->changed, &ulPostCount); + DosReleaseMutexSem(sem->id); + /* continue waiting until somebody posts the semaphore */ + ulrc = DosWaitEventSem(sem->changed, timeout); + if (ulrc==NO_ERROR) + return 0; + else + return SDL_MUTEX_TIMEDOUT; + } + } + /* never reached */ + return -1; +} + +DECLSPEC int SDLCALL SDL_SemTryWait(SDL_sem *sem) +{ + return SDL_SemWaitTimeout(sem, 0); +} + +DECLSPEC int SDLCALL SDL_SemWait(SDL_sem *sem) +{ + return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT); +} + +/* Returns the current count of the semaphore */ +DECLSPEC Uint32 SDLCALL SDL_SemValue(SDL_sem *sem) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL sem"); + return 0; + } + return sem->value; +} + +DECLSPEC int SDLCALL SDL_SemPost(SDL_sem *sem) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL sem"); + return -1; + } + if ( DosRequestMutexSem(sem->id,SEM_INDEFINITE_WAIT) ) { + SDL_SetError("DosRequestMutexSem() failed"); + return -1; + } + sem->value++; + DosPostEventSem(sem->changed); + DosReleaseMutexSem(sem->id); + return 0; +} diff --git a/3rdparty/SDL/src/thread/os2/SDL_systhread.c b/3rdparty/SDL/src/thread/os2/SDL_systhread.c new file mode 100644 index 0000000..33f815a --- /dev/null +++ b/3rdparty/SDL/src/thread/os2/SDL_systhread.c @@ -0,0 +1,108 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + +/* OS/2 thread management routines for SDL */ + +#include <process.h> +#define INCL_DOSERRORS +#define INCL_DOSPROCESS +#include <os2.h> + +#include "SDL_thread.h" +#include "../SDL_systhread.h" +#include "../SDL_thread_c.h" + +typedef struct ThreadStartParms +{ + void *args; + pfnSDL_CurrentEndThread pfnCurrentEndThread; +} tThreadStartParms, *pThreadStartParms; + +static void threadfunc(void *pparm) +{ + pThreadStartParms pThreadParms = pparm; + pfnSDL_CurrentEndThread pfnCurrentEndThread = NULL; + + // Call the thread function! + SDL_RunThread(pThreadParms->args); + + // Get the current endthread we have to use! + if (pThreadParms) + { + pfnCurrentEndThread = pThreadParms->pfnCurrentEndThread; + SDL_free(pThreadParms); + } + // Call endthread! + if (pfnCurrentEndThread) + (*pfnCurrentEndThread)(); +} + +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread) +{ + pThreadStartParms pThreadParms = SDL_malloc(sizeof(tThreadStartParms)); + if (!pThreadParms) + { + SDL_SetError("Not enough memory to create thread"); + return(-1); + } + + // Save the function which we will have to call to clear the RTL of calling app! + pThreadParms->pfnCurrentEndThread = pfnEndThread; + // Also save the real parameters we have to pass to thread function + pThreadParms->args = args; + // Start the thread using the runtime library of calling app! + thread->threadid = thread->handle = (*pfnBeginThread)(threadfunc, NULL, 512*1024, pThreadParms); + if ((int)thread->threadid <= 0) + { + SDL_SetError("Not enough resources to create thread"); + return(-1); + } + return(0); +} + +void SDL_SYS_SetupThread(void) +{ + return; +} + +DECLSPEC Uint32 SDLCALL SDL_ThreadID(void) +{ + PTIB tib; + DosGetInfoBlocks(&tib, NULL); + return((Uint32) (tib->tib_ptib2->tib2_ultid)); +} + +void SDL_SYS_WaitThread(SDL_Thread *thread) +{ + TID tid = thread->handle; + DosWaitThread(&tid, DCWW_WAIT); +} + +/* WARNING: This function is really a last resort. + * Threads should be signaled and then exit by themselves. + * TerminateThread() doesn't perform stack and DLL cleanup. + */ +void SDL_SYS_KillThread(SDL_Thread *thread) +{ + DosKillThread(thread->handle); +} diff --git a/3rdparty/SDL/src/thread/os2/SDL_systhread_c.h b/3rdparty/SDL/src/thread/os2/SDL_systhread_c.h new file mode 100644 index 0000000..3b94dfe --- /dev/null +++ b/3rdparty/SDL/src/thread/os2/SDL_systhread_c.h @@ -0,0 +1,28 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#define INCL_DOSPROCESS +#include <os2.h> + +typedef TID SYS_ThreadHandle; + diff --git a/3rdparty/SDL/src/thread/pth/SDL_syscond.c b/3rdparty/SDL/src/thread/pth/SDL_syscond.c new file mode 100644 index 0000000..ede74aa --- /dev/null +++ b/3rdparty/SDL/src/thread/pth/SDL_syscond.c @@ -0,0 +1,164 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + +/* + * GNU pth conditions variables + * + * Patrice Mandin + */ + +#include <pth.h> + +#include "SDL_thread.h" +#include "SDL_sysmutex_c.h" + +struct SDL_cond +{ + pth_cond_t condpth_p; +}; + +/* Create a condition variable */ +SDL_cond * SDL_CreateCond(void) +{ + SDL_cond *cond; + + cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); + if ( cond ) { + if ( pth_cond_init(&(cond->condpth_p)) < 0 ) { + SDL_SetError("pthread_cond_init() failed"); + SDL_free(cond); + cond = NULL; + } + } else { + SDL_OutOfMemory(); + } + return(cond); +} + +/* Destroy a condition variable */ +void SDL_DestroyCond(SDL_cond *cond) +{ + if ( 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 ( pth_cond_notify(&(cond->condpth_p), FALSE) != 0 ) { + SDL_SetError("pth_cond_notify() 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 ( pth_cond_notify(&(cond->condpth_p), TRUE) != 0 ) { + SDL_SetError("pth_cond_notify() failed"); + retval = -1; + } + return retval; +} + +/* Wait on the condition variable for at most 'ms' milliseconds. + The mutex must be locked before entering this function! + The mutex is unlocked during the wait, and locked again after the wait. + +Typical use: + +Thread A: + SDL_LockMutex(lock); + while ( ! condition ) { + SDL_CondWait(cond); + } + SDL_UnlockMutex(lock); + +Thread B: + SDL_LockMutex(lock); + ... + condition = true; + ... + SDL_UnlockMutex(lock); + */ +int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) +{ + int retval; + pth_event_t ev; + int sec; + + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + retval = 0; + + sec = ms/1000; + ev = pth_event(PTH_EVENT_TIME, pth_timeout(sec,(ms-sec*1000)*1000)); + + if ( pth_cond_await(&(cond->condpth_p), &(mutex->mutexpth_p), ev) != 0 ) { + SDL_SetError("pth_cond_await() failed"); + retval = -1; + } + + pth_event_free(ev, PTH_FREE_ALL); + + return retval; +} + +/* Wait on the condition variable forever */ +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 ( pth_cond_await(&(cond->condpth_p), &(mutex->mutexpth_p), NULL) != 0 ) { + SDL_SetError("pth_cond_await() failed"); + retval = -1; + } + return retval; +} diff --git a/3rdparty/SDL/src/thread/pth/SDL_sysmutex.c b/3rdparty/SDL/src/thread/pth/SDL_sysmutex.c new file mode 100644 index 0000000..ca83b92 --- /dev/null +++ b/3rdparty/SDL/src/thread/pth/SDL_sysmutex.c @@ -0,0 +1,87 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + +/* + * GNU pth mutexes + * + * Patrice Mandin + */ + +#include <pth.h> + +#include "SDL_mutex.h" +#include "SDL_sysmutex_c.h" + +/* Create a mutex */ +SDL_mutex *SDL_CreateMutex(void) +{ + SDL_mutex *mutex; + + /* Allocate mutex memory */ + mutex = (SDL_mutex *)SDL_malloc(sizeof(*mutex)); + if ( mutex ) { + /* Create the mutex, with initial value signaled */ + if (!pth_mutex_init(&(mutex->mutexpth_p))) { + SDL_SetError("Couldn't create mutex"); + SDL_free(mutex); + mutex = NULL; + } + } else { + SDL_OutOfMemory(); + } + return(mutex); +} + +/* Free the mutex */ +void SDL_DestroyMutex(SDL_mutex *mutex) +{ + if ( mutex ) { + SDL_free(mutex); + } +} + +/* Lock the mutex */ +int SDL_mutexP(SDL_mutex *mutex) +{ + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + pth_mutex_acquire(&(mutex->mutexpth_p), FALSE, NULL); + + return(0); +} + +/* Unlock the mutex */ +int SDL_mutexV(SDL_mutex *mutex) +{ + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + pth_mutex_release(&(mutex->mutexpth_p)); + + return(0); +} diff --git a/3rdparty/SDL/src/thread/pth/SDL_sysmutex_c.h b/3rdparty/SDL/src/thread/pth/SDL_sysmutex_c.h new file mode 100644 index 0000000..d29060e --- /dev/null +++ b/3rdparty/SDL/src/thread/pth/SDL_sysmutex_c.h @@ -0,0 +1,31 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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_SYSMUTEX_C_H_ +#define _SDL_SYSMUTEX_C_H_ + +struct SDL_mutex { + pth_mutex_t mutexpth_p; +}; + +#endif /* _SDL_SYSMUTEX_C_H_ */ diff --git a/3rdparty/SDL/src/thread/pth/SDL_systhread.c b/3rdparty/SDL/src/thread/pth/SDL_systhread.c new file mode 100644 index 0000000..bfccaf3 --- /dev/null +++ b/3rdparty/SDL/src/thread/pth/SDL_systhread.c @@ -0,0 +1,103 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + +/* + * GNU pth threads + * + * Patrice Mandin + */ + +#include <pth.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 int sig_list[] = { + SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH, + SIGVTALRM, SIGPROF, 0 +}; + +static void *RunThread(void *data) +{ + SDL_RunThread(data); + pth_exit((void*)0); + return((void *)0); /* Prevent compiler warning */ +} + +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) +{ + pth_attr_t type; + + /* Create a new attribute */ + type = pth_attr_new(); + if ( type == NULL ) { + SDL_SetError("Couldn't initialize pth attributes"); + return(-1); + } + pth_attr_set(type, PTH_ATTR_JOINABLE, TRUE); + + /* Create the thread and go! */ + thread->handle = pth_spawn(type, RunThread, args); + if ( thread->handle == NULL ) { + SDL_SetError("Not enough resources to create thread"); + return(-1); + } + return(0); +} + +void SDL_SYS_SetupThread(void) +{ + int i; + sigset_t mask; + int oldstate; + + /* Mask asynchronous signals for this thread */ + sigemptyset(&mask); + for ( i=0; sig_list[i]; ++i ) { + sigaddset(&mask, sig_list[i]); + } + pth_sigmask(SIG_BLOCK, &mask, 0); + + /* Allow ourselves to be asynchronously cancelled */ + pth_cancel_state(PTH_CANCEL_ASYNCHRONOUS, &oldstate); +} + +/* WARNING: This may not work for systems with 64-bit pid_t */ +Uint32 SDL_ThreadID(void) +{ + return((Uint32)pth_self()); +} + +void SDL_SYS_WaitThread(SDL_Thread *thread) +{ + pth_join(thread->handle, NULL); +} + +void SDL_SYS_KillThread(SDL_Thread *thread) +{ + pth_cancel(thread->handle); + pth_join(thread->handle, NULL); +} diff --git a/3rdparty/SDL/src/thread/pth/SDL_systhread_c.h b/3rdparty/SDL/src/thread/pth/SDL_systhread_c.h new file mode 100644 index 0000000..50bb26d --- /dev/null +++ b/3rdparty/SDL/src/thread/pth/SDL_systhread_c.h @@ -0,0 +1,31 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_SYSTHREAD_C_H_ +#define _SDL_SYSTHREAD_C_H_ + +#include <pth.h> + +typedef pth_t SYS_ThreadHandle; + +#endif /* _SDL_SYSTHREAD_C_H_ */ diff --git a/3rdparty/SDL/src/thread/pthread/SDL_syscond.c b/3rdparty/SDL/src/thread/pthread/SDL_syscond.c new file mode 100644 index 0000000..15bce96 --- /dev/null +++ b/3rdparty/SDL/src/thread/pthread/SDL_syscond.c @@ -0,0 +1,155 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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; +} diff --git a/3rdparty/SDL/src/thread/pthread/SDL_sysmutex.c b/3rdparty/SDL/src/thread/pthread/SDL_sysmutex.c new file mode 100644 index 0000000..c3b8ce2 --- /dev/null +++ b/3rdparty/SDL/src/thread/pthread/SDL_sysmutex.c @@ -0,0 +1,153 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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 "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; +#if 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; +#if FAKE_RECURSIVE_MUTEX + pthread_t this_thread; +#endif + + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + retval = 0; +#if 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; +#if 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; +} diff --git a/3rdparty/SDL/src/thread/pthread/SDL_sysmutex_c.h b/3rdparty/SDL/src/thread/pthread/SDL_sysmutex_c.h new file mode 100644 index 0000000..5258890 --- /dev/null +++ b/3rdparty/SDL/src/thread/pthread/SDL_sysmutex_c.h @@ -0,0 +1,31 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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 */ diff --git a/3rdparty/SDL/src/thread/pthread/SDL_syssem.c b/3rdparty/SDL/src/thread/pthread/SDL_syssem.c new file mode 100644 index 0000000..a03870f --- /dev/null +++ b/3rdparty/SDL/src/thread/pthread/SDL_syssem.c @@ -0,0 +1,190 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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 <semaphore.h> +#include <errno.h> +#include <sys/time.h> + +#include "SDL_thread.h" +#include "SDL_timer.h" + +/* Wrapper around POSIX 1003.1b semaphores */ + +#ifdef __MACOSX__ +/* Mac OS X doesn't support sem_getvalue() as of version 10.4 */ +#include "../generic/SDL_syssem.c" +#else + +struct SDL_semaphore { + sem_t sem; +}; + +/* Create a semaphore, initialized with value */ +SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) +{ + SDL_sem *sem = (SDL_sem *) SDL_malloc(sizeof(SDL_sem)); + if ( sem ) { + if ( sem_init(&sem->sem, 0, initial_value) < 0 ) { + SDL_SetError("sem_init() failed"); + SDL_free(sem); + sem = NULL; + } + } else { + SDL_OutOfMemory(); + } + return sem; +} + +void SDL_DestroySemaphore(SDL_sem *sem) +{ + if ( sem ) { + sem_destroy(&sem->sem); + 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; + if ( sem_trywait(&sem->sem) == 0 ) { + retval = 0; + } + return retval; +} + +int SDL_SemWait(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + while ( ((retval = sem_wait(&sem->sem)) == -1) && (errno == EINTR) ) {} + if ( retval < 0 ) { + SDL_SetError("sem_wait() failed"); + } + return retval; +} + +int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) +{ + int retval; +#ifdef HAVE_SEM_TIMEDWAIT + struct timeval now; + struct timespec ts_timeout; +#else + Uint32 end; +#endif + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + /* Try the easy cases first */ + if ( timeout == 0 ) { + return SDL_SemTryWait(sem); + } + if ( timeout == SDL_MUTEX_MAXWAIT ) { + return SDL_SemWait(sem); + } + +#ifdef HAVE_SEM_TIMEDWAIT + /* Setup the timeout. sem_timedwait doesn't wait for + * a lapse of time, but until we reach a certain time. + * This time is now plus the timeout. + */ + gettimeofday(&now, NULL); + + /* Add our timeout to current time */ + now.tv_usec += (timeout % 1000) * 1000; + now.tv_sec += timeout / 1000; + + /* Wrap the second if needed */ + if ( now.tv_usec >= 1000000 ) { + now.tv_usec -= 1000000; + now.tv_sec ++; + } + + /* Convert to timespec */ + ts_timeout.tv_sec = now.tv_sec; + ts_timeout.tv_nsec = now.tv_usec * 1000; + + /* Wait. */ + do + retval = sem_timedwait(&sem->sem, &ts_timeout); + while (retval == -1 && errno == EINTR); + + if (retval == -1) + SDL_SetError(strerror(errno)); +#else + end = SDL_GetTicks() + timeout; + while ((retval = SDL_SemTryWait(sem)) == SDL_MUTEX_TIMEDOUT) { + if ((SDL_GetTicks() - end) >= 0) { + break; + } + SDL_Delay(0); + } +#endif /* HAVE_SEM_TIMEDWAIT */ + + return retval; +} + +Uint32 SDL_SemValue(SDL_sem *sem) +{ + int ret = 0; + if ( sem ) { + sem_getvalue(&sem->sem, &ret); + if ( ret < 0 ) { + ret = 0; + } + } + return (Uint32)ret; +} + +int SDL_SemPost(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + retval = sem_post(&sem->sem); + if ( retval < 0 ) { + SDL_SetError("sem_post() failed"); + } + return retval; +} + +#endif /* __MACOSX__ */ diff --git a/3rdparty/SDL/src/thread/pthread/SDL_systhread.c b/3rdparty/SDL/src/thread/pthread/SDL_systhread.c new file mode 100644 index 0000000..40cc3b7 --- /dev/null +++ b/3rdparty/SDL/src/thread/pthread/SDL_systhread.c @@ -0,0 +1,120 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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 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; +Uint32 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 +} + +/* WARNING: This may not work for systems with 64-bit pid_t */ +Uint32 SDL_ThreadID(void) +{ + return((Uint32)((size_t)pthread_self())); +} + +void SDL_SYS_WaitThread(SDL_Thread *thread) +{ + pthread_join(thread->handle, 0); +} + +void SDL_SYS_KillThread(SDL_Thread *thread) +{ +#ifdef PTHREAD_CANCEL_ASYNCHRONOUS + pthread_cancel(thread->handle); +#else +#ifdef __FREEBSD__ +#warning For some reason, this doesnt actually kill a thread - FreeBSD 3.2 +#endif + pthread_kill(thread->handle, SIGKILL); +#endif +} diff --git a/3rdparty/SDL/src/thread/pthread/SDL_systhread_c.h b/3rdparty/SDL/src/thread/pthread/SDL_systhread_c.h new file mode 100644 index 0000000..33ed750 --- /dev/null +++ b/3rdparty/SDL/src/thread/pthread/SDL_systhread_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <pthread.h> + +typedef pthread_t SYS_ThreadHandle; diff --git a/3rdparty/SDL/src/thread/riscos/SDL_syscond.c b/3rdparty/SDL/src/thread/riscos/SDL_syscond.c new file mode 100644 index 0000000..ee55666 --- /dev/null +++ b/3rdparty/SDL/src/thread/riscos/SDL_syscond.c @@ -0,0 +1,160 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + +/* RISC OS implementations uses pthreads based on linux code */ + +#if SDL_THREADS_DISABLED +#include "../generic/SDL_syscond.c" +#else +#include <sys/time.h> +#include <unistd.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; +} +#endif diff --git a/3rdparty/SDL/src/thread/riscos/SDL_sysmutex.c b/3rdparty/SDL/src/thread/riscos/SDL_sysmutex.c new file mode 100644 index 0000000..e9ac139 --- /dev/null +++ b/3rdparty/SDL/src/thread/riscos/SDL_sysmutex.c @@ -0,0 +1,153 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + +/* RISC OS implementations uses pthreads based on linux code */ + +#include "SDL_thread.h" + +#if SDL_THREADS_DISABLED +#include "../generic/SDL_sysmutex.c" +#else + +#include <pthread.h> + +struct SDL_mutex { + pthread_mutex_t id; +#if SDL_THREAD_PTHREAD_NO_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_NO_RECURSIVE_MUTEX + /* No extra attributes necessary */ +#else + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); +#endif /* SDL_THREAD_PTHREAD_NO_RECURSIVE_MUTEX */ + 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; +#if SDL_THREAD_PTHREAD_NO_RECURSIVE_MUTEX + pthread_t this_thread; +#endif + + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + retval = 0; +#if SDL_THREAD_PTHREAD_NO_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; +#if SDL_THREAD_PTHREAD_NO_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 /* SDL_THREAD_PTHREAD_NO_RECURSIVE_MUTEX */ + + return retval; +} +#endif diff --git a/3rdparty/SDL/src/thread/riscos/SDL_sysmutex_c.h b/3rdparty/SDL/src/thread/riscos/SDL_sysmutex_c.h new file mode 100644 index 0000000..2391c3c --- /dev/null +++ b/3rdparty/SDL/src/thread/riscos/SDL_sysmutex_c.h @@ -0,0 +1,34 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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 + +#if !SDL_THREADS_DISABLED +struct SDL_mutex { + pthread_mutex_t id; +}; +#endif + + +#endif /* _SDL_mutex_c_h */ diff --git a/3rdparty/SDL/src/thread/riscos/SDL_syssem.c b/3rdparty/SDL/src/thread/riscos/SDL_syssem.c new file mode 100644 index 0000000..127211b --- /dev/null +++ b/3rdparty/SDL/src/thread/riscos/SDL_syssem.c @@ -0,0 +1,203 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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 <errno.h> + +#include "SDL_config.h" + +/* RISC OS semiphores based on linux code */ + + +#include "SDL_timer.h" +#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 + + +#include <unistd.h> /* For getpid() */ +#include <pthread.h> +#include <semaphore.h> + +struct SDL_semaphore { + sem_t *sem; + sem_t sem_data; +}; + +/* Create a semaphore, initialized with value */ +SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) +{ + SDL_sem *sem = (SDL_sem *) SDL_malloc(sizeof(SDL_sem)); + if ( sem ) { + if ( sem_init(&sem->sem_data, 0, initial_value) < 0 ) { + SDL_SetError("sem_init() failed"); + SDL_free(sem); + sem = NULL; + } else { + sem->sem = &sem->sem_data; + } + } else { + SDL_OutOfMemory(); + } + return sem; +} + +void SDL_DestroySemaphore(SDL_sem *sem) +{ + if ( sem ) { + sem_destroy(sem->sem); + 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; + if ( sem_trywait(sem->sem) == 0 ) { + retval = 0; + } + return retval; +} + +int SDL_SemWait(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + while ( ((retval = sem_wait(sem->sem)) == -1) && (errno == EINTR) ) {} + if ( retval < 0 ) { + SDL_SetError("sem_wait() failed"); + } + return retval; +} + +int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + /* Try the easy cases first */ + if ( timeout == 0 ) { + return SDL_SemTryWait(sem); + } + if ( timeout == SDL_MUTEX_MAXWAIT ) { + return SDL_SemWait(sem); + } + + /* Ack! We have to busy wait... */ + timeout += SDL_GetTicks(); + do { + retval = SDL_SemTryWait(sem); + if ( retval == 0 ) { + break; + } + SDL_Delay(1); + } while ( SDL_GetTicks() < timeout ); + + return retval; +} + +Uint32 SDL_SemValue(SDL_sem *sem) +{ + int ret = 0; + if ( sem ) { + sem_getvalue(sem->sem, &ret); + if ( ret < 0 ) { + ret = 0; + } + } + return (Uint32)ret; +} + +int SDL_SemPost(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + retval = sem_post(sem->sem); + if ( retval < 0 ) { + SDL_SetError("sem_post() failed"); + } + return retval; +} + +#endif /* !SDL_THREADS_DISABLED */ diff --git a/3rdparty/SDL/src/thread/riscos/SDL_systhread.c b/3rdparty/SDL/src/thread/riscos/SDL_systhread.c new file mode 100644 index 0000000..38fc333 --- /dev/null +++ b/3rdparty/SDL/src/thread/riscos/SDL_systhread.c @@ -0,0 +1,144 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + +/* RISC OS version based on pthreads linux source */ + +#include "SDL_thread.h" +#include "../SDL_systhread.h" + +#if SDL_THREADS_DISABLED + +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) +{ + SDL_SetError("Threads have not been compiled into this version of the library"); + return(-1); +} + +void SDL_SYS_SetupThread(void) +{ + return; +} + +Uint32 SDL_ThreadID(void) +{ + return(0); +} + +void SDL_SYS_WaitThread(SDL_Thread *thread) +{ + return; +} + +void SDL_SYS_KillThread(SDL_Thread *thread) +{ + return; +} + +#else + +#include <signal.h> + +/* List of signals to mask in the subthreads */ +static int sig_list[] = { + SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH, + SIGVTALRM, SIGPROF, 0 +}; + +#include <pthread.h> + +int riscos_using_threads = 0; +Uint32 riscos_main_thread = 0; /* Thread running events */ + +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); + } + + if (riscos_using_threads == 0) + { + riscos_using_threads = 1; + riscos_main_thread = SDL_ThreadID(); + } + + 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 +} + +Uint32 SDL_ThreadID(void) +{ + return((Uint32)pthread_self()); +} + +void SDL_SYS_WaitThread(SDL_Thread *thread) +{ + pthread_join(thread->handle, 0); +} + +void SDL_SYS_KillThread(SDL_Thread *thread) +{ +#ifdef PTHREAD_CANCEL_ASYNCHRONOUS + pthread_cancel(thread->handle); +#else + pthread_kill(thread->handle, SIGKILL); +#endif +} + +#endif diff --git a/3rdparty/SDL/src/thread/riscos/SDL_systhread_c.h b/3rdparty/SDL/src/thread/riscos/SDL_systhread_c.h new file mode 100644 index 0000000..9e1d2c8 --- /dev/null +++ b/3rdparty/SDL/src/thread/riscos/SDL_systhread_c.h @@ -0,0 +1,34 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#if SDL_THREADS_DISABLED + +typedef int SYS_ThreadHandle; + +#else + +#include <pthread.h> + +typedef pthread_t SYS_ThreadHandle; + +#endif diff --git a/3rdparty/SDL/src/thread/symbian/SDL_sysmutex.cpp b/3rdparty/SDL/src/thread/symbian/SDL_sysmutex.cpp new file mode 100644 index 0000000..f4b1aea --- /dev/null +++ b/3rdparty/SDL/src/thread/symbian/SDL_sysmutex.cpp @@ -0,0 +1,130 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_sysmutex.cpp + + Epoc version by Markus Mertama (w@iki.fi) +*/ + + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id: SDL_sysmutex.c,v 1.1.2.3 2000/06/22 15:25:23 hercules Exp $"; +#endif + +/* Mutex functions using the Win32 API */ + +//#include <stdio.h> +//#include <stdlib.h> + +#include <e32std.h> + +#include "epoc_sdl.h" + +#include "SDL_error.h" +#include "SDL_mutex.h" + + +#ifdef EKA2 //??? +struct SDL_mutex + { + TInt handle; + }; +#else +struct _SDL_mutex + { + TInt handle; + }; +#endif + +extern TInt CreateUnique(TInt (*aFunc)(const TDesC& aName, TAny*, TAny*), TAny*, TAny*); + +TInt NewMutex(const TDesC& aName, TAny* aPtr1, TAny*) + { + return ((RMutex*)aPtr1)->CreateGlobal(aName); + } + +void DeleteMutex(TAny* aMutex) + { + SDL_DestroyMutex ((SDL_mutex*) aMutex); + } + +/* Create a mutex */ +SDL_mutex *SDL_CreateMutex(void) +{ + RMutex rmutex; + + TInt status = CreateUnique(NewMutex, &rmutex, NULL); + if(status != KErrNone) + { + SDL_SetError("Couldn't create mutex"); + } + SDL_mutex* mutex = new /*(ELeave)*/ SDL_mutex; + mutex->handle = rmutex.Handle(); + EpocSdlEnv::AppendCleanupItem(TSdlCleanupItem(DeleteMutex, mutex)); + return(mutex); +} + +/* Free the mutex */ +void SDL_DestroyMutex(SDL_mutex *mutex) +{ + if ( mutex ) + { + RMutex rmutex; + rmutex.SetHandle(mutex->handle); + if(rmutex.IsHeld()) + { + rmutex.Signal(); + } + rmutex.Close(); + EpocSdlEnv::RemoveCleanupItem(mutex); + delete(mutex); + mutex = NULL; + } +} + +/* Lock the mutex */ +int SDL_mutexP(SDL_mutex *mutex) +{ + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + RMutex rmutex; + rmutex.SetHandle(mutex->handle); + rmutex.Wait(); + return(0); +} + +/* Unlock the mutex */ +int SDL_mutexV(SDL_mutex *mutex) +{ + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + RMutex rmutex; + rmutex.SetHandle(mutex->handle); + rmutex.Signal(); + return(0); +} diff --git a/3rdparty/SDL/src/thread/symbian/SDL_syssem.cpp b/3rdparty/SDL/src/thread/symbian/SDL_syssem.cpp new file mode 100644 index 0000000..00f9901 --- /dev/null +++ b/3rdparty/SDL/src/thread/symbian/SDL_syssem.cpp @@ -0,0 +1,214 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_syssem.cpp + + Epoc version by Markus Mertama (w@iki.fi) +*/ + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id: SDL_syssem.c,v 1.1.2.4 2000/06/22 15:24:48 hercules Exp $"; +#endif + +/* Semaphore functions using the Win32 API */ + +//#include <stdio.h> +//#include <stdlib.h> +#include <e32std.h> + +#include "SDL_error.h" +#include "SDL_thread.h" + + +#define SDL_MUTEX_TIMEOUT -2 + +struct SDL_semaphore + { + TInt handle; + TInt count; + }; + + +extern TInt CreateUnique(TInt (*aFunc)(const TDesC& aName, TAny*, TAny*), TAny*, TAny*); +#ifndef EKA2 +extern TInt NewThread(const TDesC& aName, TAny* aPtr1, TAny* aPtr2); +#endif + +TInt NewSema(const TDesC& aName, TAny* aPtr1, TAny* aPtr2) + { + TInt value = *((TInt*) aPtr2); + return ((RSemaphore*)aPtr1)->CreateGlobal(aName, value); + } + +/* Create a semaphore */ +SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) +{ + RSemaphore s; + TInt status = CreateUnique(NewSema, &s, &initial_value); + if(status != KErrNone) + { + SDL_SetError("Couldn't create semaphore"); + } + SDL_semaphore* sem = new /*(ELeave)*/ SDL_semaphore; + sem->handle = s.Handle(); + sem->count = initial_value; + return(sem); +} + +/* Free the semaphore */ +void SDL_DestroySemaphore(SDL_sem *sem) +{ + if ( sem ) + { + RSemaphore sema; + sema.SetHandle(sem->handle); + while(--sem->count) + sema.Signal(); + sema.Close(); + delete sem; + sem = NULL; + } +} + +#ifndef EKA2 + + struct TInfo + { + TInfo(TInt aTime, TInt aHandle) : + iTime(aTime), iHandle(aHandle), iVal(0) {} + TInt iTime; + TInt iHandle; + TInt iVal; + }; + + + +TBool ThreadRun(TAny* aInfo) + { + TInfo* info = STATIC_CAST(TInfo*, aInfo); + User::After(info->iTime); + RSemaphore sema; + sema.SetHandle(info->iHandle); + sema.Signal(); + info->iVal = SDL_MUTEX_TIMEOUT; + return 0; + } + +#endif + + +void _WaitAll(SDL_sem *sem) + { + //since SemTryWait may changed the counter. + //this may not be atomic, but hopes it works. + RSemaphore sema; + sema.SetHandle(sem->handle); + sema.Wait(); + while(sem->count < 0) + { + sema.Wait(); + } + } + +int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL sem"); + return -1; + } + + if ( timeout == SDL_MUTEX_MAXWAIT ) + { + _WaitAll(sem); + return SDL_MUTEX_MAXWAIT; + } + +#ifdef EKA2 + + RSemaphore sema; + sema.SetHandle(sem->handle); + if(KErrNone == sema.Wait(timeout)) + return 0; + return -1; +#else + RThread thread; + + TInfo* info = new (ELeave)TInfo(timeout, sem->handle); + + TInt status = CreateUnique(NewThread, &thread, info); + + if(status != KErrNone) + return status; + + thread.Resume(); + + _WaitAll(sem); + + if(thread.ExitType() == EExitPending) + { + thread.Kill(SDL_MUTEX_TIMEOUT); + } + + thread.Close(); + + return info->iVal; +#endif +} + +int SDL_SemTryWait(SDL_sem *sem) +{ + if(sem->count > 0) + { + sem->count--; + } + return SDL_MUTEX_TIMEOUT; +} + +int SDL_SemWait(SDL_sem *sem) +{ + return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT); +} + +/* Returns the current count of the semaphore */ +Uint32 SDL_SemValue(SDL_sem *sem) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL sem"); + return 0; + } + return sem->count; +} + +int SDL_SemPost(SDL_sem *sem) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL sem"); + return -1; + } + sem->count++; + RSemaphore sema; + sema.SetHandle(sem->handle); + sema.Signal(); + return 0; +} diff --git a/3rdparty/SDL/src/thread/symbian/SDL_systhread.cpp b/3rdparty/SDL/src/thread/symbian/SDL_systhread.cpp new file mode 100644 index 0000000..5e7adc5 --- /dev/null +++ b/3rdparty/SDL/src/thread/symbian/SDL_systhread.cpp @@ -0,0 +1,146 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_systhread.cpp + Epoc thread management routines for SDL + + Epoc version by Markus Mertama (w@iki.fi) +*/ + +#include "epoc_sdl.h" + +//#include <stdlib.h> +//#include <stdio.h> + + + +extern "C" { +#undef NULL +#include "SDL_error.h" +#include "SDL_thread.h" +#include "SDL_systhread.h" +#include "SDL_thread_c.h" + } + +#include <e32std.h> +#include "epoc_sdl.h" + + +static int object_count; + +int RunThread(TAny* data) +{ + CTrapCleanup* cleanup = CTrapCleanup::New(); + TRAPD(err, SDL_RunThread(data)); + EpocSdlEnv::CleanupItems(); + delete cleanup; + return(err); +} + + +TInt NewThread(const TDesC& aName, TAny* aPtr1, TAny* aPtr2) + { + return ((RThread*)(aPtr1))->Create(aName, + RunThread, + KDefaultStackSize, + NULL, + aPtr2); + } + +int CreateUnique(TInt (*aFunc)(const TDesC& aName, TAny*, TAny*), TAny* aPtr1, TAny* aPtr2) + { + TBuf<16> name; + TInt status = KErrNone; + do + { + object_count++; + name.Format(_L("SDL_%x"), object_count); + status = aFunc(name, aPtr1, aPtr2); + } + while(status == KErrAlreadyExists); + return status; + } + + +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) +{ + RThread rthread; + + const TInt status = CreateUnique(NewThread, &rthread, args); + if (status != KErrNone) + { + delete(((RThread*)(thread->handle))); + thread->handle = NULL; + SDL_SetError("Not enough resources to create thread"); + return(-1); + } + rthread.Resume(); + thread->handle = rthread.Handle(); + return(0); +} + +void SDL_SYS_SetupThread(void) +{ + return; +} + +Uint32 SDL_ThreadID(void) +{ + RThread current; + const TThreadId id = current.Id(); + return id; +} + +void SDL_SYS_WaitThread(SDL_Thread *thread) +{ + SDL_TRACE1("Close thread", thread); + RThread t; + const TInt err = t.Open(thread->threadid); + if(err == KErrNone && t.ExitType() == EExitPending) + { + TRequestStatus status; + t.Logon(status); + User::WaitForRequest(status); + } + t.Close(); + + /* RUndertaker taker; + taker.Create(); + TRequestStatus status; + taker.Logon(status, thread->handle); + User::WaitForRequest(status); + taker.Close();*/ + SDL_TRACE1("Closed thread", thread); +} + +/* WARNING: This function is really a last resort. + * Threads should be signaled and then exit by themselves. + * TerminateThread() doesn't perform stack and DLL cleanup. + */ +void SDL_SYS_KillThread(SDL_Thread *thread) +{ + RThread rthread; + rthread.SetHandle(thread->handle); + rthread.Kill(0); + rthread.Close(); +} diff --git a/3rdparty/SDL/src/thread/symbian/SDL_systhread_c.h b/3rdparty/SDL/src/thread/symbian/SDL_systhread_c.h new file mode 100644 index 0000000..f5f1729 --- /dev/null +++ b/3rdparty/SDL/src/thread/symbian/SDL_systhread_c.h @@ -0,0 +1,30 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_systhread_c.h + + Epoc version by Markus Mertama (w@iki.fi) +*/ + +typedef int SYS_ThreadHandle; + diff --git a/3rdparty/SDL/src/thread/win32/SDL_sysmutex.c b/3rdparty/SDL/src/thread/win32/SDL_sysmutex.c new file mode 100644 index 0000000..1d7805c --- /dev/null +++ b/3rdparty/SDL/src/thread/win32/SDL_sysmutex.c @@ -0,0 +1,95 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + +/* Mutex functions using the Win32 API */ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#include "SDL_mutex.h" + + +struct SDL_mutex { + HANDLE id; +}; + +/* Create a mutex */ +SDL_mutex *SDL_CreateMutex(void) +{ + SDL_mutex *mutex; + + /* Allocate mutex memory */ + mutex = (SDL_mutex *)SDL_malloc(sizeof(*mutex)); + if ( mutex ) { + /* Create the mutex, with initial value signaled */ + mutex->id = CreateMutex(NULL, FALSE, NULL); + if ( ! mutex->id ) { + SDL_SetError("Couldn't create mutex"); + SDL_free(mutex); + mutex = NULL; + } + } else { + SDL_OutOfMemory(); + } + return(mutex); +} + +/* Free the mutex */ +void SDL_DestroyMutex(SDL_mutex *mutex) +{ + if ( mutex ) { + if ( mutex->id ) { + CloseHandle(mutex->id); + mutex->id = 0; + } + SDL_free(mutex); + } +} + +/* Lock the mutex */ +int SDL_mutexP(SDL_mutex *mutex) +{ + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + if ( WaitForSingleObject(mutex->id, INFINITE) == WAIT_FAILED ) { + SDL_SetError("Couldn't wait on mutex"); + return -1; + } + return(0); +} + +/* Unlock the mutex */ +int SDL_mutexV(SDL_mutex *mutex) +{ + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + if ( ReleaseMutex(mutex->id) == FALSE ) { + SDL_SetError("Couldn't release mutex"); + return -1; + } + return(0); +} diff --git a/3rdparty/SDL/src/thread/win32/SDL_syssem.c b/3rdparty/SDL/src/thread/win32/SDL_syssem.c new file mode 100644 index 0000000..261d24c --- /dev/null +++ b/3rdparty/SDL/src/thread/win32/SDL_syssem.c @@ -0,0 +1,164 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + +/* Semaphore functions using the Win32 API */ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#include "SDL_thread.h" +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) +#include "win_ce_semaphore.h" +#endif + + +struct SDL_semaphore { +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) + SYNCHHANDLE id; +#else + HANDLE id; +#endif + volatile LONG count; +}; + + +/* Create a semaphore */ +SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) +{ + SDL_sem *sem; + + /* Allocate sem memory */ + sem = (SDL_sem *)SDL_malloc(sizeof(*sem)); + if ( sem ) { + /* Create the semaphore, with max value 32K */ +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) + sem->id = CreateSemaphoreCE(NULL, initial_value, 32*1024, NULL); +#else + sem->id = CreateSemaphore(NULL, initial_value, 32*1024, NULL); +#endif + sem->count = (LONG) initial_value; + if ( ! sem->id ) { + SDL_SetError("Couldn't create semaphore"); + SDL_free(sem); + sem = NULL; + } + } else { + SDL_OutOfMemory(); + } + return(sem); +} + +/* Free the semaphore */ +void SDL_DestroySemaphore(SDL_sem *sem) +{ + if ( sem ) { + if ( sem->id ) { +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) + CloseSynchHandle(sem->id); +#else + CloseHandle(sem->id); +#endif + sem->id = 0; + } + SDL_free(sem); + } +} + +int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) +{ + int retval; + DWORD dwMilliseconds; + + if ( ! sem ) { + SDL_SetError("Passed a NULL sem"); + return -1; + } + + if ( timeout == SDL_MUTEX_MAXWAIT ) { + dwMilliseconds = INFINITE; + } else { + dwMilliseconds = (DWORD)timeout; + } +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) + switch (WaitForSemaphoreCE(sem->id, dwMilliseconds)) { +#else + switch (WaitForSingleObject(sem->id, dwMilliseconds)) { +#endif + case WAIT_OBJECT_0: + InterlockedDecrement(&sem->count); + retval = 0; + break; + case WAIT_TIMEOUT: + retval = SDL_MUTEX_TIMEDOUT; + break; + default: + SDL_SetError("WaitForSingleObject() failed"); + retval = -1; + break; + } + return retval; +} + +int SDL_SemTryWait(SDL_sem *sem) +{ + return SDL_SemWaitTimeout(sem, 0); +} + +int SDL_SemWait(SDL_sem *sem) +{ + return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT); +} + +/* Returns the current count of the semaphore */ +Uint32 SDL_SemValue(SDL_sem *sem) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL sem"); + return 0; + } + return (Uint32) sem->count; +} + +int SDL_SemPost(SDL_sem *sem) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL sem"); + return -1; + } + /* Increase the counter in the first place, because + * after a successful release the semaphore may + * immediately get destroyed by another thread which + * is waiting for this semaphore. + */ + InterlockedIncrement(&sem->count); +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) + if ( ReleaseSemaphoreCE(sem->id, 1, NULL) == FALSE ) { +#else + if ( ReleaseSemaphore(sem->id, 1, NULL) == FALSE ) { +#endif + InterlockedDecrement(&sem->count); /* restore */ + SDL_SetError("ReleaseSemaphore() failed"); + return -1; + } + return 0; +} diff --git a/3rdparty/SDL/src/thread/win32/SDL_systhread.c b/3rdparty/SDL/src/thread/win32/SDL_systhread.c new file mode 100644 index 0000000..55cb88a --- /dev/null +++ b/3rdparty/SDL/src/thread/win32/SDL_systhread.c @@ -0,0 +1,162 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + +/* Win32 thread management routines for SDL */ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#include "SDL_thread.h" +#include "../SDL_thread_c.h" +#include "../SDL_systhread.h" + +#ifndef SDL_PASSED_BEGINTHREAD_ENDTHREAD +#ifndef _WIN32_WCE +/* We'll use the C library from this DLL */ +#include <process.h> +#endif + +#if defined(__WATCOMC__) +/* This is for Watcom targets except OS2 */ +#if __WATCOMC__ < 1240 +#define __watcall +#endif +typedef unsigned long (__watcall *pfnSDL_CurrentBeginThread) (void *, unsigned, + unsigned (__stdcall *func)(void *), void *arg, + unsigned, unsigned *threadID); +typedef void (__watcall *pfnSDL_CurrentEndThread)(unsigned code); +#elif (defined(__MINGW32__) && (__GNUC__ < 4)) +typedef unsigned long (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned, + unsigned (__stdcall *func)(void *), void *arg, + unsigned, unsigned *threadID); +typedef void (__cdecl *pfnSDL_CurrentEndThread)(unsigned code); +#else +typedef uintptr_t (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned, + unsigned (__stdcall *func)(void *), void *arg, + unsigned, unsigned *threadID); +typedef void (__cdecl *pfnSDL_CurrentEndThread)(unsigned code); +#endif +#endif /* !SDL_PASSED_BEGINTHREAD_ENDTHREAD */ + + +typedef struct ThreadStartParms +{ + void *args; + pfnSDL_CurrentEndThread pfnCurrentEndThread; +} tThreadStartParms, *pThreadStartParms; + +static DWORD RunThread(void *data) +{ + pThreadStartParms pThreadParms = (pThreadStartParms)data; + pfnSDL_CurrentEndThread pfnCurrentEndThread = NULL; + + // Call the thread function! + SDL_RunThread(pThreadParms->args); + + // Get the current endthread we have to use! + if (pThreadParms) + { + pfnCurrentEndThread = pThreadParms->pfnCurrentEndThread; + SDL_free(pThreadParms); + } + // Call endthread! + if (pfnCurrentEndThread) + (*pfnCurrentEndThread)(0); + return(0); +} + +static DWORD WINAPI RunThreadViaCreateThread(LPVOID data) +{ + return RunThread(data); +} + +static unsigned __stdcall RunThreadViaBeginThreadEx(void *data) +{ + return (unsigned) RunThread(data); +} + +#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread) +{ +#else +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) +{ +#ifdef _WIN32_WCE + pfnSDL_CurrentBeginThread pfnBeginThread = NULL; + pfnSDL_CurrentEndThread pfnEndThread = NULL; +#else + pfnSDL_CurrentBeginThread pfnBeginThread = _beginthreadex; + pfnSDL_CurrentEndThread pfnEndThread = _endthreadex; +#endif +#endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */ + pThreadStartParms pThreadParms = (pThreadStartParms)SDL_malloc(sizeof(tThreadStartParms)); + if (!pThreadParms) { + SDL_OutOfMemory(); + return(-1); + } + + // Save the function which we will have to call to clear the RTL of calling app! + pThreadParms->pfnCurrentEndThread = pfnEndThread; + // Also save the real parameters we have to pass to thread function + pThreadParms->args = args; + + if (pfnBeginThread) { + unsigned threadid = 0; + thread->handle = (SYS_ThreadHandle) + ((size_t) pfnBeginThread(NULL, 0, RunThreadViaBeginThreadEx, + pThreadParms, 0, &threadid)); + } else { + DWORD threadid = 0; + thread->handle = CreateThread(NULL, 0, RunThreadViaCreateThread, pThreadParms, 0, &threadid); + } + if (thread->handle == NULL) { + SDL_SetError("Not enough resources to create thread"); + return(-1); + } + return(0); +} + +void SDL_SYS_SetupThread(void) +{ + return; +} + +Uint32 SDL_ThreadID(void) +{ + return((Uint32)GetCurrentThreadId()); +} + +void SDL_SYS_WaitThread(SDL_Thread *thread) +{ + WaitForSingleObject(thread->handle, INFINITE); + CloseHandle(thread->handle); +} + +/* WARNING: This function is really a last resort. + * Threads should be signaled and then exit by themselves. + * TerminateThread() doesn't perform stack and DLL cleanup. + */ +void SDL_SYS_KillThread(SDL_Thread *thread) +{ + TerminateThread(thread->handle, FALSE); +} diff --git a/3rdparty/SDL/src/thread/win32/SDL_systhread_c.h b/3rdparty/SDL/src/thread/win32/SDL_systhread_c.h new file mode 100644 index 0000000..10b0a7d --- /dev/null +++ b/3rdparty/SDL/src/thread/win32/SDL_systhread_c.h @@ -0,0 +1,28 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +typedef HANDLE SYS_ThreadHandle; + diff --git a/3rdparty/SDL/src/thread/win32/win_ce_semaphore.c b/3rdparty/SDL/src/thread/win32/win_ce_semaphore.c new file mode 100644 index 0000000..9db45c4 --- /dev/null +++ b/3rdparty/SDL/src/thread/win32/win_ce_semaphore.c @@ -0,0 +1,216 @@ +/* win_ce_semaphore.c + + Copyright (c) 1998, Johnson M. Hart + (with corrections 2001 by Rainer Loritz) + Permission is granted for any and all use providing that this + copyright is properly acknowledged. + There are no assurances of suitability for any use whatsoever. + + WINDOWS CE: There is a collection of Windows CE functions to simulate + semaphores using only a mutex and an event. As Windows CE events cannot + be named, these simulated semaphores cannot be named either. + + Implementation notes: + 1. All required internal data structures are allocated on the process's heap. + 2. Where appropriate, a new error code is returned (see the header + file), or, if the error is a Win32 error, that code is unchanged. + 3. Notice the new handle type "SYNCHHANDLE" that has handles, counters, + and other information. This structure will grow as new objects are added + to this set; some members are specific to only one or two of the objects. + 4. Mutexes are used for critical sections. These could be replaced with + CRITICAL_SECTION objects but then this would give up the time out + capability. + 5. The implementation shows several interesting aspects of synchronization, some + of which are specific to Win32 and some of which are general. These are pointed + out in the comments as appropriate. + 6. The wait function emulates WaitForSingleObject only. An emulation of + WaitForMultipleObjects is much harder to implement outside the kernel, + and it is not clear how to handle a mixture of WCE semaphores and normal + events and mutexes. */ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#include "win_ce_semaphore.h" + +static SYNCHHANDLE CleanUp (SYNCHHANDLE hSynch, DWORD Flags); + +SYNCHHANDLE CreateSemaphoreCE ( + + LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, /* pointer to security attributes */ + LONG lInitialCount, /* initial count */ + LONG lMaximumCount, /* maximum count */ + LPCTSTR lpName ) + +/* Semaphore for use with Windows CE that does not support them directly. + Requires a counter, a mutex to protect the counter, and an + autoreset event. + + Here are the rules that must always hold between the autoreset event + and the mutex (any violation of these rules by the CE semaphore functions + will, in all likelihood, result in a defect): + 1. No thread can set, pulse, or reset the event, + nor can it access any part of the SYNCHHANDLE structure, + without first gaining ownership of the mutex. + BUT, a thread can wait on the event without owning the mutex + (this is clearly necessary or else the event could never be set). + 2. The event is in a signaled state if and only if the current semaphore + count ("CurCount") is greater than zero. + 3. The semaphore count is always >= 0 and <= the maximum count */ + +{ + SYNCHHANDLE hSynch = NULL, result = NULL; + + __try + { + if (lInitialCount > lMaximumCount || lMaximumCount < 0 || lInitialCount < 0) + { + /* Bad parameters */ + SetLastError (SYNCH_ERROR); + __leave; + } + + hSynch = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, SYNCH_HANDLE_SIZE); + if (hSynch == NULL) __leave; + + hSynch->MaxCount = lMaximumCount; + hSynch->CurCount = lInitialCount; + hSynch->lpName = lpName; + + hSynch->hMutex = CreateMutex (lpSemaphoreAttributes, FALSE, NULL); + + WaitForSingleObject (hSynch->hMutex, INFINITE); + /* Create the event. It is initially signaled if and only if the + initial count is > 0 */ + hSynch->hEvent = CreateEvent (lpSemaphoreAttributes, FALSE, + lInitialCount > 0, NULL); + ReleaseMutex (hSynch->hMutex); + hSynch->hSemph = NULL; + } + __finally + { + /* Return with the handle, or, if there was any error, return + a null after closing any open handles and freeing any allocated memory. */ + result=CleanUp(hSynch, 6 /* An event and a mutex, but no semaphore. */); + } + + return result; +} + +BOOL ReleaseSemaphoreCE (SYNCHHANDLE hSemCE, LONG cReleaseCount, LPLONG lpPreviousCount) +/* Windows CE equivalent to ReleaseSemaphore. */ +{ + BOOL Result = TRUE; + + /* Gain access to the object to assure that the release count + would not cause the total count to exceed the maximum. */ + + __try + { + WaitForSingleObject (hSemCE->hMutex, INFINITE); + /* reply only if asked to */ + if (lpPreviousCount!=NULL) + *lpPreviousCount = hSemCE->CurCount; + if (hSemCE->CurCount + cReleaseCount > hSemCE->MaxCount || cReleaseCount <= 0) + { + SetLastError (SYNCH_ERROR); + Result = FALSE; + __leave; + } + hSemCE->CurCount += cReleaseCount; + + /* Set the autoreset event, releasing exactly one waiting thread, now or + in the future. */ + + SetEvent (hSemCE->hEvent); + } + __finally + { + ReleaseMutex (hSemCE->hMutex); + } + + return Result; +} + +DWORD WaitForSemaphoreCE (SYNCHHANDLE hSemCE, DWORD dwMilliseconds) + /* Windows CE semaphore equivalent of WaitForSingleObject. */ +{ + DWORD WaitResult; + + WaitResult = WaitForSingleObject (hSemCE->hMutex, dwMilliseconds); + if (WaitResult != WAIT_OBJECT_0 && WaitResult != WAIT_ABANDONED_0) return WaitResult; + while (hSemCE->CurCount <= 0) + { + + /* The count is 0, and the thread must wait on the event (which, by + the rules, is currently reset) for semaphore resources to become + available. First, of course, the mutex must be released so that another + thread will be capable of setting the event. */ + + ReleaseMutex (hSemCE->hMutex); + + /* Wait for the event to be signaled, indicating a semaphore state change. + The event is autoreset and signaled with a SetEvent (not PulseEvent) + so exactly one waiting thread (whether or not there is currently + a waiting thread) is released as a result of the SetEvent. */ + + WaitResult = WaitForSingleObject (hSemCE->hEvent, dwMilliseconds); + if (WaitResult != WAIT_OBJECT_0) return WaitResult; + + /* This is where the properties of setting of an autoreset event is critical + to assure that, even if the semaphore state changes between the + preceding Wait and the next, and even if NO threads are waiting + on the event at the time of the SetEvent, at least one thread + will be released. + Pulsing a manual reset event would appear to work, but it would have + a defect which could appear if the semaphore state changed between + the two waits. */ + + WaitResult = WaitForSingleObject (hSemCE->hMutex, dwMilliseconds); + if (WaitResult != WAIT_OBJECT_0 && WaitResult != WAIT_ABANDONED_0) return WaitResult; + + } + /* The count is not zero and this thread owns the mutex. */ + + hSemCE->CurCount--; + /* The event is now unsignaled, BUT, the semaphore count may not be + zero, in which case the event should be signaled again + before releasing the mutex. */ + + if (hSemCE->CurCount > 0) SetEvent (hSemCE->hEvent); + ReleaseMutex (hSemCE->hMutex); + return WaitResult; +} + +BOOL CloseSynchHandle (SYNCHHANDLE hSynch) +/* Close a synchronization handle. + Improvement: Test for a valid handle before dereferencing the handle. */ +{ + BOOL Result = TRUE; + if (hSynch->hEvent != NULL) Result = Result && CloseHandle (hSynch->hEvent); + if (hSynch->hMutex != NULL) Result = Result && CloseHandle (hSynch->hMutex); + if (hSynch->hSemph != NULL) Result = Result && CloseHandle (hSynch->hSemph); + HeapFree (GetProcessHeap (), 0, hSynch); + return (Result); +} + +static SYNCHHANDLE CleanUp (SYNCHHANDLE hSynch, DWORD Flags) +{ /* Prepare to return from a create of a synchronization handle. + If there was any failure, free any allocated resources. + "Flags" indicates which Win32 objects are required in the + synchronization handle. */ + + BOOL ok = TRUE; + + if (hSynch == NULL) return NULL; + if ((Flags & 4) == 1 && (hSynch->hEvent == NULL)) ok = FALSE; + if ((Flags & 2) == 1 && (hSynch->hMutex == NULL)) ok = FALSE; + if ((Flags & 1) == 1 && (hSynch->hEvent == NULL)) ok = FALSE; + if (!ok) + { + CloseSynchHandle (hSynch); + return NULL; + } + /* Everything worked */ + return hSynch; +} diff --git a/3rdparty/SDL/src/thread/win32/win_ce_semaphore.h b/3rdparty/SDL/src/thread/win32/win_ce_semaphore.h new file mode 100644 index 0000000..af2d7b6 --- /dev/null +++ b/3rdparty/SDL/src/thread/win32/win_ce_semaphore.h @@ -0,0 +1,22 @@ +/* win_ce_semaphore.h - header file to go with win_ce_semaphore.c */ + +typedef struct _SYNCH_HANDLE_STRUCTURE { + HANDLE hEvent; + HANDLE hMutex; + HANDLE hSemph; + LONG MaxCount; + volatile LONG CurCount; + LPCTSTR lpName; +} SYNCH_HANDLE_STRUCTURE, *SYNCHHANDLE; + +#define SYNCH_HANDLE_SIZE sizeof (SYNCH_HANDLE_STRUCTURE) + + /* Error codes - all must have bit 29 set */ +#define SYNCH_ERROR 0X20000000 /* EXERCISE - REFINE THE ERROR NUMBERS */ + +extern SYNCHHANDLE CreateSemaphoreCE (LPSECURITY_ATTRIBUTES, LONG, LONG, LPCTSTR); + +extern BOOL ReleaseSemaphoreCE (SYNCHHANDLE, LONG, LPLONG); +extern DWORD WaitForSemaphoreCE (SYNCHHANDLE, DWORD); + +extern BOOL CloseSynchHandle (SYNCHHANDLE); |