Dr Andrew Scott G7VAV

My photo
 
June 2025
Mo Tu We Th Fr Sa Su
26 27 28 29 30 31 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 1 2 3 4 5 6


libc-lock.h
001: /* libc-internal interface for mutex locks.  NPTL version.
002:    Copyright (C) 1996-2003, 2005, 2007 Free Software Foundation, Inc.
003:    This file is part of the GNU C Library.
004: 
005:    The GNU C Library is free software; you can redistribute it and/or
006:    modify it under the terms of the GNU Lesser General Public License as
007:    published by the Free Software Foundation; either version 2.1 of the
008:    License, or (at your option) any later version.
009: 
010:    The GNU C Library is distributed in the hope that it will be useful,
011:    but WITHOUT ANY WARRANTY; without even the implied warranty of
012:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013:    Lesser General Public License for more details.
014: 
015:    You should have received a copy of the GNU Lesser General Public
016:    License along with the GNU C Library; see the file COPYING.LIB.  If not,
017:    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
018:    Boston, MA 02111-1307, USA.  */
019: 
020: #ifndef _BITS_LIBC_LOCK_H
021: #define _BITS_LIBC_LOCK_H 1
022: 
023: #include <pthread.h>
024: #define __need_NULL
025: #include <stddef.h>
026: 
027: 
028: /* Fortunately Linux now has a mean to do locking which is realtime
029:    safe without the aid of the thread library.  We also need no fancy
030:    options like error checking mutexes etc.  We only need simple
031:    locks, maybe recursive.  This can be easily and cheaply implemented
032:    using futexes.  We will use them everywhere except in ld.so since
033:    ld.so might be used on old kernels with a different libc.so.  */
034: #ifdef _LIBC
035: # include <lowlevellock.h>
036: # include <tls.h>
037: # include <pthread-functions.h>
038: # include <errno.h> /* For EBUSY.  */
039: # include <gnu/option-groups.h> /* For __OPTION_EGLIBC_BIG_MACROS.  */
040: #endif
041: 
042: /* Mutex type.  */
043: #if defined _LIBC || defined _IO_MTSAFE_IO
044: # if (defined NOT_IN_libc && !defined IS_IN_libpthread) || !defined _LIBC
045: typedef pthread_mutex_t __libc_lock_t;
046: typedef struct { pthread_mutex_t mutex; } __libc_lock_recursive_t;
047: # else
048: typedef int __libc_lock_t;
049: typedef struct { int lock; int cnt; void *owner; } __libc_lock_recursive_t;
050: # endif
051: typedef struct { pthread_mutex_t mutex; } __rtld_lock_recursive_t;
052: # ifdef __USE_UNIX98
053: typedef pthread_rwlock_t __libc_rwlock_t;
054: # else
055: typedef struct __libc_rwlock_opaque__ __libc_rwlock_t;
056: # endif
057: #else
058: typedef struct __libc_lock_opaque__ __libc_lock_t;
059: typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
060: typedef struct __libc_rwlock_opaque__ __libc_rwlock_t;
061: #endif
062: 
063: /* Type for key to thread-specific data.  */
064: typedef pthread_key_t __libc_key_t;
065: 
066: /* Define a lock variable NAME with storage class CLASS.  The lock must be
067:    initialized with __libc_lock_init before it can be used (or define it
068:    with __libc_lock_define_initialized, below).  Use `extern' for CLASS to
069:    declare a lock defined in another module.  In public structure
070:    definitions you must use a pointer to the lock structure (i.e., NAME
071:    begins with a `*'), because its storage size will not be known outside
072:    of libc.  */
073: #define __libc_lock_define(CLASS,NAME) \
074:   CLASS __libc_lock_t NAME;
075: #define __libc_rwlock_define(CLASS,NAME) \
076:   CLASS __libc_rwlock_t NAME;
077: #define __libc_lock_define_recursive(CLASS,NAME) \
078:   CLASS __libc_lock_recursive_t NAME;
079: #define __rtld_lock_define_recursive(CLASS,NAME) \
080:   CLASS __rtld_lock_recursive_t NAME;
081: 
082: /* Define an initialized lock variable NAME with storage class CLASS.
083: 
084:    For the C library we take a deeper look at the initializer.  For
085:    this implementation all fields are initialized to zero.  Therefore
086:    we don't initialize the variable which allows putting it into the
087:    BSS section.  (Except on PA-RISC and other odd architectures, where
088:    initialized locks must be set to one due to the lack of normal
089:    atomic operations.) */
090: 
091: #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread)
092: # if LLL_LOCK_INITIALIZER == 0
093: #  define __libc_lock_define_initialized(CLASS,NAME) \
094:   CLASS __libc_lock_t NAME;
095: # else
096: #  define __libc_lock_define_initialized(CLASS,NAME) \
097:   CLASS __libc_lock_t NAME = LLL_LOCK_INITIALIZER;
098: # endif
099: #else
100: # if __LT_SPINLOCK_INIT == 0
101: #  define __libc_lock_define_initialized(CLASS,NAME) \
102:   CLASS __libc_lock_t NAME;
103: # else
104: #  define __libc_lock_define_initialized(CLASS,NAME) \
105:   CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER;
106: # endif
107: #endif
108: 
109: #define __libc_rwlock_define_initialized(CLASS,NAME) \
110:   CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER;
111: 
112: /* Define an initialized recursive lock variable NAME with storage
113:    class CLASS.  */
114: #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread)
115: # if LLL_LOCK_INITIALIZER == 0
116: #  define __libc_lock_define_initialized_recursive(CLASS,NAME) \
117:   CLASS __libc_lock_recursive_t NAME;
118: # else
119: #  define __libc_lock_define_initialized_recursive(CLASS,NAME) \
120:   CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER;
121: # endif
122: # define _LIBC_LOCK_RECURSIVE_INITIALIZER \
123:   { LLL_LOCK_INITIALIZER, 0, NULL }
124: #else
125: # define __libc_lock_define_initialized_recursive(CLASS,NAME) \
126:   CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER;
127: # define _LIBC_LOCK_RECURSIVE_INITIALIZER \
128:   {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP}
129: #endif
130: 
131: #define __rtld_lock_define_initialized_recursive(CLASS,NAME) \
132:   CLASS __rtld_lock_recursive_t NAME = _RTLD_LOCK_RECURSIVE_INITIALIZER;
133: #define _RTLD_LOCK_RECURSIVE_INITIALIZER \
134:   {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP}
135: 
136: #define __rtld_lock_initialize(NAME) \
137:   (void) ((NAME) = (__rtld_lock_recursive_t) _RTLD_LOCK_RECURSIVE_INITIALIZER)
138: 
139: /* If we check for a weakly referenced symbol and then perform a
140:    normal jump to it te code generated for some platforms in case of
141:    PIC is unnecessarily slow.  What would happen is that the function
142:    is first referenced as data and then it is called indirectly
143:    through the PLT.  We can make this a direct jump.  */
144: #ifdef __PIC__
145: # define __libc_maybe_call(FUNC, ARGS, ELSE) \
146:   (__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \
147:                     _fn != NULL ? (*_fn) ARGS : ELSE; }))
148: #else
149: # define __libc_maybe_call(FUNC, ARGS, ELSE) \
150:   (FUNC != NULL ? FUNC ARGS : ELSE)
151: #endif
152: 
153: /* Call thread functions through the function pointer table.  */
154: #if defined SHARED && !defined NOT_IN_libc
155: # define PTFAVAIL(NAME) __libc_pthread_functions_init
156: # define __libc_ptf_call(FUNC, ARGS, ELSE) \
157:   (__libc_pthread_functions_init ? PTHFCT_CALL (ptr_##FUNC, ARGS) : ELSE)
158: # define __libc_ptf_call_always(FUNC, ARGS) \
159:   PTHFCT_CALL (ptr_##FUNC, ARGS)
160: #else
161: # define PTFAVAIL(NAME) (NAME != NULL)
162: # define __libc_ptf_call(FUNC, ARGS, ELSE) \
163:   __libc_maybe_call (FUNC, ARGS, ELSE)
164: # define __libc_ptf_call_always(FUNC, ARGS) \
165:   FUNC ARGS
166: #endif
167: 
168: 
169: /* Initialize the named lock variable, leaving it in a consistent, unlocked
170:    state.  */
171: #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread)
172: # define __libc_lock_init(NAME) ((NAME) = LLL_LOCK_INITIALIZER, 0)
173: #else
174: # define __libc_lock_init(NAME) \
175:   __libc_maybe_call (__pthread_mutex_init, (&(NAME), NULL), 0)
176: #endif
177: #if defined SHARED && !defined NOT_IN_libc
178: /* ((NAME) = (__libc_rwlock_t) PTHREAD_RWLOCK_INITIALIZER, 0) is
179:    inefficient.  */
180: # define __libc_rwlock_init(NAME) \
181:   (__builtin_memset (&(NAME), '\0', sizeof (NAME)), 0)
182: #else
183: # define __libc_rwlock_init(NAME) \
184:   __libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0)
185: #endif
186: 
187: /* Same as last but this time we initialize a recursive mutex.  */
188: #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread)
189: # define __libc_lock_init_recursive(NAME) \
190:   ((NAME) = (__libc_lock_recursive_t) _LIBC_LOCK_RECURSIVE_INITIALIZER, 0)
191: #else
192: # define __libc_lock_init_recursive(NAME) \
193:   do {                                                                        \
194:     if (__pthread_mutex_init != NULL)                                         \
195:       {                                                                       \
196:         pthread_mutexattr_t __attr;                                           \
197:         __pthread_mutexattr_init (&__attr);                                   \
198:         __pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP);    \
199:         __pthread_mutex_init (&(NAME).mutex, &__attr);                        \
200:         __pthread_mutexattr_destroy (&__attr);                                \
201:       }                                                                       \
202:   } while (0)
203: #endif
204: 
205: #define __rtld_lock_init_recursive(NAME) \
206:   do {                                                                        \
207:     if (__pthread_mutex_init != NULL)                                         \
208:       {                                                                       \
209:         pthread_mutexattr_t __attr;                                           \
210:         __pthread_mutexattr_init (&__attr);                                   \
211:         __pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP);    \
212:         __pthread_mutex_init (&(NAME).mutex, &__attr);                        \
213:         __pthread_mutexattr_destroy (&__attr);                                \
214:       }                                                                       \
215:   } while (0)
216: 
217: /* Finalize the named lock variable, which must be locked.  It cannot be
218:    used again until __libc_lock_init is called again on it.  This must be
219:    called on a lock variable before the containing storage is reused.  */
220: #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread)
221: # define __libc_lock_fini(NAME) ((void) 0)
222: #else
223: # define __libc_lock_fini(NAME) \
224:   __libc_maybe_call (__pthread_mutex_destroy, (&(NAME)), 0)
225: #endif
226: #if defined SHARED && !defined NOT_IN_libc
227: # define __libc_rwlock_fini(NAME) ((void) 0)
228: #else
229: # define __libc_rwlock_fini(NAME) \
230:   __libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0)
231: #endif
232: 
233: /* Finalize recursive named lock.  */
234: #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread)
235: # define __libc_lock_fini_recursive(NAME) ((void) 0)
236: #else
237: # define __libc_lock_fini_recursive(NAME) \
238:   __libc_maybe_call (__pthread_mutex_destroy, (&(NAME)), 0)
239: #endif
240: 
241: /* Lock the named lock variable.  */
242: #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread)
243: # if __OPTION_EGLIBC_BIG_MACROS != 1
244: /* EGLIBC: Declare wrapper function for a big macro if either
245:    !__OPTION_EGLIBC_BIG_MACROS or we are using a back door from
246:    small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2).  */
247: extern void __libc_lock_lock_fn (__libc_lock_t *);
248: libc_hidden_proto (__libc_lock_lock_fn);
249: # endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */
250: # if __OPTION_EGLIBC_BIG_MACROS
251: # define __libc_lock_lock(NAME) \
252:   ({ lll_lock (NAME, LLL_PRIVATE); 0; })
253: # else
254: #  define __libc_lock_lock(NAME)                \
255:   __libc_lock_lock_fn (&(NAME))
256: # endif /* __OPTION_EGLIBC_BIG_MACROS */
257: #else
258: # define __libc_lock_lock(NAME) \
259:   __libc_maybe_call (__pthread_mutex_lock, (&(NAME)), 0)
260: #endif
261: #define __libc_rwlock_rdlock(NAME) \
262:   __libc_ptf_call (__pthread_rwlock_rdlock, (&(NAME)), 0)
263: #define __libc_rwlock_wrlock(NAME) \
264:   __libc_ptf_call (__pthread_rwlock_wrlock, (&(NAME)), 0)
265: 
266: /* Lock the recursive named lock variable.  */
267: #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread)
268: # if __OPTION_EGLIBC_BIG_MACROS != 1
269: /* EGLIBC: Declare wrapper function for a big macro if either
270:    !__OPTION_EGLIBC_BIG_MACROS or we are using a back door from
271:    small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2).  */
272: extern void __libc_lock_lock_recursive_fn (__libc_lock_recursive_t *);
273: libc_hidden_proto (__libc_lock_lock_recursive_fn);
274: # endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */
275: # if __OPTION_EGLIBC_BIG_MACROS
276: # define __libc_lock_lock_recursive(NAME) \
277:   do {                                                                        \
278:     void *self = THREAD_SELF;                                                 \
279:     if ((NAME).owner != self)                                                 \
280:       {                                                                       \
281:         lll_lock ((NAME).lock, LLL_PRIVATE);                                  \
282:         (NAME).owner = self;                                                  \
283:       }                                                                       \
284:     ++(NAME).cnt;                                                             \
285:   } while (0)
286: # else
287: # define __libc_lock_lock_recursive(NAME)                               \
288:   __libc_lock_lock_recursive_fn (&(NAME))
289: # endif /* __OPTION_EGLIBC_BIG_MACROS */
290: #else
291: # define __libc_lock_lock_recursive(NAME) \
292:   __libc_maybe_call (__pthread_mutex_lock, (&(NAME).mutex), 0)
293: #endif
294: 
295: /* Try to lock the named lock variable.  */
296: #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread)
297: # if __OPTION_EGLIBC_BIG_MACROS != 1
298: /* EGLIBC: Declare wrapper function for a big macro if either
299:    !__OPTION_EGLIBC_BIG_MACROS or we are using a back door from
300:    small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2).  */
301: extern int __libc_lock_trylock_fn (__libc_lock_t *);
302: libc_hidden_proto (__libc_lock_trylock_fn);
303: # endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */
304: # if __OPTION_EGLIBC_BIG_MACROS
305: # define __libc_lock_trylock(NAME) \
306:   lll_trylock (NAME)
307: # else
308: # define __libc_lock_trylock(NAME) \
309:   __libc_lock_trylock_fn (&(NAME))
310: # endif /* __OPTION_EGLIBC_BIG_MACROS */
311: #else
312: # define __libc_lock_trylock(NAME) \
313:   __libc_maybe_call (__pthread_mutex_trylock, (&(NAME)), 0)
314: #endif
315: #define __libc_rwlock_tryrdlock(NAME) \
316:   __libc_maybe_call (__pthread_rwlock_tryrdlock, (&(NAME)), 0)
317: #define __libc_rwlock_trywrlock(NAME) \
318:   __libc_maybe_call (__pthread_rwlock_trywrlock, (&(NAME)), 0)
319: 
320: /* Try to lock the recursive named lock variable.  */
321: #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread)
322: # if __OPTION_EGLIBC_BIG_MACROS != 1
323: /* EGLIBC: Declare wrapper function for a big macro if either
324:    !__OPTION_EGLIBC_BIG_MACROS or we are using a back door from
325:    small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2).  */
326: extern int __libc_lock_trylock_recursive_fn (__libc_lock_recursive_t *);
327: libc_hidden_proto (__libc_lock_trylock_recursive_fn);
328: # endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */
329: # if __OPTION_EGLIBC_BIG_MACROS
330: # define __libc_lock_trylock_recursive(NAME) \
331:   ({                                                                          \
332:     int result = 0;                                                           \
333:     void *self = THREAD_SELF;                                                 \
334:     if ((NAME).owner != self)                                                 \
335:       {                                                                       \
336:         if (lll_trylock ((NAME).lock) == 0)                                   \
337:           {                                                                   \
338:             (NAME).owner = self;                                              \
339:             (NAME).cnt = 1;                                                   \
340:           }                                                                   \
341:         else                                                                  \
342:           result = EBUSY;                                                     \
343:       }                                                                       \
344:     else                                                                      \
345:       ++(NAME).cnt;                                                           \
346:     result;                                                                   \
347:   })
348: # else
349: # define __libc_lock_trylock_recursive(NAME) \
350:   __libc_lock_trylock_recursive_fn (&(NAME))
351: # endif /* __OPTION_EGLIBC_BIG_MACROS */
352: #else
353: # define __libc_lock_trylock_recursive(NAME) \
354:   __libc_maybe_call (__pthread_mutex_trylock, (&(NAME)), 0)
355: #endif
356: 
357: #define __rtld_lock_trylock_recursive(NAME) \
358:   __libc_maybe_call (__pthread_mutex_trylock, (&(NAME).mutex), 0)
359: 
360: /* Unlock the named lock variable.  */
361: #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread)
362: # if __OPTION_EGLIBC_BIG_MACROS != 1
363: /* EGLIBC: Declare wrapper function for a big macro if either
364:    !__OPTION_EGLIBC_BIG_MACROS, or we are using a back door from
365:    small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2).  */
366: extern void __libc_lock_unlock_fn (__libc_lock_t *);
367: libc_hidden_proto (__libc_lock_unlock_fn);
368: # endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */
369: # if __OPTION_EGLIBC_BIG_MACROS
370: # define __libc_lock_unlock(NAME) \
371:   lll_unlock (NAME, LLL_PRIVATE)
372: # else
373: # define __libc_lock_unlock(NAME) \
374:   __libc_lock_unlock_fn (&(NAME))
375: # endif /* __OPTION_EGLIBC_BIG_MACROS */
376: #else
377: # define __libc_lock_unlock(NAME) \
378:   __libc_maybe_call (__pthread_mutex_unlock, (&(NAME)), 0)
379: #endif
380: #define __libc_rwlock_unlock(NAME) \
381:   __libc_ptf_call (__pthread_rwlock_unlock, (&(NAME)), 0)
382: 
383: /* Unlock the recursive named lock variable.  */
384: #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread)
385: # if __OPTION_EGLIBC_BIG_MACROS != 1
386: /* EGLIBC: Declare wrapper function for a big macro if either
387:    !__OPTION_EGLIBC_BIG_MACROS, or we are using a back door from
388:    small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2).  */
389: extern void __libc_lock_unlock_recursive_fn (__libc_lock_recursive_t *);
390: libc_hidden_proto (__libc_lock_unlock_recursive_fn);
391: # endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */
392: # if __OPTION_EGLIBC_BIG_MACROS
393: /* We do no error checking here.  */
394: # define __libc_lock_unlock_recursive(NAME) \
395:   do {                                                                        \
396:     if (--(NAME).cnt == 0)                                                    \
397:       {                                                                       \
398:         (NAME).owner = NULL;                                                  \
399:         lll_unlock ((NAME).lock, LLL_PRIVATE);                                \
400:       }                                                                       \
401:   } while (0)
402: # else
403: # define __libc_lock_unlock_recursive(NAME) \
404:   __libc_lock_unlock_recursive_fn (&(NAME))
405: # endif /* __OPTION_EGLIBC_BIG_MACROS */
406: #else
407: # define __libc_lock_unlock_recursive(NAME) \
408:   __libc_maybe_call (__pthread_mutex_unlock, (&(NAME)), 0)
409: #endif
410: 
411: #if defined _LIBC && defined SHARED
412: # define __rtld_lock_default_lock_recursive(lock) \
413:   ++((pthread_mutex_t *)(lock))->__data.__count;
414: 
415: # define __rtld_lock_default_unlock_recursive(lock) \
416:   --((pthread_mutex_t *)(lock))->__data.__count;
417: 
418: # define __rtld_lock_lock_recursive(NAME) \
419:   GL(dl_rtld_lock_recursive) (&(NAME).mutex)
420: 
421: # define __rtld_lock_unlock_recursive(NAME) \
422:   GL(dl_rtld_unlock_recursive) (&(NAME).mutex)
423: #else
424: # define __rtld_lock_lock_recursive(NAME) \
425:   __libc_maybe_call (__pthread_mutex_lock, (&(NAME).mutex), 0)
426: 
427: # define __rtld_lock_unlock_recursive(NAME) \
428:   __libc_maybe_call (__pthread_mutex_unlock, (&(NAME).mutex), 0)
429: #endif
430: 
431: /* Define once control variable.  */
432: #if PTHREAD_ONCE_INIT == 0
433: /* Special case for static variables where we can avoid the initialization
434:    if it is zero.  */
435: # define __libc_once_define(CLASS, NAME) \
436:   CLASS pthread_once_t NAME
437: #else
438: # define __libc_once_define(CLASS, NAME) \
439:   CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT
440: #endif
441: 
442: /* Call handler iff the first call.  */
443: #define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
444:   do {                                                                        \
445:     if (PTFAVAIL (__pthread_once))                                            \
446:       __libc_ptf_call_always (__pthread_once, (&(ONCE_CONTROL),               \
447:                                                INIT_FUNCTION));               \
448:     else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) {                           \
449:       INIT_FUNCTION ();                                                       \
450:       (ONCE_CONTROL) |= 2;                                                    \
451:     }                                                                         \
452:   } while (0)
453: 
454: 
455: /* Note that for I/O cleanup handling we are using the old-style
456:    cancel handling.  It does not have to be integrated with C++ snce
457:    no C++ code is called in the middle.  The old-style handling is
458:    faster and the support is not going away.  */
459: extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer,
460:                                    void (*routine) (void *), void *arg);
461: extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer,
462:                                   int execute);
463: extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer,
464:                                          void (*routine) (void *), void *arg);
465: extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer,
466:                                           int execute);
467: 
468: /* Start critical region with cleanup.  */
469: #define __libc_cleanup_region_start(DOIT, FCT, ARG) \
470:   { struct _pthread_cleanup_buffer _buffer;                                   \
471:     int _avail;                                                               \
472:     if (DOIT) {                                                               \
473:       _avail = PTFAVAIL (_pthread_cleanup_push_defer);                        \
474:       if (_avail) {                                                           \
475:         __libc_ptf_call_always (_pthread_cleanup_push_defer, (&_buffer, FCT,  \
476:                                                               ARG));          \
477:       } else {                                                                \
478:         _buffer.__routine = (FCT);                                            \
479:         _buffer.__arg = (ARG);                                                \
480:       }                                                                       \
481:     } else {                                                                  \
482:       _avail = 0;                                                             \
483:     }
484: 
485: /* End critical region with cleanup.  */
486: #define __libc_cleanup_region_end(DOIT) \
487:     if (_avail) {                                                             \
488:       __libc_ptf_call_always (_pthread_cleanup_pop_restore, (&_buffer, DOIT));\
489:     } else if (DOIT)                                                          \
490:       _buffer.__routine (_buffer.__arg);                                      \
491:   }
492: 
493: /* Sometimes we have to exit the block in the middle.  */
494: #define __libc_cleanup_end(DOIT) \
495:     if (_avail) {                                                             \
496:       __libc_ptf_call_always (_pthread_cleanup_pop_restore, (&_buffer, DOIT));\
497:     } else if (DOIT)                                                          \
498:       _buffer.__routine (_buffer.__arg)
499: 
500: 
501: /* Normal cleanup handling, based on C cleanup attribute.  */
502: __extern_inline void
503: __libc_cleanup_routine (struct __pthread_cleanup_frame *f)
504: {
505:   if (f->__do_it)
506:     f->__cancel_routine (f->__cancel_arg);
507: }
508: 
509: #define __libc_cleanup_push(fct, arg) \
510:   do {                                                                        \
511:     struct __pthread_cleanup_frame __clframe                                  \
512:       __attribute__ ((__cleanup__ (__libc_cleanup_routine)))                  \
513:       = { .__cancel_routine = (fct), .__cancel_arg = (arg),                   \
514:           .__do_it = 1 };
515: 
516: #define __libc_cleanup_pop(execute) \
517:     __clframe.__do_it = (execute);                                            \
518:   } while (0)
519: 
520: 
521: /* Create thread-specific key.  */
522: #define __libc_key_create(KEY, DESTRUCTOR) \
523:   __libc_ptf_call (__pthread_key_create, (KEY, DESTRUCTOR), 1)
524: 
525: /* Get thread-specific data.  */
526: #define __libc_getspecific(KEY) \
527:   __libc_ptf_call (__pthread_getspecific, (KEY), NULL)
528: 
529: /* Set thread-specific data.  */
530: #define __libc_setspecific(KEY, VALUE) \
531:   __libc_ptf_call (__pthread_setspecific, (KEY, VALUE), 0)
532: 
533: 
534: /* Register handlers to execute before and after `fork'.  Note that the
535:    last parameter is NULL.  The handlers registered by the libc are
536:    never removed so this is OK.  */
537: #define __libc_atfork(PREPARE, PARENT, CHILD) \
538:   __register_atfork (PREPARE, PARENT, CHILD, NULL)
539: extern int __register_atfork (void (*__prepare) (void),
540:                               void (*__parent) (void),
541:                               void (*__child) (void),
542:                               void *__dso_handle);
543: 
544: /* Functions that are used by this file and are internal to the GNU C
545:    library.  */
546: 
547: extern int __pthread_mutex_init (pthread_mutex_t *__mutex,
548:                                  __const pthread_mutexattr_t *__mutex_attr);
549: 
550: extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex);
551: 
552: extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex);
553: 
554: extern int __pthread_mutex_lock (pthread_mutex_t *__mutex);
555: 
556: extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex);
557: 
558: extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr);
559: 
560: extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr);
561: 
562: extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr,
563:                                         int __kind);
564: 
565: #ifdef __USE_UNIX98
566: extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock,
567:                                   __const pthread_rwlockattr_t *__attr);
568: 
569: extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock);
570: 
571: extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock);
572: 
573: extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock);
574: 
575: extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock);
576: 
577: extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock);
578: 
579: extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock);
580: #endif
581: 
582: extern int __pthread_key_create (pthread_key_t *__key,
583:                                  void (*__destr_function) (void *));
584: 
585: extern int __pthread_setspecific (pthread_key_t __key,
586:                                   __const void *__pointer);
587: 
588: extern void *__pthread_getspecific (pthread_key_t __key);
589: 
590: extern int __pthread_once (pthread_once_t *__once_control,
591:                            void (*__init_routine) (void));
592: 
593: extern int __pthread_atfork (void (*__prepare) (void),
594:                              void (*__parent) (void),
595:                              void (*__child) (void));
596: 
597: 
598: 
599: /* Make the pthread functions weak so that we can elide them from
600:    single-threaded processes.  */
601: #ifndef __NO_WEAK_PTHREAD_ALIASES
602: # ifdef weak_extern
603: #  if _LIBC
604: #   include <bp-sym.h>
605: #  else
606: #   define BP_SYM(sym) sym
607: #  endif
608: weak_extern (BP_SYM (__pthread_mutex_init))
609: weak_extern (BP_SYM (__pthread_mutex_destroy))
610: weak_extern (BP_SYM (__pthread_mutex_lock))
611: weak_extern (BP_SYM (__pthread_mutex_trylock))
612: weak_extern (BP_SYM (__pthread_mutex_unlock))
613: weak_extern (BP_SYM (__pthread_mutexattr_init))
614: weak_extern (BP_SYM (__pthread_mutexattr_destroy))
615: weak_extern (BP_SYM (__pthread_mutexattr_settype))
616: weak_extern (BP_SYM (__pthread_rwlock_init))
617: weak_extern (BP_SYM (__pthread_rwlock_destroy))
618: weak_extern (BP_SYM (__pthread_rwlock_rdlock))
619: weak_extern (BP_SYM (__pthread_rwlock_tryrdlock))
620: weak_extern (BP_SYM (__pthread_rwlock_wrlock))
621: weak_extern (BP_SYM (__pthread_rwlock_trywrlock))
622: weak_extern (BP_SYM (__pthread_rwlock_unlock))
623: weak_extern (BP_SYM (__pthread_key_create))
624: weak_extern (BP_SYM (__pthread_setspecific))
625: weak_extern (BP_SYM (__pthread_getspecific))
626: weak_extern (BP_SYM (__pthread_once))
627: weak_extern (__pthread_initialize)
628: weak_extern (__pthread_atfork)
629: weak_extern (BP_SYM (_pthread_cleanup_push_defer))
630: weak_extern (BP_SYM (_pthread_cleanup_pop_restore))
631: weak_extern (BP_SYM (pthread_setcancelstate))
632: # else
633: #  pragma weak __pthread_mutex_init
634: #  pragma weak __pthread_mutex_destroy
635: #  pragma weak __pthread_mutex_lock
636: #  pragma weak __pthread_mutex_trylock
637: #  pragma weak __pthread_mutex_unlock
638: #  pragma weak __pthread_mutexattr_init
639: #  pragma weak __pthread_mutexattr_destroy
640: #  pragma weak __pthread_mutexattr_settype
641: #  pragma weak __pthread_rwlock_destroy
642: #  pragma weak __pthread_rwlock_rdlock
643: #  pragma weak __pthread_rwlock_tryrdlock
644: #  pragma weak __pthread_rwlock_wrlock
645: #  pragma weak __pthread_rwlock_trywrlock
646: #  pragma weak __pthread_rwlock_unlock
647: #  pragma weak __pthread_key_create
648: #  pragma weak __pthread_setspecific
649: #  pragma weak __pthread_getspecific
650: #  pragma weak __pthread_once
651: #  pragma weak __pthread_initialize
652: #  pragma weak __pthread_atfork
653: #  pragma weak _pthread_cleanup_push_defer
654: #  pragma weak _pthread_cleanup_pop_restore
655: #  pragma weak pthread_setcancelstate
656: # endif
657: #endif
658: 
659: #endif  /* bits/libc-lock.h */
660: 


for client (none)
© Andrew Scott 2006 - 2025,
All Rights Reserved
http://www.andrew-scott.uk/
Andrew Scott
http://www.andrew-scott.co.uk/