1 /* 2 * Copyright (c) 2013, NVIDIA CORPORATION. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and/or associated documentation files (the 6 * "Materials"), to deal in the Materials without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sublicense, and/or sell copies of the Materials, and to 9 * permit persons to whom the Materials are furnished to do so, subject to 10 * the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included 13 * unaltered in all copies or substantial portions of the Materials. 14 * Any additions, deletions, or changes to the original source files 15 * must be clearly indicated in accompanying documentation. 16 * 17 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 24 */ 25 26 #ifndef __GLVND_PTHREAD_H__ 27 #define __GLVND_PTHREAD_H__ 28 29 #include <pthread.h> 30 #include <errno.h> 31 32 /* 33 * pthread wrapper functions used to prevent the vendor-neutral library from 34 * needing to link against pthreads. The locking functions are no-ops unless 35 * the library is linked against pthreads. 36 * This wrapper code is also utilized by some unit tests which dynamically load 37 * pthreads. 38 */ 39 40 /* 41 * Since the underlying pthreads types are opaque, to correctly handle the 42 * single-threaded case we need to wrap some of these types with metadata. For 43 * consistency, we typedef all pthreads types, including those which don't need 44 * to be wrapped. 45 */ 46 typedef pthread_mutex_t glvnd_mutex_t; 47 typedef pthread_mutexattr_t glvnd_mutexattr_t; 48 49 #if defined(HAVE_PTHREAD_RWLOCK_T) 50 typedef pthread_rwlock_t glvnd_rwlock_t; 51 typedef pthread_rwlockattr_t glvnd_rwlockattr_t; 52 #define GLVND_RWLOCK_INITIALIZER PTHREAD_RWLOCK_INITIALIZER 53 #else 54 typedef pthread_mutex_t glvnd_rwlock_t; 55 typedef pthread_mutexattr_t glvnd_rwlockattr_t; 56 #define GLVND_RWLOCK_INITIALIZER PTHREAD_MUTEX_INITIALIZER 57 #endif 58 59 #define GLVND_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 60 61 typedef struct _glvnd_once_t { 62 pthread_once_t once; 63 int done; 64 } glvnd_once_t; 65 66 #define GLVND_ONCE_INIT { PTHREAD_ONCE_INIT, 0 } 67 68 typedef struct _glvnd_thread_t { 69 pthread_t tid; 70 int valid; 71 } glvnd_thread_t; 72 73 #define GLVND_THREAD_NULL_INIT {} 74 75 typedef pthread_attr_t glvnd_thread_attr_t; 76 77 typedef union { 78 pthread_key_t key; 79 void **data; 80 } glvnd_key_t; 81 #define GLVND_KEYS_MAX PTHREAD_KEYS_MAX 82 83 /*! 84 * Struct defining the wrapper functions implemented by this library. 85 * The implementations will differ depending on whether we're in the 86 * singlethreaded case. 87 */ 88 typedef struct GLVNDPthreadFuncsRec { 89 /* Should never be used by libglvnd. May be used by some unit tests */ 90 int (*create)(glvnd_thread_t *thread, const glvnd_thread_attr_t *attr, 91 void *(*start_routine) (void *), void *arg); 92 int (*join)(glvnd_thread_t thread, void **retval); 93 94 /* Only used in debug/tracing code */ 95 glvnd_thread_t (*self)(void); 96 int (*equal)(glvnd_thread_t t1, glvnd_thread_t t2); 97 98 /* Locking primitives */ 99 int (*mutex_init)(glvnd_mutex_t *mutex, const glvnd_mutexattr_t *attr); 100 int (*mutex_destroy)(glvnd_mutex_t *mutex); 101 int (*mutex_lock)(glvnd_mutex_t *mutex); 102 int (*mutex_trylock)(glvnd_mutex_t *mutex); 103 int (*mutex_unlock)(glvnd_mutex_t *mutex); 104 105 int (* mutexattr_init) (glvnd_mutexattr_t *attr); 106 int (* mutexattr_destroy) (glvnd_mutexattr_t *attr); 107 int (* mutexattr_settype) (glvnd_mutexattr_t *attr, int kind); 108 109 int (*rwlock_init)(glvnd_rwlock_t *rwlock, const glvnd_rwlockattr_t *attr); 110 int (*rwlock_destroy)(glvnd_rwlock_t *rwlock); 111 int (*rwlock_rdlock)(glvnd_rwlock_t *rwlock); 112 int (*rwlock_wrlock)(glvnd_rwlock_t *rwlock); 113 int (*rwlock_tryrdlock)(glvnd_rwlock_t *rwlock); 114 int (*rwlock_trywrlock)(glvnd_rwlock_t *rwlock); 115 int (*rwlock_unlock)(glvnd_rwlock_t *rwlock); 116 117 /* Other used functions */ 118 int (*once)(glvnd_once_t *once_control, void (*init_routine)(void)); 119 120 /* 121 * TSD key management. Used to handle the corner case when a thread 122 * is destroyed with a context current. 123 */ 124 int (*key_create)(glvnd_key_t *key, void (*destr_function)(void *)); 125 int (*key_delete)(glvnd_key_t key); 126 int (*setspecific)(glvnd_key_t key, const void *p); 127 void *(*getspecific)(glvnd_key_t key); 128 129 /* 130 * Are we single-threaded? 131 */ 132 int is_singlethreaded; 133 } GLVNDPthreadFuncs; 134 135 /** 136 * A NULL glvnd_thread_t value. This is mainly useful as something to pass to 137 * \c GLVNDPthreadFuncs.equal. To initialize a glvnd_thread_t variable, use 138 * \c GLVND_THREAD_NULL_INIT. 139 */ 140 extern const glvnd_thread_t GLVND_THREAD_NULL; 141 142 /** 143 * The function table with all of the pthreads function pointers. This table 144 * is initialized by \c glvndSetupPthreads. 145 */ 146 extern GLVNDPthreadFuncs __glvndPthreadFuncs; 147 148 /*! 149 * \brief Sets up pthreads wrappers. 150 * 151 * This fills the given function pointer table with the appropriate wrapper 152 * functions, using the passed-in handle to look for pthreads functions. This 153 * should only be called once on initialization. 154 */ 155 void glvndSetupPthreads(void); 156 157 158 159 #endif // __GLVND_PTHREAD_H__ 160