diff options
Diffstat (limited to 'src/thread/pthread_create.c')
-rw-r--r-- | src/thread/pthread_create.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c index a7aadb51..a65e88e1 100644 --- a/src/thread/pthread_create.c +++ b/src/thread/pthread_create.c @@ -62,6 +62,15 @@ void __do_cleanup_pop(struct __ptcb *cb) static int start(void *p) { pthread_t self = p; + if (self->startlock[0]) { + __wait(self->startlock, 0, 1, 1); + if (self->startlock[0]) { + self->detached = 2; + pthread_exit(0); + } + __syscall(SYS_rt_sigprocmask, SIG_SETMASK, + self->sigmask, 0, __SYSCALL_SSLEN); + } if (self->unblock_cancel) __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, SIGPT_SET, 0, __SYSCALL_SSLEN); @@ -95,6 +104,7 @@ int pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict attr, struct pthread *self = pthread_self(), *new; unsigned char *map, *stack, *tsd; unsigned flags = 0x7d8f00; + int do_sched = 0; if (!self) return ENOSYS; if (!libc.threaded) { @@ -144,6 +154,11 @@ int pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict attr, new->detached = 1; flags -= 0x200000; } + if (attr && attr->_a_sched) { + do_sched = new->startlock[0] = 1; + __syscall(SYS_rt_sigprocmask, SIG_BLOCK, + SIGALL_SET, self->sigmask, __SYSCALL_SSLEN); + } new->unblock_cancel = self->cancel; new->canary = self->canary; @@ -152,11 +167,25 @@ int pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict attr, __release_ptc(); + if (do_sched) { + __syscall(SYS_rt_sigprocmask, SIG_SETMASK, + new->sigmask, 0, __SYSCALL_SSLEN); + } + if (ret < 0) { a_dec(&libc.threads_minus_1); munmap(map, size); return EAGAIN; } + + if (do_sched) { + ret = __syscall(SYS_sched_setscheduler, new->tid, + attr->_a_policy, &attr->_a_prio); + a_store(new->startlock, ret<0 ? 2 : 0); + __wake(new->startlock, 1, 1); + if (ret < 0) return -ret; + } + *res = new; return 0; } |