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 * 34 * 35 * 36 * DOCUMENTATION 37 * 38 * This thread module exports the following types: 39 * _glthread_TSD Thread-specific data area 40 * _glthread_Thread Thread datatype 41 * _glthread_Mutex Mutual exclusion lock 42 * 43 * Macros: 44 * _glthread_DECLARE_STATIC_MUTEX(name) Declare a non-local mutex 45 * _glthread_INIT_MUTEX(name) Initialize a mutex 46 * _glthread_LOCK_MUTEX(name) Lock a mutex 47 * _glthread_UNLOCK_MUTEX(name) Unlock a mutex 48 * 49 * Functions: 50 * _glthread_GetID(v) Get integer thread ID 51 * _glthread_InitTSD() Initialize thread-specific data 52 * _glthread_GetTSD() Get thread-specific data 53 * _glthread_SetTSD() Set thread-specific data 54 * 55 */ 56 57/* 58 * If this file is accidentally included by a non-threaded build, 59 * it should not cause the build to fail, or otherwise cause problems. 60 * In general, it should only be included when needed however. 61 */ 62 63#ifndef GLTHREAD_H 64#define GLTHREAD_H 65 66 67#if defined(USE_MGL_NAMESPACE) 68#define _glapi_Dispatch _mglapi_Dispatch 69#endif 70 71 72 73#if (defined(PTHREADS) || defined(SOLARIS_THREADS) ||\ 74 defined(WIN32_THREADS) || defined(USE_XTHREADS) || defined(BEOS_THREADS)) \ 75 && !defined(THREADS) 76# define THREADS 77#endif 78 79#ifdef VMS 80#include <GL/vms_x_fix.h> 81#endif 82 83/* 84 * POSIX threads. This should be your choice in the Unix world 85 * whenever possible. When building with POSIX threads, be sure 86 * to enable any compiler flags which will cause the MT-safe 87 * libc (if one exists) to be used when linking, as well as any 88 * header macros for MT-safe errno, etc. For Solaris, this is the -mt 89 * compiler flag. On Solaris with gcc, use -D_REENTRANT to enable 90 * proper compiling for MT-safe libc etc. 91 */ 92#if defined(PTHREADS) 93#include <pthread.h> /* POSIX threads headers */ 94 95typedef struct { 96 pthread_key_t key; 97 int initMagic; 98} _glthread_TSD; 99 100typedef pthread_t _glthread_Thread; 101 102typedef pthread_mutex_t _glthread_Mutex; 103 104#define _glthread_DECLARE_STATIC_MUTEX(name) \ 105 static _glthread_Mutex name = PTHREAD_MUTEX_INITIALIZER 106 107#define _glthread_INIT_MUTEX(name) \ 108 pthread_mutex_init(&(name), NULL) 109 110#define _glthread_DESTROY_MUTEX(name) \ 111 pthread_mutex_destroy(&(name)) 112 113#define _glthread_LOCK_MUTEX(name) \ 114 (void) pthread_mutex_lock(&(name)) 115 116#define _glthread_UNLOCK_MUTEX(name) \ 117 (void) pthread_mutex_unlock(&(name)) 118 119#endif /* PTHREADS */ 120 121 122 123 124/* 125 * Solaris threads. Use only up to Solaris 2.4. 126 * Solaris 2.5 and higher provide POSIX threads. 127 * Be sure to compile with -mt on the Solaris compilers, or 128 * use -D_REENTRANT if using gcc. 129 */ 130#ifdef SOLARIS_THREADS 131#include <thread.h> 132 133typedef struct { 134 thread_key_t key; 135 mutex_t keylock; 136 int initMagic; 137} _glthread_TSD; 138 139typedef thread_t _glthread_Thread; 140 141typedef mutex_t _glthread_Mutex; 142 143/* XXX need to really implement mutex-related macros */ 144#define _glthread_DECLARE_STATIC_MUTEX(name) static _glthread_Mutex name = 0 145#define _glthread_INIT_MUTEX(name) (void) name 146#define _glthread_DESTROY_MUTEX(name) (void) name 147#define _glthread_LOCK_MUTEX(name) (void) name 148#define _glthread_UNLOCK_MUTEX(name) (void) name 149 150#endif /* SOLARIS_THREADS */ 151 152 153 154 155/* 156 * Windows threads. Should work with Windows NT and 95. 157 * IMPORTANT: Link with multithreaded runtime library when THREADS are 158 * used! 159 */ 160#ifdef WIN32_THREADS 161#include <windows.h> 162 163typedef struct { 164 DWORD key; 165 int initMagic; 166} _glthread_TSD; 167 168typedef HANDLE _glthread_Thread; 169 170typedef CRITICAL_SECTION _glthread_Mutex; 171 172#define _glthread_DECLARE_STATIC_MUTEX(name) /*static*/ _glthread_Mutex name = {0,0,0,0,0,0} 173#define _glthread_INIT_MUTEX(name) InitializeCriticalSection(&name) 174#define _glthread_DESTROY_MUTEX(name) DeleteCriticalSection(&name) 175#define _glthread_LOCK_MUTEX(name) EnterCriticalSection(&name) 176#define _glthread_UNLOCK_MUTEX(name) LeaveCriticalSection(&name) 177 178#endif /* WIN32_THREADS */ 179 180 181 182 183/* 184 * XFree86 has its own thread wrapper, Xthreads.h 185 * We wrap it again for GL. 186 */ 187#ifdef USE_XTHREADS 188#include <X11/Xthreads.h> 189 190typedef struct { 191 xthread_key_t key; 192 int initMagic; 193} _glthread_TSD; 194 195typedef xthread_t _glthread_Thread; 196 197typedef xmutex_rec _glthread_Mutex; 198 199#ifdef XMUTEX_INITIALIZER 200#define _glthread_DECLARE_STATIC_MUTEX(name) \ 201 static _glthread_Mutex name = XMUTEX_INITIALIZER 202#else 203#define _glthread_DECLARE_STATIC_MUTEX(name) \ 204 static _glthread_Mutex name 205#endif 206 207#define _glthread_INIT_MUTEX(name) \ 208 xmutex_init(&(name)) 209 210#define _glthread_DESTROY_MUTEX(name) \ 211 xmutex_clear(&(name)) 212 213#define _glthread_LOCK_MUTEX(name) \ 214 (void) xmutex_lock(&(name)) 215 216#define _glthread_UNLOCK_MUTEX(name) \ 217 (void) xmutex_unlock(&(name)) 218 219#endif /* USE_XTHREADS */ 220 221 222 223/* 224 * BeOS threads. R5.x required. 225 */ 226#ifdef BEOS_THREADS 227 228#include <kernel/OS.h> 229#include <support/TLS.h> 230 231typedef struct { 232 int32 key; 233 int initMagic; 234} _glthread_TSD; 235 236typedef thread_id _glthread_Thread; 237 238/* Use Benaphore, aka speeder semaphore */ 239typedef struct { 240 int32 lock; 241 sem_id sem; 242} benaphore; 243typedef benaphore _glthread_Mutex; 244 245#define _glthread_DECLARE_STATIC_MUTEX(name) static _glthread_Mutex name = { 0, 0 } 246#define _glthread_INIT_MUTEX(name) name.sem = create_sem(0, #name"_benaphore"), name.lock = 0 247#define _glthread_DESTROY_MUTEX(name) delete_sem(name.sem), name.lock = 0 248#define _glthread_LOCK_MUTEX(name) if (name.sem == 0) _glthread_INIT_MUTEX(name); \ 249 if (atomic_add(&(name.lock), 1) >= 1) acquire_sem(name.sem) 250#define _glthread_UNLOCK_MUTEX(name) if (atomic_add(&(name.lock), -1) > 1) release_sem(name.sem) 251 252#endif /* BEOS_THREADS */ 253 254 255 256#ifndef THREADS 257 258/* 259 * THREADS not defined 260 */ 261 262typedef int _glthread_TSD; 263 264typedef int _glthread_Thread; 265 266typedef int _glthread_Mutex; 267 268#define _glthread_DECLARE_STATIC_MUTEX(name) static _glthread_Mutex name = 0 269 270#define _glthread_INIT_MUTEX(name) (void) name 271 272#define _glthread_DESTROY_MUTEX(name) (void) name 273 274#define _glthread_LOCK_MUTEX(name) (void) name 275 276#define _glthread_UNLOCK_MUTEX(name) (void) name 277 278#endif /* THREADS */ 279 280 281 282/* 283 * Platform independent thread specific data API. 284 */ 285 286extern unsigned long 287_glthread_GetID(void); 288 289 290extern void 291_glthread_InitTSD(_glthread_TSD *); 292 293 294extern void * 295_glthread_GetTSD(_glthread_TSD *); 296 297 298extern void 299_glthread_SetTSD(_glthread_TSD *, void *); 300 301#if defined(GLX_USE_TLS) 302 303extern TLS struct _glapi_table * _glapi_tls_Dispatch 304 __attribute__((tls_model("initial-exec"))); 305 306#define GET_DISPATCH() _glapi_tls_Dispatch 307 308#elif !defined(GL_CALL) 309# if defined(THREADS) 310# define GET_DISPATCH() \ 311 ((__builtin_expect( _glapi_Dispatch != NULL, 1 )) \ 312 ? _glapi_Dispatch : _glapi_get_dispatch()) 313# else 314# define GET_DISPATCH() _glapi_Dispatch 315# endif /* defined(THREADS) */ 316#endif /* ndef GL_CALL */ 317 318 319#endif /* THREADS_H */ 320