[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:
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user