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