SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.

This commit is contained in:
Sam Lantinga
2006-07-10 21:04:37 +00:00
parent 8f3655506a
commit 6bc598ea61
686 changed files with 117556 additions and 98661 deletions

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -20,4 +20,4 @@
slouken@libsdl.org
*/
#include "SDL_config.h"
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -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: */

View File

@@ -20,4 +20,4 @@
slouken@libsdl.org
*/
#include "SDL_config.h"
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -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: */

View File

@@ -20,4 +20,4 @@
slouken@libsdl.org
*/
#include "SDL_config.h"
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -28,4 +28,4 @@
*/
typedef int SYS_ThreadHandle;
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -20,4 +20,4 @@
slouken@libsdl.org
*/
#include "SDL_config.h"
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -23,3 +23,4 @@
/* Stub until we implement threads on this platform */
typedef int SYS_ThreadHandle;
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -24,4 +24,4 @@
#include <sys/types.h>
typedef pid_t SYS_ThreadHandle;
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -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: */

View File

@@ -20,4 +20,4 @@
slouken@libsdl.org
*/
#include "SDL_config.h"
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -25,4 +25,4 @@
#include <os2.h>
typedef TID SYS_ThreadHandle;
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -29,3 +29,4 @@
typedef pth_t SYS_ThreadHandle;
#endif /* _SDL_SYSTHREAD_C_H_ */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -24,3 +24,4 @@
#include <pthread.h>
typedef pthread_t SYS_ThreadHandle;
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -32,3 +32,4 @@ typedef int SYS_ThreadHandle;
typedef pthread_t SYS_ThreadHandle;
#endif
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -25,4 +25,4 @@
#include <windows.h>
typedef HANDLE SYS_ThreadHandle;
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -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: */

View File

@@ -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: */