diff --git a/src/kernel/objects/channel.cpp b/src/kernel/objects/channel.cpp index 71b3bc4..9111910 100644 --- a/src/kernel/objects/channel.cpp +++ b/src/kernel/objects/channel.cpp @@ -76,6 +76,7 @@ void channel::close() { util::scoped_lock lock {m_close_lock}; + m_queue.clear(); g_kernel_buffers.return_section(m_data); m_closed = true; } diff --git a/src/kernel/objects/mailbox.cpp b/src/kernel/objects/mailbox.cpp index 63f6876..8a6fe08 100644 --- a/src/kernel/objects/mailbox.cpp +++ b/src/kernel/objects/mailbox.cpp @@ -41,8 +41,8 @@ mailbox::close() for (auto &p : m_pending) { delete p.val.msg; - p.val.sender->wake(no_message); } + m_queue.clear(); } void diff --git a/src/kernel/wait_queue.cpp b/src/kernel/wait_queue.cpp index 9920830..84584e9 100644 --- a/src/kernel/wait_queue.cpp +++ b/src/kernel/wait_queue.cpp @@ -1,14 +1,7 @@ #include "objects/thread.h" #include "wait_queue.h" -wait_queue::~wait_queue() -{ - util::scoped_lock lock {m_lock}; - for (auto *t : m_threads) { - if (!t->exited()) t->wake(); - t->handle_release(); - } -} +wait_queue::~wait_queue() { clear(); } void wait_queue::add_thread(obj::thread *t) @@ -23,7 +16,7 @@ wait_queue::pop_exited() { while (!m_threads.empty()) { obj::thread *t = m_threads.first(); - if (!t->exited()) + if (!t->exited() && !t->ready()) break; m_threads.pop_front(); @@ -48,3 +41,13 @@ wait_queue::pop_next_unlocked() return nullptr; return m_threads.pop_front(); } + +void +wait_queue::clear() +{ + util::scoped_lock lock {m_lock}; + for (auto *t : m_threads) { + if (!t->exited()) t->wake(); + t->handle_release(); + } +} diff --git a/src/kernel/wait_queue.h b/src/kernel/wait_queue.h index a440f83..14fe3b1 100644 --- a/src/kernel/wait_queue.h +++ b/src/kernel/wait_queue.h @@ -37,6 +37,9 @@ public: /// Get the spinlock to lock this queue util::spinlock & get_lock() { return m_lock; } + /// Wake and clear out all threads. + void clear(); + private: /// Get rid of any exited threads that are next /// in the queue. Caller must hold the queue lock.