| /* |
| * Mesa 3-D graphics library |
| * Version: 6.5.1 |
| * |
| * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included |
| * in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
| * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| |
| |
| /* |
| * XXX There's probably some work to do in order to make this file |
| * truly reusable outside of Mesa. |
| */ |
| |
| |
| #ifdef HAVE_DIX_CONFIG_H |
| #include <dix-config.h> |
| #endif |
| |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include "glthread.h" |
| |
| |
| /* |
| * This file should still compile even when THREADS is not defined. |
| * This is to make things easier to deal with on the makefile scene.. |
| */ |
| #ifdef THREADS |
| #include <errno.h> |
| |
| /* |
| * Error messages |
| */ |
| #define INIT_TSD_ERROR "_glthread_: failed to allocate key for thread specific data" |
| #define GET_TSD_ERROR "_glthread_: failed to get thread specific data" |
| #define SET_TSD_ERROR "_glthread_: thread failed to set thread specific data" |
| |
| |
| /* |
| * Magic number to determine if a TSD object has been initialized. |
| * Kind of a hack but there doesn't appear to be a better cross-platform |
| * solution. |
| */ |
| #define INIT_MAGIC 0xff8adc98 |
| |
| |
| |
| /* |
| * POSIX Threads -- The best way to go if your platform supports them. |
| * Solaris >= 2.5 have POSIX threads, IRIX >= 6.4 reportedly |
| * has them, and many of the free Unixes now have them. |
| * Be sure to use appropriate -mt or -D_REENTRANT type |
| * compile flags when building. |
| */ |
| #ifdef PTHREADS |
| |
| unsigned long |
| _glthread_GetID(void) |
| { |
| return (unsigned long) pthread_self(); |
| } |
| |
| |
| void |
| _glthread_InitTSD(_glthread_TSD *tsd) |
| { |
| if (pthread_key_create(&tsd->key, NULL/*free*/) != 0) { |
| perror(INIT_TSD_ERROR); |
| exit(-1); |
| } |
| tsd->initMagic = INIT_MAGIC; |
| } |
| |
| |
| void * |
| _glthread_GetTSD(_glthread_TSD *tsd) |
| { |
| if (tsd->initMagic != (int) INIT_MAGIC) { |
| _glthread_InitTSD(tsd); |
| } |
| return pthread_getspecific(tsd->key); |
| } |
| |
| |
| void |
| _glthread_SetTSD(_glthread_TSD *tsd, void *ptr) |
| { |
| if (tsd->initMagic != (int) INIT_MAGIC) { |
| _glthread_InitTSD(tsd); |
| } |
| if (pthread_setspecific(tsd->key, ptr) != 0) { |
| perror(SET_TSD_ERROR); |
| exit(-1); |
| } |
| } |
| |
| #endif /* PTHREADS */ |
| |
| |
| |
| /* |
| * Solaris/Unix International Threads -- Use only if POSIX threads |
| * aren't available on your Unix platform. Solaris 2.[34] are examples |
| * of platforms where this is the case. Be sure to use -mt and/or |
| * -D_REENTRANT when compiling. |
| */ |
| #ifdef SOLARIS_THREADS |
| #define USE_LOCK_FOR_KEY /* undef this to try a version without |
| lock for the global key... */ |
| |
| unsigned long |
| _glthread_GetID(void) |
| { |
| abort(); /* XXX not implemented yet */ |
| return (unsigned long) 0; |
| } |
| |
| |
| void |
| _glthread_InitTSD(_glthread_TSD *tsd) |
| { |
| if ((errno = mutex_init(&tsd->keylock, 0, NULL)) != 0 || |
| (errno = thr_keycreate(&(tsd->key), free)) != 0) { |
| perror(INIT_TSD_ERROR); |
| exit(-1); |
| } |
| tsd->initMagic = INIT_MAGIC; |
| } |
| |
| |
| void * |
| _glthread_GetTSD(_glthread_TSD *tsd) |
| { |
| void* ret; |
| if (tsd->initMagic != INIT_MAGIC) { |
| _glthread_InitTSD(tsd); |
| } |
| #ifdef USE_LOCK_FOR_KEY |
| mutex_lock(&tsd->keylock); |
| thr_getspecific(tsd->key, &ret); |
| mutex_unlock(&tsd->keylock); |
| #else |
| if ((errno = thr_getspecific(tsd->key, &ret)) != 0) { |
| perror(GET_TSD_ERROR); |
| exit(-1); |
| } |
| #endif |
| return ret; |
| } |
| |
| |
| void |
| _glthread_SetTSD(_glthread_TSD *tsd, void *ptr) |
| { |
| if (tsd->initMagic != INIT_MAGIC) { |
| _glthread_InitTSD(tsd); |
| } |
| if ((errno = thr_setspecific(tsd->key, ptr)) != 0) { |
| perror(SET_TSD_ERROR); |
| exit(-1); |
| } |
| } |
| |
| #undef USE_LOCK_FOR_KEY |
| #endif /* SOLARIS_THREADS */ |
| |
| |
| |
| /* |
| * Win32 Threads. The only available option for Windows 95/NT. |
| * Be sure that you compile using the Multithreaded runtime, otherwise |
| * bad things will happen. |
| */ |
| #ifdef WIN32_THREADS |
| |
| void FreeTSD(_glthread_TSD *p) |
| { |
| if (p->initMagic==INIT_MAGIC) { |
| TlsFree(p->key); |
| p->initMagic=0; |
| } |
| } |
| |
| void InsteadOf_exit(int nCode) |
| { |
| DWORD dwErr=GetLastError(); |
| } |
| |
| unsigned long |
| _glthread_GetID(void) |
| { |
| return GetCurrentThreadId(); |
| } |
| |
| |
| void |
| _glthread_InitTSD(_glthread_TSD *tsd) |
| { |
| tsd->key = TlsAlloc(); |
| if (tsd->key == TLS_OUT_OF_INDEXES) { |
| perror("Mesa:_glthread_InitTSD"); |
| InsteadOf_exit(-1); |
| } |
| tsd->initMagic = INIT_MAGIC; |
| } |
| |
| |
| void * |
| _glthread_GetTSD(_glthread_TSD *tsd) |
| { |
| if (tsd->initMagic != INIT_MAGIC) { |
| _glthread_InitTSD(tsd); |
| } |
| return TlsGetValue(tsd->key); |
| } |
| |
| |
| void |
| _glthread_SetTSD(_glthread_TSD *tsd, void *ptr) |
| { |
| /* the following code assumes that the _glthread_TSD has been initialized |
| to zero at creation */ |
| if (tsd->initMagic != INIT_MAGIC) { |
| _glthread_InitTSD(tsd); |
| } |
| if (TlsSetValue(tsd->key, ptr) == 0) { |
| perror("Mesa:_glthread_SetTSD"); |
| InsteadOf_exit(-1); |
| } |
| } |
| |
| #endif /* WIN32_THREADS */ |
| |
| |
| |
| /* |
| * XFree86 has its own thread wrapper, Xthreads.h |
| * We wrap it again for GL. |
| */ |
| #ifdef USE_XTHREADS |
| |
| unsigned long |
| _glthread_GetID(void) |
| { |
| return (unsigned long) xthread_self(); |
| } |
| |
| |
| void |
| _glthread_InitTSD(_glthread_TSD *tsd) |
| { |
| if (xthread_key_create(&tsd->key, NULL) != 0) { |
| perror(INIT_TSD_ERROR); |
| exit(-1); |
| } |
| tsd->initMagic = INIT_MAGIC; |
| } |
| |
| |
| void * |
| _glthread_GetTSD(_glthread_TSD *tsd) |
| { |
| void *ptr; |
| if (tsd->initMagic != INIT_MAGIC) { |
| _glthread_InitTSD(tsd); |
| } |
| xthread_get_specific(tsd->key, &ptr); |
| return ptr; |
| } |
| |
| |
| void |
| _glthread_SetTSD(_glthread_TSD *tsd, void *ptr) |
| { |
| if (tsd->initMagic != INIT_MAGIC) { |
| _glthread_InitTSD(tsd); |
| } |
| xthread_set_specific(tsd->key, ptr); |
| } |
| |
| #endif /* XTHREAD */ |
| |
| |
| |
| /* |
| * BeOS threads |
| */ |
| #ifdef BEOS_THREADS |
| |
| unsigned long |
| _glthread_GetID(void) |
| { |
| return (unsigned long) find_thread(NULL); |
| } |
| |
| void |
| _glthread_InitTSD(_glthread_TSD *tsd) |
| { |
| tsd->key = tls_allocate(); |
| tsd->initMagic = INIT_MAGIC; |
| } |
| |
| void * |
| _glthread_GetTSD(_glthread_TSD *tsd) |
| { |
| if (tsd->initMagic != (int) INIT_MAGIC) { |
| _glthread_InitTSD(tsd); |
| } |
| return tls_get(tsd->key); |
| } |
| |
| void |
| _glthread_SetTSD(_glthread_TSD *tsd, void *ptr) |
| { |
| if (tsd->initMagic != (int) INIT_MAGIC) { |
| _glthread_InitTSD(tsd); |
| } |
| tls_set(tsd->key, ptr); |
| } |
| |
| #endif /* BEOS_THREADS */ |
| |
| |
| |
| #else /* THREADS */ |
| |
| |
| /* |
| * no-op functions |
| */ |
| |
| unsigned long |
| _glthread_GetID(void) |
| { |
| return 0; |
| } |
| |
| |
| void |
| _glthread_InitTSD(_glthread_TSD *tsd) |
| { |
| (void) tsd; |
| } |
| |
| |
| void * |
| _glthread_GetTSD(_glthread_TSD *tsd) |
| { |
| (void) tsd; |
| return NULL; |
| } |
| |
| |
| void |
| _glthread_SetTSD(_glthread_TSD *tsd, void *ptr) |
| { |
| (void) tsd; |
| (void) ptr; |
| } |
| |
| |
| #endif /* THREADS */ |