(root)/
glibc-2.38/
sysdeps/
nptl/
libc-lock.h
       1  /* 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_LOCK_H
      20  #define _LIBC_LOCK_H 1
      21  
      22  #include <pthread.h>
      23  #define __need_NULL
      24  #include <stddef.h>
      25  #include <libc-lock-arch.h>
      26  
      27  
      28  /* Mutex type.  */
      29  #if defined _LIBC || defined _IO_MTSAFE_IO
      30  # if (!IS_IN (libc) && !IS_IN (libpthread)) || !defined _LIBC
      31  typedef struct { pthread_mutex_t mutex; } __libc_lock_recursive_t;
      32  # else
      33  typedef struct
      34  {
      35    int lock __LIBC_LOCK_ALIGNMENT;
      36    int cnt;
      37    void *owner;
      38  } __libc_lock_recursive_t;
      39  # endif
      40  #else
      41  typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
      42  #endif
      43  
      44  /* Define a lock variable NAME with storage class CLASS.  The lock must be
      45     initialized with __libc_lock_init before it can be used (or define it
      46     with __libc_lock_define_initialized, below).  Use `extern' for CLASS to
      47     declare a lock defined in another module.  In public structure
      48     definitions you must use a pointer to the lock structure (i.e., NAME
      49     begins with a `*'), because its storage size will not be known outside
      50     of libc.  */
      51  #define __libc_lock_define_recursive(CLASS,NAME) \
      52    CLASS __libc_lock_recursive_t NAME;
      53  
      54  /* Define an initialized recursive lock variable NAME with storage
      55     class CLASS.  */
      56  #if defined _LIBC && (IS_IN (libc) || IS_IN (libpthread))
      57  # define __libc_lock_define_initialized_recursive(CLASS, NAME) \
      58    CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER;
      59  # define _LIBC_LOCK_RECURSIVE_INITIALIZER \
      60    { LLL_LOCK_INITIALIZER, 0, NULL }
      61  #else
      62  # define __libc_lock_define_initialized_recursive(CLASS,NAME) \
      63    CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER;
      64  # define _LIBC_LOCK_RECURSIVE_INITIALIZER \
      65    {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP}
      66  #endif
      67  
      68  /* Initialize a recursive mutex.  */
      69  #if defined _LIBC && (IS_IN (libc) || IS_IN (libpthread))
      70  # define __libc_lock_init_recursive(NAME) \
      71    ((void) ((NAME) = (__libc_lock_recursive_t) _LIBC_LOCK_RECURSIVE_INITIALIZER))
      72  #else
      73  # define __libc_lock_init_recursive(NAME) \
      74    do {									      \
      75      if (__pthread_mutex_init != NULL)					      \
      76        {									      \
      77  	pthread_mutexattr_t __attr;					      \
      78  	__pthread_mutexattr_init (&__attr);				      \
      79  	__pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP);    \
      80  	__pthread_mutex_init (&(NAME).mutex, &__attr);			      \
      81  	__pthread_mutexattr_destroy (&__attr);				      \
      82        }									      \
      83    } while (0)
      84  #endif
      85  
      86  /* Finalize recursive named lock.  */
      87  #if defined _LIBC && (IS_IN (libc) || IS_IN (libpthread))
      88  # define __libc_lock_fini_recursive(NAME) ((void) 0)
      89  #else
      90  # define __libc_lock_fini_recursive(NAME) \
      91    __libc_maybe_call (__pthread_mutex_destroy, (&(NAME).mutex), 0)
      92  #endif
      93  
      94  /* Lock the recursive named lock variable.  */
      95  #if defined _LIBC && (IS_IN (libc) || IS_IN (libpthread))
      96  # define __libc_lock_lock_recursive(NAME) \
      97    do {									      \
      98      void *self = THREAD_SELF;						      \
      99      if ((NAME).owner != self)						      \
     100        {									      \
     101  	lll_lock ((NAME).lock, LLL_PRIVATE);				      \
     102  	(NAME).owner = self;						      \
     103        }									      \
     104      ++(NAME).cnt;							      \
     105    } while (0)
     106  #else
     107  # define __libc_lock_lock_recursive(NAME) \
     108    __libc_maybe_call (__pthread_mutex_lock, (&(NAME).mutex), 0)
     109  #endif
     110  
     111  /* Try to lock the recursive named lock variable.  */
     112  #if defined _LIBC && (IS_IN (libc) || IS_IN (libpthread))
     113  # define __libc_lock_trylock_recursive(NAME) \
     114    ({									      \
     115      int result = 0;							      \
     116      void *self = THREAD_SELF;						      \
     117      if ((NAME).owner != self)						      \
     118        {									      \
     119  	if (lll_trylock ((NAME).lock) == 0)				      \
     120  	  {								      \
     121  	    (NAME).owner = self;					      \
     122  	    (NAME).cnt = 1;						      \
     123  	  }								      \
     124  	else								      \
     125  	  result = EBUSY;						      \
     126        }									      \
     127      else								      \
     128        ++(NAME).cnt;							      \
     129      result;								      \
     130    })
     131  #else
     132  # define __libc_lock_trylock_recursive(NAME) \
     133    __libc_maybe_call (__pthread_mutex_trylock, (&(NAME).mutex), 0)
     134  #endif
     135  
     136  /* Unlock the recursive named lock variable.  */
     137  #if defined _LIBC && (IS_IN (libc) || IS_IN (libpthread))
     138  /* We do no error checking here.  */
     139  # define __libc_lock_unlock_recursive(NAME) \
     140    do {									      \
     141      if (--(NAME).cnt == 0)						      \
     142        {									      \
     143  	(NAME).owner = NULL;						      \
     144  	lll_unlock ((NAME).lock, LLL_PRIVATE);				      \
     145        }									      \
     146    } while (0)
     147  #else
     148  # define __libc_lock_unlock_recursive(NAME) \
     149    __libc_maybe_call (__pthread_mutex_unlock, (&(NAME).mutex), 0)
     150  #endif
     151  
     152  /* Put the unwind buffer BUFFER on the per-thread callback stack.  The
     153     caller must fill BUFFER->__routine and BUFFER->__arg before calling
     154     this function.  */
     155  void __libc_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer);
     156  libc_hidden_proto (__libc_cleanup_push_defer)
     157  /* Remove BUFFER from the unwind callback stack.  The caller must invoke
     158     the callback if desired.  */
     159  void __libc_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer);
     160  libc_hidden_proto (__libc_cleanup_pop_restore)
     161  
     162  /* Start critical region with cleanup.  */
     163  #define __libc_cleanup_region_start(DOIT, FCT, ARG)			\
     164    {   bool _cleanup_start_doit;						\
     165    struct _pthread_cleanup_buffer _buffer;				\
     166    /* Non-addressable copy of FCT, so that we avoid indirect calls on	\
     167       the non-unwinding path.  */					\
     168    void (*_cleanup_routine) (void *) = (FCT);				\
     169    _buffer.__arg = (ARG);						\
     170    if (DOIT)								\
     171      {									\
     172        _cleanup_start_doit = true;					\
     173        _buffer.__routine = _cleanup_routine;				\
     174        __libc_cleanup_push_defer (&_buffer);				\
     175      }									\
     176    else									\
     177        _cleanup_start_doit = false;
     178  
     179  /* End critical region with cleanup.  */
     180  #define __libc_cleanup_region_end(DOIT)		\
     181    if (_cleanup_start_doit)			\
     182      __libc_cleanup_pop_restore (&_buffer);	\
     183    if (DOIT)					\
     184      _cleanup_routine (_buffer.__arg);		\
     185    } /* matches __libc_cleanup_region_start */
     186  
     187  
     188  /* Hide the definitions which are only supposed to be used inside libc in
     189     a separate file.  This file is not present in the installation!  */
     190  #ifdef _LIBC
     191  # include "libc-lockP.h"
     192  #endif
     193  
     194  #endif	/* libc-lock.h */