diff --git a/headers/private/kernel/condition_variable.h b/headers/private/kernel/condition_variable.h index 1b733b910b..7943ca7fed 100644 --- a/headers/private/kernel/condition_variable.h +++ b/headers/private/kernel/condition_variable.h @@ -8,6 +8,8 @@ #include +#include + #ifdef __cplusplus #include @@ -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; diff --git a/src/system/kernel/condition_variable.cpp b/src/system/kernel/condition_variable.cpp index 43be0e2e95..3a5ab79fc0 100644 --- a/src/system/kernel/condition_variable.cpp +++ b/src/system/kernel/condition_variable.cpp @@ -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();