[haiku-commits] haiku: hrev49149 - src/system/kernel/locks

  • From: hamishm53@xxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 8 May 2015 00:21:55 +0200 (CEST)

hrev49149 adds 1 changeset to branch 'master'
old head: d1b6645b564f583fce22ae8c9cf1823599c5c16b
new head: fb67dbf0a4c0c681b4edd4b56cfc85196c5e8cd4
overview:
http://cgit.haiku-os.org/haiku/log/?qt=range&q=fb67dbf0a4c0+%5Ed1b6645b564f

----------------------------------------------------------------------------

fb67dbf0a4c0: user mutex: dequeue waiters when waking them up

* This prevents the same waiter being woken multiple times, before it
has a chance to run and dequeue itself.

[ Hamish Morrison <hamishm53@xxxxxxxxx> ]

----------------------------------------------------------------------------

Revision: hrev49149
Commit: fb67dbf0a4c0c681b4edd4b56cfc85196c5e8cd4
URL: http://cgit.haiku-os.org/haiku/commit/?id=fb67dbf0a4c0
Author: Hamish Morrison <hamishm53@xxxxxxxxx>
Date: Mon May 4 23:51:37 2015 UTC

----------------------------------------------------------------------------

1 file changed, 31 insertions(+), 23 deletions(-)
src/system/kernel/locks/user_mutex.cpp | 54 +++++++++++++++++-------------

----------------------------------------------------------------------------

diff --git a/src/system/kernel/locks/user_mutex.cpp
b/src/system/kernel/locks/user_mutex.cpp
index 42e2d93..c89f7f5 100644
--- a/src/system/kernel/locks/user_mutex.cpp
+++ b/src/system/kernel/locks/user_mutex.cpp
@@ -131,8 +131,8 @@ user_mutex_lock_locked(int32* mutex, addr_t
physicalAddress, const char* name,
status_t error = waitEntry.Wait(flags, timeout);
locker.Lock();

- // dequeue
- if (!remove_user_mutex_entry(&entry)) {
+ // dequeue if we weren't woken up
+ if (!entry.locked && !remove_user_mutex_entry(&entry)) {
// no one is waiting anymore -- clear the waiting flag
atomic_and(mutex, ~(int32)B_USER_MUTEX_WAITING);
}
@@ -150,29 +150,37 @@ user_mutex_lock_locked(int32* mutex, addr_t
physicalAddress, const char* name,
static void
user_mutex_unlock_locked(int32* mutex, addr_t physicalAddress, uint32 flags)
{
- if (UserMutexEntry* entry = sUserMutexTable.Lookup(physicalAddress)) {
- // Someone is waiting -- set the locked flag. It might still be
set,
- // but when using userland atomic operations, the caller will
usually
- // have cleared it already.
- int32 oldValue = atomic_or(mutex, B_USER_MUTEX_LOCKED);
-
- // unblock the first thread
- entry->locked = true;
- entry->condition.NotifyOne();
-
- if ((flags & B_USER_MUTEX_UNBLOCK_ALL) != 0
- || (oldValue & B_USER_MUTEX_DISABLED) != 0) {
- // unblock all the other waiting threads as well
- for (UserMutexEntryList::Iterator it
- = entry->otherEntries.GetIterator();
- UserMutexEntry* otherEntry = it.Next();) {
- otherEntry->locked = true;
- otherEntry->condition.NotifyOne();
- }
- }
- } else {
+ UserMutexEntry* entry = sUserMutexTable.Lookup(physicalAddress);
+ if (entry == NULL) {
// no one is waiting -- clear locked flag
atomic_and(mutex, ~(int32)B_USER_MUTEX_LOCKED);
+ return;
+ }
+
+ // Someone is waiting -- set the locked flag. It might still be set,
+ // but when using userland atomic operations, the caller will usually
+ // have cleared it already.
+ int32 oldValue = atomic_or(mutex, B_USER_MUTEX_LOCKED);
+
+ // unblock the first thread
+ entry->locked = true;
+ entry->condition.NotifyOne();
+
+ if ((flags & B_USER_MUTEX_UNBLOCK_ALL) != 0
+ || (oldValue & B_USER_MUTEX_DISABLED) != 0) {
+ // unblock and dequeue all the other waiting threads as well
+ while (UserMutexEntry* otherEntry =
entry->otherEntries.RemoveHead()) {
+ otherEntry->locked = true;
+ otherEntry->condition.NotifyOne();
+ }
+
+ // dequeue the first thread and mark the mutex uncontended
+ sUserMutexTable.Remove(entry);
+ atomic_and(mutex, ~(int32)B_USER_MUTEX_WAITING);
+ } else {
+ bool otherWaiters = remove_user_mutex_entry(entry);
+ if (!otherWaiters)
+ atomic_and(mutex, ~(int32)B_USER_MUTEX_WAITING);
}
}



Other related posts:

  • » [haiku-commits] haiku: hrev49149 - src/system/kernel/locks - hamishm53