Kernel: Require a reason to be passed to Thread::wait_on

The Lock class still permits no reason, but for everything else
require a reason to be passed to Thread::wait_on. This makes it
easier to diagnose why a Thread is in Queued state.
This commit is contained in:
Tom 2020-07-04 15:55:20 -06:00 committed by Andreas Kling
parent 0c4b0c0312
commit 788b2d64c6
Notes: sideshowbarker 2024-07-19 05:07:41 +09:00
11 changed files with 19 additions and 11 deletions

View File

@ -177,7 +177,7 @@ static void print_ide_status(u8 status)
void PATAChannel::wait_for_irq()
{
Thread::current()->wait_on(m_irq_queue);
Thread::current()->wait_on(m_irq_queue, "PATAChannel");
disable_irq();
}

View File

@ -222,7 +222,7 @@ void SB16::handle_irq(const RegisterState&)
void SB16::wait_for_irq()
{
Thread::current()->wait_on(m_irq_queue);
Thread::current()->wait_on(m_irq_queue, "SB16");
disable_irq();
}

View File

@ -67,7 +67,7 @@ void Lock::lock(Mode mode)
return;
}
timeval* timeout = nullptr;
current_thread->wait_on(m_queue, timeout, &m_lock, m_holder, m_name);
current_thread->wait_on(m_queue, m_name, timeout, &m_lock, m_holder);
} else if (Processor::current().in_critical()) {
// If we're in a critical section and trying to lock, no context
// switch will happen, so yield.

View File

@ -416,7 +416,7 @@ void E1000NetworkAdapter::send_raw(const u8* data, size_t length)
sti();
break;
}
Thread::current()->wait_on(m_wait_queue);
Thread::current()->wait_on(m_wait_queue, "E1000NetworkAdapter");
}
#ifdef E1000_DEBUG
klog() << "E1000: Sent packet, status is now " << String::format("%b", descriptor.status) << "!";

View File

@ -113,7 +113,7 @@ void NetworkTask_main()
for (;;) {
size_t packet_size = dequeue_packet(buffer, buffer_size);
if (!packet_size) {
Thread::current()->wait_on(packet_wait_queue);
Thread::current()->wait_on(packet_wait_queue, "NetworkTask");
continue;
}
if (packet_size < sizeof(EthernetFrameHeader)) {

View File

@ -4846,7 +4846,7 @@ int Process::sys$futex(const Syscall::SC_futex_params* user_params)
}
// FIXME: This is supposed to be interruptible by a signal, but right now WaitQueue cannot be interrupted.
Thread::BlockResult result = Thread::current()->wait_on(wait_queue, optional_timeout);
Thread::BlockResult result = Thread::current()->wait_on(wait_queue, "Futex", optional_timeout);
if (result == Thread::BlockResult::InterruptedByTimeout) {
return -ETIMEDOUT;
}

View File

@ -71,7 +71,7 @@ KernelRng::KernelRng()
void KernelRng::wait_for_entropy()
{
if (!resource().is_ready()) {
Thread::current()->wait_on(m_seed_queue);
Thread::current()->wait_on(m_seed_queue, "KernelRng");
}
}

View File

@ -402,7 +402,7 @@ bool Scheduler::pick_next()
#ifdef SCHEDULER_RUNNABLE_DEBUG
dbg() << "Non-runnables:";
Scheduler::for_each_nonrunnable([](Thread& thread) -> IterationDecision {
dbg() << " " << String::format("%-12s", thread.state_string()) << " " << thread << " @ " << String::format("%w", thread.tss().cs) << ":" << String::format("%x", thread.tss().eip);
dbg() << " " << String::format("%-12s", thread.state_string()) << " " << thread << " @ " << String::format("%w", thread.tss().cs) << ":" << String::format("%x", thread.tss().eip) << " Reason: " << (thread.wait_reason() ? thread.wait_reason() : "none");
return IterationDecision::Continue;
});

View File

@ -34,7 +34,7 @@ void FinalizerTask::spawn()
Process::create_kernel_process(g_finalizer, "FinalizerTask", [] {
Thread::current()->set_priority(THREAD_PRIORITY_LOW);
for (;;) {
Thread::current()->wait_on(*g_finalizer_wait_queue);
Thread::current()->wait_on(*g_finalizer_wait_queue, "FinalizerTask");
bool expected = true;
if (g_finalizer_has_work.compare_exchange_strong(expected, false, AK::MemoryOrder::memory_order_acq_rel))

View File

@ -852,7 +852,7 @@ const LogStream& operator<<(const LogStream& stream, const Thread& value)
return stream << value.process().name() << "(" << value.pid() << ":" << value.tid() << ")";
}
Thread::BlockResult Thread::wait_on(WaitQueue& queue, timeval* timeout, Atomic<bool>* lock, Thread* beneficiary, const char* reason)
Thread::BlockResult Thread::wait_on(WaitQueue& queue, const char* reason, timeval* timeout, Atomic<bool>* lock, Thread* beneficiary)
{
TimerId timer_id {};
u32 prev_crit;
@ -864,6 +864,7 @@ Thread::BlockResult Thread::wait_on(WaitQueue& queue, timeval* timeout, Atomic<b
if (lock)
*lock = false;
set_state(State::Queued);
m_wait_reason = reason;
queue.enqueue(*Thread::current());
@ -899,6 +900,7 @@ void Thread::wake_from_queue()
{
ScopedSpinLock lock(g_scheduler_lock);
ASSERT(state() == State::Queued);
m_wait_reason = nullptr;
if (this != Thread::current())
set_state(State::Runnable);
else

View File

@ -340,7 +340,7 @@ public:
return block<ConditionBlocker>(state_string, move(condition));
}
BlockResult wait_on(WaitQueue& queue, timeval* timeout = nullptr, Atomic<bool>* lock = nullptr, Thread* beneficiary = nullptr, const char* reason = nullptr);
BlockResult wait_on(WaitQueue& queue, const char* reason, timeval* timeout = nullptr, Atomic<bool>* lock = nullptr, Thread* beneficiary = nullptr);
void wake_from_queue();
void unblock();
@ -433,6 +433,11 @@ public:
m_ipv4_socket_write_bytes += bytes;
}
const char* wait_reason() const
{
return m_wait_reason;
}
Thread* clone(Process&);
template<typename Callback>
@ -484,6 +489,7 @@ private:
size_t m_thread_specific_region_size { 0 };
SignalActionData m_signal_action_data[32];
Blocker* m_blocker { nullptr };
const char* m_wait_reason { nullptr };
bool m_is_joinable { true };
Thread* m_joiner { nullptr };