1706f2543Smrg/* 2706f2543Smrg * Mesa 3-D graphics library 3706f2543Smrg * Version: 6.5.1 4706f2543Smrg * 5706f2543Smrg * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. 6706f2543Smrg * 7706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 8706f2543Smrg * copy of this software and associated documentation files (the "Software"), 9706f2543Smrg * to deal in the Software without restriction, including without limitation 10706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 12706f2543Smrg * Software is furnished to do so, subject to the following conditions: 13706f2543Smrg * 14706f2543Smrg * The above copyright notice and this permission notice shall be included 15706f2543Smrg * in all copies or substantial portions of the Software. 16706f2543Smrg * 17706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18706f2543Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20706f2543Smrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21706f2543Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22706f2543Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23706f2543Smrg */ 24706f2543Smrg 25706f2543Smrg 26706f2543Smrg/* 27706f2543Smrg * XXX There's probably some work to do in order to make this file 28706f2543Smrg * truly reusable outside of Mesa. 29706f2543Smrg */ 30706f2543Smrg 31706f2543Smrg 32706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 33706f2543Smrg#include <dix-config.h> 34706f2543Smrg#include <X11/Xfuncproto.h> 35706f2543Smrg#endif 36706f2543Smrg 37706f2543Smrg#include <stdlib.h> 38706f2543Smrg#include <stdio.h> 39706f2543Smrg#include "glthread.h" 40706f2543Smrg 41706f2543Smrg 42706f2543Smrg/* 43706f2543Smrg * This file should still compile even when THREADS is not defined. 44706f2543Smrg * This is to make things easier to deal with on the makefile scene.. 45706f2543Smrg */ 46706f2543Smrg#ifdef THREADS 47706f2543Smrg#include <errno.h> 48706f2543Smrg 49706f2543Smrg/* 50706f2543Smrg * Error messages 51706f2543Smrg */ 52706f2543Smrg#define INIT_TSD_ERROR "_glthread_: failed to allocate key for thread specific data" 53706f2543Smrg#define GET_TSD_ERROR "_glthread_: failed to get thread specific data" 54706f2543Smrg#define SET_TSD_ERROR "_glthread_: thread failed to set thread specific data" 55706f2543Smrg 56706f2543Smrg 57706f2543Smrg/* 58706f2543Smrg * Magic number to determine if a TSD object has been initialized. 59706f2543Smrg * Kind of a hack but there doesn't appear to be a better cross-platform 60706f2543Smrg * solution. 61706f2543Smrg */ 62706f2543Smrg#define INIT_MAGIC 0xff8adc98 63706f2543Smrg 64706f2543Smrg 65706f2543Smrg 66706f2543Smrg/* 67706f2543Smrg * POSIX Threads -- The best way to go if your platform supports them. 68706f2543Smrg * Solaris >= 2.5 have POSIX threads, IRIX >= 6.4 reportedly 69706f2543Smrg * has them, and many of the free Unixes now have them. 70706f2543Smrg * Be sure to use appropriate -mt or -D_REENTRANT type 71706f2543Smrg * compile flags when building. 72706f2543Smrg */ 73706f2543Smrg#ifdef PTHREADS 74706f2543Smrg 75706f2543Smrg_X_EXPORT unsigned long 76706f2543Smrg_glthread_GetID(void) 77706f2543Smrg{ 78706f2543Smrg return (unsigned long) pthread_self(); 79706f2543Smrg} 80706f2543Smrg 81706f2543Smrg 82706f2543Smrgvoid 83706f2543Smrg_glthread_InitTSD(_glthread_TSD *tsd) 84706f2543Smrg{ 85706f2543Smrg if (pthread_key_create(&tsd->key, NULL/*free*/) != 0) { 86706f2543Smrg perror(INIT_TSD_ERROR); 87706f2543Smrg exit(-1); 88706f2543Smrg } 89706f2543Smrg tsd->initMagic = INIT_MAGIC; 90706f2543Smrg} 91706f2543Smrg 92706f2543Smrg 93706f2543Smrgvoid * 94706f2543Smrg_glthread_GetTSD(_glthread_TSD *tsd) 95706f2543Smrg{ 96706f2543Smrg if (tsd->initMagic != (int) INIT_MAGIC) { 97706f2543Smrg _glthread_InitTSD(tsd); 98706f2543Smrg } 99706f2543Smrg return pthread_getspecific(tsd->key); 100706f2543Smrg} 101706f2543Smrg 102706f2543Smrg 103706f2543Smrgvoid 104706f2543Smrg_glthread_SetTSD(_glthread_TSD *tsd, void *ptr) 105706f2543Smrg{ 106706f2543Smrg if (tsd->initMagic != (int) INIT_MAGIC) { 107706f2543Smrg _glthread_InitTSD(tsd); 108706f2543Smrg } 109706f2543Smrg if (pthread_setspecific(tsd->key, ptr) != 0) { 110706f2543Smrg perror(SET_TSD_ERROR); 111706f2543Smrg exit(-1); 112706f2543Smrg } 113706f2543Smrg} 114706f2543Smrg 115706f2543Smrg#endif /* PTHREADS */ 116706f2543Smrg 117706f2543Smrg 118706f2543Smrg 119706f2543Smrg/* 120706f2543Smrg * Solaris/Unix International Threads -- Use only if POSIX threads 121706f2543Smrg * aren't available on your Unix platform. Solaris 2.[34] are examples 122706f2543Smrg * of platforms where this is the case. Be sure to use -mt and/or 123706f2543Smrg * -D_REENTRANT when compiling. 124706f2543Smrg */ 125706f2543Smrg#ifdef SOLARIS_THREADS 126706f2543Smrg#define USE_LOCK_FOR_KEY /* undef this to try a version without 127706f2543Smrg lock for the global key... */ 128706f2543Smrg 129706f2543Smrg_X_EXPORT unsigned long 130706f2543Smrg_glthread_GetID(void) 131706f2543Smrg{ 132706f2543Smrg OsAbort(); /* XXX not implemented yet */ 133706f2543Smrg return (unsigned long) 0; 134706f2543Smrg} 135706f2543Smrg 136706f2543Smrg 137706f2543Smrgvoid 138706f2543Smrg_glthread_InitTSD(_glthread_TSD *tsd) 139706f2543Smrg{ 140706f2543Smrg if ((errno = mutex_init(&tsd->keylock, 0, NULL)) != 0 || 141706f2543Smrg (errno = thr_keycreate(&(tsd->key), free)) != 0) { 142706f2543Smrg perror(INIT_TSD_ERROR); 143706f2543Smrg exit(-1); 144706f2543Smrg } 145706f2543Smrg tsd->initMagic = INIT_MAGIC; 146706f2543Smrg} 147706f2543Smrg 148706f2543Smrg 149706f2543Smrgvoid * 150706f2543Smrg_glthread_GetTSD(_glthread_TSD *tsd) 151706f2543Smrg{ 152706f2543Smrg void* ret; 153706f2543Smrg if (tsd->initMagic != INIT_MAGIC) { 154706f2543Smrg _glthread_InitTSD(tsd); 155706f2543Smrg } 156706f2543Smrg#ifdef USE_LOCK_FOR_KEY 157706f2543Smrg mutex_lock(&tsd->keylock); 158706f2543Smrg thr_getspecific(tsd->key, &ret); 159706f2543Smrg mutex_unlock(&tsd->keylock); 160706f2543Smrg#else 161706f2543Smrg if ((errno = thr_getspecific(tsd->key, &ret)) != 0) { 162706f2543Smrg perror(GET_TSD_ERROR); 163706f2543Smrg exit(-1); 164706f2543Smrg } 165706f2543Smrg#endif 166706f2543Smrg return ret; 167706f2543Smrg} 168706f2543Smrg 169706f2543Smrg 170706f2543Smrgvoid 171706f2543Smrg_glthread_SetTSD(_glthread_TSD *tsd, void *ptr) 172706f2543Smrg{ 173706f2543Smrg if (tsd->initMagic != INIT_MAGIC) { 174706f2543Smrg _glthread_InitTSD(tsd); 175706f2543Smrg } 176706f2543Smrg if ((errno = thr_setspecific(tsd->key, ptr)) != 0) { 177706f2543Smrg perror(SET_TSD_ERROR); 178706f2543Smrg exit(-1); 179706f2543Smrg } 180706f2543Smrg} 181706f2543Smrg 182706f2543Smrg#undef USE_LOCK_FOR_KEY 183706f2543Smrg#endif /* SOLARIS_THREADS */ 184706f2543Smrg 185706f2543Smrg 186706f2543Smrg 187706f2543Smrg/* 188706f2543Smrg * Win32 Threads. The only available option for Windows 95/NT. 189706f2543Smrg * Be sure that you compile using the Multithreaded runtime, otherwise 190706f2543Smrg * bad things will happen. 191706f2543Smrg */ 192706f2543Smrg#ifdef WIN32_THREADS 193706f2543Smrg 194706f2543Smrgvoid FreeTSD(_glthread_TSD *p) 195706f2543Smrg{ 196706f2543Smrg if (p->initMagic==INIT_MAGIC) { 197706f2543Smrg TlsFree(p->key); 198706f2543Smrg p->initMagic=0; 199706f2543Smrg } 200706f2543Smrg} 201706f2543Smrg 202706f2543Smrgvoid InsteadOf_exit(int nCode) 203706f2543Smrg{ 204706f2543Smrg DWORD dwErr=GetLastError(); 205706f2543Smrg} 206706f2543Smrg 207706f2543Smrgunsigned long 208706f2543Smrg_glthread_GetID(void) 209706f2543Smrg{ 210706f2543Smrg return GetCurrentThreadId(); 211706f2543Smrg} 212706f2543Smrg 213706f2543Smrg 214706f2543Smrgvoid 215706f2543Smrg_glthread_InitTSD(_glthread_TSD *tsd) 216706f2543Smrg{ 217706f2543Smrg tsd->key = TlsAlloc(); 218706f2543Smrg if (tsd->key == TLS_OUT_OF_INDEXES) { 219706f2543Smrg perror("Mesa:_glthread_InitTSD"); 220706f2543Smrg InsteadOf_exit(-1); 221706f2543Smrg } 222706f2543Smrg tsd->initMagic = INIT_MAGIC; 223706f2543Smrg} 224706f2543Smrg 225706f2543Smrg 226706f2543Smrgvoid * 227706f2543Smrg_glthread_GetTSD(_glthread_TSD *tsd) 228706f2543Smrg{ 229706f2543Smrg if (tsd->initMagic != INIT_MAGIC) { 230706f2543Smrg _glthread_InitTSD(tsd); 231706f2543Smrg } 232706f2543Smrg return TlsGetValue(tsd->key); 233706f2543Smrg} 234706f2543Smrg 235706f2543Smrg 236706f2543Smrgvoid 237706f2543Smrg_glthread_SetTSD(_glthread_TSD *tsd, void *ptr) 238706f2543Smrg{ 239706f2543Smrg /* the following code assumes that the _glthread_TSD has been initialized 240706f2543Smrg to zero at creation */ 241706f2543Smrg if (tsd->initMagic != INIT_MAGIC) { 242706f2543Smrg _glthread_InitTSD(tsd); 243706f2543Smrg } 244706f2543Smrg if (TlsSetValue(tsd->key, ptr) == 0) { 245706f2543Smrg perror("Mesa:_glthread_SetTSD"); 246706f2543Smrg InsteadOf_exit(-1); 247706f2543Smrg } 248706f2543Smrg} 249706f2543Smrg 250706f2543Smrg#endif /* WIN32_THREADS */ 251706f2543Smrg 252706f2543Smrg 253706f2543Smrg 254706f2543Smrg/* 255706f2543Smrg * XFree86 has its own thread wrapper, Xthreads.h 256706f2543Smrg * We wrap it again for GL. 257706f2543Smrg */ 258706f2543Smrg#ifdef USE_XTHREADS 259706f2543Smrg 260706f2543Smrg_X_EXPORT unsigned long 261706f2543Smrg_glthread_GetID(void) 262706f2543Smrg{ 263706f2543Smrg return (unsigned long) xthread_self(); 264706f2543Smrg} 265706f2543Smrg 266706f2543Smrg 267706f2543Smrgvoid 268706f2543Smrg_glthread_InitTSD(_glthread_TSD *tsd) 269706f2543Smrg{ 270706f2543Smrg if (xthread_key_create(&tsd->key, NULL) != 0) { 271706f2543Smrg perror(INIT_TSD_ERROR); 272706f2543Smrg exit(-1); 273706f2543Smrg } 274706f2543Smrg tsd->initMagic = INIT_MAGIC; 275706f2543Smrg} 276706f2543Smrg 277706f2543Smrg 278706f2543Smrgvoid * 279706f2543Smrg_glthread_GetTSD(_glthread_TSD *tsd) 280706f2543Smrg{ 281706f2543Smrg void *ptr; 282706f2543Smrg if (tsd->initMagic != INIT_MAGIC) { 283706f2543Smrg _glthread_InitTSD(tsd); 284706f2543Smrg } 285706f2543Smrg xthread_get_specific(tsd->key, &ptr); 286706f2543Smrg return ptr; 287706f2543Smrg} 288706f2543Smrg 289706f2543Smrg 290706f2543Smrgvoid 291706f2543Smrg_glthread_SetTSD(_glthread_TSD *tsd, void *ptr) 292706f2543Smrg{ 293706f2543Smrg if (tsd->initMagic != INIT_MAGIC) { 294706f2543Smrg _glthread_InitTSD(tsd); 295706f2543Smrg } 296706f2543Smrg xthread_set_specific(tsd->key, ptr); 297706f2543Smrg} 298706f2543Smrg 299706f2543Smrg#endif /* XTHREAD */ 300706f2543Smrg 301706f2543Smrg 302706f2543Smrg 303706f2543Smrg/* 304706f2543Smrg * BeOS threads 305706f2543Smrg */ 306706f2543Smrg#ifdef BEOS_THREADS 307706f2543Smrg 308706f2543Smrgunsigned long 309706f2543Smrg_glthread_GetID(void) 310706f2543Smrg{ 311706f2543Smrg return (unsigned long) find_thread(NULL); 312706f2543Smrg} 313706f2543Smrg 314706f2543Smrgvoid 315706f2543Smrg_glthread_InitTSD(_glthread_TSD *tsd) 316706f2543Smrg{ 317706f2543Smrg tsd->key = tls_allocate(); 318706f2543Smrg tsd->initMagic = INIT_MAGIC; 319706f2543Smrg} 320706f2543Smrg 321706f2543Smrgvoid * 322706f2543Smrg_glthread_GetTSD(_glthread_TSD *tsd) 323706f2543Smrg{ 324706f2543Smrg if (tsd->initMagic != (int) INIT_MAGIC) { 325706f2543Smrg _glthread_InitTSD(tsd); 326706f2543Smrg } 327706f2543Smrg return tls_get(tsd->key); 328706f2543Smrg} 329706f2543Smrg 330706f2543Smrgvoid 331706f2543Smrg_glthread_SetTSD(_glthread_TSD *tsd, void *ptr) 332706f2543Smrg{ 333706f2543Smrg if (tsd->initMagic != (int) INIT_MAGIC) { 334706f2543Smrg _glthread_InitTSD(tsd); 335706f2543Smrg } 336706f2543Smrg tls_set(tsd->key, ptr); 337706f2543Smrg} 338706f2543Smrg 339706f2543Smrg#endif /* BEOS_THREADS */ 340706f2543Smrg 341706f2543Smrg 342706f2543Smrg 343706f2543Smrg#else /* THREADS */ 344706f2543Smrg 345706f2543Smrg 346706f2543Smrg/* 347706f2543Smrg * no-op functions 348706f2543Smrg */ 349706f2543Smrg 350706f2543Smrg_X_EXPORT unsigned long 351706f2543Smrg_glthread_GetID(void) 352706f2543Smrg{ 353706f2543Smrg return 0; 354706f2543Smrg} 355706f2543Smrg 356706f2543Smrg 357706f2543Smrgvoid 358706f2543Smrg_glthread_InitTSD(_glthread_TSD *tsd) 359706f2543Smrg{ 360706f2543Smrg (void) tsd; 361706f2543Smrg} 362706f2543Smrg 363706f2543Smrg 364706f2543Smrgvoid * 365706f2543Smrg_glthread_GetTSD(_glthread_TSD *tsd) 366706f2543Smrg{ 367706f2543Smrg (void) tsd; 368706f2543Smrg return NULL; 369706f2543Smrg} 370706f2543Smrg 371706f2543Smrg 372706f2543Smrgvoid 373706f2543Smrg_glthread_SetTSD(_glthread_TSD *tsd, void *ptr) 374706f2543Smrg{ 375706f2543Smrg (void) tsd; 376706f2543Smrg (void) ptr; 377706f2543Smrg} 378706f2543Smrg 379706f2543Smrg 380706f2543Smrg#endif /* THREADS */ 381