mirror of
https://github.com/fergalmoran/ladybird.git
synced 2026-05-05 02:38:57 +00:00
Kernel: Add timeout support to Thread::wait_on
This change plumbs a new optional timeout option to wait_on. The timeout is enabled by enqueing a timer on the timer queue while we are waiting. We can then see if we were woken up or timed out by checking if we are still on the wait queue or not.
This commit is contained in:
committed by
Andreas Kling
parent
1d68837456
commit
faf15e3721
@@ -34,6 +34,7 @@
|
||||
#include <Kernel/Scheduler.h>
|
||||
#include <Kernel/Thread.h>
|
||||
#include <Kernel/ThreadTracer.h>
|
||||
#include <Kernel/TimerQueue.h>
|
||||
#include <Kernel/VM/MemoryManager.h>
|
||||
#include <Kernel/VM/PageDirectory.h>
|
||||
#include <Kernel/VM/ProcessPagingScope.h>
|
||||
@@ -575,8 +576,7 @@ ShouldUnblockThread Thread::dispatch_signal(u8 signal)
|
||||
|
||||
m_signal_mask |= new_signal_mask;
|
||||
|
||||
auto setup_stack = [&]<typename ThreadState>(ThreadState state, u32 * stack)
|
||||
{
|
||||
auto setup_stack = [&]<typename ThreadState>(ThreadState state, u32* stack) {
|
||||
u32 old_esp = *stack;
|
||||
u32 ret_eip = state.eip;
|
||||
u32 ret_eflags = state.eflags;
|
||||
@@ -884,7 +884,7 @@ const LogStream& operator<<(const LogStream& stream, const Thread& value)
|
||||
return stream << value.process().name() << "(" << value.pid() << ":" << value.tid() << ")";
|
||||
}
|
||||
|
||||
void Thread::wait_on(WaitQueue& queue, Atomic<bool>* lock, Thread* beneficiary, const char* reason)
|
||||
Thread::BlockResult Thread::wait_on(WaitQueue& queue, timeval* timeout, Atomic<bool>* lock, Thread* beneficiary, const char* reason)
|
||||
{
|
||||
cli();
|
||||
bool did_unlock = unlock_process_if_locked();
|
||||
@@ -892,6 +892,14 @@ void Thread::wait_on(WaitQueue& queue, Atomic<bool>* lock, Thread* beneficiary,
|
||||
*lock = false;
|
||||
set_state(State::Queued);
|
||||
queue.enqueue(*current);
|
||||
|
||||
u64 timer_id = 0;
|
||||
if (timeout) {
|
||||
timer_id = TimerQueue::the().add_timer(*timeout, [&]() {
|
||||
wake_from_queue();
|
||||
});
|
||||
}
|
||||
|
||||
// Yield and wait for the queue to wake us up again.
|
||||
if (beneficiary)
|
||||
Scheduler::donate_to(beneficiary, reason);
|
||||
@@ -900,6 +908,14 @@ void Thread::wait_on(WaitQueue& queue, Atomic<bool>* lock, Thread* beneficiary,
|
||||
// We've unblocked, relock the process if needed and carry on.
|
||||
if (did_unlock)
|
||||
relock_process();
|
||||
|
||||
BlockResult result = m_wait_queue_node.is_in_list() ? BlockResult::InterruptedByTimeout : BlockResult::WokeNormally;
|
||||
|
||||
// Make sure we cancel the timer if woke normally.
|
||||
if (timeout && result == BlockResult::WokeNormally)
|
||||
TimerQueue::the().cancel_timer(timer_id);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Thread::wake_from_queue()
|
||||
|
||||
Reference in New Issue
Block a user