]> git.ipfire.org Git - thirdparty/glibc.git/blame - htl/pt-create.c
Fix all the remaining misspellings -- BZ 25337
[thirdparty/glibc.git] / htl / pt-create.c
CommitLineData
33574c17 1/* Thread creation.
6d7e8eda 2 Copyright (C) 2000-2023 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
33574c17
ST
39/* The entry-point for new threads. */
40static void
41entry_point (struct __pthread *self, void *(*start_routine) (void *), void *arg)
42{
d482ebfa
ST
43 int err;
44
33574c17
ST
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
d482ebfa
ST
59 /* We can now unleash signals. */
60 err = __pthread_sigstate (self, SIG_SETMASK, &self->init_sigset, 0, 0);
61 assert_perror (err);
62
0c036123
ST
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 ((void*) (uintptr_t) start (arg));
71 }
72 else
73 __pthread_exit (start_routine (arg));
33574c17
ST
74}
75
76/* Create a thread with attributes given by ATTR, executing
77 START_ROUTINE with argument ARG. */
78int
f6fb29d2
ST
79__pthread_create (pthread_t * thread, const pthread_attr_t * attr,
80 void *(*start_routine) (void *), void *arg)
33574c17
ST
81{
82 int err;
83 struct __pthread *pthread;
84
85 err = __pthread_create_internal (&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}
fba7fc5a 93weak_alias (__pthread_create, pthread_create)
7c331116 94hidden_def (__pthread_create)
33574c17
ST
95
96/* Internal version of pthread_create. See comment in
97 pt-internal.h. */
98int
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
706ad1e7
FW
109 /* Avoid a data race in the multi-threaded case. */
110 if (__libc_single_threaded)
111 __libc_single_threaded = 0;
112
33574c17
ST
113 /* Allocate a new thread structure. */
114 err = __pthread_alloc (&pthread);
115 if (err)
116 goto failed;
117
0c036123
ST
118 if (attr == ATTR_C11_THREAD)
119 {
120 attr = NULL;
121 pthread->c11 = true;
122 }
123 else
124 pthread->c11 = false;
125
33574c17
ST
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;
3a614f39
ST
133 err = __getrlimit (RLIMIT_STACK, &rlim);
134 if (err == 0 && rlim.rlim_cur != RLIM_INFINITY)
33574c17
ST
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 (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 (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 (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
7f0d9e61 202 shall be empty." If the current thread is not a pthread then we
33574c17 203 just inherit the process' sigmask. */
166bb3ea 204 if (GL (dl_pthread_num_threads) == 1)
d482ebfa 205 err = __sigprocmask (0, 0, &pthread->init_sigset);
33574c17 206 else
d482ebfa 207 err = __pthread_sigstate (_pthread_self (), 0, 0, &pthread->init_sigset, 0);
33574c17
ST
208 assert_perror (err);
209
51463869
ST
210 if (start_routine)
211 /* But block the signals for now, until the thread is fully initialized. */
212 __sigfillset (&sigset);
213 else
214 sigset = pthread->init_sigset;
33574c17
ST
215 err = __pthread_sigstate (pthread, SIG_SETMASK, &sigset, 0, 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. */
d1babeb3 225 atomic_fetch_add_relaxed (&__pthread_total, 1);
33574c17
ST
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). */
166bb3ea
SB
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));
33574c17
ST
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 (pthread);
244 if (err)
245 goto failed_starting;
246
247
248 return 0;
249
250failed_starting:
251 /* If joinable, a reference was added for the caller. */
252 if (pthread->state == PTHREAD_JOINABLE)
8c86ba44
ST
253 {
254 __pthread_dealloc (pthread);
255 __pthread_dealloc_finish (pthread);
256 }
33574c17
ST
257
258 __pthread_setid (pthread->thread, NULL);
a364a3a7 259 atomic_fetch_add_relaxed (&__pthread_total, -1);
33574c17
ST
260failed_sigstate:
261 __pthread_sigstate_destroy (pthread);
262failed_setup:
263 _dl_deallocate_tls (pthread->tcb, 1);
264 pthread->tcb = NULL;
265failed_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;
271failed_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);
276failed_stack_alloc:
277 __pthread_dealloc (pthread);
8c86ba44 278 __pthread_dealloc_finish (pthread);
33574c17
ST
279failed:
280 return err;
281}