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