Change prototype of test_in_mod1.
[kopensolaris-gnu/glibc.git] / malloc / thread-m.h
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.
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$
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 <atomic.h>
35 #include <bits/libc-lock.h>
36
37 #ifdef PTHREAD_MUTEX_INITIALIZER
38
39 __libc_lock_define (typedef, mutex_t)
40
41 #if defined(LLL_LOCK_INITIALIZER) && !defined(NOT_IN_libc)
42
43 /* Assume NPTL.  */
44
45 #define mutex_init(m)           __libc_lock_init (*(m))
46 #define mutex_lock(m)           __libc_lock_lock (*(m))
47 #define mutex_trylock(m)        __libc_lock_trylock (*(m))
48 #define mutex_unlock(m)         __libc_lock_unlock (*(m))
49
50 #elif defined(__libc_maybe_call2)
51
52 #define mutex_init(m)           \
53   __libc_maybe_call2 (pthread_mutex_init, (m, NULL), (*(int *)(m) = 0))
54 #define mutex_lock(m)           \
55   __libc_maybe_call2 (pthread_mutex_lock, (m), ((*(int *)(m) = 1), 0))
56 #define mutex_trylock(m)        \
57   __libc_maybe_call2 (pthread_mutex_trylock, (m), \
58                       (*(int *)(m) ? 1 : ((*(int *)(m) = 1), 0)))
59 #define mutex_unlock(m)         \
60   __libc_maybe_call2 (pthread_mutex_unlock, (m), (*(int *)(m) = 0))
61
62 #else
63
64 #define mutex_init(m)           \
65   __libc_maybe_call (__pthread_mutex_init, (m, NULL), (*(int *)(m) = 0))
66 #define mutex_lock(m)           \
67   __libc_maybe_call (__pthread_mutex_lock, (m), ((*(int *)(m) = 1), 0))
68 #define mutex_trylock(m)        \
69   __libc_maybe_call (__pthread_mutex_trylock, (m), \
70                      (*(int *)(m) ? 1 : ((*(int *)(m) = 1), 0)))
71 #define mutex_unlock(m)         \
72   __libc_maybe_call (__pthread_mutex_unlock, (m), (*(int *)(m) = 0))
73
74 #endif
75
76 /* This is defined by newer gcc version unique for each module.  */
77 extern void *__dso_handle __attribute__ ((__weak__));
78
79 #include <fork.h>
80
81 #ifdef SHARED
82 # define thread_atfork(prepare, parent, child) \
83    __register_atfork (prepare, parent, child, __dso_handle)
84 #else
85 # define thread_atfork(prepare, parent, child) \
86    __register_atfork (prepare, parent, child,                                 \
87                       &__dso_handle == NULL ? NULL : __dso_handle)
88 #endif
89
90 #elif defined(MUTEX_INITIALIZER)
91 /* Assume hurd, with cthreads */
92
93 /* Cthreads `mutex_t' is a pointer to a mutex, and malloc wants just the
94    mutex itself.  */
95 #undef mutex_t
96 #define mutex_t struct mutex
97
98 #undef mutex_init
99 #define mutex_init(m) (__mutex_init(m), 0)
100
101 #undef mutex_lock
102 #define mutex_lock(m) (__mutex_lock(m), 0)
103
104 #undef mutex_unlock
105 #define mutex_unlock(m) (__mutex_unlock(m), 0)
106
107 #define mutex_trylock(m) (!__mutex_trylock(m))
108
109 #define thread_atfork(prepare, parent, child) do {} while(0)
110 #define thread_atfork_static(prepare, parent, child) \
111  text_set_element(_hurd_fork_prepare_hook, prepare); \
112  text_set_element(_hurd_fork_parent_hook, parent); \
113  text_set_element(_hurd_fork_child_hook, child);
114
115 /* No we're *not* using pthreads.  */
116 #define __pthread_initialize ((void (*)(void))0)
117
118 #else
119
120 #define NO_THREADS
121
122 #endif /* MUTEX_INITIALIZER && PTHREAD_MUTEX_INITIALIZER */
123
124 #ifndef NO_THREADS
125
126 /* thread specific data for glibc */
127
128 #include <bits/libc-tsd.h>
129
130 typedef int tsd_key_t[1];       /* no key data structure, libc magic does it */
131 __libc_tsd_define (static, MALLOC)      /* declaration/common definition */
132 #define tsd_key_create(key, destr)      ((void) (key))
133 #define tsd_setspecific(key, data)      __libc_tsd_set (MALLOC, (data))
134 #define tsd_getspecific(key, vptr)      ((vptr) = __libc_tsd_get (MALLOC))
135
136 #endif
137
138 #elif defined(USE_PTHREADS) /* Posix threads */
139
140 #include <pthread.h>
141
142 /* mutex */
143 #if (defined __i386__ || defined __x86_64__) && defined __GNUC__ && \
144     !defined USE_NO_SPINLOCKS
145
146 #include <time.h>
147
148 /* Use fast inline spinlocks.  */
149 typedef struct {
150   volatile unsigned int lock;
151   int pad0_;
152 } mutex_t;
153
154 #define mutex_init(m)              ((m)->lock = 0)
155 static inline int mutex_lock(mutex_t *m) {
156   int cnt = 0, r;
157   struct timespec tm;
158
159   for(;;) {
160     __asm__ __volatile__
161       ("xchgl %0, %1"
162        : "=r"(r), "=m"(m->lock)
163        : "0"(1), "m"(m->lock)
164        : "memory");
165     if(!r)
166       return 0;
167     if(cnt < 50) {
168       sched_yield();
169       cnt++;
170     } else {
171       tm.tv_sec = 0;
172       tm.tv_nsec = 2000001;
173       nanosleep(&tm, NULL);
174       cnt = 0;
175     }
176   }
177 }
178 static inline int mutex_trylock(mutex_t *m) {
179   int r;
180
181   __asm__ __volatile__
182     ("xchgl %0, %1"
183      : "=r"(r), "=m"(m->lock)
184      : "0"(1), "m"(m->lock)
185      : "memory");
186   return r;
187 }
188 static inline int mutex_unlock(mutex_t *m) {
189   m->lock = 0;
190   __asm __volatile ("" : "=m" (m->lock) : "0" (m->lock));
191   return 0;
192 }
193
194 #else
195
196 /* Normal pthread mutex.  */
197 typedef pthread_mutex_t mutex_t;
198
199 #define mutex_init(m)              pthread_mutex_init(m, NULL)
200 #define mutex_lock(m)              pthread_mutex_lock(m)
201 #define mutex_trylock(m)           pthread_mutex_trylock(m)
202 #define mutex_unlock(m)            pthread_mutex_unlock(m)
203
204 #endif /* (__i386__ || __x86_64__) && __GNUC__ && !USE_NO_SPINLOCKS */
205
206 /* thread specific data */
207 #if defined(__sgi) || defined(USE_TSD_DATA_HACK)
208
209 /* Hack for thread-specific data, e.g. on Irix 6.x.  We can't use
210    pthread_setspecific because that function calls malloc() itself.
211    The hack only works when pthread_t can be converted to an integral
212    type. */
213
214 typedef void *tsd_key_t[256];
215 #define tsd_key_create(key, destr) do { \
216   int i; \
217   for(i=0; i<256; i++) (*key)[i] = 0; \
218 } while(0)
219 #define tsd_setspecific(key, data) \
220  (key[(unsigned)pthread_self() % 256] = (data))
221 #define tsd_getspecific(key, vptr) \
222  (vptr = key[(unsigned)pthread_self() % 256])
223
224 #else
225
226 typedef pthread_key_t tsd_key_t;
227
228 #define tsd_key_create(key, destr) pthread_key_create(key, destr)
229 #define tsd_setspecific(key, data) pthread_setspecific(key, data)
230 #define tsd_getspecific(key, vptr) (vptr = pthread_getspecific(key))
231
232 #endif
233
234 /* at fork */
235 #define thread_atfork(prepare, parent, child) \
236                                    pthread_atfork(prepare, parent, child)
237
238 #elif USE_THR /* Solaris threads */
239
240 #include <thread.h>
241
242 #define mutex_init(m)              mutex_init(m, USYNC_THREAD, NULL)
243
244 /*
245  * Hack for thread-specific data on Solaris.  We can't use thr_setspecific
246  * because that function calls malloc() itself.
247  */
248 typedef void *tsd_key_t[256];
249 #define tsd_key_create(key, destr) do { \
250   int i; \
251   for(i=0; i<256; i++) (*key)[i] = 0; \
252 } while(0)
253 #define tsd_setspecific(key, data) (key[(unsigned)thr_self() % 256] = (data))
254 #define tsd_getspecific(key, vptr) (vptr = key[(unsigned)thr_self() % 256])
255
256 #define thread_atfork(prepare, parent, child) do {} while(0)
257
258 #elif USE_SPROC /* SGI sproc() threads */
259
260 #include <sys/wait.h>
261 #include <sys/types.h>
262 #include <sys/prctl.h>
263 #include <abi_mutex.h>
264
265 typedef abilock_t mutex_t;
266
267 #define mutex_init(m)              init_lock(m)
268 #define mutex_lock(m)              (spin_lock(m), 0)
269 #define mutex_trylock(m)           acquire_lock(m)
270 #define mutex_unlock(m)            release_lock(m)
271
272 typedef int tsd_key_t;
273 int tsd_key_next;
274 #define tsd_key_create(key, destr) ((*key) = tsd_key_next++)
275 #define tsd_setspecific(key, data) (((void **)(&PRDA->usr_prda))[key] = data)
276 #define tsd_getspecific(key, vptr) (vptr = ((void **)(&PRDA->usr_prda))[key])
277
278 #define thread_atfork(prepare, parent, child) do {} while(0)
279
280 #else /* no _LIBC or USE_... are defined */
281
282 #define NO_THREADS
283
284 #endif /* defined(_LIBC) */
285
286 #ifdef NO_THREADS /* No threads, provide dummy macros */
287
288 /* The mutex functions used to do absolutely nothing, i.e. lock,
289    trylock and unlock would always just return 0.  However, even
290    without any concurrently active threads, a mutex can be used
291    legitimately as an `in use' flag.  To make the code that is
292    protected by a mutex async-signal safe, these macros would have to
293    be based on atomic test-and-set operations, for example. */
294 typedef int mutex_t;
295
296 #define mutex_init(m)              (*(m) = 0)
297 #define mutex_lock(m)              ((*(m) = 1), 0)
298 #define mutex_trylock(m)           (*(m) ? 1 : ((*(m) = 1), 0))
299 #define mutex_unlock(m)            (*(m) = 0)
300
301 typedef void *tsd_key_t;
302 #define tsd_key_create(key, destr) do {} while(0)
303 #define tsd_setspecific(key, data) ((key) = (data))
304 #define tsd_getspecific(key, vptr) (vptr = (key))
305
306 #define thread_atfork(prepare, parent, child) do {} while(0)
307
308 #endif /* defined(NO_THREADS) */
309
310 #ifndef atomic_full_barrier
311 # define atomic_full_barrier() __asm ("" ::: "memory")
312 #endif
313
314 #ifndef atomic_read_barrier
315 # define atomic_read_barrier() atomic_full_barrier ()
316 #endif
317
318 #ifndef atomic_write_barrier
319 # define atomic_write_barrier() atomic_full_barrier ()
320 #endif
321
322 #endif /* !defined(_THREAD_M_H) */