refactor: full rewrite of signal feature
authorMinep <lunaixsky@qq.com>
Fri, 21 Jul 2023 18:19:01 +0000 (19:19 +0100)
committerMinep <lunaixsky@qq.com>
Fri, 21 Jul 2023 18:19:01 +0000 (19:19 +0100)
refactor: scheduler logic
refactor: (hhk) initial page mapper.
fix: remove debugging user access to kernel page
feat: make signal.h more posix compliant

20 files changed:
lunaix-os/arch/i386/hhk.c
lunaix-os/includes/arch/x86/i386_abi.h
lunaix-os/includes/lunaix/process.h
lunaix-os/includes/lunaix/signal.h
lunaix-os/includes/usr/lunaix/signal_defs.h
lunaix-os/includes/usr/lunaix/syscallid.h
lunaix-os/kernel/asm/x86/interrupt.S
lunaix-os/kernel/asm/x86/pfault.c
lunaix-os/kernel/asm/x86/syscall.S
lunaix-os/kernel/k_init.c
lunaix-os/kernel/process/sched.c
lunaix-os/kernel/process/signal.c
lunaix-os/kernel/process/task_attr.c
lunaix-os/link/linker.ld
lunaix-os/usr/libc/arch/i386/signal.c
lunaix-os/usr/libc/arch/i386/trampoline.S [new file with mode: 0644]
lunaix-os/usr/libc/arch/i386/unistd.c
lunaix-os/usr/libc/includes/signal.h
lunaix-os/usr/libc/includes/unistd.h
lunaix-os/usr/signal_demo/signal_demo.c

index a9cb814a8931ee7ee03548a7b986306c2ef65747..4250f79b4810745f83e240e6914364714c6cd16e 100644 (file)
 // Provided by linker (see linker.ld)
 extern u8_t __kernel_start;
 extern u8_t __kernel_end;
+extern u8_t __ktext_start;
+extern u8_t __ktext_end;
+
 extern u8_t __init_hhk_end;
 extern u8_t _k_stack;
 
 void
-_init_page(ptd_t* ptd)
+_init_page(x86_page_table* ptd)
 {
-    SET_PDE(ptd, 0, NEW_L1_ENTRY(PG_PREM_RW, ptd + PG_MAX_ENTRIES))
+    ptd->entry[0] = NEW_L1_ENTRY(PG_PREM_RW, (ptd_t*)ptd + PG_MAX_ENTRIES);
 
     // 对低1MiB空间进行对等映射(Identity
     // mapping),也包括了我们的VGA,方便内核操作。
+    x86_page_table* id_pt =
+      (x86_page_table*)GET_PG_ADDR(ptd->entry[PG_TABLE_IDENTITY]);
+
     for (u32_t i = 0; i < 256; i++) {
-        SET_PTE(ptd,
-                PG_TABLE_IDENTITY,
-                i,
-                NEW_L2_ENTRY(PG_PREM_RW, (i << PG_SIZE_BITS)))
+        id_pt->entry[i] = NEW_L2_ENTRY(PG_PREM_RW, (i << PG_SIZE_BITS));
     }
 
     // 对等映射我们的hhk_init,这样一来,当分页与地址转换开启后,我们依然能够照常执行最终的
     // jmp 指令来跳转至
     //  内核的入口点
     for (u32_t i = 0; i < HHK_PAGE_COUNT; i++) {
-        SET_PTE(ptd,
-                PG_TABLE_IDENTITY,
-                256 + i,
-                NEW_L2_ENTRY(PG_PREM_RW, 0x100000 + (i << PG_SIZE_BITS)))
+        id_pt->entry[256 + i] =
+          NEW_L2_ENTRY(PG_PREM_RW, 0x100000 + (i << PG_SIZE_BITS));
     }
 
     // --- 将内核重映射至高半区 ---
@@ -65,9 +66,8 @@ _init_page(ptd_t* ptd)
     //  当然,就现在而言,我们的内核只占用不到50个页(每个页表包含1024个页)
     //  这里分配了3个页表(12MiB),未雨绸缪。
     for (u32_t i = 0; i < PG_TABLE_STACK - PG_TABLE_KERNEL; i++) {
-        SET_PDE(ptd,
-                kernel_pde_index + i,
-                NEW_L1_ENTRY(PG_PREM_URW, PT_ADDR(ptd, PG_TABLE_KERNEL + i)))
+        ptd->entry[kernel_pde_index + i] =
+          NEW_L1_ENTRY(PG_PREM_RW, PT_ADDR(ptd, PG_TABLE_KERNEL + i));
     }
 
     // 首先,检查内核的大小是否可以fit进我们这几个表(12MiB)
@@ -80,22 +80,26 @@ _init_page(ptd_t* ptd)
 
     // 计算内核.text段的物理地址
     ptr_t kernel_pm = V2P(&__kernel_start);
+    ptr_t ktext_start = V2P(&__ktext_start);
+    ptr_t ktext_end = V2P(&ktext_end);
 
     // 重映射内核至高半区地址(>=0xC0000000)
     for (u32_t i = 0; i < kernel_pg_counts; i++) {
-        // FIXME: 只是用作用户模式(R3)测试!
-        //        在实际中,内核代码除了极少部分需要暴露给R3(如从信号返回),其余的应为R0。
+        ptr_t paddr = kernel_pm + (i << PG_SIZE_BITS);
+        u32_t flags = PG_PREM_RW;
 
-#warning "fixme: kernel pages should not be user-accessable"
+        if (paddr >= ktext_start && paddr <= ktext_end) {
+            flags = PG_PREM_R;
+        }
 
         SET_PTE(ptd,
                 PG_TABLE_KERNEL,
                 kernel_pte_index + i,
-                NEW_L2_ENTRY(PG_PREM_URW, kernel_pm + (i << PG_SIZE_BITS)))
+                NEW_L2_ENTRY(flags, paddr))
     }
 
     // 最后一个entry用于循环映射
-    SET_PDE(ptd, PG_MAX_ENTRIES - 1, NEW_L1_ENTRY(T_SELF_REF_PERM, ptd));
+    ptd->entry[PG_MAX_ENTRIES - 1] = NEW_L1_ENTRY(T_SELF_REF_PERM, ptd);
 }
 
 u32_t
@@ -130,7 +134,7 @@ _save_multiboot_info(multiboot_info_t* info, u8_t* destination)
 }
 
 void
-_hhk_init(ptd_t* ptd, u32_t kpg_size)
+_hhk_init(x86_page_table* ptd, u32_t kpg_size)
 {
 
     // 初始化 kpg 全为0
index 22481c9cc587334860596e7033984e3838957b79..8804bc9b08d6026880c735f31111c3506b862db7 100644 (file)
                  "r"(pc)                                                       \
                  : "eax", "memory");
 
+#define push_arg1(stack_ptr, arg) *((typeof((arg))*)(stack_ptr)--) = arg
+#define push_arg2(stack_ptr, arg1, arg2)                                       \
+    {                                                                          \
+        *((typeof((arg1))*)(stack_ptr)--) = arg1;                              \
+        *((typeof((arg2))*)(stack_ptr)--) = arg2;                              \
+    }
+#define push_arg3(stack_ptr, arg1, arg2, arg3)                                 \
+    {                                                                          \
+        *((typeof((arg1))*)(stack_ptr)--) = arg1;                              \
+        *((typeof((arg2))*)(stack_ptr)--) = arg2;                              \
+        *((typeof((arg3))*)(stack_ptr)--) = arg3;                              \
+    }
+#define push_arg4(stack_ptr, arg1, arg2, arg3, arg4)                           \
+    {                                                                          \
+        *((typeof((arg1))*)(stack_ptr)--) = arg1;                              \
+        *((typeof((arg2))*)(stack_ptr)--) = arg2;                              \
+        *((typeof((arg3))*)(stack_ptr)--) = arg3;                              \
+        *((typeof((arg4))*)(stack_ptr)--) = arg4;                              \
+    }
+
 #endif /* __LUNAIX_ABI_H */
index 974907d0d56ebfc1bbbd8f550cd8c500a0ff8e48..a8ac5d84c19e85aa48aa15341c07c7957a361526 100644 (file)
 // 虽然内核不是进程,但为了区分,这里使用Pid=-1来指代内核。这主要是方便物理页所有权检查。
 #define KERNEL_PID -1
 
+/*
+    |C|Bk|De|Tn|Pu|Rn|
+         \----/
+            Dt
+
+    Group Dt: whether this process is terminated.
+
+    Rn: Running
+    Tn: Terminated
+    De: Destoryed
+    Pu: Paused
+    Bk: Blocked
+    C : Created
+*/
+
 #define PS_READY 0
 #define PS_RUNNING 1
 #define PS_TERMNAT 2
 #define PS_DESTROY 4
-#define PS_BLOCKED 8
-#define PS_CREATED 16
+#define PS_PAUSED 8
+#define PS_BLOCKED 16
+#define PS_CREATED 32
 
-#define PROC_TERMINATED(state) (state & 0x6)
+#define PS_GrBP (PS_PAUSED | PS_BLOCKED)
+#define PS_GrDT (PS_TERMNAT | PS_DESTROY)
+
+#define PROC_TERMINATED(state) ((state)&PS_GrDT)
+#define PROC_HANGED(state) ((state)&PS_BLOCKED)
+#define PROC_RUNNABLE(state) ((state)&PS_PAUSED)
 
 #define PROC_FINPAUSE 1
 
@@ -32,10 +53,28 @@ struct proc_sigstate
     char fxstate[512] __attribute__((aligned(16)));
 };
 
+struct sigact
+{
+    struct sigact* prev;
+    sigset_t sa_mask;
+    void* sa_actor;
+    void* sa_handler;
+    pid_t sender;
+};
+
+struct sighail
+{
+    sigset_t sig_pending;
+    sigset_t sig_mask;
+    struct sigact* inprogress;
+    struct sigact signals[_SIG_NUM];
+};
+
 struct proc_sig
 {
-    void* signal_handler;
     int sig_num;
+    void* sigact;
+    void* sighand;
     struct proc_sigstate prev_context;
 } __attribute__((packed));
 
@@ -76,11 +115,8 @@ struct proc_info
     u8_t state;
     int32_t exit_code;
     int32_t k_status;
-    sigset_t sig_pending;
-    sigset_t sig_mask;
-    sigset_t sig_inprogress;
     int flags;
-    void* sig_handler[_SIG_NUM];
+    struct sighail sigctx;
     struct v_fdtable* fdtable;
     struct v_dnode* cwd;
     pid_t pgid;
@@ -94,6 +130,18 @@ block_current()
     __current->state = PS_BLOCKED;
 }
 
+static inline void
+pause_current()
+{
+    __current->state = PS_PAUSED;
+}
+
+static inline void
+resume_current()
+{
+    __current->state = PS_RUNNING;
+}
+
 /**
  * @brief 分配并初始化一个进程控制块
  *
@@ -151,4 +199,7 @@ orphaned_proc(pid_t pid);
 struct proc_info*
 get_process(pid_t pid);
 
+void
+proc_setsignal(struct proc_info* proc, int signum);
+
 #endif /* __LUNAIX_PROCESS_H */
index dbe9ce5c9c212af1d28fe167558615b65049743b..af191af7f891827234e1a2032695341c793526f2 100644 (file)
 #define _SIGSTOP SIGSTOP
 #define _SIGCONT SIGCONT
 #define _SIGTERM SIGTERM
-
-#define __SIGNAL(num) (1 << (num))
-#define __SIGSET(bitmap, num) (bitmap = bitmap | __SIGNAL(num))
-#define __SIGTEST(bitmap, num) (bitmap & __SIGNAL(num))
-#define __SIGCLEAR(bitmap, num) ((bitmap) = (bitmap) & ~__SIGNAL(num))
-
-#define _SIGNAL_UNMASKABLE (__SIGNAL(_SIGKILL) | __SIGNAL(_SIGSTOP))
-
 #define _SIG_BLOCK SIG_BLOCK
 #define _SIG_UNBLOCK SIG_UNBLOCK
 #define _SIG_SETMASK SIG_SETMASK
 
+#define sigset(num) (1 << (num))
+#define sigset_add(set, num) (set = set | sigset(num))
+#define sigset_test(set, num) (set & sigset(num))
+#define sigset_clear(set, num) ((set) = (set) & ~sigset(num))
+#define sigset_union(set, set2) ((set) = (set) | (set2))
+#define sigset_intersect(set, set2) ((set) = (set) & (set2))
+
 int
 signal_send(pid_t pid, int signum);
 
index 0bd3e7051bb0a4c99cdfbd347a7e657de86850f5..d56a44307052cb4a0b124bb4a61be256468e40d8 100644 (file)
 typedef unsigned int sigset_t;
 typedef void (*sighandler_t)(int);
 
+struct sigaction
+{
+    sigset_t sa_mask;
+    void (*sa_handler)(int);
+    void (*sa_sigaction)(int, void*, void*);
+};
+
+struct siginfo
+{
+    // TODO
+};
+
 #endif /* __LUNAIX_SIGNAL_DEFS_H */
index cc7ac7abcd3354fc289eb47f18f09ba0a9b3bafb..d388e1250e4fe1956f36217b2bbb71b1515207e9 100644 (file)
@@ -14,7 +14,7 @@
 
 #define __SYSCALL_sigreturn 11
 #define __SYSCALL_sigprocmask 12
-#define __SYSCALL_signal 13
+#define __SYSCALL_sys_sigaction 13
 #define __SYSCALL_pause 14
 #define __SYSCALL_kill 15
 #define __SYSCALL_alarm 16
index a6c0496f651b90a0574364f619dfffb22ca23d7f..602f793c6aa86b0aac6875c7f931a05a92c6cbbe 100644 (file)
@@ -16,7 +16,7 @@
 .section .bss
     .align 16
     lo_tmp_stack:
-        .skip 128
+        .skip 256
     tmp_stack:
 
 /*
         movw %ax, %ds
         movw %ax, %es
 
-        # 保存用户栈顶指针。这是因为我们允许系统调用内进行上下文切换,而这样一来,我们就失去了用户栈的信息,
-        # 这样一来,就无法设置信号上下文。这主要是为了实现了pause()而做的准备
         movl __current, %eax
 
+        # FIXME: Save x87 context to user stack, rather than kernel's memory.
         # 保存x87FPU的状态
         movl 68(%eax), %ebx
         fxsave (%ebx)
 
+        # 保存用户栈顶指针。因为我们允许同级中断的产生,所以需要该手段跟踪用户栈的地址。
         movl 124(%esp), %ebx     # 取出esp
         movl %ebx, 60(%eax)     # 存入__current->ustack_top
 
     handle_signal:
         # 注意1:任何对proc_sig的布局改动,都须及时的保证这里的一致性!
         # 注意2:handle_signal在调用之前,须确保proc_sig已经写入用户栈!
-        leal 8(%eax), %ebx      # arg1 in %eax: addr of proc_sig structure in user stack
+        # arg1 in %eax: addr of proc_sig structure in user stack
+        leal 12(%eax), %ebx      # %ebx = &proc_sig->prev_context
 
         pushl $UDATA_SEG        # proc_sig->prev_context.proc_regs.ss
         pushl %eax              # esp
+
         movl 48(%ebx), %ebx
         pushl 68(%ebx)          # proc_sig->prev_context.proc_regs.execp->eflags
+        
         pushl $UCODE_SEG        # cs
-        pushl $sig_wrapper      # eip for sig wrapper
+        pushl 4(%eax)           # %eip = proc_sig->sigact
 
         movw $UDATA_SEG, %cx    # switch data seg to user mode
         movw %cx, %es
         movw %cx, %fs
         movw %cx, %gs
 
-        iret  
-
-.section .usrtext
-    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
+        iret
\ No newline at end of file
index 70d5e560da7a145ca1b154f9e52cafd749e38d26..f527e12c3dcc0f81c292c3761c78c125943faa80 100644 (file)
 
 #include <klibc/string.h>
 
+static u32_t
+get_ptattr(struct mm_region* vmr)
+{
+    u32_t vmr_attr = vmr->attr;
+    u32_t ptattr = PG_PRESENT | PG_ALLOW_USER;
+
+    if ((vmr_attr & PROT_WRITE)) {
+        ptattr |= PG_WRITE;
+    }
+
+    return ptattr & 0xfff;
+}
+
 static void
 kprintf(const char* fmt, ...)
 {
@@ -51,13 +64,16 @@ intr_routine_page_fault(const isr_param* param)
         goto segv_term;
     }
 
-    if ((errcode & PG_ALLOW_USER)) {
-        // invalid access
-        goto segv_term;
-    }
-
     volatile x86_pte_t* pte = &PTE_MOUNTED(VMS_SELF, ptr >> 12);
     if (PG_IS_PRESENT(*pte)) {
+        if (((errcode ^ mapping.flags) & PG_ALLOW_USER)) {
+            // invalid access
+            kprintf(KDEBUG "invalid user access. (%p->%p, attr:0x%x)\n",
+                    mapping.va,
+                    mapping.pa,
+                    mapping.flags);
+            goto segv_term;
+        }
         if ((hit_region->attr & COW_MASK) == COW_MASK) {
             // normal page fault, do COW
             cpu_invplg((ptr_t)pte);
@@ -84,7 +100,7 @@ intr_routine_page_fault(const isr_param* param)
                 goto oom;
             }
 
-            *pte = *pte | pa | PG_PRESENT | PG_ALLOW_USER;
+            *pte = *pte | pa | get_ptattr(hit_region);
             memset((void*)PG_ALIGN(ptr), 0, PG_SIZE);
             goto resolved;
         }
@@ -107,7 +123,7 @@ intr_routine_page_fault(const isr_param* param)
         }
 
         cpu_invplg((ptr_t)pte);
-        *pte = (*pte & 0xFFF) | pa | PG_PRESENT | PG_ALLOW_USER;
+        *pte = (*pte & 0xFFF) | pa | get_ptattr(hit_region);
 
         memset((void*)ptr, 0, PG_SIZE);
 
@@ -143,7 +159,7 @@ segv_term:
             param->execp->eip,
             param->execp->err_code);
 
-    __SIGSET(__current->sig_pending, _SIGSEGV);
+    sigset_add(__current->sigctx.sig_pending, _SIGSEGV);
 
     schedule();
     // should not reach
index b48aeade91db4150136b9201f3872c5b616014e1..ac3fe80d4a75afb9a7d93e643324309f62345d58 100644 (file)
@@ -20,7 +20,7 @@
         .long __lxsys_waitpid       /* 10 */
         .long __lxsys_sigreturn
         .long __lxsys_sigprocmask
-        .long __lxsys_signal
+        .long __lxsys_sys_sigaction
         .long __lxsys_pause
         .long __lxsys_kill          /* 15 */
         .long __lxsys_alarm
index d399251960ee6421354c28d4d6a273f837a40d79..71adb3098cadb369e9fdd7ced62e64c8ea218edf 100644 (file)
@@ -179,9 +179,6 @@ spawn_proc0()
     assert_msg(0, "Unexpected Return");
 }
 
-extern u8_t __usrtext_start;
-extern u8_t __usrtext_end;
-
 // 按照 Memory map 标识可用的物理页
 void
 setup_memory(multiboot_memory_map_t* map, size_t map_size)
@@ -202,11 +199,6 @@ setup_memory(multiboot_memory_map_t* map, size_t map_size)
     size_t pg_count = V2P(&__kernel_end) >> PG_SIZE_BITS;
     pmm_mark_chunk_occupied(KERNEL_PID, 0, pg_count, PP_FGLOCKED);
 
-    for (ptr_t i = (ptr_t)&__usrtext_start; i < (ptr_t)&__usrtext_end;
-         i += PG_SIZE) {
-        vmm_set_mapping(VMS_SELF, i, V2P(i), PG_PREM_UR, VMAP_NULL);
-    }
-
     // reserve higher half
     for (size_t i = L1_INDEX(KERNEL_MM_BASE); i < 1023; i++) {
         assert(vmm_set_mapping(VMS_SELF, i << 22, 0, 0, VMAP_NOMAP));
index b21d086ebce3667c7397cbb39da75575bfb0ba27..5e5db25e8ca20f22e6dac2d4c28fa4bec7fe614f 100644 (file)
@@ -111,14 +111,24 @@ run(struct proc_info* proc)
 int
 can_schedule(struct proc_info* proc)
 {
-    if (__SIGTEST(proc->sig_pending, _SIGCONT)) {
-        __SIGCLEAR(proc->sig_pending, _SIGSTOP);
-    } else if (__SIGTEST(proc->sig_pending, _SIGSTOP)) {
+    if (!proc) {
+        return 0;
+    }
+
+    struct sighail* sh = &proc->sigctx;
+
+    if ((proc->state & PS_PAUSED)) {
+        return !!(sh->sig_pending & ~1);
+    }
+
+    if (sigset_test(sh->sig_pending, _SIGCONT)) {
+        sigset_clear(sh->sig_pending, _SIGSTOP);
+    } else if (sigset_test(sh->sig_pending, _SIGSTOP)) {
         // 如果进程受到SIGSTOP,则该进程不给予调度。
         return 0;
     }
 
-    return 1;
+    return (proc->state == PS_READY);
 }
 
 void
@@ -143,7 +153,7 @@ check_sleepers()
 
         if (atime && now >= atime) {
             pos->sleep.alarm_time = 0;
-            __SIGSET(pos->sig_pending, _SIGALRM);
+            proc_setsignal(pos, _SIGALRM);
         }
 
         if (!wtime && !atime) {
@@ -165,6 +175,7 @@ schedule()
     struct proc_info* next;
     int prev_ptr = sched_ctx.procs_index;
     int ptr = prev_ptr;
+    int found = 0;
 
     if (!(__current->state & ~PS_RUNNING)) {
         __current->state = PS_READY;
@@ -174,23 +185,20 @@ schedule()
 
     // round-robin scheduler
 redo:
+
     do {
         ptr = (ptr + 1) % sched_ctx.ptable_len;
         next = sched_ctx._procs[ptr];
-    } while (!next || (next->state != PS_READY && ptr != prev_ptr));
 
-    sched_ctx.procs_index = ptr;
-
-    if (next->state != PS_READY) {
-        // schedule the dummy process if we're out of choice
-        next = &dummy_proc;
-        goto done;
-    }
+        if (!(found = can_schedule(next))) {
+            if (ptr == prev_ptr) {
+                next = &dummy_proc;
+                goto done;
+            }
+        }
+    } while (!found);
 
-    if (!can_schedule(next)) {
-        // 如果该进程不给予调度,则尝试重新选择
-        goto redo;
-    }
+    sched_ctx.procs_index = ptr;
 
 done:
     run(next);
@@ -305,7 +313,6 @@ repeat:
     goto repeat;
 
 done:
-    status_flags |= PEXITSIG * (proc->sig_inprogress != 0);
     if (status) {
         *status = proc->exit_code | status_flags;
     }
@@ -433,7 +440,7 @@ terminate_proc(int exit_code)
     __current->state = PS_TERMNAT;
     __current->exit_code = exit_code;
 
-    __SIGSET(__current->parent->sig_pending, _SIGCHLD);
+    proc_setsignal(__current->parent, _SIGCHLD);
 }
 
 struct proc_info*
index d12c62e176e8f1d3800a3345e94f672aa93a26d3..a8ec2397eaf3b98d4d6839892fe3184b8fe132cb 100644 (file)
@@ -9,51 +9,55 @@
 
 extern struct scheduler sched_ctx; /* kernel/sched.c */
 
-static u32_t term_sigs =
-  (1 << SIGSEGV) | (1 << SIGINT) | (1 << SIGKILL) | (1 << SIGTERM);
+#define UNMASKABLE (sigset(SIGKILL) | sigset(SIGTERM))
+#define TERMSIG (sigset(SIGSEGV) | sigset(SIGINT) | UNMASKABLE)
 
 // Referenced in kernel/asm/x86/interrupt.S
 void*
 signal_dispatch()
 {
-    if (!__current->sig_pending) {
+    if (!__current->sigctx.sig_pending) {
         // 没有待处理信号
         return 0;
     }
 
-    int sig_selected =
-      31 - __builtin_clz(__current->sig_pending &
-                         ~(__current->sig_mask | __current->sig_inprogress));
+    struct sighail* psig = &__current->sigctx;
+    struct sigact* prev_working = psig->inprogress;
+    sigset_t mask = psig->sig_mask | (prev_working ? prev_working->sa_mask : 0);
 
-    __SIGCLEAR(__current->sig_pending, sig_selected);
+    int sig_selected = 31 - __builtin_clz(psig->sig_pending & ~mask);
+
+    sigset_clear(psig->sig_pending, sig_selected);
+
+    struct sigact* action = &psig->signals[sig_selected];
 
     if (sig_selected == 0) {
         // SIG0 is reserved
         return 0;
     }
 
-    if (!__current->sig_handler[sig_selected]) {
-        if ((term_sigs & (1 << sig_selected))) {
-            terminate_proc(sig_selected);
+    if (!action->sa_actor) {
+        if (sigset_test(TERMSIG, sig_selected)) {
+            terminate_proc(sig_selected | PEXITSIG);
             schedule();
             // never return
         }
         return 0;
     }
 
-    ptr_t ustack = __current->ustack_top & ~0xf;
+    ptr_t ustack = __current->ustack_top;
 
     if ((int)(ustack - USTACK_END) < (int)sizeof(struct proc_sig)) {
         // 用户栈没有空间存放信号上下文
         return 0;
     }
 
-    struct proc_sig* sig_ctx =
-      (struct proc_sig*)(ustack - sizeof(struct proc_sig));
+    struct proc_sig* sigframe =
+      (struct proc_sig*)((ustack - sizeof(struct proc_sig)) & ~0xf);
 
     /*
         这是一个相当恶心的坑。
-        问题是出在原本的sig_ctx->prev_context = __current->intr_ctx的上面
+        问题是出在原本的sigframe->prev_context = __current->intr_ctx的上面
         这个语句会被gcc在编译时,用更加高效的 rep movsl 来代替。
 
         由于我们采用按需分页,所以在很多情况下,用户栈实际被分配的空间不允许我们进行完整的
@@ -75,14 +79,23 @@ signal_dispatch()
     __temp_save.proc_regs = __current->intr_ctx;
     memcpy(__temp_save.fxstate, __current->fxstate, 512);
 
-    sig_ctx->prev_context = __temp_save;
+    sigframe->sig_num = sig_selected;
 
-    sig_ctx->sig_num = sig_selected;
-    sig_ctx->signal_handler = __current->sig_handler[sig_selected];
+    sigframe->sigact = action->sa_actor;
+    sigframe->sighand = action->sa_handler;
+    sigframe->prev_context = __temp_save;
 
-    __SIGSET(__current->sig_inprogress, sig_selected);
+    action->prev = prev_working;
+    psig->inprogress = action;
 
-    return sig_ctx;
+    return sigframe;
+}
+
+void
+proc_setsignal(struct proc_info* proc, int signum)
+{
+    sigset_add(proc->sigctx.sig_pending, signum);
+    proc->sigctx.signals[signum].sender = __current->pid;
 }
 
 int
@@ -93,7 +106,9 @@ signal_send(pid_t pid, int signum)
         return -1;
     }
 
+    pid_t sender_pid = __current->pid;
     struct proc_info* proc;
+
     if (pid > 0) {
         proc = get_process(pid);
         goto send_single;
@@ -114,7 +129,9 @@ send_grp:
     struct proc_info *pos, *n;
     llist_for_each(pos, n, &proc->grp_member, grp_member)
     {
-        __SIGSET(pos->sig_pending, signum);
+        struct sighail* sh = &pos->sigctx;
+        sigset_add(sh->sig_pending, signum);
+        sh->signals[signum].sender = sender_pid;
     }
 
 send_single:
@@ -122,7 +139,10 @@ send_single:
         __current->k_status = EINVAL;
         return -1;
     }
-    __SIGSET(proc->sig_pending, signum);
+
+    sigset_add(proc->sigctx.sig_pending, signum);
+    proc->sigctx.signals[signum].sender = sender_pid;
+
     return 0;
 }
 
@@ -130,8 +150,15 @@ __DEFINE_LXSYSCALL1(int, sigreturn, struct proc_sig, *sig_ctx)
 {
     memcpy(__current->fxstate, sig_ctx->prev_context.fxstate, 512);
     __current->intr_ctx = sig_ctx->prev_context.proc_regs;
-    __current->flags &= ~PROC_FINPAUSE;
-    __SIGCLEAR(__current->sig_inprogress, sig_ctx->sig_num);
+
+    struct sigact* current = __current->sigctx.inprogress;
+    if (current) {
+        __current->sigctx.inprogress = current->prev;
+        current->prev = NULL;
+    } else {
+        __current->sigctx.inprogress = NULL;
+    }
+
     schedule();
 
     // never reach!
@@ -147,50 +174,48 @@ __DEFINE_LXSYSCALL3(int,
                     sigset_t,
                     *oldset)
 {
-    *oldset = __current->sig_mask;
+    struct sighail* sh = &__current->sigctx;
+    *oldset = sh->sig_mask;
+
     if (how == _SIG_BLOCK) {
-        __current->sig_mask |= *set;
+        sigset_union(sh->sig_mask, *set);
     } else if (how == _SIG_UNBLOCK) {
-        __current->sig_mask &= ~(*set);
+        sigset_intersect(sh->sig_mask, ~(*set));
     } else if (how == _SIG_SETMASK) {
-        __current->sig_mask = *set;
+        sh->sig_mask = *set;
     } else {
         return 0;
     }
-    __current->sig_mask &= ~_SIGNAL_UNMASKABLE;
+
+    sigset_intersect(sh->sig_mask, ~UNMASKABLE);
     return 1;
 }
 
-__DEFINE_LXSYSCALL2(int, signal, int, signum, sighandler_t, handler)
+__DEFINE_LXSYSCALL2(int, sys_sigaction, int, signum, struct sigaction*, action)
 {
     if (signum <= 0 || signum >= _SIG_NUM) {
         return -1;
     }
 
-    if ((__SIGNAL(signum) & _SIGNAL_UNMASKABLE)) {
+    if (sigset_test(UNMASKABLE, signum)) {
         return -1;
     }
 
-    __current->sig_handler[signum] = (void*)handler;
+    struct sigact* sa = &__current->sigctx.signals[signum];
+
+    sa->sa_actor = (void*)action->sa_sigaction;
+    sa->sa_handler = (void*)action->sa_handler;
+    sigset_union(sa->sa_mask, sigset(signum));
 
     return 0;
 }
 
-void
-__do_pause()
+__DEFINE_LXSYSCALL(int, pause)
 {
-    __current->flags |= PROC_FINPAUSE;
-
-    while ((__current->flags & PROC_FINPAUSE)) {
-        sched_yieldk();
-    }
+    pause_current();
+    sched_yieldk();
 
     __current->k_status = EINTR;
-}
-
-__DEFINE_LXSYSCALL(int, pause)
-{
-    __do_pause();
     return -1;
 }
 
@@ -201,15 +226,18 @@ __DEFINE_LXSYSCALL2(int, kill, pid_t, pid, int, signum)
 
 __DEFINE_LXSYSCALL1(int, sigpending, sigset_t, *sigset)
 {
-    *sigset = __current->sig_pending;
+    *sigset = __current->sigctx.sig_pending;
     return 0;
 }
 
 __DEFINE_LXSYSCALL1(int, sigsuspend, sigset_t, *mask)
 {
-    sigset_t tmp = __current->sig_mask;
-    __current->sig_mask = (*mask) & ~_SIGNAL_UNMASKABLE;
-    __do_pause();
-    __current->sig_mask = tmp;
+    sigset_t tmp = __current->sigctx.sig_mask;
+    __current->sigctx.sig_mask = (*mask) & ~UNMASKABLE;
+
+    pause_current();
+    sched_yieldk();
+
+    __current->sigctx.sig_mask = tmp;
     return -1;
 }
\ No newline at end of file
index 7c954b30ea9c3a44510885d0e389dbd8de379c05..1cca227937fdbc980ae9e9703118ee3f80e11cd5 100644 (file)
@@ -5,14 +5,14 @@ void
 __read_pending_sig(struct twimap* map)
 {
     struct proc_info* proc = twimap_data(map, struct proc_info*);
-    twimap_printf(map, "%bb", proc->sig_pending);
+    twimap_printf(map, "%bb", proc->sigctx.sig_pending);
 }
 
 void
 __read_masked_sig(struct twimap* map)
 {
     struct proc_info* proc = twimap_data(map, struct proc_info*);
-    twimap_printf(map, "%bb", proc->sig_mask);
+    twimap_printf(map, "%bb", proc->sigctx.sig_mask);
 }
 
 void
index 4ea6b4eecb72d755e225800c1bdb59d6bc3753bf..d2d39f0d276bf1a03081ee2fe80be710f658fe96 100644 (file)
@@ -37,17 +37,15 @@ SECTIONS {
     /* 好了,我们的内核…… */
     .text BLOCK(4K) : AT ( ADDR(.text) - 0xC0000000 ) {
         __kernel_start = .;
+        PROVIDE(__ktext_start = .);
+        
         kernel/*.o (.text)
         hal/*.o (.text)
         debug/*.o (.text)
         libs/*.o (.text)
-    }
 
-    __usrtext_start = ALIGN(4K);
-    .usrtext BLOCK(4K) : AT ( ADDR(.usrtext) - 0xC0000000 ) {
-        * (.usrtext)
+        PROVIDE(__ktext_end = .);
     }
-    __usrtext_end = ALIGN(4K);
 
     .data BLOCK(4K) : AT ( ADDR(.data) - 0xC0000000 ) {
         kernel/*.o (.data)
index 681f193100c42dc7d8d817cbf1a631bca37b19bb..d4026c604e3a0c1246fcd116c0c15055c7630e6b 100644 (file)
@@ -1,7 +1,6 @@
 #include "syscall.h"
 #include <lunaix/signal_defs.h>
-
-__LXSYSCALL2(int, signal, int, signum, sighandler_t, handler);
+#include <lunaix/types.h>
 
 __LXSYSCALL1(int, sigpending, sigset_t, *set);
 __LXSYSCALL1(int, sigsuspend, const sigset_t, *mask);
@@ -14,3 +13,48 @@ __LXSYSCALL3(int,
              *set,
              sigset_t,
              *oldset);
+
+__LXSYSCALL2(int, sys_sigaction, int, signum, struct sigaction*, action);
+
+__LXSYSCALL2(int, kill, pid_t, pid, int, signum);
+
+extern void
+sigtrampoline();
+
+sighandler_t
+signal(int signum, sighandler_t handler)
+{
+    struct sigaction sa = { .sa_handler = (void*)handler,
+                            .sa_mask = (sigset_t)-1,
+                            .sa_sigaction = (void*)sigtrampoline };
+
+    sys_sigaction(signum, &sa);
+
+    return handler;
+}
+
+int
+raise(int signum)
+{
+    return kill(0, signum);
+}
+
+int
+sigaction(int signum, struct sigaction* action)
+{
+    return sys_sigaction(signum, action);
+}
+
+struct siguctx
+{
+    void* sigact;
+    void (*sa_handler)(int);
+    unsigned char saved_frame[0];
+};
+
+void
+sig_dohandling(int signum, void* siginfo, void* sigctx)
+{
+    struct siguctx* uctx = (struct siguctx*)sigctx;
+    uctx->sa_handler(signum);
+}
\ No newline at end of file
diff --git a/lunaix-os/usr/libc/arch/i386/trampoline.S b/lunaix-os/usr/libc/arch/i386/trampoline.S
new file mode 100644 (file)
index 0000000..9261e4b
--- /dev/null
@@ -0,0 +1,20 @@
+#include <lunaix/syscallid.h>
+
+.section .text
+    .global sigtrampoline
+    sigtrampoline:
+        movl %esp, %eax
+        andl $0xfffffff0, %esp
+        pushl %eax
+        
+        leal 4(%eax), %eax
+        pushl %eax
+        pushl $0
+        pushl -4(%eax)
+        call sig_dohandling
+
+        addl $12, %esp
+        
+        movl $__SYSCALL_sigreturn, %eax
+        popl %ebx
+        int $33
\ No newline at end of file
index 9790cb188f8ab37b424bd0e5f6939ed5ec00b96f..a8c8443b47138641b4afe031b3debf238f41ea2c 100644 (file)
@@ -21,8 +21,6 @@ __LXSYSCALL1(unsigned int, sleep, unsigned int, seconds)
 
 __LXSYSCALL(int, pause)
 
-__LXSYSCALL2(int, kill, pid_t, pid, int, signum)
-
 __LXSYSCALL1(unsigned int, alarm, unsigned int, seconds)
 
 __LXSYSCALL2(int, link, const char*, oldpath, const char*, newpath)
index 0e6cce2b31b10e32dcbeb6d055553ace470e187a..b05dec5f2fb4f12ba4466eb733f3df085aaf1eb7 100644 (file)
@@ -4,9 +4,18 @@
 #include <lunaix/signal_defs.h>
 #include <lunaix/types.h>
 
-extern int
+extern sighandler_t
 signal(int signum, sighandler_t handler);
 
+extern int
+kill(pid_t pid, int signum);
+
+extern int
+raise(int signum);
+
+extern int
+sigaction(int signum, struct sigaction* action);
+
 extern int
 sigpending(sigset_t* set);
 
index 24e519f9757d4b37444c13f78868a3f60e8cd226..a5bf1e5bb2f4e78dd1d2a66a931cfe2fd81a0378 100644 (file)
@@ -35,9 +35,6 @@ sleep(unsigned int);
 extern int
 pause();
 
-extern int
-kill(pid_t pid, int signum);
-
 extern unsigned int
 alarm(unsigned int seconds);
 
index 612e132a6d4aaf2b226b97f6c864f09dc1f6c56a..b20f4adb92e0ce39bda4a0a67119904fec95c785 100644 (file)
@@ -31,11 +31,11 @@ main()
     signal(SIGSEGV, sigsegv_handler);
     signal(SIGALRM, sigalrm_handler);
 
-    alarm(5);
-
     int status;
     pid_t p = 0;
 
+    alarm(5);
+
     printf("Child sleep 3s, parent pause.\n");
     if (!fork()) {
         sleep(3);