X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fauxiliary%2Fos%2Fos_thread.h;h=8f1245bff550d6b2a8420ab9e9fb2f6c6d52d621;hb=c3b2230b71cb3a00a7f4c0987197d397bada650b;hp=63108605d3aa0167183220be4df31525db2a087a;hpb=45dac0d82a5a69166e86dce77c2550f7512c541e;p=mesa.git diff --git a/src/gallium/auxiliary/os/os_thread.h b/src/gallium/auxiliary/os/os_thread.h index 63108605d3a..8f1245bff55 100644 --- a/src/gallium/auxiliary/os/os_thread.h +++ b/src/gallium/auxiliary/os/os_thread.h @@ -27,7 +27,8 @@ /** * @file * - * Thread, mutex, condition var and thread-specific data functions. + * Thread, mutex, condition variable, barrier, semaphore and + * thread-specific data functions. */ @@ -39,13 +40,14 @@ #include "util/u_debug.h" /* for assert */ -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) || defined(PIPE_OS_CYGWIN) #include /* POSIX threads headers */ #include /* for perror() */ -#define PIPE_THREAD_HAVE_CONDVAR +/* pipe_thread + */ typedef pthread_t pipe_thread; #define PIPE_THREAD_ROUTINE( name, param ) \ @@ -54,7 +56,14 @@ typedef pthread_t pipe_thread; static INLINE pipe_thread pipe_thread_create( void *(* routine)( void *), void *param ) { pipe_thread thread; - if (pthread_create( &thread, NULL, routine, param )) + sigset_t saved_set, new_set; + int ret; + + sigfillset(&new_set); + pthread_sigmask(SIG_SETMASK, &new_set, &saved_set); + ret = pthread_create( &thread, NULL, routine, param ); + pthread_sigmask(SIG_SETMASK, &saved_set, NULL); + if (ret) return 0; return thread; } @@ -69,8 +78,10 @@ static INLINE int pipe_thread_destroy( pipe_thread thread ) return pthread_detach( thread ); } + +/* pipe_mutex + */ typedef pthread_mutex_t pipe_mutex; -typedef pthread_cond_t pipe_condvar; #define pipe_static_mutex(mutex) \ static pipe_mutex mutex = PTHREAD_MUTEX_INITIALIZER @@ -87,6 +98,11 @@ typedef pthread_cond_t pipe_condvar; #define pipe_mutex_unlock(mutex) \ (void) pthread_mutex_unlock(&(mutex)) + +/* pipe_condvar + */ +typedef pthread_cond_t pipe_condvar; + #define pipe_static_condvar(mutex) \ static pipe_condvar mutex = PTHREAD_COND_INITIALIZER @@ -106,10 +122,13 @@ typedef pthread_cond_t pipe_condvar; pthread_cond_broadcast(&(cond)) + #elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) #include +/* pipe_thread + */ typedef HANDLE pipe_thread; #define PIPE_THREAD_ROUTINE( name, param ) \ @@ -135,10 +154,14 @@ static INLINE int pipe_thread_destroy( pipe_thread thread ) return -1; } + +/* pipe_mutex + */ typedef CRITICAL_SECTION pipe_mutex; +/* http://locklessinc.com/articles/pthreads_on_windows/ */ #define pipe_static_mutex(mutex) \ - /*static*/ pipe_mutex mutex = {0,0,0,0,0,0} + static pipe_mutex mutex = {(PCRITICAL_SECTION_DEBUG)-1, -1, 0, 0, 0, 0} #define pipe_mutex_init(mutex) \ InitializeCriticalSection(&mutex) @@ -152,23 +175,95 @@ typedef CRITICAL_SECTION pipe_mutex; #define pipe_mutex_unlock(mutex) \ LeaveCriticalSection(&mutex) -/* XXX: dummy definitions, make it compile */ +/* TODO: Need a macro to declare "I don't care about WinXP compatibilty" */ +#if 0 && defined (_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600) +/* CONDITION_VARIABLE is only available on newer versions of Windows + * (Server 2008/Vista or later). + * http://msdn.microsoft.com/en-us/library/ms682052(VS.85).aspx + * + * pipe_condvar + */ +typedef CONDITION_VARIABLE pipe_condvar; -typedef unsigned pipe_condvar; +#define pipe_static_condvar(cond) \ + /*static*/ pipe_condvar cond = CONDITION_VARIABLE_INIT -#define pipe_condvar_init(condvar) \ - (void) condvar +#define pipe_condvar_init(cond) \ + InitializeConditionVariable(&(cond)) -#define pipe_condvar_broadcast(condvar) \ - (void) condvar +#define pipe_condvar_destroy(cond) \ + (void) cond /* nothing to do */ + +#define pipe_condvar_wait(cond, mutex) \ + SleepConditionVariableCS(&(cond), &(mutex), INFINITE) + +#define pipe_condvar_signal(cond) \ + WakeConditionVariable(&(cond)) + +#define pipe_condvar_broadcast(cond) \ + WakeAllConditionVariable(&(cond)) + +#else /* need compatibility with pre-Vista Win32 */ + +/* pipe_condvar (XXX FIX THIS) + * See http://www.cs.wustl.edu/~schmidt/win32-cv-1.html + * for potential pitfalls in implementation. + */ +typedef DWORD pipe_condvar; + +#define pipe_static_condvar(cond) \ + /*static*/ pipe_condvar cond = 1 + +#define pipe_condvar_init(cond) \ + (void) (cond = 1) + +#define pipe_condvar_destroy(cond) \ + (void) cond + +/* Poor man's pthread_cond_wait(): + Just release the mutex and sleep for one millisecond. + The caller's while() loop does all the work. */ +#define pipe_condvar_wait(cond, mutex) \ + do { pipe_mutex_unlock(mutex); \ + Sleep(cond); \ + pipe_mutex_lock(mutex); \ + } while (0) + +#define pipe_condvar_signal(cond) \ + (void) cond + +#define pipe_condvar_broadcast(cond) \ + (void) cond + +#endif /* pre-Vista win32 */ #else +#include "os/os_time.h" + /** Dummy definitions */ typedef unsigned pipe_thread; + +#define PIPE_THREAD_ROUTINE( name, param ) \ + void * name( void *param ) + +static INLINE pipe_thread pipe_thread_create( void *(* routine)( void *), void *param ) +{ + return 0; +} + +static INLINE int pipe_thread_wait( pipe_thread thread ) +{ + return -1; +} + +static INLINE int pipe_thread_destroy( pipe_thread thread ) +{ + return -1; +} + typedef unsigned pipe_mutex; -typedef unsigned pipe_condvar; #define pipe_static_mutex(mutex) \ static pipe_mutex mutex = 0 @@ -185,17 +280,25 @@ typedef unsigned pipe_condvar; #define pipe_mutex_unlock(mutex) \ (void) mutex +typedef int64_t pipe_condvar; + #define pipe_static_condvar(condvar) \ - static unsigned condvar = 0 + static pipe_condvar condvar = 1000 #define pipe_condvar_init(condvar) \ - (void) condvar + (void) (condvar = 1000) #define pipe_condvar_destroy(condvar) \ (void) condvar +/* Poor man's pthread_cond_wait(): + Just release the mutex and sleep for one millisecond. + The caller's while() loop does all the work. */ #define pipe_condvar_wait(condvar, mutex) \ - (void) condvar + do { pipe_mutex_unlock(mutex); \ + os_time_sleep(condvar); \ + pipe_mutex_lock(mutex); \ + } while (0) #define pipe_condvar_signal(condvar) \ (void) condvar @@ -207,13 +310,139 @@ typedef unsigned pipe_condvar; #endif /* PIPE_OS_? */ +/* + * pipe_barrier + */ + +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_HAIKU) + +typedef pthread_barrier_t pipe_barrier; + +static INLINE void pipe_barrier_init(pipe_barrier *barrier, unsigned count) +{ + pthread_barrier_init(barrier, NULL, count); +} + +static INLINE void pipe_barrier_destroy(pipe_barrier *barrier) +{ + pthread_barrier_destroy(barrier); +} + +static INLINE void pipe_barrier_wait(pipe_barrier *barrier) +{ + pthread_barrier_wait(barrier); +} + + +#else /* If the OS doesn't have its own, implement barriers using a mutex and a condvar */ + +typedef struct { + unsigned count; + unsigned waiters; + uint64_t sequence; + pipe_mutex mutex; + pipe_condvar condvar; +} pipe_barrier; + +static INLINE void pipe_barrier_init(pipe_barrier *barrier, unsigned count) +{ + barrier->count = count; + barrier->waiters = 0; + barrier->sequence = 0; + pipe_mutex_init(barrier->mutex); + pipe_condvar_init(barrier->condvar); +} + +static INLINE void pipe_barrier_destroy(pipe_barrier *barrier) +{ + assert(barrier->waiters == 0); + pipe_mutex_destroy(barrier->mutex); + pipe_condvar_destroy(barrier->condvar); +} + +static INLINE void pipe_barrier_wait(pipe_barrier *barrier) +{ + pipe_mutex_lock(barrier->mutex); + + assert(barrier->waiters < barrier->count); + barrier->waiters++; + + if (barrier->waiters < barrier->count) { + uint64_t sequence = barrier->sequence; + + do { + pipe_condvar_wait(barrier->condvar, barrier->mutex); + } while (sequence == barrier->sequence); + } else { + barrier->waiters = 0; + barrier->sequence++; + pipe_condvar_broadcast(barrier->condvar); + } + + pipe_mutex_unlock(barrier->mutex); +} + + +#endif + + +/* + * Semaphores + */ + +typedef struct +{ + pipe_mutex mutex; + pipe_condvar cond; + int counter; +} pipe_semaphore; + + +static INLINE void +pipe_semaphore_init(pipe_semaphore *sema, int init_val) +{ + pipe_mutex_init(sema->mutex); + pipe_condvar_init(sema->cond); + sema->counter = init_val; +} + +static INLINE void +pipe_semaphore_destroy(pipe_semaphore *sema) +{ + pipe_mutex_destroy(sema->mutex); + pipe_condvar_destroy(sema->cond); +} + +/** Signal/increment semaphore counter */ +static INLINE void +pipe_semaphore_signal(pipe_semaphore *sema) +{ + pipe_mutex_lock(sema->mutex); + sema->counter++; + pipe_condvar_signal(sema->cond); + pipe_mutex_unlock(sema->mutex); +} + +/** Wait for semaphore counter to be greater than zero */ +static INLINE void +pipe_semaphore_wait(pipe_semaphore *sema) +{ + pipe_mutex_lock(sema->mutex); + while (sema->counter <= 0) { + pipe_condvar_wait(sema->cond, sema->mutex); + } + sema->counter--; + pipe_mutex_unlock(sema->mutex); +} + + /* * Thread-specific data. */ typedef struct { -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) || defined(PIPE_OS_CYGWIN) pthread_key_t key; #elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) DWORD key; @@ -228,7 +457,7 @@ typedef struct { static INLINE void pipe_tsd_init(pipe_tsd *tsd) { -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) || defined(PIPE_OS_CYGWIN) if (pthread_key_create(&tsd->key, NULL/*free*/) != 0) { perror("pthread_key_create(): failed to allocate key for thread specific data"); exit(-1); @@ -245,7 +474,7 @@ pipe_tsd_get(pipe_tsd *tsd) if (tsd->initMagic != (int) PIPE_TSD_INIT_MAGIC) { pipe_tsd_init(tsd); } -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) || defined(PIPE_OS_CYGWIN) return pthread_getspecific(tsd->key); #elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) assert(0); @@ -262,7 +491,7 @@ 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) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) || defined(PIPE_OS_CYGWIN) if (pthread_setspecific(tsd->key, value) != 0) { perror("pthread_set_specific() failed"); exit(-1);