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