From b6b7baa0952658963ea7c57a89e943ba0a17fceb Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 1 Apr 2002 15:35:28 +0000 Subject: [PATCH] Patrice's fixes for GNU Pthread support --- configure.in | 15 ++-- src/thread/SDL_thread.c | 10 +++ src/thread/pth/SDL_syscond.c | 140 +++++++++++++++++++++++++++++++ src/thread/pth/SDL_syscond_c.h | 9 ++ src/thread/pth/SDL_sysmutex.c | 67 +++++++++++++++ src/thread/pth/SDL_sysmutex_c.h | 8 ++ src/thread/pth/SDL_systhread.c | 18 ++-- src/thread/pth/SDL_systhread_c.h | 5 ++ 8 files changed, 259 insertions(+), 13 deletions(-) create mode 100644 src/thread/pth/SDL_syscond.c create mode 100644 src/thread/pth/SDL_syscond_c.h create mode 100644 src/thread/pth/SDL_sysmutex.c create mode 100644 src/thread/pth/SDL_sysmutex_c.h diff --git a/configure.in b/configure.in index ebd140e26..fe0d0e702 100644 --- a/configure.in +++ b/configure.in @@ -1265,6 +1265,7 @@ CheckPTH() PTH_LIBS=`$PTH_CONFIG --libs --all` SDL_CFLAGS="$SDL_CFLAGS $PTH_CFLAGS" SDL_LIBS="$SDL_LIBS $PTH_LIBS" + CFLAGS="$CFLAGS -DENABLE_PTH" use_pth=yes fi AC_MSG_CHECKING(pth) @@ -2295,16 +2296,20 @@ case "$target" in if test x$enable_pth = xyes; then COPY_ARCH_SRC(src/thread, pth, SDL_systhread.c) COPY_ARCH_SRC(src/thread, pth, SDL_systhread_c.h) + COPY_ARCH_SRC(src/thread, pth, SDL_sysmutex.c) + COPY_ARCH_SRC(src/thread, pth, SDL_sysmutex_c.h) + COPY_ARCH_SRC(src/thread, pth, SDL_syscond.c) + COPY_ARCH_SRC(src/thread, pth, SDL_syscond_c.h) else COPY_ARCH_SRC(src/thread, generic, SDL_systhread.c) COPY_ARCH_SRC(src/thread, generic, SDL_systhread_c.h) + COPY_ARCH_SRC(src/thread, generic, SDL_sysmutex.c) + COPY_ARCH_SRC(src/thread, generic, SDL_sysmutex_c.h) + COPY_ARCH_SRC(src/thread, generic, SDL_syscond.c) + COPY_ARCH_SRC(src/thread, generic, SDL_syscond_c.h) fi - COPY_ARCH_SRC(src/thread, generic, SDL_sysmutex.c) - COPY_ARCH_SRC(src/thread, generic, SDL_sysmutex_c.h) - COPY_ARCH_SRC(src/thread, linux, SDL_syssem.c) + COPY_ARCH_SRC(src/thread, generic, SDL_syssem.c) COPY_ARCH_SRC(src/thread, generic, SDL_syssem_c.h) - COPY_ARCH_SRC(src/thread, generic, SDL_syscond.c) - COPY_ARCH_SRC(src/thread, generic, SDL_syscond_c.h) fi # Set up files for the timer library if test x$enable_timers = xyes; then diff --git a/src/thread/SDL_thread.c b/src/thread/SDL_thread.c index 0e591343e..645d48e07 100644 --- a/src/thread/SDL_thread.c +++ b/src/thread/SDL_thread.c @@ -52,6 +52,12 @@ int SDL_ThreadsInit(void) { int retval; +#ifdef ENABLE_PTH + if (!pth_init()) { + return -1; + } +#endif + retval = 0; /* Set the thread lock creation flag so that we can reuse an existing lock on the system - since this mutex never gets @@ -80,6 +86,10 @@ void SDL_ThreadsQuit() if ( mutex != NULL ) { SDL_DestroyMutex(mutex); } + +#ifdef ENABLE_PTH + pth_kill(); +#endif } /* Routines for manipulating the thread list */ diff --git a/src/thread/pth/SDL_syscond.c b/src/thread/pth/SDL_syscond.c new file mode 100644 index 000000000..a45ca0206 --- /dev/null +++ b/src/thread/pth/SDL_syscond.c @@ -0,0 +1,140 @@ +/* + * GNU pth conditions variables + * + * Patrice Mandin + */ + +#include +#include +#include + +#include "SDL_error.h" +#include "SDL_thread.h" +#include "SDL_syscond_c.h" +#include "SDL_sysmutex_c.h" + +/* Create a condition variable */ +SDL_cond * SDL_CreateCond(void) +{ + SDL_cond *cond; + + cond = (SDL_cond *) malloc(sizeof(SDL_cond)); + if ( cond ) { + if ( pth_cond_init(&(cond->condpth_p)) < 0 ) { + SDL_SetError("pthread_cond_init() failed"); + free(cond); + cond = NULL; + } + } else { + SDL_OutOfMemory(); + } + return(cond); +} + +/* Destroy a condition variable */ +void SDL_DestroyCond(SDL_cond *cond) +{ + if ( cond ) { + free(cond); + } +} + +/* Restart one of the threads that are waiting on the condition variable */ +int SDL_CondSignal(SDL_cond *cond) +{ + int retval; + + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + retval = 0; + if ( pth_cond_notify(&(cond->condpth_p), FALSE) != 0 ) { + SDL_SetError("pth_cond_notify() failed"); + retval = -1; + } + return retval; +} + +/* Restart all threads that are waiting on the condition variable */ +int SDL_CondBroadcast(SDL_cond *cond) +{ + int retval; + + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + retval = 0; + if ( pth_cond_notify(&(cond->condpth_p), TRUE) != 0 ) { + SDL_SetError("pth_cond_notify() failed"); + retval = -1; + } + return retval; +} + +/* Wait on the condition variable for at most 'ms' milliseconds. + The mutex must be locked before entering this function! + The mutex is unlocked during the wait, and locked again after the wait. + +Typical use: + +Thread A: + SDL_LockMutex(lock); + while ( ! condition ) { + SDL_CondWait(cond); + } + SDL_UnlockMutex(lock); + +Thread B: + SDL_LockMutex(lock); + ... + condition = true; + ... + SDL_UnlockMutex(lock); + */ +int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) +{ + int retval; + pth_event_t ev; + int sec; + + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + retval = 0; + + sec = ms/1000; + ev = pth_event(PTH_EVENT_TIME, pth_timeout(sec,(ms-sec*1000)*1000)); + + if ( pth_cond_await(&(cond->condpth_p), &(mutex->mutexpth_p), ev) != 0 ) { + SDL_SetError("pth_cond_await() failed"); + retval = -1; + } + + pth_event_free(ev, PTH_FREE_ALL); + + return retval; +} + +/* Wait on the condition variable forever */ +int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex) +{ + int retval; + + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + retval = 0; + if ( pth_cond_await(&(cond->condpth_p), &(mutex->mutexpth_p), NULL) != 0 ) { + SDL_SetError("pth_cond_await() failed"); + retval = -1; + } + return retval; +} diff --git a/src/thread/pth/SDL_syscond_c.h b/src/thread/pth/SDL_syscond_c.h new file mode 100644 index 000000000..30ed5c5de --- /dev/null +++ b/src/thread/pth/SDL_syscond_c.h @@ -0,0 +1,9 @@ +#ifndef _SDL_SYSCOND_C_H_ +#define _SDL_SYSCOND_C_H_ + +struct SDL_cond +{ + pth_cond_t condpth_p; +}; + +#endif /* _SDL_SYSCOND_C_H_ */ diff --git a/src/thread/pth/SDL_sysmutex.c b/src/thread/pth/SDL_sysmutex.c new file mode 100644 index 000000000..7a56da4cd --- /dev/null +++ b/src/thread/pth/SDL_sysmutex.c @@ -0,0 +1,67 @@ +/* + * GNU pth mutexes + * + * Patrice Mandin + */ + +#include +#include +#include + +#include "SDL_error.h" +#include "SDL_mutex.h" +#include "SDL_sysmutex_c.h" + +/* Create a mutex */ +SDL_mutex *SDL_CreateMutex(void) +{ + SDL_mutex *mutex; + + /* Allocate mutex memory */ + mutex = (SDL_mutex *)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"); + free(mutex); + mutex = NULL; + } + } else { + SDL_OutOfMemory(); + } + return(mutex); +} + +/* Free the mutex */ +void SDL_DestroyMutex(SDL_mutex *mutex) +{ + if ( mutex ) { + free(mutex); + } +} + +/* Lock the mutex */ +int SDL_mutexP(SDL_mutex *mutex) +{ + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + pth_mutex_acquire(&(mutex->mutexpth_p), FALSE, NULL); + + return(0); +} + +/* Unlock the mutex */ +int SDL_mutexV(SDL_mutex *mutex) +{ + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + pth_mutex_release(&(mutex->mutexpth_p)); + + return(0); +} diff --git a/src/thread/pth/SDL_sysmutex_c.h b/src/thread/pth/SDL_sysmutex_c.h new file mode 100644 index 000000000..4a9bf2bc6 --- /dev/null +++ b/src/thread/pth/SDL_sysmutex_c.h @@ -0,0 +1,8 @@ +#ifndef _SDL_SYSMUTEX_C_H_ +#define _SDL_SYSMUTEX_C_H_ + +struct SDL_mutex { + pth_mutex_t mutexpth_p; +}; + +#endif /* _SDL_SYSMUTEX_C_H_ */ diff --git a/src/thread/pth/SDL_systhread.c b/src/thread/pth/SDL_systhread.c index cb16ce1c3..70c25f539 100644 --- a/src/thread/pth/SDL_systhread.c +++ b/src/thread/pth/SDL_systhread.c @@ -25,7 +25,11 @@ static char rcsid = "@(#) $Id$"; #endif -/* Pth thread management routines for SDL */ +/* + * GNU pth threads + * + * Patrice Mandin + */ #include "SDL_error.h" #include "SDL_thread.h" @@ -51,17 +55,16 @@ int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) { pth_attr_t type; + /* Create a new attribute */ type = pth_attr_new(); - - /* Set the thread attributes */ - if ( pth_attr_init(type) != 0 ) { + 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! */ - if ( pth_spawn(type, RunThread, args) != 0 ) { + if ( pth_spawn(type, RunThread, args) == NULL ) { SDL_SetError("Not enough resources to create thread"); return(-1); } @@ -72,6 +75,7 @@ void SDL_SYS_SetupThread(void) { int i; sigset_t mask; + int oldstate; /* Mask asynchronous signals for this thread */ sigemptyset(&mask); @@ -81,9 +85,7 @@ void SDL_SYS_SetupThread(void) pth_sigmask(SIG_BLOCK, &mask, 0); /* Allow ourselves to be asynchronously cancelled */ - { int oldstate; - pth_cancel_state(PTH_CANCEL_ASYNCHRONOUS, &oldstate); - } + pth_cancel_state(PTH_CANCEL_ASYNCHRONOUS, &oldstate); } /* WARNING: This may not work for systems with 64-bit pid_t */ diff --git a/src/thread/pth/SDL_systhread_c.h b/src/thread/pth/SDL_systhread_c.h index 0a7f0917d..b79062a8d 100644 --- a/src/thread/pth/SDL_systhread_c.h +++ b/src/thread/pth/SDL_systhread_c.h @@ -20,6 +20,11 @@ slouken@libsdl.org */ +#ifndef _SDL_SYSTHREAD_C_H_ +#define _SDL_SYSTHREAD_C_H_ + #include typedef pth_t SYS_ThreadHandle; + +#endif /* _SDL_SYSTHREAD_C_H_ */