diff options
Diffstat (limited to 'hurd')
-rw-r--r-- | hurd/ChangeLog | 10 | ||||
-rw-r--r-- | hurd/mutex.h | 5 | ||||
-rw-r--r-- | hurd/rmutex.h | 20 |
3 files changed, 27 insertions, 8 deletions
diff --git a/hurd/ChangeLog b/hurd/ChangeLog index 0f89c2b..1b9e509 100644 --- a/hurd/ChangeLog +++ b/hurd/ChangeLog @@ -1,5 +1,15 @@ 2008-01-23 Neal H. Walfield <neal@gnu.org> + * mutex.h (ss_mutex_unlock): Correctly test whether there are + waiters. + * rmutex.h (ss_rmutex_lock): Save the value of LOCKP->COUNT before + unlocking the LOCKP->LOCK. After unlocking, use the cached value. + (ss_rmutex_unlock): Improve assert. Only clear LOCKP->OWNER and + wake a waiter if LOCKP->COUNT drops to 0. + (ss_rmutex_trylock): Correctly test whether we got LOCKP->LOCK. + +2008-01-23 Neal H. Walfield <neal@gnu.org> + * rmutex.h (ss_rmutex_lock): Don't use __lock_acquire or __lock_release to lock or unlock LOCKP->LOCK, but ss_mutex_lock and ss_mutex_unlock. diff --git a/hurd/mutex.h b/hurd/mutex.h index 3e21eee..3f50934 100644 --- a/hurd/mutex.h +++ b/hurd/mutex.h @@ -89,8 +89,9 @@ ss_mutex_unlock (__const char *caller, int line, ss_mutex_t *lockp) { /* We rely on the knowledge that unlocked is 0, locked and no waiters is 1 and locked with waiters is 2. Thus if *lockp is 1, - an atomic dec yields 0 and we know that there are no waiters. */ - if (! atomic_decrement_and_test (lockp)) + an atomic dec yields 1 (the old value) and we know that there are + no waiters. */ + if (atomic_decrement_and_test (lockp) != _MUTEX_LOCKED) /* There are waiters. */ { *lockp = 0; diff --git a/hurd/rmutex.h b/hurd/rmutex.h index d8cb71f..ddba589 100644 --- a/hurd/rmutex.h +++ b/hurd/rmutex.h @@ -89,10 +89,12 @@ ss_rmutex_lock (const char *caller, int line, ss_rmutex_t *lockp) /* Note that there are waiters. */ lockp->count = -lockp->count; + int count = lockp->count; + ss_mutex_unlock (&lockp->lock); ss_mutex_trace_add (SS_RMUTEX_LOCK, caller, line, lockp); - futex_wait (&lockp->count, lockp->count); + futex_wait (&lockp->count, count); } } @@ -109,7 +111,11 @@ ss_rmutex_unlock (const char *caller, int line, ss_rmutex_t *lockp) { ss_mutex_lock (&lockp->lock); - assert (lockp->owner == l4_myself ()); + if (lockp->owner != l4_myself ()) + ss_lock_trace_dump (lockp); + assertx (lockp->owner == l4_myself (), + "%x != %x (count: %d, caller: %s:%d)", + lockp->owner, l4_myself (), lockp->count, caller, line); assert (lockp->count != 0); int waiters = lockp->count < 0; @@ -118,16 +124,18 @@ ss_rmutex_unlock (const char *caller, int line, ss_rmutex_t *lockp) else lockp->count ++; + bool released = lockp->count == 0; + if (released) + lockp->owner = l4_nilthread; + if (lockp->count == 0) ss_mutex_trace_add (SS_RMUTEX_UNLOCK, caller, line, lockp); else ss_mutex_trace_add (SS_RMUTEX_UNLOCK_DEC, caller, line, lockp); - lockp->owner = l4_nilthread; - ss_mutex_unlock (&lockp->lock); - if (waiters) + if (released && waiters) futex_wake (&lockp->count, 1); } @@ -144,7 +152,7 @@ ss_rmutex_trylock (const char *caller, int line, ss_rmutex_t *lockp) { /* If someone holds the meta-lock then the lock is either held or about to be held. */ - if (ss_mutex_trylock (&lockp->lock) == 1) + if (! ss_mutex_trylock (&lockp->lock)) /* Busy. */ { ss_mutex_trace_add (SS_RMUTEX_TRYLOCK_BLOCKED, caller, line, lockp); |