Explorar el Código

Kernel: Port select to ThreadBlocker

Robin Burchell hace 6 años
padre
commit
4f9ae9b970
Se han modificado 4 ficheros con 86 adiciones y 68 borrados
  1. 28 24
      Kernel/Process.cpp
  2. 37 28
      Kernel/Scheduler.cpp
  3. 0 2
      Kernel/Thread.cpp
  4. 21 14
      Kernel/Thread.h

+ 28 - 24
Kernel/Process.cpp

@@ -1792,13 +1792,17 @@ int Process::sys$select(const Syscall::SC_select_params* params)
     if (params->nfds < 0)
         return -EINVAL;
 
+    timeval timeout;
+    bool select_has_timeout = false;
     if (params->timeout && (params->timeout->tv_sec || params->timeout->tv_usec)) {
-        timeval_add(kgettimeofday(), *params->timeout, current->m_select_timeout);
-        current->m_select_has_timeout = true;
-    } else {
-        current->m_select_has_timeout = false;
+        timeval_add(kgettimeofday(), *params->timeout, timeout);
+        select_has_timeout = true;
     }
 
+    Vector<int> rfds;
+    Vector<int> wfds;
+    Vector<int> efds;
+
     auto transfer_fds = [&](auto* fds, auto& vector) -> int {
         vector.clear_with_capacity();
         if (!fds)
@@ -1812,19 +1816,19 @@ int Process::sys$select(const Syscall::SC_select_params* params)
         }
         return 0;
     };
-    if (int error = transfer_fds(params->writefds, current->m_select_write_fds))
+    if (int error = transfer_fds(params->writefds, wfds))
         return error;
-    if (int error = transfer_fds(params->readfds, current->m_select_read_fds))
+    if (int error = transfer_fds(params->readfds, rfds))
         return error;
-    if (int error = transfer_fds(params->exceptfds, current->m_select_exceptional_fds))
+    if (int error = transfer_fds(params->exceptfds, efds))
         return error;
 
 #if defined(DEBUG_IO) || defined(DEBUG_POLL_SELECT)
-    dbgprintf("%s<%u> selecting on (read:%u, write:%u), timeout=%p\n", name().characters(), pid(), current->m_select_read_fds.size(), current->m_select_write_fds.size(), params->timeout);
+    dbgprintf("%s<%u> selecting on (read:%u, write:%u), timeout=%p\n", name().characters(), pid(), rfds.size(), wfds.size(), params->timeout);
 #endif
 
-    if (!params->timeout || current->m_select_has_timeout)
-        current->block(Thread::State::BlockedSelect);
+    if (!params->timeout || select_has_timeout)
+        current->block(*new Thread::ThreadBlockerSelect(timeout, select_has_timeout, rfds, wfds, efds));
 
     int marked_fd_count = 0;
     auto mark_fds = [&](auto* fds, auto& vector, auto should_mark) {
@@ -1838,8 +1842,8 @@ int Process::sys$select(const Syscall::SC_select_params* params)
             }
         }
     };
-    mark_fds(params->readfds, current->m_select_read_fds, [](auto& description) { return description.can_read(); });
-    mark_fds(params->writefds, current->m_select_write_fds, [](auto& description) { return description.can_write(); });
+    mark_fds(params->readfds, rfds, [](auto& description) { return description.can_read(); });
+    mark_fds(params->writefds, wfds, [](auto& description) { return description.can_write(); });
     // FIXME: We should also mark params->exceptfds as appropriate.
     return marked_fd_count;
 }
@@ -1849,15 +1853,18 @@ int Process::sys$poll(pollfd* fds, int nfds, int timeout)
     if (!validate_read_typed(fds))
         return -EFAULT;
 
-    current->m_select_write_fds.clear_with_capacity();
-    current->m_select_read_fds.clear_with_capacity();
+    Vector<int> rfds;
+    Vector<int> wfds;
+
     for (int i = 0; i < nfds; ++i) {
         if (fds[i].events & POLLIN)
-            current->m_select_read_fds.append(fds[i].fd);
+            rfds.append(fds[i].fd);
         if (fds[i].events & POLLOUT)
-            current->m_select_write_fds.append(fds[i].fd);
+            wfds.append(fds[i].fd);
     }
 
+    timeval actual_timeout;
+    bool has_timeout = false;
     if (timeout >= 0) {
         // poll is in ms, we want s/us.
         struct timeval tvtimeout;
@@ -1867,19 +1874,16 @@ int Process::sys$poll(pollfd* fds, int nfds, int timeout)
             timeout -= 1000;
         }
         tvtimeout.tv_usec = timeout * 1000;
-        timeval_add(kgettimeofday(), tvtimeout, current->m_select_timeout);
-        current->m_select_has_timeout = true;
-    } else {
-        current->m_select_has_timeout = false;
+        timeval_add(kgettimeofday(), tvtimeout, actual_timeout);
+        has_timeout = true;
     }
 
 #if defined(DEBUG_IO) || defined(DEBUG_POLL_SELECT)
-    dbgprintf("%s<%u> polling on (read:%u, write:%u), timeout=%d\n", name().characters(), pid(), current->m_select_read_fds.size(), current->m_select_write_fds.size(), timeout);
+    dbgprintf("%s<%u> polling on (read:%u, write:%u), timeout=%d\n", name().characters(), pid(), rfds.size(), wfds.size(), timeout);
 #endif
 
-    if (current->m_select_has_timeout || timeout < 0) {
-        current->block(Thread::State::BlockedSelect);
-    }
+    if (has_timeout|| timeout < 0)
+        current->block(*new Thread::ThreadBlockerSelect(actual_timeout, has_timeout, rfds, wfds, Vector<int>()));
 
     int fds_with_revents = 0;
 

+ 37 - 28
Kernel/Scheduler.cpp

@@ -65,7 +65,7 @@ Thread::ThreadBlockerAccept::ThreadBlockerAccept(const RefPtr<FileDescription>&
 {
 }
 
-bool Thread::ThreadBlockerAccept::should_unblock(time_t, long)
+bool Thread::ThreadBlockerAccept::should_unblock(Thread&, time_t, long)
 {
     auto& description = *blocked_description();
     auto& socket = *description.socket();
@@ -78,7 +78,7 @@ Thread::ThreadBlockerReceive::ThreadBlockerReceive(const RefPtr<FileDescription>
 {
 }
 
-bool Thread::ThreadBlockerReceive::should_unblock(time_t now_sec, long now_usec)
+bool Thread::ThreadBlockerReceive::should_unblock(Thread&, time_t now_sec, long now_usec)
 {
     auto& description = *blocked_description();
     auto& socket = *description.socket();
@@ -94,7 +94,7 @@ Thread::ThreadBlockerConnect::ThreadBlockerConnect(const RefPtr<FileDescription>
 {
 }
 
-bool Thread::ThreadBlockerConnect::should_unblock(time_t, long)
+bool Thread::ThreadBlockerConnect::should_unblock(Thread&, time_t, long)
 {
     auto& description = *blocked_description();
     auto& socket = *description.socket();
@@ -106,7 +106,7 @@ Thread::ThreadBlockerWrite::ThreadBlockerWrite(const RefPtr<FileDescription>& de
 {
 }
 
-bool Thread::ThreadBlockerWrite::should_unblock(time_t, long)
+bool Thread::ThreadBlockerWrite::should_unblock(Thread&, time_t, long)
 {
     return blocked_description()->can_write();
 }
@@ -116,7 +116,7 @@ Thread::ThreadBlockerRead::ThreadBlockerRead(const RefPtr<FileDescription>& desc
 {
 }
 
-bool Thread::ThreadBlockerRead::should_unblock(time_t, long)
+bool Thread::ThreadBlockerRead::should_unblock(Thread&, time_t, long)
 {
     // FIXME: Block until the amount of data wanted is available.
     return blocked_description()->can_read();
@@ -128,7 +128,7 @@ Thread::ThreadBlockerCondition::ThreadBlockerCondition(Function<bool()> &conditi
     ASSERT(m_block_until_condition);
 }
 
-bool Thread::ThreadBlockerCondition::should_unblock(time_t, long)
+bool Thread::ThreadBlockerCondition::should_unblock(Thread&, time_t, long)
 {
     return m_block_until_condition();
 }
@@ -138,11 +138,40 @@ Thread::ThreadBlockerSleep::ThreadBlockerSleep(u64 wakeup_time)
 {
 }
 
-bool Thread::ThreadBlockerSleep::should_unblock(time_t, long)
+bool Thread::ThreadBlockerSleep::should_unblock(Thread&, time_t, long)
 {
     return m_wakeup_time <= g_uptime;
 }
 
+Thread::ThreadBlockerSelect::ThreadBlockerSelect(const timeval& tv, bool select_has_timeout, const Vector<int>& read_fds, const Vector<int>& write_fds, const Vector<int>& except_fds)
+    : m_select_timeout(tv)
+    , m_select_has_timeout(select_has_timeout)
+    , m_select_read_fds(read_fds)
+    , m_select_write_fds(write_fds)
+    , m_select_exceptional_fds(except_fds)
+{
+}
+
+bool Thread::ThreadBlockerSelect::should_unblock(Thread& thread, time_t now_sec, long now_usec)
+{
+    if (m_select_has_timeout) {
+        if (now_sec > m_select_timeout.tv_sec || (now_sec == m_select_timeout.tv_sec && now_usec >= m_select_timeout.tv_usec))
+            return true;
+    }
+
+    auto& process = thread.process();
+    for (int fd : m_select_read_fds) {
+        if (process.m_fds[fd].description->can_read())
+            return true;
+    }
+    for (int fd : m_select_write_fds) {
+        if (process.m_fds[fd].description->can_write())
+            return true;
+    }
+
+    return false;
+}
+
 // 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)
@@ -181,29 +210,9 @@ void Thread::consider_unblock(time_t now_sec, long now_usec)
             return IterationDecision::Break;
         });
         return;
-    case Thread::BlockedSelect:
-        if (m_select_has_timeout) {
-            if (now_sec > m_select_timeout.tv_sec || (now_sec == m_select_timeout.tv_sec && now_usec >= m_select_timeout.tv_usec)) {
-                unblock();
-                return;
-            }
-        }
-        for (int fd : m_select_read_fds) {
-            if (process.m_fds[fd].description->can_read()) {
-                unblock();
-                return;
-            }
-        }
-        for (int fd : m_select_write_fds) {
-            if (process.m_fds[fd].description->can_write()) {
-                unblock();
-                return;
-            }
-        }
-        return;
     case Thread::BlockedCondition:
         ASSERT(m_blocker);
-        if (m_blocker->should_unblock(now_sec, now_usec)) {
+        if (m_blocker->should_unblock(*this, now_sec, now_usec)) {
             unblock();
             m_blocker = nullptr;
         }

+ 0 - 2
Kernel/Thread.cpp

@@ -166,8 +166,6 @@ const char* to_string(Thread::State state)
         return "Wait";
     case Thread::BlockedSignal:
         return "Signal";
-    case Thread::BlockedSelect:
-        return "Select";
     case Thread::BlockedLurking:
         return "Lurking";
     case Thread::BlockedCondition:

+ 21 - 14
Kernel/Thread.h

@@ -67,7 +67,6 @@ public:
         BlockedLurking,
         BlockedWait,
         BlockedSignal,
-        BlockedSelect,
         BlockedCondition,
         __End_Blocked_States__
     };
@@ -75,7 +74,7 @@ public:
     class ThreadBlocker {
     public:
         virtual ~ThreadBlocker() {}
-        virtual bool should_unblock(time_t now_s, long us) = 0;
+        virtual bool should_unblock(Thread&, time_t now_s, long us) = 0;
     };
 
     class ThreadBlockerFileDescription : public ThreadBlocker {
@@ -90,37 +89,37 @@ public:
     class ThreadBlockerAccept : public ThreadBlockerFileDescription {
     public:
         ThreadBlockerAccept(const RefPtr<FileDescription>& description);
-        virtual bool should_unblock(time_t, long) override;
+        virtual bool should_unblock(Thread&, time_t, long) override;
     };
 
     class ThreadBlockerReceive : public ThreadBlockerFileDescription {
     public:
         ThreadBlockerReceive(const RefPtr<FileDescription>& description);
-        virtual bool should_unblock(time_t, long) override;
+        virtual bool should_unblock(Thread&, time_t, long) override;
     };
 
     class ThreadBlockerConnect : public ThreadBlockerFileDescription {
     public:
         ThreadBlockerConnect(const RefPtr<FileDescription>& description);
-        virtual bool should_unblock(time_t, long) override;
+        virtual bool should_unblock(Thread&, time_t, long) override;
     };
 
     class ThreadBlockerWrite : public ThreadBlockerFileDescription {
     public:
         ThreadBlockerWrite(const RefPtr<FileDescription>& description);
-        virtual bool should_unblock(time_t, long) override;
+        virtual bool should_unblock(Thread&, time_t, long) override;
     };
 
     class ThreadBlockerRead : public ThreadBlockerFileDescription {
     public:
         ThreadBlockerRead(const RefPtr<FileDescription>& description);
-        virtual bool should_unblock(time_t, long) override;
+        virtual bool should_unblock(Thread&, time_t, long) override;
     };
 
     class ThreadBlockerCondition : public ThreadBlocker {
     public:
         ThreadBlockerCondition(Function<bool()> &condition);
-        virtual bool should_unblock(time_t, long) override;
+        virtual bool should_unblock(Thread&, time_t, long) override;
 
     private:
         Function<bool()> m_block_until_condition;
@@ -129,12 +128,25 @@ public:
     class ThreadBlockerSleep : public ThreadBlocker {
     public:
         ThreadBlockerSleep(u64 wakeup_time);
-        virtual bool should_unblock(time_t, long) override;
+        virtual bool should_unblock(Thread&, time_t, long) override;
 
     private:
         u64 m_wakeup_time { 0 };
     };
 
+    class ThreadBlockerSelect : public ThreadBlocker {
+    public:
+        ThreadBlockerSelect(const timeval& tv, bool select_has_timeout, const Vector<int>& read_fds, const Vector<int>& write_fds, const Vector<int>& except_fds);
+        virtual bool should_unblock(Thread&, time_t, long) override;
+
+    private:
+        timeval m_select_timeout;
+        bool m_select_has_timeout { false };
+        const Vector<int>& m_select_read_fds;
+        const Vector<int>& m_select_write_fds;
+        const Vector<int>& m_select_exceptional_fds;
+    };
+
     void did_schedule() { ++m_times_scheduled; }
     u32 times_scheduled() const { return m_times_scheduled; }
 
@@ -240,17 +252,12 @@ private:
     RefPtr<Region> m_kernel_stack_for_signal_handler_region;
     pid_t m_waitee_pid { -1 };
     int m_wait_options { 0 };
-    timeval m_select_timeout;
     SignalActionData m_signal_action_data[32];
     Region* m_signal_stack_user_region { nullptr };
     OwnPtr<ThreadBlocker> m_blocker;
-    Vector<int> m_select_read_fds;
-    Vector<int> m_select_write_fds;
-    Vector<int> m_select_exceptional_fds;
     FPUState* m_fpu_state { nullptr };
     InlineLinkedList<Thread>* m_thread_list { nullptr };
     State m_state { Invalid };
-    bool m_select_has_timeout { false };
     bool m_has_used_fpu { false };
     bool m_was_interrupted_while_blocked { false };
 };