diff options
| -rw-r--r-- | src/internal/pthread_impl.h | 11 | ||||
| -rw-r--r-- | src/thread/pthread_attr_setinheritsched.c | 19 | ||||
| -rw-r--r-- | src/thread/pthread_create.c | 93 | ||||
| -rw-r--r-- | src/time/timer_create.c | 1 | 
4 files changed, 56 insertions, 68 deletions
| diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h index 58ecce90..c677f7f6 100644 --- a/src/internal/pthread_impl.h +++ b/src/internal/pthread_impl.h @@ -29,15 +29,12 @@ struct pthread {  	volatile int cancel;  	volatile unsigned char canceldisable, cancelasync;  	unsigned char tsd_used:1; -	unsigned char unblock_cancel:1;  	unsigned char dlerror_flag:1;  	unsigned char *map_base;  	size_t map_size;  	void *stack;  	size_t stack_size;  	size_t guard_size; -	void *start_arg; -	void *(*start)(void *);  	void *result;  	struct __ptcb *cancelbuf;  	void **tsd; @@ -58,14 +55,6 @@ struct pthread {  	uintptr_t *dtv_copy;  }; -struct start_sched_args { -	void *start_arg; -	void *(*start_fn)(void *); -	sigset_t mask; -	pthread_attr_t *attr; -	volatile int futex; -}; -  enum {  	DT_EXITED = 0,  	DT_EXITING, diff --git a/src/thread/pthread_attr_setinheritsched.c b/src/thread/pthread_attr_setinheritsched.c index 6a648376..ca264be7 100644 --- a/src/thread/pthread_attr_setinheritsched.c +++ b/src/thread/pthread_attr_setinheritsched.c @@ -1,25 +1,6 @@  #include "pthread_impl.h"  #include "syscall.h" -hidden void *__start_sched(void *p) -{ -	struct start_sched_args *ssa = p; -	void *start_arg = ssa->start_arg; -	void *(*start_fn)(void *) = ssa->start_fn; -	pthread_t self = __pthread_self(); - -	int ret = -__syscall(SYS_sched_setscheduler, self->tid, -		ssa->attr->_a_policy, &ssa->attr->_a_prio); -	if (!ret) __restore_sigs(&ssa->mask); -	a_store(&ssa->futex, ret); -	__wake(&ssa->futex, 1, 1); -	if (ret) { -		self->detach_state = DT_DYNAMIC; -		return 0; -	} -	return start_fn(start_arg); -} -  int pthread_attr_setinheritsched(pthread_attr_t *a, int inherit)  {  	if (inherit > 1U) return EINVAL; diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c index 3da7db14..8761381a 100644 --- a/src/thread/pthread_create.c +++ b/src/thread/pthread_create.c @@ -16,12 +16,6 @@ weak_alias(dummy_0, __pthread_tsd_run_dtors);  weak_alias(dummy_0, __do_orphaned_stdio_locks);  weak_alias(dummy_0, __dl_thread_cleanup); -static void *dummy_1(void *p) -{ -	return 0; -} -weak_alias(dummy_1, __start_sched); -  _Noreturn void __pthread_exit(void *result)  {  	pthread_t self = __pthread_self(); @@ -135,21 +129,38 @@ void __do_cleanup_pop(struct __ptcb *cb)  	__pthread_self()->cancelbuf = cb->__next;  } +struct start_args { +	void *(*start_func)(void *); +	void *start_arg; +	pthread_attr_t *attr; +	volatile int *perr; +	unsigned long sig_mask[_NSIG/8/sizeof(long)]; +}; +  static int start(void *p)  { -	pthread_t self = p; -	if (self->unblock_cancel) -		__syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, -			SIGPT_SET, 0, _NSIG/8); -	__pthread_exit(self->start(self->start_arg)); +	struct start_args *args = p; +	if (args->attr) { +		pthread_t self = __pthread_self(); +		int ret = -__syscall(SYS_sched_setscheduler, self->tid, +			args->attr->_a_policy, &args->attr->_a_prio); +		if (a_swap(args->perr, ret)==-2) +			__wake(args->perr, 1, 1); +		if (ret) { +			self->detach_state = DT_DYNAMIC; +			__pthread_exit(0); +		} +	} +	__syscall(SYS_rt_sigprocmask, SIG_SETMASK, &args->sig_mask, 0, _NSIG/8); +	__pthread_exit(args->start_func(args->start_arg));  	return 0;  }  static int start_c11(void *p)  { -	pthread_t self = p; -	int (*start)(void*) = (int(*)(void*)) self->start; -	__pthread_exit((void *)(uintptr_t)start(self->start_arg)); +	struct start_args *args = p; +	int (*start)(void*) = (int(*)(void*)) args->start_func; +	__pthread_exit((void *)(uintptr_t)start(args->start_arg));  	return 0;  } @@ -182,9 +193,9 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att  	unsigned flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND  		| CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS  		| CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_DETACHED; -	int do_sched = 0;  	pthread_attr_t attr = { 0 }; -	struct start_sched_args ssa; +	sigset_t set; +	volatile int err = -1;  	if (!libc.can_do_threads) return ENOSYS;  	self = __pthread_self(); @@ -257,8 +268,6 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att  	new->stack = stack;  	new->stack_size = stack - stack_limit;  	new->guard_size = guard; -	new->start = entry; -	new->start_arg = arg;  	new->self = new;  	new->tsd = (void *)tsd;  	new->locale = &libc.global_locale; @@ -268,38 +277,48 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att  	} else {  		new->detach_state = DT_JOINABLE;  	} -	if (attr._a_sched) { -		do_sched = 1; -		ssa.futex = -1; -		ssa.start_fn = new->start; -		ssa.start_arg = new->start_arg; -		ssa.attr = &attr; -		new->start = __start_sched; -		new->start_arg = &ssa; -		__block_app_sigs(&ssa.mask); -	}  	new->robust_list.head = &new->robust_list.head; -	new->unblock_cancel = self->cancel;  	new->CANARY = self->CANARY; +	/* Setup argument structure for the new thread on its stack. */ +	stack -= (uintptr_t)stack % sizeof(uintptr_t); +	stack -= sizeof(struct start_args); +	struct start_args *args = (void *)stack; +	args->start_func = entry; +	args->start_arg = arg; +	if (attr._a_sched) { +		args->attr = &attr; +		args->perr = &err; +	} else { +		args->attr = 0; +		args->perr = 0; +	} + +	__block_app_sigs(&set); + +	/* Ensure SIGCANCEL is unblocked in new thread. This requires +	 * working with a copy of the set so we can restore the +	 * original mask in the calling thread. */ +	memcpy(&args->sig_mask, &set, sizeof args->sig_mask); +	args->sig_mask[(SIGCANCEL-1)/8/sizeof(long)] &= +		~(1UL<<((SIGCANCEL-1)%(8*sizeof(long)))); +  	a_inc(&libc.threads_minus_1); -	ret = __clone((c11 ? start_c11 : start), stack, flags, new, &new->tid, TP_ADJ(new), &new->detach_state); +	ret = __clone((c11 ? start_c11 : start), stack, flags, args, &new->tid, TP_ADJ(new), &new->detach_state); +	__restore_sigs(&set);  	__release_ptc(); -	if (do_sched) { -		__restore_sigs(&ssa.mask); -	} -  	if (ret < 0) {  		a_dec(&libc.threads_minus_1);  		if (map) __munmap(map, size);  		return EAGAIN;  	} -	if (do_sched) { -		__futexwait(&ssa.futex, -1, 1); -		ret = ssa.futex; +	if (attr._a_sched) { +		if (a_cas(&err, -1, -2)==-1) +			__wait(&err, 0, -2, 1); +		ret = err;  		if (ret) return ret;  	} diff --git a/src/time/timer_create.c b/src/time/timer_create.c index 94219574..c5e40a19 100644 --- a/src/time/timer_create.c +++ b/src/time/timer_create.c @@ -27,7 +27,6 @@ static void cleanup_fromsig(void *p)  	self->cancelbuf = 0;  	self->canceldisable = 0;  	self->cancelasync = 0; -	self->unblock_cancel = 0;  	__reset_tls();  	longjmp(p, 1);  } | 
