1/* 2 * Mesa 3-D graphics library 3 * Version: 6.5.1 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 * XXX There's probably some work to do in order to make this file 28 * truly reusable outside of Mesa. 29 */ 30 31 32#ifdef HAVE_DIX_CONFIG_H 33#include <dix-config.h> 34#include <X11/Xfuncproto.h> 35#endif 36 37#include <stdlib.h> 38#include <stdio.h> 39#include "glthread.h" 40 41 42/* 43 * This file should still compile even when THREADS is not defined. 44 * This is to make things easier to deal with on the makefile scene.. 45 */ 46#ifdef THREADS 47#include <errno.h> 48 49/* 50 * Error messages 51 */ 52#define INIT_TSD_ERROR "_glthread_: failed to allocate key for thread specific data" 53#define GET_TSD_ERROR "_glthread_: failed to get thread specific data" 54#define SET_TSD_ERROR "_glthread_: thread failed to set thread specific data" 55 56 57/* 58 * Magic number to determine if a TSD object has been initialized. 59 * Kind of a hack but there doesn't appear to be a better cross-platform 60 * solution. 61 */ 62#define INIT_MAGIC 0xff8adc98 63 64 65 66/* 67 * POSIX Threads -- The best way to go if your platform supports them. 68 * Solaris >= 2.5 have POSIX threads, IRIX >= 6.4 reportedly 69 * has them, and many of the free Unixes now have them. 70 * Be sure to use appropriate -mt or -D_REENTRANT type 71 * compile flags when building. 72 */ 73#ifdef PTHREADS 74 75_X_EXPORT unsigned long 76_glthread_GetID(void) 77{ 78 return (unsigned long) pthread_self(); 79} 80 81 82void 83_glthread_InitTSD(_glthread_TSD *tsd) 84{ 85 if (pthread_key_create(&tsd->key, NULL/*free*/) != 0) { 86 perror(INIT_TSD_ERROR); 87 exit(-1); 88 } 89 tsd->initMagic = INIT_MAGIC; 90} 91 92 93void * 94_glthread_GetTSD(_glthread_TSD *tsd) 95{ 96 if (tsd->initMagic != (int) INIT_MAGIC) { 97 _glthread_InitTSD(tsd); 98 } 99 return pthread_getspecific(tsd->key); 100} 101 102 103void 104_glthread_SetTSD(_glthread_TSD *tsd, void *ptr) 105{ 106 if (tsd->initMagic != (int) INIT_MAGIC) { 107 _glthread_InitTSD(tsd); 108 } 109 if (pthread_setspecific(tsd->key, ptr) != 0) { 110 perror(SET_TSD_ERROR); 111 exit(-1); 112 } 113} 114 115#endif /* PTHREADS */ 116 117 118 119/* 120 * Solaris/Unix International Threads -- Use only if POSIX threads 121 * aren't available on your Unix platform. Solaris 2.[34] are examples 122 * of platforms where this is the case. Be sure to use -mt and/or 123 * -D_REENTRANT when compiling. 124 */ 125#ifdef SOLARIS_THREADS 126#define USE_LOCK_FOR_KEY /* undef this to try a version without 127 lock for the global key... */ 128 129_X_EXPORT unsigned long 130_glthread_GetID(void) 131{ 132 OsAbort(); /* XXX not implemented yet */ 133 return (unsigned long) 0; 134} 135 136 137void 138_glthread_InitTSD(_glthread_TSD *tsd) 139{ 140 if ((errno = mutex_init(&tsd->keylock, 0, NULL)) != 0 || 141 (errno = thr_keycreate(&(tsd->key), free)) != 0) { 142 perror(INIT_TSD_ERROR); 143 exit(-1); 144 } 145 tsd->initMagic = INIT_MAGIC; 146} 147 148 149void * 150_glthread_GetTSD(_glthread_TSD *tsd) 151{ 152 void* ret; 153 if (tsd->initMagic != INIT_MAGIC) { 154 _glthread_InitTSD(tsd); 155 } 156#ifdef USE_LOCK_FOR_KEY 157 mutex_lock(&tsd->keylock); 158 thr_getspecific(tsd->key, &ret); 159 mutex_unlock(&tsd->keylock); 160#else 161 if ((errno = thr_getspecific(tsd->key, &ret)) != 0) { 162 perror(GET_TSD_ERROR); 163 exit(-1); 164 } 165#endif 166 return ret; 167} 168 169 170void 171_glthread_SetTSD(_glthread_TSD *tsd, void *ptr) 172{ 173 if (tsd->initMagic != INIT_MAGIC) { 174 _glthread_InitTSD(tsd); 175 } 176 if ((errno = thr_setspecific(tsd->key, ptr)) != 0) { 177 perror(SET_TSD_ERROR); 178 exit(-1); 179 } 180} 181 182#undef USE_LOCK_FOR_KEY 183#endif /* SOLARIS_THREADS */ 184 185 186 187/* 188 * Win32 Threads. The only available option for Windows 95/NT. 189 * Be sure that you compile using the Multithreaded runtime, otherwise 190 * bad things will happen. 191 */ 192#ifdef WIN32_THREADS 193 194void FreeTSD(_glthread_TSD *p) 195{ 196 if (p->initMagic==INIT_MAGIC) { 197 TlsFree(p->key); 198 p->initMagic=0; 199 } 200} 201 202void InsteadOf_exit(int nCode) 203{ 204 DWORD dwErr=GetLastError(); 205} 206 207unsigned long 208_glthread_GetID(void) 209{ 210 return GetCurrentThreadId(); 211} 212 213 214void 215_glthread_InitTSD(_glthread_TSD *tsd) 216{ 217 tsd->key = TlsAlloc(); 218 if (tsd->key == TLS_OUT_OF_INDEXES) { 219 perror("Mesa:_glthread_InitTSD"); 220 InsteadOf_exit(-1); 221 } 222 tsd->initMagic = INIT_MAGIC; 223} 224 225 226void * 227_glthread_GetTSD(_glthread_TSD *tsd) 228{ 229 if (tsd->initMagic != INIT_MAGIC) { 230 _glthread_InitTSD(tsd); 231 } 232 return TlsGetValue(tsd->key); 233} 234 235 236void 237_glthread_SetTSD(_glthread_TSD *tsd, void *ptr) 238{ 239 /* the following code assumes that the _glthread_TSD has been initialized 240 to zero at creation */ 241 if (tsd->initMagic != INIT_MAGIC) { 242 _glthread_InitTSD(tsd); 243 } 244 if (TlsSetValue(tsd->key, ptr) == 0) { 245 perror("Mesa:_glthread_SetTSD"); 246 InsteadOf_exit(-1); 247 } 248} 249 250#endif /* WIN32_THREADS */ 251 252 253 254/* 255 * XFree86 has its own thread wrapper, Xthreads.h 256 * We wrap it again for GL. 257 */ 258#ifdef USE_XTHREADS 259 260_X_EXPORT unsigned long 261_glthread_GetID(void) 262{ 263 return (unsigned long) xthread_self(); 264} 265 266 267void 268_glthread_InitTSD(_glthread_TSD *tsd) 269{ 270 if (xthread_key_create(&tsd->key, NULL) != 0) { 271 perror(INIT_TSD_ERROR); 272 exit(-1); 273 } 274 tsd->initMagic = INIT_MAGIC; 275} 276 277 278void * 279_glthread_GetTSD(_glthread_TSD *tsd) 280{ 281 void *ptr; 282 if (tsd->initMagic != INIT_MAGIC) { 283 _glthread_InitTSD(tsd); 284 } 285 xthread_get_specific(tsd->key, &ptr); 286 return ptr; 287} 288 289 290void 291_glthread_SetTSD(_glthread_TSD *tsd, void *ptr) 292{ 293 if (tsd->initMagic != INIT_MAGIC) { 294 _glthread_InitTSD(tsd); 295 } 296 xthread_set_specific(tsd->key, ptr); 297} 298 299#endif /* XTHREAD */ 300 301 302 303/* 304 * BeOS threads 305 */ 306#ifdef BEOS_THREADS 307 308unsigned long 309_glthread_GetID(void) 310{ 311 return (unsigned long) find_thread(NULL); 312} 313 314void 315_glthread_InitTSD(_glthread_TSD *tsd) 316{ 317 tsd->key = tls_allocate(); 318 tsd->initMagic = INIT_MAGIC; 319} 320 321void * 322_glthread_GetTSD(_glthread_TSD *tsd) 323{ 324 if (tsd->initMagic != (int) INIT_MAGIC) { 325 _glthread_InitTSD(tsd); 326 } 327 return tls_get(tsd->key); 328} 329 330void 331_glthread_SetTSD(_glthread_TSD *tsd, void *ptr) 332{ 333 if (tsd->initMagic != (int) INIT_MAGIC) { 334 _glthread_InitTSD(tsd); 335 } 336 tls_set(tsd->key, ptr); 337} 338 339#endif /* BEOS_THREADS */ 340 341 342 343#else /* THREADS */ 344 345 346/* 347 * no-op functions 348 */ 349 350_X_EXPORT unsigned long 351_glthread_GetID(void) 352{ 353 return 0; 354} 355 356 357void 358_glthread_InitTSD(_glthread_TSD *tsd) 359{ 360 (void) tsd; 361} 362 363 364void * 365_glthread_GetTSD(_glthread_TSD *tsd) 366{ 367 (void) tsd; 368 return NULL; 369} 370 371 372void 373_glthread_SetTSD(_glthread_TSD *tsd, void *ptr) 374{ 375 (void) tsd; 376 (void) ptr; 377} 378 379 380#endif /* THREADS */ 381