1 /* Internal defenitions for pthreads library.
2 Copyright (C) 2000-2022 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
__pthread_enqueue(struct __pthread ** head,struct __pthread * thread)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
__pthread_dequeue(struct __pthread * thread)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
169 /* Concurrency hint. */
170 extern int __pthread_concurrency;
171
172 /* The size of the thread ID lookup table. */
173 extern int __pthread_max_threads;
174
175 #define __pthread_getid(thread) \
176 ({ struct __pthread *__t = NULL; \
177 __libc_rwlock_rdlock (GL (dl_pthread_threads_lock)); \
178 if (thread <= __pthread_max_threads) \
179 __t = GL (dl_pthread_threads)[thread - 1]; \
180 __libc_rwlock_unlock (GL (dl_pthread_threads_lock)); \
181 __t; })
182
183 #define __pthread_setid(thread, pthread) \
184 __libc_rwlock_wrlock (GL (dl_pthread_threads_lock)); \
185 GL (dl_pthread_threads)[thread - 1] = pthread; \
186 __libc_rwlock_unlock (GL (dl_pthread_threads_lock));
187
188 /* Similar to pthread_self, but returns the thread descriptor instead
189 of the thread ID. */
190 #ifndef _pthread_self
191 extern struct __pthread *_pthread_self (void);
192 #endif
193
194 /* Stores the stack of cleanup handlers for the thread. */
195 extern __thread struct __pthread_cancelation_handler *__pthread_cleanup_stack;
196
197
198 /* Initialize the pthreads library. */
199 extern void ___pthread_init (void);
200
201 /* Internal version of pthread_create. Rather than return the new
202 tid, we return the whole __pthread structure in *PTHREAD. */
203 extern int __pthread_create_internal (struct __pthread **__restrict pthread,
204 const pthread_attr_t *__restrict attr,
205 void *(*start_routine) (void *),
206 void *__restrict arg);
207
208 /* Allocate a new thread structure and a pthread thread ID (but not a
209 kernel thread or a stack). THREAD has one reference. */
210 extern int __pthread_alloc (struct __pthread **thread);
211
212 /* Deallocate the content of the thread structure. This is the dual of
213 __pthread_alloc (N.B. it does not call __pthread_stack_dealloc nor
214 __pthread_thread_terminate). THREAD loses one reference, and if
215 if the reference counter drops to 0 this returns 1, and the caller has
216 to call __pthread_dealloc_finish when it is really finished with using
217 THREAD. */
218 extern void __pthread_dealloc (struct __pthread *thread);
219
220 /* Confirm deallocating the thread structure. Before calling this
221 the structure will not be reused yet. */
222 extern void __pthread_dealloc_finish (struct __pthread *pthread);
223
224
225 /* Allocate a stack of size STACKSIZE. The stack base shall be
226 returned in *STACKADDR. */
227 extern int __pthread_stack_alloc (void **stackaddr, size_t stacksize);
228
229 /* Deallocate the stack STACKADDR of size STACKSIZE. */
230 extern void __pthread_stack_dealloc (void *stackaddr, size_t stacksize);
231
232
233 /* Setup thread THREAD's context. */
234 extern int __pthread_setup (struct __pthread *__restrict thread,
235 void (*entry_point) (struct __pthread *,
236 void *(*)(void *),
237 void *),
238 void *(*start_routine) (void *),
239 void *__restrict arg);
240
241
242 /* Allocate a kernel thread (and any miscellaneous system dependent
243 resources) for THREAD; it must not be placed on the run queue. */
244 extern int __pthread_thread_alloc (struct __pthread *thread);
245
246 /* Start THREAD making it eligible to run. */
247 extern int __pthread_thread_start (struct __pthread *thread);
248
249 /* Terminate the kernel thread associated with THREAD, and deallocate its
250 stack as well as any other kernel resource associated with it.
251 In addition, THREAD looses one reference.
252
253 This function can be called by any thread, including the target thread.
254 Since some resources that are destroyed along the kernel thread are
255 stored in thread-local variables, the conditions required for this
256 function to behave correctly are a bit unusual : as long as the target
257 thread hasn't been started, any thread can terminate it, but once it
258 has started, no other thread can terminate it, so that thread-local
259 variables created by that thread are correctly released. */
260 extern void __pthread_thread_terminate (struct __pthread *thread);
261
262
263 /* Called by a thread just before it calls the provided start
264 routine. */
265 extern void __pthread_startup (void);
266
267 /* Block THREAD. */
268 extern void __pthread_block (struct __pthread *thread);
269
270 /* Block THREAD until *ABSTIME is reached. */
271 extern error_t __pthread_timedblock (struct __pthread *__restrict thread,
272 const struct timespec *__restrict abstime,
273 clockid_t clock_id);
274
275 /* Block THREAD with interrupts. */
276 extern error_t __pthread_block_intr (struct __pthread *thread);
277
278 /* Block THREAD until *ABSTIME is reached, with interrupts. */
279 extern error_t __pthread_timedblock_intr (struct __pthread *__restrict thread,
280 const struct timespec *__restrict abstime,
281 clockid_t clock_id);
282
283 /* Wakeup THREAD. */
284 extern void __pthread_wakeup (struct __pthread *thread);
285
286
287 /* Perform a cancelation. The CANCEL_LOCK member of the given thread must
288 be locked before calling this function, which must unlock it. */
289 extern int __pthread_do_cancel (struct __pthread *thread);
290
291
292 /* Initialize the thread specific data structures. THREAD must be the
293 calling thread. */
294 extern error_t __pthread_init_specific (struct __pthread *thread);
295
296 /* Call the destructors on all of the thread specific data in THREAD.
297 THREAD must be the calling thread. */
298 extern void __pthread_destroy_specific (struct __pthread *thread);
299
300
301 /* Initialize newly create thread *THREAD's signal state data
302 structures. */
303 extern error_t __pthread_sigstate_init (struct __pthread *thread);
304
305 /* Destroy the signal state data structures associcated with thread
306 *THREAD. */
307 extern void __pthread_sigstate_destroy (struct __pthread *thread);
308
309 /* Modify thread *THREAD's signal state. */
310 extern error_t __pthread_sigstate (struct __pthread *__restrict thread, int how,
311 const sigset_t *__restrict set,
312 sigset_t *__restrict oset,
313 int clear_pending);
314
315 /* If supported, check that MUTEX is locked by the caller. */
316 extern int __pthread_mutex_checklocked (pthread_mutex_t *mtx);
317
318
319 /* Default thread attributes. */
320 extern struct __pthread_attr __pthread_default_attr;
321
322 /* Default barrier attributes. */
323 extern const struct __pthread_barrierattr __pthread_default_barrierattr;
324
325 /* Default rdlock attributes. */
326 extern const struct __pthread_rwlockattr __pthread_default_rwlockattr;
327
328 /* Default condition attributes. */
329 extern const struct __pthread_condattr __pthread_default_condattr;
330
331 /* Semaphore encoding.
332 See nptl implementation for the details. */
333 struct new_sem
334 {
335 #if __HAVE_64B_ATOMICS
336 /* The data field holds both value (in the least-significant 32 bits) and
337 nwaiters. */
338 # if __BYTE_ORDER == __LITTLE_ENDIAN
339 # define SEM_VALUE_OFFSET 0
340 # elif __BYTE_ORDER == __BIG_ENDIAN
341 # define SEM_VALUE_OFFSET 1
342 # else
343 # error Unsupported byte order.
344 # endif
345 # define SEM_NWAITERS_SHIFT 32
346 # define SEM_VALUE_MASK (~(unsigned int)0)
347 uint64_t data;
348 int pshared;
349 #define __SEMAPHORE_INITIALIZER(value, pshared) \
350 { (value), (pshared) }
351 #else
352 # define SEM_VALUE_SHIFT 1
353 # define SEM_NWAITERS_MASK ((unsigned int)1)
354 unsigned int value;
355 unsigned int nwaiters;
356 int pshared;
357 #define __SEMAPHORE_INITIALIZER(value, pshared) \
358 { (value) << SEM_VALUE_SHIFT, 0, (pshared) }
359 #endif
360 };
361
362 extern int __sem_waitfast (struct new_sem *isem, int definitive_result);
363
364 #endif /* pt-internal.h */
365