Date: Fri, 31 Dec 2004 14:52:58 GMT From: David Xu <davidxu@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 67974 for review Message-ID: <200412311452.iBVEqw1E009026@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
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); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200412311452.iBVEqw1E009026>