Эх сурвалжийг харах

Merge branch 'signal' into tty

greatbridf 2 жил өмнө
parent
commit
feff857aaf

+ 2 - 0
CMakeLists.txt

@@ -49,6 +49,7 @@ set(KERNEL_MAIN_SOURCES src/fs/fat.cpp
                         src/kernel/hw/serial.cpp
                         src/kernel/hw/timer.c
                         src/kernel/event/event.cpp
+                        src/kernel/signal.cpp
                         src/types/bitmap.c
                         src/types/elf.cpp
                         src/types/libstdcpp.cpp
@@ -66,6 +67,7 @@ set(KERNEL_MAIN_SOURCES src/fs/fat.cpp
                         include/kernel/mm.hpp
                         include/kernel/vfs.hpp
                         include/kernel/vga.hpp
+                        include/kernel/signal.hpp
                         include/kernel/hw/ata.hpp
                         include/kernel/hw/keyboard.h
                         include/kernel/hw/port.hpp

+ 22 - 1
include/kernel/process.hpp

@@ -5,6 +5,7 @@
 #include <kernel/event/evtqueue.hpp>
 #include <kernel/interrupt.h>
 #include <kernel/mm.hpp>
+#include <kernel/signal.hpp>
 #include <kernel/task.h>
 #include <kernel/tty.hpp>
 #include <kernel/vfs.hpp>
@@ -266,6 +267,7 @@ public:
     process_attr attr;
     filearr files;
     types::string<> pwd;
+    kernel::signal_list signals;
 
     pid_t pid;
     pid_t ppid;
@@ -276,7 +278,10 @@ public:
     process(process&& val);
     process(const process&);
 
-    explicit process(pid_t ppid, bool system = true, types::string<>&& path = "/");
+    explicit process(pid_t ppid,
+        bool system = true,
+        types::string<>&& path = "/",
+        kernel::signal_list&& sigs = {});
 
     constexpr bool is_system(void) const
     {
@@ -387,6 +392,20 @@ public:
         }
     }
 
+    void send_signal(pid_t pid, kernel::sig_t signal)
+    {
+        auto iter = this->find(pid);
+        if (!iter)
+            return iter->signals.set(signal);
+    }
+    void send_signal_grp(pid_t pgid, kernel::sig_t signal)
+    {
+        for (auto& proc : m_procs) {
+            if (proc.value.pgid == pgid)
+                proc.value.signals.set(signal);
+        }
+    }
+
     void kill(pid_t pid, int exit_code);
 };
 
@@ -464,3 +483,5 @@ void k_new_thread(void (*func)(void*), void* data);
 
 void NORETURN freeze(void);
 void NORETURN kill_current(int exit_code);
+
+void check_signal(void);

+ 69 - 0
include/kernel/signal.hpp

@@ -0,0 +1,69 @@
+#pragma once
+
+#include <stdint.h>
+#include <types/cplusplus.hpp>
+#include <types/list.hpp>
+
+namespace kernel {
+
+using sig_t = uint32_t;
+
+constexpr sig_t SIGINT = 1 << 0;
+constexpr sig_t SIGQUIT = 1 << 1;
+constexpr sig_t SIGSTOP = 1 << 2;
+
+class signal_list {
+public:
+    using list_type = types::list<sig_t>;
+
+private:
+    list_type m_list;
+    sig_t m_mask;
+
+public:
+    constexpr signal_list(void)
+        : m_mask(0)
+    {
+    }
+    constexpr signal_list(const signal_list& val)
+        : m_list(val.m_list)
+        , m_mask(val.m_mask)
+    {
+    }
+
+    constexpr signal_list(signal_list&& val)
+        : m_list(types::move(val.m_list))
+        , m_mask(val.m_mask)
+    {
+    }
+
+    constexpr bool empty(void) const
+    {
+        return this->m_list.empty();
+    }
+
+    constexpr void set(sig_t signal)
+    {
+        if (this->m_mask && signal)
+            return;
+
+        this->m_list.push_back(signal);
+        this->m_mask |= signal;
+    }
+
+    constexpr sig_t pop(void)
+    {
+        if (this->empty())
+            return 0;
+
+        auto iter = this->m_list.begin();
+        sig_t signal = *iter;
+        this->m_list.erase(iter);
+
+        this->m_mask &= ~signal;
+
+        return signal;
+    }
+};
+
+} // namespace kernel

+ 2 - 0
include/types/map.hpp

@@ -323,12 +323,14 @@ public:
         constexpr iterator& operator=(const iterator& iter)
         {
             p = iter.p;
+            return *this;
         }
 
         constexpr iterator& operator=(iterator&& iter)
         {
             p = iter.p;
             iter.p = nullptr;
+            return *this;
         }
 
         constexpr bool operator==(const iterator& iter) const

+ 21 - 0
src/kernel/interrupt.cpp

@@ -244,10 +244,16 @@ extern "C" void int14_handler(int14_data* d)
     }
 }
 
+void after_irq(void)
+{
+    check_signal();
+}
+
 extern "C" void irq0_handler(interrupt_stack*)
 {
     inc_tick();
     asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
+    after_irq();
     schedule();
 }
 // keyboard interrupt
@@ -255,70 +261,85 @@ extern "C" void irq1_handler(void)
 {
     asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
     handle_keyboard_interrupt();
+    after_irq();
 }
 extern "C" void irq2_handler(void)
 {
     asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
+    after_irq();
 }
 extern "C" void irq3_handler(void)
 {
     asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
+    after_irq();
 }
 extern "C" void irq4_handler(void)
 {
     // TODO: register interrupt handler in serial port driver
     serial_receive_data_interrupt();
     asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
+    after_irq();
 }
 extern "C" void irq5_handler(void)
 {
     asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
+    after_irq();
 }
 extern "C" void irq6_handler(void)
 {
     asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
+    after_irq();
 }
 extern "C" void irq7_handler(void)
 {
     asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
+    after_irq();
 }
 extern "C" void irq8_handler(void)
 {
     asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
     asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
+    after_irq();
 }
 extern "C" void irq9_handler(void)
 {
     asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
     asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
+    after_irq();
 }
 extern "C" void irq10_handler(void)
 {
     asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
     asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
+    after_irq();
 }
 extern "C" void irq11_handler(void)
 {
     asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
     asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
+    after_irq();
 }
 extern "C" void irq12_handler(void)
 {
     asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
     asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
+    after_irq();
 }
 extern "C" void irq13_handler(void)
 {
     asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
     asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
+    after_irq();
 }
 extern "C" void irq14_handler(void)
 {
     asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
     asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
+    after_irq();
 }
 extern "C" void irq15_handler(void)
 {
     asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
     asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
+    after_irq();
 }

+ 23 - 3
src/kernel/process.cpp

@@ -105,7 +105,10 @@ process::process(process&& val)
 }
 
 process::process(const process& parent)
-    : process { parent.pid, parent.is_system(), types::string<>(parent.pwd) }
+    : process { parent.pid,
+        parent.is_system(),
+        types::string<>(parent.pwd),
+        kernel::signal_list(parent.signals) }
 {
     this->pgid = parent.pgid;
     this->sid = parent.sid;
@@ -120,10 +123,14 @@ process::process(const process& parent)
     this->files.dup(parent.files);
 }
 
-process::process(pid_t _ppid, bool _system, types::string<>&& path)
+process::process(pid_t _ppid,
+    bool _system,
+    types::string<>&& path,
+    kernel::signal_list&& _sigs)
     : mms(*kernel_mms)
     , attr { .system = _system }
-    , pwd { path }
+    , pwd { types::move(path) }
+    , signals(types::move(_sigs))
     , pid { process::alloc_pid() }
     , ppid { _ppid }
     , pgid { 0 }
@@ -400,3 +407,16 @@ void NORETURN kill_current(int exit_code)
     procs->kill(current_process->pid, exit_code);
     schedule_noreturn();
 }
+
+void check_signal()
+{
+    switch (current_process->signals.pop()) {
+    case kernel::SIGINT:
+    case kernel::SIGQUIT:
+    case kernel::SIGSTOP:
+        kill_current(-1);
+        break;
+    case 0:
+        break;
+    }
+}

+ 0 - 0
src/kernel/signal.cpp


+ 3 - 2
src/kernel/syscall.cpp

@@ -89,7 +89,8 @@ int _syscall_read(interrupt_stack* data)
 
     // TODO: copy to user function !IMPORTANT
     int n_wrote = fs::vfs_read(file->ind, buf, n, file->cursor, n);
-    file->cursor += n_wrote;
+    if (n_wrote >= 0)
+        file->cursor += n_wrote;
     return n_wrote;
 }
 
@@ -296,7 +297,7 @@ extern "C" void syscall_entry(interrupt_stack* data)
 
     data->s_regs.eax = ret;
 
-    // TODO: check signal
+    check_signal();
 }
 
 SECTION(".text.kinit")

+ 40 - 11
src/kernel/tty.cpp

@@ -1,3 +1,4 @@
+#include <kernel/event/evtqueue.hpp>
 #include <kernel/hw/serial.h>
 #include <kernel/process.hpp>
 #include <kernel/tty.hpp>
@@ -5,6 +6,10 @@
 #include <stdint.h>
 #include <stdio.h>
 
+#define TTY_DATA (1 << 0)
+#define TTY_EOF (1 << 1)
+#define TTY_INT (1 << 2)
+
 tty::tty()
     : buf(BUFFER_SIZE)
 {
@@ -22,15 +27,31 @@ size_t tty::read(char* buf, size_t buf_size, size_t n)
 
     while (buf_size && n) {
         if (this->buf.empty()) {
-            current_thread->attr.ready = 0;
-            current_thread->attr.wait = 1;
-            this->blocklist.subscribe(current_thread);
-            schedule();
-            this->blocklist.unsubscribe(current_thread);
-        }
+            while (this->blocklist.empty()) {
+                current_thread->attr.ready = 0;
+                current_thread->attr.wait = 1;
+                this->blocklist.subscribe(current_thread);
+                schedule();
+
+                if (!this->blocklist.empty()) {
+                    this->blocklist.unsubscribe(current_thread);
+                    break;
+                }
+            }
 
-        if (this->buf.empty())
-            break;
+            auto evt = this->blocklist.front();
+            switch ((int)evt.data1) {
+            // INTERRUPT
+            case TTY_INT:
+                return -1;
+            // DATA
+            case TTY_DATA:
+                break;
+            // EOF
+            case TTY_EOF:
+                return orig_n - n;
+            }
+        }
 
         *buf = this->buf.get();
         --buf_size;
@@ -81,6 +102,7 @@ void serial_tty::recvchar(char c)
             serial_send_data(PORT_SERIAL0, '\r');
             serial_send_data(PORT_SERIAL0, '\n');
         }
+        this->blocklist.push(kernel::evt { nullptr, (void*)TTY_DATA, nullptr, nullptr });
         this->blocklist.notify();
         break;
     // ^?: backspace
@@ -117,19 +139,26 @@ void serial_tty::recvchar(char c)
         break;
     // ^C: SIGINT
     case 0x03:
-        console->print("sigint");
+        this->blocklist.push(kernel::evt { nullptr, (void*)TTY_INT, nullptr, nullptr });
+        this->blocklist.notify();
+        procs->send_signal_grp(fg_pgroup, kernel::SIGINT);
         break;
     // ^D: EOF
     case 0x04:
+        this->blocklist.push(kernel::evt { nullptr, (void*)TTY_EOF, nullptr, nullptr });
         this->blocklist.notify();
         break;
     // ^Z: SIGSTOP
     case 0x1a:
-        console->print("sigstop");
+        this->blocklist.push(kernel::evt { nullptr, (void*)TTY_INT, nullptr, nullptr });
+        this->blocklist.notify();
+        procs->send_signal_grp(fg_pgroup, kernel::SIGSTOP);
         break;
     // ^\: SIGQUIT
     case 0x1c:
-        console->print("sigquit");
+        this->blocklist.push(kernel::evt { nullptr, (void*)TTY_INT, nullptr, nullptr });
+        this->blocklist.notify();
+        procs->send_signal_grp(fg_pgroup, kernel::SIGQUIT);
         break;
     default:
         buf.put(c);