فهرست منبع

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.
Tom 5 سال پیش
والد
کامیت
788b2d64c6

+ 1 - 1
Kernel/Devices/PATAChannel.cpp

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

+ 1 - 1
Kernel/Devices/SB16.cpp

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

+ 1 - 1
Kernel/Lock.cpp

@@ -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.

+ 1 - 1
Kernel/Net/E1000NetworkAdapter.cpp

@@ -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) << "!";

+ 1 - 1
Kernel/Net/NetworkTask.cpp

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

+ 1 - 1
Kernel/Process.cpp

@@ -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;
         }

+ 1 - 1
Kernel/Random.cpp

@@ -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");
     }
 }
 

+ 1 - 1
Kernel/Scheduler.cpp

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

+ 1 - 1
Kernel/Tasks/FinalizerTask.cpp

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

+ 3 - 1
Kernel/Thread.cpp

@@ -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

+ 7 - 1
Kernel/Thread.h

@@ -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 };