.vscode/*.log
.VSCodeCounter/
.idea
+bx_enh_dbg.ini
\ No newline at end of file
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
#include <stdint.h>
+#define SEL_RPL(selector) ((selector)&0x3)
+
typedef unsigned int reg32;
typedef unsigned short reg16;
#ifndef __LUNAIX_PROCESS_H
#define __LUNAIX_PROCESS_H
-#include <stdint.h>
#include <arch/x86/interrupts.h>
-#include <lunaix/mm/mm.h>
-#include <lunaix/types.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>
// 虽然内核不是进程,但为了区分,这里使用Pid=-1来指代内核。这主要是方便物理页所有权检查。
#define KERNEL_PID -1
#define PROC_TERMMASK 0x6
-
-struct proc_mm {
+struct proc_mm
+{
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;
- 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;
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;
+pid_t
+alloc_pid();
-pid_t alloc_pid();
-
-void init_proc(struct proc_info *pcb);
+void
+init_proc(struct proc_info* pcb);
/**
* @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) 实现)
- *
+ *
*/
-pid_t dup_proc();
+pid_t
+dup_proc();
/**
* @brief 创建新进程(LunaixOS的类 CreateProcess (Windows) 实现)
- *
+ *
*/
-void new_proc();
+void
+new_proc();
/**
* @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 */
--- /dev/null
+#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 */
#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
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) \
#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
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
.global soft_iret
soft_iret:
+ cli
popl %esp
popl %eax
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
.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
popl %ebp
- ret
-
-
+ ret
\ No newline at end of file
#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>
apic_done_servicing();
+ signal_dispatch();
+
asm volatile("pushl %0\n"
"jmp soft_iret\n" ::"r"(&__current->intr_ctx)
: "memory");
--- /dev/null
+#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