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