Ver código fonte

feat: replace evequeue by cond_var

greatbridf 2 anos atrás
pai
commit
1ff2137333

+ 13 - 25
include/kernel/event/evtqueue.hpp

@@ -1,5 +1,6 @@
 #pragma once
 
+#include <types/cplusplus.hpp>
 #include <types/list.hpp>
 #include <types/lock.hpp>
 
@@ -8,38 +9,25 @@ struct thread;
 
 namespace kernel {
 
-struct evt {
-    thread* emitter;
-    void* data1;
-    void* data2;
-    void* data3;
-};
-
-class evtqueue {
-public:
-    // TODO: use small object allocator
-    using evt_list_type = types::list<evt>;
-    using subscriber_list_type = types::list<thread*>;
-
+class cond_var : public types::non_copyable {
 private:
+    using list_type = types::list<thread*>;
+
     types::mutex m_mtx;
-    evt_list_type m_evts;
-    subscriber_list_type m_subscribers;
+    list_type m_subscribers;
 
 public:
-    evtqueue(void) = default;
-    evtqueue(const evtqueue&) = delete;
-    evtqueue(evtqueue&&);
+    cond_var(void) = default;
 
-    void push(evt&& event);
-    evt front();
-    const evt* peek(void) const;
+    constexpr types::mutex& mtx(void)
+    {
+        return m_mtx;
+    }
 
-    bool empty(void) const;
+    /// @param lock should have already been locked
+    bool wait(types::mutex& lock);
     void notify(void);
-
-    void subscribe(thread* thd);
-    void unsubscribe(thread* thd);
+    void notify_all(void);
 };
 
 } // namespace kernel

+ 9 - 1
include/kernel/process.hpp

@@ -317,10 +317,16 @@ public:
         }
     };
 
+    struct wait_obj {
+        pid_t pid;
+        int code;
+    };
+
 public:
     mutable kernel::mm_list mms;
     thdlist thds;
-    kernel::evtqueue wait_lst;
+    kernel::cond_var cv_wait;
+    types::list<wait_obj> waitlist;
     process_attr attr;
     filearr files;
     types::string<> pwd;
@@ -332,6 +338,8 @@ public:
     pid_t sid;
 
 public:
+    // if waitlist is not empty or mutex in cv_wait
+    // is locked, its behavior is undefined
     process(process&& val);
     process(const process&);
 

+ 1 - 1
include/kernel/tty.hpp

@@ -33,7 +33,7 @@ public:
 
 protected:
     types::buffer<types::kernel_ident_allocator> buf;
-    kernel::evtqueue blocklist;
+    kernel::cond_var m_cv;
 
     pid_t fg_pgroup;
 };

+ 28 - 37
src/kernel/event/event.cpp

@@ -46,55 +46,46 @@ void dispatch_event(void)
     }
 }
 
-kernel::evtqueue::evtqueue(evtqueue&& q)
-    : m_evts { types::move(q.m_evts) }
-    , m_subscribers { types::move(q.m_subscribers) }
+bool kernel::cond_var::wait(types::mutex& lock)
 {
-}
+    thread* thd = current_thread;
 
-void kernel::evtqueue::push(kernel::evt&& event)
-{
-    types::lock_guard lck(m_mtx);
-    m_evts.push_back(types::move(event));
-    this->notify();
+    current_thread->attr.ready = 0;
+    current_thread->attr.wait = 1;
+    m_subscribers.push_back(thd);
+
+    lock.unlock();
+    bool ret = schedule();
+    lock.lock();
+
+    return ret;
 }
 
-kernel::evt kernel::evtqueue::front()
+void kernel::cond_var::notify(void)
 {
-    assert(!this->empty());
     types::lock_guard lck(m_mtx);
 
-    auto iter = m_evts.begin();
-    evt e = types::move(*iter);
-    m_evts.erase(iter);
-    return e;
-}
+    auto iter = m_subscribers.begin();
+    if (iter == m_subscribers.end())
+        return;
 
-const kernel::evt* kernel::evtqueue::peek(void) const
-{
-    return &m_evts.begin();
-}
+    auto* thd = *iter;
+    thd->attr.ready = 1;
+    thd->attr.wait = 0;
+    readythds->push(thd);
 
-bool kernel::evtqueue::empty(void) const
-{
-    return m_evts.empty();
+    m_subscribers.erase(iter);
 }
 
-void kernel::evtqueue::notify(void)
+void kernel::cond_var::notify_all(void)
 {
-    for (auto* sub : m_subscribers) {
-        sub->attr.ready = 1;
-        sub->attr.wait = 0;
-        readythds->push(sub);
-    }
-}
+    types::lock_guard lck(m_mtx);
 
-void kernel::evtqueue::subscribe(thread* thd)
-{
-    m_subscribers.push_back(thd);
-}
+    for (auto& thd : m_subscribers) {
+        thd->attr.ready = 1;
+        thd->attr.wait = 0;
+        readythds->push(thd);
+    }
 
-void kernel::evtqueue::unsubscribe(thread* thd)
-{
-    m_subscribers.erase(m_subscribers.find(thd));
+    m_subscribers.clear();
 }

+ 22 - 4
src/kernel/process.cpp

@@ -91,7 +91,6 @@ void thread::free_kstack(uint32_t p)
 process::process(process&& val)
     : mms(types::move(val.mms))
     , thds { types::move(val.thds), this }
-    , wait_lst(types::move(val.wait_lst))
     , attr { val.attr }
     , files(types::move(val.files))
     , pwd(types::move(val.pwd))
@@ -168,10 +167,29 @@ void proclist::kill(pid_t pid, int exit_code)
     // notify parent process and init
     auto* parent = this->find(proc->ppid);
     auto* init = this->find(1);
-    while (!proc->wait_lst.empty()) {
-        init->wait_lst.push(proc->wait_lst.front());
+
+    {
+        auto& mtx = init->cv_wait.mtx();
+        types::lock_guard lck(mtx);
+
+        {
+            auto& mtx = proc->cv_wait.mtx();
+            types::lock_guard lck(mtx);
+
+            for (const auto& item : proc->waitlist)
+                init->waitlist.push_back(item);
+
+            proc->waitlist.clear();
+        }
+    }
+    init->cv_wait.notify();
+
+    {
+        auto& mtx = parent->cv_wait.mtx();
+        types::lock_guard lck(mtx);
+        parent->waitlist.push_back({ pid, exit_code });
     }
-    parent->wait_lst.push({ nullptr, (void*)pid, (void*)exit_code, nullptr });
+    parent->cv_wait.notify();
 }
 
 void kernel_threadd_main(void)

+ 21 - 21
src/kernel/syscall.cpp

@@ -15,6 +15,7 @@
 #include <string.h>
 #include <types/allocator.hpp>
 #include <types/elf.hpp>
+#include <types/lock.hpp>
 #include <types/status.h>
 
 #define SYSCALL_HANDLERS_SIZE (128)
@@ -200,34 +201,33 @@ int _syscall_wait(interrupt_stack* data)
 {
     auto* arg1 = reinterpret_cast<int*>(data->s_regs.edi);
 
-    auto& waitlst = current_process->wait_lst;
-    if (waitlst.empty() && !procs->has_child(current_process->pid))
+    auto& cv = current_process->cv_wait;
+    auto& mtx = cv.mtx();
+    types::lock_guard lck(mtx);
+
+    auto& waitlist = current_process->waitlist;
+    if (waitlist.empty() && !procs->has_child(current_process->pid))
         return -ECHILD;
 
-    while (waitlst.empty()) {
-        current_thread->attr.ready = 0;
-        current_thread->attr.wait = 1;
-        waitlst.subscribe(current_thread);
+    while (cv.wait(mtx)) {
+        if (!waitlist.empty()) {
+            auto iter = waitlist.begin();
+            assert(iter != waitlist.end());
 
-        if (!schedule()) {
-            waitlst.unsubscribe(current_thread);
-            return -EINTR;
-        }
+            auto& obj = *iter;
+            pid_t pid = obj.pid;
 
-        if (!waitlst.empty()) {
-            waitlst.unsubscribe(current_thread);
-            break;
-        }
-    }
+            // TODO: copy_to_user check privilege
+            *arg1 = obj.code;
 
-    auto evt = waitlst.front();
+            procs->remove(pid);
+            waitlist.erase(iter);
 
-    pid_t pid = (pid_t)evt.data1;
-    // TODO: copy_to_user check privilege
-    *arg1 = (int)evt.data2;
+            return pid;
+        }
+    }
 
-    procs->remove(pid);
-    return pid;
+    return -EINTR;
 }
 
 int _syscall_getdents(interrupt_stack* data)

+ 11 - 12
src/kernel/tty.cpp

@@ -5,6 +5,7 @@
 #include <kernel/vga.hpp>
 #include <stdint.h>
 #include <stdio.h>
+#include <types/lock.hpp>
 
 tty::tty()
     : buf(BUFFER_SIZE)
@@ -22,15 +23,14 @@ size_t tty::read(char* buf, size_t buf_size, size_t n)
     size_t orig_n = n;
 
     while (buf_size && n) {
+        auto& mtx = this->m_cv.mtx();
+        types::lock_guard lck(mtx);
+
         if (this->buf.empty()) {
-            current_thread->attr.ready = 0;
-            current_thread->attr.wait = 1;
-            this->blocklist.subscribe(current_thread);
+            bool intr = !this->m_cv.wait(mtx);
 
-            bool intr = !schedule();
-            this->blocklist.unsubscribe(current_thread);
             if (intr || this->buf.empty())
-                goto _end;
+                break;
         }
 
         *buf = this->buf.get();
@@ -41,7 +41,6 @@ size_t tty::read(char* buf, size_t buf_size, size_t n)
             break;
     }
 
-_end:
     return orig_n - n;
 }
 
@@ -83,7 +82,7 @@ void serial_tty::recvchar(char c)
             serial_send_data(PORT_SERIAL0, '\r');
             serial_send_data(PORT_SERIAL0, '\n');
         }
-        this->blocklist.notify();
+        this->m_cv.notify();
         break;
     // ^?: backspace
     case 0x7f:
@@ -120,21 +119,21 @@ void serial_tty::recvchar(char c)
     // ^C: SIGINT
     case 0x03:
         procs->send_signal_grp(fg_pgroup, kernel::SIGINT);
-        this->blocklist.notify();
+        this->m_cv.notify();
         break;
     // ^D: EOF
     case 0x04:
-        this->blocklist.notify();
+        this->m_cv.notify();
         break;
     // ^Z: SIGSTOP
     case 0x1a:
         procs->send_signal_grp(fg_pgroup, kernel::SIGSTOP);
-        this->blocklist.notify();
+        this->m_cv.notify();
         break;
     // ^\: SIGQUIT
     case 0x1c:
         procs->send_signal_grp(fg_pgroup, kernel::SIGQUIT);
-        this->blocklist.notify();
+        this->m_cv.notify();
         break;
     default:
         buf.put(c);