Support cancellation in librt.
[glibc.git] / malloc / thread-m.h
blobda8bbf36f813fb27f6b48fc2143dd64a62c29e46
1 /* Basic platform-independent macro definitions for mutexes and
2 thread-specific data.
3 Copyright (C) 1996-1998,2000,2001,2002,2003 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
20 02111-1307 USA. */
22 /* $Id$
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. */
27 #ifndef _THREAD_M_H
28 #define _THREAD_M_H
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)
42 /* Assume NPTL. */
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))
61 #else
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))
73 #endif
75 /* This is defined by newer gcc version unique for each module. */
76 extern void *__dso_handle __attribute__ ((__weak__));
78 #include <fork.h>
80 #ifdef SHARED
81 # define thread_atfork(prepare, parent, child) \
82 __register_atfork (prepare, parent, child, __dso_handle)
83 #else
84 # define thread_atfork(prepare, parent, child) \
85 __register_atfork (prepare, parent, child, \
86 &__dso_handle == NULL ? NULL : __dso_handle)
87 #endif
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
93 mutex itself. */
94 #undef mutex_t
95 #define mutex_t struct mutex
97 #undef mutex_init
98 #define mutex_init(m) (__mutex_init(m), 0)
100 #undef mutex_lock
101 #define mutex_lock(m) (__mutex_lock(m), 0)
103 #undef mutex_unlock
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)
117 #else
119 #define NO_THREADS
121 #endif /* MUTEX_INITIALIZER && PTHREAD_MUTEX_INITIALIZER */
123 #ifndef NO_THREADS
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))
135 #endif
137 #elif defined(USE_PTHREADS) /* Posix threads */
139 #include <pthread.h>
141 /* mutex */
142 #if (defined __i386__ || defined __x86_64__) && defined __GNUC__ && \
143 !defined USE_NO_SPINLOCKS
145 #include <time.h>
147 /* Use fast inline spinlocks. */
148 typedef struct {
149 volatile unsigned int lock;
150 int pad0_;
151 } mutex_t;
153 #define mutex_init(m) ((m)->lock = 0)
154 static inline int mutex_lock(mutex_t *m) {
155 int cnt = 0, r;
156 struct timespec tm;
158 for(;;) {
159 __asm__ __volatile__
160 ("xchgl %0, %1"
161 : "=r"(r), "=m"(m->lock)
162 : "0"(1), "m"(m->lock)
163 : "memory");
164 if(!r)
165 return 0;
166 if(cnt < 50) {
167 sched_yield();
168 cnt++;
169 } else {
170 tm.tv_sec = 0;
171 tm.tv_nsec = 2000001;
172 nanosleep(&tm, NULL);
173 cnt = 0;
177 static inline int mutex_trylock(mutex_t *m) {
178 int r;
180 __asm__ __volatile__
181 ("xchgl %0, %1"
182 : "=r"(r), "=m"(m->lock)
183 : "0"(1), "m"(m->lock)
184 : "memory");
185 return r;
187 static inline int mutex_unlock(mutex_t *m) {
188 m->lock = 0;
189 __asm __volatile ("" : "=m" (m->lock) : "0" (m->lock));
190 return 0;
193 #else
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
211 type. */
213 typedef void *tsd_key_t[256];
214 #define tsd_key_create(key, destr) do { \
215 int i; \
216 for(i=0; i<256; i++) (*key)[i] = 0; \
217 } while(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])
223 #else
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))
231 #endif
233 /* at fork */
234 #define thread_atfork(prepare, parent, child) \
235 pthread_atfork(prepare, parent, child)
237 #elif USE_THR /* Solaris threads */
239 #include <thread.h>
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 { \
249 int i; \
250 for(i=0; i<256; i++) (*key)[i] = 0; \
251 } while(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;
272 int tsd_key_next;
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 */
281 #define NO_THREADS
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. */
293 typedef int mutex_t;
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) */