diff options
Diffstat (limited to 'src/thread')
-rw-r--r-- | src/thread/cancel_impl.c | 3 | ||||
-rw-r--r-- | src/thread/pthread_create.c | 11 | ||||
-rw-r--r-- | src/thread/pthread_key_create.c | 8 | ||||
-rw-r--r-- | src/thread/pthread_self.c | 41 | ||||
-rw-r--r-- | src/thread/pthread_setcancelstate.c | 12 |
5 files changed, 23 insertions, 52 deletions
diff --git a/src/thread/cancel_impl.c b/src/thread/cancel_impl.c index c835813a..525d2904 100644 --- a/src/thread/cancel_impl.c +++ b/src/thread/cancel_impl.c @@ -20,7 +20,7 @@ long (__syscall_cp)(syscall_arg_t nr, pthread_t self; long r; - if (!libc.main_thread || (self = __pthread_self())->canceldisable) + if (!libc.has_thread_pointer || (self = __pthread_self())->canceldisable) return __syscall(nr, u, v, w, x, y, z); r = __syscall_cp_asm(&self->cancel, nr, u, v, w, x, y, z); @@ -57,6 +57,7 @@ static void cancel_handler(int sig, siginfo_t *si, void *ctx) void __testcancel() { + if (!libc.has_thread_pointer) return; pthread_t self = pthread_self(); if (self->cancel && !self->canceldisable) __cancel(); diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c index ee6c31c4..08c74110 100644 --- a/src/thread/pthread_create.c +++ b/src/thread/pthread_create.c @@ -77,6 +77,7 @@ _Noreturn void pthread_exit(void *result) void __do_cleanup_push(struct __ptcb *cb) { + if (!libc.has_thread_pointer) return; struct pthread *self = pthread_self(); cb->__next = self->cancelbuf; self->cancelbuf = cb; @@ -84,6 +85,7 @@ void __do_cleanup_push(struct __ptcb *cb) void __do_cleanup_pop(struct __ptcb *cb) { + if (!libc.has_thread_pointer) return; __pthread_self()->cancelbuf = cb->__next; } @@ -110,6 +112,8 @@ static int start(void *p) /* pthread_key_create.c overrides this */ static const size_t dummy = 0; weak_alias(dummy, __pthread_tsd_size); +static const void *dummy_tsd[1] = { 0 }; +weak_alias(dummy_tsd, __pthread_tsd_main); static FILE *const dummy_file = 0; weak_alias(dummy_file, __stdin_used); @@ -127,7 +131,7 @@ int pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict attrp { int ret; size_t size, guard; - struct pthread *self = pthread_self(), *new; + struct pthread *self, *new; unsigned char *map = 0, *stack = 0, *tsd = 0, *stack_limit; unsigned flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS @@ -135,13 +139,16 @@ int pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict attrp int do_sched = 0; pthread_attr_t attr = {0}; - if (!self) return ENOSYS; + if (!libc.can_do_threads) return ENOSYS; + self = __pthread_self(); if (!libc.threaded) { for (FILE *f=libc.ofl_head; f; f=f->next) init_file_lock(f); init_file_lock(__stdin_used); init_file_lock(__stdout_used); init_file_lock(__stderr_used); + __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, SIGPT_SET, 0, _NSIG/8); + self->tsd = __pthread_tsd_main; libc.threaded = 1; } if (attrp) attr = *attrp; diff --git a/src/thread/pthread_key_create.c b/src/thread/pthread_key_create.c index c29935c1..ef8a755d 100644 --- a/src/thread/pthread_key_create.c +++ b/src/thread/pthread_key_create.c @@ -14,7 +14,13 @@ int pthread_key_create(pthread_key_t *k, void (*dtor)(void *)) unsigned i = (uintptr_t)&k / 16 % PTHREAD_KEYS_MAX; unsigned j = i; - __pthread_self_init(); + if (libc.has_thread_pointer) { + pthread_t self = __pthread_self(); + /* This can only happen in the main thread before + * pthread_create has been called. */ + if (!self->tsd) self->tsd = __pthread_tsd_main; + } + if (!dtor) dtor = nodtor; do { if (!a_cas_p(keys+j, 0, (void *)dtor)) { diff --git a/src/thread/pthread_self.c b/src/thread/pthread_self.c index aed4b5f1..5f9e6516 100644 --- a/src/thread/pthread_self.c +++ b/src/thread/pthread_self.c @@ -1,45 +1,6 @@ #include "pthread_impl.h" -static struct pthread *main_thread = &(struct pthread){0}; - -/* pthread_key_create.c overrides this */ -static const void *dummy[1] = { 0 }; -weak_alias(dummy, __pthread_tsd_main); - -static int init_main_thread() -{ - __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, - SIGPT_SET, 0, _NSIG/8); - if (__set_thread_area(TP_ADJ(main_thread)) < 0) return -1; - main_thread->canceldisable = libc.canceldisable; - main_thread->tsd = (void **)__pthread_tsd_main; - main_thread->errno_ptr = __errno_location(); - main_thread->self = main_thread; - main_thread->tid = main_thread->pid = - __syscall(SYS_set_tid_address, &main_thread->tid); - if (!main_thread->dtv) - main_thread->dtv = (void *)dummy; - libc.main_thread = main_thread; - return 0; -} - -pthread_t __pthread_self_def() +pthread_t pthread_self() { - static int init, failed; - if (!init) { - if (failed) return 0; - if (init_main_thread() < 0) failed = 1; - if (failed) return 0; - init = 1; - } return __pthread_self(); } - -weak_alias(__pthread_self_def, pthread_self); -weak_alias(__pthread_self_def, __pthread_self_init); - -void *__install_initial_tls(void *p) -{ - main_thread = p; - return __pthread_self_def(); -} diff --git a/src/thread/pthread_setcancelstate.c b/src/thread/pthread_setcancelstate.c index ba2b2311..060bcdcc 100644 --- a/src/thread/pthread_setcancelstate.c +++ b/src/thread/pthread_setcancelstate.c @@ -3,13 +3,9 @@ int pthread_setcancelstate(int new, int *old) { if (new > 1U) return EINVAL; - if (libc.main_thread) { - struct pthread *self = __pthread_self(); - if (old) *old = self->canceldisable; - self->canceldisable = new; - } else { - if (old) *old = libc.canceldisable; - libc.canceldisable = new; - } + if (!libc.has_thread_pointer) return ENOSYS; + struct pthread *self = __pthread_self(); + if (old) *old = self->canceldisable; + self->canceldisable = new; return 0; } |