]>
Commit | Line | Data |
---|---|---|
33574c17 | 1 | /* Thread creation. |
2b778ceb | 2 | Copyright (C) 2000-2021 Free Software Foundation, Inc. |
33574c17 ST |
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 | |
ad2b41bf ST |
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. | |
33574c17 ST |
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 | |
ad2b41bf | 13 | Lesser General Public License for more details. |
33574c17 | 14 | |
ad2b41bf ST |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, see | |
5a82c748 | 17 | <https://www.gnu.org/licenses/>. */ |
33574c17 ST |
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> | |
706ad1e7 | 27 | #include <sys/single_threaded.h> |
33574c17 ST |
28 | |
29 | #include <pt-internal.h> | |
f6fb29d2 | 30 | #include <pthreadP.h> |
33574c17 ST |
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 | \f | |
44 | ||
45 | /* The entry-point for new threads. */ | |
46 | static void | |
47 | entry_point (struct __pthread *self, void *(*start_routine) (void *), void *arg) | |
48 | { | |
d482ebfa ST |
49 | int err; |
50 | ||
33574c17 ST |
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 | ||
d482ebfa ST |
65 | /* We can now unleash signals. */ |
66 | err = __pthread_sigstate (self, SIG_SETMASK, &self->init_sigset, 0, 0); | |
67 | assert_perror (err); | |
68 | ||
0c036123 ST |
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 ((void*) (uintptr_t) start (arg)); | |
77 | } | |
78 | else | |
79 | __pthread_exit (start_routine (arg)); | |
33574c17 ST |
80 | } |
81 | ||
82 | /* Create a thread with attributes given by ATTR, executing | |
83 | START_ROUTINE with argument ARG. */ | |
84 | int | |
f6fb29d2 ST |
85 | __pthread_create (pthread_t * thread, const pthread_attr_t * attr, |
86 | void *(*start_routine) (void *), void *arg) | |
33574c17 ST |
87 | { |
88 | int err; | |
89 | struct __pthread *pthread; | |
90 | ||
91 | err = __pthread_create_internal (&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 | } | |
fba7fc5a | 99 | weak_alias (__pthread_create, pthread_create) |
7c331116 | 100 | hidden_def (__pthread_create) |
33574c17 ST |
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 | ||
706ad1e7 FW |
115 | /* Avoid a data race in the multi-threaded case. */ |
116 | if (__libc_single_threaded) | |
117 | __libc_single_threaded = 0; | |
118 | ||
33574c17 ST |
119 | /* Allocate a new thread structure. */ |
120 | err = __pthread_alloc (&pthread); | |
121 | if (err) | |
122 | goto failed; | |
123 | ||
0c036123 ST |
124 | if (attr == ATTR_C11_THREAD) |
125 | { | |
126 | attr = NULL; | |
127 | pthread->c11 = true; | |
128 | } | |
129 | else | |
130 | pthread->c11 = false; | |
131 | ||
33574c17 ST |
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 (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 (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 (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 (__pthread_num_threads == 1) | |
d482ebfa | 211 | err = __sigprocmask (0, 0, &pthread->init_sigset); |
33574c17 | 212 | else |
d482ebfa | 213 | err = __pthread_sigstate (_pthread_self (), 0, 0, &pthread->init_sigset, 0); |
33574c17 ST |
214 | assert_perror (err); |
215 | ||
d482ebfa ST |
216 | /* But block the signals for now, until the thread is fully initialized. */ |
217 | __sigfillset (&sigset); | |
33574c17 ST |
218 | err = __pthread_sigstate (pthread, SIG_SETMASK, &sigset, 0, 1); |
219 | assert_perror (err); | |
220 | ||
221 | /* Increase the total number of threads. We do this before actually | |
222 | starting the new thread, since the new thread might immediately | |
223 | call `pthread_exit' which decreases the number of threads and | |
224 | calls `exit' if the number of threads reaches zero. Increasing | |
225 | the number of threads from within the new thread isn't an option | |
226 | since this thread might return and call `pthread_exit' before the | |
227 | new thread runs. */ | |
228 | atomic_increment (&__pthread_total); | |
229 | ||
230 | /* Store a pointer to this thread in the thread ID lookup table. We | |
231 | could use __thread_setid, however, we only lock for reading as no | |
232 | other thread should be using this entry (we also assume that the | |
233 | store is atomic). */ | |
234 | __pthread_rwlock_rdlock (&__pthread_threads_lock); | |
235 | __pthread_threads[pthread->thread - 1] = pthread; | |
236 | __pthread_rwlock_unlock (&__pthread_threads_lock); | |
237 | ||
238 | /* At this point it is possible to guess our pthread ID. We have to | |
239 | make sure that all functions taking a pthread_t argument can | |
240 | handle the fact that this thread isn't really running yet. Since | |
241 | the new thread might be passed its ID through pthread_create (to | |
242 | avoid calling pthread_self), read it before starting the thread. */ | |
243 | *thread = pthread; | |
244 | ||
245 | /* Schedule the new thread. */ | |
246 | err = __pthread_thread_start (pthread); | |
247 | if (err) | |
248 | goto failed_starting; | |
249 | ||
250 | ||
251 | return 0; | |
252 | ||
253 | failed_starting: | |
254 | /* If joinable, a reference was added for the caller. */ | |
255 | if (pthread->state == PTHREAD_JOINABLE) | |
256 | __pthread_dealloc (pthread); | |
257 | ||
258 | __pthread_setid (pthread->thread, NULL); | |
259 | atomic_decrement (&__pthread_total); | |
260 | failed_sigstate: | |
261 | __pthread_sigstate_destroy (pthread); | |
262 | failed_setup: | |
263 | _dl_deallocate_tls (pthread->tcb, 1); | |
264 | pthread->tcb = NULL; | |
265 | failed_thread_tls_alloc: | |
266 | __pthread_thread_terminate (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 (pthread); | |
278 | failed: | |
279 | return err; | |
280 | } |