* Fixed incorrect check in condition_variable_interrupt_thread().
Condition variables would never be interrupted. * ConditionVariableEntry::Add() did not correctly insert the entry into the per-thread list of entries (the next link of the previous entry was not adjusted), which could leave the entry unnotified when the previous entry was notified, thus leaving it in the respective condition variable's list after the end of its life time. This should fix a crashing bug I rarely encountered. * Added debug checks in the PrivateConditionVariableEntry constructor/destructor that should have helped me to find forementioned bug hours earlier, had I been bright enough to realize that I didn't include <debug.h> and those KDEBUG guarded checks were never executed. :-/ git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22151 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
667f1eeb67
commit
addece2001
@ -8,6 +8,8 @@
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <util/OpenHashTable.h>
|
||||
@ -18,11 +20,28 @@ class PrivateConditionVariable;
|
||||
|
||||
struct PrivateConditionVariableEntry {
|
||||
public:
|
||||
#if KDEBUG
|
||||
inline PrivateConditionVariableEntry()
|
||||
: fVariable(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
inline ~PrivateConditionVariableEntry()
|
||||
{
|
||||
if (fVariable != NULL) {
|
||||
panic("Destroying condition variable entry %p, but it's still "
|
||||
"attached to variable %p\n", this, fVariable);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
inline PrivateConditionVariable* Variable() const
|
||||
{ return fVariable; }
|
||||
|
||||
inline PrivateConditionVariableEntry* ThreadNext() const
|
||||
{ return fThreadNext; }
|
||||
inline PrivateConditionVariableEntry* ThreadPrevious() const
|
||||
{ return fThreadPrevious; }
|
||||
|
||||
class Private;
|
||||
|
||||
|
@ -107,6 +107,8 @@ PrivateConditionVariableEntry::Add(const void* object,
|
||||
if (threadNext) {
|
||||
fThreadPrevious = threadNext->fThreadPrevious;
|
||||
threadNext->fThreadPrevious = this;
|
||||
if (fThreadPrevious)
|
||||
fThreadPrevious->fThreadNext = this;
|
||||
} else
|
||||
fThreadPrevious = NULL;
|
||||
|
||||
@ -399,7 +401,7 @@ condition_variable_interrupt_thread(struct thread* thread)
|
||||
// re-get the thread and do the checks again
|
||||
thread = thread_get_thread_struct_locked(threadID);
|
||||
|
||||
if (thread != NULL || thread->state != B_THREAD_WAITING
|
||||
if (thread == NULL || thread->state != B_THREAD_WAITING
|
||||
|| thread->condition_variable_entry == NULL) {
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
@ -417,6 +419,7 @@ condition_variable_interrupt_thread(struct thread* thread)
|
||||
PrivateConditionVariableEntry::Private(*entry).SetResult(B_INTERRUPTED);
|
||||
|
||||
// remove all of the thread's entries from their variables
|
||||
ASSERT(entry->ThreadPrevious() == NULL);
|
||||
while (entry) {
|
||||
PrivateConditionVariableEntry::Private(*entry).Remove();
|
||||
entry = entry->ThreadNext();
|
||||
|
Loading…
Reference in New Issue
Block a user