Back to index

glibc  2.9
libc-lock.h
Go to the documentation of this file.
00001 /* libc-internal interface for mutex locks.  Hurd version using Mach cthreads.
00002    Copyright (C) 1996,97,98,2000,01, 2002, 2003 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #ifndef _BITS_LIBC_LOCK_H
00021 #define _BITS_LIBC_LOCK_H 1
00022 
00023 #if (_LIBC - 0) || (_CTHREADS_ - 0)
00024 #include <cthreads.h>
00025 #include <hurd/threadvar.h>
00026 
00027 typedef struct mutex __libc_lock_t;
00028 typedef struct
00029 {
00030   struct mutex mutex;
00031   void *owner;
00032   int count;
00033 } __libc_lock_recursive_t;
00034 
00035 #define __libc_lock_owner_self() ((void *) __hurd_threadvar_location (0))
00036 
00037 #else
00038 typedef struct __libc_lock_opaque__ __libc_lock_t;
00039 typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
00040 #endif
00041 
00042 /* Define a lock variable NAME with storage class CLASS.  The lock must be
00043    initialized with __libc_lock_init before it can be used (or define it
00044    with __libc_lock_define_initialized, below).  Use `extern' for CLASS to
00045    declare a lock defined in another module.  In public structure
00046    definitions you must use a pointer to the lock structure (i.e., NAME
00047    begins with a `*'), because its storage size will not be known outside
00048    of libc.  */
00049 #define __libc_lock_define(CLASS,NAME) \
00050   CLASS __libc_lock_t NAME;
00051 
00052 /* Define an initialized lock variable NAME with storage class CLASS.  */
00053 #define __libc_lock_define_initialized(CLASS,NAME) \
00054   CLASS __libc_lock_t NAME = MUTEX_INITIALIZER;
00055 
00056 /* Initialize the named lock variable, leaving it in a consistent, unlocked
00057    state.  */
00058 #define __libc_lock_init(NAME) __mutex_init (&(NAME))
00059 
00060 /* Finalize the named lock variable, which must be locked.  It cannot be
00061    used again until __libc_lock_init is called again on it.  This must be
00062    called on a lock variable before the containing storage is reused.  */
00063 #define __libc_lock_fini(NAME) __mutex_unlock (&(NAME))
00064 #define __libc_lock_fini_recursive(NAME) __mutex_unlock (&(NAME).mutex)
00065 #define __rtld_lock_fini_recursive(NAME) __mutex_unlock (&(NAME).mutex)
00066 
00067 
00068 /* Lock the named lock variable.  */
00069 #define __libc_lock_lock(NAME) __mutex_lock (&(NAME))
00070 
00071 /* Lock the named lock variable.  */
00072 #define __libc_lock_trylock(NAME) (!__mutex_trylock (&(NAME)))
00073 
00074 /* Unlock the named lock variable.  */
00075 #define __libc_lock_unlock(NAME) __mutex_unlock (&(NAME))
00076 
00077 
00078 #define __libc_lock_define_recursive(CLASS,NAME) \
00079   CLASS __libc_lock_recursive_t NAME;
00080 #define _LIBC_LOCK_RECURSIVE_INITIALIZER { MUTEX_INITIALIZER, 0, 0 }
00081 #define __libc_lock_define_initialized_recursive(CLASS,NAME) \
00082   CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER;
00083 
00084 #define __rtld_lock_define_recursive(CLASS,NAME) \
00085   __libc_lock_define_recursive (CLASS, NAME)
00086 #define _RTLD_LOCK_RECURSIVE_INITIALIZER \
00087   _LIBC_LOCK_RECURSIVE_INITIALIZER
00088 #define __rtld_lock_define_initialized_recursive(CLASS,NAME) \
00089   __libc_lock_define_initialized_recursive (CLASS, NAME)
00090 
00091 #define __libc_lock_init_recursive(NAME) \
00092   ({ __libc_lock_recursive_t *const __lock = &(NAME); \
00093      __lock->owner = 0; mutex_init (&__lock->mutex); })
00094 
00095 #define __libc_lock_trylock_recursive(NAME)                                 \
00096   ({ __libc_lock_recursive_t *const __lock = &(NAME);                       \
00097      void *__self = __libc_lock_owner_self ();                              \
00098      __mutex_trylock (&__lock->mutex)                                       \
00099      ? (__lock->owner = __self, __lock->count = 1, 0)                       \
00100      : __lock->owner == __self ? (++__lock->count, 0) : 1; })
00101 
00102 #define __libc_lock_lock_recursive(NAME)                             \
00103   ({ __libc_lock_recursive_t *const __lock = &(NAME);                       \
00104      void *__self = __libc_lock_owner_self ();                              \
00105      if (__mutex_trylock (&__lock->mutex)                            \
00106         || (__lock->owner != __self                                         \
00107             && (__mutex_lock (&__lock->mutex), 1)))                         \
00108        __lock->owner = __self, __lock->count = 1;                           \
00109      else                                                            \
00110        ++__lock->count;                                                     \
00111   })
00112 #define __libc_lock_unlock_recursive(NAME)                                  \
00113   ({ __libc_lock_recursive_t *const __lock = &(NAME);                       \
00114      if (--__lock->count == 0)                                              \
00115        {                                                             \
00116         __lock->owner = 0;                                           \
00117         __mutex_unlock (&__lock->mutex);                             \
00118        }                                                             \
00119   })
00120 
00121 
00122 #define __rtld_lock_init_recursive(NAME) \
00123   __libc_lock_init_recursive (NAME)
00124 #define __rtld_lock_trylock_recursive(NAME) \
00125   __libc_lock_trylock_recursive (NAME)
00126 #define __rtld_lock_lock_recursive(NAME) \
00127   __libc_lock_lock_recursive(NAME)
00128 #define __rtld_lock_unlock_recursive(NAME) \
00129   __libc_lock_unlock_recursive (NAME)
00130 
00131 
00132 /* XXX for now */
00133 #define __libc_rwlock_define              __libc_lock_define
00134 #define __libc_rwlock_define_initialized __libc_lock_define_initialized
00135 #define __libc_rwlock_init         __libc_lock_init
00136 #define __libc_rwlock_fini         __libc_lock_fini
00137 #define __libc_rwlock_rdlock              __libc_lock_lock
00138 #define __libc_rwlock_wrlock              __libc_lock_lock
00139 #define __libc_rwlock_tryrdlock           __libc_lock_trylock
00140 #define __libc_rwlock_trywrlock           __libc_lock_trylock
00141 #define __libc_rwlock_unlock              __libc_lock_unlock
00142 
00143 
00144 /* Start a critical region with a cleanup function */
00145 #define __libc_cleanup_region_start(DOIT, FCT, ARG)                       \
00146 {                                                                  \
00147   typeof (***(FCT)) *__save_FCT = (DOIT) ? (FCT) : 0;                     \
00148   typeof (ARG) __save_ARG = ARG;                                   \
00149   /* close brace is in __libc_cleanup_region_end below. */
00150 
00151 /* End a critical region started with __libc_cleanup_region_start. */
00152 #define __libc_cleanup_region_end(DOIT)                                   \
00153   if ((DOIT) && __save_FCT != 0)                                   \
00154     (*__save_FCT)(__save_ARG);                                            \
00155 }
00156 
00157 /* Sometimes we have to exit the block in the middle.  */
00158 #define __libc_cleanup_end(DOIT)                                   \
00159   if ((DOIT) && __save_FCT != 0)                                   \
00160     (*__save_FCT)(__save_ARG);                                            \
00161 
00162 #define __libc_cleanup_push(fct, arg) __libc_cleanup_region_start (1, fct, arg)
00163 #define __libc_cleanup_pop(execute) __libc_cleanup_region_end (execute)
00164 
00165 #if (_CTHREADS_ - 0)
00166 
00167 /* Use mutexes as once control variables. */
00168 
00169 struct __libc_once
00170   {
00171     __libc_lock_t lock;
00172     int done;
00173   };
00174 
00175 #define __libc_once_define(CLASS,NAME) \
00176   CLASS struct __libc_once NAME = { MUTEX_INITIALIZER, 0 }
00177 
00178 /* Call handler iff the first call.  */
00179 #define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
00180   do {                                                               \
00181     __libc_lock_lock (ONCE_CONTROL.lock);                            \
00182     if (!ONCE_CONTROL.done)                                          \
00183       (INIT_FUNCTION) ();                                            \
00184     ONCE_CONTROL.done = 1;                                           \
00185     __libc_lock_unlock (ONCE_CONTROL.lock);                                 \
00186   } while (0)
00187 
00188 #ifdef _LIBC
00189 /* We need portable names for some functions.  E.g., when they are
00190    used as argument to __libc_cleanup_region_start.  */
00191 #define __libc_mutex_unlock __mutex_unlock
00192 #endif
00193 
00194 /* Type for key of thread specific data.  */
00195 typedef cthread_key_t __libc_key_t;
00196 
00197 #define __libc_key_create(KEY,DEST) cthread_keycreate (KEY)
00198 #define __libc_setspecific(KEY,VAL) cthread_setspecific (KEY, VAL)
00199 void *__libc_getspecific (__libc_key_t key);
00200 
00201 #endif /* _CTHREADS_ */
00202 
00203 #endif /* bits/libc-lock.h */