always block signals for starting new threads, refactor start args
[musl] / src / thread / pthread_create.c
1 #define _GNU_SOURCE
2 #include "pthread_impl.h"
3 #include "stdio_impl.h"
4 #include "libc.h"
5 #include "lock.h"
6 #include <sys/mman.h>
7 #include <string.h>
8 #include <stddef.h>
9
10 static void dummy_0()
11 {
12 }
13 weak_alias(dummy_0, __acquire_ptc);
14 weak_alias(dummy_0, __release_ptc);
15 weak_alias(dummy_0, __pthread_tsd_run_dtors);
16 weak_alias(dummy_0, __do_orphaned_stdio_locks);
17 weak_alias(dummy_0, __dl_thread_cleanup);
18
19 _Noreturn void __pthread_exit(void *result)
20 {
21         pthread_t self = __pthread_self();
22         sigset_t set;
23
24         self->canceldisable = 1;
25         self->cancelasync = 0;
26         self->result = result;
27
28         while (self->cancelbuf) {
29                 void (*f)(void *) = self->cancelbuf->__f;
30                 void *x = self->cancelbuf->__x;
31                 self->cancelbuf = self->cancelbuf->__next;
32                 f(x);
33         }
34
35         __pthread_tsd_run_dtors();
36
37         /* Access to target the exiting thread with syscalls that use
38          * its kernel tid is controlled by killlock. For detached threads,
39          * any use past this point would have undefined behavior, but for
40          * joinable threads it's a valid usage that must be handled. */
41         LOCK(self->killlock);
42
43         /* Block all signals before decrementing the live thread count.
44          * This is important to ensure that dynamically allocated TLS
45          * is not under-allocated/over-committed, and possibly for other
46          * reasons as well. */
47         __block_all_sigs(&set);
48
49         /* It's impossible to determine whether this is "the last thread"
50          * until performing the atomic decrement, since multiple threads
51          * could exit at the same time. For the last thread, revert the
52          * decrement, restore the tid, and unblock signals to give the
53          * atexit handlers and stdio cleanup code a consistent state. */
54         if (a_fetch_add(&libc.threads_minus_1, -1)==0) {
55                 libc.threads_minus_1 = 0;
56                 UNLOCK(self->killlock);
57                 __restore_sigs(&set);
58                 exit(0);
59         }
60
61         /* Process robust list in userspace to handle non-pshared mutexes
62          * and the detached thread case where the robust list head will
63          * be invalid when the kernel would process it. */
64         __vm_lock();
65         volatile void *volatile *rp;
66         while ((rp=self->robust_list.head) && rp != &self->robust_list.head) {
67                 pthread_mutex_t *m = (void *)((char *)rp
68                         - offsetof(pthread_mutex_t, _m_next));
69                 int waiters = m->_m_waiters;
70                 int priv = (m->_m_type & 128) ^ 128;
71                 self->robust_list.pending = rp;
72                 self->robust_list.head = *rp;
73                 int cont = a_swap(&m->_m_lock, 0x40000000);
74                 self->robust_list.pending = 0;
75                 if (cont < 0 || waiters)
76                         __wake(&m->_m_lock, 1, priv);
77         }
78         __vm_unlock();
79
80         __do_orphaned_stdio_locks();
81         __dl_thread_cleanup();
82
83         /* This atomic potentially competes with a concurrent pthread_detach
84          * call; the loser is responsible for freeing thread resources. */
85         int state = a_cas(&self->detach_state, DT_JOINABLE, DT_EXITING);
86
87         if (state>=DT_DETACHED && self->map_base) {
88                 /* Detached threads must avoid the kernel clear_child_tid
89                  * feature, since the virtual address will have been
90                  * unmapped and possibly already reused by a new mapping
91                  * at the time the kernel would perform the write. In
92                  * the case of threads that started out detached, the
93                  * initial clone flags are correct, but if the thread was
94                  * detached later, we need to clear it here. */
95                 if (state == DT_DYNAMIC) __syscall(SYS_set_tid_address, 0);
96
97                 /* Robust list will no longer be valid, and was already
98                  * processed above, so unregister it with the kernel. */
99                 if (self->robust_list.off)
100                         __syscall(SYS_set_robust_list, 0, 3*sizeof(long));
101
102                 /* Since __unmapself bypasses the normal munmap code path,
103                  * explicitly wait for vmlock holders first. */
104                 __vm_wait();
105
106                 /* The following call unmaps the thread's stack mapping
107                  * and then exits without touching the stack. */
108                 __unmapself(self->map_base, self->map_size);
109         }
110
111         /* After the kernel thread exits, its tid may be reused. Clear it
112          * to prevent inadvertent use and inform functions that would use
113          * it that it's no longer available. */
114         self->tid = 0;
115         UNLOCK(self->killlock);
116
117         for (;;) __syscall(SYS_exit, 0);
118 }
119
120 void __do_cleanup_push(struct __ptcb *cb)
121 {
122         struct pthread *self = __pthread_self();
123         cb->__next = self->cancelbuf;
124         self->cancelbuf = cb;
125 }
126
127 void __do_cleanup_pop(struct __ptcb *cb)
128 {
129         __pthread_self()->cancelbuf = cb->__next;
130 }
131
132 struct start_args {
133         void *(*start_func)(void *);
134         void *start_arg;
135         pthread_attr_t *attr;
136         volatile int *perr;
137         unsigned long sig_mask[_NSIG/8/sizeof(long)];
138 };
139
140 static int start(void *p)
141 {
142         struct start_args *args = p;
143         if (args->attr) {
144                 pthread_t self = __pthread_self();
145                 int ret = -__syscall(SYS_sched_setscheduler, self->tid,
146                         args->attr->_a_policy, &args->attr->_a_prio);
147                 if (a_swap(args->perr, ret)==-2)
148                         __wake(args->perr, 1, 1);
149                 if (ret) {
150                         self->detach_state = DT_DYNAMIC;
151                         __pthread_exit(0);
152                 }
153         }
154         __syscall(SYS_rt_sigprocmask, SIG_SETMASK, &args->sig_mask, 0, _NSIG/8);
155         __pthread_exit(args->start_func(args->start_arg));
156         return 0;
157 }
158
159 static int start_c11(void *p)
160 {
161         struct start_args *args = p;
162         int (*start)(void*) = (int(*)(void*)) args->start_func;
163         __pthread_exit((void *)(uintptr_t)start(args->start_arg));
164         return 0;
165 }
166
167 #define ROUND(x) (((x)+PAGE_SIZE-1)&-PAGE_SIZE)
168
169 /* pthread_key_create.c overrides this */
170 static volatile size_t dummy = 0;
171 weak_alias(dummy, __pthread_tsd_size);
172 static void *dummy_tsd[1] = { 0 };
173 weak_alias(dummy_tsd, __pthread_tsd_main);
174
175 volatile int __block_new_threads = 0;
176
177 static FILE *volatile dummy_file = 0;
178 weak_alias(dummy_file, __stdin_used);
179 weak_alias(dummy_file, __stdout_used);
180 weak_alias(dummy_file, __stderr_used);
181
182 static void init_file_lock(FILE *f)
183 {
184         if (f && f->lock<0) f->lock = 0;
185 }
186
187 int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict attrp, void *(*entry)(void *), void *restrict arg)
188 {
189         int ret, c11 = (attrp == __ATTRP_C11_THREAD);
190         size_t size, guard;
191         struct pthread *self, *new;
192         unsigned char *map = 0, *stack = 0, *tsd = 0, *stack_limit;
193         unsigned flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND
194                 | CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS
195                 | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_DETACHED;
196         pthread_attr_t attr = { 0 };
197         sigset_t set;
198         volatile int err = -1;
199
200         if (!libc.can_do_threads) return ENOSYS;
201         self = __pthread_self();
202         if (!libc.threaded) {
203                 for (FILE *f=*__ofl_lock(); f; f=f->next)
204                         init_file_lock(f);
205                 __ofl_unlock();
206                 init_file_lock(__stdin_used);
207                 init_file_lock(__stdout_used);
208                 init_file_lock(__stderr_used);
209                 __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, SIGPT_SET, 0, _NSIG/8);
210                 self->tsd = (void **)__pthread_tsd_main;
211                 libc.threaded = 1;
212         }
213         if (attrp && !c11) attr = *attrp;
214
215         __acquire_ptc();
216         if (!attrp || c11) {
217                 attr._a_stacksize = __default_stacksize;
218                 attr._a_guardsize = __default_guardsize;
219         }
220
221         if (__block_new_threads) __wait(&__block_new_threads, 0, 1, 1);
222
223         if (attr._a_stackaddr) {
224                 size_t need = libc.tls_size + __pthread_tsd_size;
225                 size = attr._a_stacksize;
226                 stack = (void *)(attr._a_stackaddr & -16);
227                 stack_limit = (void *)(attr._a_stackaddr - size);
228                 /* Use application-provided stack for TLS only when
229                  * it does not take more than ~12% or 2k of the
230                  * application's stack space. */
231                 if (need < size/8 && need < 2048) {
232                         tsd = stack - __pthread_tsd_size;
233                         stack = tsd - libc.tls_size;
234                         memset(stack, 0, need);
235                 } else {
236                         size = ROUND(need);
237                 }
238                 guard = 0;
239         } else {
240                 guard = ROUND(attr._a_guardsize);
241                 size = guard + ROUND(attr._a_stacksize
242                         + libc.tls_size +  __pthread_tsd_size);
243         }
244
245         if (!tsd) {
246                 if (guard) {
247                         map = __mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANON, -1, 0);
248                         if (map == MAP_FAILED) goto fail;
249                         if (__mprotect(map+guard, size-guard, PROT_READ|PROT_WRITE)
250                             && errno != ENOSYS) {
251                                 __munmap(map, size);
252                                 goto fail;
253                         }
254                 } else {
255                         map = __mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
256                         if (map == MAP_FAILED) goto fail;
257                 }
258                 tsd = map + size - __pthread_tsd_size;
259                 if (!stack) {
260                         stack = tsd - libc.tls_size;
261                         stack_limit = map + guard;
262                 }
263         }
264
265         new = __copy_tls(tsd - libc.tls_size);
266         new->map_base = map;
267         new->map_size = size;
268         new->stack = stack;
269         new->stack_size = stack - stack_limit;
270         new->guard_size = guard;
271         new->self = new;
272         new->tsd = (void *)tsd;
273         new->locale = &libc.global_locale;
274         if (attr._a_detach) {
275                 new->detach_state = DT_DETACHED;
276                 flags -= CLONE_CHILD_CLEARTID;
277         } else {
278                 new->detach_state = DT_JOINABLE;
279         }
280         new->robust_list.head = &new->robust_list.head;
281         new->CANARY = self->CANARY;
282
283         /* Setup argument structure for the new thread on its stack. */
284         stack -= (uintptr_t)stack % sizeof(uintptr_t);
285         stack -= sizeof(struct start_args);
286         struct start_args *args = (void *)stack;
287         args->start_func = entry;
288         args->start_arg = arg;
289         if (attr._a_sched) {
290                 args->attr = &attr;
291                 args->perr = &err;
292         } else {
293                 args->attr = 0;
294                 args->perr = 0;
295         }
296
297         __block_app_sigs(&set);
298
299         /* Ensure SIGCANCEL is unblocked in new thread. This requires
300          * working with a copy of the set so we can restore the
301          * original mask in the calling thread. */
302         memcpy(&args->sig_mask, &set, sizeof args->sig_mask);
303         args->sig_mask[(SIGCANCEL-1)/8/sizeof(long)] &=
304                 ~(1UL<<((SIGCANCEL-1)%(8*sizeof(long))));
305
306         a_inc(&libc.threads_minus_1);
307         ret = __clone((c11 ? start_c11 : start), stack, flags, args, &new->tid, TP_ADJ(new), &new->detach_state);
308
309         __restore_sigs(&set);
310         __release_ptc();
311
312         if (ret < 0) {
313                 a_dec(&libc.threads_minus_1);
314                 if (map) __munmap(map, size);
315                 return EAGAIN;
316         }
317
318         if (attr._a_sched) {
319                 if (a_cas(&err, -1, -2)==-1)
320                         __wait(&err, 0, -2, 1);
321                 ret = err;
322                 if (ret) return ret;
323         }
324
325         *res = new;
326         return 0;
327 fail:
328         __release_ptc();
329         return EAGAIN;
330 }
331
332 weak_alias(__pthread_exit, pthread_exit);
333 weak_alias(__pthread_create, pthread_create);