PERFORCE change 67974 for review
David Xu
davidxu at FreeBSD.org
Fri Dec 31 06:52:59 PST 2004
http://perforce.freebsd.org/chv.cgi?CH=67974
Change 67974 by davidxu at 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);
}
More information about the p4-projects
mailing list