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.
This commit is contained in:
@@ -58,11 +58,11 @@ public:
|
|||||||
const char* objectType);
|
const char* objectType);
|
||||||
void Unpublish();
|
void Unpublish();
|
||||||
|
|
||||||
inline void NotifyOne(status_t result = B_OK);
|
inline int32 NotifyOne(status_t result = B_OK);
|
||||||
inline void NotifyAll(status_t result = B_OK);
|
inline int32 NotifyAll(status_t result = B_OK);
|
||||||
|
|
||||||
static void NotifyOne(const void* object, status_t result);
|
static int32 NotifyOne(const void* object, status_t result);
|
||||||
static void NotifyAll(const void* object, status_t result);
|
static int32 NotifyAll(const void* object, status_t result);
|
||||||
|
|
||||||
void Add(ConditionVariableEntry* entry);
|
void Add(ConditionVariableEntry* entry);
|
||||||
int32 EntriesCount() { return atomic_get(&fEntriesCount); }
|
int32 EntriesCount() { return atomic_get(&fEntriesCount); }
|
||||||
@@ -79,9 +79,9 @@ public:
|
|||||||
void Dump() const;
|
void Dump() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void _Notify(const void* object, bool all, status_t result);
|
static int32 _Notify(const void* object, bool all, status_t result);
|
||||||
void _Notify(bool all, status_t result);
|
int32 _Notify(bool all, status_t result);
|
||||||
void _NotifyLocked(bool all, status_t result);
|
int32 _NotifyLocked(bool all, status_t result);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef DoublyLinkedList<ConditionVariableEntry> EntryList;
|
typedef DoublyLinkedList<ConditionVariableEntry> EntryList;
|
||||||
@@ -102,17 +102,17 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
inline void
|
inline int32
|
||||||
ConditionVariable::NotifyOne(status_t result)
|
ConditionVariable::NotifyOne(status_t result)
|
||||||
{
|
{
|
||||||
_Notify(false, result);
|
return _Notify(false, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void
|
inline int32
|
||||||
ConditionVariable::NotifyAll(status_t result)
|
ConditionVariable::NotifyAll(status_t result)
|
||||||
{
|
{
|
||||||
_Notify(true, result);
|
return _Notify(true, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
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)
|
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)
|
ConditionVariable::_Notify(const void* object, bool all, status_t result)
|
||||||
{
|
{
|
||||||
InterruptsLocker ints;
|
InterruptsLocker ints;
|
||||||
ReadSpinLocker hashLocker(sConditionVariableHashLock);
|
ReadSpinLocker hashLocker(sConditionVariableHashLock);
|
||||||
ConditionVariable* variable = sConditionVariableHash.Lookup(object);
|
ConditionVariable* variable = sConditionVariableHash.Lookup(object);
|
||||||
if (variable == NULL)
|
if (variable == NULL)
|
||||||
return;
|
return 0;
|
||||||
SpinLocker variableLocker(variable->fLock);
|
SpinLocker variableLocker(variable->fLock);
|
||||||
hashLocker.Unlock();
|
hashLocker.Unlock();
|
||||||
|
|
||||||
variable->_NotifyLocked(all, result);
|
return variable->_NotifyLocked(all, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
int32
|
||||||
ConditionVariable::_Notify(bool all, status_t result)
|
ConditionVariable::_Notify(bool all, status_t result)
|
||||||
{
|
{
|
||||||
InterruptsSpinLocker _(fLock);
|
InterruptsSpinLocker _(fLock);
|
||||||
|
|
||||||
if (!fEntries.IsEmpty()) {
|
if (!fEntries.IsEmpty()) {
|
||||||
if (result > B_OK) {
|
if (result > B_OK) {
|
||||||
panic("tried to notify with invalid result %" B_PRId32 "\n", result);
|
panic("tried to notify with invalid result %" B_PRId32 "\n", result);
|
||||||
result = B_ERROR;
|
result = B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
_NotifyLocked(all, result);
|
return _NotifyLocked(all, result);
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Called with interrupts disabled and the condition variable's spinlock held.
|
/*! Called with interrupts disabled and the condition variable's spinlock held.
|
||||||
*/
|
*/
|
||||||
void
|
int32
|
||||||
ConditionVariable::_NotifyLocked(bool all, status_t result)
|
ConditionVariable::_NotifyLocked(bool all, status_t result)
|
||||||
{
|
{
|
||||||
|
int32 notified = 0;
|
||||||
|
|
||||||
// Dequeue and wake up the blocked threads.
|
// Dequeue and wake up the blocked threads.
|
||||||
while (ConditionVariableEntry* entry = fEntries.RemoveHead()) {
|
while (ConditionVariableEntry* entry = fEntries.RemoveHead()) {
|
||||||
Thread* thread = atomic_pointer_get_and_set(&entry->fThread, (Thread*)NULL);
|
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);
|
thread_unblock_locked(thread, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notified++;
|
||||||
if (!all)
|
if (!all)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return notified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user