1 /* Basic platform-independent macro definitions for mutexes and
3 Copyright (C) 1996,1997,1998,2000,2001,2002 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5 Contributed by Wolfram Gloger <wg@malloc.de>, 2001.
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.
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.
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
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. */
30 #undef thread_atfork_static
32 #if defined(_LIBC) /* The GNU C library, a special case of Posix threads */
34 #include <bits/libc-lock.h>
36 #ifdef PTHREAD_MUTEX_INITIALIZER
38 __libc_lock_define (typedef, mutex_t
)
40 #if defined(LLL_LOCK_INITIALIZER) && !defined(NOT_IN_libc)
44 #define mutex_init(m) __libc_lock_init (*(m))
45 #define mutex_lock(m) __libc_lock_lock (*(m))
46 #define mutex_trylock(m) __libc_lock_trylock (*(m))
47 #define mutex_unlock(m) __libc_lock_unlock (*(m))
49 #elif defined(__libc_maybe_call2)
51 #define mutex_init(m) \
52 __libc_maybe_call2 (pthread_mutex_init, (m, NULL), (*(int *)(m) = 0))
53 #define mutex_lock(m) \
54 __libc_maybe_call2 (pthread_mutex_lock, (m), ((*(int *)(m) = 1), 0))
55 #define mutex_trylock(m) \
56 __libc_maybe_call2 (pthread_mutex_trylock, (m), \
57 (*(int *)(m) ? 1 : ((*(int *)(m) = 1), 0)))
58 #define mutex_unlock(m) \
59 __libc_maybe_call2 (pthread_mutex_unlock, (m), (*(int *)(m) = 0))
63 #define mutex_init(m) \
64 __libc_maybe_call (__pthread_mutex_init, (m, NULL), (*(int *)(m) = 0))
65 #define mutex_lock(m) \
66 __libc_maybe_call (__pthread_mutex_lock, (m), ((*(int *)(m) = 1), 0))
67 #define mutex_trylock(m) \
68 __libc_maybe_call (__pthread_mutex_trylock, (m), \
69 (*(int *)(m) ? 1 : ((*(int *)(m) = 1), 0)))
70 #define mutex_unlock(m) \
71 __libc_maybe_call (__pthread_mutex_unlock, (m), (*(int *)(m) = 0))
75 /* This is defined by newer gcc version unique for each module. */
76 extern void *__dso_handle
__attribute__ ((__weak__
));
81 # define thread_atfork(prepare, parent, child) \
82 __register_atfork (prepare, parent, child, __dso_handle)
84 # define thread_atfork(prepare, parent, child) \
85 __register_atfork (prepare, parent, child, \
86 &__dso_handle == NULL ? NULL : __dso_handle)
89 #elif defined(MUTEX_INITIALIZER)
90 /* Assume hurd, with cthreads */
92 /* Cthreads `mutex_t' is a pointer to a mutex, and malloc wants just the
95 #define mutex_t struct mutex
98 #define mutex_init(m) (__mutex_init(m), 0)
101 #define mutex_lock(m) (__mutex_lock(m), 0)
104 #define mutex_unlock(m) (__mutex_unlock(m), 0)
106 #define mutex_trylock(m) (!__mutex_trylock(m))
108 #define thread_atfork(prepare, parent, child) do {} while(0)
109 #define thread_atfork_static(prepare, parent, child) \
110 text_set_element(_hurd_fork_prepare_hook, prepare); \
111 text_set_element(_hurd_fork_parent_hook, parent); \
112 text_set_element(_hurd_fork_child_hook, child);
114 /* No we're *not* using pthreads. */
115 #define __pthread_initialize ((void (*)(void))0)
121 #endif /* MUTEX_INITIALIZER && PTHREAD_MUTEX_INITIALIZER */
125 /* thread specific data for glibc */
127 #include <bits/libc-tsd.h>
129 typedef int tsd_key_t
[1]; /* no key data structure, libc magic does it */
130 __libc_tsd_define (static, MALLOC
) /* declaration/common definition */
131 #define tsd_key_create(key, destr) ((void) (key))
132 #define tsd_setspecific(key, data) __libc_tsd_set (MALLOC, (data))
133 #define tsd_getspecific(key, vptr) ((vptr) = __libc_tsd_get (MALLOC))
137 #elif defined(USE_PTHREADS) /* Posix threads */
142 #if (defined __i386__ || defined __x86_64__) && defined __GNUC__ && \
143 !defined USE_NO_SPINLOCKS
147 /* Use fast inline spinlocks. */
149 volatile unsigned int lock
;
153 #define mutex_init(m) ((m)->lock = 0)
154 static inline int mutex_lock(mutex_t
*m
) {
161 : "=r"(r
), "=m"(m
->lock
)
162 : "0"(1), "m"(m
->lock
)
171 tm
.tv_nsec
= 2000001;
172 nanosleep(&tm
, NULL
);
177 static inline int mutex_trylock(mutex_t
*m
) {
182 : "=r"(r
), "=m"(m
->lock
)
183 : "0"(1), "m"(m
->lock
)
187 static inline int mutex_unlock(mutex_t
*m
) {
189 __asm
__volatile ("" : "=m" (m
->lock
) : "0" (m
->lock
));
195 /* Normal pthread mutex. */
196 typedef pthread_mutex_t mutex_t
;
198 #define mutex_init(m) pthread_mutex_init(m, NULL)
199 #define mutex_lock(m) pthread_mutex_lock(m)
200 #define mutex_trylock(m) pthread_mutex_trylock(m)
201 #define mutex_unlock(m) pthread_mutex_unlock(m)
203 #endif /* (__i386__ || __x86_64__) && __GNUC__ && !USE_NO_SPINLOCKS */
205 /* thread specific data */
206 #if defined(__sgi) || defined(USE_TSD_DATA_HACK)
208 /* Hack for thread-specific data, e.g. on Irix 6.x. We can't use
209 pthread_setspecific because that function calls malloc() itself.
210 The hack only works when pthread_t can be converted to an integral
213 typedef void *tsd_key_t
[256];
214 #define tsd_key_create(key, destr) do { \
216 for(i=0; i<256; i++) (*key)[i] = 0; \
218 #define tsd_setspecific(key, data) \
219 (key[(unsigned)pthread_self() % 256] = (data))
220 #define tsd_getspecific(key, vptr) \
221 (vptr = key[(unsigned)pthread_self() % 256])
225 typedef pthread_key_t tsd_key_t
;
227 #define tsd_key_create(key, destr) pthread_key_create(key, destr)
228 #define tsd_setspecific(key, data) pthread_setspecific(key, data)
229 #define tsd_getspecific(key, vptr) (vptr = pthread_getspecific(key))
234 #define thread_atfork(prepare, parent, child) \
235 pthread_atfork(prepare, parent, child)
237 #elif USE_THR /* Solaris threads */
241 #define mutex_init(m) mutex_init(m, USYNC_THREAD, NULL)
244 * Hack for thread-specific data on Solaris. We can't use thr_setspecific
245 * because that function calls malloc() itself.
247 typedef void *tsd_key_t
[256];
248 #define tsd_key_create(key, destr) do { \
250 for(i=0; i<256; i++) (*key)[i] = 0; \
252 #define tsd_setspecific(key, data) (key[(unsigned)thr_self() % 256] = (data))
253 #define tsd_getspecific(key, vptr) (vptr = key[(unsigned)thr_self() % 256])
255 #define thread_atfork(prepare, parent, child) do {} while(0)
257 #elif USE_SPROC /* SGI sproc() threads */
259 #include <sys/wait.h>
260 #include <sys/types.h>
261 #include <sys/prctl.h>
262 #include <abi_mutex.h>
264 typedef abilock_t mutex_t
;
266 #define mutex_init(m) init_lock(m)
267 #define mutex_lock(m) (spin_lock(m), 0)
268 #define mutex_trylock(m) acquire_lock(m)
269 #define mutex_unlock(m) release_lock(m)
271 typedef int tsd_key_t
;
273 #define tsd_key_create(key, destr) ((*key) = tsd_key_next++)
274 #define tsd_setspecific(key, data) (((void **)(&PRDA->usr_prda))[key] = data)
275 #define tsd_getspecific(key, vptr) (vptr = ((void **)(&PRDA->usr_prda))[key])
277 #define thread_atfork(prepare, parent, child) do {} while(0)
279 #else /* no _LIBC or USE_... are defined */
283 #endif /* defined(_LIBC) */
285 #ifdef NO_THREADS /* No threads, provide dummy macros */
287 /* The mutex functions used to do absolutely nothing, i.e. lock,
288 trylock and unlock would always just return 0. However, even
289 without any concurrently active threads, a mutex can be used
290 legitimately as an `in use' flag. To make the code that is
291 protected by a mutex async-signal safe, these macros would have to
292 be based on atomic test-and-set operations, for example. */
295 #define mutex_init(m) (*(m) = 0)
296 #define mutex_lock(m) ((*(m) = 1), 0)
297 #define mutex_trylock(m) (*(m) ? 1 : ((*(m) = 1), 0))
298 #define mutex_unlock(m) (*(m) = 0)
300 typedef void *tsd_key_t
;
301 #define tsd_key_create(key, destr) do {} while(0)
302 #define tsd_setspecific(key, data) ((key) = (data))
303 #define tsd_getspecific(key, vptr) (vptr = (key))
305 #define thread_atfork(prepare, parent, child) do {} while(0)
307 #endif /* defined(NO_THREADS) */
309 #endif /* !defined(_THREAD_M_H) */