summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hurd/ChangeLog10
-rw-r--r--hurd/mutex.h5
-rw-r--r--hurd/rmutex.h20
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);