os_thread.h revision cdc920a0
1/************************************************************************** 2 * 3 * Copyright 1999-2006 Brian Paul 4 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 5 * All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 **************************************************************************/ 25 26 27/** 28 * @file 29 * 30 * Thread, mutex, condition variable, barrier, semaphore and 31 * thread-specific data functions. 32 */ 33 34 35#ifndef OS_THREAD_H_ 36#define OS_THREAD_H_ 37 38 39#include "pipe/p_compiler.h" 40#include "util/u_debug.h" /* for assert */ 41 42 43#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) 44 45#include <pthread.h> /* POSIX threads headers */ 46#include <stdio.h> /* for perror() */ 47 48#define PIPE_THREAD_HAVE_CONDVAR 49 50/* pipe_thread 51 */ 52typedef pthread_t pipe_thread; 53 54#define PIPE_THREAD_ROUTINE( name, param ) \ 55 void *name( void *param ) 56 57static INLINE pipe_thread pipe_thread_create( void *(* routine)( void *), void *param ) 58{ 59 pipe_thread thread; 60 if (pthread_create( &thread, NULL, routine, param )) 61 return 0; 62 return thread; 63} 64 65static INLINE int pipe_thread_wait( pipe_thread thread ) 66{ 67 return pthread_join( thread, NULL ); 68} 69 70static INLINE int pipe_thread_destroy( pipe_thread thread ) 71{ 72 return pthread_detach( thread ); 73} 74 75 76/* pipe_mutex 77 */ 78typedef pthread_mutex_t pipe_mutex; 79 80#define pipe_static_mutex(mutex) \ 81 static pipe_mutex mutex = PTHREAD_MUTEX_INITIALIZER 82 83#define pipe_mutex_init(mutex) \ 84 (void) pthread_mutex_init(&(mutex), NULL) 85 86#define pipe_mutex_destroy(mutex) \ 87 pthread_mutex_destroy(&(mutex)) 88 89#define pipe_mutex_lock(mutex) \ 90 (void) pthread_mutex_lock(&(mutex)) 91 92#define pipe_mutex_unlock(mutex) \ 93 (void) pthread_mutex_unlock(&(mutex)) 94 95 96/* pipe_condvar 97 */ 98typedef pthread_cond_t pipe_condvar; 99 100#define pipe_static_condvar(mutex) \ 101 static pipe_condvar mutex = PTHREAD_COND_INITIALIZER 102 103#define pipe_condvar_init(cond) \ 104 pthread_cond_init(&(cond), NULL) 105 106#define pipe_condvar_destroy(cond) \ 107 pthread_cond_destroy(&(cond)) 108 109#define pipe_condvar_wait(cond, mutex) \ 110 pthread_cond_wait(&(cond), &(mutex)) 111 112#define pipe_condvar_signal(cond) \ 113 pthread_cond_signal(&(cond)) 114 115#define pipe_condvar_broadcast(cond) \ 116 pthread_cond_broadcast(&(cond)) 117 118 119 120#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) 121 122#include <windows.h> 123 124/* pipe_thread 125 */ 126typedef HANDLE pipe_thread; 127 128#define PIPE_THREAD_ROUTINE( name, param ) \ 129 void * WINAPI name( void *param ) 130 131static INLINE pipe_thread pipe_thread_create( void *(WINAPI * routine)( void *), void *param ) 132{ 133 DWORD id; 134 return CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE) routine, param, 0, &id ); 135} 136 137static INLINE int pipe_thread_wait( pipe_thread thread ) 138{ 139 if (WaitForSingleObject( thread, INFINITE ) == WAIT_OBJECT_0) 140 return 0; 141 return -1; 142} 143 144static INLINE int pipe_thread_destroy( pipe_thread thread ) 145{ 146 if (CloseHandle( thread )) 147 return 0; 148 return -1; 149} 150 151 152/* pipe_mutex 153 */ 154typedef CRITICAL_SECTION pipe_mutex; 155 156#define pipe_static_mutex(mutex) \ 157 /*static*/ pipe_mutex mutex = {0,0,0,0,0,0} 158 159#define pipe_mutex_init(mutex) \ 160 InitializeCriticalSection(&mutex) 161 162#define pipe_mutex_destroy(mutex) \ 163 DeleteCriticalSection(&mutex) 164 165#define pipe_mutex_lock(mutex) \ 166 EnterCriticalSection(&mutex) 167 168#define pipe_mutex_unlock(mutex) \ 169 LeaveCriticalSection(&mutex) 170 171 172/* pipe_condvar (XXX FIX THIS) 173 */ 174typedef unsigned pipe_condvar; 175 176#define pipe_condvar_init(cond) \ 177 (void) cond 178 179#define pipe_condvar_destroy(cond) \ 180 (void) cond 181 182#define pipe_condvar_wait(cond, mutex) \ 183 (void) cond; (void) mutex 184 185#define pipe_condvar_signal(cond) \ 186 (void) cond 187 188#define pipe_condvar_broadcast(cond) \ 189 (void) cond 190 191 192#else 193 194/** Dummy definitions */ 195 196typedef unsigned pipe_thread; 197 198#define PIPE_THREAD_ROUTINE( name, param ) \ 199 void * name( void *param ) 200 201static INLINE pipe_thread pipe_thread_create( void *(* routine)( void *), void *param ) 202{ 203 return 0; 204} 205 206static INLINE int pipe_thread_wait( pipe_thread thread ) 207{ 208 return -1; 209} 210 211static INLINE int pipe_thread_destroy( pipe_thread thread ) 212{ 213 return -1; 214} 215 216typedef unsigned pipe_mutex; 217typedef unsigned pipe_condvar; 218 219#define pipe_static_mutex(mutex) \ 220 static pipe_mutex mutex = 0 221 222#define pipe_mutex_init(mutex) \ 223 (void) mutex 224 225#define pipe_mutex_destroy(mutex) \ 226 (void) mutex 227 228#define pipe_mutex_lock(mutex) \ 229 (void) mutex 230 231#define pipe_mutex_unlock(mutex) \ 232 (void) mutex 233 234#define pipe_static_condvar(condvar) \ 235 static unsigned condvar = 0 236 237#define pipe_condvar_init(condvar) \ 238 (void) condvar 239 240#define pipe_condvar_destroy(condvar) \ 241 (void) condvar 242 243#define pipe_condvar_wait(condvar, mutex) \ 244 (void) condvar 245 246#define pipe_condvar_signal(condvar) \ 247 (void) condvar 248 249#define pipe_condvar_broadcast(condvar) \ 250 (void) condvar 251 252 253#endif /* PIPE_OS_? */ 254 255 256/* 257 * pipe_barrier 258 */ 259 260#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_HAIKU) 261 262typedef pthread_barrier_t pipe_barrier; 263 264static INLINE void pipe_barrier_init(pipe_barrier *barrier, unsigned count) 265{ 266 pthread_barrier_init(barrier, NULL, count); 267} 268 269static INLINE void pipe_barrier_destroy(pipe_barrier *barrier) 270{ 271 pthread_barrier_destroy(barrier); 272} 273 274static INLINE void pipe_barrier_wait(pipe_barrier *barrier) 275{ 276 pthread_barrier_wait(barrier); 277} 278 279 280#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) 281 282/* XXX FIX THIS */ 283typedef unsigned pipe_barrier; 284 285static INLINE void pipe_barrier_init(pipe_barrier *barrier, unsigned count) 286{ 287 /* XXX we could implement barriers with a mutex and condition var */ 288} 289 290static INLINE void pipe_barrier_destroy(pipe_barrier *barrier) 291{ 292} 293 294static INLINE void pipe_barrier_wait(pipe_barrier *barrier) 295{ 296 assert(0); 297} 298 299 300#else 301 302typedef unsigned pipe_barrier; 303 304static INLINE void pipe_barrier_init(pipe_barrier *barrier, unsigned count) 305{ 306 /* XXX we could implement barriers with a mutex and condition var */ 307 assert(0); 308} 309 310static INLINE void pipe_barrier_destroy(pipe_barrier *barrier) 311{ 312 assert(0); 313} 314 315static INLINE void pipe_barrier_wait(pipe_barrier *barrier) 316{ 317 assert(0); 318} 319 320 321#endif 322 323 324/* 325 * Semaphores 326 */ 327 328typedef struct 329{ 330 pipe_mutex mutex; 331 pipe_condvar cond; 332 int counter; 333} pipe_semaphore; 334 335 336static INLINE void 337pipe_semaphore_init(pipe_semaphore *sema, int init_val) 338{ 339 pipe_mutex_init(sema->mutex); 340 pipe_condvar_init(sema->cond); 341 sema->counter = init_val; 342} 343 344static INLINE void 345pipe_semaphore_destroy(pipe_semaphore *sema) 346{ 347 pipe_mutex_destroy(sema->mutex); 348 pipe_condvar_destroy(sema->cond); 349} 350 351/** Signal/increment semaphore counter */ 352static INLINE void 353pipe_semaphore_signal(pipe_semaphore *sema) 354{ 355 pipe_mutex_lock(sema->mutex); 356 sema->counter++; 357 pipe_condvar_signal(sema->cond); 358 pipe_mutex_unlock(sema->mutex); 359} 360 361/** Wait for semaphore counter to be greater than zero */ 362static INLINE void 363pipe_semaphore_wait(pipe_semaphore *sema) 364{ 365 pipe_mutex_lock(sema->mutex); 366 while (sema->counter <= 0) { 367 pipe_condvar_wait(sema->cond, sema->mutex); 368 } 369 sema->counter--; 370 pipe_mutex_unlock(sema->mutex); 371} 372 373 374 375/* 376 * Thread-specific data. 377 */ 378 379typedef struct { 380#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) 381 pthread_key_t key; 382#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) 383 DWORD key; 384#endif 385 int initMagic; 386} pipe_tsd; 387 388 389#define PIPE_TSD_INIT_MAGIC 0xff8adc98 390 391 392static INLINE void 393pipe_tsd_init(pipe_tsd *tsd) 394{ 395#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) 396 if (pthread_key_create(&tsd->key, NULL/*free*/) != 0) { 397 perror("pthread_key_create(): failed to allocate key for thread specific data"); 398 exit(-1); 399 } 400#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) 401 assert(0); 402#endif 403 tsd->initMagic = PIPE_TSD_INIT_MAGIC; 404} 405 406static INLINE void * 407pipe_tsd_get(pipe_tsd *tsd) 408{ 409 if (tsd->initMagic != (int) PIPE_TSD_INIT_MAGIC) { 410 pipe_tsd_init(tsd); 411 } 412#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) 413 return pthread_getspecific(tsd->key); 414#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) 415 assert(0); 416 return NULL; 417#else 418 assert(0); 419 return NULL; 420#endif 421} 422 423static INLINE void 424pipe_tsd_set(pipe_tsd *tsd, void *value) 425{ 426 if (tsd->initMagic != (int) PIPE_TSD_INIT_MAGIC) { 427 pipe_tsd_init(tsd); 428 } 429#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) 430 if (pthread_setspecific(tsd->key, value) != 0) { 431 perror("pthread_set_specific() failed"); 432 exit(-1); 433 } 434#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) 435 assert(0); 436#else 437 assert(0); 438#endif 439} 440 441 442 443#endif /* OS_THREAD_H_ */ 444