1 /* Basic platform-independent macro definitions for mutexes and 2 thread-specific data. 3 Copyright (C) 1996, 1997, 1998, 2000 Free Software Foundation, Inc. 4 This file is part of the GNU C Library. 5 Contributed by Wolfram Gloger <wmglo@dent.med.uni-muenchen.de>, 1996. 6 7 The GNU C Library is free software; you can redistribute it and/or 8 modify it under the terms of the GNU Lesser General Public 9 License as published by the Free Software Foundation; either 10 version 2.1 of the License, or (at your option) any later version. 11 12 The GNU C Library is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 Lesser General Public License for more details. 16 17 You should have received a copy of the GNU Lesser General Public 18 License along with the GNU C Library; if not, write to the Free 19 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 20 02111-1307 USA. */ 21 22 /* $Id: thread-m.h 135 2004-10-08 10:01:07Z oyvind $ 23 One out of _LIBC, USE_PTHREADS, USE_THR or USE_SPROC should be 24 defined, otherwise the token NO_THREADS and dummy implementations 25 of the macros will be defined. */ 26 27 #ifndef _THREAD_M_H 28 #define _THREAD_M_H 29 30 #undef thread_atfork_static 31 32 #if defined(_LIBC) /* The GNU C library, a special case of Posix threads */ 33 34 #include <bits/libc-lock.h> 35 36 #ifdef PTHREAD_MUTEX_INITIALIZER 37 38 typedef pthread_t thread_id; 39 40 /* mutex */ 41 typedef pthread_mutex_t mutex_t; 42 43 #define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 44 45 /* Even if not linking with libpthread, ensure usability of mutex as 46 an `in use' flag, see also the NO_THREADS case below. Assume 47 pthread_mutex_t is at least one int wide. */ 48 49 #define mutex_init(m) \ 50 (__pthread_mutex_init != NULL \ 51 ? __pthread_mutex_init (m, NULL) : (*(int *)(m) = 0)) 52 #define mutex_lock(m) \ 53 (__pthread_mutex_lock != NULL \ 54 ? __pthread_mutex_lock (m) : ((*(int *)(m) = 1), 0)) 55 #define mutex_trylock(m) \ 56 (__pthread_mutex_trylock != NULL \ 57 ? __pthread_mutex_trylock (m) : (*(int *)(m) ? 1 : ((*(int *)(m) = 1), 0))) 58 #define mutex_unlock(m) \ 59 (__pthread_mutex_unlock != NULL \ 60 ? __pthread_mutex_unlock (m) : (*(int*)(m) = 0)) 61 62 #define thread_atfork(prepare, parent, child) \ 63 (__pthread_atfork != NULL ? __pthread_atfork(prepare, parent, child) : 0) 64 65 #elif defined(MUTEX_INITIALIZER) 66 /* Assume hurd, with cthreads */ 67 68 /* Cthreads `mutex_t' is a pointer to a mutex, and malloc wants just the 69 mutex itself. */ 70 #undef mutex_t 71 #define mutex_t struct mutex 72 73 #undef mutex_init 74 #define mutex_init(m) (__mutex_init(m), 0) 75 76 #undef mutex_lock 77 #define mutex_lock(m) (__mutex_lock(m), 0) 78 79 #undef mutex_unlock 80 #define mutex_unlock(m) (__mutex_unlock(m), 0) 81 82 #define mutex_trylock(m) (!__mutex_trylock(m)) 83 84 #define thread_atfork(prepare, parent, child) do {} while(0) 85 #define thread_atfork_static(prepare, parent, child) \ 86 text_set_element(_hurd_fork_prepare_hook, prepare); \ 87 text_set_element(_hurd_fork_parent_hook, parent); \ 88 text_set_element(_hurd_fork_child_hook, child); 89 90 /* No we're *not* using pthreads. */ 91 #define __pthread_initialize ((void (*)(void))0) 92 93 #else 94 95 #define NO_THREADS 96 97 #endif /* MUTEX_INITIALIZER && PTHREAD_MUTEX_INITIALIZER */ 98 99 #ifndef NO_THREADS 100 101 /* thread specific data for glibc */ 102 103 #include <libc-tsd.h> 104 105 typedef int tsd_key_t[1]; /* no key data structure, libc magic does it */ 106 __libc_tsd_define (, MALLOC) /* declaration/common definition */ 107 #define tsd_key_create(key, destr) ((void) (key)) 108 #define tsd_setspecific(key, data) __libc_tsd_set (MALLOC, (data)) 109 #define tsd_getspecific(key, vptr) ((vptr) = __libc_tsd_get (MALLOC)) 110 111 #endif 112 113 #elif defined(USE_PTHREADS) /* Posix threads */ 114 115 #include <pthread.h> 116 117 typedef pthread_t thread_id; 118 119 /* mutex */ 120 typedef pthread_mutex_t mutex_t; 121 122 #define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 123 #define mutex_init(m) pthread_mutex_init(m, NULL) 124 #define mutex_lock(m) pthread_mutex_lock(m) 125 #define mutex_trylock(m) pthread_mutex_trylock(m) 126 #define mutex_unlock(m) pthread_mutex_unlock(m) 127 128 /* thread specific data */ 129 #if defined(__sgi) || defined(USE_TSD_DATA_HACK) 130 131 /* Hack for thread-specific data, e.g. on Irix 6.x. We can't use 132 pthread_setspecific because that function calls malloc() itself. 133 The hack only works when pthread_t can be converted to an integral 134 type. */ 135 136 typedef void *tsd_key_t[256]; 137 #define tsd_key_create(key, destr) do { \ 138 int i; \ 139 for(i=0; i<256; i++) (*key)[i] = 0; \ 140 } while(0) 141 #define tsd_setspecific(key, data) \ 142 (key[(unsigned)pthread_self() % 256] = (data)) 143 #define tsd_getspecific(key, vptr) \ 144 (vptr = key[(unsigned)pthread_self() % 256]) 145 146 #else 147 148 typedef pthread_key_t tsd_key_t; 149 150 #define tsd_key_create(key, destr) pthread_key_create(key, destr) 151 #define tsd_setspecific(key, data) pthread_setspecific(key, data) 152 #define tsd_getspecific(key, vptr) (vptr = pthread_getspecific(key)) 153 154 #endif 155 156 /* at fork */ 157 #define thread_atfork(prepare, parent, child) \ 158 pthread_atfork(prepare, parent, child) 159 160 #elif USE_THR /* Solaris threads */ 161 162 #include <thread.h> 163 164 typedef thread_t thread_id; 165 166 #define MUTEX_INITIALIZER { 0 } 167 #define mutex_init(m) mutex_init(m, USYNC_THREAD, NULL) 168 169 /* 170 * Hack for thread-specific data on Solaris. We can't use thr_setspecific 171 * because that function calls malloc() itself. 172 */ 173 typedef void *tsd_key_t[256]; 174 #define tsd_key_create(key, destr) do { \ 175 int i; \ 176 for(i=0; i<256; i++) (*key)[i] = 0; \ 177 } while(0) 178 #define tsd_setspecific(key, data) (key[(unsigned)thr_self() % 256] = (data)) 179 #define tsd_getspecific(key, vptr) (vptr = key[(unsigned)thr_self() % 256]) 180 181 #define thread_atfork(prepare, parent, child) do {} while(0) 182 183 #elif USE_SPROC /* SGI sproc() threads */ 184 185 #include <sys/wait.h> 186 #include <sys/types.h> 187 #include <sys/prctl.h> 188 #include <abi_mutex.h> 189 190 typedef int thread_id; 191 192 typedef abilock_t mutex_t; 193 194 #define MUTEX_INITIALIZER { 0 } 195 #define mutex_init(m) init_lock(m) 196 #define mutex_lock(m) (spin_lock(m), 0) 197 #define mutex_trylock(m) acquire_lock(m) 198 #define mutex_unlock(m) release_lock(m) 199 200 typedef int tsd_key_t; 201 int tsd_key_next; 202 #define tsd_key_create(key, destr) ((*key) = tsd_key_next++) 203 #define tsd_setspecific(key, data) (((void **)(&PRDA->usr_prda))[key] = data) 204 #define tsd_getspecific(key, vptr) (vptr = ((void **)(&PRDA->usr_prda))[key]) 205 206 #define thread_atfork(prepare, parent, child) do {} while(0) 207 208 #else /* no _LIBC or USE_... are defined */ 209 210 #define NO_THREADS 211 212 #endif /* defined(_LIBC) */ 213 214 #ifdef NO_THREADS /* No threads, provide dummy macros */ 215 216 typedef int thread_id; 217 218 /* The mutex functions used to do absolutely nothing, i.e. lock, 219 trylock and unlock would always just return 0. However, even 220 without any concurrently active threads, a mutex can be used 221 legitimately as an `in use' flag. To make the code that is 222 protected by a mutex async-signal safe, these macros would have to 223 be based on atomic test-and-set operations, for example. */ 224 typedef int mutex_t; 225 226 #define MUTEX_INITIALIZER 0 227 #define mutex_init(m) (*(m) = 0) 228 #define mutex_lock(m) ((*(m) = 1), 0) 229 #define mutex_trylock(m) (*(m) ? 1 : ((*(m) = 1), 0)) 230 #define mutex_unlock(m) (*(m) = 0) 231 232 typedef void *tsd_key_t; 233 #define tsd_key_create(key, destr) do {} while(0) 234 #define tsd_setspecific(key, data) ((key) = (data)) 235 #define tsd_getspecific(key, vptr) (vptr = (key)) 236 237 #define thread_atfork(prepare, parent, child) do {} while(0) 238 239 #endif /* defined(NO_THREADS) */ 240 241 #endif /* !defined(_THREAD_M_H) */ 242