Add IP_PROTOCOL from Linux 6.4 to bits/in.h
[glibc.git] / sysdeps / nptl / libc-lock.h
blob61027be74c895d7f5f3f4e59a82a87a44047f704
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.
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.
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.
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/>. */
19 #ifndef _LIBC_LOCK_H
20 #define _LIBC_LOCK_H 1
22 #include <pthread.h>
23 #define __need_NULL
24 #include <stddef.h>
25 #include <libc-lock-arch.h>
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
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
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;
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
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
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
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) \
101 lll_lock ((NAME).lock, LLL_PRIVATE); \
102 (NAME).owner = self; \
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
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) \
119 if (lll_trylock ((NAME).lock) == 0) \
121 (NAME).owner = self; \
122 (NAME).cnt = 1; \
124 else \
125 result = EBUSY; \
127 else \
128 ++(NAME).cnt; \
129 result; \
131 #else
132 # define __libc_lock_trylock_recursive(NAME) \
133 __libc_maybe_call (__pthread_mutex_trylock, (&(NAME).mutex), 0)
134 #endif
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) \
143 (NAME).owner = NULL; \
144 lll_unlock ((NAME).lock, LLL_PRIVATE); \
146 } while (0)
147 #else
148 # define __libc_lock_unlock_recursive(NAME) \
149 __libc_maybe_call (__pthread_mutex_unlock, (&(NAME).mutex), 0)
150 #endif
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)
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) \
172 _cleanup_start_doit = true; \
173 _buffer.__routine = _cleanup_routine; \
174 __libc_cleanup_push_defer (&_buffer); \
176 else \
177 _cleanup_start_doit = false;
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 */
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
194 #endif /* libc-lock.h */