From a8851a0fb965e874e53e6455853ae0f725548030 Mon Sep 17 00:00:00 2001 From: David Xu Date: Thu, 6 Apr 2006 23:50:13 +0000 Subject: [PATCH] Unlock recursive mutex in pthread_cond_wait, though this is arguable. --- lib/libthread_xu/thread/thr_cond.c | 27 ++++----- lib/libthread_xu/thread/thr_mutex.c | 83 ++++++++++++++------------- lib/libthread_xu/thread/thr_private.h | 6 +- 3 files changed, 59 insertions(+), 57 deletions(-) diff --git a/lib/libthread_xu/thread/thr_cond.c b/lib/libthread_xu/thread/thr_cond.c index 642e2d8654..e98d65da3e 100644 --- a/lib/libthread_xu/thread/thr_cond.c +++ b/lib/libthread_xu/thread/thr_cond.c @@ -23,7 +23,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $DragonFly: src/lib/libthread_xu/thread/thr_cond.c,v 1.9 2006/04/06 13:05:35 davidxu Exp $ + * $DragonFly: src/lib/libthread_xu/thread/thr_cond.c,v 1.10 2006/04/06 23:50:13 davidxu Exp $ */ #include "namespace.h" @@ -148,19 +148,20 @@ struct cond_cancel_info { pthread_mutex_t *mutex; pthread_cond_t *cond; - long seqno; + int seqno; + int count; }; static void cond_cancel_handler(void *arg) { struct pthread *curthread = tls_get_curthread(); - struct cond_cancel_info *cci = (struct cond_cancel_info *)arg; + struct cond_cancel_info *info = (struct cond_cancel_info *)arg; pthread_cond_t cv; - cv = *(cci->cond); + cv = *(info->cond); THR_LOCK_ACQUIRE(curthread, &cv->c_lock); - if (cv->c_seqno != cci->seqno && cv->c_wakeups != 0) { + if (cv->c_seqno != info->seqno && cv->c_wakeups != 0) { if (cv->c_waiters > 0) { cv->c_seqno++; _thr_umtx_wake(&cv->c_seqno, 1); @@ -171,7 +172,7 @@ cond_cancel_handler(void *arg) } THR_LOCK_RELEASE(curthread, &cv->c_lock); - _mutex_cv_lock(cci->mutex); + _mutex_cv_lock(info->mutex, info->count); } static int @@ -180,7 +181,7 @@ cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex, { struct pthread *curthread = tls_get_curthread(); struct timespec ts, ts2, *tsp; - struct cond_cancel_info cci; + struct cond_cancel_info info; pthread_cond_t cv; int seq, oldseq; int oldcancel; @@ -196,15 +197,15 @@ cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex, cv = *cond; THR_LOCK_ACQUIRE(curthread, &cv->c_lock); - ret = _mutex_cv_unlock(mutex); + ret = _mutex_cv_unlock(mutex, &info.count); if (ret) { THR_LOCK_RELEASE(curthread, &cv->c_lock); return (ret); } oldseq = seq = cv->c_seqno; - cci.mutex = mutex; - cci.cond = cond; - cci.seqno = oldseq; + info.mutex = mutex; + info.cond = cond; + info.seqno = oldseq; cv->c_waiters++; do { @@ -218,7 +219,7 @@ cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex, tsp = NULL; if (cancel) { - THR_CLEANUP_PUSH(curthread, cond_cancel_handler, &cci); + THR_CLEANUP_PUSH(curthread, cond_cancel_handler, &info); oldcancel = _thr_cancel_enter(curthread); ret = _thr_umtx_wait(&cv->c_seqno, seq, tsp, cv->c_clockid); @@ -247,7 +248,7 @@ cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex, cv->c_waiters--; } THR_LOCK_RELEASE(curthread, &cv->c_lock); - _mutex_cv_lock(mutex); + _mutex_cv_lock(mutex, info.count); return (ret); } diff --git a/lib/libthread_xu/thread/thr_mutex.c b/lib/libthread_xu/thread/thr_mutex.c index 6ef87a3a3b..2a72850318 100644 --- a/lib/libthread_xu/thread/thr_mutex.c +++ b/lib/libthread_xu/thread/thr_mutex.c @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/lib/libpthread/thread/thr_mutex.c,v 1.46 2004/10/31 05:03:50 green Exp $ - * $DragonFly: src/lib/libthread_xu/thread/thr_mutex.c,v 1.11 2006/04/06 13:03:09 davidxu Exp $ + * $DragonFly: src/lib/libthread_xu/thread/thr_mutex.c,v 1.12 2006/04/06 23:50:13 davidxu Exp $ */ #include "namespace.h" @@ -83,7 +83,7 @@ umtx_t _mutex_static_lock; static int mutex_self_trylock(pthread_mutex_t); static int mutex_self_lock(pthread_mutex_t, const struct timespec *abstime); -static int mutex_unlock_common(pthread_mutex_t *, int); +static int mutex_unlock_common(pthread_mutex_t *, int, int *); int __pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutex_attr); @@ -451,22 +451,24 @@ _pthread_mutex_timedlock(pthread_mutex_t *m, int _pthread_mutex_unlock(pthread_mutex_t *m) { - return (mutex_unlock_common(m, /* add reference */ 0)); + return (mutex_unlock_common(m, 0, NULL)); } int -_mutex_cv_unlock(pthread_mutex_t *m) +_mutex_cv_unlock(pthread_mutex_t *m, int *count) { - return (mutex_unlock_common(m, /* add reference */ 1)); + return (mutex_unlock_common(m, 1, count)); } int -_mutex_cv_lock(pthread_mutex_t *m) +_mutex_cv_lock(pthread_mutex_t *m, int count) { int ret; - if ((ret = _pthread_mutex_lock(m)) == 0) + if ((ret = _pthread_mutex_lock(m)) == 0) { (*m)->m_refcount--; + (*m)->m_count += count; + } return (ret); } @@ -559,46 +561,45 @@ mutex_self_lock(pthread_mutex_t m, const struct timespec *abstime) } static int -mutex_unlock_common(pthread_mutex_t *m, int add_reference) +mutex_unlock_common(pthread_mutex_t *mutex, int cv, int *count) { struct pthread *curthread = tls_get_curthread(); + struct pthread_mutex *m = *mutex; int ret = 0; - if (m == NULL || *m == NULL) - ret = EINVAL; - else { + if (m == NULL) + return (EINVAL); + /* + * Check if the running thread is not the owner of the mutex: + */ + if (__predict_false(m->m_owner != curthread)) + return (EPERM); + + if (cv) { + *count = m->m_count; + m->m_count = 0; + } + + if (__predict_false( + m->m_type == PTHREAD_MUTEX_RECURSIVE && + m->m_count > 0)) { + m->m_count--; + } else { /* - * Check if the running thread is not the owner of the - * mutex: + * Clear the count in case this is a recursive mutex. */ - if (__predict_false((*m)->m_owner != curthread)) { - ret = EPERM; - } else if (__predict_false( - (*m)->m_type == PTHREAD_MUTEX_RECURSIVE && - (*m)->m_count > 0)) { - /* Decrement the count: */ - (*m)->m_count--; - if (add_reference) - (*m)->m_refcount++; - } else { - /* - * Clear the count in case this is a recursive - * mutex. - */ - (*m)->m_count = 0; - (*m)->m_owner = NULL; - /* Remove the mutex from the threads queue. */ - MUTEX_ASSERT_IS_OWNED(*m); - TAILQ_REMOVE(&curthread->mutexq, (*m), m_qe); - MUTEX_INIT_LINK(*m); - if (add_reference) - (*m)->m_refcount++; - /* - * Hand off the mutex to the next waiting - * thread. - */ - _thr_umtx_unlock(&(*m)->m_lock, curthread->tid); - } + m->m_count = 0; + m->m_owner = NULL; + /* Remove the mutex from the threads queue. */ + MUTEX_ASSERT_IS_OWNED(m); + TAILQ_REMOVE(&curthread->mutexq, m, m_qe); + MUTEX_INIT_LINK(m); + if (cv) + m->m_refcount++; + /* + * Hand off the mutex to the next waiting thread. + */ + THR_UMTX_UNLOCK(curthread, &m->m_lock); } return (ret); } diff --git a/lib/libthread_xu/thread/thr_private.h b/lib/libthread_xu/thread/thr_private.h index 09a214a54a..b4fb9d5322 100644 --- a/lib/libthread_xu/thread/thr_private.h +++ b/lib/libthread_xu/thread/thr_private.h @@ -32,7 +32,7 @@ * Private thread definitions for the uthread kernel. * * $FreeBSD: src/lib/libpthread/thread/thr_private.h,v 1.120 2004/11/01 10:49:34 davidxu Exp $ - * $DragonFly: src/lib/libthread_xu/thread/thr_private.h,v 1.12 2006/04/06 13:03:09 davidxu Exp $ + * $DragonFly: src/lib/libthread_xu/thread/thr_private.h,v 1.13 2006/04/06 23:50:13 davidxu Exp $ */ #ifndef _THR_PRIVATE_H @@ -660,8 +660,8 @@ extern umtx_t _thr_event_lock; */ __BEGIN_DECLS int _thr_setthreaded(int); -int _mutex_cv_lock(pthread_mutex_t *); -int _mutex_cv_unlock(pthread_mutex_t *); +int _mutex_cv_lock(pthread_mutex_t *, int count); +int _mutex_cv_unlock(pthread_mutex_t *, int *count); void _mutex_notify_priochange(struct pthread *, struct pthread *, int); int _mutex_reinit(pthread_mutex_t *); void _mutex_fork(struct pthread *curthread); -- 2.41.0