install dynamic tls synchronously at dlopen, streamline access
[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 weak_alias(dummy_0, __dl_prepare_for_threads);
19
20 void __tl_lock(void)
21 {
22         if (!a_cas(&__thread_list_lock, 0, 1)) return;
23         do {
24                 a_cas(&__thread_list_lock, 1, 2);
25                 __futexwait(&__thread_list_lock, 2, 0);
26         } while (a_cas(&__thread_list_lock, 0, 2));
27 }
28
29 void __tl_unlock(void)
30 {
31         if (a_swap(&__thread_list_lock, 0)==2)
32                 __wake(&__thread_list_lock, 1, 0);
33 }
34
35 void __tl_sync(pthread_t td)
36 {
37         a_barrier();
38         if (!__thread_list_lock) return;
39         a_cas(&__thread_list_lock, 1, 2);
40         __wait(&__thread_list_lock, 0, 2, 0);
41         __wake(&__thread_list_lock, 1, 0);
42 }
43
44 _Noreturn void __pthread_exit(void *result)
45 {
46         pthread_t self = __pthread_self();
47         sigset_t set;
48
49         self->canceldisable = 1;
50         self->cancelasync = 0;
51         self->result = result;
52
53         while (self->cancelbuf) {
54                 void (*f)(void *) = self->cancelbuf->__f;
55                 void *x = self->cancelbuf->__x;
56                 self->cancelbuf = self->cancelbuf->__next;
57                 f(x);
58         }
59
60         __pthread_tsd_run_dtors();
61
62         /* Access to target the exiting thread with syscalls that use
63          * its kernel tid is controlled by killlock. For detached threads,
64          * any use past this point would have undefined behavior, but for
65          * joinable threads it's a valid usage that must be handled. */
66         LOCK(self->killlock);
67
68         /* The thread list lock must be AS-safe, and thus requires
69          * application signals to be blocked before it can be taken. */
70         __block_app_sigs(&set);
71         __tl_lock();
72
73         /* If this is the only thread in the list, don't proceed with
74          * termination of the thread, but restore the previous lock and
75          * signal state to prepare for exit to call atexit handlers. */
76         if (self->next == self) {
77                 __tl_unlock();
78                 __restore_sigs(&set);
79                 UNLOCK(self->killlock);
80                 exit(0);
81         }
82
83         /* At this point we are committed to thread termination. Unlink
84          * the thread from the list. This change will not be visible
85          * until the lock is released, which only happens after SYS_exit
86          * has been called, via the exit futex address pointing at the lock. */
87         libc.threads_minus_1--;
88         self->next->prev = self->prev;
89         self->prev->next = self->next;
90         self->prev = self->next = self;
91
92         /* Process robust list in userspace to handle non-pshared mutexes
93          * and the detached thread case where the robust list head will
94          * be invalid when the kernel would process it. */
95         __vm_lock();
96         volatile void *volatile *rp;
97         while ((rp=self->robust_list.head) && rp != &self->robust_list.head) {
98                 pthread_mutex_t *m = (void *)((char *)rp
99                         - offsetof(pthread_mutex_t, _m_next));
100                 int waiters = m->_m_waiters;
101                 int priv = (m->_m_type & 128) ^ 128;
102                 self->robust_list.pending = rp;
103                 self->robust_list.head = *rp;
104                 int cont = a_swap(&m->_m_lock, 0x40000000);
105                 self->robust_list.pending = 0;
106                 if (cont < 0 || waiters)
107                         __wake(&m->_m_lock, 1, priv);
108         }
109         __vm_unlock();
110
111         __do_orphaned_stdio_locks();
112         __dl_thread_cleanup();
113
114         /* This atomic potentially competes with a concurrent pthread_detach
115          * call; the loser is responsible for freeing thread resources. */
116         int state = a_cas(&self->detach_state, DT_JOINABLE, DT_EXITING);
117
118         if (state==DT_DETACHED && self->map_base) {
119                 /* Detached threads must block even implementation-internal
120                  * signals, since they will not have a stack in their last
121                  * moments of existence. */
122                 __block_all_sigs(&set);
123
124                 /* Robust list will no longer be valid, and was already
125                  * processed above, so unregister it with the kernel. */
126                 if (self->robust_list.off)
127                         __syscall(SYS_set_robust_list, 0, 3*sizeof(long));
128
129                 /* Since __unmapself bypasses the normal munmap code path,
130                  * explicitly wait for vmlock holders first. */
131                 __vm_wait();
132
133                 /* The following call unmaps the thread's stack mapping
134                  * and then exits without touching the stack. */
135                 __unmapself(self->map_base, self->map_size);
136         }
137
138         /* Wake any joiner. */
139         __wake(&self->detach_state, 1, 1);
140
141         /* After the kernel thread exits, its tid may be reused. Clear it
142          * to prevent inadvertent use and inform functions that would use
143          * it that it's no longer available. */
144         self->tid = 0;
145         UNLOCK(self->killlock);
146
147         for (;;) __syscall(SYS_exit, 0);
148 }
149
150 void __do_cleanup_push(struct __ptcb *cb)
151 {
152         struct pthread *self = __pthread_self();
153         cb->__next = self->cancelbuf;
154         self->cancelbuf = cb;
155 }
156
157 void __do_cleanup_pop(struct __ptcb *cb)
158 {
159         __pthread_self()->cancelbuf = cb->__next;
160 }
161
162 struct start_args {
163         void *(*start_func)(void *);
164         void *start_arg;
165         pthread_attr_t *attr;
166         volatile int *perr;
167         unsigned long sig_mask[_NSIG/8/sizeof(long)];
168 };
169
170 static int start(void *p)
171 {
172         struct start_args *args = p;
173         if (args->attr) {
174                 pthread_t self = __pthread_self();
175                 int ret = -__syscall(SYS_sched_setscheduler, self->tid,
176                         args->attr->_a_policy, &args->attr->_a_prio);
177                 if (a_swap(args->perr, ret)==-2)
178                         __wake(args->perr, 1, 1);
179                 if (ret) {
180                         self->detach_state = DT_DETACHED;
181                         __pthread_exit(0);
182                 }
183         }
184         __syscall(SYS_rt_sigprocmask, SIG_SETMASK, &args->sig_mask, 0, _NSIG/8);
185         __pthread_exit(args->start_func(args->start_arg));
186         return 0;
187 }
188
189 static int start_c11(void *p)
190 {
191         struct start_args *args = p;
192         int (*start)(void*) = (int(*)(void*)) args->start_func;
193         __pthread_exit((void *)(uintptr_t)start(args->start_arg));
194         return 0;
195 }
196
197 #define ROUND(x) (((x)+PAGE_SIZE-1)&-PAGE_SIZE)
198
199 /* pthread_key_create.c overrides this */
200 static volatile size_t dummy = 0;
201 weak_alias(dummy, __pthread_tsd_size);
202 static void *dummy_tsd[1] = { 0 };
203 weak_alias(dummy_tsd, __pthread_tsd_main);
204
205 static FILE *volatile dummy_file = 0;
206 weak_alias(dummy_file, __stdin_used);
207 weak_alias(dummy_file, __stdout_used);
208 weak_alias(dummy_file, __stderr_used);
209
210 static void init_file_lock(FILE *f)
211 {
212         if (f && f->lock<0) f->lock = 0;
213 }
214
215 int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict attrp, void *(*entry)(void *), void *restrict arg)
216 {
217         int ret, c11 = (attrp == __ATTRP_C11_THREAD);
218         size_t size, guard;
219         struct pthread *self, *new;
220         unsigned char *map = 0, *stack = 0, *tsd = 0, *stack_limit;
221         unsigned flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND
222                 | CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS
223                 | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_DETACHED;
224         pthread_attr_t attr = { 0 };
225         sigset_t set;
226         volatile int err = -1;
227
228         if (!libc.can_do_threads) return ENOSYS;
229         self = __pthread_self();
230         if (!libc.threaded) {
231                 for (FILE *f=*__ofl_lock(); f; f=f->next)
232                         init_file_lock(f);
233                 __ofl_unlock();
234                 init_file_lock(__stdin_used);
235                 init_file_lock(__stdout_used);
236                 init_file_lock(__stderr_used);
237                 __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, SIGPT_SET, 0, _NSIG/8);
238                 self->tsd = (void **)__pthread_tsd_main;
239                 __dl_prepare_for_threads();
240                 libc.threaded = 1;
241         }
242         if (attrp && !c11) attr = *attrp;
243
244         __acquire_ptc();
245         if (!attrp || c11) {
246                 attr._a_stacksize = __default_stacksize;
247                 attr._a_guardsize = __default_guardsize;
248         }
249
250         if (attr._a_stackaddr) {
251                 size_t need = libc.tls_size + __pthread_tsd_size;
252                 size = attr._a_stacksize;
253                 stack = (void *)(attr._a_stackaddr & -16);
254                 stack_limit = (void *)(attr._a_stackaddr - size);
255                 /* Use application-provided stack for TLS only when
256                  * it does not take more than ~12% or 2k of the
257                  * application's stack space. */
258                 if (need < size/8 && need < 2048) {
259                         tsd = stack - __pthread_tsd_size;
260                         stack = tsd - libc.tls_size;
261                         memset(stack, 0, need);
262                 } else {
263                         size = ROUND(need);
264                 }
265                 guard = 0;
266         } else {
267                 guard = ROUND(attr._a_guardsize);
268                 size = guard + ROUND(attr._a_stacksize
269                         + libc.tls_size +  __pthread_tsd_size);
270         }
271
272         if (!tsd) {
273                 if (guard) {
274                         map = __mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANON, -1, 0);
275                         if (map == MAP_FAILED) goto fail;
276                         if (__mprotect(map+guard, size-guard, PROT_READ|PROT_WRITE)
277                             && errno != ENOSYS) {
278                                 __munmap(map, size);
279                                 goto fail;
280                         }
281                 } else {
282                         map = __mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
283                         if (map == MAP_FAILED) goto fail;
284                 }
285                 tsd = map + size - __pthread_tsd_size;
286                 if (!stack) {
287                         stack = tsd - libc.tls_size;
288                         stack_limit = map + guard;
289                 }
290         }
291
292         new = __copy_tls(tsd - libc.tls_size);
293         new->map_base = map;
294         new->map_size = size;
295         new->stack = stack;
296         new->stack_size = stack - stack_limit;
297         new->guard_size = guard;
298         new->self = new;
299         new->tsd = (void *)tsd;
300         new->locale = &libc.global_locale;
301         if (attr._a_detach) {
302                 new->detach_state = DT_DETACHED;
303         } else {
304                 new->detach_state = DT_JOINABLE;
305         }
306         new->robust_list.head = &new->robust_list.head;
307         new->CANARY = self->CANARY;
308
309         /* Setup argument structure for the new thread on its stack.
310          * It's safe to access from the caller only until the thread
311          * list is unlocked. */
312         stack -= (uintptr_t)stack % sizeof(uintptr_t);
313         stack -= sizeof(struct start_args);
314         struct start_args *args = (void *)stack;
315         args->start_func = entry;
316         args->start_arg = arg;
317         if (attr._a_sched) {
318                 args->attr = &attr;
319                 args->perr = &err;
320         } else {
321                 args->attr = 0;
322                 args->perr = 0;
323         }
324
325         /* Application signals (but not the synccall signal) must be
326          * blocked before the thread list lock can be taken, to ensure
327          * that the lock is AS-safe. */
328         __block_app_sigs(&set);
329
330         /* Ensure SIGCANCEL is unblocked in new thread. This requires
331          * working with a copy of the set so we can restore the
332          * original mask in the calling thread. */
333         memcpy(&args->sig_mask, &set, sizeof args->sig_mask);
334         args->sig_mask[(SIGCANCEL-1)/8/sizeof(long)] &=
335                 ~(1UL<<((SIGCANCEL-1)%(8*sizeof(long))));
336
337         __tl_lock();
338         libc.threads_minus_1++;
339         ret = __clone((c11 ? start_c11 : start), stack, flags, args, &new->tid, TP_ADJ(new), &__thread_list_lock);
340
341         /* If clone succeeded, new thread must be linked on the thread
342          * list before unlocking it, even if scheduling may still fail. */
343         if (ret >= 0) {
344                 new->next = self->next;
345                 new->prev = self;
346                 new->next->prev = new;
347                 new->prev->next = new;
348         }
349         __tl_unlock();
350         __restore_sigs(&set);
351         __release_ptc();
352
353         if (ret < 0) {
354                 libc.threads_minus_1--;
355                 if (map) __munmap(map, size);
356                 return EAGAIN;
357         }
358
359         if (attr._a_sched) {
360                 if (a_cas(&err, -1, -2)==-1)
361                         __wait(&err, 0, -2, 1);
362                 ret = err;
363                 if (ret) return ret;
364         }
365
366         *res = new;
367         return 0;
368 fail:
369         __release_ptc();
370         return EAGAIN;
371 }
372
373 weak_alias(__pthread_exit, pthread_exit);
374 weak_alias(__pthread_create, pthread_create);