git://scm.lunaixsky.com
/
lunaix-os.git
/ commitdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
| commitdiff |
tree
raw
|
patch
|
inline
| side by side (parent:
8fdcd15
)
feat: signal support (tested!)
author
Minep
<zelong56@gmail.com>
Sun, 19 Jun 2022 17:56:28 +0000
(18:56 +0100)
committer
Minep
<zelong56@gmail.com>
Sun, 19 Jun 2022 17:56:28 +0000
(18:56 +0100)
feat: signal demo.
lunaix-os/includes/lunaix/signal.h
patch
|
blob
|
history
lunaix-os/includes/lunaix/spike.h
patch
|
blob
|
history
lunaix-os/kernel/asm/x86/interrupt.S
patch
|
blob
|
history
lunaix-os/kernel/asm/x86/interrupts.c
patch
|
blob
|
history
lunaix-os/kernel/lxinit.c
patch
|
blob
|
history
lunaix-os/kernel/sched.c
patch
|
blob
|
history
lunaix-os/kernel/signal.c
patch
|
blob
|
history
diff --git
a/lunaix-os/includes/lunaix/signal.h
b/lunaix-os/includes/lunaix/signal.h
index 4a4cf0b725234ba2f65ad2fc3276f3fecc1a4041..d1f7041ebd284257b8ce8730f3c155a6d56d426e 100644
(file)
--- a/
lunaix-os/includes/lunaix/signal.h
+++ b/
lunaix-os/includes/lunaix/signal.h
@@
-1,6
+1,8
@@
#ifndef __LUNAIX_SIGNAL_H
#define __LUNAIX_SIGNAL_H
#ifndef __LUNAIX_SIGNAL_H
#define __LUNAIX_SIGNAL_H
+#include <lunaix/syscall.h>
+
#define _SIG_NUM 8
#define _SIG_PENDING(bitmap, sig) ((bitmap) & (1 << (sig)))
#define _SIG_NUM 8
#define _SIG_PENDING(bitmap, sig) ((bitmap) & (1 << (sig)))
@@
-8,13
+10,16
@@
#define _SIGSEGV 0
#define _SIGALRM 1
#define _SIGCHLD 2
#define _SIGSEGV 0
#define _SIGALRM 1
#define _SIGCHLD 2
-#define _SIGCLD SIGCHLD
+#define _SIGCLD
_
SIGCHLD
#define _SIGINT 3
#define _SIGKILL 4
#define _SIGSTOP 5
#define _SIGCONT 6
#define _SIGINT 3
#define _SIGKILL 4
#define _SIGSTOP 5
#define _SIGCONT 6
-#define _SIGNAL_UNMASKABLE ((1 << _SIGKILL) | (1 << _SIGSTOP))
+#define __SIGNAL(num) (1 << (num))
+#define __SET_SIGNAL(bitmap, num) (bitmap = bitmap | __SIGNAL(num))
+
+#define _SIGNAL_UNMASKABLE (__SIGNAL(_SIGKILL) | __SIGNAL(_SIGSTOP))
#define _SIG_BLOCK 1
#define _SIG_UNBLOCK 2
#define _SIG_BLOCK 1
#define _SIG_UNBLOCK 2
@@
-23,4
+28,6
@@
typedef unsigned int sigset_t;
typedef void (*sighandler_t)(int);
typedef unsigned int sigset_t;
typedef void (*sighandler_t)(int);
+__LXSYSCALL2(int, signal, int, signum, sighandler_t, handler);
+
#endif /* __LUNAIX_SIGNAL_H */
#endif /* __LUNAIX_SIGNAL_H */
diff --git
a/lunaix-os/includes/lunaix/spike.h
b/lunaix-os/includes/lunaix/spike.h
index 1ce7481aabfb752242dff6ab7e018c3618fba07b..48a19045dbb5b801d5e901856b9c391f8ed4ec81 100644
(file)
--- a/
lunaix-os/includes/lunaix/spike.h
+++ b/
lunaix-os/includes/lunaix/spike.h
@@
-15,7
+15,7
@@
// 获取v最近的最小k倍数
#define ROUNDDOWN(v, k) ((v) & ~((k)-1))
// 获取v最近的最小k倍数
#define ROUNDDOWN(v, k) ((v) & ~((k)-1))
-#define __USER__ __attribute__((section("usrtext")))
+#define __USER__ __attribute__((section("
.
usrtext")))
inline static void
spin()
inline static void
spin()
diff --git
a/lunaix-os/kernel/asm/x86/interrupt.S
b/lunaix-os/kernel/asm/x86/interrupt.S
index e9419837ab5b6c07ea36b9a23173b4aec3d15ba4..48dff2faff1850a4be0b7aca45926d76ab357118 100644
(file)
--- a/
lunaix-os/kernel/asm/x86/interrupt.S
+++ b/
lunaix-os/kernel/asm/x86/interrupt.S
@@
-22,6
+22,12
@@
.skip 16
#endif
.skip 16
#endif
+.section .bss
+ .align 16
+ lo_tmp_stack:
+ .skip 128
+ tmp_stack:
+
.section .text
isr_template FAULT_DIVISION_ERROR
isr_template FAULT_GENERAL_PROTECTION, no_error_code=0
.section .text
isr_template FAULT_DIVISION_ERROR
isr_template FAULT_GENERAL_PROTECTION, no_error_code=0
@@
-128,23
+134,30
@@
addl $8, %esp
addl $8, %esp
-#ifdef __ASM_INTR_DIAGNOSIS
pushl %eax
pushl %eax
+#ifdef __ASM_INTR_DIAGNOSIS
movl 4(%esp), %eax
movl %eax, debug_resv
movl 4(%esp), %eax
movl %eax, debug_resv
- popl %eax
#endif
#endif
+ # 处理TSS.ESP的一些边界条件。如果是正常iret(即从内核模式*优雅地*退出)
+ # 那么TSS.ESP0应该为iret进行弹栈后,%esp的值。
+ # 所以这里的边界条件是:如返回用户模式,iret会额外弹出8个字节(ss,esp)
+ movl 8(%esp), %eax
+ andl $3, %eax
+ setnz %al
+ shll $3, %eax
+ addl $16, %eax
+ addl %esp, %eax
+ movl %eax, (_tss + 4)
+ popl %eax
iret
.global switch_to
switch_to:
# 约定
iret
.global switch_to
switch_to:
# 约定
- # arg1: 目标进程PCB地址 (next)
- popl %ecx # next
-
- call signal_dispatch # kernel/signal.c
- movl %eax, %edx
+ # arg1: 目标进程PCB地址 (next
+ popl %ecx # next
movl __current, %eax
movl 88(%eax), %ebx # __current->pagetable
movl 88(%ecx), %eax # next->pagetable
movl __current, %eax
movl 88(%eax), %ebx # __current->pagetable
movl 88(%ecx), %eax # next->pagetable
@@
-156,9
+169,13
@@
1:
movl %ecx, __current # __current = next
1:
movl %ecx, __current # __current = next
- test %edx, %edx # do we have signal to handle?
+ # 我们已经处在了新的地址空间,为了避免影响其先前的栈布局
+ # 需要使用一个临时的栈空间
+ movl $tmp_stack, %esp
+ call signal_dispatch # kernel/signal.c
+
+ test %eax, %eax # do we have signal to handle?
jz 1f
jz 1f
- movl %edx, %eax
jmp handle_signal
1:
leal 8(%ecx), %eax
jmp handle_signal
1:
leal 8(%ecx), %eax
@@
-170,7
+187,7
@@
# 注意2:handle_signal在调用之前,须确保proc_sig已经写入用户栈!
leal 8(%eax), %ebx # arg1 in %eax: addr of proc_sig structure in user stack
# 注意2:handle_signal在调用之前,须确保proc_sig已经写入用户栈!
leal 8(%eax), %ebx # arg1 in %eax: addr of proc_sig structure in user stack
- pushl
72(%ebx)
# proc_sig->prev_context.ss
+ pushl
$UDATA_SEG
# proc_sig->prev_context.ss
pushl %eax # esp
pushl 64(%ebx) # proc_sig->prev_context.eflags
pushl $UCODE_SEG # cs
pushl %eax # esp
pushl 64(%ebx) # proc_sig->prev_context.eflags
pushl $UCODE_SEG # cs
diff --git
a/lunaix-os/kernel/asm/x86/interrupts.c
b/lunaix-os/kernel/asm/x86/interrupts.c
index 688799f29212f26548502b1fa9e0a6bcf89a024b..864c7da58af3df7f09a292feee299df532474e43 100644
(file)
--- a/
lunaix-os/kernel/asm/x86/interrupts.c
+++ b/
lunaix-os/kernel/asm/x86/interrupts.c
@@
-1,4
+1,5
@@
#include <arch/x86/interrupts.h>
#include <arch/x86/interrupts.h>
+#include <arch/x86/tss.h>
#include <hal/apic.h>
#include <hal/cpu.h>
#include <lunaix/mm/page.h>
#include <hal/apic.h>
#include <hal/cpu.h>
#include <lunaix/mm/page.h>
diff --git
a/lunaix-os/kernel/lxinit.c
b/lunaix-os/kernel/lxinit.c
index 57e2bda22421da102c8b063bca8adfd2f1fd58c4..1485c3411e4d95266642876f8481f0b9b3168173 100644
(file)
--- a/
lunaix-os/kernel/lxinit.c
+++ b/
lunaix-os/kernel/lxinit.c
@@
-5,6
+5,7
@@
#include <lunaix/mm/kalloc.h>
#include <lunaix/mm/vmm.h>
#include <lunaix/proc.h>
#include <lunaix/mm/kalloc.h>
#include <lunaix/mm/vmm.h>
#include <lunaix/proc.h>
+#include <lunaix/signal.h>
#include <lunaix/spike.h>
#include <lunaix/syslog.h>
#include <lunaix/timer.h>
#include <lunaix/spike.h>
#include <lunaix/syslog.h>
#include <lunaix/timer.h>
@@
-18,6
+19,12
@@
LOG_MODULE("INIT")
#define WAIT_DEMO
#define IN_USER_MODE
#define WAIT_DEMO
#define IN_USER_MODE
+void __USER__
+sigchild_handler(int signum)
+{
+ kprintf(KINFO "SIGCHLD received\n");
+}
+
void __USER__
_lxinit_main()
{
void __USER__
_lxinit_main()
{
@@
-31,6
+38,8
@@
_lxinit_main()
}
#endif
}
#endif
+ signal(_SIGCHLD, sigchild_handler);
+
int status;
#ifdef WAIT_DEMO
// 测试wait
int status;
#ifdef WAIT_DEMO
// 测试wait
@@
-57,7
+66,7
@@
_lxinit_main()
waitpid(-1, &status, WNOHANG);
waitpid(-1, &status, WNOHANG);
- for (size_t i = 0; i <
5
; i++) {
+ for (size_t i = 0; i <
10
; i++) {
pid_t pid = 0;
if (!(pid = fork())) {
sleep(i);
pid_t pid = 0;
if (!(pid = fork())) {
sleep(i);
diff --git
a/lunaix-os/kernel/sched.c
b/lunaix-os/kernel/sched.c
index 1a9743dd9752b182e6e151ef645a91c1d76eea68..50f5f67ceaa6cf209d885fd7e9b78ebaa3ef8635 100644
(file)
--- a/
lunaix-os/kernel/sched.c
+++ b/
lunaix-os/kernel/sched.c
@@
-49,8
+49,15
@@
run(struct proc_info* proc)
}
proc->state = PROC_RUNNING;
}
proc->state = PROC_RUNNING;
- // XXX: 我们需要这一步吗?
- // tss_update_esp(__current->intr_ctx.esp);
+ /*
+ 将tss.esp0设置为上次调度前的esp值。
+ 当处理信号时,上下文信息是不会恢复的,而是保存在用户栈中,然后直接跳转进位于用户空间的sig_wrapper进行
+ 信号的处理。当用户自定义的信号处理函数返回时,sigreturn的系统调用才开始进行上下文的恢复(或者说是进行
+ 另一次调度。
+ 由于这中间没有进行地址空间的交换,所以第二次跳转使用的是同一个内核栈,而之前默认tss.esp0的值是永远指向最顶部
+ 这样一来就有可能会覆盖更早的上下文信息(比如嵌套的信号捕获函数)
+ */
+ tss_update_esp(proc->intr_ctx.registers.esp);
apic_done_servicing();
apic_done_servicing();
@@
-258,6
+265,8
@@
terminate_proc(int exit_code)
__current->state = PROC_TERMNAT;
__current->exit_code = exit_code;
__current->state = PROC_TERMNAT;
__current->exit_code = exit_code;
+ __SET_SIGNAL(__current->parent->sig_pending, _SIGCHLD);
+
schedule();
}
schedule();
}
diff --git
a/lunaix-os/kernel/signal.c
b/lunaix-os/kernel/signal.c
index 4c0bb56ad27b307c1e1b44641d47e28db1b88799..49f1e534f6c65d06c4d0ba916847867e66cc491c 100644
(file)
--- a/
lunaix-os/kernel/signal.c
+++ b/
lunaix-os/kernel/signal.c
@@
-26,7
+26,7
@@
signal_dispatch()
int sig_selected =
31 - __builtin_clz(__current->sig_pending & ~__current->sig_mask);
int sig_selected =
31 - __builtin_clz(__current->sig_pending & ~__current->sig_mask);
- __current->sig_pending = __current->sig_pending & ~
(1 <<
sig_selected);
+ __current->sig_pending = __current->sig_pending & ~
__SIGNAL(
sig_selected);
if (!__current->sig_handler[sig_selected] &&
!default_handlers[sig_selected]) {
if (!__current->sig_handler[sig_selected] &&
!default_handlers[sig_selected]) {
@@
-34,7
+34,7
@@
signal_dispatch()
return 0;
}
return 0;
}
- uintptr_t ustack = __current->ustack_top;
+ uintptr_t ustack = __current->ustack_top
& ~0xf
;
if ((int)(ustack - USTACK_END) < (int)sizeof(struct proc_sig)) {
// 用户栈没有空间存放信号上下文
if ((int)(ustack - USTACK_END) < (int)sizeof(struct proc_sig)) {
// 用户栈没有空间存放信号上下文
@@
-53,12
+53,15
@@
signal_dispatch()
sig_ctx->signal_handler = default_handlers[sig_selected];
}
sig_ctx->signal_handler = default_handlers[sig_selected];
}
+ __current->sig_mask |= __SIGNAL(sig_selected);
+
return sig_ctx;
}
__DEFINE_LXSYSCALL1(int, sigreturn, struct proc_sig, *sig_ctx)
{
__current->intr_ctx = sig_ctx->prev_context;
return sig_ctx;
}
__DEFINE_LXSYSCALL1(int, sigreturn, struct proc_sig, *sig_ctx)
{
__current->intr_ctx = sig_ctx->prev_context;
+ __current->sig_mask &= ~__SIGNAL(sig_ctx->sig_num);
schedule();
}
schedule();
}