Home | History | Annotate | Download | only in mapi
      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