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