1 /* Internal defenitions for pthreads library.
2    Copyright (C) 2000-2021 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   /* The thread structure is unallocated and available for reuse.  */
52   PTHREAD_TERMINATED
53 };
54 
55 #ifndef PTHREAD_KEY_MEMBERS
56 # define PTHREAD_KEY_MEMBERS
57 #endif
58 
59 #ifndef PTHREAD_SYSDEP_MEMBERS
60 # define PTHREAD_SYSDEP_MEMBERS
61 #endif
62 
63 /* This structure describes a POSIX thread.  */
64 struct __pthread
65 {
66   /* Thread ID.  */
67   pthread_t thread;
68 
69   unsigned int nr_refs;		/* Detached threads have a self reference only,
70 				   while joinable threads have two references.
71 				   These are used to keep the structure valid at
72 				   thread destruction.  Detaching/joining a thread
73 				   drops a reference.  */
74 
75   /* Cancellation.  */
76   pthread_mutex_t cancel_lock;	/* Protect cancel_xxx members.  */
77   void (*cancel_hook) (void *);	/* Called to unblock a thread blocking
78 				   in a cancellation point (namely,
79 				   __pthread_cond_timedwait_internal).  */
80   void *cancel_hook_arg;
81   int cancel_state;
82   int cancel_type;
83   int cancel_pending;
84 
85   /* Thread stack.  */
86   void *stackaddr;
87   size_t stacksize;
88   size_t guardsize;
89   int stack;			/* Nonzero if the stack was allocated.  */
90 
91   /* Exit status.  */
92   void *status;
93 
94   /* Thread state.  */
95   enum pthread_state state;
96   pthread_mutex_t state_lock;	/* Locks the state.  */
97   pthread_cond_t state_cond;	/* Signalled when the state changes.  */
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 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 is
215    released if the reference counter drops to 0.  */
216 extern void __pthread_dealloc (struct __pthread *thread);
217 
218 
219 /* Allocate a stack of size STACKSIZE.  The stack base shall be
220    returned in *STACKADDR.  */
221 extern int __pthread_stack_alloc (void **stackaddr, size_t stacksize);
222 
223 /* Deallocate the stack STACKADDR of size STACKSIZE.  */
224 extern void __pthread_stack_dealloc (void *stackaddr, size_t stacksize);
225 
226 
227 /* Setup thread THREAD's context.  */
228 extern int __pthread_setup (struct __pthread *__restrict thread,
229 			    void (*entry_point) (struct __pthread *,
230 						 void *(*)(void *),
231 						 void *),
232 			    void *(*start_routine) (void *),
233 			    void *__restrict arg);
234 
235 
236 /* Allocate a kernel thread (and any miscellaneous system dependent
237    resources) for THREAD; it must not be placed on the run queue.  */
238 extern int __pthread_thread_alloc (struct __pthread *thread);
239 
240 /* Start THREAD making it eligible to run.  */
241 extern int __pthread_thread_start (struct __pthread *thread);
242 
243 /* Terminate the kernel thread associated with THREAD, and deallocate its
244    stack as well as any other kernel resource associated with it.
245    In addition, THREAD looses one reference.
246 
247    This function can be called by any thread, including the target thread.
248    Since some resources that are destroyed along the kernel thread are
249    stored in thread-local variables, the conditions required for this
250    function to behave correctly are a bit unusual : as long as the target
251    thread hasn't been started, any thread can terminate it, but once it
252    has started, no other thread can terminate it, so that thread-local
253    variables created by that thread are correctly released.  */
254 extern void __pthread_thread_terminate (struct __pthread *thread);
255 
256 
257 /* Called by a thread just before it calls the provided start
258    routine.  */
259 extern void __pthread_startup (void);
260 
261 /* Block THREAD.  */
262 extern void __pthread_block (struct __pthread *thread);
263 
264 /* Block THREAD until *ABSTIME is reached.  */
265 extern error_t __pthread_timedblock (struct __pthread *__restrict thread,
266 				     const struct timespec *__restrict abstime,
267 				     clockid_t clock_id);
268 
269 /* Block THREAD with interrupts.  */
270 extern error_t __pthread_block_intr (struct __pthread *thread);
271 
272 /* Block THREAD until *ABSTIME is reached, with interrupts.  */
273 extern error_t __pthread_timedblock_intr (struct __pthread *__restrict thread,
274 					  const struct timespec *__restrict abstime,
275 					  clockid_t clock_id);
276 
277 /* Wakeup THREAD.  */
278 extern void __pthread_wakeup (struct __pthread *thread);
279 
280 
281 /* Perform a cancelation.  The CANCEL_LOCK member of the given thread must
282    be locked before calling this function, which must unlock it.  */
283 extern int __pthread_do_cancel (struct __pthread *thread);
284 
285 
286 /* Initialize the thread specific data structures.  THREAD must be the
287    calling thread.  */
288 extern error_t __pthread_init_specific (struct __pthread *thread);
289 
290 /* Call the destructors on all of the thread specific data in THREAD.
291    THREAD must be the calling thread.  */
292 extern void __pthread_destroy_specific (struct __pthread *thread);
293 
294 
295 /* Initialize newly create thread *THREAD's signal state data
296    structures.  */
297 extern error_t __pthread_sigstate_init (struct __pthread *thread);
298 
299 /* Destroy the signal state data structures associcated with thread
300    *THREAD.  */
301 extern void __pthread_sigstate_destroy (struct __pthread *thread);
302 
303 /* Modify thread *THREAD's signal state.  */
304 extern error_t __pthread_sigstate (struct __pthread *__restrict thread, int how,
305 				   const sigset_t *__restrict set,
306 				   sigset_t *__restrict oset,
307 				   int clear_pending);
308 
309 /* If supported, check that MUTEX is locked by the caller.  */
310 extern int __pthread_mutex_checklocked (pthread_mutex_t *mtx);
311 
312 
313 /* Default thread attributes.  */
314 extern struct __pthread_attr __pthread_default_attr;
315 
316 /* Default barrier attributes.  */
317 extern const struct __pthread_barrierattr __pthread_default_barrierattr;
318 
319 /* Default rdlock attributes.  */
320 extern const struct __pthread_rwlockattr __pthread_default_rwlockattr;
321 
322 /* Default condition attributes.  */
323 extern const struct __pthread_condattr __pthread_default_condattr;
324 
325 /* Semaphore encoding.
326    See nptl implementation for the details.  */
327 struct new_sem
328 {
329 #if __HAVE_64B_ATOMICS
330   /* The data field holds both value (in the least-significant 32 bits) and
331      nwaiters.  */
332 # if __BYTE_ORDER == __LITTLE_ENDIAN
333 #  define SEM_VALUE_OFFSET 0
334 # elif __BYTE_ORDER == __BIG_ENDIAN
335 #  define SEM_VALUE_OFFSET 1
336 # else
337 #  error Unsupported byte order.
338 # endif
339 # define SEM_NWAITERS_SHIFT 32
340 # define SEM_VALUE_MASK (~(unsigned int)0)
341   uint64_t data;
342   int pshared;
343 #define __SEMAPHORE_INITIALIZER(value, pshared) \
344   { (value), (pshared) }
345 #else
346 # define SEM_VALUE_SHIFT 1
347 # define SEM_NWAITERS_MASK ((unsigned int)1)
348   unsigned int value;
349   unsigned int nwaiters;
350   int pshared;
351 #define __SEMAPHORE_INITIALIZER(value, pshared) \
352   { (value) << SEM_VALUE_SHIFT, 0, (pshared) }
353 #endif
354 };
355 
356 extern int __sem_waitfast (struct new_sem *isem, int definitive_result);
357 
358 #endif /* pt-internal.h */
359