2 #include "pthread_impl.h"
3 #include "stdio_impl.h"
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);
19 _Noreturn void __pthread_exit(void *result)
21 pthread_t self = __pthread_self();
24 self->canceldisable = 1;
25 self->cancelasync = 0;
26 self->result = result;
28 while (self->cancelbuf) {
29 void (*f)(void *) = self->cancelbuf->__f;
30 void *x = self->cancelbuf->__x;
31 self->cancelbuf = self->cancelbuf->__next;
35 __pthread_tsd_run_dtors();
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. */
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
47 __block_all_sigs(&set);
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);
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. */
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);
80 __do_orphaned_stdio_locks();
81 __dl_thread_cleanup();
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);
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);
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));
102 /* Since __unmapself bypasses the normal munmap code path,
103 * explicitly wait for vmlock holders first. */
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);
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. */
115 UNLOCK(self->killlock);
117 for (;;) __syscall(SYS_exit, 0);
120 void __do_cleanup_push(struct __ptcb *cb)
122 struct pthread *self = __pthread_self();
123 cb->__next = self->cancelbuf;
124 self->cancelbuf = cb;
127 void __do_cleanup_pop(struct __ptcb *cb)
129 __pthread_self()->cancelbuf = cb->__next;
133 void *(*start_func)(void *);
135 pthread_attr_t *attr;
137 unsigned long sig_mask[_NSIG/8/sizeof(long)];
140 static int start(void *p)
142 struct start_args *args = p;
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);
150 self->detach_state = DT_DYNAMIC;
154 __syscall(SYS_rt_sigprocmask, SIG_SETMASK, &args->sig_mask, 0, _NSIG/8);
155 __pthread_exit(args->start_func(args->start_arg));
159 static int start_c11(void *p)
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));
167 #define ROUND(x) (((x)+PAGE_SIZE-1)&-PAGE_SIZE)
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);
175 volatile int __block_new_threads = 0;
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);
182 static void init_file_lock(FILE *f)
184 if (f && f->lock<0) f->lock = 0;
187 int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict attrp, void *(*entry)(void *), void *restrict arg)
189 int ret, c11 = (attrp == __ATTRP_C11_THREAD);
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 };
198 volatile int err = -1;
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)
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;
213 if (attrp && !c11) attr = *attrp;
217 attr._a_stacksize = __default_stacksize;
218 attr._a_guardsize = __default_guardsize;
221 if (__block_new_threads) __wait(&__block_new_threads, 0, 1, 1);
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);
240 guard = ROUND(attr._a_guardsize);
241 size = guard + ROUND(attr._a_stacksize
242 + libc.tls_size + __pthread_tsd_size);
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) {
255 map = __mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
256 if (map == MAP_FAILED) goto fail;
258 tsd = map + size - __pthread_tsd_size;
260 stack = tsd - libc.tls_size;
261 stack_limit = map + guard;
265 new = __copy_tls(tsd - libc.tls_size);
267 new->map_size = size;
269 new->stack_size = stack - stack_limit;
270 new->guard_size = guard;
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;
278 new->detach_state = DT_JOINABLE;
280 new->robust_list.head = &new->robust_list.head;
281 new->CANARY = self->CANARY;
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;
297 __block_app_sigs(&set);
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))));
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);
309 __restore_sigs(&set);
313 a_dec(&libc.threads_minus_1);
314 if (map) __munmap(map, size);
319 if (a_cas(&err, -1, -2)==-1)
320 __wait(&err, 0, -2, 1);
332 weak_alias(__pthread_exit, pthread_exit);
333 weak_alias(__pthread_create, pthread_create);