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:
Ingo Weinhold
2008-04-20 15:19:48 +00:00
parent 66aac81e98
commit 8db2e37492
2 changed files with 35 additions and 114 deletions
+10 -19
View File
@@ -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);
} }
+25 -95
View File
@@ -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;