Unlock recursive mutex in pthread_cond_wait, though this is arguable.
authorDavid Xu <davidxu@dragonflybsd.org>
Thu, 6 Apr 2006 23:50:13 +0000 (23:50 +0000)
committerDavid Xu <davidxu@dragonflybsd.org>
Thu, 6 Apr 2006 23:50:13 +0000 (23:50 +0000)
lib/libthread_xu/thread/thr_cond.c
lib/libthread_xu/thread/thr_mutex.c
lib/libthread_xu/thread/thr_private.h

index 642e2d8..e98d65d 100644 (file)
@@ -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);
 }
 
index 6ef87a3..2a72850 100644 (file)
@@ -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);
 }
index 09a214a..b4fb9d5 100644 (file)
@@ -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);