Bladeren bron

Kernel: Port wait to ThreadBlocker

Robin Burchell 6 jaren geleden
bovenliggende
commit
782e4ee6e1
4 gewijzigde bestanden met toevoegingen van 43 en 31 verwijderingen
  1. 4 5
      Kernel/Process.cpp
  2. 29 20
      Kernel/Scheduler.cpp
  3. 0 2
      Kernel/Thread.cpp
  4. 10 4
      Kernel/Thread.h

+ 4 - 5
Kernel/Process.cpp

@@ -1441,16 +1441,15 @@ pid_t Process::sys$waitpid(pid_t waitee, int* wstatus, int options)
         }
     }
 
-    current->m_waitee_pid = waitee;
-    current->m_wait_options = options;
-    current->block(Thread::State::BlockedWait);
+    pid_t waitee_pid = waitee;
+    current->block(*new Thread::ThreadBlockerWait(options, waitee_pid));
     if (current->m_was_interrupted_while_blocked)
         return -EINTR;
 
     InterruptDisabler disabler;
 
     // NOTE: If waitee was -1, m_waitee_pid will have been filled in by the scheduler.
-    Process* waitee_process = Process::from_pid(current->m_waitee_pid);
+    Process* waitee_process = Process::from_pid(waitee_pid);
     ASSERT(waitee_process);
     if (waitee_process->is_dead()) {
         exit_status = reap(*waitee_process);
@@ -1458,7 +1457,7 @@ pid_t Process::sys$waitpid(pid_t waitee, int* wstatus, int options)
         ASSERT(waitee_process->main_thread().state() == Thread::State::Stopped);
         exit_status = 0x7f;
     }
-    return current->m_waitee_pid;
+    return waitee_pid;
 }
 
 enum class KernelMemoryCheckResult {

+ 29 - 20
Kernel/Scheduler.cpp

@@ -172,11 +172,39 @@ bool Thread::ThreadBlockerSelect::should_unblock(Thread& thread, time_t now_sec,
     return false;
 }
 
+Thread::ThreadBlockerWait::ThreadBlockerWait(int wait_options, pid_t& waitee_pid)
+    : m_wait_options(wait_options)
+    , m_waitee_pid(waitee_pid)
+{
+}
+
+bool Thread::ThreadBlockerWait::should_unblock(Thread& thread, time_t, long)
+{
+    bool should_unblock = false;
+    thread.process().for_each_child([&](Process& child) {
+        if (m_waitee_pid != -1 && m_waitee_pid != child.pid())
+            return IterationDecision::Continue;
+
+        bool child_exited = child.is_dead();
+        bool child_stopped = child.main_thread().state() == Thread::State::Stopped;
+
+        bool wait_finished = ((m_wait_options & WEXITED) && child_exited)
+            || ((m_wait_options & WSTOPPED) && child_stopped);
+
+        if (!wait_finished)
+            return IterationDecision::Continue;
+
+        m_waitee_pid = child.pid();
+        should_unblock = true;
+        return IterationDecision::Break;
+    });
+    return should_unblock;
+}
+
 // Called by the scheduler on threads that are blocked for some reason.
 // Make a decision as to whether to unblock them or not.
 void Thread::consider_unblock(time_t now_sec, long now_usec)
 {
-    auto& process = this->process();
     switch (state()) {
     case Thread::__Begin_Blocked_States__:
     case Thread::__End_Blocked_States__:
@@ -191,25 +219,6 @@ void Thread::consider_unblock(time_t now_sec, long now_usec)
     case Thread::BlockedSignal:
         /* don't know, don't care */
         return;
-    case Thread::BlockedWait:
-        process.for_each_child([&](Process& child) {
-            if (waitee_pid() != -1 && waitee_pid() != child.pid())
-                return IterationDecision::Continue;
-
-            bool child_exited = child.is_dead();
-            bool child_stopped = child.main_thread().state() == Thread::State::Stopped;
-
-            bool wait_finished = ((m_wait_options & WEXITED) && child_exited)
-                || ((m_wait_options & WSTOPPED) && child_stopped);
-
-            if (!wait_finished)
-                return IterationDecision::Continue;
-
-            m_waitee_pid = child.pid();
-            unblock();
-            return IterationDecision::Break;
-        });
-        return;
     case Thread::BlockedCondition:
         ASSERT(m_blocker);
         if (m_blocker->should_unblock(*this, now_sec, now_usec)) {

+ 0 - 2
Kernel/Thread.cpp

@@ -162,8 +162,6 @@ const char* to_string(Thread::State state)
         return "Skip1";
     case Thread::Skip0SchedulerPasses:
         return "Skip0";
-    case Thread::BlockedWait:
-        return "Wait";
     case Thread::BlockedSignal:
         return "Signal";
     case Thread::BlockedLurking:

+ 10 - 4
Kernel/Thread.h

@@ -65,7 +65,6 @@ public:
 
         __Begin_Blocked_States__,
         BlockedLurking,
-        BlockedWait,
         BlockedSignal,
         BlockedCondition,
         __End_Blocked_States__
@@ -147,6 +146,16 @@ public:
         const Vector<int>& m_select_exceptional_fds;
     };
 
+    class ThreadBlockerWait : public ThreadBlocker {
+    public:
+        ThreadBlockerWait(int wait_options, pid_t& waitee_pid);
+        virtual bool should_unblock(Thread&, time_t, long) override;
+
+    private:
+        int m_wait_options { 0 };
+        pid_t& m_waitee_pid;
+    };
+
     void did_schedule() { ++m_times_scheduled; }
     u32 times_scheduled() const { return m_times_scheduled; }
 
@@ -164,7 +173,6 @@ public:
     TSS32& tss() { return m_tss; }
     State state() const { return m_state; }
     u32 ticks() const { return m_ticks; }
-    pid_t waitee_pid() const { return m_waitee_pid; }
 
     u64 sleep(u32 ticks);
     void block(Thread::State);
@@ -250,8 +258,6 @@ private:
     u32 m_kernel_stack_base { 0 };
     RefPtr<Region> m_kernel_stack_region;
     RefPtr<Region> m_kernel_stack_for_signal_handler_region;
-    pid_t m_waitee_pid { -1 };
-    int m_wait_options { 0 };
     SignalActionData m_signal_action_data[32];
     Region* m_signal_stack_user_region { nullptr };
     OwnPtr<ThreadBlocker> m_blocker;