Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 31 Dec 2004 15:05:19 GMT
From:      David Xu <davidxu@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 67985 for review
Message-ID:  <200412311505.iBVF5JAp009532@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=67985

Change 67985 by davidxu@davidxu_tiger on 2004/12/31 15:04:21

	rework thread wakeup code, for priority mutex only.

Affected files ...

.. //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_mutex.c#7 edit

Differences ...

==== //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_mutex.c#7 (text+ko) ====

@@ -216,8 +216,8 @@
         }
 }
 
-void
-_thr_mutex_reinit(pthread_mutex_t *mutex)
+int
+_mutex_reinit(pthread_mutex_t *mutex)
 {
 	umtx_init(&(*mutex)->m_lock);
 	TAILQ_INIT(&(*mutex)->m_queue);
@@ -227,6 +227,7 @@
 	(*mutex)->m_refcount = 0;
 	(*mutex)->m_prio = 0;
 	(*mutex)->m_saved_prio = 0;
+	return (0);
 }
 
 int
@@ -490,6 +491,7 @@
 mutex_lock_common(struct pthread *curthread, pthread_mutex_t *m,
 	const struct timespec * abstime)
 {
+	long	cycle;
 	int	ret = 0;
 
 	THR_ASSERT((m != NULL) && (*m != NULL),
@@ -515,10 +517,16 @@
 #endif
 		} else if (umtx_owner(&(*m)->m_lock) == curthread->tid &&
 			   (*m)->m_type != PTHREAD_MUTEX_NORMAL) {
+			/*
+			 * We don't do deadlock sleep in mutex_self_lock
+			 * if type is normal, instead let umtx_lock sleep
+			 * in kernel.
+			 */
 			ret = mutex_self_lock(curthread, *m);
 		} else {
 			if (abstime == NULL) {
-				ret = UMTX_LOCK(&(*m)->m_lock, curthread->tid);
+				UMTX_LOCK(&(*m)->m_lock, curthread->tid);
+				ret = 0;
 			} else {
 				ret = umtx_timedlock(&(*m)->m_lock,
 					 curthread->tid, abstime);
@@ -548,11 +556,6 @@
 	    abstime->tv_nsec >= 1000000000))
 		return (EINVAL);
 
-	/* Reset the interrupted flag: */
-	curthread->interrupted = 0;
-	curthread->timeout = 0;
-	curthread->wakeup_time.tv_sec = -1;
-
 	/*
 	 * Enter a loop waiting to become the mutex owner.  We need a
 	 * loop in case the waiting thread is interrupted by a signal
@@ -613,14 +616,6 @@
 				/* Unlock the mutex structure: */
 				THR_LOCK_RELEASE(curthread, &(*m)->m_lock);
 			} else {
-				/* Set the wakeup time: */
-				if (abstime) {
-					curthread->wakeup_time.tv_sec =
-						abstime->tv_sec;
-					curthread->wakeup_time.tv_nsec =
-						abstime->tv_nsec;
-				}
-
 				/*
 				 * Join the queue of threads waiting to lock
 				 * the mutex and save a pointer to the mutex.
@@ -629,23 +624,27 @@
 				curthread->data.mutex = *m;
 				curthread->sigbackout = mutex_lock_backout;
 
-				/*
-				 * This thread is active and is in a critical
-				 * region (holding the mutex lock); we should
-				 * be able to safely set the state.
-				 */
 				if (curthread->active_priority > (*m)->m_prio)
 					/* Adjust priorities: */
 					mutex_priority_adjust(curthread, *m);
 
-				THR_LOCK_SWITCH(curthread);
-				THR_SET_STATE(curthread, PS_MUTEX_WAIT);
+				THR_LOCK(curthread);
+				cycle = curthread->cycle;
+				THR_UNLOCK(curthread);
 
 				/* Unlock the mutex structure: */
 				THR_LOCK_RELEASE(curthread, &(*m)->m_lock);
 
-				/* Schedule the next thread: */
-				_thr_sched_switch_unlocked(curthread);
+				if (abstime) {
+					ret = umtx_timedwait((struct umtx *)&curthread->cycle,
+						cycle, abstime);
+					if (ret == EAGAIN)
+						ret = ETIMEDOUT;
+					else
+						ret = 0;
+				} else {
+					umtx_wait((struct umtx *)&curthread->cycle, cycle);
+				}
 
 				if (THR_IN_MUTEXQ(curthread)) {
 					THR_LOCK_ACQUIRE(curthread, &(*m)->m_lock);
@@ -707,14 +706,6 @@
 				/* Unlock the mutex structure: */
 				THR_LOCK_RELEASE(curthread, &(*m)->m_lock);
 			} else {
-				/* Set the wakeup time: */
-				if (abstime) {
-					curthread->wakeup_time.tv_sec =
-						abstime->tv_sec;
-					curthread->wakeup_time.tv_nsec =
-						abstime->tv_nsec;
-				}
-
 				/*
 				 * Join the queue of threads waiting to lock
 				 * the mutex and save a pointer to the mutex.
@@ -726,20 +717,23 @@
 				/* Clear any previous error: */
 				curthread->error = 0;
 
-				/*
-				 * This thread is active and is in a critical
-				 * region (holding the mutex lock); we should
-				 * be able to safely set the state.
-				 */
+				THR_LOCK(curthread);
+				cycle = curthread->cycle;
+				THR_UNLOCK(curthread);
 
-				THR_LOCK_SWITCH(curthread);
-				THR_SET_STATE(curthread, PS_MUTEX_WAIT);
-
 				/* Unlock the mutex structure: */
 				THR_LOCK_RELEASE(curthread, &(*m)->m_lock);
 
-				/* Schedule the next thread: */
-				_thr_sched_switch_unlocked(curthread);
+				if (abstime) {
+					ret = umtx_timedwait((struct umtx *)&curthread->cycle,
+						cycle, abstime);
+					if (ret == EAGAIN)
+						ret = ETIMEDOUT;
+					else
+						ret = 0;
+				} else {
+					umtx_wait((struct umtx *)&curthread->cycle, cycle);
+				}
 
 				curthread->data.mutex = NULL;
 				if (THR_IN_MUTEXQ(curthread)) {
@@ -774,28 +768,8 @@
 			break;
 		}
 
-	} while (((*m)->m_owner != curthread) && (ret == 0) &&
-	    (curthread->interrupted == 0) && (curthread->timeout == 0));
-
-	if (ret == 0 && (*m)->m_owner != curthread && curthread->timeout)
-		ret = ETIMEDOUT;
-
-	/*
-	 * Check to see if this thread was interrupted and
-	 * is still in the mutex queue of waiting threads:
-	 */
-	if (curthread->interrupted != 0) {
-		/* Remove this thread from the mutex queue. */
-		THR_LOCK_ACQUIRE(curthread, &(*m)->m_lock);
-		if (THR_IN_SYNCQ(curthread))
-			mutex_queue_remove(*m, curthread);
-		THR_LOCK_RELEASE(curthread, &(*m)->m_lock);
+	} while (((*m)->m_owner != curthread) && (ret == 0));
 
-		/* Check for asynchronous cancellation. */
-		if (curthread->continuation != NULL)
-			curthread->continuation((void *) curthread);
-	}
-
 	/* Return the completion status: */
 	return (ret);
 }
@@ -971,15 +945,15 @@
 		 * What SS2 define as a 'normal' mutex.  Intentionally
 		 * deadlock on attempts to get a lock you already own.
 		 */
-
-		THR_LOCK_SWITCH(curthread);
-		THR_SET_STATE(curthread, PS_DEADLOCK);
-
-		/* Unlock the mutex structure: */
-		THR_LOCK_RELEASE(curthread, &m->m_lock);
+		if (m->m_protocol != PTHREAD_PRIO_NONE) {
+			/* Unlock the mutex structure: */
+			THR_LOCK_RELEASE(curthread, &m->m_lock);
+			for (;;)
+				thr_suspend(NULL);
+		} else {
+			PANIC("shouldn't be here!\n");
+		}
 
-		/* Schedule the next thread: */
-		_thr_sched_switch_unlocked(curthread);
 		ret = 0;
 		break;
 
@@ -1181,8 +1155,6 @@
 
 		/* Unlock the mutex structure: */
 		THR_LOCK_RELEASE(curthread, &(*m)->m_lock);
-		if (tid != -1)
-			thr_wake(tid);
 	}
 
 	/* Return the completion status: */
@@ -1712,7 +1684,8 @@
 		}
 
 		/* Make the thread runnable and unlock the scheduling queue: */
-		tid = _thr_setrunnable_unlocked(pthread);
+		pthread->cycle++;
+		umtx_wake((struct umtx *)&pthread->cycle, 1);
 
 		THR_THREAD_UNLOCK(curthread, pthread);
 		if (mutex->m_owner == pthread)
@@ -1741,13 +1714,6 @@
 	while ((pthread = TAILQ_FIRST(&mutex->m_queue)) != NULL) {
 		TAILQ_REMOVE(&mutex->m_queue, pthread, sqe);
 		pthread->sflags &= ~THR_FLAGS_IN_SYNCQ;
-
-		/*
-		 * Only exit the loop if the thread hasn't been
-		 * cancelled.
-		 */
-		if (pthread->interrupted == 0)
-			break;
 	}
 
 	return (pthread);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200412311505.iBVF5JAp009532>