Pārlūkot izejas kodu

feat: read and write of pipes will wait for data

greatbridf 2 gadi atpakaļ
vecāks
revīzija
ba8f40e69b
4 mainītis faili ar 64 papildinājumiem un 27 dzēšanām
  1. 32 9
      include/kernel/vfs.hpp
  2. 10 0
      include/types/buffer.hpp
  3. 6 2
      src/kernel/process.cpp
  4. 16 16
      src/kernel/syscall.cpp

+ 32 - 9
include/kernel/vfs.hpp

@@ -1,6 +1,9 @@
 #pragma once
 
+#include "errno.h"
+
 #include <assert.h>
+#include <kernel/event/evtqueue.hpp>
 #include <stdint.h>
 #include <types/allocator.hpp>
 #include <types/buffer.hpp>
@@ -205,7 +208,7 @@ private:
 
 private:
     types::buffer<types::kernel_allocator> buf;
-    types::mutex mtx;
+    kernel::cond_var m_cv;
     uint32_t flags;
 
 public:
@@ -217,16 +220,19 @@ public:
 
     void close_read(void)
     {
+        // TODO: lock
         flags &= (~READABLE);
     }
 
     void close_write(void)
     {
+        // TODO: lock
         flags &= (~WRITABLE);
     }
 
     void close_one(void)
     {
+        // TODO: lock
         if (flags & READABLE)
             close_read();
         else
@@ -235,30 +241,47 @@ public:
 
     bool is_free(void) const
     {
+        // TODO: lock
         return (flags & (READABLE | WRITABLE)) == 0;
     }
 
     int write(const char* buf, size_t n)
     {
         // TODO: check privilege
-        for (size_t i = 0; i < n; ++i) {
-            if (this->buf.full())
-                assert(false);
-            this->buf.put(*(buf++));
+        // TODO: check EPIPE
+        {
+            auto& mtx = m_cv.mtx();
+            types::lock_guard lck(mtx);
+
+            while (this->buf.avail() < n)
+                if (!m_cv.wait(mtx))
+                    return -EINTR;
+
+            for (size_t i = 0; i < n; ++i)
+                this->buf.put(*(buf++));
         }
 
+        m_cv.notify();
         return n;
     }
 
     int read(char* buf, size_t n)
     {
         // TODO: check privilege
-        for (size_t i = 0; i < n; ++i) {
-            if (this->buf.empty())
-                assert(false);
-            *(buf++) = this->buf.pop();
+        // TODO: check EPIPE
+        {
+            auto& mtx = m_cv.mtx();
+            types::lock_guard lck(mtx);
+
+            while (this->buf.size() < n)
+                if (!m_cv.wait(mtx))
+                    return -EINTR;
+
+            for (size_t i = 0; i < n; ++i)
+                *(buf++) = this->buf.get();
         }
 
+        m_cv.notify();
         return n;
     }
 };

+ 10 - 0
include/types/buffer.hpp

@@ -134,6 +134,16 @@ public:
         head = _forward(head);
         return c;
     }
+
+    constexpr size_t size(void) const
+    {
+        return count;
+    }
+
+    constexpr size_t avail(void) const
+    {
+        return end - start + 1 - count;
+    }
 };
 
 } // namespace types

+ 6 - 2
src/kernel/process.cpp

@@ -168,6 +168,7 @@ void proclist::kill(pid_t pid, int exit_code)
     auto* parent = this->find(proc->ppid);
     auto* init = this->find(1);
 
+    bool flag = false;
     {
         auto& mtx = init->cv_wait.mtx();
         types::lock_guard lck(mtx);
@@ -176,13 +177,16 @@ void proclist::kill(pid_t pid, int exit_code)
             auto& mtx = proc->cv_wait.mtx();
             types::lock_guard lck(mtx);
 
-            for (const auto& item : proc->waitlist)
+            for (const auto& item : proc->waitlist) {
                 init->waitlist.push_back(item);
+                flag = true;
+            }
 
             proc->waitlist.clear();
         }
     }
-    init->cv_wait.notify();
+    if (flag)
+        init->cv_wait.notify();
 
     {
         auto& mtx = parent->cv_wait.mtx();

+ 16 - 16
src/kernel/syscall.cpp

@@ -206,28 +206,28 @@ int _syscall_wait(interrupt_stack* data)
     types::lock_guard lck(mtx);
 
     auto& waitlist = current_process->waitlist;
-    if (waitlist.empty() && !procs->has_child(current_process->pid))
-        return -ECHILD;
 
-    while (cv.wait(mtx)) {
-        if (!waitlist.empty()) {
-            auto iter = waitlist.begin();
-            assert(iter != waitlist.end());
+    while (waitlist.empty()) {
+        if (!procs->has_child(current_process->pid))
+            return -ECHILD;
 
-            auto& obj = *iter;
-            pid_t pid = obj.pid;
+        if (!cv.wait(mtx))
+            return -EINTR;
+    }
 
-            // TODO: copy_to_user check privilege
-            *arg1 = obj.code;
+    auto iter = waitlist.begin();
+    assert(iter != waitlist.end());
 
-            procs->remove(pid);
-            waitlist.erase(iter);
+    auto& obj = *iter;
+    pid_t pid = obj.pid;
 
-            return pid;
-        }
-    }
+    // TODO: copy_to_user check privilege
+    *arg1 = obj.code;
+
+    procs->remove(pid);
+    waitlist.erase(iter);
 
-    return -EINTR;
+    return pid;
 }
 
 int _syscall_getdents(interrupt_stack* data)