1 | /* Thread creation. |
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 | #include <assert.h> |
20 | #include <errno.h> |
21 | #include <pthread.h> |
22 | #include <signal.h> |
23 | #include <resolv.h> |
24 | |
25 | #include <atomic.h> |
26 | #include <hurd/resource.h> |
27 | #include <sys/single_threaded.h> |
28 | |
29 | #include <pt-internal.h> |
30 | #include <pthreadP.h> |
31 | |
32 | #if IS_IN (libpthread) |
33 | # include <ctype.h> |
34 | #endif |
35 | #ifdef HAVE_USELOCALE |
36 | # include <locale.h> |
37 | #endif |
38 | |
39 | /* The entry-point for new threads. */ |
40 | static void |
41 | entry_point (struct __pthread *self, void *(*start_routine) (void *), void *arg) |
42 | { |
43 | int err; |
44 | |
45 | ___pthread_self = self; |
46 | __resp = &self->res_state; |
47 | |
48 | #if IS_IN (libpthread) |
49 | /* Initialize pointers to locale data. */ |
50 | __ctype_init (); |
51 | #endif |
52 | #ifdef HAVE_USELOCALE |
53 | /* A fresh thread needs to be bound to the global locale. */ |
54 | uselocale (LC_GLOBAL_LOCALE); |
55 | #endif |
56 | |
57 | __pthread_startup (); |
58 | |
59 | /* We can now unleash signals. */ |
60 | err = __pthread_sigstate (thread: self, SIG_SETMASK, set: &self->init_sigset, oset: 0, clear_pending: 0); |
61 | assert_perror (err); |
62 | |
63 | if (self->c11) |
64 | { |
65 | /* The function pointer of the c11 thread start is cast to an incorrect |
66 | type on __pthread_create call, however it is casted back to correct |
67 | one so the call behavior is well-defined (it is assumed that pointers |
68 | to void are able to represent all values of int). */ |
69 | int (*start)(void*) = (int (*) (void*)) start_routine; |
70 | __pthread_exit (value: (void*) (uintptr_t) start (arg)); |
71 | } |
72 | else |
73 | __pthread_exit (value: start_routine (arg)); |
74 | } |
75 | |
76 | /* Create a thread with attributes given by ATTR, executing |
77 | START_ROUTINE with argument ARG. */ |
78 | int |
79 | __pthread_create (pthread_t * thread, const pthread_attr_t * attr, |
80 | void *(*start_routine) (void *), void *arg) |
81 | { |
82 | int err; |
83 | struct __pthread *pthread; |
84 | |
85 | err = __pthread_create_internal (pthread: &pthread, attr, start_routine, arg); |
86 | if (!err) |
87 | *thread = pthread->thread; |
88 | else if (err == ENOMEM) |
89 | err = EAGAIN; |
90 | |
91 | return err; |
92 | } |
93 | weak_alias (__pthread_create, pthread_create) |
94 | hidden_def (__pthread_create) |
95 | |
96 | /* Internal version of pthread_create. See comment in |
97 | pt-internal.h. */ |
98 | int |
99 | __pthread_create_internal (struct __pthread **thread, |
100 | const pthread_attr_t * attr, |
101 | void *(*start_routine) (void *), void *arg) |
102 | { |
103 | int err; |
104 | struct __pthread *pthread; |
105 | const struct __pthread_attr *setup; |
106 | sigset_t sigset; |
107 | size_t stacksize; |
108 | |
109 | /* Avoid a data race in the multi-threaded case. */ |
110 | if (__libc_single_threaded) |
111 | __libc_single_threaded = 0; |
112 | |
113 | /* Allocate a new thread structure. */ |
114 | err = __pthread_alloc (thread: &pthread); |
115 | if (err) |
116 | goto failed; |
117 | |
118 | if (attr == ATTR_C11_THREAD) |
119 | { |
120 | attr = NULL; |
121 | pthread->c11 = true; |
122 | } |
123 | else |
124 | pthread->c11 = false; |
125 | |
126 | /* Use the default attributes if ATTR is NULL. */ |
127 | setup = attr ? attr : &__pthread_default_attr; |
128 | |
129 | stacksize = setup->__stacksize; |
130 | if (stacksize == 0) |
131 | { |
132 | struct rlimit rlim; |
133 | err = __getrlimit (RLIMIT_STACK, &rlim); |
134 | if (err == 0 && rlim.rlim_cur != RLIM_INFINITY) |
135 | stacksize = rlim.rlim_cur; |
136 | if (stacksize == 0) |
137 | stacksize = PTHREAD_STACK_DEFAULT; |
138 | } |
139 | |
140 | /* Initialize the thread state. */ |
141 | pthread->state = (setup->__detachstate == PTHREAD_CREATE_DETACHED |
142 | ? PTHREAD_DETACHED : PTHREAD_JOINABLE); |
143 | |
144 | if (setup->__stackaddr) |
145 | { |
146 | pthread->stackaddr = setup->__stackaddr; |
147 | |
148 | /* If the user supplied a stack, it is not our responsibility to |
149 | setup a stack guard. */ |
150 | pthread->guardsize = 0; |
151 | pthread->stack = 0; |
152 | } |
153 | else |
154 | { |
155 | /* Allocate a stack. */ |
156 | err = __pthread_stack_alloc (&pthread->stackaddr, |
157 | ((setup->__guardsize + __vm_page_size - 1) |
158 | / __vm_page_size) * __vm_page_size |
159 | + stacksize); |
160 | if (err) |
161 | goto failed_stack_alloc; |
162 | |
163 | pthread->guardsize = setup->__guardsize; |
164 | pthread->stack = 1; |
165 | } |
166 | |
167 | pthread->stacksize = stacksize; |
168 | |
169 | /* Allocate the kernel thread and other required resources. */ |
170 | err = __pthread_thread_alloc (thread: pthread); |
171 | if (err) |
172 | goto failed_thread_alloc; |
173 | |
174 | pthread->tcb = _dl_allocate_tls (NULL); |
175 | if (pthread->tcb == NULL) |
176 | { |
177 | err = ENOMEM; |
178 | goto failed_thread_tls_alloc; |
179 | } |
180 | pthread->tcb->tcb = pthread->tcb; |
181 | |
182 | /* And initialize the rest of the machine context. This may include |
183 | additional machine- and system-specific initializations that |
184 | prove convenient. */ |
185 | err = __pthread_setup (thread: pthread, entry_point, start_routine, arg); |
186 | if (err) |
187 | goto failed_setup; |
188 | |
189 | /* Initialize the system-specific signal state for the new |
190 | thread. */ |
191 | err = __pthread_sigstate_init (thread: pthread); |
192 | if (err) |
193 | goto failed_sigstate; |
194 | |
195 | /* If the new thread is joinable, add a reference for the caller. */ |
196 | if (pthread->state == PTHREAD_JOINABLE) |
197 | pthread->nr_refs++; |
198 | |
199 | /* Set the new thread's signal mask and set the pending signals to |
200 | empty. POSIX says: "The signal mask shall be inherited from the |
201 | creating thread. The set of signals pending for the new thread |
202 | shall be empty." If the current thread is not a pthread then we |
203 | just inherit the process' sigmask. */ |
204 | if (GL (dl_pthread_num_threads) == 1) |
205 | err = __sigprocmask (how: 0, set: 0, oset: &pthread->init_sigset); |
206 | else |
207 | err = __pthread_sigstate (thread: _pthread_self (), how: 0, set: 0, oset: &pthread->init_sigset, clear_pending: 0); |
208 | assert_perror (err); |
209 | |
210 | if (start_routine) |
211 | /* But block the signals for now, until the thread is fully initialized. */ |
212 | __sigfillset (set: &sigset); |
213 | else |
214 | sigset = pthread->init_sigset; |
215 | err = __pthread_sigstate (thread: pthread, SIG_SETMASK, set: &sigset, oset: 0, clear_pending: 1); |
216 | assert_perror (err); |
217 | |
218 | /* Increase the total number of threads. We do this before actually |
219 | starting the new thread, since the new thread might immediately |
220 | call `pthread_exit' which decreases the number of threads and |
221 | calls `exit' if the number of threads reaches zero. Increasing |
222 | the number of threads from within the new thread isn't an option |
223 | since this thread might return and call `pthread_exit' before the |
224 | new thread runs. */ |
225 | atomic_fetch_add_relaxed (&__pthread_total, 1); |
226 | |
227 | /* Store a pointer to this thread in the thread ID lookup table. We |
228 | could use __thread_setid, however, we only lock for reading as no |
229 | other thread should be using this entry (we also assume that the |
230 | store is atomic). */ |
231 | __libc_rwlock_rdlock (GL (dl_pthread_threads_lock)); |
232 | GL (dl_pthread_threads)[pthread->thread - 1] = pthread; |
233 | __libc_rwlock_unlock (GL (dl_pthread_threads_lock)); |
234 | |
235 | /* At this point it is possible to guess our pthread ID. We have to |
236 | make sure that all functions taking a pthread_t argument can |
237 | handle the fact that this thread isn't really running yet. Since |
238 | the new thread might be passed its ID through pthread_create (to |
239 | avoid calling pthread_self), read it before starting the thread. */ |
240 | *thread = pthread; |
241 | |
242 | /* Schedule the new thread. */ |
243 | err = __pthread_thread_start (thread: pthread); |
244 | if (err) |
245 | goto failed_starting; |
246 | |
247 | |
248 | return 0; |
249 | |
250 | failed_starting: |
251 | /* If joinable, a reference was added for the caller. */ |
252 | if (pthread->state == PTHREAD_JOINABLE) |
253 | { |
254 | __pthread_dealloc (thread: pthread); |
255 | __pthread_dealloc_finish (pthread); |
256 | } |
257 | |
258 | __pthread_setid (pthread->thread, NULL); |
259 | atomic_fetch_add_relaxed (&__pthread_total, -1); |
260 | failed_sigstate: |
261 | __pthread_sigstate_destroy (thread: pthread); |
262 | failed_setup: |
263 | _dl_deallocate_tls (pthread->tcb, 1); |
264 | pthread->tcb = NULL; |
265 | failed_thread_tls_alloc: |
266 | __pthread_thread_terminate (thread: pthread); |
267 | |
268 | /* __pthread_thread_terminate has taken care of deallocating the stack and |
269 | the thread structure. */ |
270 | goto failed; |
271 | failed_thread_alloc: |
272 | if (pthread->stack) |
273 | __pthread_stack_dealloc (pthread->stackaddr, |
274 | ((setup->__guardsize + __vm_page_size - 1) |
275 | / __vm_page_size) * __vm_page_size + stacksize); |
276 | failed_stack_alloc: |
277 | __pthread_dealloc (thread: pthread); |
278 | __pthread_dealloc_finish (pthread); |
279 | failed: |
280 | return err; |
281 | } |
282 | |