summaryrefslogtreecommitdiff
path: root/lib/libpthread/thread/thr_cancel.c
diff options
context:
space:
mode:
authorDaniel Eischen <deischen@FreeBSD.org>2003-05-24 02:29:25 +0000
committerDaniel Eischen <deischen@FreeBSD.org>2003-05-24 02:29:25 +0000
commit1cb570c53190e8b569091f708781c6bf9c3126c7 (patch)
treee99d3167d044ff37cf6b26fa4f4fe83140c8af79 /lib/libpthread/thread/thr_cancel.c
parenta224a3919d4b2260bb1d91fb7f848de673444c26 (diff)
Notes
Diffstat (limited to 'lib/libpthread/thread/thr_cancel.c')
-rw-r--r--lib/libpthread/thread/thr_cancel.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/lib/libpthread/thread/thr_cancel.c b/lib/libpthread/thread/thr_cancel.c
index 2c3ae5939429..064e422cadf8 100644
--- a/lib/libpthread/thread/thr_cancel.c
+++ b/lib/libpthread/thread/thr_cancel.c
@@ -19,6 +19,7 @@ int
_pthread_cancel(pthread_t pthread)
{
struct pthread *curthread = _get_curthread();
+ struct pthread *joinee = NULL;
int ret;
if ((ret = _thr_ref_add(curthread, pthread, /*include dead*/0)) == 0) {
@@ -64,7 +65,17 @@ _pthread_cancel(pthread_t pthread)
break;
case PS_JOIN:
+ /* Disconnect the thread from the joinee: */
+ joinee = pthread->join_status.thread;
+ pthread->join_status.thread = NULL;
pthread->cancelflags |= THR_CANCELLING;
+ _thr_setrunnable_unlocked(pthread);
+ if ((joinee != NULL) &&
+ (curthread->kseg == joinee->kseg)) {
+ /* Remove the joiner from the joinee. */
+ joinee->joiner = NULL;
+ joinee = NULL;
+ }
break;
case PS_SUSPENDED:
@@ -103,6 +114,15 @@ _pthread_cancel(pthread_t pthread)
*/
THR_SCHED_UNLOCK(curthread, pthread);
_thr_ref_delete(curthread, pthread);
+
+ if ((joinee != NULL) &&
+ (_thr_ref_add(curthread, joinee, /* include dead */1) == 0)) {
+ /* Remove the joiner from the joinee. */
+ THR_SCHED_LOCK(curthread, joinee);
+ joinee->joiner = NULL;
+ THR_SCHED_UNLOCK(curthread, joinee);
+ _thr_ref_delete(curthread, joinee);
+ }
}
return (ret);
}