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