[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.
This commit is contained in:
Justin C. Miller
2023-02-18 17:21:39 -08:00
parent 38ca7004a6
commit 42db1e8899
3 changed files with 28 additions and 5 deletions

View File

@@ -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()
{

View File

@@ -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();

View File

@@ -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 &current = obj::thread::current();
add_thread(&current);
current.block();
util::scoped_lock lock {m_lock};
current.handle_retain();
m_threads.push_back(&current);
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();
}