From aca21731ff7636d67c524101ae87398079868eb8 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Tue, 25 Jul 2023 15:27:40 -0400 Subject: [PATCH] kernel/condition_variable: Return the count of unblocked threads from Notify. No reason not to, and it's needed in user_mutex to avoid a very rare potential race, anyway. --- headers/private/kernel/condition_variable.h | 22 ++++++++--------- src/system/kernel/condition_variable.cpp | 27 ++++++++++++--------- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/headers/private/kernel/condition_variable.h b/headers/private/kernel/condition_variable.h index 43ef0186c9..e57dd67df5 100644 --- a/headers/private/kernel/condition_variable.h +++ b/headers/private/kernel/condition_variable.h @@ -58,11 +58,11 @@ public: const char* objectType); void Unpublish(); - inline void NotifyOne(status_t result = B_OK); - inline void NotifyAll(status_t result = B_OK); + inline int32 NotifyOne(status_t result = B_OK); + inline int32 NotifyAll(status_t result = B_OK); - static void NotifyOne(const void* object, status_t result); - static void NotifyAll(const void* object, status_t result); + static int32 NotifyOne(const void* object, status_t result); + static int32 NotifyAll(const void* object, status_t result); void Add(ConditionVariableEntry* entry); int32 EntriesCount() { return atomic_get(&fEntriesCount); } @@ -79,9 +79,9 @@ public: void Dump() const; private: - static void _Notify(const void* object, bool all, status_t result); - void _Notify(bool all, status_t result); - void _NotifyLocked(bool all, status_t result); + static int32 _Notify(const void* object, bool all, status_t result); + int32 _Notify(bool all, status_t result); + int32 _NotifyLocked(bool all, status_t result); protected: typedef DoublyLinkedList EntryList; @@ -102,17 +102,17 @@ protected: }; -inline void +inline int32 ConditionVariable::NotifyOne(status_t result) { - _Notify(false, result); + return _Notify(false, result); } -inline void +inline int32 ConditionVariable::NotifyAll(status_t result) { - _Notify(true, result); + return _Notify(true, result); } diff --git a/src/system/kernel/condition_variable.cpp b/src/system/kernel/condition_variable.cpp index 1691645a6a..7f9785f877 100644 --- a/src/system/kernel/condition_variable.cpp +++ b/src/system/kernel/condition_variable.cpp @@ -324,56 +324,58 @@ ConditionVariable::Wait(recursive_lock* lock, uint32 flags, bigtime_t timeout) } -/*static*/ void +/*static*/ int32 ConditionVariable::NotifyOne(const void* object, status_t result) { - _Notify(object, false, result); + return _Notify(object, false, result); } -/*static*/ void +/*static*/ int32 ConditionVariable::NotifyAll(const void* object, status_t result) { - _Notify(object, true, result); + return _Notify(object, true, result); } -/*static*/ void +/*static*/ int32 ConditionVariable::_Notify(const void* object, bool all, status_t result) { InterruptsLocker ints; ReadSpinLocker hashLocker(sConditionVariableHashLock); ConditionVariable* variable = sConditionVariableHash.Lookup(object); if (variable == NULL) - return; + return 0; SpinLocker variableLocker(variable->fLock); hashLocker.Unlock(); - variable->_NotifyLocked(all, result); + return variable->_NotifyLocked(all, result); } -void +int32 ConditionVariable::_Notify(bool all, status_t result) { InterruptsSpinLocker _(fLock); - if (!fEntries.IsEmpty()) { if (result > B_OK) { panic("tried to notify with invalid result %" B_PRId32 "\n", result); result = B_ERROR; } - _NotifyLocked(all, result); + return _NotifyLocked(all, result); } + return 0; } /*! Called with interrupts disabled and the condition variable's spinlock held. */ -void +int32 ConditionVariable::_NotifyLocked(bool all, status_t result) { + int32 notified = 0; + // Dequeue and wake up the blocked threads. while (ConditionVariableEntry* entry = fEntries.RemoveHead()) { Thread* thread = atomic_pointer_get_and_set(&entry->fThread, (Thread*)NULL); @@ -417,9 +419,12 @@ ConditionVariable::_NotifyLocked(bool all, status_t result) thread_unblock_locked(thread, result); } + notified++; if (!all) break; } + + return notified; }