Merge branch 'master' into signal-dev
authorMinep <zelong56@gmail.com>
Thu, 16 Jun 2022 16:20:38 +0000 (17:20 +0100)
committerMinep <zelong56@gmail.com>
Thu, 16 Jun 2022 16:20:38 +0000 (17:20 +0100)
14 files changed:
lunaix-os/bx_enh_dbg.ini
lunaix-os/includes/hal/cpu.h
lunaix-os/includes/lunaix/proc.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/lxinit.c
lunaix-os/kernel/proc0.c
lunaix-os/kernel/process.c
lunaix-os/kernel/sched.c
lunaix-os/kernel/signal.c [new file with mode: 0644]
lunaix-os/kernel/syscall.c

index 5e8e29861dce8a23a631f0bd535b8f779acf0228..348609581b0f845e46617cd2789eb8eb89a14af2 100644 (file)
@@ -19,8 +19,8 @@ isLittleEndian = TRUE
 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
index fe633d090fa7f3c7a189d590e9c8655c691ba752..af56120b9ac29a38a2ad15073f20e790f8c11340 100644 (file)
@@ -3,6 +3,8 @@
 
 #include <stdint.h>
 
+#define SEL_RPL(selector) ((selector)&0x3)
+
 typedef unsigned int reg32;
 typedef unsigned short reg16;
 
index a6f44700aa67ab7b59d8b6500a92beabfb0bb2af..eafae4fc43968e6f7958c8432b61c066271b4029 100644 (file)
@@ -7,6 +7,7 @@
 __LXSYSCALL(void, yield);
 
 __LXSYSCALL1(pid_t, wait, int*, status);
+
 __LXSYSCALL3(pid_t, waitpid, pid_t, pid, int*, status, int, options);
 
 #endif /* __LUNAIX_SYS_H */
index 32b74dff5397e2fe29ce13eab3ef89ea3191f317..28cb76b97a797089cdceacac9a3323c373c0760a 100644 (file)
@@ -4,6 +4,7 @@
 #include <arch/x86/interrupts.h>
 #include <lunaix/clock.h>
 #include <lunaix/mm/mm.h>
+#include <lunaix/signal.h>
 #include <lunaix/timer.h>
 #include <lunaix/types.h>
 #include <stdint.h>
@@ -26,11 +27,21 @@ struct proc_mm
     struct mm_region* regions;
 };
 
+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;
-    isr_param intr_ctx;
+    isr_param intr_ctx; // size=76
+    uintptr_t ustack_top;
     struct llist_header siblings;
     struct llist_header children;
     struct llist_header grp_member;
@@ -40,6 +51,9 @@ struct proc_info
     uint8_t state;
     int32_t exit_code;
     int32_t k_status;
+    sigset_t sig_pending;
+    sigset_t sig_mask;
+    void* sig_handler[_SIG_NUM];
     pid_t pgid;
     struct lx_timer* timer;
 };
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 37aa852bebfd6e0a627a34c7e5c4abbf983ff7cc..3a6e2eba10285ed8f84726ab543f5d40a52a0b50 100644 (file)
 #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
 
@@ -46,7 +50,7 @@ syscall_install();
     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)                                             \
index a03bce613f3897b5fe65c54d15be68a9e9670453..27bdc4c4cab8a0fcac2d8813bacf81b81f057d9d 100644 (file)
@@ -1,6 +1,7 @@
 #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
 
     interrupt_wrapper:
         /*
-         Stack layout
+         Stack layout (layout of struct isr_param)
     msa:   [ss]
            [esp]
-           eflags
+           eflags     > offset = 48 + 16 = 64
            cs
            eip
            err_code   
@@ -62,6 +63,7 @@
             las: Least Significant Address
             msa: Most Significant Address
         */
+        cld
         pushl %esp
 
         subl $16, %esp
         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
         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_sigreturn
+        .long __lxsys_sigprocmask
+        .long __lxsys_signal
         2:
         .rept __SYSCALL_MAX - (2b - 1b)/4
             .long 0
@@ -58,6 +61,4 @@
 
         popl %ebp
         
-        ret
-
-
+        ret
\ No newline at end of file
index fa8458c98eca67c28e782f9a3a7948ea32d283e9..43f0f2d9381e2ba7a533696298a38d934c5b3432 100644 (file)
@@ -49,14 +49,13 @@ _lxinit_main()
     pid_t p = 0;
 
     if (!fork()) {
-        kprintf("Test no hang!");
-        sleep(12);
+        kprintf("Test no hang!\n");
+        sleep(6);
         _exit(0);
     }
 
     waitpid(-1, &status, WNOHANG);
 
-    // 这里是就是LunaixOS的第一个进程了!
     for (size_t i = 0; i < 5; i++) {
         pid_t pid = 0;
         if (!(pid = fork())) {
index dac1b55597c7400c783efcbca659ac72b6a7a390..074bcd9347c40cdf070e97c26c3127eddbc2b3b0 100644 (file)
@@ -36,6 +36,20 @@ void
 __proc0()
 {
     init_platform();
+    asm volatile("movw %0, %ax\n"
+                 "movw %ax, %es\n"
+                 "movw %ax, %ds\n"
+                 "movw %ax, %fs\n"
+                 "movw %ax, %gs\n"
+                 "pushl %0\n"
+                 "pushl %1\n"
+                 "pushl %2\n"
+                 "pushl %3\n"
+                 "retf" ::"i"(UDATA_SEG),
+                 "i"(USTACK_TOP & ~0xf),
+                 "i"(UCODE_SEG),
+                 "r"(&&usr));
+usr:
     if (!fork()) {
         asm("jmp _lxinit_main");
     }
index 64f2654af6a0d1b621e2cc7e1d1f71657a5fae8f..020dfb47fe3fe8a5a92c8b404f11005bf3a5ec03 100644 (file)
@@ -107,14 +107,14 @@ __DEFINE_LXSYSCALL2(int, setpgid, pid_t, pid, pid_t, pgid)
 
     pgid = pgid ? pgid : proc->pid;
 
-    llist_delete(&proc->grp_member);
     struct proc_info* gruppenfuhrer = get_process(pgid);
 
-    if (!gruppenfuhrer) {
+    if (!gruppenfuhrer || proc->pgid == proc->pid) {
         __current->k_status = LXINVL;
         return -1;
     }
 
+    llist_delete(&proc->grp_member);
     llist_append(&gruppenfuhrer->grp_member, &proc->grp_member);
 
     proc->pgid = pgid;
index 8c43b149d3eb761ec094269a765ba9808ca775ea..026fb515a8dbfbc34410e868de18ccad40b7b308 100644 (file)
@@ -1,12 +1,14 @@
 #include <arch/x86/interrupts.h>
 #include <arch/x86/tss.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/signal.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();
 
+    signal_dispatch();
+
     asm volatile("movl %0, %%eax\n"
                  "jmp soft_iret\n" ::"r"(&__current->intr_ctx)
                  : "eax", "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
index 0d41470d8944ddff5b5ac0aba0da37309fb4ca28..ce0f2a794813dcc1a405c6d288fbdc85c2518b32 100644 (file)
@@ -1,13 +1,16 @@
-#include <lunaix/syscall.h>
 #include <arch/x86/interrupts.h>
 #include <lunaix/process.h>
 #include <lunaix/sched.h>
+#include <lunaix/syscall.h>
 #include <lunaix/syslog.h>
 
 LOG_MODULE("SYSCALL")
 
-extern void syscall_hndlr(isr_param* param);
+extern void
+syscall_hndlr(isr_param* param);
 
-void syscall_install() {
+void
+syscall_install()
+{
     intr_subscribe(LUNAIX_SYS_CALL, syscall_hndlr);
 }
\ No newline at end of file