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