From 42db1e8899fc74bd8b48b9f130c6abd74f60382d Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Sat, 18 Feb 2023 17:21:39 -0800 Subject: [PATCH] [kernel] Add lock-releasing version of thread::block() Add a version of thread::block() that takes a lock and releases it after marking the thread as unready, but before calling the scheduler. Use this version of block() in the wait_queue. --- src/kernel/objects/thread.cpp | 12 ++++++++++++ src/kernel/objects/thread.h | 7 ++++++- src/kernel/wait_queue.cpp | 14 ++++++++++---- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/kernel/objects/thread.cpp b/src/kernel/objects/thread.cpp index 351b85e..b9b0f2f 100644 --- a/src/kernel/objects/thread.cpp +++ b/src/kernel/objects/thread.cpp @@ -52,6 +52,18 @@ thread::block() return m_wake_value; } +uint64_t +thread::block(util::scoped_lock &lock) +{ + kassert(current_cpu().thread == this, + "unlocking block() called on non-current thread"); + + clear_state(state::ready); + lock.release(); + scheduler::get().schedule(); + return m_wake_value; +} + j6_status_t thread::join() { diff --git a/src/kernel/objects/thread.h b/src/kernel/objects/thread.h index cc320af..344b735 100644 --- a/src/kernel/objects/thread.h +++ b/src/kernel/objects/thread.h @@ -96,9 +96,14 @@ public: inline void set_priority(uint8_t p) { if (!constant()) m_tcb.priority = p; } /// Block this thread, waiting for a value - /// \returns The value passed to wake() + /// \returns The value passed to wake() uint64_t block(); + /// Block this thread, waiting for a value + /// \arg held A held lock to unlock when blocking + /// \returns The value passed to wake() + uint64_t block(util::scoped_lock &held); + /// Block the calling thread until this thread exits j6_status_t join(); diff --git a/src/kernel/wait_queue.cpp b/src/kernel/wait_queue.cpp index a5399bf..faa812d 100644 --- a/src/kernel/wait_queue.cpp +++ b/src/kernel/wait_queue.cpp @@ -6,6 +6,7 @@ wait_queue::~wait_queue() { clear(); } void wait_queue::add_thread(obj::thread *t) { + kassert(t, "Adding a null thread to the wait queue"); util::scoped_lock lock {m_lock}; t->handle_retain(); m_threads.push_back(t); @@ -15,8 +16,12 @@ void wait_queue::wait() { obj::thread ¤t = obj::thread::current(); - add_thread(¤t); - current.block(); + + util::scoped_lock lock {m_lock}; + current.handle_retain(); + m_threads.push_back(¤t); + + current.block(lock); } void @@ -54,9 +59,10 @@ void wait_queue::clear(uint64_t value) { util::scoped_lock lock {m_lock}; - for (auto *t : m_threads) { + while (!m_threads.empty()) { + obj::thread *t = pop_next_unlocked(); + kassert(t, "Null thread in the wait queue"); if (!t->exited()) t->wake(value); t->handle_release(); } - m_threads.clear(); }