mirror of
https://github.com/yawut/SDL.git
synced 2026-09-07 08:36:19 -05:00
SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
This commit is contained in:
@@ -33,9 +33,11 @@
|
||||
on success.
|
||||
*/
|
||||
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
|
||||
extern int SDL_SYS_CreateThread(SDL_Thread *thread, void *args, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread);
|
||||
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);
|
||||
extern int SDL_SYS_CreateThread(SDL_Thread * thread, void *args);
|
||||
#endif
|
||||
|
||||
/* This function does any necessary setup in the child thread */
|
||||
@@ -44,9 +46,10 @@ 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);
|
||||
extern void SDL_SYS_WaitThread(SDL_Thread * thread);
|
||||
|
||||
/* This function kills the thread and returns */
|
||||
extern void SDL_SYS_KillThread(SDL_Thread *thread);
|
||||
extern void SDL_SYS_KillThread(SDL_Thread * thread);
|
||||
|
||||
#endif /* _SDL_systhread_h */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -38,16 +38,17 @@ static int SDL_numthreads = 0;
|
||||
static SDL_Thread **SDL_Threads = NULL;
|
||||
static SDL_mutex *thread_lock = NULL;
|
||||
|
||||
int SDL_ThreadsInit(void)
|
||||
int
|
||||
SDL_ThreadsInit(void)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
retval = 0;
|
||||
thread_lock = SDL_CreateMutex();
|
||||
if ( thread_lock == NULL ) {
|
||||
retval = -1;
|
||||
}
|
||||
return(retval);
|
||||
retval = 0;
|
||||
thread_lock = SDL_CreateMutex();
|
||||
if (thread_lock == NULL) {
|
||||
retval = -1;
|
||||
}
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/* This should never be called...
|
||||
@@ -55,244 +56,260 @@ int SDL_ThreadsInit(void)
|
||||
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)
|
||||
void
|
||||
SDL_ThreadsQuit(void)
|
||||
{
|
||||
SDL_mutex *mutex;
|
||||
SDL_mutex *mutex;
|
||||
|
||||
mutex = thread_lock;
|
||||
thread_lock = NULL;
|
||||
if ( mutex != NULL ) {
|
||||
SDL_DestroyMutex(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)
|
||||
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);
|
||||
/* 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 */
|
||||
/* Expand the list of threads, if necessary */
|
||||
#ifdef DEBUG_THREADS
|
||||
printf("Adding thread (%d already - %d max)\n",
|
||||
SDL_numthreads, SDL_maxthreads);
|
||||
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);
|
||||
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)
|
||||
static void
|
||||
SDL_DelThread(SDL_Thread * thread)
|
||||
{
|
||||
int i;
|
||||
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;
|
||||
}
|
||||
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);
|
||||
printf("Deleting thread (%d left - %d max)\n",
|
||||
SDL_numthreads, SDL_maxthreads);
|
||||
#endif
|
||||
}
|
||||
SDL_mutexV(thread_lock);
|
||||
}
|
||||
SDL_mutexV(thread_lock);
|
||||
|
||||
if ( SDL_Threads == NULL ) {
|
||||
SDL_ThreadsQuit();
|
||||
}
|
||||
if (SDL_Threads == NULL) {
|
||||
SDL_ThreadsQuit();
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 *
|
||||
SDL_GetErrBuf(void)
|
||||
{
|
||||
SDL_error *errbuf;
|
||||
SDL_error *errbuf;
|
||||
|
||||
errbuf = &SDL_global_error;
|
||||
if ( SDL_Threads ) {
|
||||
int i;
|
||||
Uint32 this_thread;
|
||||
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);
|
||||
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;
|
||||
typedef struct
|
||||
{
|
||||
int (SDLCALL * func) (void *);
|
||||
void *data;
|
||||
SDL_Thread *info;
|
||||
SDL_sem *wait;
|
||||
} thread_args;
|
||||
|
||||
void SDL_RunThread(void *data)
|
||||
void
|
||||
SDL_RunThread(void *data)
|
||||
{
|
||||
thread_args *args;
|
||||
int (SDLCALL *userfunc)(void *);
|
||||
void *userdata;
|
||||
int *statusloc;
|
||||
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();
|
||||
/* 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();
|
||||
/* 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;
|
||||
/* 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);
|
||||
/* Wake up the parent thread */
|
||||
SDL_SemPost(args->wait);
|
||||
|
||||
/* Run the function */
|
||||
*statusloc = userfunc(userdata);
|
||||
/* 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)
|
||||
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)
|
||||
DECLSPEC SDL_Thread *SDLCALL
|
||||
SDL_CreateThread(int (SDLCALL * fn) (void *), void *data)
|
||||
#endif
|
||||
{
|
||||
SDL_Thread *thread;
|
||||
thread_args *args;
|
||||
int ret;
|
||||
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;
|
||||
/* 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);
|
||||
}
|
||||
/* 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);
|
||||
/* Add the thread to the list of available threads */
|
||||
SDL_AddThread(thread);
|
||||
|
||||
/* Create the thread and go! */
|
||||
/* Create the thread and go! */
|
||||
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
|
||||
ret = SDL_SYS_CreateThread(thread, args, pfnBeginThread, pfnEndThread);
|
||||
ret = SDL_SYS_CreateThread(thread, args, pfnBeginThread, pfnEndThread);
|
||||
#else
|
||||
ret = SDL_SYS_CreateThread(thread, args);
|
||||
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);
|
||||
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);
|
||||
/* Everything is running now */
|
||||
return (thread);
|
||||
}
|
||||
|
||||
void SDL_WaitThread(SDL_Thread *thread, int *status)
|
||||
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);
|
||||
}
|
||||
if (thread) {
|
||||
SDL_SYS_WaitThread(thread);
|
||||
if (status) {
|
||||
*status = thread->status;
|
||||
}
|
||||
SDL_DelThread(thread);
|
||||
SDL_free(thread);
|
||||
}
|
||||
}
|
||||
|
||||
Uint32 SDL_GetThreadID(SDL_Thread *thread)
|
||||
Uint32
|
||||
SDL_GetThreadID(SDL_Thread * thread)
|
||||
{
|
||||
Uint32 id;
|
||||
Uint32 id;
|
||||
|
||||
if ( thread ) {
|
||||
id = thread->threadid;
|
||||
} else {
|
||||
id = SDL_ThreadID();
|
||||
}
|
||||
return(id);
|
||||
if (thread) {
|
||||
id = thread->threadid;
|
||||
} else {
|
||||
id = SDL_ThreadID();
|
||||
}
|
||||
return (id);
|
||||
}
|
||||
|
||||
void SDL_KillThread(SDL_Thread *thread)
|
||||
void
|
||||
SDL_KillThread(SDL_Thread * thread)
|
||||
{
|
||||
if ( thread ) {
|
||||
SDL_SYS_KillThread(thread);
|
||||
SDL_WaitThread(thread, NULL);
|
||||
}
|
||||
if (thread) {
|
||||
SDL_SYS_KillThread(thread);
|
||||
SDL_WaitThread(thread, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -52,15 +52,17 @@
|
||||
#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;
|
||||
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 */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -29,120 +29,126 @@
|
||||
|
||||
struct SDL_semaphore
|
||||
{
|
||||
struct SignalSemaphore Sem;
|
||||
struct SignalSemaphore Sem;
|
||||
};
|
||||
|
||||
#undef D
|
||||
|
||||
#define D(x)
|
||||
|
||||
SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
|
||||
SDL_sem *
|
||||
SDL_CreateSemaphore(Uint32 initial_value)
|
||||
{
|
||||
SDL_sem *sem;
|
||||
SDL_sem *sem;
|
||||
|
||||
sem = (SDL_sem *)SDL_malloc(sizeof(*sem));
|
||||
sem = (SDL_sem *) SDL_malloc(sizeof(*sem));
|
||||
|
||||
if ( ! sem ) {
|
||||
SDL_OutOfMemory();
|
||||
return(0);
|
||||
}
|
||||
if (!sem) {
|
||||
SDL_OutOfMemory();
|
||||
return (0);
|
||||
}
|
||||
|
||||
D(bug("Creating semaphore %lx...\n",sem));
|
||||
D(bug("Creating semaphore %lx...\n", sem));
|
||||
|
||||
SDL_memset(sem,0,sizeof(*sem));
|
||||
SDL_memset(sem, 0, sizeof(*sem));
|
||||
|
||||
InitSemaphore(&sem->Sem);
|
||||
InitSemaphore(&sem->Sem);
|
||||
|
||||
return(sem);
|
||||
return (sem);
|
||||
}
|
||||
|
||||
void SDL_DestroySemaphore(SDL_sem *sem)
|
||||
void
|
||||
SDL_DestroySemaphore(SDL_sem * sem)
|
||||
{
|
||||
D(bug("Destroying semaphore %lx...\n",sem));
|
||||
D(bug("Destroying semaphore %lx...\n", sem));
|
||||
|
||||
if ( sem ) {
|
||||
if (sem) {
|
||||
// Condizioni per liberare i task in attesa?
|
||||
SDL_free(sem);
|
||||
}
|
||||
SDL_free(sem);
|
||||
}
|
||||
}
|
||||
|
||||
int SDL_SemTryWait(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemTryWait(SDL_sem * sem)
|
||||
{
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
D(bug("TryWait semaphore...%lx\n",sem));
|
||||
D(bug("TryWait semaphore...%lx\n", sem));
|
||||
|
||||
ObtainSemaphore(&sem->Sem);
|
||||
// ReleaseSemaphore(&sem->Sem);
|
||||
ObtainSemaphore(&sem->Sem);
|
||||
// ReleaseSemaphore(&sem->Sem);
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
|
||||
int
|
||||
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
D(bug("WaitTimeout (%ld) semaphore...%lx\n",timeout,sem));
|
||||
D(bug("WaitTimeout (%ld) semaphore...%lx\n", timeout, sem));
|
||||
|
||||
/* A timeout of 0 is an easy case */
|
||||
if ( timeout == 0 ) {
|
||||
ObtainSemaphore(&sem->Sem);
|
||||
return 1;
|
||||
}
|
||||
if(!(retval=AttemptSemaphore(&sem->Sem)))
|
||||
{
|
||||
SDL_Delay(timeout);
|
||||
retval=AttemptSemaphore(&sem->Sem);
|
||||
}
|
||||
/* A timeout of 0 is an easy case */
|
||||
if (timeout == 0) {
|
||||
ObtainSemaphore(&sem->Sem);
|
||||
return 1;
|
||||
}
|
||||
if (!(retval = AttemptSemaphore(&sem->Sem))) {
|
||||
SDL_Delay(timeout);
|
||||
retval = AttemptSemaphore(&sem->Sem);
|
||||
}
|
||||
|
||||
if(retval==TRUE)
|
||||
{
|
||||
// ReleaseSemaphore(&sem->Sem);
|
||||
retval=1;
|
||||
}
|
||||
if (retval == TRUE) {
|
||||
// ReleaseSemaphore(&sem->Sem);
|
||||
retval = 1;
|
||||
}
|
||||
|
||||
return retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
int SDL_SemWait(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemWait(SDL_sem * sem)
|
||||
{
|
||||
ObtainSemaphore(&sem->Sem);
|
||||
return 0;
|
||||
ObtainSemaphore(&sem->Sem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Uint32 SDL_SemValue(SDL_sem *sem)
|
||||
Uint32
|
||||
SDL_SemValue(SDL_sem * sem)
|
||||
{
|
||||
Uint32 value;
|
||||
Uint32 value;
|
||||
|
||||
value = 0;
|
||||
if ( sem ) {
|
||||
#ifdef STORMC4_WOS
|
||||
value = sem->Sem.ssppc_SS.ss_NestCount;
|
||||
#else
|
||||
value = sem->Sem.ss_NestCount;
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
value = 0;
|
||||
if (sem) {
|
||||
#ifdef STORMC4_WOS
|
||||
value = sem->Sem.ssppc_SS.ss_NestCount;
|
||||
#else
|
||||
value = sem->Sem.ss_NestCount;
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
int SDL_SemPost(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemPost(SDL_sem * sem)
|
||||
{
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
D(bug("SemPost semaphore...%lx\n",sem));
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
D(bug("SemPost semaphore...%lx\n", sem));
|
||||
|
||||
ReleaseSemaphore(&sem->Sem);
|
||||
return 0;
|
||||
ReleaseSemaphore(&sem->Sem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -29,123 +29,137 @@
|
||||
#include "../SDL_systhread.h"
|
||||
#include "mydebug.h"
|
||||
|
||||
typedef struct {
|
||||
int (*func)(void *);
|
||||
void *data;
|
||||
SDL_Thread *info;
|
||||
struct Task *wait;
|
||||
typedef struct
|
||||
{
|
||||
int (*func) (void *);
|
||||
void *data;
|
||||
SDL_Thread *info;
|
||||
struct Task *wait;
|
||||
} thread_args;
|
||||
|
||||
#ifndef MORPHOS
|
||||
|
||||
#if defined(__SASC) && !defined(__PPC__)
|
||||
__saveds __asm Uint32 RunThread(register __a0 char *args )
|
||||
#if defined(__SASC) && !defined(__PPC__)
|
||||
__saveds __asm Uint32
|
||||
RunThread(register __a0 char *args)
|
||||
#elif defined(__PPC__)
|
||||
Uint32 RunThread(char *args)
|
||||
Uint32
|
||||
RunThread(char *args)
|
||||
#else
|
||||
Uint32 __saveds RunThread(char *args __asm("a0") )
|
||||
Uint32 __saveds
|
||||
RunThread(char *args __asm("a0"))
|
||||
#endif
|
||||
{
|
||||
#ifdef STORMC4_WOS
|
||||
thread_args *data=(thread_args *)args;
|
||||
#else
|
||||
thread_args *data=(thread_args *)atol(args);
|
||||
#endif
|
||||
#ifdef STORMC4_WOS
|
||||
thread_args *data = (thread_args *) args;
|
||||
#else
|
||||
thread_args *data = (thread_args *) atol(args);
|
||||
#endif
|
||||
|
||||
struct Task *Father;
|
||||
struct Task *Father;
|
||||
|
||||
D(bug("Received data: %lx\n",data));
|
||||
Father=data->wait;
|
||||
D(bug("Received data: %lx\n", data));
|
||||
Father = data->wait;
|
||||
|
||||
SDL_RunThread(data);
|
||||
SDL_RunThread(data);
|
||||
|
||||
Signal(Father,SIGBREAKF_CTRL_F);
|
||||
D(bug("Thread with data %lx ended\n",data));
|
||||
return(0);
|
||||
Signal(Father, SIGBREAKF_CTRL_F);
|
||||
D(bug("Thread with data %lx ended\n", data));
|
||||
return (0);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <emul/emulinterface.h>
|
||||
|
||||
Uint32 RunTheThread(void)
|
||||
Uint32
|
||||
RunTheThread(void)
|
||||
{
|
||||
thread_args *data=(thread_args *)atol((char *)REG_A0);
|
||||
struct Task *Father;
|
||||
thread_args *data = (thread_args *) atol((char *) REG_A0);
|
||||
struct Task *Father;
|
||||
|
||||
D(bug("Received data: %lx\n",data));
|
||||
Father=data->wait;
|
||||
D(bug("Received data: %lx\n", data));
|
||||
Father = data->wait;
|
||||
|
||||
SDL_RunThread(data);
|
||||
SDL_RunThread(data);
|
||||
|
||||
Signal(Father,SIGBREAKF_CTRL_F);
|
||||
D(bug("Thread with data %lx ended\n",data));
|
||||
return(0);
|
||||
Signal(Father, SIGBREAKF_CTRL_F);
|
||||
D(bug("Thread with data %lx ended\n", data));
|
||||
return (0);
|
||||
}
|
||||
|
||||
struct EmulLibEntry RunThreadStruct=
|
||||
{
|
||||
TRAP_LIB,
|
||||
0,
|
||||
(ULONG)RunTheThread
|
||||
struct EmulLibEntry RunThreadStruct = {
|
||||
TRAP_LIB,
|
||||
0,
|
||||
(ULONG) RunTheThread
|
||||
};
|
||||
|
||||
void *RunThread=&RunThreadStruct;
|
||||
void *RunThread = &RunThreadStruct;
|
||||
#endif
|
||||
|
||||
|
||||
int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
|
||||
int
|
||||
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
|
||||
{
|
||||
/* Create the thread and go! */
|
||||
char buffer[20];
|
||||
/* Create the thread and go! */
|
||||
char buffer[20];
|
||||
|
||||
D(bug("Sending %lx to the new thread...\n",args));
|
||||
D(bug("Sending %lx to the new thread...\n", args));
|
||||
|
||||
if(args)
|
||||
SDL_snprintf(buffer, SDL_arraysize(buffer),"%ld",args);
|
||||
if (args)
|
||||
SDL_snprintf(buffer, SDL_arraysize(buffer), "%ld", args);
|
||||
|
||||
#ifdef STORMC4_WOS
|
||||
thread->handle=CreateTaskPPCTags(TASKATTR_CODE, RunThread,
|
||||
TASKATTR_NAME, "SDL subtask",
|
||||
TASKATTR_STACKSIZE, 100000,
|
||||
(args ? TASKATTR_R3 : TAG_IGNORE), args,
|
||||
TASKATTR_INHERITR2, TRUE,
|
||||
TAG_DONE);
|
||||
#else
|
||||
thread->handle=(struct Task *)CreateNewProcTags(NP_Output,Output(),
|
||||
NP_Name,(ULONG)"SDL subtask",
|
||||
NP_CloseOutput, FALSE,
|
||||
NP_StackSize,20000,
|
||||
NP_Entry,(ULONG)RunThread,
|
||||
args ? NP_Arguments : TAG_IGNORE,(ULONG)buffer,
|
||||
TAG_DONE);
|
||||
#endif
|
||||
#ifdef STORMC4_WOS
|
||||
thread->handle = CreateTaskPPCTags(TASKATTR_CODE, RunThread,
|
||||
TASKATTR_NAME, "SDL subtask",
|
||||
TASKATTR_STACKSIZE, 100000,
|
||||
(args ? TASKATTR_R3 : TAG_IGNORE),
|
||||
args, TASKATTR_INHERITR2, TRUE,
|
||||
TAG_DONE);
|
||||
#else
|
||||
thread->handle = (struct Task *) CreateNewProcTags(NP_Output, Output(),
|
||||
NP_Name,
|
||||
(ULONG) "SDL subtask",
|
||||
NP_CloseOutput, FALSE,
|
||||
NP_StackSize, 20000,
|
||||
NP_Entry,
|
||||
(ULONG) RunThread,
|
||||
args ? NP_Arguments :
|
||||
TAG_IGNORE,
|
||||
(ULONG) buffer,
|
||||
TAG_DONE);
|
||||
#endif
|
||||
|
||||
if(!thread->handle)
|
||||
{
|
||||
SDL_SetError("Not enough resources to create thread");
|
||||
return(-1);
|
||||
}
|
||||
if (!thread->handle) {
|
||||
SDL_SetError("Not enough resources to create thread");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void SDL_SYS_SetupThread(void)
|
||||
void
|
||||
SDL_SYS_SetupThread(void)
|
||||
{
|
||||
}
|
||||
|
||||
Uint32 SDL_ThreadID(void)
|
||||
Uint32
|
||||
SDL_ThreadID(void)
|
||||
{
|
||||
return((Uint32)FindTask(NULL));
|
||||
return ((Uint32) FindTask(NULL));
|
||||
}
|
||||
|
||||
void SDL_SYS_WaitThread(SDL_Thread *thread)
|
||||
void
|
||||
SDL_SYS_WaitThread(SDL_Thread * thread)
|
||||
{
|
||||
SetSignal(0L,SIGBREAKF_CTRL_F|SIGBREAKF_CTRL_C);
|
||||
Wait(SIGBREAKF_CTRL_F|SIGBREAKF_CTRL_C);
|
||||
SetSignal(0L, SIGBREAKF_CTRL_F | SIGBREAKF_CTRL_C);
|
||||
Wait(SIGBREAKF_CTRL_F | SIGBREAKF_CTRL_C);
|
||||
}
|
||||
|
||||
void SDL_SYS_KillThread(SDL_Thread *thread)
|
||||
void
|
||||
SDL_SYS_KillThread(SDL_Thread * thread)
|
||||
{
|
||||
Signal((struct Task *)thread->handle,SIGBREAKF_CTRL_C);
|
||||
Signal((struct Task *) thread->handle, SIGBREAKF_CTRL_C);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -57,5 +57,5 @@ extern struct DosLibrary *DOSBase;
|
||||
#else
|
||||
|
||||
#define SYS_ThreadHandle struct Task *
|
||||
#endif /*STORMC4_WOS*/
|
||||
|
||||
#endif /*STORMC4_WOS */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -39,11 +39,12 @@ static SDL_Thread **SDL_Threads = NULL;
|
||||
static struct SignalSemaphore thread_lock;
|
||||
int thread_lock_created = 0;
|
||||
|
||||
int SDL_ThreadsInit(void)
|
||||
int
|
||||
SDL_ThreadsInit(void)
|
||||
{
|
||||
InitSemaphore(&thread_lock);
|
||||
thread_lock_created=1;
|
||||
return 0;
|
||||
InitSemaphore(&thread_lock);
|
||||
thread_lock_created = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This should never be called...
|
||||
@@ -51,228 +52,240 @@ int SDL_ThreadsInit(void)
|
||||
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_ThreadsQuit()
|
||||
{
|
||||
thread_lock_created=0;
|
||||
thread_lock_created = 0;
|
||||
}
|
||||
|
||||
/* Routines for manipulating the thread list */
|
||||
static void SDL_AddThread(SDL_Thread *thread)
|
||||
static void
|
||||
SDL_AddThread(SDL_Thread * thread)
|
||||
{
|
||||
SDL_Thread **threads;
|
||||
SDL_Thread **threads;
|
||||
|
||||
/* 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_created ) {
|
||||
if ( SDL_ThreadsInit() < 0 ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
ObtainSemaphore(&thread_lock);
|
||||
/* 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_created) {
|
||||
if (SDL_ThreadsInit() < 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
ObtainSemaphore(&thread_lock);
|
||||
|
||||
/* Expand the list of threads, if necessary */
|
||||
/* Expand the list of threads, if necessary */
|
||||
#ifdef DEBUG_THREADS
|
||||
printf("Adding thread (%d already - %d max)\n",
|
||||
SDL_numthreads, SDL_maxthreads);
|
||||
printf("Adding thread (%d already - %d max)\n",
|
||||
SDL_numthreads, SDL_maxthreads);
|
||||
#endif
|
||||
if ( SDL_numthreads == SDL_maxthreads ) {
|
||||
threads=(SDL_Thread **)SDL_malloc((SDL_maxthreads+ARRAY_CHUNKSIZE)*
|
||||
(sizeof *threads));
|
||||
if ( threads == NULL ) {
|
||||
SDL_OutOfMemory();
|
||||
goto done;
|
||||
}
|
||||
SDL_memcpy(threads, SDL_Threads, SDL_numthreads*(sizeof *threads));
|
||||
SDL_maxthreads += ARRAY_CHUNKSIZE;
|
||||
if ( SDL_Threads ) {
|
||||
SDL_free(SDL_Threads);
|
||||
}
|
||||
SDL_Threads = threads;
|
||||
}
|
||||
SDL_Threads[SDL_numthreads++] = thread;
|
||||
done:
|
||||
ReleaseSemaphore(&thread_lock);
|
||||
if (SDL_numthreads == SDL_maxthreads) {
|
||||
threads =
|
||||
(SDL_Thread **) SDL_malloc((SDL_maxthreads + ARRAY_CHUNKSIZE) *
|
||||
(sizeof *threads));
|
||||
if (threads == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
goto done;
|
||||
}
|
||||
SDL_memcpy(threads, SDL_Threads, SDL_numthreads * (sizeof *threads));
|
||||
SDL_maxthreads += ARRAY_CHUNKSIZE;
|
||||
if (SDL_Threads) {
|
||||
SDL_free(SDL_Threads);
|
||||
}
|
||||
SDL_Threads = threads;
|
||||
}
|
||||
SDL_Threads[SDL_numthreads++] = thread;
|
||||
done:
|
||||
ReleaseSemaphore(&thread_lock);
|
||||
}
|
||||
|
||||
static void SDL_DelThread(SDL_Thread *thread)
|
||||
static void
|
||||
SDL_DelThread(SDL_Thread * thread)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
if ( thread_lock_created ) {
|
||||
ObtainSemaphore(&thread_lock);
|
||||
for ( i=0; i<SDL_numthreads; ++i ) {
|
||||
if ( thread == SDL_Threads[i] ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( i < SDL_numthreads ) {
|
||||
--SDL_numthreads;
|
||||
while ( i < SDL_numthreads ) {
|
||||
SDL_Threads[i] = SDL_Threads[i+1];
|
||||
++i;
|
||||
}
|
||||
if (thread_lock_created) {
|
||||
ObtainSemaphore(&thread_lock);
|
||||
for (i = 0; i < SDL_numthreads; ++i) {
|
||||
if (thread == SDL_Threads[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < SDL_numthreads) {
|
||||
--SDL_numthreads;
|
||||
while (i < SDL_numthreads) {
|
||||
SDL_Threads[i] = SDL_Threads[i + 1];
|
||||
++i;
|
||||
}
|
||||
#ifdef DEBUG_THREADS
|
||||
printf("Deleting thread (%d left - %d max)\n",
|
||||
SDL_numthreads, SDL_maxthreads);
|
||||
printf("Deleting thread (%d left - %d max)\n",
|
||||
SDL_numthreads, SDL_maxthreads);
|
||||
#endif
|
||||
}
|
||||
ReleaseSemaphore(&thread_lock);
|
||||
}
|
||||
}
|
||||
ReleaseSemaphore(&thread_lock);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 *
|
||||
SDL_GetErrBuf(void)
|
||||
{
|
||||
SDL_error *errbuf;
|
||||
SDL_error *errbuf;
|
||||
|
||||
errbuf = &SDL_global_error;
|
||||
if ( SDL_Threads ) {
|
||||
int i;
|
||||
Uint32 this_thread;
|
||||
errbuf = &SDL_global_error;
|
||||
if (SDL_Threads) {
|
||||
int i;
|
||||
Uint32 this_thread;
|
||||
|
||||
this_thread = SDL_ThreadID();
|
||||
ObtainSemaphore(&thread_lock);
|
||||
for ( i=0; i<SDL_numthreads; ++i ) {
|
||||
if ( this_thread == SDL_Threads[i]->threadid ) {
|
||||
errbuf = &SDL_Threads[i]->errbuf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ReleaseSemaphore(&thread_lock);
|
||||
}
|
||||
return(errbuf);
|
||||
this_thread = SDL_ThreadID();
|
||||
ObtainSemaphore(&thread_lock);
|
||||
for (i = 0; i < SDL_numthreads; ++i) {
|
||||
if (this_thread == SDL_Threads[i]->threadid) {
|
||||
errbuf = &SDL_Threads[i]->errbuf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ReleaseSemaphore(&thread_lock);
|
||||
}
|
||||
return (errbuf);
|
||||
}
|
||||
|
||||
|
||||
/* Arguments and callback to setup and run the user thread function */
|
||||
typedef struct {
|
||||
int (*func)(void *);
|
||||
void *data;
|
||||
SDL_Thread *info;
|
||||
struct Task *wait;
|
||||
typedef struct
|
||||
{
|
||||
int (*func) (void *);
|
||||
void *data;
|
||||
SDL_Thread *info;
|
||||
struct Task *wait;
|
||||
} thread_args;
|
||||
|
||||
void SDL_RunThread(void *data)
|
||||
void
|
||||
SDL_RunThread(void *data)
|
||||
{
|
||||
thread_args *args;
|
||||
int (*userfunc)(void *);
|
||||
void *userdata;
|
||||
int *statusloc;
|
||||
thread_args *args;
|
||||
int (*userfunc) (void *);
|
||||
void *userdata;
|
||||
int *statusloc;
|
||||
|
||||
/* Perform any system-dependent setup
|
||||
- this function cannot fail, and cannot use SDL_SetError()
|
||||
*/
|
||||
SDL_SYS_SetupThread();
|
||||
/* 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();
|
||||
/* 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;
|
||||
/* Figure out what function to run */
|
||||
userfunc = args->func;
|
||||
userdata = args->data;
|
||||
statusloc = &args->info->status;
|
||||
|
||||
/* Wake up the parent thread */
|
||||
Signal(args->wait,SIGBREAKF_CTRL_E);
|
||||
/* Wake up the parent thread */
|
||||
Signal(args->wait, SIGBREAKF_CTRL_E);
|
||||
|
||||
/* Run the function */
|
||||
*statusloc = userfunc(userdata);
|
||||
/* Run the function */
|
||||
*statusloc = userfunc(userdata);
|
||||
}
|
||||
|
||||
SDL_Thread *SDL_CreateThread(int (*fn)(void *), void *data)
|
||||
SDL_Thread *
|
||||
SDL_CreateThread(int (*fn) (void *), void *data)
|
||||
{
|
||||
SDL_Thread *thread;
|
||||
thread_args *args;
|
||||
int ret;
|
||||
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;
|
||||
/* 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 = FindTask(NULL);
|
||||
if ( args->wait == NULL ) {
|
||||
SDL_free(thread);
|
||||
SDL_free(args);
|
||||
SDL_OutOfMemory();
|
||||
return(NULL);
|
||||
}
|
||||
/* 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 = FindTask(NULL);
|
||||
if (args->wait == NULL) {
|
||||
SDL_free(thread);
|
||||
SDL_free(args);
|
||||
SDL_OutOfMemory();
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Add the thread to the list of available threads */
|
||||
SDL_AddThread(thread);
|
||||
/* Add the thread to the list of available threads */
|
||||
SDL_AddThread(thread);
|
||||
|
||||
D(bug("Starting thread...\n"));
|
||||
D(bug("Starting thread...\n"));
|
||||
|
||||
/* Create the thread and go! */
|
||||
ret = SDL_SYS_CreateThread(thread, args);
|
||||
if ( ret >= 0 ) {
|
||||
D(bug("Waiting for thread CTRL_E...\n"));
|
||||
/* Wait for the thread function to use arguments */
|
||||
Wait(SIGBREAKF_CTRL_E);
|
||||
D(bug(" Arrived."));
|
||||
} else {
|
||||
/* Oops, failed. Gotta free everything */
|
||||
SDL_DelThread(thread);
|
||||
SDL_free(thread);
|
||||
thread = NULL;
|
||||
}
|
||||
SDL_free(args);
|
||||
/* Create the thread and go! */
|
||||
ret = SDL_SYS_CreateThread(thread, args);
|
||||
if (ret >= 0) {
|
||||
D(bug("Waiting for thread CTRL_E...\n"));
|
||||
/* Wait for the thread function to use arguments */
|
||||
Wait(SIGBREAKF_CTRL_E);
|
||||
D(bug(" Arrived."));
|
||||
} else {
|
||||
/* Oops, failed. Gotta free everything */
|
||||
SDL_DelThread(thread);
|
||||
SDL_free(thread);
|
||||
thread = NULL;
|
||||
}
|
||||
SDL_free(args);
|
||||
|
||||
/* Everything is running now */
|
||||
return(thread);
|
||||
/* Everything is running now */
|
||||
return (thread);
|
||||
}
|
||||
|
||||
void SDL_WaitThread(SDL_Thread *thread, int *status)
|
||||
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);
|
||||
}
|
||||
if (thread) {
|
||||
SDL_SYS_WaitThread(thread);
|
||||
if (status) {
|
||||
*status = thread->status;
|
||||
}
|
||||
SDL_DelThread(thread);
|
||||
SDL_free(thread);
|
||||
}
|
||||
}
|
||||
|
||||
Uint32 SDL_GetThreadID(SDL_Thread *thread)
|
||||
Uint32
|
||||
SDL_GetThreadID(SDL_Thread * thread)
|
||||
{
|
||||
Uint32 id;
|
||||
Uint32 id;
|
||||
|
||||
if ( thread ) {
|
||||
id = thread->threadid;
|
||||
} else {
|
||||
id = SDL_ThreadID();
|
||||
}
|
||||
return(id);
|
||||
if (thread) {
|
||||
id = thread->threadid;
|
||||
} else {
|
||||
id = SDL_ThreadID();
|
||||
}
|
||||
return (id);
|
||||
}
|
||||
|
||||
void SDL_KillThread(SDL_Thread *thread)
|
||||
void
|
||||
SDL_KillThread(SDL_Thread * thread)
|
||||
{
|
||||
if ( thread ) {
|
||||
SDL_SYS_KillThread(thread);
|
||||
SDL_WaitThread(thread, NULL);
|
||||
}
|
||||
if (thread) {
|
||||
SDL_SYS_KillThread(thread);
|
||||
SDL_WaitThread(thread, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -28,115 +28,125 @@
|
||||
#include "SDL_thread.h"
|
||||
|
||||
|
||||
struct SDL_semaphore {
|
||||
sem_id id;
|
||||
struct SDL_semaphore
|
||||
{
|
||||
sem_id id;
|
||||
};
|
||||
|
||||
/* Create a counting semaphore */
|
||||
SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
|
||||
SDL_sem *
|
||||
SDL_CreateSemaphore(Uint32 initial_value)
|
||||
{
|
||||
SDL_sem *sem;
|
||||
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);
|
||||
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)
|
||||
void
|
||||
SDL_DestroySemaphore(SDL_sem * sem)
|
||||
{
|
||||
if ( sem ) {
|
||||
if ( sem->id >= B_NO_ERROR ) {
|
||||
delete_sem(sem->id);
|
||||
}
|
||||
SDL_free(sem);
|
||||
}
|
||||
if (sem) {
|
||||
if (sem->id >= B_NO_ERROR) {
|
||||
delete_sem(sem->id);
|
||||
}
|
||||
SDL_free(sem);
|
||||
}
|
||||
}
|
||||
|
||||
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
|
||||
int
|
||||
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
|
||||
{
|
||||
int32 val;
|
||||
int retval;
|
||||
int32 val;
|
||||
int retval;
|
||||
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
return retval;
|
||||
}
|
||||
|
||||
int SDL_SemTryWait(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemTryWait(SDL_sem * sem)
|
||||
{
|
||||
return SDL_SemWaitTimeout(sem, 0);
|
||||
return SDL_SemWaitTimeout(sem, 0);
|
||||
}
|
||||
|
||||
int SDL_SemWait(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemWait(SDL_sem * sem)
|
||||
{
|
||||
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
|
||||
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
|
||||
}
|
||||
|
||||
/* Returns the current count of the semaphore */
|
||||
Uint32 SDL_SemValue(SDL_sem *sem)
|
||||
Uint32
|
||||
SDL_SemValue(SDL_sem * sem)
|
||||
{
|
||||
int32 count;
|
||||
Uint32 value;
|
||||
int32 count;
|
||||
Uint32 value;
|
||||
|
||||
value = 0;
|
||||
if ( sem ) {
|
||||
get_sem_count(sem->id, &count);
|
||||
if ( count > 0 ) {
|
||||
value = (Uint32)count;
|
||||
}
|
||||
}
|
||||
return 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)
|
||||
int
|
||||
SDL_SemPost(SDL_sem * sem)
|
||||
{
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
if (release_sem(sem->id) != B_NO_ERROR) {
|
||||
SDL_SetError("release_sem() failed");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -34,63 +34,74 @@
|
||||
|
||||
|
||||
static int sig_list[] = {
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGWINCH, 0
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGWINCH, 0
|
||||
};
|
||||
|
||||
void SDL_MaskSignals(sigset_t *omask)
|
||||
void
|
||||
SDL_MaskSignals(sigset_t * omask)
|
||||
{
|
||||
sigset_t mask;
|
||||
int i;
|
||||
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);
|
||||
sigemptyset(&mask);
|
||||
for (i = 0; sig_list[i]; ++i) {
|
||||
sigaddset(&mask, sig_list[i]);
|
||||
}
|
||||
sigprocmask(SIG_BLOCK, &mask, omask);
|
||||
}
|
||||
|
||||
static int32 RunThread(void *data)
|
||||
void
|
||||
SDL_UnmaskSignals(sigset_t * omask)
|
||||
{
|
||||
SDL_RunThread(data);
|
||||
return(0);
|
||||
sigprocmask(SIG_SETMASK, omask, NULL);
|
||||
}
|
||||
|
||||
int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
|
||||
static int32
|
||||
RunThread(void *data)
|
||||
{
|
||||
/* 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);
|
||||
SDL_RunThread(data);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void SDL_SYS_SetupThread(void)
|
||||
int
|
||||
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
|
||||
{
|
||||
/* Mask asynchronous signals for this thread */
|
||||
SDL_MaskSignals(NULL);
|
||||
/* 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);
|
||||
}
|
||||
|
||||
Uint32 SDL_ThreadID(void)
|
||||
void
|
||||
SDL_SYS_SetupThread(void)
|
||||
{
|
||||
return((Uint32)find_thread(NULL));
|
||||
/* Mask asynchronous signals for this thread */
|
||||
SDL_MaskSignals(NULL);
|
||||
}
|
||||
|
||||
void SDL_SYS_WaitThread(SDL_Thread *thread)
|
||||
Uint32
|
||||
SDL_ThreadID(void)
|
||||
{
|
||||
status_t the_status;
|
||||
|
||||
wait_for_thread(thread->handle, &the_status);
|
||||
return ((Uint32) find_thread(NULL));
|
||||
}
|
||||
|
||||
void SDL_SYS_KillThread(SDL_Thread *thread)
|
||||
void
|
||||
SDL_SYS_WaitThread(SDL_Thread * thread)
|
||||
{
|
||||
kill_thread(thread->handle);
|
||||
status_t the_status;
|
||||
|
||||
wait_for_thread(thread->handle, &the_status);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_KillThread(SDL_Thread * thread)
|
||||
{
|
||||
kill_thread(thread->handle);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -27,5 +27,7 @@
|
||||
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);
|
||||
extern void SDL_MaskSignals(sigset_t * omask);
|
||||
extern void SDL_UnmaskSignals(sigset_t * omask);
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -31,107 +31,111 @@
|
||||
|
||||
struct SDL_cond
|
||||
{
|
||||
SDL_mutex *lock;
|
||||
int waiting;
|
||||
int signals;
|
||||
SDL_sem *wait_sem;
|
||||
SDL_sem *wait_done;
|
||||
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 *
|
||||
SDL_CreateCond(void)
|
||||
{
|
||||
SDL_cond *cond;
|
||||
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);
|
||||
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)
|
||||
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);
|
||||
}
|
||||
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)
|
||||
int
|
||||
SDL_CondSignal(SDL_cond * cond)
|
||||
{
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
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);
|
||||
}
|
||||
/* 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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Restart all threads that are waiting on the condition variable */
|
||||
int SDL_CondBroadcast(SDL_cond *cond)
|
||||
int
|
||||
SDL_CondBroadcast(SDL_cond * cond)
|
||||
{
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
/* 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);
|
||||
}
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Wait on the condition variable for at most 'ms' milliseconds.
|
||||
@@ -154,62 +158,66 @@ Thread B:
|
||||
...
|
||||
SDL_UnlockMutex(lock);
|
||||
*/
|
||||
int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
|
||||
int
|
||||
SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
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);
|
||||
/* 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);
|
||||
/* 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);
|
||||
}
|
||||
/* 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);
|
||||
/* 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);
|
||||
/* Signal handshake complete */
|
||||
--cond->signals;
|
||||
}
|
||||
--cond->waiting;
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
|
||||
/* Lock the mutex, as is required by condition variable semantics */
|
||||
SDL_LockMutex(mutex);
|
||||
/* Lock the mutex, as is required by condition variable semantics */
|
||||
SDL_LockMutex(mutex);
|
||||
|
||||
return retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Wait on the condition variable forever */
|
||||
int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
|
||||
int
|
||||
SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex)
|
||||
{
|
||||
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
|
||||
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -20,4 +20,4 @@
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -28,95 +28,102 @@
|
||||
|
||||
#include <arch/spinlock.h>
|
||||
|
||||
struct SDL_mutex {
|
||||
int recursive;
|
||||
Uint32 owner;
|
||||
spinlock_t mutex;
|
||||
struct SDL_mutex
|
||||
{
|
||||
int recursive;
|
||||
Uint32 owner;
|
||||
spinlock_t mutex;
|
||||
};
|
||||
|
||||
/* Create a mutex */
|
||||
SDL_mutex *SDL_CreateMutex(void)
|
||||
SDL_mutex *
|
||||
SDL_CreateMutex(void)
|
||||
{
|
||||
SDL_mutex *mutex;
|
||||
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;
|
||||
/* 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)
|
||||
void
|
||||
SDL_DestroyMutex(SDL_mutex * mutex)
|
||||
{
|
||||
if ( mutex ) {
|
||||
SDL_free(mutex);
|
||||
}
|
||||
if (mutex) {
|
||||
SDL_free(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/* Lock the semaphore */
|
||||
int SDL_mutexP(SDL_mutex *mutex)
|
||||
int
|
||||
SDL_mutexP(SDL_mutex * mutex)
|
||||
{
|
||||
#if SDL_THREADS_DISABLED
|
||||
return SDL_arraysize(return ),0;
|
||||
return SDL_arraysize(return), 0;
|
||||
#else
|
||||
Uint32 this_thread;
|
||||
Uint32 this_thread;
|
||||
|
||||
if ( mutex == NULL ) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
return 0;
|
||||
#endif /* SDL_THREADS_DISABLED */
|
||||
}
|
||||
|
||||
/* Unlock the mutex */
|
||||
int SDL_mutexV(SDL_mutex *mutex)
|
||||
int
|
||||
SDL_mutexV(SDL_mutex * mutex)
|
||||
{
|
||||
#if SDL_THREADS_DISABLED
|
||||
return 0;
|
||||
return 0;
|
||||
#else
|
||||
if ( mutex == NULL ) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
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 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;
|
||||
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 */
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -20,4 +20,4 @@
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -19,9 +19,6 @@
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* An implementation of semaphores using mutexes and condition variables */
|
||||
@@ -33,44 +30,51 @@
|
||||
|
||||
#if SDL_THREADS_DISABLED
|
||||
|
||||
SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
|
||||
SDL_sem *
|
||||
SDL_CreateSemaphore(Uint32 initial_value)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return (SDL_sem *)0;
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return (SDL_sem *) 0;
|
||||
}
|
||||
|
||||
void SDL_DestroySemaphore(SDL_sem *sem)
|
||||
void
|
||||
SDL_DestroySemaphore(SDL_sem * sem)
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
int SDL_SemTryWait(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemTryWait(SDL_sem * sem)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
|
||||
int
|
||||
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int SDL_SemWait(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemWait(SDL_sem * sem)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Uint32 SDL_SemValue(SDL_sem *sem)
|
||||
Uint32
|
||||
SDL_SemValue(SDL_sem * sem)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SDL_SemPost(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemPost(SDL_sem * sem)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -79,95 +83,104 @@ int SDL_SemPost(SDL_sem *sem)
|
||||
|
||||
struct SDL_semaphore
|
||||
{
|
||||
semaphore_t sem;
|
||||
semaphore_t sem;
|
||||
};
|
||||
|
||||
SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
|
||||
SDL_sem *
|
||||
SDL_CreateSemaphore(Uint32 initial_value)
|
||||
{
|
||||
return (SDL_sem *)sem_create(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)
|
||||
void
|
||||
SDL_DestroySemaphore(SDL_sem * sem)
|
||||
{
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return;
|
||||
}
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return;
|
||||
}
|
||||
|
||||
sem_destroy(&sem->sem);
|
||||
sem_destroy(&sem->sem);
|
||||
}
|
||||
|
||||
int SDL_SemTryWait(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemTryWait(SDL_sem * sem)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
retval = sem_trywait(&sem->sem);
|
||||
if (retval == 0)
|
||||
return 0;
|
||||
else
|
||||
return SDL_MUTEX_TIMEDOUT;
|
||||
|
||||
return retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
|
||||
int
|
||||
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
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);
|
||||
}
|
||||
/* 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;
|
||||
retval = sem_wait_timed(&sem->sem, timeout);
|
||||
if (retval == -1)
|
||||
retval = SDL_MUTEX_TIMEDOUT;
|
||||
|
||||
return retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
int SDL_SemWait(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemWait(SDL_sem * sem)
|
||||
{
|
||||
int retval;
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ( ((retval = sem_wait(&sem->sem)) == -1) && (errno == EINTR) ) {}
|
||||
return retval;
|
||||
sem_wait(&sem->sem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Uint32 SDL_SemValue(SDL_sem *sem)
|
||||
Uint32
|
||||
SDL_SemValue(SDL_sem * sem)
|
||||
{
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return sem_count(&sem->sem);
|
||||
return sem_count(&sem->sem);
|
||||
}
|
||||
|
||||
int SDL_SemPost(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemPost(SDL_sem * sem)
|
||||
{
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sem_signal(&sem->sem);
|
||||
return 0;
|
||||
sem_signal(&sem->sem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_THREADS_DISABLED */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -20,4 +20,4 @@
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -29,32 +29,39 @@
|
||||
|
||||
#include <kos/thread.h>
|
||||
|
||||
int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
|
||||
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);
|
||||
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)
|
||||
void
|
||||
SDL_SYS_SetupThread(void)
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
Uint32 SDL_ThreadID(void)
|
||||
Uint32
|
||||
SDL_ThreadID(void)
|
||||
{
|
||||
return (Uint32)thd_get_current();
|
||||
return (Uint32) thd_get_current();
|
||||
}
|
||||
|
||||
void SDL_SYS_WaitThread(SDL_Thread *thread)
|
||||
void
|
||||
SDL_SYS_WaitThread(SDL_Thread * thread)
|
||||
{
|
||||
thd_wait(thread->handle);
|
||||
thd_wait(thread->handle);
|
||||
}
|
||||
|
||||
void SDL_SYS_KillThread(SDL_Thread *thread)
|
||||
void
|
||||
SDL_SYS_KillThread(SDL_Thread * thread)
|
||||
{
|
||||
thd_destroy(thread->handle);
|
||||
thd_destroy(thread->handle);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -21,4 +21,5 @@
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
typedef struct kthread* SYS_ThreadHandle;
|
||||
typedef struct kthread *SYS_ThreadHandle;
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -28,4 +28,4 @@
|
||||
*/
|
||||
|
||||
typedef int SYS_ThreadHandle;
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -31,107 +31,111 @@
|
||||
|
||||
struct SDL_cond
|
||||
{
|
||||
SDL_mutex *lock;
|
||||
int waiting;
|
||||
int signals;
|
||||
SDL_sem *wait_sem;
|
||||
SDL_sem *wait_done;
|
||||
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 *
|
||||
SDL_CreateCond(void)
|
||||
{
|
||||
SDL_cond *cond;
|
||||
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);
|
||||
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)
|
||||
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);
|
||||
}
|
||||
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)
|
||||
int
|
||||
SDL_CondSignal(SDL_cond * cond)
|
||||
{
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
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);
|
||||
}
|
||||
/* 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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Restart all threads that are waiting on the condition variable */
|
||||
int SDL_CondBroadcast(SDL_cond *cond)
|
||||
int
|
||||
SDL_CondBroadcast(SDL_cond * cond)
|
||||
{
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
/* 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);
|
||||
}
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Wait on the condition variable for at most 'ms' milliseconds.
|
||||
@@ -154,62 +158,66 @@ Thread B:
|
||||
...
|
||||
SDL_UnlockMutex(lock);
|
||||
*/
|
||||
int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
|
||||
int
|
||||
SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
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);
|
||||
/* 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);
|
||||
/* 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);
|
||||
}
|
||||
/* 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);
|
||||
/* 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);
|
||||
/* Signal handshake complete */
|
||||
--cond->signals;
|
||||
}
|
||||
--cond->waiting;
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
|
||||
/* Lock the mutex, as is required by condition variable semantics */
|
||||
SDL_LockMutex(mutex);
|
||||
/* Lock the mutex, as is required by condition variable semantics */
|
||||
SDL_LockMutex(mutex);
|
||||
|
||||
return retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Wait on the condition variable forever */
|
||||
int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
|
||||
int
|
||||
SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex)
|
||||
{
|
||||
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
|
||||
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -27,103 +27,110 @@
|
||||
#include "SDL_systhread_c.h"
|
||||
|
||||
|
||||
struct SDL_mutex {
|
||||
int recursive;
|
||||
Uint32 owner;
|
||||
SDL_sem *sem;
|
||||
struct SDL_mutex
|
||||
{
|
||||
int recursive;
|
||||
Uint32 owner;
|
||||
SDL_sem *sem;
|
||||
};
|
||||
|
||||
/* Create a mutex */
|
||||
SDL_mutex *SDL_CreateMutex(void)
|
||||
SDL_mutex *
|
||||
SDL_CreateMutex(void)
|
||||
{
|
||||
SDL_mutex *mutex;
|
||||
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;
|
||||
/* 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)
|
||||
void
|
||||
SDL_DestroyMutex(SDL_mutex * mutex)
|
||||
{
|
||||
if ( mutex ) {
|
||||
if ( mutex->sem ) {
|
||||
SDL_DestroySemaphore(mutex->sem);
|
||||
}
|
||||
SDL_free(mutex);
|
||||
}
|
||||
if (mutex) {
|
||||
if (mutex->sem) {
|
||||
SDL_DestroySemaphore(mutex->sem);
|
||||
}
|
||||
SDL_free(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/* Lock the semaphore */
|
||||
int SDL_mutexP(SDL_mutex *mutex)
|
||||
int
|
||||
SDL_mutexP(SDL_mutex * mutex)
|
||||
{
|
||||
#if SDL_THREADS_DISABLED
|
||||
return 0;
|
||||
return 0;
|
||||
#else
|
||||
Uint32 this_thread;
|
||||
Uint32 this_thread;
|
||||
|
||||
if ( mutex == NULL ) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
return 0;
|
||||
#endif /* SDL_THREADS_DISABLED */
|
||||
}
|
||||
|
||||
/* Unlock the mutex */
|
||||
int SDL_mutexV(SDL_mutex *mutex)
|
||||
int
|
||||
SDL_mutexV(SDL_mutex * mutex)
|
||||
{
|
||||
#if SDL_THREADS_DISABLED
|
||||
return 0;
|
||||
return 0;
|
||||
#else
|
||||
if ( mutex == NULL ) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
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 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;
|
||||
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 */
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -20,4 +20,4 @@
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -30,180 +30,195 @@
|
||||
|
||||
#if SDL_THREADS_DISABLED
|
||||
|
||||
SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
|
||||
SDL_sem *
|
||||
SDL_CreateSemaphore(Uint32 initial_value)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return (SDL_sem *)0;
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return (SDL_sem *) 0;
|
||||
}
|
||||
|
||||
void SDL_DestroySemaphore(SDL_sem *sem)
|
||||
void
|
||||
SDL_DestroySemaphore(SDL_sem * sem)
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
int SDL_SemTryWait(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemTryWait(SDL_sem * sem)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
|
||||
int
|
||||
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int SDL_SemWait(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemWait(SDL_sem * sem)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Uint32 SDL_SemValue(SDL_sem *sem)
|
||||
Uint32
|
||||
SDL_SemValue(SDL_sem * sem)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SDL_SemPost(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemPost(SDL_sem * sem)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
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;
|
||||
Uint32 count;
|
||||
Uint32 waiters_count;
|
||||
SDL_mutex *count_lock;
|
||||
SDL_cond *count_nonzero;
|
||||
};
|
||||
|
||||
SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
|
||||
SDL_sem *
|
||||
SDL_CreateSemaphore(Uint32 initial_value)
|
||||
{
|
||||
SDL_sem *sem;
|
||||
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 = (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;
|
||||
}
|
||||
sem->count_lock = SDL_CreateMutex();
|
||||
sem->count_nonzero = SDL_CreateCond();
|
||||
if (!sem->count_lock || !sem->count_nonzero) {
|
||||
SDL_DestroySemaphore(sem);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return sem;
|
||||
return sem;
|
||||
}
|
||||
|
||||
/* WARNING:
|
||||
You cannot call this function when another thread is using the semaphore.
|
||||
*/
|
||||
void SDL_DestroySemaphore(SDL_sem *sem)
|
||||
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);
|
||||
}
|
||||
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
|
||||
SDL_SemTryWait(SDL_sem * sem)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
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);
|
||||
retval = SDL_MUTEX_TIMEDOUT;
|
||||
SDL_LockMutex(sem->count_lock);
|
||||
if (sem->count > 0) {
|
||||
--sem->count;
|
||||
retval = 0;
|
||||
}
|
||||
SDL_UnlockMutex(sem->count_lock);
|
||||
|
||||
return retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
|
||||
int
|
||||
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
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);
|
||||
}
|
||||
/* 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;
|
||||
--sem->count;
|
||||
SDL_UnlockMutex(sem->count_lock);
|
||||
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;
|
||||
--sem->count;
|
||||
SDL_UnlockMutex(sem->count_lock);
|
||||
|
||||
return retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
int SDL_SemWait(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemWait(SDL_sem * sem)
|
||||
{
|
||||
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
|
||||
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
|
||||
}
|
||||
|
||||
Uint32 SDL_SemValue(SDL_sem *sem)
|
||||
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;
|
||||
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)
|
||||
int
|
||||
SDL_SemPost(SDL_sem * sem)
|
||||
{
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
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);
|
||||
SDL_LockMutex(sem->count_lock);
|
||||
if (sem->waiters_count > 0) {
|
||||
SDL_CondSignal(sem->count_nonzero);
|
||||
}
|
||||
++sem->count;
|
||||
SDL_UnlockMutex(sem->count_lock);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_THREADS_DISABLED */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -26,29 +26,35 @@
|
||||
#include "SDL_thread.h"
|
||||
#include "../SDL_systhread.h"
|
||||
|
||||
int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
|
||||
int
|
||||
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
|
||||
{
|
||||
SDL_SetError("Threads are not supported on this platform");
|
||||
return(-1);
|
||||
SDL_SetError("Threads are not supported on this platform");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
void SDL_SYS_SetupThread(void)
|
||||
void
|
||||
SDL_SYS_SetupThread(void)
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
Uint32 SDL_ThreadID(void)
|
||||
Uint32
|
||||
SDL_ThreadID(void)
|
||||
{
|
||||
return(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void SDL_SYS_WaitThread(SDL_Thread *thread)
|
||||
void
|
||||
SDL_SYS_WaitThread(SDL_Thread * thread)
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
void SDL_SYS_KillThread(SDL_Thread *thread)
|
||||
void
|
||||
SDL_SYS_KillThread(SDL_Thread * thread)
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -23,3 +23,4 @@
|
||||
|
||||
/* Stub until we implement threads on this platform */
|
||||
typedef int SYS_ThreadHandle;
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -36,8 +36,9 @@
|
||||
#include "SDL_thread.h"
|
||||
|
||||
|
||||
struct SDL_semaphore {
|
||||
int id;
|
||||
struct SDL_semaphore
|
||||
{
|
||||
int id;
|
||||
};
|
||||
|
||||
/* Not defined by many operating systems, use configure to detect */
|
||||
@@ -52,168 +53,178 @@ union semun {
|
||||
*/
|
||||
|
||||
static struct sembuf op_trywait[2] = {
|
||||
{ 0, -1, (IPC_NOWAIT|SEM_UNDO) } /* Decrement semaphore, no block */
|
||||
{0, -1, (IPC_NOWAIT | SEM_UNDO)} /* Decrement semaphore, no block */
|
||||
};
|
||||
static struct sembuf op_wait[2] = {
|
||||
{ 0, -1, SEM_UNDO } /* Decrement semaphore */
|
||||
{0, -1, SEM_UNDO} /* Decrement semaphore */
|
||||
};
|
||||
static struct sembuf op_post[1] = {
|
||||
{ 0, 1, (IPC_NOWAIT|SEM_UNDO) } /* Increment semaphore */
|
||||
{0, 1, (IPC_NOWAIT | SEM_UNDO)} /* Increment semaphore */
|
||||
};
|
||||
|
||||
/* Create a blockable semaphore */
|
||||
SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
|
||||
SDL_sem *
|
||||
SDL_CreateSemaphore(Uint32 initial_value)
|
||||
{
|
||||
extern int _creating_thread_lock; /* SDL_threads.c */
|
||||
SDL_sem *sem;
|
||||
union semun init;
|
||||
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);
|
||||
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)
|
||||
void
|
||||
SDL_DestroySemaphore(SDL_sem * sem)
|
||||
{
|
||||
if ( sem ) {
|
||||
if (sem) {
|
||||
#ifdef __IRIX__
|
||||
semctl(sem->id, 0, IPC_RMID);
|
||||
semctl(sem->id, 0, IPC_RMID);
|
||||
#else
|
||||
union semun dummy;
|
||||
dummy.val = 0;
|
||||
semctl(sem->id, 0, IPC_RMID, dummy);
|
||||
union semun dummy;
|
||||
dummy.val = 0;
|
||||
semctl(sem->id, 0, IPC_RMID, dummy);
|
||||
#endif
|
||||
SDL_free(sem);
|
||||
}
|
||||
SDL_free(sem);
|
||||
}
|
||||
}
|
||||
|
||||
int SDL_SemTryWait(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemTryWait(SDL_sem * sem)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
retval = 0;
|
||||
tryagain:
|
||||
if ( semop(sem->id, op_trywait, 1) < 0 ) {
|
||||
if ( errno == EINTR ) {
|
||||
goto tryagain;
|
||||
}
|
||||
retval = SDL_MUTEX_TIMEDOUT;
|
||||
}
|
||||
return retval;
|
||||
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
|
||||
SDL_SemWait(SDL_sem * sem)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
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;
|
||||
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
|
||||
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
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);
|
||||
}
|
||||
/* 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 );
|
||||
/* 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;
|
||||
return retval;
|
||||
}
|
||||
|
||||
Uint32 SDL_SemValue(SDL_sem *sem)
|
||||
Uint32
|
||||
SDL_SemValue(SDL_sem * sem)
|
||||
{
|
||||
int semval;
|
||||
Uint32 value;
|
||||
|
||||
value = 0;
|
||||
if ( sem ) {
|
||||
tryagain:
|
||||
int semval;
|
||||
Uint32 value;
|
||||
|
||||
value = 0;
|
||||
if (sem) {
|
||||
tryagain:
|
||||
#ifdef __IRIX__
|
||||
semval = semctl(sem->id, 0, GETVAL);
|
||||
semval = semctl(sem->id, 0, GETVAL);
|
||||
#else
|
||||
{
|
||||
union semun arg;
|
||||
arg.val = 0;
|
||||
semval = semctl(sem->id, 0, GETVAL, arg);
|
||||
}
|
||||
{
|
||||
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;
|
||||
if (semval < 0) {
|
||||
if (errno == EINTR) {
|
||||
goto tryagain;
|
||||
}
|
||||
} else {
|
||||
value = (Uint32) semval;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
int SDL_SemPost(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemPost(SDL_sem * sem)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
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;
|
||||
if (semop(sem->id, op_post, 1) < 0) {
|
||||
if (errno == EINTR) {
|
||||
goto tryagain;
|
||||
}
|
||||
SDL_SetError("Semaphore operation error");
|
||||
retval = -1;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -34,52 +34,58 @@
|
||||
|
||||
|
||||
static int sig_list[] = {
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCLD, SIGWINCH,
|
||||
SIGVTALRM, SIGPROF, 0
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCLD, SIGWINCH,
|
||||
SIGVTALRM, SIGPROF, 0
|
||||
};
|
||||
|
||||
|
||||
int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
|
||||
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);
|
||||
/* 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)
|
||||
void
|
||||
SDL_SYS_SetupThread(void)
|
||||
{
|
||||
int i;
|
||||
sigset_t mask;
|
||||
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);
|
||||
/* 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)
|
||||
Uint32
|
||||
SDL_ThreadID(void)
|
||||
{
|
||||
return((Uint32)getpid());
|
||||
return ((Uint32) getpid());
|
||||
}
|
||||
|
||||
/* WARNING: This may not work for systems with 64-bit pid_t */
|
||||
void SDL_WaitThread(SDL_Thread *thread, int *status)
|
||||
void
|
||||
SDL_WaitThread(SDL_Thread * thread, int *status)
|
||||
{
|
||||
errno = 0;
|
||||
while ( errno != ECHILD ) {
|
||||
waitpid(thread->handle, NULL, 0);
|
||||
}
|
||||
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)
|
||||
void
|
||||
SDL_KillThread(SDL_Thread * thread)
|
||||
{
|
||||
kill(thread->handle, SIGKILL);
|
||||
kill(thread->handle, SIGKILL);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -24,4 +24,4 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef pid_t SYS_ThreadHandle;
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -31,107 +31,111 @@
|
||||
|
||||
struct SDL_cond
|
||||
{
|
||||
SDL_mutex *lock;
|
||||
int waiting;
|
||||
int signals;
|
||||
SDL_sem *wait_sem;
|
||||
SDL_sem *wait_done;
|
||||
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)
|
||||
DECLSPEC SDL_cond *SDLCALL
|
||||
SDL_CreateCond(void)
|
||||
{
|
||||
SDL_cond *cond;
|
||||
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);
|
||||
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)
|
||||
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);
|
||||
}
|
||||
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)
|
||||
DECLSPEC int SDLCALL
|
||||
SDL_CondSignal(SDL_cond * cond)
|
||||
{
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
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);
|
||||
}
|
||||
/* 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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Restart all threads that are waiting on the condition variable */
|
||||
DECLSPEC int SDLCALL SDL_CondBroadcast(SDL_cond *cond)
|
||||
DECLSPEC int SDLCALL
|
||||
SDL_CondBroadcast(SDL_cond * cond)
|
||||
{
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
/* 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);
|
||||
}
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Wait on the condition variable for at most 'ms' milliseconds.
|
||||
@@ -154,62 +158,66 @@ Thread B:
|
||||
...
|
||||
SDL_UnlockMutex(lock);
|
||||
*/
|
||||
DECLSPEC int SDLCALL SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
|
||||
DECLSPEC int SDLCALL
|
||||
SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
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);
|
||||
/* 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);
|
||||
/* 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);
|
||||
}
|
||||
/* 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);
|
||||
/* 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);
|
||||
/* Signal handshake complete */
|
||||
--cond->signals;
|
||||
}
|
||||
--cond->waiting;
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
|
||||
/* Lock the mutex, as is required by condition variable semantics */
|
||||
SDL_LockMutex(mutex);
|
||||
/* Lock the mutex, as is required by condition variable semantics */
|
||||
SDL_LockMutex(mutex);
|
||||
|
||||
return retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Wait on the condition variable forever */
|
||||
DECLSPEC int SDLCALL SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
|
||||
DECLSPEC int SDLCALL
|
||||
SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex)
|
||||
{
|
||||
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
|
||||
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -20,4 +20,4 @@
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -30,79 +30,78 @@
|
||||
#include "SDL_mutex.h"
|
||||
|
||||
|
||||
struct SDL_mutex {
|
||||
HMTX hmtxID;
|
||||
struct SDL_mutex
|
||||
{
|
||||
HMTX hmtxID;
|
||||
};
|
||||
|
||||
/* Create a mutex */
|
||||
DECLSPEC SDL_mutex * SDLCALL SDL_CreateMutex(void)
|
||||
DECLSPEC SDL_mutex *SDLCALL
|
||||
SDL_CreateMutex(void)
|
||||
{
|
||||
SDL_mutex *mutex;
|
||||
APIRET ulrc;
|
||||
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;
|
||||
/* 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();
|
||||
}
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
return(mutex);
|
||||
return (mutex);
|
||||
}
|
||||
|
||||
/* Free the mutex */
|
||||
DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_mutex *mutex)
|
||||
DECLSPEC void SDLCALL
|
||||
SDL_DestroyMutex(SDL_mutex * mutex)
|
||||
{
|
||||
if ( mutex )
|
||||
{
|
||||
if ( mutex->hmtxID )
|
||||
{
|
||||
DosCloseMutexSem(mutex->hmtxID);
|
||||
mutex->hmtxID = 0;
|
||||
if (mutex) {
|
||||
if (mutex->hmtxID) {
|
||||
DosCloseMutexSem(mutex->hmtxID);
|
||||
mutex->hmtxID = 0;
|
||||
}
|
||||
SDL_free(mutex);
|
||||
}
|
||||
SDL_free(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/* Lock the mutex */
|
||||
DECLSPEC int SDLCALL SDL_mutexP(SDL_mutex *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);
|
||||
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)
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -32,161 +32,163 @@
|
||||
#include "SDL_timer.h"
|
||||
|
||||
|
||||
struct SDL_semaphore {
|
||||
HMTX id;
|
||||
HEV changed;
|
||||
Uint32 value;
|
||||
struct SDL_semaphore
|
||||
{
|
||||
HMTX id;
|
||||
HEV changed;
|
||||
Uint32 value;
|
||||
};
|
||||
|
||||
|
||||
/* Create a semaphore */
|
||||
DECLSPEC SDL_sem * SDLCALL SDL_CreateSemaphore(Uint32 initial_value)
|
||||
DECLSPEC SDL_sem *SDLCALL
|
||||
SDL_CreateSemaphore(Uint32 initial_value)
|
||||
{
|
||||
SDL_sem *sem;
|
||||
ULONG ulrc;
|
||||
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);
|
||||
}
|
||||
/* 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 {
|
||||
SDL_OutOfMemory();
|
||||
DosCreateEventSem(NULL, &(sem->changed), 0, FALSE);
|
||||
sem->value = initial_value;
|
||||
DosReleaseMutexSem(sem->id);
|
||||
}
|
||||
return(sem);
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
return (sem);
|
||||
}
|
||||
|
||||
/* Free the semaphore */
|
||||
DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_sem *sem)
|
||||
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);
|
||||
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)
|
||||
DECLSPEC int SDLCALL
|
||||
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
|
||||
{
|
||||
ULONG ulrc;
|
||||
ULONG ulrc;
|
||||
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL sem");
|
||||
return -1;
|
||||
}
|
||||
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 {
|
||||
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) {
|
||||
/* if error waiting mutex */
|
||||
SDL_SetError("DosRequestMutexSem() failed");
|
||||
return -1;
|
||||
} else if (sem->value) {
|
||||
sem->value--;
|
||||
DosReleaseMutexSem(sem->id);
|
||||
return 0;
|
||||
} else {
|
||||
} 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;
|
||||
}
|
||||
DosWaitEventSem(sem->changed, SEM_INDEFINITE_WAIT);
|
||||
}
|
||||
}
|
||||
/* never reached */
|
||||
return -1;
|
||||
} 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)
|
||||
DECLSPEC int SDLCALL
|
||||
SDL_SemTryWait(SDL_sem * sem)
|
||||
{
|
||||
return SDL_SemWaitTimeout(sem, 0);
|
||||
return SDL_SemWaitTimeout(sem, 0);
|
||||
}
|
||||
|
||||
DECLSPEC int SDLCALL SDL_SemWait(SDL_sem *sem)
|
||||
DECLSPEC int SDLCALL
|
||||
SDL_SemWait(SDL_sem * sem)
|
||||
{
|
||||
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
|
||||
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
|
||||
}
|
||||
|
||||
/* Returns the current count of the semaphore */
|
||||
DECLSPEC Uint32 SDLCALL SDL_SemValue(SDL_sem *sem)
|
||||
DECLSPEC Uint32 SDLCALL
|
||||
SDL_SemValue(SDL_sem * sem)
|
||||
{
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL sem");
|
||||
return 0;
|
||||
}
|
||||
return sem->value;
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL sem");
|
||||
return 0;
|
||||
}
|
||||
return sem->value;
|
||||
}
|
||||
|
||||
DECLSPEC int SDLCALL SDL_SemPost(SDL_sem *sem)
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -34,75 +34,82 @@
|
||||
|
||||
typedef struct ThreadStartParms
|
||||
{
|
||||
void *args;
|
||||
pfnSDL_CurrentEndThread pfnCurrentEndThread;
|
||||
void *args;
|
||||
pfnSDL_CurrentEndThread pfnCurrentEndThread;
|
||||
} tThreadStartParms, *pThreadStartParms;
|
||||
|
||||
static void threadfunc(void *pparm)
|
||||
static void
|
||||
threadfunc(void *pparm)
|
||||
{
|
||||
pThreadStartParms pThreadParms = pparm;
|
||||
pfnSDL_CurrentEndThread pfnCurrentEndThread = NULL;
|
||||
pThreadStartParms pThreadParms = pparm;
|
||||
pfnSDL_CurrentEndThread pfnCurrentEndThread = NULL;
|
||||
|
||||
// Call the thread function!
|
||||
SDL_RunThread(pThreadParms->args);
|
||||
// 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)();
|
||||
// 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)
|
||||
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);
|
||||
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)
|
||||
void
|
||||
SDL_SYS_SetupThread(void)
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
DECLSPEC Uint32 SDLCALL SDL_ThreadID(void)
|
||||
DECLSPEC Uint32 SDLCALL
|
||||
SDL_ThreadID(void)
|
||||
{
|
||||
PTIB tib;
|
||||
DosGetInfoBlocks(&tib, NULL);
|
||||
return((Uint32) (tib->tib_ptib2->tib2_ultid));
|
||||
PTIB tib;
|
||||
DosGetInfoBlocks(&tib, NULL);
|
||||
return ((Uint32) (tib->tib_ptib2->tib2_ultid));
|
||||
}
|
||||
|
||||
void SDL_SYS_WaitThread(SDL_Thread *thread)
|
||||
void
|
||||
SDL_SYS_WaitThread(SDL_Thread * thread)
|
||||
{
|
||||
TID tid = thread->handle;
|
||||
DosWaitThread(&tid, DCWW_WAIT);
|
||||
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)
|
||||
void
|
||||
SDL_SYS_KillThread(SDL_Thread * thread)
|
||||
{
|
||||
DosKillThread(thread->handle);
|
||||
DosKillThread(thread->handle);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -25,4 +25,4 @@
|
||||
#include <os2.h>
|
||||
|
||||
typedef TID SYS_ThreadHandle;
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -34,69 +34,73 @@
|
||||
|
||||
struct SDL_cond
|
||||
{
|
||||
pth_cond_t condpth_p;
|
||||
pth_cond_t condpth_p;
|
||||
};
|
||||
|
||||
/* Create a condition variable */
|
||||
SDL_cond * SDL_CreateCond(void)
|
||||
SDL_cond *
|
||||
SDL_CreateCond(void)
|
||||
{
|
||||
SDL_cond *cond;
|
||||
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);
|
||||
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)
|
||||
void
|
||||
SDL_DestroyCond(SDL_cond * cond)
|
||||
{
|
||||
if ( cond ) {
|
||||
SDL_free(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
|
||||
SDL_CondSignal(SDL_cond * cond)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
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
|
||||
SDL_CondBroadcast(SDL_cond * cond)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
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.
|
||||
@@ -119,46 +123,51 @@ Thread B:
|
||||
...
|
||||
SDL_UnlockMutex(lock);
|
||||
*/
|
||||
int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
|
||||
int
|
||||
SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
|
||||
{
|
||||
int retval;
|
||||
pth_event_t ev;
|
||||
int sec;
|
||||
int retval;
|
||||
pth_event_t ev;
|
||||
int sec;
|
||||
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
if (!cond) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
retval = 0;
|
||||
|
||||
sec = ms/1000;
|
||||
ev = pth_event(PTH_EVENT_TIME, pth_timeout(sec,(ms-sec*1000)*1000));
|
||||
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;
|
||||
}
|
||||
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;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Wait on the condition variable forever */
|
||||
int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
|
||||
int
|
||||
SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
retval = 0;
|
||||
if (pth_cond_await(&(cond->condpth_p), &(mutex->mutexpth_p), NULL) != 0) {
|
||||
SDL_SetError("pth_cond_await() failed");
|
||||
retval = -1;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -33,55 +33,61 @@
|
||||
#include "SDL_sysmutex_c.h"
|
||||
|
||||
/* Create a mutex */
|
||||
SDL_mutex *SDL_CreateMutex(void)
|
||||
SDL_mutex *
|
||||
SDL_CreateMutex(void)
|
||||
{
|
||||
SDL_mutex *mutex;
|
||||
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);
|
||||
/* 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)
|
||||
void
|
||||
SDL_DestroyMutex(SDL_mutex * mutex)
|
||||
{
|
||||
if ( mutex ) {
|
||||
SDL_free(mutex);
|
||||
}
|
||||
if (mutex) {
|
||||
SDL_free(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/* Lock the mutex */
|
||||
int SDL_mutexP(SDL_mutex *mutex)
|
||||
int
|
||||
SDL_mutexP(SDL_mutex * mutex)
|
||||
{
|
||||
if ( mutex == NULL ) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
if (mutex == NULL) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pth_mutex_acquire(&(mutex->mutexpth_p), FALSE, NULL);
|
||||
pth_mutex_acquire(&(mutex->mutexpth_p), FALSE, NULL);
|
||||
|
||||
return(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Unlock the mutex */
|
||||
int SDL_mutexV(SDL_mutex *mutex)
|
||||
int
|
||||
SDL_mutexV(SDL_mutex * mutex)
|
||||
{
|
||||
if ( mutex == NULL ) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
if (mutex == NULL) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pth_mutex_release(&(mutex->mutexpth_p));
|
||||
|
||||
return(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -24,8 +24,10 @@
|
||||
#ifndef _SDL_SYSMUTEX_C_H_
|
||||
#define _SDL_SYSMUTEX_C_H_
|
||||
|
||||
struct SDL_mutex {
|
||||
pth_mutex_t mutexpth_p;
|
||||
struct SDL_mutex
|
||||
{
|
||||
pth_mutex_t mutexpth_p;
|
||||
};
|
||||
|
||||
#endif /* _SDL_SYSMUTEX_C_H_ */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -36,68 +36,76 @@
|
||||
|
||||
/* List of signals to mask in the subthreads */
|
||||
static int sig_list[] = {
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH,
|
||||
SIGVTALRM, SIGPROF, 0
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH,
|
||||
SIGVTALRM, SIGPROF, 0
|
||||
};
|
||||
|
||||
static void *RunThread(void *data)
|
||||
static void *
|
||||
RunThread(void *data)
|
||||
{
|
||||
SDL_RunThread(data);
|
||||
pth_exit((void*)0);
|
||||
return((void *)0); /* Prevent compiler warning */
|
||||
SDL_RunThread(data);
|
||||
pth_exit((void *) 0);
|
||||
return ((void *) 0); /* Prevent compiler warning */
|
||||
}
|
||||
|
||||
int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
|
||||
int
|
||||
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
|
||||
{
|
||||
pth_attr_t type;
|
||||
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 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);
|
||||
/* 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)
|
||||
void
|
||||
SDL_SYS_SetupThread(void)
|
||||
{
|
||||
int i;
|
||||
sigset_t mask;
|
||||
int oldstate;
|
||||
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);
|
||||
/* 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);
|
||||
/* 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)
|
||||
Uint32
|
||||
SDL_ThreadID(void)
|
||||
{
|
||||
return((Uint32)pth_self());
|
||||
return ((Uint32) pth_self());
|
||||
}
|
||||
|
||||
void SDL_SYS_WaitThread(SDL_Thread *thread)
|
||||
void
|
||||
SDL_SYS_WaitThread(SDL_Thread * thread)
|
||||
{
|
||||
pth_join(thread->handle, NULL);
|
||||
pth_join(thread->handle, NULL);
|
||||
}
|
||||
|
||||
void SDL_SYS_KillThread(SDL_Thread *thread)
|
||||
void
|
||||
SDL_SYS_KillThread(SDL_Thread * thread)
|
||||
{
|
||||
pth_cancel(thread->handle);
|
||||
pth_join(thread->handle, NULL);
|
||||
pth_cancel(thread->handle);
|
||||
pth_join(thread->handle, NULL);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -29,3 +29,4 @@
|
||||
typedef pth_t SYS_ThreadHandle;
|
||||
|
||||
#endif /* _SDL_SYSTHREAD_C_H_ */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -31,125 +31,133 @@
|
||||
|
||||
struct SDL_cond
|
||||
{
|
||||
pthread_cond_t cond;
|
||||
pthread_cond_t cond;
|
||||
};
|
||||
|
||||
/* Create a condition variable */
|
||||
SDL_cond * SDL_CreateCond(void)
|
||||
SDL_cond *
|
||||
SDL_CreateCond(void)
|
||||
{
|
||||
SDL_cond *cond;
|
||||
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);
|
||||
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)
|
||||
void
|
||||
SDL_DestroyCond(SDL_cond * cond)
|
||||
{
|
||||
if ( cond ) {
|
||||
pthread_cond_destroy(&cond->cond);
|
||||
SDL_free(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
|
||||
SDL_CondSignal(SDL_cond * cond)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
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
|
||||
SDL_CondBroadcast(SDL_cond * cond)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
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
|
||||
SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
|
||||
{
|
||||
int retval;
|
||||
struct timeval delta;
|
||||
struct timespec abstime;
|
||||
int retval;
|
||||
struct timeval delta;
|
||||
struct timespec abstime;
|
||||
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
if (!cond) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gettimeofday(&delta, NULL);
|
||||
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;
|
||||
}
|
||||
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;
|
||||
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
|
||||
SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
retval = 0;
|
||||
if (pthread_cond_wait(&cond->cond, &mutex->id) != 0) {
|
||||
SDL_SetError("pthread_cond_wait() failed");
|
||||
retval = -1;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -30,124 +30,131 @@
|
||||
#define FAKE_RECURSIVE_MUTEX
|
||||
#endif
|
||||
|
||||
struct SDL_mutex {
|
||||
pthread_mutex_t id;
|
||||
struct SDL_mutex
|
||||
{
|
||||
pthread_mutex_t id;
|
||||
#if FAKE_RECURSIVE_MUTEX
|
||||
int recursive;
|
||||
pthread_t owner;
|
||||
int recursive;
|
||||
pthread_t owner;
|
||||
#endif
|
||||
};
|
||||
|
||||
SDL_mutex *SDL_CreateMutex (void)
|
||||
SDL_mutex *
|
||||
SDL_CreateMutex(void)
|
||||
{
|
||||
SDL_mutex *mutex;
|
||||
pthread_mutexattr_t attr;
|
||||
SDL_mutex *mutex;
|
||||
pthread_mutexattr_t attr;
|
||||
|
||||
/* Allocate the structure */
|
||||
mutex = (SDL_mutex *)SDL_calloc(1, sizeof(*mutex));
|
||||
if ( mutex ) {
|
||||
pthread_mutexattr_init(&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);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
#elif SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP
|
||||
pthread_mutexattr_setkind_np(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
|
||||
pthread_mutexattr_setkind_np(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
|
||||
#else
|
||||
/* No extra attributes necessary */
|
||||
/* 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);
|
||||
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)
|
||||
void
|
||||
SDL_DestroyMutex(SDL_mutex * mutex)
|
||||
{
|
||||
if ( mutex ) {
|
||||
pthread_mutex_destroy(&mutex->id);
|
||||
SDL_free(mutex);
|
||||
}
|
||||
if (mutex) {
|
||||
pthread_mutex_destroy(&mutex->id);
|
||||
SDL_free(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/* Lock the mutex */
|
||||
int SDL_mutexP(SDL_mutex *mutex)
|
||||
int
|
||||
SDL_mutexP(SDL_mutex * mutex)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
#if FAKE_RECURSIVE_MUTEX
|
||||
pthread_t this_thread;
|
||||
pthread_t this_thread;
|
||||
#endif
|
||||
|
||||
if ( mutex == NULL ) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
if (mutex == NULL) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
if (pthread_mutex_lock(&mutex->id) < 0) {
|
||||
SDL_SetError("pthread_mutex_lock() failed");
|
||||
retval = -1;
|
||||
}
|
||||
#endif
|
||||
return retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
int SDL_mutexV(SDL_mutex *mutex)
|
||||
int
|
||||
SDL_mutexV(SDL_mutex * mutex)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( mutex == NULL ) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
if (mutex == NULL) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
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;
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
if (pthread_mutex_unlock(&mutex->id) < 0) {
|
||||
SDL_SetError("pthread_mutex_unlock() failed");
|
||||
retval = -1;
|
||||
}
|
||||
#endif /* FAKE_RECURSIVE_MUTEX */
|
||||
|
||||
return retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -24,8 +24,10 @@
|
||||
#ifndef _SDL_mutex_c_h
|
||||
#define _SDL_mutex_c_h
|
||||
|
||||
struct SDL_mutex {
|
||||
pthread_mutex_t id;
|
||||
struct SDL_mutex
|
||||
{
|
||||
pthread_mutex_t id;
|
||||
};
|
||||
|
||||
#endif /* _SDL_mutex_c_h */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_timer.h"
|
||||
@@ -35,122 +34,132 @@
|
||||
#include "../generic/SDL_syssem.c"
|
||||
#else
|
||||
|
||||
struct SDL_semaphore {
|
||||
sem_t sem;
|
||||
struct SDL_semaphore
|
||||
{
|
||||
sem_t sem;
|
||||
};
|
||||
|
||||
/* Create a semaphore, initialized with value */
|
||||
SDL_sem *SDL_CreateSemaphore(Uint32 initial_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;
|
||||
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)
|
||||
void
|
||||
SDL_DestroySemaphore(SDL_sem * sem)
|
||||
{
|
||||
if ( sem ) {
|
||||
sem_destroy(&sem->sem);
|
||||
SDL_free(sem);
|
||||
}
|
||||
if (sem) {
|
||||
sem_destroy(&sem->sem);
|
||||
SDL_free(sem);
|
||||
}
|
||||
}
|
||||
|
||||
int SDL_SemTryWait(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemTryWait(SDL_sem * sem)
|
||||
{
|
||||
int retval;
|
||||
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;
|
||||
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
|
||||
SDL_SemWait(SDL_sem * sem)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
retval = sem_wait(&sem->sem);
|
||||
if (retval < 0) {
|
||||
SDL_SetError("sem_wait() failed");
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
|
||||
int
|
||||
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
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);
|
||||
}
|
||||
/* 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... */
|
||||
/* FIXME: Use sem_timedwait()? */
|
||||
timeout += SDL_GetTicks();
|
||||
do {
|
||||
retval = SDL_SemTryWait(sem);
|
||||
if ( retval == 0 ) {
|
||||
break;
|
||||
}
|
||||
SDL_Delay(1);
|
||||
} while ( SDL_GetTicks() < timeout );
|
||||
/* Ack! We have to busy wait... */
|
||||
/* FIXME: Use sem_timedwait()? */
|
||||
timeout += SDL_GetTicks();
|
||||
do {
|
||||
retval = SDL_SemTryWait(sem);
|
||||
if (retval == 0) {
|
||||
break;
|
||||
}
|
||||
SDL_Delay(1);
|
||||
}
|
||||
while (SDL_GetTicks() < timeout);
|
||||
|
||||
return retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
Uint32 SDL_SemValue(SDL_sem *sem)
|
||||
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 ret = 0;
|
||||
if (sem) {
|
||||
sem_getvalue(&sem->sem, &ret);
|
||||
if (ret < 0) {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
return (Uint32) ret;
|
||||
}
|
||||
|
||||
int SDL_SemPost(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemPost(SDL_sem * sem)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
retval = sem_post(&sem->sem);
|
||||
if (retval < 0) {
|
||||
SDL_SetError("sem_post() failed");
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
#endif /* __MACOSX__ */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -30,91 +30,99 @@
|
||||
|
||||
/* List of signals to mask in the subthreads */
|
||||
static int sig_list[] = {
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH,
|
||||
SIGVTALRM, SIGPROF, 0
|
||||
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 */
|
||||
Uint32 riscos_main_thread = 0; /* Thread running events */
|
||||
#endif
|
||||
|
||||
|
||||
static void *RunThread(void *data)
|
||||
|
||||
static void *
|
||||
RunThread(void *data)
|
||||
{
|
||||
SDL_RunThread(data);
|
||||
pthread_exit((void*)0);
|
||||
return((void *)0); /* Prevent compiler warning */
|
||||
SDL_RunThread(data);
|
||||
pthread_exit((void *) 0);
|
||||
return ((void *) 0); /* Prevent compiler warning */
|
||||
}
|
||||
|
||||
int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
|
||||
int
|
||||
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
|
||||
{
|
||||
pthread_attr_t type;
|
||||
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);
|
||||
}
|
||||
/* 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();
|
||||
}
|
||||
if (riscos_using_threads == 0) {
|
||||
riscos_using_threads = 1;
|
||||
riscos_main_thread = SDL_ThreadID();
|
||||
}
|
||||
#endif
|
||||
|
||||
return(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void SDL_SYS_SetupThread(void)
|
||||
void
|
||||
SDL_SYS_SetupThread(void)
|
||||
{
|
||||
int i;
|
||||
sigset_t mask;
|
||||
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);
|
||||
/* 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);
|
||||
}
|
||||
/* 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)
|
||||
Uint32
|
||||
SDL_ThreadID(void)
|
||||
{
|
||||
return((Uint32)pthread_self());
|
||||
return ((Uint32) pthread_self());
|
||||
}
|
||||
|
||||
void SDL_SYS_WaitThread(SDL_Thread *thread)
|
||||
void
|
||||
SDL_SYS_WaitThread(SDL_Thread * thread)
|
||||
{
|
||||
pthread_join(thread->handle, 0);
|
||||
pthread_join(thread->handle, 0);
|
||||
}
|
||||
|
||||
void SDL_SYS_KillThread(SDL_Thread *thread)
|
||||
void
|
||||
SDL_SYS_KillThread(SDL_Thread * thread)
|
||||
{
|
||||
#ifdef PTHREAD_CANCEL_ASYNCHRONOUS
|
||||
pthread_cancel(thread->handle);
|
||||
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);
|
||||
pthread_kill(thread->handle, SIGKILL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -24,3 +24,4 @@
|
||||
#include <pthread.h>
|
||||
|
||||
typedef pthread_t SYS_ThreadHandle;
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -35,126 +35,133 @@
|
||||
|
||||
struct SDL_cond
|
||||
{
|
||||
pthread_cond_t cond;
|
||||
pthread_cond_t cond;
|
||||
};
|
||||
|
||||
/* Create a condition variable */
|
||||
SDL_cond * SDL_CreateCond(void)
|
||||
SDL_cond *
|
||||
SDL_CreateCond(void)
|
||||
{
|
||||
SDL_cond *cond;
|
||||
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);
|
||||
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)
|
||||
void
|
||||
SDL_DestroyCond(SDL_cond * cond)
|
||||
{
|
||||
if ( cond ) {
|
||||
pthread_cond_destroy(&cond->cond);
|
||||
SDL_free(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
|
||||
SDL_CondSignal(SDL_cond * cond)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
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
|
||||
SDL_CondBroadcast(SDL_cond * cond)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
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
|
||||
SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
|
||||
{
|
||||
int retval;
|
||||
struct timeval delta;
|
||||
struct timespec abstime;
|
||||
int retval;
|
||||
struct timeval delta;
|
||||
struct timespec abstime;
|
||||
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
if (!cond) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gettimeofday(&delta, NULL);
|
||||
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;
|
||||
}
|
||||
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;
|
||||
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
|
||||
SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! cond ) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
retval = 0;
|
||||
if (pthread_cond_wait(&cond->cond, &mutex->id) != 0) {
|
||||
SDL_SetError("pthread_cond_wait() failed");
|
||||
retval = -1;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -31,123 +31,129 @@
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
struct SDL_mutex {
|
||||
pthread_mutex_t id;
|
||||
struct SDL_mutex
|
||||
{
|
||||
pthread_mutex_t id;
|
||||
#if SDL_THREAD_PTHREAD_NO_RECURSIVE_MUTEX
|
||||
int recursive;
|
||||
pthread_t owner;
|
||||
int recursive;
|
||||
pthread_t owner;
|
||||
#endif
|
||||
};
|
||||
|
||||
SDL_mutex *SDL_CreateMutex (void)
|
||||
SDL_mutex *
|
||||
SDL_CreateMutex(void)
|
||||
{
|
||||
SDL_mutex *mutex;
|
||||
pthread_mutexattr_t attr;
|
||||
SDL_mutex *mutex;
|
||||
pthread_mutexattr_t attr;
|
||||
|
||||
/* Allocate the structure */
|
||||
mutex = (SDL_mutex *)SDL_calloc(1, sizeof(*mutex));
|
||||
if ( mutex ) {
|
||||
pthread_mutexattr_init(&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 */
|
||||
/* No extra attributes necessary */
|
||||
#else
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
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);
|
||||
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)
|
||||
void
|
||||
SDL_DestroyMutex(SDL_mutex * mutex)
|
||||
{
|
||||
if ( mutex ) {
|
||||
pthread_mutex_destroy(&mutex->id);
|
||||
SDL_free(mutex);
|
||||
}
|
||||
if (mutex) {
|
||||
pthread_mutex_destroy(&mutex->id);
|
||||
SDL_free(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/* Lock the mutex */
|
||||
int SDL_mutexP(SDL_mutex *mutex)
|
||||
int
|
||||
SDL_mutexP(SDL_mutex * mutex)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
#if SDL_THREAD_PTHREAD_NO_RECURSIVE_MUTEX
|
||||
pthread_t this_thread;
|
||||
pthread_t this_thread;
|
||||
#endif
|
||||
|
||||
if ( mutex == NULL ) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
if (mutex == NULL) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
if (pthread_mutex_lock(&mutex->id) < 0) {
|
||||
SDL_SetError("pthread_mutex_lock() failed");
|
||||
retval = -1;
|
||||
}
|
||||
#endif
|
||||
return retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
int SDL_mutexV(SDL_mutex *mutex)
|
||||
int
|
||||
SDL_mutexV(SDL_mutex * mutex)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( mutex == NULL ) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
if (mutex == NULL) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
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;
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
if (pthread_mutex_unlock(&mutex->id) < 0) {
|
||||
SDL_SetError("pthread_mutex_unlock() failed");
|
||||
retval = -1;
|
||||
}
|
||||
#endif /* SDL_THREAD_PTHREAD_NO_RECURSIVE_MUTEX */
|
||||
|
||||
return retval;
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -25,10 +25,12 @@
|
||||
#define _SDL_mutex_c_h
|
||||
|
||||
#if !SDL_THREADS_DISABLED
|
||||
struct SDL_mutex {
|
||||
pthread_mutex_t id;
|
||||
struct SDL_mutex
|
||||
{
|
||||
pthread_mutex_t id;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _SDL_mutex_c_h */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -19,9 +19,6 @@
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* RISC OS semiphores based on linux code */
|
||||
@@ -33,171 +30,188 @@
|
||||
|
||||
#if !SDL_THREADS_DISABLED
|
||||
|
||||
SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
|
||||
SDL_sem *
|
||||
SDL_CreateSemaphore(Uint32 initial_value)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return (SDL_sem *)0;
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return (SDL_sem *) 0;
|
||||
}
|
||||
|
||||
void SDL_DestroySemaphore(SDL_sem *sem)
|
||||
void
|
||||
SDL_DestroySemaphore(SDL_sem * sem)
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
int SDL_SemTryWait(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemTryWait(SDL_sem * sem)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
|
||||
int
|
||||
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int SDL_SemWait(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemWait(SDL_sem * sem)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Uint32 SDL_SemValue(SDL_sem *sem)
|
||||
Uint32
|
||||
SDL_SemValue(SDL_sem * sem)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SDL_SemPost(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemPost(SDL_sem * sem)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
|
||||
#include <unistd.h> /* For getpid() */
|
||||
#include <unistd.h> /* For getpid() */
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
struct SDL_semaphore {
|
||||
sem_t *sem;
|
||||
sem_t sem_data;
|
||||
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 *
|
||||
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;
|
||||
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)
|
||||
void
|
||||
SDL_DestroySemaphore(SDL_sem * sem)
|
||||
{
|
||||
if ( sem ) {
|
||||
sem_destroy(sem->sem);
|
||||
SDL_free(sem);
|
||||
}
|
||||
if (sem) {
|
||||
sem_destroy(sem->sem);
|
||||
SDL_free(sem);
|
||||
}
|
||||
}
|
||||
|
||||
int SDL_SemTryWait(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemTryWait(SDL_sem * sem)
|
||||
{
|
||||
int retval;
|
||||
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;
|
||||
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
|
||||
SDL_SemWait(SDL_sem * sem)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
retval = sem_wait(sem->sem);
|
||||
if (retval < 0) {
|
||||
SDL_SetError("sem_wait() failed");
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
|
||||
int
|
||||
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
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);
|
||||
}
|
||||
/* 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 );
|
||||
/* 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;
|
||||
return retval;
|
||||
}
|
||||
|
||||
Uint32 SDL_SemValue(SDL_sem *sem)
|
||||
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 ret = 0;
|
||||
if (sem) {
|
||||
sem_getvalue(sem->sem, &ret);
|
||||
if (ret < 0) {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
return (Uint32) ret;
|
||||
}
|
||||
|
||||
int SDL_SemPost(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemPost(SDL_sem * sem)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
retval = sem_post(sem->sem);
|
||||
if (retval < 0) {
|
||||
SDL_SetError("sem_post() failed");
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
#endif /* !SDL_THREADS_DISABLED */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -28,30 +28,36 @@
|
||||
|
||||
#if SDL_THREADS_DISABLED
|
||||
|
||||
int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
|
||||
int
|
||||
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
|
||||
{
|
||||
SDL_SetError("Threads have not been compiled into this version of the library");
|
||||
return(-1);
|
||||
SDL_SetError
|
||||
("Threads have not been compiled into this version of the library");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
void SDL_SYS_SetupThread(void)
|
||||
void
|
||||
SDL_SYS_SetupThread(void)
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
Uint32 SDL_ThreadID(void)
|
||||
Uint32
|
||||
SDL_ThreadID(void)
|
||||
{
|
||||
return(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void SDL_SYS_WaitThread(SDL_Thread *thread)
|
||||
void
|
||||
SDL_SYS_WaitThread(SDL_Thread * thread)
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
void SDL_SYS_KillThread(SDL_Thread *thread)
|
||||
void
|
||||
SDL_SYS_KillThread(SDL_Thread * thread)
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -60,85 +66,92 @@ void SDL_SYS_KillThread(SDL_Thread *thread)
|
||||
|
||||
/* List of signals to mask in the subthreads */
|
||||
static int sig_list[] = {
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH,
|
||||
SIGVTALRM, SIGPROF, 0
|
||||
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 */
|
||||
Uint32 riscos_main_thread = 0; /* Thread running events */
|
||||
|
||||
static void *RunThread(void *data)
|
||||
static void *
|
||||
RunThread(void *data)
|
||||
{
|
||||
SDL_RunThread(data);
|
||||
pthread_exit((void*)0);
|
||||
return((void *)0); /* Prevent compiler warning */
|
||||
SDL_RunThread(data);
|
||||
pthread_exit((void *) 0);
|
||||
return ((void *) 0); /* Prevent compiler warning */
|
||||
}
|
||||
|
||||
int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
|
||||
int
|
||||
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
|
||||
{
|
||||
pthread_attr_t type;
|
||||
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);
|
||||
/* 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);
|
||||
}
|
||||
/* 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);
|
||||
if (riscos_using_threads == 0) {
|
||||
riscos_using_threads = 1;
|
||||
riscos_main_thread = SDL_ThreadID();
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void SDL_SYS_SetupThread(void)
|
||||
void
|
||||
SDL_SYS_SetupThread(void)
|
||||
{
|
||||
int i;
|
||||
sigset_t mask;
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
/* Allow ourselves to be asynchronously cancelled */
|
||||
{
|
||||
int oldstate;
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32 SDL_ThreadID(void)
|
||||
Uint32
|
||||
SDL_ThreadID(void)
|
||||
{
|
||||
return((Uint32)pthread_self());
|
||||
return ((Uint32) pthread_self());
|
||||
}
|
||||
|
||||
void SDL_SYS_WaitThread(SDL_Thread *thread)
|
||||
void
|
||||
SDL_SYS_WaitThread(SDL_Thread * thread)
|
||||
{
|
||||
pthread_join(thread->handle, 0);
|
||||
pthread_join(thread->handle, 0);
|
||||
}
|
||||
|
||||
void SDL_SYS_KillThread(SDL_Thread *thread)
|
||||
void
|
||||
SDL_SYS_KillThread(SDL_Thread * thread)
|
||||
{
|
||||
#ifdef PTHREAD_CANCEL_ASYNCHRONOUS
|
||||
pthread_cancel(thread->handle);
|
||||
pthread_cancel(thread->handle);
|
||||
#else
|
||||
pthread_kill(thread->handle, SIGKILL);
|
||||
pthread_kill(thread->handle, SIGKILL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -32,3 +32,4 @@ typedef int SYS_ThreadHandle;
|
||||
typedef pthread_t SYS_ThreadHandle;
|
||||
|
||||
#endif
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -29,67 +29,74 @@
|
||||
#include "SDL_mutex.h"
|
||||
|
||||
|
||||
struct SDL_mutex {
|
||||
HANDLE id;
|
||||
struct SDL_mutex
|
||||
{
|
||||
HANDLE id;
|
||||
};
|
||||
|
||||
/* Create a mutex */
|
||||
SDL_mutex *SDL_CreateMutex(void)
|
||||
SDL_mutex *
|
||||
SDL_CreateMutex(void)
|
||||
{
|
||||
SDL_mutex *mutex;
|
||||
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);
|
||||
/* 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)
|
||||
void
|
||||
SDL_DestroyMutex(SDL_mutex * mutex)
|
||||
{
|
||||
if ( mutex ) {
|
||||
if ( mutex->id ) {
|
||||
CloseHandle(mutex->id);
|
||||
mutex->id = 0;
|
||||
}
|
||||
SDL_free(mutex);
|
||||
}
|
||||
if (mutex) {
|
||||
if (mutex->id) {
|
||||
CloseHandle(mutex->id);
|
||||
mutex->id = 0;
|
||||
}
|
||||
SDL_free(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/* Lock the mutex */
|
||||
int SDL_mutexP(SDL_mutex *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);
|
||||
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)
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -32,133 +32,143 @@
|
||||
#endif
|
||||
|
||||
|
||||
struct SDL_semaphore {
|
||||
struct SDL_semaphore
|
||||
{
|
||||
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
|
||||
SYNCHHANDLE id;
|
||||
SYNCHHANDLE id;
|
||||
#else
|
||||
HANDLE id;
|
||||
HANDLE id;
|
||||
#endif
|
||||
Uint32 volatile count;
|
||||
Uint32 volatile count;
|
||||
};
|
||||
|
||||
|
||||
/* Create a semaphore */
|
||||
SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
|
||||
SDL_sem *
|
||||
SDL_CreateSemaphore(Uint32 initial_value)
|
||||
{
|
||||
SDL_sem *sem;
|
||||
SDL_sem *sem;
|
||||
|
||||
/* Allocate sem memory */
|
||||
sem = (SDL_sem *)SDL_malloc(sizeof(*sem));
|
||||
if ( sem ) {
|
||||
/* Create the semaphore, with max value 32K */
|
||||
/* 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);
|
||||
sem->id = CreateSemaphoreCE(NULL, initial_value, 32 * 1024, NULL);
|
||||
#else
|
||||
sem->id = CreateSemaphore(NULL, initial_value, 32*1024, NULL);
|
||||
sem->id = CreateSemaphore(NULL, initial_value, 32 * 1024, NULL);
|
||||
#endif
|
||||
sem->count = initial_value;
|
||||
if ( ! sem->id ) {
|
||||
SDL_SetError("Couldn't create semaphore");
|
||||
SDL_free(sem);
|
||||
sem = NULL;
|
||||
}
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
return(sem);
|
||||
sem->count = 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)
|
||||
void
|
||||
SDL_DestroySemaphore(SDL_sem * sem)
|
||||
{
|
||||
if ( sem ) {
|
||||
if ( sem->id ) {
|
||||
if (sem) {
|
||||
if (sem->id) {
|
||||
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
|
||||
CloseSynchHandle(sem->id);
|
||||
CloseSynchHandle(sem->id);
|
||||
#else
|
||||
CloseHandle(sem->id);
|
||||
CloseHandle(sem->id);
|
||||
#endif
|
||||
sem->id = 0;
|
||||
}
|
||||
SDL_free(sem);
|
||||
}
|
||||
sem->id = 0;
|
||||
}
|
||||
SDL_free(sem);
|
||||
}
|
||||
}
|
||||
|
||||
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
|
||||
int
|
||||
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
|
||||
{
|
||||
int retval;
|
||||
DWORD dwMilliseconds;
|
||||
int retval;
|
||||
DWORD dwMilliseconds;
|
||||
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL sem");
|
||||
return -1;
|
||||
}
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL sem");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( timeout == SDL_MUTEX_MAXWAIT ) {
|
||||
dwMilliseconds = INFINITE;
|
||||
} else {
|
||||
dwMilliseconds = (DWORD)timeout;
|
||||
}
|
||||
if (timeout == SDL_MUTEX_MAXWAIT) {
|
||||
dwMilliseconds = INFINITE;
|
||||
} else {
|
||||
dwMilliseconds = (DWORD) timeout;
|
||||
}
|
||||
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
|
||||
switch (WaitForSemaphoreCE(sem->id, dwMilliseconds)) {
|
||||
switch (WaitForSemaphoreCE(sem->id, dwMilliseconds)) {
|
||||
#else
|
||||
switch (WaitForSingleObject(sem->id, dwMilliseconds)) {
|
||||
switch (WaitForSingleObject(sem->id, dwMilliseconds)) {
|
||||
#endif
|
||||
case WAIT_OBJECT_0:
|
||||
--sem->count;
|
||||
retval = 0;
|
||||
break;
|
||||
case WAIT_TIMEOUT:
|
||||
retval = SDL_MUTEX_TIMEDOUT;
|
||||
break;
|
||||
default:
|
||||
SDL_SetError("WaitForSingleObject() failed");
|
||||
retval = -1;
|
||||
break;
|
||||
}
|
||||
return retval;
|
||||
case WAIT_OBJECT_0:
|
||||
--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)
|
||||
int
|
||||
SDL_SemTryWait(SDL_sem * sem)
|
||||
{
|
||||
return SDL_SemWaitTimeout(sem, 0);
|
||||
return SDL_SemWaitTimeout(sem, 0);
|
||||
}
|
||||
|
||||
int SDL_SemWait(SDL_sem *sem)
|
||||
int
|
||||
SDL_SemWait(SDL_sem * sem)
|
||||
{
|
||||
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
|
||||
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
|
||||
}
|
||||
|
||||
/* Returns the current count of the semaphore */
|
||||
Uint32 SDL_SemValue(SDL_sem *sem)
|
||||
Uint32
|
||||
SDL_SemValue(SDL_sem * sem)
|
||||
{
|
||||
if ( ! sem ) {
|
||||
SDL_SetError("Passed a NULL sem");
|
||||
return 0;
|
||||
}
|
||||
return sem->count;
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL sem");
|
||||
return 0;
|
||||
}
|
||||
return sem->count;
|
||||
}
|
||||
|
||||
int SDL_SemPost(SDL_sem *sem)
|
||||
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.
|
||||
*/
|
||||
++sem->count;
|
||||
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.
|
||||
*/
|
||||
++sem->count;
|
||||
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
|
||||
if ( ReleaseSemaphoreCE(sem->id, 1, NULL) == FALSE ) {
|
||||
if (ReleaseSemaphoreCE(sem->id, 1, NULL) == FALSE) {
|
||||
#else
|
||||
if ( ReleaseSemaphore(sem->id, 1, NULL) == FALSE ) {
|
||||
if (ReleaseSemaphore(sem->id, 1, NULL) == FALSE) {
|
||||
#endif
|
||||
--sem->count; /* restore */
|
||||
SDL_SetError("ReleaseSemaphore() failed");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
--sem->count; /* restore */
|
||||
SDL_SetError("ReleaseSemaphore() failed");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -37,114 +37,141 @@
|
||||
#endif
|
||||
|
||||
#if __GNUC__
|
||||
typedef unsigned long (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned,
|
||||
unsigned (__stdcall *func)(void *), void *arg,
|
||||
unsigned, unsigned *threadID);
|
||||
typedef void (__cdecl *pfnSDL_CurrentEndThread)(unsigned code);
|
||||
typedef unsigned long (__cdecl * pfnSDL_CurrentBeginThread) (void *, unsigned,
|
||||
unsigned
|
||||
(__stdcall *
|
||||
func) (void *),
|
||||
void *arg,
|
||||
unsigned,
|
||||
unsigned
|
||||
*threadID);
|
||||
typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code);
|
||||
#elif 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);
|
||||
typedef unsigned long (__watcall * pfnSDL_CurrentBeginThread) (void *,
|
||||
unsigned,
|
||||
unsigned
|
||||
(__stdcall *
|
||||
func) (void
|
||||
*),
|
||||
void *arg,
|
||||
unsigned,
|
||||
unsigned
|
||||
*threadID);
|
||||
typedef void (__watcall * 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);
|
||||
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;
|
||||
void *args;
|
||||
pfnSDL_CurrentEndThread pfnCurrentEndThread;
|
||||
} tThreadStartParms, *pThreadStartParms;
|
||||
|
||||
static unsigned __stdcall RunThread(void *data)
|
||||
static unsigned __stdcall
|
||||
RunThread(void *data)
|
||||
{
|
||||
pThreadStartParms pThreadParms = (pThreadStartParms)data;
|
||||
pfnSDL_CurrentEndThread pfnCurrentEndThread = NULL;
|
||||
pThreadStartParms pThreadParms = (pThreadStartParms) data;
|
||||
pfnSDL_CurrentEndThread pfnCurrentEndThread = NULL;
|
||||
|
||||
// Call the thread function!
|
||||
SDL_RunThread(pThreadParms->args);
|
||||
// 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);
|
||||
// Get the current endthread we have to use!
|
||||
if (pThreadParms) {
|
||||
pfnCurrentEndThread = pThreadParms->pfnCurrentEndThread;
|
||||
SDL_free(pThreadParms);
|
||||
}
|
||||
// Call endthread!
|
||||
if (pfnCurrentEndThread)
|
||||
(*pfnCurrentEndThread) (0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
|
||||
int SDL_SYS_CreateThread(SDL_Thread *thread, void *args, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread)
|
||||
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)
|
||||
int
|
||||
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
|
||||
{
|
||||
#ifdef _WIN32_WCE
|
||||
pfnSDL_CurrentBeginThread pfnBeginThread = NULL;
|
||||
pfnSDL_CurrentEndThread pfnEndThread = NULL;
|
||||
pfnSDL_CurrentBeginThread pfnBeginThread = NULL;
|
||||
pfnSDL_CurrentEndThread pfnEndThread = NULL;
|
||||
#else
|
||||
pfnSDL_CurrentBeginThread pfnBeginThread = _beginthreadex;
|
||||
pfnSDL_CurrentEndThread pfnEndThread = _endthreadex;
|
||||
pfnSDL_CurrentBeginThread pfnBeginThread = _beginthreadex;
|
||||
pfnSDL_CurrentEndThread pfnEndThread = _endthreadex;
|
||||
#endif
|
||||
#endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */
|
||||
unsigned threadid;
|
||||
pThreadStartParms pThreadParms = (pThreadStartParms)SDL_malloc(sizeof(tThreadStartParms));
|
||||
if (!pThreadParms) {
|
||||
SDL_OutOfMemory();
|
||||
return(-1);
|
||||
}
|
||||
unsigned threadid;
|
||||
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;
|
||||
|
||||
// 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) {
|
||||
thread->handle = (SYS_ThreadHandle) pfnBeginThread(NULL, 0, RunThread,
|
||||
pThreadParms, 0, &threadid);
|
||||
} else {
|
||||
thread->handle = CreateThread(NULL, 0, RunThread, pThreadParms, 0, &threadid);
|
||||
}
|
||||
if (thread->handle == NULL) {
|
||||
SDL_SetError("Not enough resources to create thread");
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
if (pfnBeginThread) {
|
||||
thread->handle =
|
||||
(SYS_ThreadHandle) pfnBeginThread(NULL, 0, RunThread,
|
||||
pThreadParms, 0, &threadid);
|
||||
} else {
|
||||
thread->handle =
|
||||
CreateThread(NULL, 0, RunThread, pThreadParms, 0, &threadid);
|
||||
}
|
||||
if (thread->handle == NULL) {
|
||||
SDL_SetError("Not enough resources to create thread");
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
void SDL_SYS_SetupThread(void)
|
||||
void
|
||||
SDL_SYS_SetupThread(void)
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
Uint32 SDL_ThreadID(void)
|
||||
Uint32
|
||||
SDL_ThreadID(void)
|
||||
{
|
||||
return((Uint32)GetCurrentThreadId());
|
||||
return ((Uint32) GetCurrentThreadId());
|
||||
}
|
||||
|
||||
void SDL_SYS_WaitThread(SDL_Thread *thread)
|
||||
void
|
||||
SDL_SYS_WaitThread(SDL_Thread * thread)
|
||||
{
|
||||
WaitForSingleObject(thread->handle, INFINITE);
|
||||
CloseHandle(thread->handle);
|
||||
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)
|
||||
void
|
||||
SDL_SYS_KillThread(SDL_Thread * thread)
|
||||
{
|
||||
TerminateThread(thread->handle, FALSE);
|
||||
TerminateThread(thread->handle, FALSE);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -25,4 +25,4 @@
|
||||
#include <windows.h>
|
||||
|
||||
typedef HANDLE SYS_ThreadHandle;
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -33,15 +33,13 @@
|
||||
|
||||
#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 )
|
||||
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.
|
||||
@@ -57,160 +55,174 @@ SYNCHHANDLE CreateSemaphoreCE (
|
||||
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;
|
||||
SYNCHHANDLE hSynch = NULL, result = NULL;
|
||||
|
||||
__try
|
||||
{
|
||||
if (lInitialCount > lMaximumCount || lMaximumCount < 0 || lInitialCount < 0)
|
||||
{
|
||||
/* Bad parameters */
|
||||
SetLastError (SYNCH_ERROR);
|
||||
__leave;
|
||||
}
|
||||
__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 =
|
||||
HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SYNCH_HANDLE_SIZE);
|
||||
if (hSynch == NULL)
|
||||
__leave;
|
||||
|
||||
hSynch->MaxCount = lMaximumCount;
|
||||
hSynch->CurCount = lInitialCount;
|
||||
hSynch->lpName = lpName;
|
||||
hSynch->MaxCount = lMaximumCount;
|
||||
hSynch->CurCount = lInitialCount;
|
||||
hSynch->lpName = lpName;
|
||||
|
||||
hSynch->hMutex = CreateMutex (lpSemaphoreAttributes, FALSE, NULL);
|
||||
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. */);
|
||||
}
|
||||
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;
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL ReleaseSemaphoreCE (SYNCHHANDLE hSemCE, LONG cReleaseCount, LPLONG lpPreviousCount)
|
||||
BOOL
|
||||
ReleaseSemaphoreCE(SYNCHHANDLE hSemCE, LONG cReleaseCount,
|
||||
LPLONG lpPreviousCount)
|
||||
/* Windows CE equivalent to ReleaseSemaphore. */
|
||||
{
|
||||
BOOL Result = TRUE;
|
||||
BOOL Result = TRUE;
|
||||
|
||||
/* Gain access to the object to assure that the release count
|
||||
would not cause the total count to exceed the maximum. */
|
||||
/* 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;
|
||||
__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. */
|
||||
/* Set the autoreset event, releasing exactly one waiting thread, now or
|
||||
in the future. */
|
||||
|
||||
SetEvent (hSemCE->hEvent);
|
||||
}
|
||||
__finally
|
||||
{
|
||||
ReleaseMutex (hSemCE->hMutex);
|
||||
}
|
||||
SetEvent(hSemCE->hEvent);
|
||||
}
|
||||
__finally {
|
||||
ReleaseMutex(hSemCE->hMutex);
|
||||
}
|
||||
|
||||
return Result;
|
||||
return Result;
|
||||
}
|
||||
|
||||
DWORD WaitForSemaphoreCE (SYNCHHANDLE hSemCE, DWORD dwMilliseconds)
|
||||
DWORD
|
||||
WaitForSemaphoreCE(SYNCHHANDLE hSemCE, DWORD dwMilliseconds)
|
||||
/* Windows CE semaphore equivalent of WaitForSingleObject. */
|
||||
{
|
||||
DWORD WaitResult;
|
||||
DWORD WaitResult;
|
||||
|
||||
WaitResult = WaitForSingleObject (hSemCE->hMutex, dwMilliseconds);
|
||||
if (WaitResult != WAIT_OBJECT_0 && WaitResult != WAIT_ABANDONED_0) return WaitResult;
|
||||
while (hSemCE->CurCount <= 0)
|
||||
{
|
||||
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. */
|
||||
/* 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);
|
||||
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. */
|
||||
/* 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;
|
||||
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. */
|
||||
/* 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;
|
||||
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. */
|
||||
}
|
||||
/* 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. */
|
||||
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;
|
||||
if (hSemCE->CurCount > 0)
|
||||
SetEvent(hSemCE->hEvent);
|
||||
ReleaseMutex(hSemCE->hMutex);
|
||||
return WaitResult;
|
||||
}
|
||||
|
||||
BOOL CloseSynchHandle (SYNCHHANDLE hSynch)
|
||||
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);
|
||||
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. */
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -1,22 +1,25 @@
|
||||
/* 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;
|
||||
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 */
|
||||
#define SYNCH_ERROR 0X20000000 /* EXERCISE - REFINE THE ERROR NUMBERS */
|
||||
|
||||
extern SYNCHHANDLE CreateSemaphoreCE (LPSECURITY_ATTRIBUTES, LONG, LONG, LPCTSTR);
|
||||
extern SYNCHHANDLE CreateSemaphoreCE(LPSECURITY_ATTRIBUTES, LONG, LONG,
|
||||
LPCTSTR);
|
||||
|
||||
extern BOOL ReleaseSemaphoreCE (SYNCHHANDLE, LONG, LPLONG);
|
||||
extern DWORD WaitForSemaphoreCE (SYNCHHANDLE, DWORD);
|
||||
extern BOOL ReleaseSemaphoreCE(SYNCHHANDLE, LONG, LPLONG);
|
||||
extern DWORD WaitForSemaphoreCE(SYNCHHANDLE, DWORD);
|
||||
|
||||
extern BOOL CloseSynchHandle (SYNCHHANDLE);
|
||||
extern BOOL CloseSynchHandle(SYNCHHANDLE);
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
Reference in New Issue
Block a user