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