fix and optimize non-default-type mutex behavior
authorRich Felker <dalias@aerifal.cx>
Tue, 8 Mar 2011 08:41:05 +0000 (03:41 -0500)
committerRich Felker <dalias@aerifal.cx>
Tue, 8 Mar 2011 08:41:05 +0000 (03:41 -0500)
problem 1: mutex type from the attribute was being ignored by
pthread_mutex_init, so recursive/errorchecking mutexes were never
being used at all.

problem 2: ownership of recursive mutexes was not being enforced at
unlock time.

src/internal/pthread_impl.h
src/thread/pthread_mutex_init.c
src/thread/pthread_mutex_trylock.c
src/thread/pthread_mutex_unlock.c

index 22ba8b76fedc69ae947140bdea490d19a569a3e7..adb80f2f6783ae737a4d3ca44df16b8bf2943f99 100644 (file)
@@ -47,6 +47,7 @@ struct pthread {
 #define _m_lock __u.__i[1]
 #define _m_waiters __u.__i[2]
 #define _m_owner __u.__i[3]
+#define _m_count __u.__i[4]
 #define _c_block __u.__i[0]
 #define _c_clock __u.__i[1]
 #define _rw_wrlock __u.__i[0]
index d453543d06709856ca4a075103a298bd6f6fb0da..6e23df139a213f64b036b901fa9f933c7cf59419 100644 (file)
@@ -3,7 +3,6 @@
 int pthread_mutex_init(pthread_mutex_t *m, const pthread_mutexattr_t *a)
 {
        memset(m, 0, sizeof *m);
-       if (a) {
-       }
+       if (a) m->_m_type = *a & 3;
        return 0;
 }
index 29268fdb0fa772f02e06dddf51bf00c851bebe88..7ff4f703b9ff1e68bc365a2bf31e64fdd6faa278 100644 (file)
@@ -2,27 +2,24 @@
 
 int pthread_mutex_trylock(pthread_mutex_t *m)
 {
-       if (m->_m_type == PTHREAD_MUTEX_RECURSIVE) {
-               pthread_t self = pthread_self();
-               if (m->_m_owner == self->tid) {
-                       if ((unsigned)m->_m_lock >= INT_MAX) return EAGAIN;
-                       a_inc(&m->_m_lock);
+       pthread_t self;
+       if (m->_m_type != PTHREAD_MUTEX_NORMAL) {
+               self = pthread_self();
+               if (m->_m_type == PTHREAD_MUTEX_RECURSIVE
+                && m->_m_owner == self->tid) {
+                       if ((unsigned)m->_m_count >= INT_MAX) return EAGAIN;
+                       m->_m_count++;
                        return 0;
                }
-               if (a_fetch_add(&m->_m_lock, 1)) {
-                       if (a_fetch_add(&m->_m_lock, -1)==1 && m->_m_waiters)
-                               __wake(&m->_m_lock, 1, 0);
-                       return EBUSY;
-               }
-               m->_m_owner = self->tid;
-               return 0;
        }
 
        if (a_xchg(&m->_m_lock, 1))
                if (m->_m_type == PTHREAD_MUTEX_ERRORCHECK
-                && m->_m_owner == pthread_self()->tid) return EDEADLK;
+                && m->_m_owner == self->tid) return EDEADLK;
                else return EBUSY;
-       if (m->_m_type == PTHREAD_MUTEX_ERRORCHECK)
-               m->_m_owner = pthread_self()->tid;
+       if (m->_m_type != PTHREAD_MUTEX_NORMAL) {
+               m->_m_owner = self->tid;
+               m->_m_count = 1;
+       }
        return 0;
 }
index 0275eb52e6e6a5e93f34a2037e601dbbaaccdfac..39cea4b6d4fc0a9b45f43aa6671c51380f6a2031 100644 (file)
@@ -2,16 +2,13 @@
 
 int pthread_mutex_unlock(pthread_mutex_t *m)
 {
-       if (m->_m_type == PTHREAD_MUTEX_RECURSIVE) {
-               if (a_fetch_add(&m->_m_lock, -1)==1 && m->_m_waiters)
-                       __wake(&m->_m_lock, 1, 0);
-               return 0;
+       if (m->_m_type != PTHREAD_MUTEX_NORMAL) {
+               if (m->_m_owner != pthread_self()->tid)
+                       return EPERM;
+               if (m->_m_type == PTHREAD_MUTEX_RECURSIVE && --m->_m_count)
+                       return 0;
        }
 
-       if (m->_m_type == PTHREAD_MUTEX_ERRORCHECK
-        && m->_m_owner != pthread_self()->tid)
-               return EPERM;
-
        m->_m_owner = 0;
        m->_m_lock = 0;
        if (m->_m_waiters) __wake(&m->_m_lock, 1, 0);