(root)/
glibc-2.38/
sysdeps/
nptl/
libc-lockP.h
       1  /* Private libc-internal interface for mutex locks.  NPTL version.
       2     Copyright (C) 1996-2023 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 License as
       7     published by the Free Software Foundation; either version 2.1 of the
       8     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; see the file COPYING.LIB.  If
      17     not, see <https://www.gnu.org/licenses/>.  */
      18  
      19  #ifndef _LIBC_LOCKP_H
      20  #define _LIBC_LOCKP_H 1
      21  
      22  #include <pthread.h>
      23  #define __need_NULL
      24  #include <stddef.h>
      25  
      26  
      27  /* Fortunately Linux now has a mean to do locking which is realtime
      28     safe without the aid of the thread library.  We also need no fancy
      29     options like error checking mutexes etc.  We only need simple
      30     locks, maybe recursive.  This can be easily and cheaply implemented
      31     using futexes.  We will use them everywhere except in ld.so since
      32     ld.so might be used on old kernels with a different libc.so.  */
      33  #include <lowlevellock.h>
      34  #include <tls.h>
      35  #include <libc-lock-arch.h>
      36  
      37  /* Mutex type.  */
      38  typedef int __libc_lock_t __LIBC_LOCK_ALIGNMENT;
      39  typedef struct { pthread_mutex_t mutex; } __rtld_lock_recursive_t;
      40  typedef pthread_rwlock_t __libc_rwlock_t;
      41  
      42  /* Define a lock variable NAME with storage class CLASS.  The lock must be
      43     initialized with __libc_lock_init before it can be used (or define it
      44     with __libc_lock_define_initialized, below).  Use `extern' for CLASS to
      45     declare a lock defined in another module.  In public structure
      46     definitions you must use a pointer to the lock structure (i.e., NAME
      47     begins with a `*'), because its storage size will not be known outside
      48     of libc.  */
      49  #define __libc_lock_define(CLASS,NAME) \
      50    CLASS __libc_lock_t NAME;
      51  #define __libc_rwlock_define(CLASS,NAME) \
      52    CLASS __libc_rwlock_t NAME;
      53  #define __rtld_lock_define_recursive(CLASS,NAME) \
      54    CLASS __rtld_lock_recursive_t NAME;
      55  
      56  /* Define an initialized lock variable NAME with storage class CLASS.
      57  
      58     For the C library we take a deeper look at the initializer.  For
      59     this implementation all fields are initialized to zero.  Therefore
      60     we don't initialize the variable which allows putting it into the
      61     BSS section.  */
      62  
      63  _Static_assert (LLL_LOCK_INITIALIZER == 0, "LLL_LOCK_INITIALIZER != 0");
      64  #define _LIBC_LOCK_INITIALIZER LLL_LOCK_INITIALIZER
      65  #define __libc_lock_define_initialized(CLASS,NAME) \
      66    CLASS __libc_lock_t NAME;
      67  
      68  #define __libc_rwlock_define_initialized(CLASS,NAME) \
      69    CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER;
      70  
      71  #define __rtld_lock_define_initialized_recursive(CLASS,NAME) \
      72    CLASS __rtld_lock_recursive_t NAME = _RTLD_LOCK_RECURSIVE_INITIALIZER;
      73  #define _RTLD_LOCK_RECURSIVE_INITIALIZER \
      74    {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP}
      75  
      76  #define __rtld_lock_initialize(NAME) \
      77    (void) ((NAME) = (__rtld_lock_recursive_t) _RTLD_LOCK_RECURSIVE_INITIALIZER)
      78  
      79  /* If we check for a weakly referenced symbol and then perform a
      80     normal jump to it te code generated for some platforms in case of
      81     PIC is unnecessarily slow.  What would happen is that the function
      82     is first referenced as data and then it is called indirectly
      83     through the PLT.  We can make this a direct jump.  */
      84  #ifdef __PIC__
      85  # define __libc_maybe_call(FUNC, ARGS, ELSE) \
      86    (__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \
      87  		    _fn != NULL ? (*_fn) ARGS : ELSE; }))
      88  #else
      89  # define __libc_maybe_call(FUNC, ARGS, ELSE) \
      90    (FUNC != NULL ? FUNC ARGS : ELSE)
      91  #endif
      92  
      93  /* All previously forwarded functions are now called directly (either
      94     via local call in libc, or through a __export), but __libc_ptf_call
      95     is still used in generic code shared with Hurd.  */
      96  #define PTFAVAIL(NAME) 1
      97  #define __libc_ptf_call(FUNC, ARGS, ELSE) FUNC ARGS
      98  #define __libc_ptf_call_always(FUNC, ARGS) FUNC ARGS
      99  
     100  /* Initialize the named lock variable, leaving it in a consistent, unlocked
     101     state.  */
     102  #define __libc_lock_init(NAME) ((void) ((NAME) = LLL_LOCK_INITIALIZER))
     103  #define __libc_rwlock_init(NAME) __pthread_rwlock_init (&(NAME), NULL)
     104  
     105  /* Finalize the named lock variable, which must be locked.  It cannot be
     106     used again until __libc_lock_init is called again on it.  This must be
     107     called on a lock variable before the containing storage is reused.  */
     108  #define __libc_lock_fini(NAME) ((void) 0)
     109  #define __libc_rwlock_fini(NAME) ((void) 0)
     110  
     111  /* Lock the named lock variable.  */
     112  #define __libc_lock_lock(NAME) ({ lll_lock (NAME, LLL_PRIVATE); 0; })
     113  #define __libc_rwlock_rdlock(NAME) __pthread_rwlock_rdlock (&(NAME))
     114  #define __libc_rwlock_wrlock(NAME) __pthread_rwlock_wrlock (&(NAME))
     115  
     116  /* Try to lock the named lock variable.  */
     117  #define __libc_lock_trylock(NAME) lll_trylock (NAME)
     118  
     119  /* Unlock the named lock variable.  */
     120  #define __libc_lock_unlock(NAME) lll_unlock (NAME, LLL_PRIVATE)
     121  #define __libc_rwlock_unlock(NAME) __pthread_rwlock_unlock (&(NAME))
     122  
     123  #if IS_IN (rtld)
     124  # define __rtld_lock_lock_recursive(NAME) \
     125    ___rtld_mutex_lock (&(NAME).mutex)
     126  
     127  # define __rtld_lock_unlock_recursive(NAME) \
     128    ___rtld_mutex_unlock (&(NAME).mutex)
     129  #else /* Not in the dynamic loader.  */
     130  # define __rtld_lock_lock_recursive(NAME) \
     131    __pthread_mutex_lock (&(NAME).mutex)
     132  
     133  # define __rtld_lock_unlock_recursive(NAME) \
     134    __pthread_mutex_unlock (&(NAME).mutex)
     135  #endif
     136  
     137  /* Define once control variable.  */
     138  #if PTHREAD_ONCE_INIT == 0
     139  /* Special case for static variables where we can avoid the initialization
     140     if it is zero.  */
     141  # define __libc_once_define(CLASS, NAME) \
     142    CLASS pthread_once_t NAME
     143  #else
     144  # define __libc_once_define(CLASS, NAME) \
     145    CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT
     146  #endif
     147  
     148  /* Call handler iff the first call.  Use a local call in libc, but the
     149     global pthread_once symbol elsewhere.  */
     150  #if IS_IN (libc)
     151  # define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
     152    __pthread_once (&(ONCE_CONTROL), INIT_FUNCTION)
     153  #else
     154  # define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
     155    pthread_once (&(ONCE_CONTROL), INIT_FUNCTION)
     156  #endif
     157  
     158  /* Get once control variable.  */
     159  #define __libc_once_get(ONCE_CONTROL)	((ONCE_CONTROL) != PTHREAD_ONCE_INIT)
     160  
     161  /* __libc_cleanup_push and __libc_cleanup_pop depend on exception
     162     handling and stack unwinding.  */
     163  #ifdef __EXCEPTIONS
     164  
     165  /* Normal cleanup handling, based on C cleanup attribute.  */
     166  static __always_inline void
     167  __libc_cleanup_routine (struct __pthread_cleanup_frame *f)
     168  {
     169    if (f->__do_it)
     170      f->__cancel_routine (f->__cancel_arg);
     171  }
     172  
     173  # define __libc_cleanup_push(fct, arg) \
     174    do {									      \
     175      struct __pthread_cleanup_frame __clframe				      \
     176        __attribute__ ((__cleanup__ (__libc_cleanup_routine)))		      \
     177        = { .__cancel_routine = (fct), .__cancel_arg = (arg),		      \
     178  	  .__do_it = 1 };
     179  
     180  # define __libc_cleanup_pop(execute) \
     181      __clframe.__do_it = (execute);					      \
     182    } while (0)
     183  #endif /* __EXCEPTIONS */
     184  
     185  /* Register handlers to execute before and after `fork'.  Note that the
     186     last parameter is NULL.  The handlers registered by the libc are
     187     never removed so this is OK.  */
     188  extern int __register_atfork (void (*__prepare) (void),
     189  			      void (*__parent) (void),
     190  			      void (*__child) (void),
     191  			      void *__dso_handle);
     192  
     193  /* Functions that are used by this file and are internal to the GNU C
     194     library.  */
     195  
     196  extern int __pthread_mutex_init (pthread_mutex_t *__mutex,
     197  				 const pthread_mutexattr_t *__mutex_attr);
     198  libc_hidden_proto (__pthread_mutex_init)
     199  extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex);
     200  libc_hidden_proto (__pthread_mutex_destroy)
     201  extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex);
     202  
     203  extern int __pthread_mutex_lock (pthread_mutex_t *__mutex);
     204  libc_hidden_proto (__pthread_mutex_lock)
     205  extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex);
     206  libc_hidden_proto (__pthread_mutex_unlock)
     207  
     208  extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr);
     209  
     210  extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock,
     211  				  const pthread_rwlockattr_t *__attr);
     212  libc_hidden_proto (__pthread_rwlock_init)
     213  
     214  extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock);
     215  
     216  extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock);
     217  libc_hidden_proto (__pthread_rwlock_rdlock)
     218  
     219  extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock);
     220  libc_hidden_proto (__pthread_rwlock_wrlock)
     221  
     222  extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock);
     223  libc_hidden_proto (__pthread_rwlock_unlock)
     224  extern int __pthread_once (pthread_once_t *__once_control,
     225  			   void (*__init_routine) (void));
     226  libc_hidden_proto (__pthread_once)
     227  
     228  extern int __pthread_atfork (void (*__prepare) (void),
     229  			     void (*__parent) (void),
     230  			     void (*__child) (void));
     231  
     232  extern int __pthread_setcancelstate (int state, int *oldstate);
     233  libc_hidden_proto (__pthread_setcancelstate)
     234  
     235  /* Make the pthread functions weak so that we can elide them from
     236     single-threaded processes.  */
     237  #ifndef __NO_WEAK_PTHREAD_ALIASES
     238  # ifdef weak_extern
     239  weak_extern (__pthread_mutex_trylock)
     240  weak_extern (__pthread_mutexattr_destroy)
     241  weak_extern (__pthread_initialize)
     242  weak_extern (__pthread_atfork)
     243  # else
     244  #  pragma weak __pthread_mutex_trylock
     245  #  pragma weak __pthread_mutexattr_destroy
     246  #  pragma weak __pthread_initialize
     247  #  pragma weak __pthread_atfork
     248  # endif
     249  #endif
     250  
     251  #endif	/* libc-lockP.h */