1 | /* Internal definitions for pthreads library. |
2 | Copyright (C) 2000-2024 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 _PT_INTERNAL_H |
20 | #define _PT_INTERNAL_H 1 |
21 | |
22 | #include <pthread.h> |
23 | #include <stddef.h> |
24 | #include <sched.h> |
25 | #include <signal.h> |
26 | #include <assert.h> |
27 | #include <bits/types/res_state.h> |
28 | |
29 | #include <atomic.h> |
30 | |
31 | #include <pt-key.h> |
32 | |
33 | #include <pt-sysdep.h> |
34 | #include <pt-machdep.h> |
35 | |
36 | #if IS_IN (libpthread) |
37 | # include <ldsodefs.h> |
38 | #endif |
39 | |
40 | #include <tls.h> |
41 | |
42 | /* Thread state. */ |
43 | enum pthread_state |
44 | { |
45 | /* The thread is running and joinable. */ |
46 | PTHREAD_JOINABLE = 0, |
47 | /* The thread is running and detached. */ |
48 | PTHREAD_DETACHED, |
49 | /* A joinable thread exited and its return code is available. */ |
50 | PTHREAD_EXITED, |
51 | }; |
52 | |
53 | #ifndef PTHREAD_KEY_MEMBERS |
54 | # define PTHREAD_KEY_MEMBERS |
55 | #endif |
56 | |
57 | #ifndef PTHREAD_SYSDEP_MEMBERS |
58 | # define PTHREAD_SYSDEP_MEMBERS |
59 | #endif |
60 | |
61 | /* This structure describes a POSIX thread. */ |
62 | struct __pthread |
63 | { |
64 | /* Thread ID. */ |
65 | pthread_t thread; |
66 | |
67 | unsigned int nr_refs; /* Detached threads have a self reference only, |
68 | while joinable threads have two references. |
69 | These are used to keep the structure valid at |
70 | thread destruction. Detaching/joining a thread |
71 | drops a reference. */ |
72 | |
73 | /* Cancellation. */ |
74 | pthread_mutex_t cancel_lock; /* Protect cancel_xxx members. */ |
75 | void (*cancel_hook) (void *); /* Called to unblock a thread blocking |
76 | in a cancellation point (namely, |
77 | __pthread_cond_timedwait_internal). */ |
78 | void *cancel_hook_arg; |
79 | int cancel_state; |
80 | int cancel_type; |
81 | int cancel_pending; |
82 | |
83 | /* Thread stack. */ |
84 | void *stackaddr; |
85 | size_t stacksize; |
86 | size_t guardsize; |
87 | int stack; /* Nonzero if the stack was allocated. */ |
88 | |
89 | /* Exit status. */ |
90 | void *status; |
91 | |
92 | /* Thread state. */ |
93 | enum pthread_state state; |
94 | pthread_mutex_t state_lock; /* Locks the state. */ |
95 | pthread_cond_t state_cond; /* Signalled when the state changes. */ |
96 | bool terminated; /* Whether the kernel thread is over |
97 | and we can reuse this structure. */ |
98 | |
99 | /* Resolver state. */ |
100 | struct __res_state res_state; |
101 | |
102 | /* Indicates whether is a C11 thread created by thrd_creat. */ |
103 | bool c11; |
104 | |
105 | /* Initial sigset for the thread. */ |
106 | sigset_t init_sigset; |
107 | |
108 | /* Thread context. */ |
109 | struct pthread_mcontext mcontext; |
110 | |
111 | PTHREAD_KEY_MEMBERS |
112 | |
113 | PTHREAD_SYSDEP_MEMBERS |
114 | |
115 | tcbhead_t *tcb; |
116 | |
117 | /* Queue links. Since PREVP is used to determine if a thread has been |
118 | awaken, it must be protected by the queue lock. */ |
119 | struct __pthread *next, **prevp; |
120 | }; |
121 | |
122 | /* Enqueue an element THREAD on the queue *HEAD. */ |
123 | static inline void |
124 | __pthread_enqueue (struct __pthread **head, struct __pthread *thread) |
125 | { |
126 | assert (thread->prevp == 0); |
127 | |
128 | thread->next = *head; |
129 | thread->prevp = head; |
130 | if (*head) |
131 | (*head)->prevp = &thread->next; |
132 | *head = thread; |
133 | } |
134 | |
135 | /* Dequeue the element THREAD from the queue it is connected to. */ |
136 | static inline void |
137 | __pthread_dequeue (struct __pthread *thread) |
138 | { |
139 | assert (thread); |
140 | assert (thread->prevp); |
141 | |
142 | if (thread->next) |
143 | thread->next->prevp = thread->prevp; |
144 | *thread->prevp = thread->next; |
145 | thread->prevp = 0; |
146 | } |
147 | |
148 | /* Iterate over QUEUE storing each element in ELEMENT. */ |
149 | #define __pthread_queue_iterate(queue, element) \ |
150 | for (struct __pthread *__pdi_next = (queue); \ |
151 | ((element) = __pdi_next) \ |
152 | && ((__pdi_next = __pdi_next->next), \ |
153 | 1); \ |
154 | ) |
155 | |
156 | /* Iterate over QUEUE dequeuing each element, storing it in |
157 | ELEMENT. */ |
158 | #define __pthread_dequeuing_iterate(queue, element) \ |
159 | for (struct __pthread *__pdi_next = (queue); \ |
160 | ((element) = __pdi_next) \ |
161 | && ((__pdi_next = __pdi_next->next), \ |
162 | ((element)->prevp = 0), \ |
163 | 1); \ |
164 | ) |
165 | |
166 | /* The total number of threads currently active. */ |
167 | extern unsigned int __pthread_total; |
168 | libc_hidden_proto (__pthread_total) |
169 | |
170 | /* Concurrency hint. */ |
171 | extern int __pthread_concurrency; |
172 | |
173 | /* The size of the thread ID lookup table. */ |
174 | extern int __pthread_max_threads; |
175 | |
176 | #define __pthread_getid(thread) \ |
177 | ({ struct __pthread *__t = NULL; \ |
178 | __libc_rwlock_rdlock (GL (dl_pthread_threads_lock)); \ |
179 | if (thread <= __pthread_max_threads) \ |
180 | __t = GL (dl_pthread_threads)[thread - 1]; \ |
181 | __libc_rwlock_unlock (GL (dl_pthread_threads_lock)); \ |
182 | __t; }) |
183 | |
184 | #define __pthread_setid(thread, pthread) \ |
185 | __libc_rwlock_wrlock (GL (dl_pthread_threads_lock)); \ |
186 | GL (dl_pthread_threads)[thread - 1] = pthread; \ |
187 | __libc_rwlock_unlock (GL (dl_pthread_threads_lock)); |
188 | |
189 | /* Similar to pthread_self, but returns the thread descriptor instead |
190 | of the thread ID. */ |
191 | #ifndef _pthread_self |
192 | extern struct __pthread *_pthread_self (void); |
193 | #endif |
194 | |
195 | /* Stores the stack of cleanup handlers for the thread. */ |
196 | extern __thread struct __pthread_cancelation_handler *__pthread_cleanup_stack; |
197 | |
198 | |
199 | /* Initialize the pthreads library. */ |
200 | extern void ___pthread_init (void); |
201 | |
202 | /* Internal version of pthread_create. Rather than return the new |
203 | tid, we return the whole __pthread structure in *PTHREAD. */ |
204 | extern int __pthread_create_internal (struct __pthread **__restrict pthread, |
205 | const pthread_attr_t *__restrict attr, |
206 | void *(*start_routine) (void *), |
207 | void *__restrict arg); |
208 | |
209 | /* Allocate a new thread structure and a pthread thread ID (but not a |
210 | kernel thread or a stack). THREAD has one reference. */ |
211 | extern int __pthread_alloc (struct __pthread **thread); |
212 | |
213 | /* Deallocate the content of the thread structure. This is the dual of |
214 | __pthread_alloc (N.B. it does not call __pthread_stack_dealloc nor |
215 | __pthread_thread_terminate). THREAD loses one reference, and if |
216 | if the reference counter drops to 0 this returns 1, and the caller has |
217 | to call __pthread_dealloc_finish when it is really finished with using |
218 | THREAD. */ |
219 | extern void __pthread_dealloc (struct __pthread *thread); |
220 | |
221 | /* Confirm deallocating the thread structure. Before calling this |
222 | the structure will not be reused yet. */ |
223 | extern void __pthread_dealloc_finish (struct __pthread *pthread); |
224 | |
225 | |
226 | /* Allocate a stack of size STACKSIZE. The stack base shall be |
227 | returned in *STACKADDR. */ |
228 | extern int __pthread_stack_alloc (void **stackaddr, size_t stacksize); |
229 | |
230 | /* Deallocate the stack STACKADDR of size STACKSIZE. */ |
231 | extern void __pthread_stack_dealloc (void *stackaddr, size_t stacksize); |
232 | |
233 | |
234 | /* Setup thread THREAD's context. */ |
235 | extern int __pthread_setup (struct __pthread *__restrict thread, |
236 | void (*entry_point) (struct __pthread *, |
237 | void *(*)(void *), |
238 | void *), |
239 | void *(*start_routine) (void *), |
240 | void *__restrict arg); |
241 | |
242 | |
243 | /* Allocate a kernel thread (and any miscellaneous system dependent |
244 | resources) for THREAD; it must not be placed on the run queue. */ |
245 | extern int __pthread_thread_alloc (struct __pthread *thread); |
246 | |
247 | /* Start THREAD making it eligible to run. */ |
248 | extern int __pthread_thread_start (struct __pthread *thread); |
249 | |
250 | /* Terminate the kernel thread associated with THREAD, and deallocate its |
251 | stack as well as any other kernel resource associated with it. |
252 | In addition, THREAD looses one reference. |
253 | |
254 | This function can be called by any thread, including the target thread. |
255 | Since some resources that are destroyed along the kernel thread are |
256 | stored in thread-local variables, the conditions required for this |
257 | function to behave correctly are a bit unusual : as long as the target |
258 | thread hasn't been started, any thread can terminate it, but once it |
259 | has started, no other thread can terminate it, so that thread-local |
260 | variables created by that thread are correctly released. */ |
261 | extern void __pthread_thread_terminate (struct __pthread *thread); |
262 | |
263 | |
264 | /* Called by a thread just before it calls the provided start |
265 | routine. */ |
266 | extern void __pthread_startup (void); |
267 | |
268 | /* Block THREAD. */ |
269 | extern void __pthread_block (struct __pthread *thread); |
270 | |
271 | /* Block THREAD until *ABSTIME is reached. */ |
272 | extern error_t __pthread_timedblock (struct __pthread *__restrict thread, |
273 | const struct timespec *__restrict abstime, |
274 | clockid_t clock_id); |
275 | |
276 | /* Block THREAD with interrupts. */ |
277 | extern error_t __pthread_block_intr (struct __pthread *thread); |
278 | |
279 | /* Block THREAD until *ABSTIME is reached, with interrupts. */ |
280 | extern error_t __pthread_timedblock_intr (struct __pthread *__restrict thread, |
281 | const struct timespec *__restrict abstime, |
282 | clockid_t clock_id); |
283 | |
284 | /* Wakeup THREAD. */ |
285 | extern void __pthread_wakeup (struct __pthread *thread); |
286 | |
287 | |
288 | /* Perform a cancelation. The CANCEL_LOCK member of the given thread must |
289 | be locked before calling this function, which must unlock it. */ |
290 | extern int __pthread_do_cancel (struct __pthread *thread); |
291 | |
292 | |
293 | /* Initialize the thread specific data structures. THREAD must be the |
294 | calling thread. */ |
295 | extern error_t __pthread_init_specific (struct __pthread *thread); |
296 | |
297 | /* Call the destructors on all of the thread specific data in THREAD. |
298 | THREAD must be the calling thread. */ |
299 | extern void __pthread_destroy_specific (struct __pthread *thread); |
300 | |
301 | |
302 | /* Initialize newly create thread *THREAD's signal state data |
303 | structures. */ |
304 | extern error_t __pthread_sigstate_init (struct __pthread *thread); |
305 | |
306 | /* Destroy the signal state data structures associated with thread |
307 | *THREAD. */ |
308 | extern void __pthread_sigstate_destroy (struct __pthread *thread); |
309 | |
310 | /* Modify thread *THREAD's signal state. */ |
311 | extern error_t __pthread_sigstate (struct __pthread *__restrict thread, int how, |
312 | const sigset_t *__restrict set, |
313 | sigset_t *__restrict oset, |
314 | int clear_pending); |
315 | |
316 | /* If supported, check that MUTEX is locked by the caller. */ |
317 | extern int __pthread_mutex_checklocked (pthread_mutex_t *mtx); |
318 | |
319 | |
320 | /* Default thread attributes. */ |
321 | extern struct __pthread_attr __pthread_default_attr; |
322 | |
323 | /* Default barrier attributes. */ |
324 | extern const struct __pthread_barrierattr __pthread_default_barrierattr; |
325 | |
326 | /* Default rdlock attributes. */ |
327 | extern const struct __pthread_rwlockattr __pthread_default_rwlockattr; |
328 | |
329 | /* Default condition attributes. */ |
330 | extern const struct __pthread_condattr __pthread_default_condattr; |
331 | |
332 | /* Semaphore encoding. |
333 | See nptl implementation for the details. */ |
334 | struct new_sem |
335 | { |
336 | #if __HAVE_64B_ATOMICS |
337 | /* The data field holds both value (in the least-significant 32 bits) and |
338 | nwaiters. */ |
339 | # if __BYTE_ORDER == __LITTLE_ENDIAN |
340 | # define SEM_VALUE_OFFSET 0 |
341 | # elif __BYTE_ORDER == __BIG_ENDIAN |
342 | # define SEM_VALUE_OFFSET 1 |
343 | # else |
344 | # error Unsupported byte order. |
345 | # endif |
346 | # define SEM_NWAITERS_SHIFT 32 |
347 | # define SEM_VALUE_MASK (~(unsigned int)0) |
348 | uint64_t data; |
349 | int pshared; |
350 | #define __SEMAPHORE_INITIALIZER(value, pshared) \ |
351 | { (value), (pshared) } |
352 | #else |
353 | # define SEM_VALUE_SHIFT 1 |
354 | # define SEM_NWAITERS_MASK ((unsigned int)1) |
355 | unsigned int value; |
356 | unsigned int nwaiters; |
357 | int pshared; |
358 | #define __SEMAPHORE_INITIALIZER(value, pshared) \ |
359 | { (value) << SEM_VALUE_SHIFT, 0, (pshared) } |
360 | #endif |
361 | }; |
362 | |
363 | extern int __sem_waitfast (struct new_sem *isem, int definitive_result); |
364 | |
365 | #endif /* pt-internal.h */ |
366 | |