diff --git a/headers/private/kernel/condition_variable.h b/headers/private/kernel/condition_variable.h index a122541790..efc9f70762 100644 --- a/headers/private/kernel/condition_variable.h +++ b/headers/private/kernel/condition_variable.h @@ -29,8 +29,8 @@ public: protected: bool Add(const void* object, PrivateConditionVariableEntry* threadNext); - void Wait(uint32 flags); - void Wait(const void* object, uint32 flags); + status_t Wait(uint32 flags); + status_t Wait(const void* object, uint32 flags); private: void _Remove(); @@ -40,6 +40,7 @@ protected: PrivateConditionVariable* fVariable; struct thread* fThread; uint32 fFlags; + status_t fResult; PrivateConditionVariableEntry* fThreadPrevious; PrivateConditionVariableEntry* fThreadNext; @@ -62,7 +63,7 @@ protected: void Notify(bool all); private: - void _Notify(bool all); + void _Notify(bool all, status_t result); protected: const void* fObject; @@ -92,11 +93,8 @@ public: inline bool Add(const Type* object, PrivateConditionVariableEntry* threadNext = NULL); - inline void Wait(uint32 flags = 0); - inline void Wait(const Type* object, uint32 flags = 0); - -private: - bool fAdded; + inline status_t Wait(uint32 flags = 0); + inline status_t Wait(const Type* object, uint32 flags = 0); }; @@ -142,18 +140,18 @@ ConditionVariableEntry::Add(const Type* object, template -inline void +inline status_t ConditionVariableEntry::Wait(uint32 flags) { - PrivateConditionVariableEntry::Wait(flags); + return PrivateConditionVariableEntry::Wait(flags); } template -inline void +inline status_t ConditionVariableEntry::Wait(const Type* object, uint32 flags) { - PrivateConditionVariableEntry::Wait(object, flags); + return PrivateConditionVariableEntry::Wait(object, flags); } diff --git a/src/system/kernel/condition_variable.cpp b/src/system/kernel/condition_variable.cpp index 9d1b8cb9c7..9ef2b9dc13 100644 --- a/src/system/kernel/condition_variable.cpp +++ b/src/system/kernel/condition_variable.cpp @@ -97,6 +97,7 @@ PrivateConditionVariableEntry::Add(const void* object, fThread = thread_get_current_thread(); fFlags = 0; + fResult = B_OK; InterruptsLocker _; SpinLocker locker(sConditionVariablesLock); @@ -114,19 +115,20 @@ PrivateConditionVariableEntry::Add(const void* object, if (fVariable) { fVariableNext = fVariable->fEntries; fVariable->fEntries = this; - } + } else + fResult = B_ENTRY_NOT_FOUND; return (fVariable != NULL); } -void +status_t PrivateConditionVariableEntry::Wait(uint32 flags) { if (!are_interrupts_enabled()) { panic("wait_for_condition_variable_entry() called with interrupts " "disabled"); - return; + return B_ERROR; } InterruptsLocker _; @@ -142,7 +144,7 @@ PrivateConditionVariableEntry::Wait(uint32 flags) PrivateConditionVariableEntry* entry = firstEntry; while (entry) { if (entry->fVariable == NULL) - return; + return entry->fResult; entry->fFlags = flags; @@ -159,14 +161,17 @@ PrivateConditionVariableEntry::Wait(uint32 flags) locker.Unlock(); scheduler_reschedule(); RELEASE_THREAD_LOCK(); + + return firstEntry->fResult; } -void +status_t PrivateConditionVariableEntry::Wait(const void* object, uint32 flags) { if (Add(object, NULL)) - Wait(flags); + return Wait(flags); + return B_ENTRY_NOT_FOUND; } @@ -207,8 +212,9 @@ public: { } - inline uint32 Flags() const { return fEntry.fFlags; } - inline void Remove() const { fEntry._Remove(); } + inline uint32 Flags() const { return fEntry.fFlags; } + inline void Remove() const { fEntry._Remove(); } + inline void SetResult(status_t result) { fEntry.fResult = result; } private: PrivateConditionVariableEntry& fEntry; @@ -294,7 +300,7 @@ PrivateConditionVariable::Unpublish() fObjectType = NULL; if (fEntries) - _Notify(true); + _Notify(true, B_ENTRY_NOT_FOUND); } @@ -315,13 +321,13 @@ PrivateConditionVariable::Notify(bool all) #endif if (fEntries) - _Notify(all); + _Notify(all, B_OK); } //! Called with interrupts disabled and the condition variable spinlock held. void -PrivateConditionVariable::_Notify(bool all) +PrivateConditionVariable::_Notify(bool all, status_t result) { // dequeue and wake up the blocked threads GRAB_THREAD_LOCK(); @@ -330,6 +336,9 @@ PrivateConditionVariable::_Notify(bool all) fEntries = entry->fVariableNext; struct thread* thread = entry->fThread; + if (thread->condition_variable_entry != NULL) + thread->condition_variable_entry->fResult = result; + entry->fVariableNext = NULL; entry->fVariable = NULL; @@ -401,6 +410,8 @@ condition_variable_interrupt_thread(struct thread* thread) return B_NOT_ALLOWED; } + PrivateConditionVariableEntry::Private(*entry).SetResult(B_INTERRUPTED); + // remove all of the thread's entries from their variables while (entry) { PrivateConditionVariableEntry::Private(*entry).Remove();