From 2cc89328fa9d75c050a2d9daa670ea67be89b0e8 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Tue, 25 Jul 2023 15:21:00 -0400 Subject: [PATCH] kernel/user_mutex: Fix race in user_mutex_sem_release. We need to be sure nothing will start waiting before marking the semaphore as uncontended. Fixes a deadlock observed in libuv. --- src/system/kernel/locks/user_mutex.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/system/kernel/locks/user_mutex.cpp b/src/system/kernel/locks/user_mutex.cpp index 314ec48f75..1a09c64e40 100644 --- a/src/system/kernel/locks/user_mutex.cpp +++ b/src/system/kernel/locks/user_mutex.cpp @@ -435,7 +435,8 @@ user_mutex_sem_acquire_locked(UserMutexEntry* entry, int32* sem, static void user_mutex_sem_release(UserMutexEntry* entry, int32* sem, bool isWired) { - if (entry == NULL) { + WriteLocker entryLocker(entry->lock); + if (entry->condition.EntriesCount() == 0) { // no waiters - mark as uncontended and release int32 oldValue = user_atomic_get(sem, isWired); while (true) { @@ -447,7 +448,6 @@ user_mutex_sem_release(UserMutexEntry* entry, int32* sem, bool isWired) } } - WriteLocker entryLocker(entry->lock); entry->condition.NotifyOne(B_OK); if (entry->condition.EntriesCount() == 0) { // mark the semaphore uncontended @@ -706,7 +706,7 @@ _user_mutex_sem_release(int32* sem) return error; UserMutexEntry* entry = get_user_mutex_entry(context, - wiringInfo.physicalAddress, true); + wiringInfo.physicalAddress); { user_mutex_sem_release(entry, sem, true); }