u_thread.h revision a2f28ceea22254f09ee37039eec873ccdf689e6c
1/* 2 * Mesa 3-D graphics library 3 * Version: 6.5.2 4 * 5 * Copyright (C) 1999-2006 Brian Paul 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 * Thread support for gl dispatch. 28 * 29 * Initial version by John Stone (j.stone@acm.org) (johns@cs.umr.edu) 30 * and Christoph Poliwoda (poliwoda@volumegraphics.com) 31 * Revised by Keith Whitwell 32 * Adapted for new gl dispatcher by Brian Paul 33 * Modified for use in mapi by Chia-I Wu 34 */ 35 36/* 37 * If this file is accidentally included by a non-threaded build, 38 * it should not cause the build to fail, or otherwise cause problems. 39 * In general, it should only be included when needed however. 40 */ 41 42#ifndef _U_THREAD_H_ 43#define _U_THREAD_H_ 44 45#include <stdio.h> 46#include <stdlib.h> 47#include "u_compiler.h" 48 49#if defined(HAVE_PTHREAD) 50#include <pthread.h> /* POSIX threads headers */ 51#endif 52#ifdef _WIN32 53#include <windows.h> 54#endif 55 56#if defined(HAVE_PTHREAD) || defined(_WIN32) 57#ifndef THREADS 58#define THREADS 59#endif 60#endif 61 62/* 63 * Error messages 64 */ 65#define INIT_TSD_ERROR "_glthread_: failed to allocate key for thread specific data" 66#define GET_TSD_ERROR "_glthread_: failed to get thread specific data" 67#define SET_TSD_ERROR "_glthread_: thread failed to set thread specific data" 68 69 70/* 71 * Magic number to determine if a TSD object has been initialized. 72 * Kind of a hack but there doesn't appear to be a better cross-platform 73 * solution. 74 */ 75#define INIT_MAGIC 0xff8adc98 76 77#ifdef __cplusplus 78extern "C" { 79#endif 80 81 82/* 83 * POSIX threads. This should be your choice in the Unix world 84 * whenever possible. When building with POSIX threads, be sure 85 * to enable any compiler flags which will cause the MT-safe 86 * libc (if one exists) to be used when linking, as well as any 87 * header macros for MT-safe errno, etc. For Solaris, this is the -mt 88 * compiler flag. On Solaris with gcc, use -D_REENTRANT to enable 89 * proper compiling for MT-safe libc etc. 90 */ 91#if defined(HAVE_PTHREAD) 92 93struct u_tsd { 94 pthread_key_t key; 95 unsigned initMagic; 96}; 97 98typedef pthread_mutex_t u_mutex; 99 100#define u_mutex_declare_static(name) \ 101 static u_mutex name = PTHREAD_MUTEX_INITIALIZER 102 103#define u_mutex_init(name) pthread_mutex_init(&(name), NULL) 104#define u_mutex_destroy(name) pthread_mutex_destroy(&(name)) 105#define u_mutex_lock(name) (void) pthread_mutex_lock(&(name)) 106#define u_mutex_unlock(name) (void) pthread_mutex_unlock(&(name)) 107 108static INLINE unsigned long 109u_thread_self(void) 110{ 111 return (unsigned long) pthread_self(); 112} 113 114 115static INLINE void 116u_tsd_init(struct u_tsd *tsd) 117{ 118 if (pthread_key_create(&tsd->key, NULL/*free*/) != 0) { 119 perror(INIT_TSD_ERROR); 120 exit(-1); 121 } 122 tsd->initMagic = INIT_MAGIC; 123} 124 125 126static INLINE void * 127u_tsd_get(struct u_tsd *tsd) 128{ 129 if (tsd->initMagic != INIT_MAGIC) { 130 u_tsd_init(tsd); 131 } 132 return pthread_getspecific(tsd->key); 133} 134 135 136static INLINE void 137u_tsd_set(struct u_tsd *tsd, void *ptr) 138{ 139 if (tsd->initMagic != INIT_MAGIC) { 140 u_tsd_init(tsd); 141 } 142 if (pthread_setspecific(tsd->key, ptr) != 0) { 143 perror(SET_TSD_ERROR); 144 exit(-1); 145 } 146} 147 148#endif /* HAVE_PTHREAD */ 149 150 151/* 152 * Windows threads. Should work with Windows NT and 95. 153 * IMPORTANT: Link with multithreaded runtime library when THREADS are 154 * used! 155 */ 156#ifdef WIN32 157 158struct u_tsd { 159 DWORD key; 160 unsigned initMagic; 161}; 162 163typedef CRITICAL_SECTION u_mutex; 164 165/* http://locklessinc.com/articles/pthreads_on_windows/ */ 166#define u_mutex_declare_static(name) \ 167 static u_mutex name = {(PCRITICAL_SECTION_DEBUG)-1, -1, 0, 0, 0, 0} 168 169#define u_mutex_init(name) InitializeCriticalSection(&name) 170#define u_mutex_destroy(name) DeleteCriticalSection(&name) 171#define u_mutex_lock(name) EnterCriticalSection(&name) 172#define u_mutex_unlock(name) LeaveCriticalSection(&name) 173 174static INLINE unsigned long 175u_thread_self(void) 176{ 177 return GetCurrentThreadId(); 178} 179 180 181static INLINE void 182u_tsd_init(struct u_tsd *tsd) 183{ 184 tsd->key = TlsAlloc(); 185 if (tsd->key == TLS_OUT_OF_INDEXES) { 186 perror(INIT_TSD_ERROR); 187 exit(-1); 188 } 189 tsd->initMagic = INIT_MAGIC; 190} 191 192 193static INLINE void 194u_tsd_destroy(struct u_tsd *tsd) 195{ 196 if (tsd->initMagic != INIT_MAGIC) { 197 return; 198 } 199 TlsFree(tsd->key); 200 tsd->initMagic = 0x0; 201} 202 203 204static INLINE void * 205u_tsd_get(struct u_tsd *tsd) 206{ 207 if (tsd->initMagic != INIT_MAGIC) { 208 u_tsd_init(tsd); 209 } 210 return TlsGetValue(tsd->key); 211} 212 213 214static INLINE void 215u_tsd_set(struct u_tsd *tsd, void *ptr) 216{ 217 /* the following code assumes that the struct u_tsd has been initialized 218 to zero at creation */ 219 if (tsd->initMagic != INIT_MAGIC) { 220 u_tsd_init(tsd); 221 } 222 if (TlsSetValue(tsd->key, ptr) == 0) { 223 perror(SET_TSD_ERROR); 224 exit(-1); 225 } 226} 227 228#endif /* WIN32 */ 229 230 231/* 232 * THREADS not defined 233 */ 234#ifndef THREADS 235 236struct u_tsd { 237 unsigned initMagic; 238}; 239 240typedef unsigned u_mutex; 241 242#define u_mutex_declare_static(name) static u_mutex name = 0 243#define u_mutex_init(name) (void) name 244#define u_mutex_destroy(name) (void) name 245#define u_mutex_lock(name) (void) name 246#define u_mutex_unlock(name) (void) name 247 248/* 249 * no-op functions 250 */ 251 252static INLINE unsigned long 253u_thread_self(void) 254{ 255 return 0; 256} 257 258 259static INLINE void 260u_tsd_init(struct u_tsd *tsd) 261{ 262 (void) tsd; 263} 264 265 266static INLINE void * 267u_tsd_get(struct u_tsd *tsd) 268{ 269 (void) tsd; 270 return NULL; 271} 272 273 274static INLINE void 275u_tsd_set(struct u_tsd *tsd, void *ptr) 276{ 277 (void) tsd; 278 (void) ptr; 279} 280#endif /* THREADS */ 281 282 283#ifdef __cplusplus 284} 285#endif 286 287#endif /* _U_THREAD_H_ */ 288