Wait() returns a status_t now, which can be B_OK (condition variable

exists and thread was notified), B_ENTRY_NOT_FOUND (condition variable
not found or Unpublish()ed while waiting), or B_INTERRUPTED
(interrupted by a signal).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22083 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2007-08-27 20:17:31 +00:00
parent 4f6fa362cf
commit 4ed7917682
2 changed files with 32 additions and 23 deletions

View File

@ -29,8 +29,8 @@ public:
protected: protected:
bool Add(const void* object, bool Add(const void* object,
PrivateConditionVariableEntry* threadNext); PrivateConditionVariableEntry* threadNext);
void Wait(uint32 flags); status_t Wait(uint32 flags);
void Wait(const void* object, uint32 flags); status_t Wait(const void* object, uint32 flags);
private: private:
void _Remove(); void _Remove();
@ -40,6 +40,7 @@ protected:
PrivateConditionVariable* fVariable; PrivateConditionVariable* fVariable;
struct thread* fThread; struct thread* fThread;
uint32 fFlags; uint32 fFlags;
status_t fResult;
PrivateConditionVariableEntry* fThreadPrevious; PrivateConditionVariableEntry* fThreadPrevious;
PrivateConditionVariableEntry* fThreadNext; PrivateConditionVariableEntry* fThreadNext;
@ -62,7 +63,7 @@ protected:
void Notify(bool all); void Notify(bool all);
private: private:
void _Notify(bool all); void _Notify(bool all, status_t result);
protected: protected:
const void* fObject; const void* fObject;
@ -92,11 +93,8 @@ public:
inline bool Add(const Type* object, inline bool Add(const Type* object,
PrivateConditionVariableEntry* threadNext PrivateConditionVariableEntry* threadNext
= NULL); = NULL);
inline void Wait(uint32 flags = 0); inline status_t Wait(uint32 flags = 0);
inline void Wait(const Type* object, uint32 flags = 0); inline status_t Wait(const Type* object, uint32 flags = 0);
private:
bool fAdded;
}; };
@ -142,18 +140,18 @@ ConditionVariableEntry<Type>::Add(const Type* object,
template<typename Type> template<typename Type>
inline void inline status_t
ConditionVariableEntry<Type>::Wait(uint32 flags) ConditionVariableEntry<Type>::Wait(uint32 flags)
{ {
PrivateConditionVariableEntry::Wait(flags); return PrivateConditionVariableEntry::Wait(flags);
} }
template<typename Type> template<typename Type>
inline void inline status_t
ConditionVariableEntry<Type>::Wait(const Type* object, uint32 flags) ConditionVariableEntry<Type>::Wait(const Type* object, uint32 flags)
{ {
PrivateConditionVariableEntry::Wait(object, flags); return PrivateConditionVariableEntry::Wait(object, flags);
} }

View File

@ -97,6 +97,7 @@ PrivateConditionVariableEntry::Add(const void* object,
fThread = thread_get_current_thread(); fThread = thread_get_current_thread();
fFlags = 0; fFlags = 0;
fResult = B_OK;
InterruptsLocker _; InterruptsLocker _;
SpinLocker locker(sConditionVariablesLock); SpinLocker locker(sConditionVariablesLock);
@ -114,19 +115,20 @@ PrivateConditionVariableEntry::Add(const void* object,
if (fVariable) { if (fVariable) {
fVariableNext = fVariable->fEntries; fVariableNext = fVariable->fEntries;
fVariable->fEntries = this; fVariable->fEntries = this;
} } else
fResult = B_ENTRY_NOT_FOUND;
return (fVariable != NULL); return (fVariable != NULL);
} }
void status_t
PrivateConditionVariableEntry::Wait(uint32 flags) PrivateConditionVariableEntry::Wait(uint32 flags)
{ {
if (!are_interrupts_enabled()) { if (!are_interrupts_enabled()) {
panic("wait_for_condition_variable_entry() called with interrupts " panic("wait_for_condition_variable_entry() called with interrupts "
"disabled"); "disabled");
return; return B_ERROR;
} }
InterruptsLocker _; InterruptsLocker _;
@ -142,7 +144,7 @@ PrivateConditionVariableEntry::Wait(uint32 flags)
PrivateConditionVariableEntry* entry = firstEntry; PrivateConditionVariableEntry* entry = firstEntry;
while (entry) { while (entry) {
if (entry->fVariable == NULL) if (entry->fVariable == NULL)
return; return entry->fResult;
entry->fFlags = flags; entry->fFlags = flags;
@ -159,14 +161,17 @@ PrivateConditionVariableEntry::Wait(uint32 flags)
locker.Unlock(); locker.Unlock();
scheduler_reschedule(); scheduler_reschedule();
RELEASE_THREAD_LOCK(); RELEASE_THREAD_LOCK();
return firstEntry->fResult;
} }
void status_t
PrivateConditionVariableEntry::Wait(const void* object, uint32 flags) PrivateConditionVariableEntry::Wait(const void* object, uint32 flags)
{ {
if (Add(object, NULL)) 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 uint32 Flags() const { return fEntry.fFlags; }
inline void Remove() const { fEntry._Remove(); } inline void Remove() const { fEntry._Remove(); }
inline void SetResult(status_t result) { fEntry.fResult = result; }
private: private:
PrivateConditionVariableEntry& fEntry; PrivateConditionVariableEntry& fEntry;
@ -294,7 +300,7 @@ PrivateConditionVariable::Unpublish()
fObjectType = NULL; fObjectType = NULL;
if (fEntries) if (fEntries)
_Notify(true); _Notify(true, B_ENTRY_NOT_FOUND);
} }
@ -315,13 +321,13 @@ PrivateConditionVariable::Notify(bool all)
#endif #endif
if (fEntries) if (fEntries)
_Notify(all); _Notify(all, B_OK);
} }
//! Called with interrupts disabled and the condition variable spinlock held. //! Called with interrupts disabled and the condition variable spinlock held.
void void
PrivateConditionVariable::_Notify(bool all) PrivateConditionVariable::_Notify(bool all, status_t result)
{ {
// dequeue and wake up the blocked threads // dequeue and wake up the blocked threads
GRAB_THREAD_LOCK(); GRAB_THREAD_LOCK();
@ -330,6 +336,9 @@ PrivateConditionVariable::_Notify(bool all)
fEntries = entry->fVariableNext; fEntries = entry->fVariableNext;
struct thread* thread = entry->fThread; struct thread* thread = entry->fThread;
if (thread->condition_variable_entry != NULL)
thread->condition_variable_entry->fResult = result;
entry->fVariableNext = NULL; entry->fVariableNext = NULL;
entry->fVariable = NULL; entry->fVariable = NULL;
@ -401,6 +410,8 @@ condition_variable_interrupt_thread(struct thread* thread)
return B_NOT_ALLOWED; return B_NOT_ALLOWED;
} }
PrivateConditionVariableEntry::Private(*entry).SetResult(B_INTERRUPTED);
// remove all of the thread's entries from their variables // remove all of the thread's entries from their variables
while (entry) { while (entry) {
PrivateConditionVariableEntry::Private(*entry).Remove(); PrivateConditionVariableEntry::Private(*entry).Remove();