PERFORCE change 69093 for review

David Xu davidxu at FreeBSD.org
Sat Jan 15 16:34:25 PST 2005


http://perforce.freebsd.org/chv.cgi?CH=69093

Change 69093 by davidxu at davidxu_tiger on 2005/01/16 00:33:32

	simplify exit + detach + join code.

Affected files ...

.. //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_detach.c#4 edit
.. //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_exit.c#6 edit
.. //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_join.c#4 edit

Differences ...

==== //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_detach.c#4 (text+ko) ====

@@ -43,7 +43,6 @@
 _pthread_detach(pthread_t pthread)
 {
 	struct pthread *curthread = _get_curthread();
-	struct pthread *joiner;
 	int rval;
 
 	if (pthread == NULL)
@@ -56,33 +55,17 @@
 		return (rval);
 	}
 
-	/* Check if the thread is already detached. */
-	if ((pthread->tlflags & TLFLAGS_DETACHED) != 0) {
+	/* Check if the thread is already detached or has a joiner. */
+	if ((pthread->tlflags & TLFLAGS_DETACHED) != 0 ||
+	    (pthread->joiner != NULL)) {
 		THREAD_LIST_UNLOCK(curthread);
 		return (EINVAL);
 	}
 
 	/* Flag the thread as detached. */
 	pthread->tlflags |= TLFLAGS_DETACHED;
-
-	/* Retrieve any joining thread and remove it. */
-	joiner = pthread->joiner;
-
-	/* See if there is a thread waiting in pthread_join(). */
-	if (joiner != NULL) {
-		THR_THREAD_LOCK(curthread, joiner);
-		if (joiner->join_status.thread == pthread) {
-			/*
-			 * Set the return value for the woken thread:
-			 */
-			joiner->join_status.error = ESRCH;
-			joiner->join_status.ret = NULL;
-			joiner->join_status.thread = NULL;
-			joiner->cycle++;
-			umtx_wake((struct umtx *)&joiner->cycle, 1);
-		}
-		THR_THREAD_UNLOCK(curthread, joiner);
-	}
+	if (pthread->state == PS_DEAD)
+		THR_GCLIST_ADD(pthread);
 	THREAD_LIST_UNLOCK(curthread);
 
 	return (0);

==== //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_exit.c#6 (text+ko) ====

@@ -45,7 +45,7 @@
 __weak_reference(_pthread_exit, pthread_exit);
 
 void
-_thr_exit(char *fname, int lineno, char *msg)
+_thread_exit(char *fname, int lineno, char *msg)
 {
 
 	/* Write an error message to the standard error file descriptor: */
@@ -86,7 +86,6 @@
 _pthread_exit(void *status)
 {
 	struct pthread *curthread = _get_curthread();
-	struct pthread *joiner;
 
 	/* Check if this thread is already in the process of exiting: */
 	if ((curthread->cancelflags & THR_CANCEL_EXITING) != 0) {
@@ -97,10 +96,7 @@
 		PANIC(msg);
 	}
 
-	/*
-	 * Flag this thread as exiting.  Threads should now be prevented
-	 * from joining to this thread.
-	 */
+	/* Flag this thread as exiting. */
 	atomic_set_int(&curthread->cancelflags, THR_CANCEL_EXITING);
 	
 	_thr_exit_cleanup();
@@ -123,29 +119,20 @@
 		exit(0);
 
 	THREAD_LIST_LOCK(curthread);
-	if ((joiner = curthread->joiner) != NULL) {
-		THR_THREAD_LOCK(curthread, joiner);
-		if (joiner->join_status.thread == curthread) {
-			joiner->join_status.thread = NULL;
-			joiner->join_status.ret = curthread->ret;
-			joiner->cycle++;
-			umtx_wake((struct umtx *)&joiner->cycle, 1);
-		}
-		THR_THREAD_UNLOCK(curthread, joiner);
-	}
 	_thread_active_threads--;
 	if (_thread_active_threads == 0) {
 		THREAD_LIST_UNLOCK(curthread);
 		exit(0);
 		/* Never reach! */
 	}
-	curthread->tlflags |= TLFLAGS_GC_SAFE;
-	THR_GCLIST_ADD(curthread);
-	THR_LOCK(curthread);
+	if (curthread->tlflags & TLFLAGS_DETACHED)
+		THR_GCLIST_ADD(curthread);
 	curthread->state = PS_DEAD;
-	THR_UNLOCK(curthread);
 	THREAD_LIST_UNLOCK(curthread);
-	thr_exit(&curthread->isdead);
+	if (curthread->joiner) {
+		umtx_wake((struct umtx *)&curthread->state, INT_MAX);
+	}
+	thr_exit(&curthread->terminated);
 	PANIC("thr_exit() returned");
 	/* Never reach! */
 }

==== //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_join.c#4 (text+ko) ====

@@ -43,10 +43,7 @@
 	struct pthread *pthread = (struct pthread *)arg;
 
 	THREAD_LIST_LOCK(curthread);
-	if (_thr_find_thread(curthread, pthread, /*include dead*/1) == 0) {
-		if (pthread->joiner == curthread)
-			pthread->joiner = NULL;
-	}
+	pthread->joiner = NULL;
 	THREAD_LIST_UNLOCK(curthread);
 }
 
@@ -55,114 +52,52 @@
 {
 	struct pthread *curthread = _get_curthread();
 	void *tmp;
+	long state;
 	int oldcancel;
 	int ret = 0;
  
-	if (pthread == NULL) {
+	if (pthread == NULL)
 		return (EINVAL);
-	}
 
-	if (pthread == curthread) {
+	if (pthread == curthread)
 		return (EDEADLK);
-	}
 
 	THREAD_LIST_LOCK(curthread);
-	if ((ret = _thr_find_thread(curthread, pthread, /*include dead*/1)) != 0) {
-		THREAD_LIST_UNLOCK(curthread);
-		return (ESRCH);
+	if ((ret = _thr_find_thread(curthread, pthread, 1)) != 0) {
+		ret = ESRCH;
+	} else if ((pthread->tlflags & TLFLAGS_DETACHED) != 0) {
+		ret = ESRCH;
+	} else if (pthread->joiner != NULL) {
+		/* Multiple joiners are not supported. */
+		ret = ENOTSUP;
 	}
-
-	/* Check if this thread has been detached. */
-	if ((pthread->tlflags & TLFLAGS_DETACHED) != 0) {
+	if (ret) {
 		THREAD_LIST_UNLOCK(curthread);
-		return (ESRCH);
+		return (ret);
 	}
-	
-	THR_THREAD_LOCK(curthread, pthread);
-	/* Lock the target thread while checking its state. */
-	if (pthread->state == PS_DEAD) {
-		/* Return the thread's return value. */
-		tmp = pthread->ret;
-
-		THR_THREAD_UNLOCK(curthread, pthread);
-
-		/* Detach the thread. */
-		pthread->tlflags |= TLFLAGS_DETACHED;
-
-		/*
-		 * Remove the thread from the list of active
-		 * threads and add it to the GC list.
-		 */
-		THR_LIST_REMOVE(pthread);
-		THR_GCLIST_ADD(pthread);
-
-		/* Unlock the thread list. */
-		THREAD_LIST_UNLOCK(curthread);
-
-		if (thread_return != NULL)
-			*thread_return = tmp;
-		return (0);
-	}
-	THR_THREAD_UNLOCK(curthread, pthread);
-
-	if (pthread->joiner != NULL) {
-		THREAD_LIST_UNLOCK(curthread);
-
-		/* Multiple joiners are not supported. */
-		return (ENOTSUP);
-	}
-
 	/* Set the running thread to be the joiner: */
 	pthread->joiner = curthread;
 
-	/* Keep track of which thread we're joining to: */
-	curthread->join_status.error = 0;
-	curthread->join_status.thread = pthread;
-
 	THREAD_LIST_UNLOCK(curthread);
 
 	THR_CLEANUP_PUSH(curthread, backout_join, pthread);
+	oldcancel = _thr_cancel_enter(curthread);
 
-	long cycle;
-	THR_LOCK(curthread);
-	while (curthread->join_status.thread == pthread) {
-		cycle = curthread->cycle;
-		THR_UNLOCK(curthread);
-		oldcancel = _thr_cancel_enter(curthread);
-		umtx_wait((struct umtx *)&curthread->cycle, cycle);
-		_thr_cancel_leave(curthread, oldcancel);
-		THR_LOCK(curthread);
+	while ((state = pthread->state) != PS_DEAD) {
+		umtx_wait((struct umtx *)&pthread->state, state);
 	}
-	THR_UNLOCK(curthread);
+
+	_thr_cancel_leave(curthread, oldcancel);
 	THR_CLEANUP_POP(curthread, 0);
 
-	if (curthread->join_status.error == 0) {
-		THREAD_LIST_LOCK(curthread);
-		if (_thr_find_thread(curthread, pthread, /*include dead*/1) == 0) {
-			if (pthread->joiner == curthread) {
-				pthread->tlflags |= TLFLAGS_DETACHED;
-				/*
-				 * Remove the thread from the list of active
-				 * threads and add it to the GC list.
-				 */
-				THR_LIST_REMOVE(pthread);
-				THR_GCLIST_ADD(pthread);
-			}
-			THREAD_LIST_UNLOCK(curthread);
-		} else {
-			THREAD_LIST_UNLOCK(curthread);
-			/* Return an error: */
-			return (ESRCH);
-		}
-	}
-	/*
-	 * The thread return value and error are set by the
-	 * thread we're joining to when it exits or detaches:
-	 */
-	ret = curthread->join_status.error;
-	if ((ret == 0) && (thread_return != NULL))
-		*thread_return = curthread->join_status.ret;
+	tmp = pthread->ret;
+	THREAD_LIST_LOCK(curthread);
+	pthread->tlflags |= TLFLAGS_DETACHED;
+	THR_GCLIST_ADD(pthread);
+	THREAD_LIST_UNLOCK(curthread);
+
+	if (thread_return != NULL)
+		*thread_return = tmp;
 
-	/* Return the completion status: */
 	return (ret);
 }


More information about the p4-projects mailing list