From: Minep Date: Thu, 16 Jun 2022 16:20:38 +0000 (+0100) Subject: Merge branch 'master' into signal-dev X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/commitdiff_plain/58bc147210ab1363ee9ddc169a8e1c46ce24cf29?hp=efbabf3bcf37c1da148c1e7579974999021f2b86 Merge branch 'master' into signal-dev --- diff --git a/lunaix-os/bx_enh_dbg.ini b/lunaix-os/bx_enh_dbg.ini index 5e8e298..3486095 100644 --- a/lunaix-os/bx_enh_dbg.ini +++ b/lunaix-os/bx_enh_dbg.ini @@ -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 diff --git a/lunaix-os/includes/hal/cpu.h b/lunaix-os/includes/hal/cpu.h index fe633d0..af56120 100644 --- a/lunaix-os/includes/hal/cpu.h +++ b/lunaix-os/includes/hal/cpu.h @@ -3,6 +3,8 @@ #include +#define SEL_RPL(selector) ((selector)&0x3) + typedef unsigned int reg32; typedef unsigned short reg16; diff --git a/lunaix-os/includes/lunaix/proc.h b/lunaix-os/includes/lunaix/proc.h index a6f4470..eafae4f 100644 --- a/lunaix-os/includes/lunaix/proc.h +++ b/lunaix-os/includes/lunaix/proc.h @@ -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 */ diff --git a/lunaix-os/includes/lunaix/process.h b/lunaix-os/includes/lunaix/process.h index 32b74df..28cb76b 100644 --- a/lunaix-os/includes/lunaix/process.h +++ b/lunaix-os/includes/lunaix/process.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -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 index 0000000..c98441a --- /dev/null +++ b/lunaix-os/includes/lunaix/signal.h @@ -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 */ diff --git a/lunaix-os/includes/lunaix/syscall.h b/lunaix-os/includes/lunaix/syscall.h index 37aa852..3a6e2eb 100644 --- a/lunaix-os/includes/lunaix/syscall.h +++ b/lunaix-os/includes/lunaix/syscall.h @@ -13,6 +13,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 @@ -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) \ diff --git a/lunaix-os/kernel/asm/x86/interrupt.S b/lunaix-os/kernel/asm/x86/interrupt.S index a03bce6..27bdc4c 100644 --- a/lunaix-os/kernel/asm/x86/interrupt.S +++ b/lunaix-os/kernel/asm/x86/interrupt.S @@ -1,6 +1,7 @@ #define __ASM__ #include #include +#include #define __ASM_INTR_DIAGNOSIS .macro isr_template vector, no_error_code=1 @@ -38,10 +39,10 @@ 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 @@ -88,6 +90,12 @@ 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 @@ -126,3 +134,39 @@ 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 diff --git a/lunaix-os/kernel/asm/x86/syscall.S b/lunaix-os/kernel/asm/x86/syscall.S index 2e36196..e97cc6f 100644 --- a/lunaix-os/kernel/asm/x86/syscall.S +++ b/lunaix-os/kernel/asm/x86/syscall.S @@ -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 diff --git a/lunaix-os/kernel/lxinit.c b/lunaix-os/kernel/lxinit.c index fa8458c..43f0f2d 100644 --- a/lunaix-os/kernel/lxinit.c +++ b/lunaix-os/kernel/lxinit.c @@ -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())) { diff --git a/lunaix-os/kernel/proc0.c b/lunaix-os/kernel/proc0.c index dac1b55..074bcd9 100644 --- a/lunaix-os/kernel/proc0.c +++ b/lunaix-os/kernel/proc0.c @@ -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"); } diff --git a/lunaix-os/kernel/process.c b/lunaix-os/kernel/process.c index 64f2654..020dfb4 100644 --- a/lunaix-os/kernel/process.c +++ b/lunaix-os/kernel/process.c @@ -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; diff --git a/lunaix-os/kernel/sched.c b/lunaix-os/kernel/sched.c index 8c43b14..026fb51 100644 --- a/lunaix-os/kernel/sched.c +++ b/lunaix-os/kernel/sched.c @@ -1,12 +1,14 @@ #include #include + #include #include + #include #include #include #include - +#include #include #include #include @@ -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 index 0000000..3edb2f4 --- /dev/null +++ b/lunaix-os/kernel/signal.c @@ -0,0 +1,101 @@ +#include +#include +#include +#include + +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 diff --git a/lunaix-os/kernel/syscall.c b/lunaix-os/kernel/syscall.c index 0d41470..ce0f2a7 100644 --- a/lunaix-os/kernel/syscall.c +++ b/lunaix-os/kernel/syscall.c @@ -1,13 +1,16 @@ -#include #include #include #include +#include #include 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