diff options
Diffstat (limited to 'src/gallium/include/pipe/p_thread.h')
-rw-r--r-- | src/gallium/include/pipe/p_thread.h | 403 |
1 files changed, 174 insertions, 229 deletions
diff --git a/src/gallium/include/pipe/p_thread.h b/src/gallium/include/pipe/p_thread.h index 6e526b7aa8b..e01d5a602b8 100644 --- a/src/gallium/include/pipe/p_thread.h +++ b/src/gallium/include/pipe/p_thread.h @@ -23,307 +23,252 @@ * **************************************************************************/ + /** - * @file - * Thread - * - * Initial version by John Stone ([email protected]) ([email protected]) - * and Christoph Poliwoda ([email protected]) - * Revised by Keith Whitwell - * Adapted for new gl dispatcher by Brian Paul - * - * - * - * DOCUMENTATION - * - * This thread module exports the following types: - * _glthread_TSD Thread-specific data area - * _glthread_Thread Thread datatype - * _glthread_Mutex Mutual exclusion lock - * - * Macros: - * _glthread_DECLARE_STATIC_MUTEX(name) Declare a non-local mutex - * _glthread_INIT_MUTEX(name) Initialize a mutex - * _glthread_LOCK_MUTEX(name) Lock a mutex - * _glthread_UNLOCK_MUTEX(name) Unlock a mutex - * - * Functions: - * _glthread_GetID(v) Get integer thread ID - * _glthread_InitTSD() Initialize thread-specific data - * _glthread_GetTSD() Get thread-specific data - * _glthread_SetTSD() Set thread-specific data - * - * If this file is accidentally included by a non-threaded build, - * it should not cause the build to fail, or otherwise cause problems. - * In general, it should only be included when needed however. + * Thread, mutex, condition var and thread-specific data functions. */ -#ifndef _P_THREAD_H_ -#define _P_THREAD_H_ +#ifndef _P_THREAD2_H_ +#define _P_THREAD2_H_ -#if (defined(PTHREADS) || defined(SOLARIS_THREADS) ||\ - defined(WIN32_THREADS) || defined(USE_XTHREADS) || defined(BEOS_THREADS)) \ - && !defined(THREADS) -# define THREADS -#endif -#ifdef VMS -#include <GL/vms_x_fix.h> -#endif +#include "pipe/p_compiler.h" + + +#if defined(PIPE_OS_LINUX) -/* - * POSIX threads. This should be your choice in the Unix world - * whenever possible. When building with POSIX threads, be sure - * to enable any compiler flags which will cause the MT-safe - * libc (if one exists) to be used when linking, as well as any - * header macros for MT-safe errno, etc. For Solaris, this is the -mt - * compiler flag. On Solaris with gcc, use -D_REENTRANT to enable - * proper compiling for MT-safe libc etc. - */ -#if defined(PTHREADS) #include <pthread.h> /* POSIX threads headers */ +#include <stdio.h> /* for perror() */ -typedef struct { - pthread_key_t key; - int initMagic; -} _glthread_TSD; +typedef pthread_t pipe_thread; + +#define PIPE_THREAD_ROUTINE( name, param ) \ + void *name( void *param ) -typedef pthread_t _glthread_Thread; +static INLINE pipe_thread pipe_thread_create( void *(* routine)( void *), void *param ) +{ + pipe_thread thread; + if (pthread_create( &thread, NULL, routine, param )) + return 0; + return thread; +} -typedef pthread_mutex_t _glthread_Mutex; +static INLINE int pipe_thread_wait( pipe_thread thread ) +{ + return pthread_join( thread, NULL ); +} -#define _glthread_DECLARE_STATIC_MUTEX(name) \ - static _glthread_Mutex name = PTHREAD_MUTEX_INITIALIZER +static INLINE int pipe_thread_destroy( pipe_thread thread ) +{ + return pthread_detach( thread ); +} -#define _glthread_INIT_MUTEX(name) \ - pthread_mutex_init(&(name), NULL) +typedef pthread_mutex_t pipe_mutex; +typedef pthread_cond_t pipe_condvar; -#define _glthread_DESTROY_MUTEX(name) \ - pthread_mutex_destroy(&(name)) +#define pipe_static_mutex(mutex) \ + static pipe_mutex mutex = PTHREAD_MUTEX_INITIALIZER -#define _glthread_LOCK_MUTEX(name) \ - (void) pthread_mutex_lock(&(name)) +#define pipe_mutex_init(mutex) \ + pthread_mutex_init(&(mutex), NULL) -#define _glthread_UNLOCK_MUTEX(name) \ - (void) pthread_mutex_unlock(&(name)) +#define pipe_mutex_destroy(mutex) \ + pthread_mutex_destroy(&(mutex)) -typedef pthread_cond_t _glthread_Cond; +#define pipe_mutex_lock(mutex) \ + (void) pthread_mutex_lock(&(mutex)) -#define _glthread_DECLARE_STATIC_COND(name) \ - static _glthread_Cond name = PTHREAD_COND_INITIALIZER +#define pipe_mutex_unlock(mutex) \ + (void) pthread_mutex_unlock(&(mutex)) -#define _glthread_INIT_COND(cond) \ +#define pipe_static_condvar(mutex) \ + static pipe_condvar mutex = PTHREAD_COND_INITIALIZER + +#define pipe_condvar_init(cond) \ pthread_cond_init(&(cond), NULL) -#define _glthread_DESTROY_COND(name) \ - pthread_cond_destroy(&(name)) +#define pipe_condvar_destroy(cond) \ + pthread_cond_destroy(&(cond)) -#define _glthread_COND_WAIT(cond, mutex) \ +#define pipe_condvar_wait(cond, mutex) \ pthread_cond_wait(&(cond), &(mutex)) -#define _glthread_COND_SIGNAL(cond) \ +#define pipe_condvar_signal(cond) \ pthread_cond_signal(&(cond)) -#define _glthread_COND_BROADCAST(cond) \ +#define pipe_condvar_broadcast(cond) \ pthread_cond_broadcast(&(cond)) -#endif /* PTHREADS */ - +#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) - -/* - * Solaris threads. Use only up to Solaris 2.4. - * Solaris 2.5 and higher provide POSIX threads. - * Be sure to compile with -mt on the Solaris compilers, or - * use -D_REENTRANT if using gcc. - */ -#ifdef SOLARIS_THREADS -#include <thread.h> - -typedef struct { - thread_key_t key; - mutex_t keylock; - int initMagic; -} _glthread_TSD; - -typedef thread_t _glthread_Thread; - -typedef mutex_t _glthread_Mutex; - -/* XXX need to really implement mutex-related macros */ -#define _glthread_DECLARE_STATIC_MUTEX(name) static _glthread_Mutex name = 0 -#define _glthread_INIT_MUTEX(name) (void) name -#define _glthread_DESTROY_MUTEX(name) (void) name -#define _glthread_LOCK_MUTEX(name) (void) name -#define _glthread_UNLOCK_MUTEX(name) (void) name - -#endif /* SOLARIS_THREADS */ - - - - -/* - * Windows threads. Should work with Windows NT and 95. - * IMPORTANT: Link with multithreaded runtime library when THREADS are - * used! - */ -#ifdef WIN32_THREADS #include <windows.h> -typedef struct { - DWORD key; - int initMagic; -} _glthread_TSD; +typedef HANDLE pipe_thread; -typedef HANDLE _glthread_Thread; +#define PIPE_THREAD_ROUTINE( name, param ) \ + void * WINAPI name( void *param ) -typedef CRITICAL_SECTION _glthread_Mutex; +static INLINE pipe_thread pipe_thread_create( void *(WINAPI * routine)( void *), void *param ) +{ + DWORD id; + return CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE) routine, param, 0, &id ); +} -#define _glthread_DECLARE_STATIC_MUTEX(name) /*static*/ _glthread_Mutex name = {0,0,0,0,0,0} -#define _glthread_INIT_MUTEX(name) InitializeCriticalSection(&name) -#define _glthread_DESTROY_MUTEX(name) DeleteCriticalSection(&name) -#define _glthread_LOCK_MUTEX(name) EnterCriticalSection(&name) -#define _glthread_UNLOCK_MUTEX(name) LeaveCriticalSection(&name) +static INLINE int pipe_thread_wait( pipe_thread thread ) +{ + if (WaitForSingleObject( thread, INFINITE ) == WAIT_OBJECT_0) + return 0; + return -1; +} -#endif /* WIN32_THREADS */ +static INLINE int pipe_thread_destroy( pipe_thread thread ) +{ + if (CloseHandle( thread )) + return 0; + return -1; +} +typedef CRITICAL_SECTION pipe_mutex; +#define pipe_static_mutex(name) \ + /*static*/ pipe_mutex name = {0,0,0,0,0,0} +#define pipe_mutex_init(name) \ + InitializeCriticalSection(&name) -/* - * XFree86 has its own thread wrapper, Xthreads.h - * We wrap it again for GL. - */ -#ifdef USE_XTHREADS -#include <X11/Xthreads.h> +#define pipe_mutex_destroy(name) \ + DeleteCriticalSection(&name) -typedef struct { - xthread_key_t key; - int initMagic; -} _glthread_TSD; - -typedef xthread_t _glthread_Thread; - -typedef xmutex_rec _glthread_Mutex; - -#ifdef XMUTEX_INITIALIZER -#define _glthread_DECLARE_STATIC_MUTEX(name) \ - static _glthread_Mutex name = XMUTEX_INITIALIZER -#else -#define _glthread_DECLARE_STATIC_MUTEX(name) \ - static _glthread_Mutex name -#endif - -#define _glthread_INIT_MUTEX(name) \ - xmutex_init(&(name)) - -#define _glthread_DESTROY_MUTEX(name) \ - xmutex_clear(&(name)) - -#define _glthread_LOCK_MUTEX(name) \ - (void) xmutex_lock(&(name)) - -#define _glthread_UNLOCK_MUTEX(name) \ - (void) xmutex_unlock(&(name)) - -#endif /* USE_XTHREADS */ - - - -/* - * BeOS threads. R5.x required. - */ -#ifdef BEOS_THREADS - -#include <kernel/OS.h> -#include <support/TLS.h> - -typedef struct { - int32 key; - int initMagic; -} _glthread_TSD; - -typedef thread_id _glthread_Thread; - -/* Use Benaphore, aka speeder semaphore */ -typedef struct { - int32 lock; - sem_id sem; -} benaphore; -typedef benaphore _glthread_Mutex; - -#define _glthread_DECLARE_STATIC_MUTEX(name) static _glthread_Mutex name = { 0, 0 } -#define _glthread_INIT_MUTEX(name) name.sem = create_sem(0, #name"_benaphore"), name.lock = 0 -#define _glthread_DESTROY_MUTEX(name) delete_sem(name.sem), name.lock = 0 -#define _glthread_LOCK_MUTEX(name) if (name.sem == 0) _glthread_INIT_MUTEX(name); \ - if (atomic_add(&(name.lock), 1) >= 1) acquire_sem(name.sem) -#define _glthread_UNLOCK_MUTEX(name) if (atomic_add(&(name.lock), -1) > 1) release_sem(name.sem) +#define pipe_mutex_lock(name) \ + EnterCriticalSection(&name) -#endif /* BEOS_THREADS */ +#define pipe_mutex_unlock(name) \ + LeaveCriticalSection(&name) +/* XXX: dummy definitions, make it compile */ +typedef unsigned pipe_condvar; -#ifndef THREADS +#define pipe_condvar_init(condvar) \ + (void) condvar -/* - * THREADS not defined - */ +#define pipe_condvar_broadcast(condvar) \ + (void) condvar -typedef unsigned _glthread_TSD; +#else -typedef unsigned _glthread_Thread; +/** Dummy definitions */ -typedef unsigned _glthread_Mutex; +typedef unsigned pipe_thread; +typedef unsigned pipe_mutex; +typedef unsigned pipe_condvar; -#define _glthread_DECLARE_STATIC_MUTEX(name) static _glthread_Mutex name = 0 +#define pipe_static_mutex(mutex) \ + static pipe_mutex mutex = 0 -#define _glthread_INIT_MUTEX(name) (void) name +#define pipe_mutex_init(mutex) \ + (void) mutex -#define _glthread_DESTROY_MUTEX(name) (void) name +#define pipe_mutex_destroy(mutex) \ + (void) mutex -#define _glthread_LOCK_MUTEX(name) (void) name +#define pipe_mutex_lock(mutex) \ + (void) mutex -#define _glthread_UNLOCK_MUTEX(name) (void) name +#define pipe_mutex_unlock(mutex) \ + (void) mutex -typedef unsigned _glthread_Cond; +#define pipe_static_condvar(condvar) \ + static unsigned condvar = 0 -#define _glthread_DECLARE_STATIC_COND(name) static _glthread_Cond name = 0 +#define pipe_condvar_init(condvar) \ + (void) condvar -#define _glthread_INIT_COND(name) (void) name +#define pipe_condvar_destroy(condvar) \ + (void) condvar -#define _glthread_DESTROY_COND(name) (void) name +#define pipe_condvar_wait(condvar, mutex) \ + (void) condvar -#define _glthread_COND_WAIT(name, mutex) (void) name +#define pipe_condvar_signal(condvar) \ + (void) condvar -#define _glthread_COND_SIGNAL(name) (void) name +#define pipe_condvar_broadcast(condvar) \ + (void) condvar -#define _glthread_COND_BROADCAST(name) (void) name -#endif /* THREADS */ +#endif /* PIPE_OS_? */ /* - * Platform independent thread specific data API. + * Thread-specific data. */ -extern unsigned long -_glthread_GetID(void); - - -extern void -_glthread_InitTSD(_glthread_TSD *); +typedef struct { +#if defined(PIPE_OS_LINUX) + pthread_key_t key; +#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) + DWORD key; +#endif + int initMagic; +} pipe_tsd; -extern void * -_glthread_GetTSD(_glthread_TSD *); +#define PIPE_TSD_INIT_MAGIC 0xff8adc98 -extern void -_glthread_SetTSD(_glthread_TSD *, void *); +static INLINE void +pipe_tsd_init(pipe_tsd *tsd) +{ +#if defined(PIPE_OS_LINUX) + if (pthread_key_create(&tsd->key, NULL/*free*/) != 0) { + perror("pthread_key_create(): failed to allocate key for thread specific data"); + exit(-1); + } +#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) + assert(0); +#endif + tsd->initMagic = PIPE_TSD_INIT_MAGIC; +} + +static INLINE void * +pipe_tsd_get(pipe_tsd *tsd) +{ + if (tsd->initMagic != (int) PIPE_TSD_INIT_MAGIC) { + pipe_tsd_init(tsd); + } +#if defined(PIPE_OS_LINUX) + return pthread_getspecific(tsd->key); +#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) + assert(0); + return NULL; +#else + assert(0); + return NULL; +#endif +} + +static INLINE void +pipe_tsd_set(pipe_tsd *tsd, void *value) +{ + if (tsd->initMagic != (int) PIPE_TSD_INIT_MAGIC) { + pipe_tsd_init(tsd); + } +#if defined(PIPE_OS_LINUX) + if (pthread_setspecific(tsd->key, value) != 0) { + perror("pthread_set_specific() failed"); + exit(-1); + } +#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) + assert(0); +#else + assert(0); +#endif +} -#endif /* _P_THREAD_H_ */ +#endif /* _P_THREAD2_H_ */ |