feat: add signal handling support (not tested!)
authorMinep <zelong56@gmail.com>
Mon, 13 Jun 2022 14:40:28 +0000 (15:40 +0100)
committerMinep <zelong56@gmail.com>
Mon, 13 Jun 2022 14:40:28 +0000 (15:40 +0100)
lunaix-os/.gitignore
lunaix-os/bx_enh_dbg.ini
lunaix-os/includes/hal/cpu.h
lunaix-os/includes/lunaix/process.h
lunaix-os/includes/lunaix/signal.h [new file with mode: 0644]
lunaix-os/includes/lunaix/syscall.h
lunaix-os/kernel/asm/x86/interrupt.S
lunaix-os/kernel/asm/x86/syscall.S
lunaix-os/kernel/sched.c
lunaix-os/kernel/signal.c [new file with mode: 0644]

index 2b8398e2eb5ccededdd3d2fba00ce90432a2a4c7..0b666f608891ffc23607978a06b54a54543986bb 100644 (file)
@@ -4,3 +4,4 @@ playground/
 .vscode/*.log
 .VSCodeCounter/
 .idea
 .vscode/*.log
 .VSCodeCounter/
 .idea
+bx_enh_dbg.ini
\ No newline at end of file
index 5e8e29861dce8a23a631f0bd535b8f779acf0228..348609581b0f845e46617cd2789eb8eb89a14af2 100644 (file)
@@ -19,8 +19,8 @@ isLittleEndian = TRUE
 DefaultAsmLines = 512
 DumpWSIndex = 2
 DockOrder = 0x123
 DefaultAsmLines = 512
 DumpWSIndex = 2
 DockOrder = 0x123
-ListWidthPix[0] = 257
-ListWidthPix[1] = 318
-ListWidthPix[2] = 367
-MainWindow = 0, 0, 743, 500
+ListWidthPix[0] = 203
+ListWidthPix[1] = 249
+ListWidthPix[2] = 287
+MainWindow = 2536, 358, 743, 500
 FontName = Normal
 FontName = Normal
index fe633d090fa7f3c7a189d590e9c8655c691ba752..af56120b9ac29a38a2ad15073f20e790f8c11340 100644 (file)
@@ -3,6 +3,8 @@
 
 #include <stdint.h>
 
 
 #include <stdint.h>
 
+#define SEL_RPL(selector) ((selector)&0x3)
+
 typedef unsigned int reg32;
 typedef unsigned short reg16;
 
 typedef unsigned int reg32;
 typedef unsigned short reg16;
 
index 76ecaccf0b2884deb0460a345006aae62a7fb69b..e429060ab5f785b9ffdcec9f12c6cb534bfc48aa 100644 (file)
@@ -1,12 +1,13 @@
 #ifndef __LUNAIX_PROCESS_H
 #define __LUNAIX_PROCESS_H
 
 #ifndef __LUNAIX_PROCESS_H
 #define __LUNAIX_PROCESS_H
 
-#include <stdint.h>
 #include <arch/x86/interrupts.h>
 #include <arch/x86/interrupts.h>
-#include <lunaix/mm/mm.h>
-#include <lunaix/types.h>
 #include <lunaix/clock.h>
 #include <lunaix/clock.h>
+#include <lunaix/mm/mm.h>
+#include <lunaix/signal.h>
 #include <lunaix/timer.h>
 #include <lunaix/timer.h>
+#include <lunaix/types.h>
+#include <stdint.h>
 
 // 虽然内核不是进程,但为了区分,这里使用Pid=-1来指代内核。这主要是方便物理页所有权检查。
 #define KERNEL_PID -1
 
 // 虽然内核不是进程,但为了区分,这里使用Pid=-1来指代内核。这主要是方便物理页所有权检查。
 #define KERNEL_PID -1
 
 #define PROC_TERMMASK 0x6
 
 
 #define PROC_TERMMASK 0x6
 
-
-struct proc_mm {
+struct proc_mm
+{
     heap_context_t u_heap;
     struct mm_region* regions;
 };
 
     heap_context_t u_heap;
     struct mm_region* regions;
 };
 
-struct proc_info {
+struct proc_sig
+{
+    void* signal_handler;
+    int sig_num;
+    isr_param prev_context;
+};
+
+#define PROC_SIG_SIZE sizeof(struct proc_sig) // size=84
+
+struct proc_info
+{
     pid_t pid;
     struct proc_info* parent;
     pid_t pid;
     struct proc_info* parent;
-    isr_param intr_ctx;
+    isr_param intr_ctx; // size=76
+    uintptr_t ustack_top;
     struct llist_header siblings;
     struct llist_header children;
     struct proc_mm mm;
     struct llist_header siblings;
     struct llist_header children;
     struct proc_mm mm;
@@ -38,47 +50,59 @@ struct proc_info {
     uint8_t state;
     int32_t exit_code;
     int32_t k_status;
     uint8_t state;
     int32_t exit_code;
     int32_t k_status;
+    sigset_t sig_pending;
+    sigset_t sig_mask;
+    void* sig_handler[_SIG_NUM];
     struct lx_timer* timer;
 };
 
 extern volatile struct proc_info* __current;
 
     struct lx_timer* timer;
 };
 
 extern volatile struct proc_info* __current;
 
+pid_t
+alloc_pid();
 
 
-pid_t alloc_pid();
-
-void init_proc(struct proc_info *pcb);
+void
+init_proc(struct proc_info* pcb);
 
 /**
  * @brief 向系统发布一个进程,使其可以被调度。
 
 /**
  * @brief 向系统发布一个进程,使其可以被调度。
- * 
- * @param process 
+ *
+ * @param process
  */
  */
-void push_process(struct proc_info* process);
+void
+push_process(struct proc_info* process);
 
 
-pid_t destroy_process(pid_t pid);
+pid_t
+destroy_process(pid_t pid);
 
 
-void setup_proc_mem(struct proc_info* proc, uintptr_t kstack_from);
+void
+setup_proc_mem(struct proc_info* proc, uintptr_t kstack_from);
 
 /**
  * @brief 复制当前进程(LunaixOS的类 fork (unix) 实现)
 
 /**
  * @brief 复制当前进程(LunaixOS的类 fork (unix) 实现)
- * 
+ *
  */
  */
-pid_t dup_proc();
+pid_t
+dup_proc();
 
 /**
  * @brief 创建新进程(LunaixOS的类 CreateProcess (Windows) 实现)
 
 /**
  * @brief 创建新进程(LunaixOS的类 CreateProcess (Windows) 实现)
- * 
+ *
  */
  */
-void new_proc();
+void
+new_proc();
 
 /**
  * @brief 终止(退出)当前进程
 
 /**
  * @brief 终止(退出)当前进程
- * 
+ *
  */
  */
-void terminate_proc(int exit_code);
+void
+terminate_proc(int exit_code);
 
 
-int orphaned_proc(pid_t pid);
+int
+orphaned_proc(pid_t pid);
 
 
-struct proc_info* get_process(pid_t pid);
+struct proc_info*
+get_process(pid_t pid);
 
 #endif /* __LUNAIX_PROCESS_H */
 
 #endif /* __LUNAIX_PROCESS_H */
diff --git a/lunaix-os/includes/lunaix/signal.h b/lunaix-os/includes/lunaix/signal.h
new file mode 100644 (file)
index 0000000..c98441a
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __LUNAIX_SIGNAL_H
+#define __LUNAIX_SIGNAL_H
+
+#define _SIG_NUM 8
+
+#define _SIG_PENDING(bitmap, sig) ((bitmap) & (1 << (sig)))
+
+#define _SIGSEGV 0
+#define _SIGALRM 1
+#define _SIGCHLD 2
+#define _SIGCLD SIGCHLD
+#define _SIGINT 3
+#define _SIGKILL 4
+#define _SIGSTOP 5
+#define _SIGCONT 6
+
+#define _SIGNAL_UNMASKABLE ((1 << _SIGKILL) | (1 << _SIGSTOP))
+
+#define _SIG_BLOCK 1
+#define _SIG_UNBLOCK 2
+#define _SIG_SETMASK 3
+
+typedef unsigned int sigset_t;
+typedef void (*sighandler_t)(int);
+
+void
+signal_dispatch();
+
+#endif /* __LUNAIX_SIGNAL_H */
index c19d5016ae01e26494734a55cf7ffb5017ea7f58..9cb77647fcad0c1839802cc934486f6d141bd21b 100644 (file)
 #define __SYSCALL__exit 8
 #define __SYSCALL_wait 9
 #define __SYSCALL_waitpid 10
 #define __SYSCALL__exit 8
 #define __SYSCALL_wait 9
 #define __SYSCALL_waitpid 10
+#define __SYSCALL_sigreturn 11
+#define __SYSCALL_sigprocmask 12
+#define __SYSCALL_signal 13
+#define __SYSCALL_pause 14
 
 #define __SYSCALL_MAX 0x100
 
 
 #define __SYSCALL_MAX 0x100
 
@@ -52,7 +56,7 @@ syscall(unsigned int callcode)
     asmlinkage rettype __lxsys_##name(__PARAM_MAP3(t1, p1, t2, p2, t3, p3))
 
 #define __DEFINE_LXSYSCALL4(rettype, name, t1, p1, t2, p2, t3, p3, t4, p4)     \
     asmlinkage rettype __lxsys_##name(__PARAM_MAP3(t1, p1, t2, p2, t3, p3))
 
 #define __DEFINE_LXSYSCALL4(rettype, name, t1, p1, t2, p2, t3, p3, t4, p4)     \
-    asmlinkage rettype __lxsys_##nam                                         \
+    asmlinkage rettype __lxsys_##name(                                         \
       __PARAM_MAP4(t1, p1, t2, p2, t3, p3, t4, p4))
 
 #define __LXSYSCALL(rettype, name)                                             \
       __PARAM_MAP4(t1, p1, t2, p2, t3, p3, t4, p4))
 
 #define __LXSYSCALL(rettype, name)                                             \
index e0cda172957dc1e7efc253cd55cc31df224b89b0..62c9ec512630270ec3215451ea7e33eca587244d 100644 (file)
@@ -1,6 +1,7 @@
 #define __ASM__
 #include <arch/x86/interrupts.h>
 #include <lunaix/common.h>
 #define __ASM__
 #include <arch/x86/interrupts.h>
 #include <lunaix/common.h>
+#include <lunaix/syscall.h>
 #define __ASM_INTR_DIAGNOSIS
 
 .macro isr_template vector, no_error_code=1
 #define __ASM_INTR_DIAGNOSIS
 
 .macro isr_template vector, no_error_code=1
 
     interrupt_wrapper:
         /*
 
     interrupt_wrapper:
         /*
-         Stack layout
+         Stack layout (layout of struct isr_param)
     msa:   [ss]
            [esp]
     msa:   [ss]
            [esp]
-           eflags
+           eflags     > offset = 48 + 16 = 64
            cs
            eip
            err_code   
            cs
            eip
            err_code   
@@ -62,6 +63,7 @@
             las: Least Significant Address
             msa: Most Significant Address
         */
             las: Least Significant Address
             msa: Most Significant Address
         */
+        cld
         pushl %esp
 
         subl $16, %esp
         pushl %esp
 
         subl $16, %esp
         movw %ax, %ds
         movw %ax, %es
 
         movw %ax, %ds
         movw %ax, %es
 
+        # 保存用户栈顶指针。这是因为我们允许系统调用内进行上下文切换,而这样一来,我们就失去了用户栈的信息,
+        # 这样一来,就无法设置信号上下文。这主要是为了实现了pause()而做的准备
+        movl (__current), %eax  
+        movl 68(%esp), %ebx     # 取出esp
+        movl %ebx, 84(%eax)     # 存入__current->ustack_top
+
     1:
         movl %esp, %eax
         andl $0xfffffff0, %esp
     1:
         movl %esp, %eax
         andl $0xfffffff0, %esp
 
     .global soft_iret
     soft_iret:
 
     .global soft_iret
     soft_iret:
+        cli
         popl %esp
 
         popl %eax
         popl %esp
 
         popl %eax
         popl %eax
 #endif
         iret
         popl %eax
 #endif
         iret
+
+    handle_signal:
+        # 注意1:任何对proc_sig的布局改动,都须及时的保证这里的一致性!
+        # 注意2:handle_signal在调用之前,须确保proc_sig已经写入用户栈!
+        popl %eax               # arg1: addr of proc_sig structure in user stack
+        leal 8(%eax), %ebx
+
+        pushl 72(%ebx)          # proc_sig->prev_context.ss
+        pushl %eax              # esp
+        pushl 64(%ebx)          # proc_sig->prev_context.eflags
+        pushl $UCODE_SEG        # cs
+        pushl $sig_wrapper      # eip for sig wrapper
+
+        movw $UDATA_SEG, %cx    # switch data seg to user mode
+        movw %cx, %es
+        movw %cx, %ds
+        movw %cx, %fs
+        movw %cx, %gs
+
+        iret  
+
+    sig_wrapper:                # in user mode
+        movl %esp, %eax
+        and $0xfffffff0, %esp
+        subl $8, %esp
+        pushl %eax              # Addr to proc_sig structure 
+        pushl 4(%eax)           # proc_sig->sig_num     ---- 16 bytes aligned
+
+        call (%eax)             # invoke signal handler
+
+        # invoke the sigreturn syscall to exit the signal wrapper
+        movl $__SYSCALL_sigreturn, %eax
+        movl 4(%esp), %ebx
+        int $LUNAIX_SYS_CALL    
+
+        ud2                     # never reach!
\ No newline at end of file
index 2e361967295265bd8bc900a265cfb9464b15ff98..e97cc6f1fc56a383d2bbc457a0de07814472243e 100644 (file)
@@ -18,6 +18,9 @@
         .long __lxsys_exit
         .long __lxsys_wait          
         .long __lxsys_waitpid       /* 10 */
         .long __lxsys_exit
         .long __lxsys_wait          
         .long __lxsys_waitpid       /* 10 */
+        .long __lxsys_sigreturn
+        .long __lxsys_sigprocmask
+        .long __lxsys_signal
         2:
         .rept __SYSCALL_MAX - (2b - 1b)/4
             .long 0
         2:
         .rept __SYSCALL_MAX - (2b - 1b)/4
             .long 0
@@ -58,6 +61,4 @@
 
         popl %ebp
         
 
         popl %ebp
         
-        ret
-
-
+        ret
\ No newline at end of file
index 442921ebccfb444fd13d1374988f5fdbe7cef108..7f124c428bccd9cf908e268e0bccda4c2ae990fe 100644 (file)
@@ -1,12 +1,14 @@
 #include <arch/x86/interrupts.h>
 #include <arch/x86/tss.h>
 #include <arch/x86/interrupts.h>
 #include <arch/x86/tss.h>
+
 #include <hal/apic.h>
 #include <hal/cpu.h>
 #include <hal/apic.h>
 #include <hal/cpu.h>
+
 #include <lunaix/mm/kalloc.h>
 #include <lunaix/mm/vmm.h>
 #include <lunaix/process.h>
 #include <lunaix/sched.h>
 #include <lunaix/mm/kalloc.h>
 #include <lunaix/mm/vmm.h>
 #include <lunaix/process.h>
 #include <lunaix/sched.h>
-
+#include <lunaix/signal.h>
 #include <lunaix/spike.h>
 #include <lunaix/status.h>
 #include <lunaix/syscall.h>
 #include <lunaix/spike.h>
 #include <lunaix/status.h>
 #include <lunaix/syscall.h>
@@ -58,6 +60,8 @@ run(struct proc_info* proc)
 
     apic_done_servicing();
 
 
     apic_done_servicing();
 
+    signal_dispatch();
+
     asm volatile("pushl %0\n"
                  "jmp soft_iret\n" ::"r"(&__current->intr_ctx)
                  : "memory");
     asm volatile("pushl %0\n"
                  "jmp soft_iret\n" ::"r"(&__current->intr_ctx)
                  : "memory");
diff --git a/lunaix-os/kernel/signal.c b/lunaix-os/kernel/signal.c
new file mode 100644 (file)
index 0000000..3edb2f4
--- /dev/null
@@ -0,0 +1,101 @@
+#include <lunaix/process.h>
+#include <lunaix/sched.h>
+#include <lunaix/signal.h>
+#include <lunaix/syscall.h>
+
+extern struct scheduler sched_ctx; /* kernel/sched.c */
+
+void* default_handlers[_SIG_NUM] = {
+    // TODO: 添加默认handler
+};
+
+void
+signal_dispatch()
+{
+    // if (!(SEL_RPL(__current->intr_ctx.cs))) {
+    //     // 同特权级间调度不进行信号处理
+    //     return;
+    // }
+
+    if (!__current->sig_pending) {
+        // 没有待处理信号
+        return;
+    }
+
+    int sig_selected =
+      31 - __builtin_clz(__current->sig_pending & ~__current->sig_mask);
+
+    __current->sig_pending = __current->sig_pending & ~(1 << sig_selected);
+
+    if (!__current->sig_handler[sig_selected] &&
+        !default_handlers[sig_selected]) {
+        // 如果该信号没有handler,则忽略
+        return;
+    }
+
+    uintptr_t ustack = __current->ustack_top;
+
+    if ((int)(ustack - USTACK_END) < (int)sizeof(struct proc_sig)) {
+        // 用户栈没有空间存放信号上下文
+        return;
+    }
+
+    struct proc_sig* sig_ctx =
+      (struct proc_sig*)(ustack - sizeof(struct proc_sig));
+
+    sig_ctx->prev_context = __current->intr_ctx;
+    sig_ctx->sig_num = sig_selected;
+    sig_ctx->signal_handler = __current->sig_handler[sig_selected];
+
+    if (!sig_ctx->signal_handler) {
+        // 如果没有用户自定义的Handler,则使用系统默认Handler。
+        sig_ctx->signal_handler = default_handlers[sig_selected];
+    }
+
+    asm volatile("pushl %0\n"
+                 "jmp handle_signal" ::"r"(sig_ctx));
+}
+
+__DEFINE_LXSYSCALL1(int, sigreturn, struct proc_sig, *sig_ctx)
+{
+    __current->intr_ctx = sig_ctx->prev_context;
+    schedule();
+}
+
+__DEFINE_LXSYSCALL3(int,
+                    sigprocmask,
+                    int,
+                    how,
+                    const sigset_t,
+                    *set,
+                    sigset_t,
+                    *oldset)
+{
+    *oldset = __current->sig_mask;
+    if (how == _SIG_BLOCK) {
+        __current->sig_mask |= *set;
+    } else if (how == _SIG_UNBLOCK) {
+        __current->sig_mask &= ~(*set);
+    } else if (how == _SIG_SETMASK) {
+        __current->sig_mask = *set;
+    } else {
+        return 0;
+    }
+    __current->sig_mask &= ~_SIGNAL_UNMASKABLE;
+    return 1;
+}
+
+__DEFINE_LXSYSCALL2(int, signal, int, signum, sighandler_t, handler)
+{
+    if (signum < 0 || signum >= _SIG_NUM) {
+        return -1;
+    }
+
+    if (((1 << signum) & _SIGNAL_UNMASKABLE)) {
+        return -1;
+    }
+
+    __current->sig_handler[signum] = (void*)handler;
+
+    return 0;
+}
\ No newline at end of file