Date: Sun, 16 Jan 2005 00:34:23 GMT From: David Xu <davidxu@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 69093 for review Message-ID: <200501160034.j0G0YNoL007197@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=69093 Change 69093 by davidxu@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); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200501160034.j0G0YNoL007197>