diff options
Diffstat (limited to 'src/thread')
| -rw-r--r-- | src/thread/pthread_create.c | 24 | ||||
| -rw-r--r-- | src/thread/pthread_getschedparam.c | 2 | ||||
| -rw-r--r-- | src/thread/pthread_kill.c | 4 | ||||
| -rw-r--r-- | src/thread/pthread_setschedparam.c | 2 | ||||
| -rw-r--r-- | src/thread/pthread_setschedprio.c | 2 | 
5 files changed, 18 insertions, 16 deletions
| diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c index ac06d7a7..a86b5e1b 100644 --- a/src/thread/pthread_create.c +++ b/src/thread/pthread_create.c @@ -39,9 +39,11 @@ _Noreturn void __pthread_exit(void *result)  	LOCK(self->exitlock); -	/* Mark this thread dead before decrementing count */ +	/* Access to target the exiting thread with syscalls that use +	 * its kernel tid is controlled by killlock. For detached threads, +	 * any use past this point would have undefined behavior, but for +	 * joinable threads it's a valid usage that must be handled. */  	LOCK(self->killlock); -	self->dead = 1;  	/* Block all signals before decrementing the live thread count.  	 * This is important to ensure that dynamically allocated TLS @@ -49,20 +51,14 @@ _Noreturn void __pthread_exit(void *result)  	 * reasons as well. */  	__block_all_sigs(&set); -	/* Wait to unlock the kill lock, which governs functions like -	 * pthread_kill which target a thread id, until signals have -	 * been blocked. This precludes observation of the thread id -	 * as a live thread (with application code running in it) after -	 * the thread was reported dead by ESRCH being returned. */ -	UNLOCK(self->killlock); -  	/* It's impossible to determine whether this is "the last thread"  	 * until performing the atomic decrement, since multiple threads  	 * could exit at the same time. For the last thread, revert the -	 * decrement and unblock signals to give the atexit handlers and -	 * stdio cleanup code a consistent state. */ +	 * decrement, restore the tid, and unblock signals to give the +	 * atexit handlers and stdio cleanup code a consistent state. */  	if (a_fetch_add(&libc.threads_minus_1, -1)==0) {  		libc.threads_minus_1 = 0; +		UNLOCK(self->killlock);  		__restore_sigs(&set);  		exit(0);  	} @@ -113,6 +109,12 @@ _Noreturn void __pthread_exit(void *result)  		__unmapself(self->map_base, self->map_size);  	} +	/* After the kernel thread exits, its tid may be reused. Clear it +	 * to prevent inadvertent use and inform functions that would use +	 * it that it's no longer available. */ +	self->tid = 0; +	UNLOCK(self->killlock); +  	for (;;) __syscall(SYS_exit, 0);  } diff --git a/src/thread/pthread_getschedparam.c b/src/thread/pthread_getschedparam.c index a994b637..05be4242 100644 --- a/src/thread/pthread_getschedparam.c +++ b/src/thread/pthread_getschedparam.c @@ -4,7 +4,7 @@ int pthread_getschedparam(pthread_t t, int *restrict policy, struct sched_param  {  	int r;  	LOCK(t->killlock); -	if (t->dead) { +	if (!t->tid) {  		r = ESRCH;  	} else {  		r = -__syscall(SYS_sched_getparam, t->tid, param); diff --git a/src/thread/pthread_kill.c b/src/thread/pthread_kill.c index 0a139231..6d70e626 100644 --- a/src/thread/pthread_kill.c +++ b/src/thread/pthread_kill.c @@ -4,8 +4,8 @@ int pthread_kill(pthread_t t, int sig)  {  	int r;  	LOCK(t->killlock); -	r = t->dead ? (sig+0U >= _NSIG ? EINVAL : 0) -		: -__syscall(SYS_tkill, t->tid, sig); +	r = t->tid ? -__syscall(SYS_tkill, t->tid, sig) +		: (sig+0U >= _NSIG ? EINVAL : 0);  	UNLOCK(t->killlock);  	return r;  } diff --git a/src/thread/pthread_setschedparam.c b/src/thread/pthread_setschedparam.c index 9e2fa456..ab45f2ff 100644 --- a/src/thread/pthread_setschedparam.c +++ b/src/thread/pthread_setschedparam.c @@ -4,7 +4,7 @@ int pthread_setschedparam(pthread_t t, int policy, const struct sched_param *par  {  	int r;  	LOCK(t->killlock); -	r = t->dead ? ESRCH : -__syscall(SYS_sched_setscheduler, t->tid, policy, param); +	r = !t->tid ? ESRCH : -__syscall(SYS_sched_setscheduler, t->tid, policy, param);  	UNLOCK(t->killlock);  	return r;  } diff --git a/src/thread/pthread_setschedprio.c b/src/thread/pthread_setschedprio.c index dc745b42..c353f6b5 100644 --- a/src/thread/pthread_setschedprio.c +++ b/src/thread/pthread_setschedprio.c @@ -4,7 +4,7 @@ int pthread_setschedprio(pthread_t t, int prio)  {  	int r;  	LOCK(t->killlock); -	r = t->dead ? ESRCH : -__syscall(SYS_sched_setparam, t->tid, &prio); +	r = !t->tid ? ESRCH : -__syscall(SYS_sched_setparam, t->tid, &prio);  	UNLOCK(t->killlock);  	return r;  } | 
