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:
parent
4f6fa362cf
commit
4ed7917682
@ -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<Type>::Add(const Type* object,
|
||||
|
||||
|
||||
template<typename Type>
|
||||
inline void
|
||||
inline status_t
|
||||
ConditionVariableEntry<Type>::Wait(uint32 flags)
|
||||
{
|
||||
PrivateConditionVariableEntry::Wait(flags);
|
||||
return PrivateConditionVariableEntry::Wait(flags);
|
||||
}
|
||||
|
||||
|
||||
template<typename Type>
|
||||
inline void
|
||||
inline status_t
|
||||
ConditionVariableEntry<Type>::Wait(const Type* object, uint32 flags)
|
||||
{
|
||||
PrivateConditionVariableEntry::Wait(object, flags);
|
||||
return PrivateConditionVariableEntry::Wait(object, flags);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user