diff options
| author | Alfred Perlstein <alfred@FreeBSD.org> | 1999-11-28 05:38:13 +0000 | 
|---|---|---|
| committer | Alfred Perlstein <alfred@FreeBSD.org> | 1999-11-28 05:38:13 +0000 | 
| commit | 7285bccf1a9224fadd3b7b81be034cd04f35a820 (patch) | |
| tree | 124a02d2660bf074fa7b02495dcb9d400ac52505 /lib/libpthread/thread/thr_join.c | |
| parent | d29b1c8b20283bd2639ac939af816f5a6824dbb1 (diff) | |
Notes
Diffstat (limited to 'lib/libpthread/thread/thr_join.c')
| -rw-r--r-- | lib/libpthread/thread/thr_join.c | 31 | 
1 files changed, 29 insertions, 2 deletions
diff --git a/lib/libpthread/thread/thr_join.c b/lib/libpthread/thread/thr_join.c index 8b000825b207..d149cf16e303 100644 --- a/lib/libpthread/thread/thr_join.c +++ b/lib/libpthread/thread/thr_join.c @@ -41,16 +41,22 @@ pthread_join(pthread_t pthread, void **thread_return)  {  	int ret = 0;  	pthread_t pthread1 = NULL; +  +	_thread_enter_cancellation_point();  	/* Check if the caller has specified an invalid thread: */ -	if (pthread == NULL || pthread->magic != PTHREAD_MAGIC) +	if (pthread == NULL || pthread->magic != PTHREAD_MAGIC) {  		/* Invalid thread: */ +		_thread_leave_cancellation_point();  		return(EINVAL); +	}  	/* Check if the caller has specified itself: */ -	if (pthread == _thread_run) +	if (pthread == _thread_run) {  		/* Avoid a deadlock condition: */ +		_thread_leave_cancellation_point();  		return(EDEADLK); +	}  	/*  	 * Find the thread in the list of active threads or in the @@ -71,12 +77,31 @@ pthread_join(pthread_t pthread, void **thread_return)  	/* Check if the thread is not dead: */  	else if (pthread->state != PS_DEAD) { +		/* Clear the interrupted flag: */ +		_thread_run->interrupted = 0; + +		/* +		 * Protect against being context switched out while +		 * adding this thread to the join queue. +		 */ +		_thread_kern_sig_defer(); +  		/* Add the running thread to the join queue: */  		TAILQ_INSERT_TAIL(&(pthread->join_queue), _thread_run, qe);  		/* Schedule the next thread: */  		_thread_kern_sched_state(PS_JOIN, __FILE__, __LINE__); +		if (_thread_run->interrupted != 0) +			TAILQ_REMOVE(&(pthread->join_queue), _thread_run, qe); + +		_thread_kern_sig_undefer(); + +		if ((_thread_run->cancelflags & PTHREAD_CANCEL_NEEDED) != 0) { +			_thread_exit_cleanup(); +			pthread_exit(PTHREAD_CANCELED); +		} +  		/* Check if the thread is not detached: */  		if ((pthread->attr.flags & PTHREAD_DETACHED) == 0) {  			/* Check if the return value is required: */ @@ -93,6 +118,8 @@ pthread_join(pthread_t pthread, void **thread_return)  		/* Return the thread's return value: */  		*thread_return = pthread->ret; +	_thread_leave_cancellation_point(); +  	/* Return the completion status: */  	return (ret);  }  | 
