master
  1/* libc-internal interface for mutex locks.  Mach cthreads version.
  2   Copyright (C) 1996-2025 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 Lesser General Public
  7   License as published by the Free Software Foundation; either
  8   version 2.1 of the 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   Lesser General Public License for more details.
 14
 15   You should have received a copy of the GNU Lesser General Public
 16   License along with the GNU C Library; if not, see
 17   <https://www.gnu.org/licenses/>.  */
 18
 19#ifndef _LIBC_LOCK_H
 20#define _LIBC_LOCK_H 1
 21
 22#ifdef _LIBC
 23
 24#include <tls.h>
 25#include <lowlevellock.h>
 26
 27typedef unsigned int __libc_lock_t;
 28typedef struct
 29{
 30  __libc_lock_t lock;
 31  int cnt;
 32  void *owner;
 33} __libc_lock_recursive_t;
 34
 35typedef __libc_lock_recursive_t __rtld_lock_recursive_t;
 36
 37#define __libc_lock_owner_self()   \
 38  (__LIBC_NO_TLS () ? (void *) 1 : THREAD_SELF)
 39
 40#else
 41typedef struct __libc_lock_opaque__ __libc_lock_t;
 42typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
 43#endif
 44
 45/* Define a lock variable NAME with storage class CLASS.  The lock must be
 46   initialized with __libc_lock_init before it can be used (or define it
 47   with __libc_lock_define_initialized, below).  Use `extern' for CLASS to
 48   declare a lock defined in another module.  In public structure
 49   definitions you must use a pointer to the lock structure (i.e., NAME
 50   begins with a `*'), because its storage size will not be known outside
 51   of libc.  */
 52#define __libc_lock_define(CLASS,NAME) \
 53  CLASS __libc_lock_t NAME;
 54
 55/* Define an initialized lock variable NAME with storage class CLASS.  */
 56#define _LIBC_LOCK_INITIALIZER LLL_LOCK_INITIALIZER
 57#define __libc_lock_define_initialized(CLASS,NAME) \
 58  CLASS __libc_lock_t NAME = LLL_LOCK_INITIALIZER;
 59
 60/* Initialize the named lock variable, leaving it in a consistent, unlocked
 61   state.  */
 62#define __libc_lock_init(NAME) (NAME) = LLL_LOCK_INITIALIZER
 63
 64/* Finalize the named lock variable, which must be locked.  It cannot be
 65   used again until __libc_lock_init is called again on it.  This must be
 66   called on a lock variable before the containing storage is reused.  */
 67#define __libc_lock_fini             __libc_lock_unlock
 68#define __libc_lock_fini_recursive   __libc_lock_unlock_recursive
 69#define __rtld_lock_fini_recursive   __rtld_lock_unlock_recursive
 70
 71/* Lock the named lock variable.  */
 72#define __libc_lock_lock(NAME)   \
 73  ({ lll_lock ((NAME), LLL_PRIVATE); 0; })
 74
 75/* Lock the named lock variable.  */
 76#define __libc_lock_trylock(NAME) lll_trylock (NAME)
 77
 78/* Unlock the named lock variable.  */
 79#define __libc_lock_unlock(NAME)   \
 80  ({ lll_unlock ((NAME), LLL_PRIVATE); 0; })
 81
 82#define __libc_lock_define_recursive(CLASS,NAME) \
 83  CLASS __libc_lock_recursive_t NAME;
 84
 85#define _LIBC_LOCK_RECURSIVE_INITIALIZER { LLL_LOCK_INITIALIZER, 0, 0 }
 86
 87#define __libc_lock_define_initialized_recursive(CLASS,NAME) \
 88  CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER;
 89
 90#define __rtld_lock_define_recursive(CLASS,NAME) \
 91  __libc_lock_define_recursive (CLASS, NAME)
 92#define _RTLD_LOCK_RECURSIVE_INITIALIZER \
 93  _LIBC_LOCK_RECURSIVE_INITIALIZER
 94#define __rtld_lock_define_initialized_recursive(CLASS,NAME) \
 95  __libc_lock_define_initialized_recursive (CLASS, NAME)
 96
 97#define __libc_lock_init_recursive(NAME)   \
 98  ({   \
 99     (NAME) = (__libc_lock_recursive_t)_LIBC_LOCK_RECURSIVE_INITIALIZER;   \
100     0;   \
101  })
102
103#define __libc_lock_trylock_recursive(NAME)   \
104  ({   \
105     __libc_lock_recursive_t *const __lock = &(NAME);   \
106     void *__self = __libc_lock_owner_self ();   \
107     int __r = 0;   \
108     if (__self == __lock->owner)   \
109       ++__lock->cnt;   \
110     else if ((__r = lll_trylock (__lock->lock)) == 0)   \
111       __lock->owner = __self, __lock->cnt = 1;   \
112     __r;   \
113   })
114
115#define __libc_lock_lock_recursive(NAME)   \
116  ({   \
117     __libc_lock_recursive_t *const __lock = &(NAME);   \
118     void *__self = __libc_lock_owner_self ();   \
119     if (__self != __lock->owner)   \
120       {   \
121         lll_lock (__lock->lock, 0);   \
122         __lock->owner = __self;   \
123       }   \
124     ++__lock->cnt;   \
125     (void)0;   \
126   })
127
128#define __libc_lock_unlock_recursive(NAME)   \
129  ({   \
130     __libc_lock_recursive_t *const __lock = &(NAME);   \
131     if (--__lock->cnt == 0)   \
132       {   \
133         __lock->owner = 0;   \
134         lll_unlock (__lock->lock, 0);   \
135       }   \
136   })
137
138
139#define __rtld_lock_initialize(NAME) \
140  (void) ((NAME) = (__rtld_lock_recursive_t) _RTLD_LOCK_RECURSIVE_INITIALIZER)
141#define __rtld_lock_trylock_recursive(NAME) \
142  __libc_lock_trylock_recursive (NAME)
143#define __rtld_lock_lock_recursive(NAME) \
144  __libc_lock_lock_recursive(NAME)
145#define __rtld_lock_unlock_recursive(NAME) \
146  __libc_lock_unlock_recursive (NAME)
147
148/* XXX for now */
149#define __libc_rwlock_define		__libc_lock_define
150#define __libc_rwlock_define_initialized __libc_lock_define_initialized
151#define __libc_rwlock_init		__libc_lock_init
152#define __libc_rwlock_fini		__libc_lock_fini
153#define __libc_rwlock_rdlock		__libc_lock_lock
154#define __libc_rwlock_wrlock		__libc_lock_lock
155#define __libc_rwlock_tryrdlock		__libc_lock_trylock
156#define __libc_rwlock_trywrlock		__libc_lock_trylock
157#define __libc_rwlock_unlock		__libc_lock_unlock
158
159struct __libc_cleanup_frame
160{
161  void (*__fct) (void *);
162  void *__argp;
163  int __doit;
164};
165
166__extern_inline void
167__libc_cleanup_fct (struct __libc_cleanup_frame *framep)
168{
169  if (framep->__doit)
170    framep->__fct (framep->__argp);
171}
172
173/* Start a critical region with a cleanup function */
174#define __libc_cleanup_region_start(DOIT, FCT, ARG)   \
175  do   \
176    {   \
177      struct __libc_cleanup_frame __cleanup   \
178        __attribute__ ((__cleanup__ (__libc_cleanup_fct))) =   \
179        { .__fct = (FCT), .__argp = (ARG), .__doit = (DOIT) };
180
181/* This one closes the brace above.  */
182#define __libc_cleanup_region_end(DOIT)   \
183      __cleanup.__doit = (DOIT);   \
184    }   \
185  while (0)
186
187#define __libc_cleanup_end(DOIT)   __cleanup.__doit = (DOIT);
188
189#define __libc_cleanup_push(fct, arg) __libc_cleanup_region_start (1, fct, arg)
190#define __libc_cleanup_pop(execute) __libc_cleanup_region_end (execute)
191
192/* Use mutexes as once control variables.  */
193
194struct __libc_once
195  {
196    __libc_lock_t lock;
197    int done;
198  };
199
200#define __libc_once_define(CLASS,NAME) \
201  CLASS struct __libc_once NAME = { _LIBC_LOCK_INITIALIZER, 0 }
202
203/* Call handler iff the first call.  */
204#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
205  do {									      \
206    __libc_lock_lock (ONCE_CONTROL.lock);				      \
207    if (!ONCE_CONTROL.done)						      \
208      (INIT_FUNCTION) ();						      \
209    ONCE_CONTROL.done = 1;						      \
210    __libc_lock_unlock (ONCE_CONTROL.lock);				      \
211  } while (0)
212
213/* Get once control variable.  */
214#define __libc_once_get(ONCE_CONTROL)	((ONCE_CONTROL).done != 0)
215
216#ifdef _LIBC
217/* We need portable names for some functions.  E.g., when they are
218   used as argument to __libc_cleanup_region_start.  */
219#define __libc_mutex_unlock __libc_lock_unlock
220
221/* Hide the definitions which are only supposed to be used inside libc in
222   a separate file.  This file is not present in the installation!  */
223# include <libc-lockP.h>
224#endif
225
226#endif	/* libc-lock.h */