Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included
  14.  * in all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  17.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  20.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  21.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  22.  * 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.  * 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.