1 /* libc-internal interface for mutex locks.  LinuxThreads version.
2    Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003
3    	Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5 
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public License as
8    published by the Free Software Foundation; either version 2.1 of the
9    License, or (at your option) any later version.
10 
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15 
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; see the file COPYING.LIB.  If
18    not, see <http://www.gnu.org/licenses/>.  */
19 
20 #ifndef _BITS_LIBC_LOCK_H
21 #define _BITS_LIBC_LOCK_H 1
22 
23 #include <pthread.h>
24 
25 #if defined _LIBC && !defined NOT_IN_libc
26 #include <linuxthreads/internals.h>
27 #endif
28 
29 /* Mutex type.  */
30 #if defined(_LIBC) || defined(_IO_MTSAFE_IO)
31 typedef pthread_mutex_t __libc_lock_t;
32 typedef pthread_mutex_t __libc_lock_recursive_t;
33 # ifdef __USE_UNIX98
34 typedef pthread_rwlock_t __libc_rwlock_t;
35 # else
36 typedef struct __libc_rwlock_opaque__ __libc_rwlock_t;
37 # endif
38 typedef __libc_lock_recursive_t __rtld_lock_recursive_t;
39 #else
40 typedef struct __libc_lock_opaque__ __libc_lock_t;
41 typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
42 typedef struct __libc_rwlock_opaque__ __libc_rwlock_t;
43 #endif
44 
45 /* Type for key to thread-specific data.  */
46 typedef pthread_key_t __libc_key_t;
47 
48 /* Define a lock variable NAME with storage class CLASS.  The lock must be
49    initialized with __libc_lock_init before it can be used (or define it
50    with __libc_lock_define_initialized, below).  Use `extern' for CLASS to
51    declare a lock defined in another module.  In public structure
52    definitions you must use a pointer to the lock structure (i.e., NAME
53    begins with a `*'), because its storage size will not be known outside
54    of libc.  */
55 #define __libc_lock_define(CLASS,NAME) \
56   CLASS __libc_lock_t NAME;
57 #define __libc_rwlock_define(CLASS,NAME) \
58   CLASS __libc_rwlock_t NAME;
59 #define __libc_lock_define_recursive(CLASS,NAME) \
60   CLASS __libc_lock_recursive_t NAME;
61 #define __rtld_lock_define_recursive(CLASS,NAME) \
62   CLASS __rtld_lock_recursive_t NAME;
63 
64 /* Define an initialized lock variable NAME with storage class CLASS.
65 
66    For the C library we take a deeper look at the initializer.  For
67    this implementation all fields are initialized to zero.  Therefore
68    we don't initialize the variable which allows putting it into the
69    BSS section.  (Except on PA-RISC and other odd architectures, where
70    initialized locks must be set to one due to the lack of normal
71    atomic operations.) */
72 
73 #if __LT_SPINLOCK_INIT == 0
74 #  define __libc_lock_define_initialized(CLASS,NAME) \
75   CLASS __libc_lock_t NAME;
76 #else
77 #  define __libc_lock_define_initialized(CLASS,NAME) \
78   CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER;
79 #endif
80 
81 #define __libc_rwlock_define_initialized(CLASS,NAME) \
82   CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER;
83 
84 /* Define an initialized recursive lock variable NAME with storage
85    class CLASS.  */
86 #define __libc_lock_define_initialized_recursive(CLASS,NAME) \
87   CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER;
88 #define _LIBC_LOCK_RECURSIVE_INITIALIZER \
89   {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP}
90 
91 #define __rtld_lock_define_initialized_recursive(CLASS,NAME) \
92   CLASS __rtld_lock_recursive_t NAME = _RTLD_LOCK_RECURSIVE_INITIALIZER;
93 #define _RTLD_LOCK_RECURSIVE_INITIALIZER \
94   {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP}
95 
96 #if defined _LIBC && defined IS_IN_libpthread
97 # define __libc_maybe_call(FUNC, ARGS, ELSE) FUNC ARGS
98 #else
99 # if defined __PIC__ || (defined _LIBC && defined SHARED)
100 #  define __libc_maybe_call(FUNC, ARGS, ELSE) \
101   (__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \
102                     _fn != NULL ? (*_fn) ARGS : ELSE; }))
103 # else
104 #  define __libc_maybe_call(FUNC, ARGS, ELSE) \
105   (FUNC != NULL ? FUNC ARGS : ELSE)
106 # endif
107 #endif
108 
109 #define __libc_maybe_call2(FUNC, ARGS, ELSE) __libc_maybe_call (__##FUNC, ARGS, ELSE)
110 
111 /* Initialize the named lock variable, leaving it in a consistent, unlocked
112    state.  */
113 #if defined _LIBC && !defined NOT_IN_libc && defined SHARED
114 #define __libc_lock_init(NAME) \
115   ({									      \
116     (NAME).__m_count = 0;						      \
117     (NAME).__m_owner = NULL;						      \
118     (NAME).__m_kind = PTHREAD_MUTEX_TIMED_NP;				      \
119     (NAME).__m_lock.__status = 0;					      \
120     (NAME).__m_lock.__spinlock = __LT_SPINLOCK_INIT;			      \
121     0; })
122 #else
123 #define __libc_lock_init(NAME) \
124   (__libc_maybe_call2 (pthread_mutex_init, (&(NAME), NULL), 0))
125 #endif
126 #define __libc_rwlock_init(NAME) \
127   (__libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0));
128 
129 /* Same as last but this time we initialize an adaptive mutex.  */
130 #if defined _LIBC && !defined NOT_IN_libc && defined SHARED
131 #define __libc_lock_init_adaptive(NAME) \
132   ({									      \
133     (NAME).__m_count = 0;						      \
134     (NAME).__m_owner = NULL;						      \
135     (NAME).__m_kind = PTHREAD_MUTEX_ADAPTIVE_NP;			      \
136     (NAME).__m_lock.__status = 0;					      \
137     (NAME).__m_lock.__spinlock = __LT_SPINLOCK_INIT;			      \
138     0; })
139 #else
140 #define __libc_lock_init_adaptive(NAME) \
141   do {									      \
142     if (__pthread_mutex_init != NULL)					      \
143       {									      \
144 	pthread_mutexattr_t __attr;					      \
145 	__pthread_mutexattr_init (&__attr);				      \
146 	__pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_ADAPTIVE_NP);     \
147 	__pthread_mutex_init (&(NAME), &__attr);			      \
148 	__pthread_mutexattr_destroy (&__attr);				      \
149       }									      \
150   } while (0);
151 #endif
152 
153 /* Same as last but this time we initialize a recursive mutex.  */
154 #if defined _LIBC && !defined NOT_IN_libc && defined SHARED
155 #define __libc_lock_init_recursive(NAME) \
156   ({									      \
157     (NAME).__m_count = 0;						      \
158     (NAME).__m_owner = NULL;					      \
159     (NAME).__m_kind = PTHREAD_MUTEX_RECURSIVE_NP;			      \
160     (NAME).__m_lock.__status = 0;					      \
161     (NAME).__m_lock.__spinlock = __LT_SPINLOCK_INIT;		      \
162     0; })
163 #else
164 #define __libc_lock_init_recursive(NAME) \
165   do {									      \
166     if (__pthread_mutex_init != NULL)					      \
167       {									      \
168 	pthread_mutexattr_t __attr;					      \
169 	__pthread_mutexattr_init (&__attr);				      \
170 	__pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \
171 	__pthread_mutex_init (&(NAME), &__attr);			      \
172 	__pthread_mutexattr_destroy (&__attr);				      \
173       }									      \
174   } while (0);
175 #endif
176 #define __rtld_lock_init_recursive(NAME) \
177   __libc_lock_init_recursive (NAME)
178 
179 /* Finalize the named lock variable, which must be locked.  It cannot be
180    used again until __libc_lock_init is called again on it.  This must be
181    called on a lock variable before the containing storage is reused.  */
182 #define __libc_lock_fini(NAME) \
183   (__libc_maybe_call2 (pthread_mutex_destroy, (&(NAME)), 0));
184 #define __libc_rwlock_fini(NAME) \
185   (__libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0));
186 
187 /* Finalize recursive named lock.  */
188 #define __libc_lock_fini_recursive(NAME) __libc_lock_fini ((NAME).mutex)
189 #define __rtld_lock_fini_recursive(NAME) __libc_lock_fini_recursive (NAME)
190 
191 /* Lock the named lock variable.  */
192 #define __libc_lock_lock(NAME) \
193   (__libc_maybe_call2 (pthread_mutex_lock, (&(NAME)), 0));
194 #define __libc_rwlock_rdlock(NAME) \
195   (__libc_maybe_call (__pthread_rwlock_rdlock, (&(NAME)), 0));
196 #define __libc_rwlock_wrlock(NAME) \
197   (__libc_maybe_call (__pthread_rwlock_wrlock, (&(NAME)), 0));
198 
199 /* Lock the recursive named lock variable.  */
200 #define __libc_lock_lock_recursive(NAME) __libc_lock_lock ((NAME).mutex)
201 
202 /* Try to lock the named lock variable.  */
203 #define __libc_lock_trylock(NAME) \
204   (__libc_maybe_call2 (pthread_mutex_trylock, (&(NAME)), 0))
205 #define __libc_rwlock_tryrdlock(NAME) \
206   (__libc_maybe_call (__pthread_rwlock_tryrdlock, (&(NAME)), 0))
207 #define __libc_rwlock_trywrlock(NAME) \
208   (__libc_maybe_call (__pthread_rwlock_trywrlock, (&(NAME)), 0))
209 
210 /* Try to lock the recursive named lock variable.  */
211 #define __libc_lock_trylock_recursive(NAME) __libc_lock_trylock ((NAME).mutex)
212 #define __rtld_lock_trylock_recursive(NAME) \
213   __libc_lock_trylock_recursive (NAME)
214 
215 /* Unlock the named lock variable.  */
216 #define __libc_lock_unlock(NAME) \
217   (__libc_maybe_call2 (pthread_mutex_unlock, (&(NAME)), 0));
218 #define __libc_rwlock_unlock(NAME) \
219   (__libc_maybe_call (__pthread_rwlock_unlock, (&(NAME)), 0));
220 
221 /* Unlock the recursive named lock variable.  */
222 #define __libc_lock_unlock_recursive(NAME) __libc_lock_unlock ((NAME).mutex)
223 
224 /* Define once control variable.  */
225 #if PTHREAD_ONCE_INIT == 0
226 /* Special case for static variables where we can avoid the initialization
227    if it is zero.  */
228 # define __libc_once_define(CLASS, NAME) \
229   CLASS pthread_once_t NAME
230 #else
231 # define __libc_once_define(CLASS, NAME) \
232   CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT
233 #endif
234 
235 /* Call handler iff the first call.  */
236 #define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
237   do {									      \
238     if (__pthread_once != NULL)						      \
239       __pthread_once (&(ONCE_CONTROL), (INIT_FUNCTION));		      \
240     else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) {			      \
241       INIT_FUNCTION ();							      \
242       (ONCE_CONTROL) = !PTHREAD_ONCE_INIT;				      \
243     }									      \
244   } while (0)
245 
246 
247 /* Start critical region with cleanup.  */
248 #define __libc_cleanup_region_start(DOIT, FCT, ARG) \
249   { struct _pthread_cleanup_buffer _buffer;				      \
250     int _avail = (DOIT) && _pthread_cleanup_push_defer != NULL;		      \
251     if (_avail) {							      \
252       _pthread_cleanup_push_defer (&_buffer, (FCT), (ARG));		      \
253     }
254 
255 /* End critical region with cleanup.  */
256 #define __libc_cleanup_region_end(DOIT) \
257     if (_avail) {							      \
258       _pthread_cleanup_pop_restore (&_buffer, (DOIT));			      \
259     }									      \
260   }
261 
262 /* Sometimes we have to exit the block in the middle.  */
263 #define __libc_cleanup_end(DOIT) \
264     if (_avail) {							      \
265       _pthread_cleanup_pop_restore (&_buffer, (DOIT));			      \
266     }
267 
268 #if 0
269 #define __libc_cleanup_push(fct, arg) \
270     { struct _pthread_cleanup_buffer _buffer; 				      \
271     __libc_maybe_call (_pthread_cleanup_push, (&_buffer, (fct), (arg)), 0)
272 
273 #define __libc_cleanup_pop(execute) \
274     __libc_maybe_call (_pthread_cleanup_pop, (&_buffer, execute), 0);	      \
275     }
276 #endif
277 
278 /* Create thread-specific key.  */
279 #define __libc_key_create(KEY, DESTRUCTOR) \
280   (__libc_maybe_call (__pthread_key_create, (KEY, DESTRUCTOR), 1))
281 
282 /* Get thread-specific data.  */
283 #define __libc_getspecific(KEY) \
284   (__libc_maybe_call (__pthread_getspecific, (KEY), NULL))
285 
286 /* Set thread-specific data.  */
287 #define __libc_setspecific(KEY, VALUE) \
288   (__libc_maybe_call (__pthread_setspecific, (KEY, VALUE), 0))
289 
290 
291 /* Register handlers to execute before and after `fork'.  */
292 #define __libc_atfork(PREPARE, PARENT, CHILD) \
293   (__libc_maybe_call (__pthread_atfork, (PREPARE, PARENT, CHILD), 0))
294 
295 /* Functions that are used by this file and are internal to the GNU C
296    library.  */
297 
298 extern int __pthread_mutex_init (pthread_mutex_t *__mutex,
299 				 const pthread_mutexattr_t *__mutex_attr);
300 
301 extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex);
302 
303 extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex);
304 
305 extern int __pthread_mutex_lock (pthread_mutex_t *__mutex);
306 
307 extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex);
308 
309 extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr);
310 
311 extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr);
312 
313 extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr,
314 					int __kind);
315 
316 #ifdef __USE_UNIX98
317 extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock,
318 				  const pthread_rwlockattr_t *__attr);
319 
320 extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock);
321 
322 extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock);
323 
324 extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock);
325 
326 extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock);
327 
328 extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock);
329 
330 extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock);
331 #endif
332 
333 extern int __pthread_key_create (pthread_key_t *__key,
334 				 void (*__destr_function) (void *));
335 
336 extern int __pthread_setspecific (pthread_key_t __key,
337 				  const void *__pointer);
338 
339 extern void *__pthread_getspecific (pthread_key_t __key);
340 
341 extern int __pthread_once (pthread_once_t *__once_control,
342 			   void (*__init_routine) (void));
343 
344 extern int __pthread_atfork (void (*__prepare) (void),
345 			     void (*__parent) (void),
346 			     void (*__child) (void));
347 
348 
349 /* We need portable names for some functions.  E.g., when they are
350    used as argument to __libc_cleanup_region_start.  */
351 #define __libc_mutex_unlock __pthread_mutex_unlock
352 
353 #endif	/* bits/libc-lock.h */
354