Back to index

glibc  2.9
libc-lock.h
Go to the documentation of this file.
00001 /* libc-internal interface for mutex locks.  LinuxThreads version.
00002    Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003,2006
00003        Free Software Foundation, Inc.
00004    This file is part of the GNU C Library.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public License as
00008    published by the Free Software Foundation; either version 2.1 of the
00009    License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; see the file COPYING.LIB.  If not,
00018    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019    Boston, MA 02111-1307, USA.  */
00020 
00021 #ifndef _BITS_LIBC_LOCK_H
00022 #define _BITS_LIBC_LOCK_H 1
00023 
00024 #include <pthread.h>
00025 
00026 #if defined _LIBC && !defined NOT_IN_libc
00027 #include <linuxthreads/internals.h>
00028 #endif
00029 
00030 /* Mutex type.  */
00031 #if defined(_LIBC) || defined(_IO_MTSAFE_IO)
00032 typedef pthread_mutex_t __libc_lock_t;
00033 typedef struct { pthread_mutex_t mutex; } __libc_lock_recursive_t;
00034 # ifdef __USE_UNIX98
00035 typedef pthread_rwlock_t __libc_rwlock_t;
00036 # else
00037 typedef struct __libc_rwlock_opaque__ __libc_rwlock_t;
00038 # endif
00039 typedef __libc_lock_recursive_t __rtld_lock_recursive_t;
00040 #else
00041 typedef struct __libc_lock_opaque__ __libc_lock_t;
00042 typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
00043 typedef struct __libc_rwlock_opaque__ __libc_rwlock_t;
00044 #endif
00045 
00046 /* Type for key to thread-specific data.  */
00047 typedef pthread_key_t __libc_key_t;
00048 
00049 /* Define a lock variable NAME with storage class CLASS.  The lock must be
00050    initialized with __libc_lock_init before it can be used (or define it
00051    with __libc_lock_define_initialized, below).  Use `extern' for CLASS to
00052    declare a lock defined in another module.  In public structure
00053    definitions you must use a pointer to the lock structure (i.e., NAME
00054    begins with a `*'), because its storage size will not be known outside
00055    of libc.  */
00056 #define __libc_lock_define(CLASS,NAME) \
00057   CLASS __libc_lock_t NAME;
00058 #define __libc_rwlock_define(CLASS,NAME) \
00059   CLASS __libc_rwlock_t NAME;
00060 #define __libc_lock_define_recursive(CLASS,NAME) \
00061   CLASS __libc_lock_recursive_t NAME;
00062 #define __rtld_lock_define_recursive(CLASS,NAME) \
00063   CLASS __rtld_lock_recursive_t NAME;
00064 
00065 /* Define an initialized lock variable NAME with storage class CLASS.
00066 
00067    For the C library we take a deeper look at the initializer.  For
00068    this implementation all fields are initialized to zero.  Therefore
00069    we don't initialize the variable which allows putting it into the
00070    BSS section.  (Except on PA-RISC and other odd architectures, where
00071    initialized locks must be set to one due to the lack of normal
00072    atomic operations.) */
00073 
00074 #if __LT_SPINLOCK_INIT == 0
00075 #  define __libc_lock_define_initialized(CLASS,NAME) \
00076   CLASS __libc_lock_t NAME;
00077 #else
00078 #  define __libc_lock_define_initialized(CLASS,NAME) \
00079   CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER;
00080 #endif
00081 
00082 #define __libc_rwlock_define_initialized(CLASS,NAME) \
00083   CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER;
00084 
00085 /* Define an initialized recursive lock variable NAME with storage
00086    class CLASS.  */
00087 #define __libc_lock_define_initialized_recursive(CLASS,NAME) \
00088   CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER;
00089 #define _LIBC_LOCK_RECURSIVE_INITIALIZER \
00090   {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP}
00091 
00092 #define __rtld_lock_define_initialized_recursive(CLASS,NAME) \
00093   CLASS __rtld_lock_recursive_t NAME = _RTLD_LOCK_RECURSIVE_INITIALIZER;
00094 #define _RTLD_LOCK_RECURSIVE_INITIALIZER \
00095   {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP}
00096 
00097 #if defined _LIBC && defined IS_IN_libpthread
00098 # define __libc_maybe_call(FUNC, ARGS, ELSE) FUNC ARGS
00099 #else
00100 # if defined __PIC__ || (defined _LIBC && defined SHARED)
00101 #  define __libc_maybe_call(FUNC, ARGS, ELSE) \
00102   (__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \
00103                     _fn != NULL ? (*_fn) ARGS : ELSE; }))
00104 # else
00105 #  define __libc_maybe_call(FUNC, ARGS, ELSE) \
00106   (FUNC != NULL ? FUNC ARGS : ELSE)
00107 # endif
00108 #endif
00109 #if defined _LIBC && !defined NOT_IN_libc && defined SHARED
00110 # define __libc_maybe_call2(FUNC, ARGS, ELSE) \
00111   ({__builtin_expect (__libc_pthread_functions.ptr_##FUNC != NULL, 0) \
00112     ? __libc_pthread_functions.ptr_##FUNC ARGS : ELSE; })
00113 #else
00114 # define __libc_maybe_call2(FUNC, ARGS, ELSE) __libc_maybe_call (__##FUNC, ARGS, ELSE)
00115 #endif
00116 
00117 /* Initialize the named lock variable, leaving it in a consistent, unlocked
00118    state.  */
00119 #if defined _LIBC && !defined NOT_IN_libc && defined SHARED
00120 #define __libc_lock_init(NAME) \
00121   ({                                                                 \
00122     (NAME).__m_count = 0;                                            \
00123     (NAME).__m_owner = NULL;                                                \
00124     (NAME).__m_kind = PTHREAD_MUTEX_TIMED_NP;                               \
00125     (NAME).__m_lock.__status = 0;                                    \
00126     (NAME).__m_lock.__spinlock = __LT_SPINLOCK_INIT;                        \
00127     0; })
00128 #else
00129 #define __libc_lock_init(NAME) \
00130   (__libc_maybe_call2 (pthread_mutex_init, (&(NAME), NULL), 0))
00131 #endif
00132 #define __libc_rwlock_init(NAME) \
00133   (__libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0));
00134 
00135 /* Same as last but this time we initialize a recursive mutex.  */
00136 #if defined _LIBC && !defined NOT_IN_libc && defined SHARED
00137 #define __libc_lock_init_recursive(NAME) \
00138   ({                                                                 \
00139     (NAME).mutex.__m_count = 0;                                             \
00140     (NAME).mutex.__m_owner = NULL;                                   \
00141     (NAME).mutex.__m_kind = PTHREAD_MUTEX_RECURSIVE_NP;                     \
00142     (NAME).mutex.__m_lock.__status = 0;                                     \
00143     (NAME).mutex.__m_lock.__spinlock = __LT_SPINLOCK_INIT;                  \
00144     0; })
00145 #else
00146 #define __libc_lock_init_recursive(NAME) \
00147   do {                                                               \
00148     if (__pthread_mutex_init != NULL)                                       \
00149       {                                                                     \
00150        pthread_mutexattr_t __attr;                                   \
00151        __pthread_mutexattr_init (&__attr);                                  \
00152        __pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \
00153        __pthread_mutex_init (&(NAME).mutex, &__attr);                       \
00154        __pthread_mutexattr_destroy (&__attr);                               \
00155       }                                                                     \
00156   } while (0);
00157 #endif
00158 #define __rtld_lock_init_recursive(NAME) \
00159   __libc_lock_init_recursive (NAME)
00160 
00161 /* Finalize the named lock variable, which must be locked.  It cannot be
00162    used again until __libc_lock_init is called again on it.  This must be
00163    called on a lock variable before the containing storage is reused.  */
00164 #define __libc_lock_fini(NAME) \
00165   (__libc_maybe_call2 (pthread_mutex_destroy, (&(NAME)), 0));
00166 #define __libc_rwlock_fini(NAME) \
00167   (__libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0));
00168 
00169 /* Finalize recursive named lock.  */
00170 #define __libc_lock_fini_recursive(NAME) __libc_lock_fini ((NAME).mutex)
00171 #define __rtld_lock_fini_recursive(NAME) __libc_lock_fini_recursive (NAME)
00172 
00173 /* Lock the named lock variable.  */
00174 #define __libc_lock_lock(NAME) \
00175   (__libc_maybe_call2 (pthread_mutex_lock, (&(NAME)), 0));
00176 #define __libc_rwlock_rdlock(NAME) \
00177   (__libc_maybe_call (__pthread_rwlock_rdlock, (&(NAME)), 0));
00178 #define __libc_rwlock_wrlock(NAME) \
00179   (__libc_maybe_call (__pthread_rwlock_wrlock, (&(NAME)), 0));
00180 
00181 /* Lock the recursive named lock variable.  */
00182 #define __libc_lock_lock_recursive(NAME) __libc_lock_lock ((NAME).mutex)
00183 
00184 /* Try to lock the named lock variable.  */
00185 #define __libc_lock_trylock(NAME) \
00186   (__libc_maybe_call2 (pthread_mutex_trylock, (&(NAME)), 0))
00187 #define __libc_rwlock_tryrdlock(NAME) \
00188   (__libc_maybe_call (__pthread_rwlock_tryrdlock, (&(NAME)), 0))
00189 #define __libc_rwlock_trywrlock(NAME) \
00190   (__libc_maybe_call (__pthread_rwlock_trywrlock, (&(NAME)), 0))
00191 
00192 /* Try to lock the recursive named lock variable.  */
00193 #define __libc_lock_trylock_recursive(NAME) __libc_lock_trylock ((NAME).mutex)
00194 #define __rtld_lock_trylock_recursive(NAME) \
00195   __libc_lock_trylock_recursive (NAME)
00196 
00197 /* Unlock the named lock variable.  */
00198 #define __libc_lock_unlock(NAME) \
00199   (__libc_maybe_call2 (pthread_mutex_unlock, (&(NAME)), 0));
00200 #define __libc_rwlock_unlock(NAME) \
00201   (__libc_maybe_call (__pthread_rwlock_unlock, (&(NAME)), 0));
00202 
00203 /* Unlock the recursive named lock variable.  */
00204 #define __libc_lock_unlock_recursive(NAME) __libc_lock_unlock ((NAME).mutex)
00205 
00206 #if defined _LIBC && defined SHARED
00207 # define __rtld_lock_default_lock_recursive(lock) \
00208   ++((pthread_mutex_t *)(lock))->__m_count;
00209 
00210 # define __rtld_lock_default_unlock_recursive(lock) \
00211   --((pthread_mutex_t *)(lock))->__m_count;
00212 
00213 # define __rtld_lock_lock_recursive(NAME) \
00214   GL(dl_rtld_lock_recursive) (&(NAME).mutex)
00215 
00216 # define __rtld_lock_unlock_recursive(NAME) \
00217   GL(dl_rtld_unlock_recursive) (&(NAME).mutex)
00218 #else
00219 #define __rtld_lock_lock_recursive(NAME) __libc_lock_lock_recursive (NAME)
00220 #define __rtld_lock_unlock_recursive(NAME) __libc_lock_unlock_recursive (NAME)
00221 #endif
00222 
00223 /* Define once control variable.  */
00224 #if PTHREAD_ONCE_INIT == 0
00225 /* Special case for static variables where we can avoid the initialization
00226    if it is zero.  */
00227 # define __libc_once_define(CLASS, NAME) \
00228   CLASS pthread_once_t NAME
00229 #else
00230 # define __libc_once_define(CLASS, NAME) \
00231   CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT
00232 #endif
00233 
00234 /* Call handler iff the first call.  */
00235 #define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
00236   do {                                                               \
00237     if (__pthread_once != NULL)                                             \
00238       __pthread_once (&(ONCE_CONTROL), (INIT_FUNCTION));                    \
00239     else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) {                         \
00240       INIT_FUNCTION ();                                                     \
00241       (ONCE_CONTROL) = 2;                                            \
00242     }                                                                \
00243   } while (0)
00244 
00245 
00246 /* Start critical region with cleanup.  */
00247 #define __libc_cleanup_region_start(DOIT, FCT, ARG) \
00248   { struct _pthread_cleanup_buffer _buffer;                                 \
00249     int _avail = (DOIT) && _pthread_cleanup_push_defer != NULL;                    \
00250     if (_avail) {                                                    \
00251       _pthread_cleanup_push_defer (&_buffer, (FCT), (ARG));                 \
00252     }
00253 
00254 /* End critical region with cleanup.  */
00255 #define __libc_cleanup_region_end(DOIT) \
00256     if (_avail) {                                                    \
00257       _pthread_cleanup_pop_restore (&_buffer, (DOIT));                      \
00258     }                                                                \
00259   }
00260 
00261 /* Sometimes we have to exit the block in the middle.  */
00262 #define __libc_cleanup_end(DOIT) \
00263     if (_avail) {                                                    \
00264       _pthread_cleanup_pop_restore (&_buffer, (DOIT));                      \
00265     }
00266 
00267 #define __libc_cleanup_push(fct, arg) \
00268     { struct _pthread_cleanup_buffer _buffer;                               \
00269     __libc_maybe_call (_pthread_cleanup_push, (&_buffer, (fct), (arg)), 0)
00270 
00271 #define __libc_cleanup_pop(execute) \
00272     __libc_maybe_call (_pthread_cleanup_pop, (&_buffer, execute), 0);       \
00273     }
00274 
00275 /* Create thread-specific key.  */
00276 #define __libc_key_create(KEY, DESTRUCTOR) \
00277   (__libc_maybe_call (__pthread_key_create, (KEY, DESTRUCTOR), 1))
00278 
00279 /* Get thread-specific data.  */
00280 #define __libc_getspecific(KEY) \
00281   (__libc_maybe_call (__pthread_getspecific, (KEY), NULL))
00282 
00283 /* Set thread-specific data.  */
00284 #define __libc_setspecific(KEY, VALUE) \
00285   (__libc_maybe_call (__pthread_setspecific, (KEY, VALUE), 0))
00286 
00287 
00288 /* Register handlers to execute before and after `fork'.  */
00289 #define __libc_atfork(PREPARE, PARENT, CHILD) \
00290   (__libc_maybe_call (__pthread_atfork, (PREPARE, PARENT, CHILD), 0))
00291 
00292 /* Functions that are used by this file and are internal to the GNU C
00293    library.  */
00294 
00295 extern int __pthread_mutex_init (pthread_mutex_t *__mutex,
00296                              __const pthread_mutexattr_t *__mutex_attr);
00297 
00298 extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex);
00299 
00300 extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex);
00301 
00302 extern int __pthread_mutex_lock (pthread_mutex_t *__mutex);
00303 
00304 extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex);
00305 
00306 extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr);
00307 
00308 extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr);
00309 
00310 extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr,
00311                                    int __kind);
00312 
00313 #ifdef __USE_UNIX98
00314 extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock,
00315                               __const pthread_rwlockattr_t *__attr);
00316 
00317 extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock);
00318 
00319 extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock);
00320 
00321 extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock);
00322 
00323 extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock);
00324 
00325 extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock);
00326 
00327 extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock);
00328 #endif
00329 
00330 extern int __pthread_key_create (pthread_key_t *__key,
00331                              void (*__destr_function) (void *));
00332 
00333 extern int __pthread_setspecific (pthread_key_t __key,
00334                               __const void *__pointer);
00335 
00336 extern void *__pthread_getspecific (pthread_key_t __key);
00337 
00338 extern int __pthread_once (pthread_once_t *__once_control,
00339                         void (*__init_routine) (void));
00340 
00341 extern int __pthread_atfork (void (*__prepare) (void),
00342                           void (*__parent) (void),
00343                           void (*__child) (void));
00344 
00345 
00346 
00347 /* Make the pthread functions weak so that we can elide them from
00348    single-threaded processes.  */
00349 #ifndef __NO_WEAK_PTHREAD_ALIASES
00350 # ifdef weak_extern
00351 #  if _LIBC
00352 #   include <bp-sym.h>
00353 #  else
00354 #   define BP_SYM(sym) sym
00355 #  endif
00356 weak_extern (BP_SYM (__pthread_mutex_init))
00357 weak_extern (BP_SYM (__pthread_mutex_destroy))
00358 weak_extern (BP_SYM (__pthread_mutex_lock))
00359 weak_extern (BP_SYM (__pthread_mutex_trylock))
00360 weak_extern (BP_SYM (__pthread_mutex_unlock))
00361 weak_extern (BP_SYM (__pthread_mutexattr_init))
00362 weak_extern (BP_SYM (__pthread_mutexattr_destroy))
00363 weak_extern (BP_SYM (__pthread_mutexattr_settype))
00364 weak_extern (BP_SYM (__pthread_rwlock_init))
00365 weak_extern (BP_SYM (__pthread_rwlock_destroy))
00366 weak_extern (BP_SYM (__pthread_rwlock_rdlock))
00367 weak_extern (BP_SYM (__pthread_rwlock_tryrdlock))
00368 weak_extern (BP_SYM (__pthread_rwlock_wrlock))
00369 weak_extern (BP_SYM (__pthread_rwlock_trywrlock))
00370 weak_extern (BP_SYM (__pthread_rwlock_unlock))
00371 weak_extern (BP_SYM (__pthread_key_create))
00372 weak_extern (BP_SYM (__pthread_setspecific))
00373 weak_extern (BP_SYM (__pthread_getspecific))
00374 weak_extern (BP_SYM (__pthread_once))
00375 weak_extern (__pthread_initialize)
00376 weak_extern (__pthread_atfork)
00377 weak_extern (BP_SYM (_pthread_cleanup_push))
00378 weak_extern (BP_SYM (_pthread_cleanup_pop))
00379 weak_extern (BP_SYM (_pthread_cleanup_push_defer))
00380 weak_extern (BP_SYM (_pthread_cleanup_pop_restore))
00381 # else
00382 #  pragma weak __pthread_mutex_init
00383 #  pragma weak __pthread_mutex_destroy
00384 #  pragma weak __pthread_mutex_lock
00385 #  pragma weak __pthread_mutex_trylock
00386 #  pragma weak __pthread_mutex_unlock
00387 #  pragma weak __pthread_mutexattr_init
00388 #  pragma weak __pthread_mutexattr_destroy
00389 #  pragma weak __pthread_mutexattr_settype
00390 #  pragma weak __pthread_rwlock_destroy
00391 #  pragma weak __pthread_rwlock_rdlock
00392 #  pragma weak __pthread_rwlock_tryrdlock
00393 #  pragma weak __pthread_rwlock_wrlock
00394 #  pragma weak __pthread_rwlock_trywrlock
00395 #  pragma weak __pthread_rwlock_unlock
00396 #  pragma weak __pthread_key_create
00397 #  pragma weak __pthread_setspecific
00398 #  pragma weak __pthread_getspecific
00399 #  pragma weak __pthread_once
00400 #  pragma weak __pthread_initialize
00401 #  pragma weak __pthread_atfork
00402 #  pragma weak _pthread_cleanup_push_defer
00403 #  pragma weak _pthread_cleanup_pop_restore
00404 #  pragma weak _pthread_cleanup_push
00405 #  pragma weak _pthread_cleanup_pop
00406 # endif
00407 #endif
00408 
00409 /* We need portable names for some functions.  E.g., when they are
00410    used as argument to __libc_cleanup_region_start.  */
00411 #define __libc_mutex_unlock __pthread_mutex_unlock
00412 
00413 #endif /* bits/libc-lock.h */