From owner-p4-projects@FreeBSD.ORG Fri Dec 31 14:52:59 2004 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 05FE516A515; Fri, 31 Dec 2004 14:52:59 +0000 (GMT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id B576316A4E3 for ; Fri, 31 Dec 2004 14:52:58 +0000 (GMT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 8734443D1D for ; Fri, 31 Dec 2004 14:52:58 +0000 (GMT) (envelope-from davidxu@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.1/8.13.1) with ESMTP id iBVEqwKQ009029 for ; Fri, 31 Dec 2004 14:52:58 GMT (envelope-from davidxu@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.1/8.13.1/Submit) id iBVEqw1E009026 for perforce@freebsd.org; Fri, 31 Dec 2004 14:52:58 GMT (envelope-from davidxu@freebsd.org) Date: Fri, 31 Dec 2004 14:52:58 GMT Message-Id: <200412311452.iBVEqw1E009026@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to davidxu@freebsd.org using -f From: David Xu To: Perforce Change Reviews Subject: PERFORCE change 67974 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 31 Dec 2004 14:52:59 -0000 http://perforce.freebsd.org/chv.cgi?CH=67974 Change 67974 by davidxu@davidxu_tiger on 2004/12/31 14:52:50 simplify cancellation code. Affected files ... .. //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_cancel.c#4 edit Differences ... ==== //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_cancel.c#4 (text+ko) ==== @@ -14,27 +14,16 @@ static inline int checkcancel(struct pthread *curthread) { - if ((curthread->cancelflags & THR_CANCELLING) != 0) { - /* - * It is possible for this thread to be swapped out - * while performing cancellation; do not allow it - * to be cancelled again. - */ - if ((curthread->flags & THR_FLAGS_EXITING) != 0) { - /* - * this may happen once, but after this, it - * shouldn't happen again. - */ - curthread->cancelflags &= ~THR_CANCELLING; - return (0); - } - if ((curthread->cancelflags & PTHREAD_CANCEL_DISABLE) == 0) { - curthread->cancelflags &= ~THR_CANCELLING; - return (1); - } + /* + * Don't do cancellation again if it was already in progress. + */ + if ((curthread->cancelflags & + (THR_CANCEL_EXITING | THR_CANCELLING | THR_CANCEL_DISABLE | + THR_CANCEL_NEEDED)) == THR_CANCEL_NEEDED) { + curthread->cancelflags |= THR_CANCELLING; + return (1); } - else - return (0); + return (0); } static inline void @@ -43,8 +32,6 @@ if (checkcancel(curthread) != 0) { /* Unlock before exiting: */ THR_UNLOCK(curthread); - - _thr_exit_cleanup(); pthread_exit(PTHREAD_CANCELED); PANIC("cancel"); } @@ -54,93 +41,35 @@ _pthread_cancel(pthread_t pthread) { struct pthread *curthread = _get_curthread(); - struct pthread *joinee = NULL; long tid = -1; int ret; - if ((ret = _thr_ref_add(curthread, pthread, /*include dead*/0)) == 0) { + THREAD_LIST_LOCK(curthread); + if ((ret = _thr_find_thread(curthread, pthread, 0)) == 0) { /* * Take the thread's lock while we change the cancel flags. */ THR_THREAD_LOCK(curthread, pthread); - if (pthread->flags & THR_FLAGS_EXITING) { + THREAD_LIST_UNLOCK(curthread); + if (pthread->cancelflags & + (THR_CANCELLING | THR_CANCEL_EXITING)) { THR_THREAD_UNLOCK(curthread, pthread); - _thr_ref_delete(curthread, pthread); - return (ESRCH); + return (0); } - if (((pthread->cancelflags & PTHREAD_CANCEL_DISABLE) != 0) || - (((pthread->cancelflags & THR_AT_CANCEL_POINT) == 0) && - ((pthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) == 0))) - /* Just mark it for cancellation: */ - pthread->cancelflags |= THR_CANCELLING; - else { - /* - * Check if we need to kick it back into the - * run queue: - */ - switch (pthread->state) { - case PS_RUNNING: - /* No need to resume: */ - pthread->cancelflags |= THR_CANCELLING; - tid = pthread->tid; - break; - - case PS_JOIN: - /* Disconnect the thread from the joinee: */ - joinee = pthread->join_status.thread; - pthread->join_status.thread = NULL; - pthread->cancelflags |= THR_CANCELLING; - tid = _thr_setrunnable_unlocked(pthread); - break; - - case PS_SUSPENDED: - case PS_MUTEX_WAIT: - /* - * Threads in these states may be in queues. - * In order to preserve queue integrity, the - * cancelled thread must remove itself from the - * queue. Mark the thread as interrupted and - * needing cancellation, and set the state to - * running. When the thread resumes, it will - * remove itself from the queue and call the - * cancellation completion routine. - */ - pthread->interrupted = 1; - pthread->cancelflags |= THR_CANCEL_NEEDED; - tid = _thr_setrunnable_unlocked(pthread); - pthread->continuation = - _thr_finish_cancellation; - break; - - case PS_DEAD: - case PS_DEADLOCK: - case PS_STATE_MAX: - /* Ignore - only here to silence -Wall: */ - break; - } - -#if 0 - thr_interrupt(pthread->tid, 1); -#endif + pthread->cancelflags |= THR_CANCEL_NEEDED; + if ((pthread->cancelflags & PTHREAD_CANCEL_DISABLE) == 0 && + ((pthread->cancelflags & THR_CANCEL_AT_POINT) != 0 || + (pthread->cancelflags & THR_CANCEL_ASYNCHRONOUS) != 0)) { + tid = pthread->tid; + thr_kill(tid, SIGCANCEL); } - /* * Release the thread's lock and remove the * reference: */ THR_THREAD_UNLOCK(curthread, pthread); - _thr_ref_delete(curthread, pthread); - if (tid != -1) - thr_wake(tid); - - if ((joinee != NULL) && - (_thr_ref_add(curthread, joinee, /* include dead */1) == 0)) { - /* Remove the joiner from the joinee. */ - THR_THREAD_LOCK(curthread, joinee); - joinee->joiner = NULL; - THR_THREAD_UNLOCK(curthread, joinee); - _thr_ref_delete(curthread, joinee); - } + } else { + THREAD_LIST_UNLOCK(curthread); } return (ret); } @@ -149,24 +78,27 @@ _pthread_setcancelstate(int state, int *oldstate) { struct pthread *curthread = _get_curthread(); + int need_exit = 0; int ostate; int ret; - int need_exit = 0; /* Take the thread's lock while fiddling with the state: */ THR_LOCK(curthread); - ostate = curthread->cancelflags & PTHREAD_CANCEL_DISABLE; + if (curthread->cancelflags & THR_CANCEL_DISABLE) + ostate = PTHREAD_CANCEL_DISABLE; + else + ostate = PTHREAD_CANCEL_ENABLE; switch (state) { case PTHREAD_CANCEL_ENABLE: - curthread->cancelflags &= ~PTHREAD_CANCEL_DISABLE; - if ((curthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) != 0) + curthread->cancelflags &= ~THR_CANCEL_DISABLE; + if ((curthread->cancelflags & THR_CANCEL_ASYNCHRONOUS) != 0) need_exit = checkcancel(curthread); ret = 0; break; case PTHREAD_CANCEL_DISABLE: - curthread->cancelflags |= PTHREAD_CANCEL_DISABLE; + curthread->cancelflags |= THR_CANCEL_DISABLE; ret = 0; break; default: @@ -175,7 +107,6 @@ THR_UNLOCK(curthread); if (need_exit != 0) { - _thr_exit_cleanup(); pthread_exit(PTHREAD_CANCELED); PANIC("cancel"); } @@ -189,22 +120,25 @@ _pthread_setcanceltype(int type, int *oldtype) { struct pthread *curthread = _get_curthread(); + int need_exit = 0; int otype; int ret; - int need_exit = 0; /* Take the thread's lock while fiddling with the state: */ THR_LOCK(curthread); - otype = curthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS; + if (curthread->cancelflags & THR_CANCEL_ASYNCHRONOUS) + otype = PTHREAD_CANCEL_ASYNCHRONOUS; + else + otype = PTHREAD_CANCEL_DEFERRED; switch (type) { case PTHREAD_CANCEL_ASYNCHRONOUS: - curthread->cancelflags |= PTHREAD_CANCEL_ASYNCHRONOUS; + curthread->cancelflags |= THR_CANCEL_ASYNCHRONOUS; need_exit = checkcancel(curthread); ret = 0; break; case PTHREAD_CANCEL_DEFERRED: - curthread->cancelflags &= ~PTHREAD_CANCEL_ASYNCHRONOUS; + curthread->cancelflags &= ~THR_CANCEL_ASYNCHRONOUS; ret = 0; break; default: @@ -213,7 +147,6 @@ THR_UNLOCK(curthread); if (need_exit != 0) { - _thr_exit_cleanup(); pthread_exit(PTHREAD_CANCELED); PANIC("cancel"); } @@ -233,41 +166,28 @@ THR_UNLOCK(curthread); } -void +int _thr_cancel_enter(struct pthread *curthread) { + int old; + /* Look for a cancellation before we block: */ THR_LOCK(curthread); - testcancel(curthread); - curthread->cancelflags |= THR_AT_CANCEL_POINT; - THR_UNLOCK(curthread); -} - -void -_thr_cancel_leave(struct pthread *curthread, int check) -{ - THR_LOCK(curthread); - curthread->cancelflags &= ~THR_AT_CANCEL_POINT; - /* Look for a cancellation after we unblock: */ - if (check) + old = curthread->cancelflags; + if (!(curthread->cancelflags & THR_CANCEL_AT_POINT)) { testcancel(curthread); + curthread->cancelflags |= THR_CANCEL_AT_POINT; + } THR_UNLOCK(curthread); + return (old); } void -_thr_finish_cancellation(void *arg) +_thr_cancel_leave(struct pthread *curthread, int previous) { - struct pthread *curthread = _get_curthread(); - - curthread->continuation = NULL; - curthread->interrupted = 0; - + if (!(previous & THR_CANCEL_AT_POINT)) + return; THR_LOCK(curthread); - if ((curthread->cancelflags & THR_CANCEL_NEEDED) != 0) { - curthread->cancelflags &= ~THR_CANCEL_NEEDED; - THR_UNLOCK(curthread); - _thr_exit_cleanup(); - pthread_exit(PTHREAD_CANCELED); - } + curthread->cancelflags &= ~THR_CANCEL_AT_POINT; THR_UNLOCK(curthread); }