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 (at) acm.org) (johns (at) cs.umr.edu) 30 * and Christoph Poliwoda (poliwoda (at) 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 78 extern "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 93 struct u_tsd { 94 pthread_key_t key; 95 unsigned initMagic; 96 }; 97 98 typedef 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 108 static INLINE unsigned long 109 u_thread_self(void) 110 { 111 return (unsigned long) pthread_self(); 112 } 113 114 115 static INLINE void 116 u_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 126 static INLINE void * 127 u_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 136 static INLINE void 137 u_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 158 struct u_tsd { 159 DWORD key; 160 unsigned initMagic; 161 }; 162 163 typedef 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 174 static INLINE unsigned long 175 u_thread_self(void) 176 { 177 return GetCurrentThreadId(); 178 } 179 180 181 static INLINE void 182 u_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 193 static INLINE void 194 u_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 204 static INLINE void * 205 u_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 214 static INLINE void 215 u_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 236 struct u_tsd { 237 unsigned initMagic; 238 }; 239 240 typedef 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 252 static INLINE unsigned long 253 u_thread_self(void) 254 { 255 return 0; 256 } 257 258 259 static INLINE void 260 u_tsd_init(struct u_tsd *tsd) 261 { 262 (void) tsd; 263 } 264 265 266 static INLINE void * 267 u_tsd_get(struct u_tsd *tsd) 268 { 269 (void) tsd; 270 return NULL; 271 } 272 273 274 static INLINE void 275 u_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