Removed the feature that a thread can wait for more than one condition
variable at once. It wasn't used anymore, and the code gets simpler. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25080 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -12,13 +12,15 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include <util/DoublyLinkedList.h>
|
||||||
#include <util/OpenHashTable.h>
|
#include <util/OpenHashTable.h>
|
||||||
|
|
||||||
|
|
||||||
class PrivateConditionVariable;
|
class PrivateConditionVariable;
|
||||||
|
|
||||||
|
|
||||||
struct PrivateConditionVariableEntry {
|
struct PrivateConditionVariableEntry
|
||||||
|
: DoublyLinkedListLinkImpl<PrivateConditionVariableEntry> {
|
||||||
public:
|
public:
|
||||||
#if KDEBUG
|
#if KDEBUG
|
||||||
inline PrivateConditionVariableEntry()
|
inline PrivateConditionVariableEntry()
|
||||||
@@ -38,16 +40,10 @@ public:
|
|||||||
inline PrivateConditionVariable* Variable() const
|
inline PrivateConditionVariable* Variable() const
|
||||||
{ return fVariable; }
|
{ return fVariable; }
|
||||||
|
|
||||||
inline PrivateConditionVariableEntry* ThreadNext() const
|
|
||||||
{ return fThreadNext; }
|
|
||||||
inline PrivateConditionVariableEntry* ThreadPrevious() const
|
|
||||||
{ return fThreadPrevious; }
|
|
||||||
|
|
||||||
class Private;
|
class Private;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool Add(const void* object,
|
bool Add(const void* object);
|
||||||
PrivateConditionVariableEntry* threadNext);
|
|
||||||
status_t Wait(uint32 flags);
|
status_t Wait(uint32 flags);
|
||||||
status_t Wait(const void* object, uint32 flags);
|
status_t Wait(const void* object, uint32 flags);
|
||||||
|
|
||||||
@@ -55,15 +51,11 @@ private:
|
|||||||
void _Remove();
|
void _Remove();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PrivateConditionVariableEntry* fVariableNext;
|
|
||||||
PrivateConditionVariable* fVariable;
|
PrivateConditionVariable* fVariable;
|
||||||
struct thread* fThread;
|
struct thread* fThread;
|
||||||
uint32 fFlags;
|
uint32 fFlags;
|
||||||
status_t fResult;
|
status_t fResult;
|
||||||
|
|
||||||
PrivateConditionVariableEntry* fThreadPrevious;
|
|
||||||
PrivateConditionVariableEntry* fThreadNext;
|
|
||||||
|
|
||||||
friend class PrivateConditionVariable;
|
friend class PrivateConditionVariable;
|
||||||
friend class Private;
|
friend class Private;
|
||||||
};
|
};
|
||||||
@@ -85,9 +77,11 @@ private:
|
|||||||
void _Notify(bool all, status_t result);
|
void _Notify(bool all, status_t result);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
typedef DoublyLinkedList<PrivateConditionVariableEntry> EntryList;
|
||||||
|
|
||||||
const void* fObject;
|
const void* fObject;
|
||||||
const char* fObjectType;
|
const char* fObjectType;
|
||||||
PrivateConditionVariableEntry* fEntries;
|
EntryList fEntries;
|
||||||
|
|
||||||
friend class PrivateConditionVariableEntry;
|
friend class PrivateConditionVariableEntry;
|
||||||
friend class ConditionVariableHashDefinition;
|
friend class ConditionVariableHashDefinition;
|
||||||
@@ -109,9 +103,7 @@ public:
|
|||||||
template<typename Type = void>
|
template<typename Type = void>
|
||||||
class ConditionVariableEntry : public PrivateConditionVariableEntry {
|
class ConditionVariableEntry : public PrivateConditionVariableEntry {
|
||||||
public:
|
public:
|
||||||
inline bool Add(const Type* object,
|
inline bool Add(const Type* object);
|
||||||
PrivateConditionVariableEntry* threadNext
|
|
||||||
= NULL);
|
|
||||||
inline status_t Wait(uint32 flags = 0);
|
inline status_t Wait(uint32 flags = 0);
|
||||||
inline status_t Wait(const Type* object, uint32 flags = 0);
|
inline status_t Wait(const Type* object, uint32 flags = 0);
|
||||||
};
|
};
|
||||||
@@ -151,10 +143,9 @@ ConditionVariable<Type>::NotifyAll(bool threadsLocked)
|
|||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
inline bool
|
inline bool
|
||||||
ConditionVariableEntry<Type>::Add(const Type* object,
|
ConditionVariableEntry<Type>::Add(const Type* object)
|
||||||
PrivateConditionVariableEntry* threadNext)
|
|
||||||
{
|
{
|
||||||
return PrivateConditionVariableEntry::Add(object, threadNext);
|
return PrivateConditionVariableEntry::Add(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -92,8 +92,7 @@ dump_condition_variable(int argc, char** argv)
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PrivateConditionVariableEntry::Add(const void* object,
|
PrivateConditionVariableEntry::Add(const void* object)
|
||||||
PrivateConditionVariableEntry* threadNext)
|
|
||||||
{
|
{
|
||||||
ASSERT(object != NULL);
|
ASSERT(object != NULL);
|
||||||
|
|
||||||
@@ -104,22 +103,11 @@ PrivateConditionVariableEntry::Add(const void* object,
|
|||||||
InterruptsLocker _;
|
InterruptsLocker _;
|
||||||
SpinLocker locker(sConditionVariablesLock);
|
SpinLocker locker(sConditionVariablesLock);
|
||||||
|
|
||||||
// add to the list of entries for this thread
|
|
||||||
fThreadNext = threadNext;
|
|
||||||
if (threadNext) {
|
|
||||||
fThreadPrevious = threadNext->fThreadPrevious;
|
|
||||||
threadNext->fThreadPrevious = this;
|
|
||||||
if (fThreadPrevious)
|
|
||||||
fThreadPrevious->fThreadNext = this;
|
|
||||||
} else
|
|
||||||
fThreadPrevious = NULL;
|
|
||||||
|
|
||||||
// add to the queue for the variable
|
// add to the queue for the variable
|
||||||
fVariable = sConditionVariableHash.Lookup(object);
|
fVariable = sConditionVariableHash.Lookup(object);
|
||||||
if (fVariable) {
|
if (fVariable)
|
||||||
fVariableNext = fVariable->fEntries;
|
fVariable->fEntries.Add(this);
|
||||||
fVariable->fEntries = this;
|
else
|
||||||
} else
|
|
||||||
fResult = B_ENTRY_NOT_FOUND;
|
fResult = B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
return (fVariable != NULL);
|
return (fVariable != NULL);
|
||||||
@@ -139,22 +127,11 @@ PrivateConditionVariableEntry::Wait(uint32 flags)
|
|||||||
SpinLocker threadLocker(thread_spinlock);
|
SpinLocker threadLocker(thread_spinlock);
|
||||||
SpinLocker locker(sConditionVariablesLock);
|
SpinLocker locker(sConditionVariablesLock);
|
||||||
|
|
||||||
// get first entry for this thread
|
// check whether this entry has already been notified
|
||||||
PrivateConditionVariableEntry* firstEntry = this;
|
|
||||||
while (firstEntry->fThreadPrevious)
|
|
||||||
firstEntry = firstEntry->fThreadPrevious;
|
|
||||||
|
|
||||||
// check whether any entry has already been notified
|
|
||||||
// (set the flags while at it)
|
// (set the flags while at it)
|
||||||
PrivateConditionVariableEntry* entry = firstEntry;
|
if (fVariable == NULL)
|
||||||
while (entry) {
|
return fResult;
|
||||||
if (entry->fVariable == NULL)
|
fFlags = flags;
|
||||||
return entry->fResult;
|
|
||||||
|
|
||||||
entry->fFlags = flags;
|
|
||||||
|
|
||||||
entry = entry->fThreadNext;
|
|
||||||
}
|
|
||||||
|
|
||||||
// When interruptable, check pending signals first
|
// When interruptable, check pending signals first
|
||||||
struct thread* thread = thread_get_current_thread();
|
struct thread* thread = thread_get_current_thread();
|
||||||
@@ -162,32 +139,28 @@ PrivateConditionVariableEntry::Wait(uint32 flags)
|
|||||||
&& (thread->sig_pending & ~thread->sig_block_mask) != 0)
|
&& (thread->sig_pending & ~thread->sig_block_mask) != 0)
|
||||||
|| ((flags & B_KILL_CAN_INTERRUPT)
|
|| ((flags & B_KILL_CAN_INTERRUPT)
|
||||||
&& (thread->sig_pending & KILL_SIGNALS))) {
|
&& (thread->sig_pending & KILL_SIGNALS))) {
|
||||||
// remove all of the thread's entries from their variables
|
// remove entry from the variables
|
||||||
entry = firstEntry;
|
_Remove();
|
||||||
while (entry) {
|
|
||||||
entry->_Remove();
|
|
||||||
entry = entry->fThreadNext;
|
|
||||||
}
|
|
||||||
return B_INTERRUPTED;
|
return B_INTERRUPTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait
|
// wait
|
||||||
thread->next_state = B_THREAD_WAITING;
|
thread->next_state = B_THREAD_WAITING;
|
||||||
thread->condition_variable_entry = firstEntry;
|
thread->condition_variable_entry = this;
|
||||||
thread->sem.blocking = -1;
|
thread->sem.blocking = -1;
|
||||||
|
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
scheduler_reschedule();
|
scheduler_reschedule();
|
||||||
threadLocker.Unlock();
|
threadLocker.Unlock();
|
||||||
|
|
||||||
return firstEntry->fResult;
|
return fResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
PrivateConditionVariableEntry::Wait(const void* object, uint32 flags)
|
PrivateConditionVariableEntry::Wait(const void* object, uint32 flags)
|
||||||
{
|
{
|
||||||
if (Add(object, NULL))
|
if (Add(object))
|
||||||
return Wait(flags);
|
return Wait(flags);
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
@@ -199,28 +172,9 @@ PrivateConditionVariableEntry::Wait(const void* object, uint32 flags)
|
|||||||
void
|
void
|
||||||
PrivateConditionVariableEntry::_Remove()
|
PrivateConditionVariableEntry::_Remove()
|
||||||
{
|
{
|
||||||
if (!fVariable)
|
if (fVariable) {
|
||||||
return;
|
fVariable->fEntries.Remove(this);
|
||||||
|
|
||||||
// fast path, if we're first in queue
|
|
||||||
if (this == fVariable->fEntries) {
|
|
||||||
fVariable->fEntries = fVariableNext;
|
|
||||||
fVariableNext = NULL;
|
|
||||||
fVariable = NULL;
|
fVariable = NULL;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// we're not the first entry -- find our previous entry
|
|
||||||
PrivateConditionVariableEntry* entry = fVariable->fEntries;
|
|
||||||
while (entry->fVariableNext) {
|
|
||||||
if (this == entry->fVariableNext) {
|
|
||||||
entry->fVariableNext = fVariableNext;
|
|
||||||
fVariableNext = NULL;
|
|
||||||
fVariable = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = entry->fVariableNext;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,12 +206,7 @@ PrivateConditionVariable::ListAll()
|
|||||||
ConditionVariableHash::Iterator it(&sConditionVariableHash);
|
ConditionVariableHash::Iterator it(&sConditionVariableHash);
|
||||||
while (PrivateConditionVariable* variable = it.Next()) {
|
while (PrivateConditionVariable* variable = it.Next()) {
|
||||||
// count waiting threads
|
// count waiting threads
|
||||||
int count = 0;
|
int count = variable->fEntries.Size();
|
||||||
PrivateConditionVariableEntry* entry = variable->fEntries;
|
|
||||||
while (entry) {
|
|
||||||
count++;
|
|
||||||
entry = entry->fVariableNext;
|
|
||||||
}
|
|
||||||
|
|
||||||
kprintf("%p %p %-20s %15d\n", variable, variable->fObject,
|
kprintf("%p %p %-20s %15d\n", variable, variable->fObject,
|
||||||
variable->fObjectType, count);
|
variable->fObjectType, count);
|
||||||
@@ -271,10 +220,10 @@ PrivateConditionVariable::Dump() const
|
|||||||
kprintf("condition variable %p\n", this);
|
kprintf("condition variable %p\n", this);
|
||||||
kprintf(" object: %p (%s)\n", fObject, fObjectType);
|
kprintf(" object: %p (%s)\n", fObject, fObjectType);
|
||||||
kprintf(" threads:");
|
kprintf(" threads:");
|
||||||
PrivateConditionVariableEntry* entry = fEntries;
|
|
||||||
while (entry) {
|
for (EntryList::ConstIterator it = fEntries.GetIterator();
|
||||||
|
PrivateConditionVariableEntry* entry = it.Next();) {
|
||||||
kprintf(" %ld", entry->fThread->id);
|
kprintf(" %ld", entry->fThread->id);
|
||||||
entry = entry->fVariableNext;
|
|
||||||
}
|
}
|
||||||
kprintf("\n");
|
kprintf("\n");
|
||||||
}
|
}
|
||||||
@@ -287,7 +236,7 @@ PrivateConditionVariable::Publish(const void* object, const char* objectType)
|
|||||||
|
|
||||||
fObject = object;
|
fObject = object;
|
||||||
fObjectType = objectType;
|
fObjectType = objectType;
|
||||||
fEntries = NULL;
|
new(&fEntries) EntryList;
|
||||||
|
|
||||||
InterruptsLocker _;
|
InterruptsLocker _;
|
||||||
SpinLocker locker(sConditionVariablesLock);
|
SpinLocker locker(sConditionVariablesLock);
|
||||||
@@ -320,7 +269,7 @@ PrivateConditionVariable::Unpublish(bool threadsLocked)
|
|||||||
fObject = NULL;
|
fObject = NULL;
|
||||||
fObjectType = NULL;
|
fObjectType = NULL;
|
||||||
|
|
||||||
if (fEntries)
|
if (!fEntries.IsEmpty())
|
||||||
_Notify(true, B_ENTRY_NOT_FOUND);
|
_Notify(true, B_ENTRY_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,7 +291,7 @@ PrivateConditionVariable::Notify(bool all, bool threadsLocked)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (fEntries)
|
if (!fEntries.IsEmpty())
|
||||||
_Notify(all, B_OK);
|
_Notify(all, B_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,9 +303,7 @@ void
|
|||||||
PrivateConditionVariable::_Notify(bool all, status_t result)
|
PrivateConditionVariable::_Notify(bool all, status_t result)
|
||||||
{
|
{
|
||||||
// dequeue and wake up the blocked threads
|
// dequeue and wake up the blocked threads
|
||||||
while (PrivateConditionVariableEntry* entry = fEntries) {
|
while (PrivateConditionVariableEntry* entry = fEntries.RemoveHead()) {
|
||||||
fEntries = entry->fVariableNext;
|
|
||||||
entry->fVariableNext = NULL;
|
|
||||||
entry->fVariable = NULL;
|
entry->fVariable = NULL;
|
||||||
|
|
||||||
struct thread* thread = entry->fThread;
|
struct thread* thread = entry->fThread;
|
||||||
@@ -364,19 +311,6 @@ PrivateConditionVariable::_Notify(bool all, status_t result)
|
|||||||
if (thread->condition_variable_entry != NULL)
|
if (thread->condition_variable_entry != NULL)
|
||||||
thread->condition_variable_entry->fResult = result;
|
thread->condition_variable_entry->fResult = result;
|
||||||
|
|
||||||
// remove other entries of this thread from their respective variables
|
|
||||||
PrivateConditionVariableEntry* otherEntry = entry->fThreadPrevious;
|
|
||||||
while (otherEntry) {
|
|
||||||
otherEntry->_Remove();
|
|
||||||
otherEntry = otherEntry->fThreadPrevious;
|
|
||||||
}
|
|
||||||
|
|
||||||
otherEntry = entry->fThreadNext;
|
|
||||||
while (otherEntry) {
|
|
||||||
otherEntry->_Remove();
|
|
||||||
otherEntry = otherEntry->fThreadNext;
|
|
||||||
}
|
|
||||||
|
|
||||||
// wake up the thread
|
// wake up the thread
|
||||||
thread->condition_variable_entry = NULL;
|
thread->condition_variable_entry = NULL;
|
||||||
if (thread->state == B_THREAD_WAITING)
|
if (thread->state == B_THREAD_WAITING)
|
||||||
@@ -415,12 +349,8 @@ condition_variable_interrupt_thread(struct thread* thread)
|
|||||||
|
|
||||||
PrivateConditionVariableEntry::Private(*entry).SetResult(B_INTERRUPTED);
|
PrivateConditionVariableEntry::Private(*entry).SetResult(B_INTERRUPTED);
|
||||||
|
|
||||||
// remove all of the thread's entries from their variables
|
// remove entry from its variable
|
||||||
ASSERT(entry->ThreadPrevious() == NULL);
|
PrivateConditionVariableEntry::Private(*entry).Remove();
|
||||||
while (entry) {
|
|
||||||
PrivateConditionVariableEntry::Private(*entry).Remove();
|
|
||||||
entry = entry->ThreadNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
// wake up the thread
|
// wake up the thread
|
||||||
thread->condition_variable_entry = NULL;
|
thread->condition_variable_entry = NULL;
|
||||||
|
|||||||
Reference in New Issue
Block a user