#define __ASM__
-#include <arch/i386/interrupts.h>
-#include <arch/i386/i386_asm.h>
-#include <arch/i386/tss.h>
+#include <sys/interrupts.h>
+#include <sys/abi.h>
+#include <sys/interrupt.S.inc>
+
#include <lunaix/syscall.h>
-#include <arch/i386/interrupt.S.inc>
#define __ASM_INTR_DIAGNOSIS
*/
.section .text
+ .type interrupt_wrapper, @function
.global interrupt_wrapper
interrupt_wrapper:
cld
subl $16, %esp
movl %eax, (%esp)
+ xorl %ebp, %ebp # marks the boundary of stack walking
call intr_handler
movl (%esp), %eax
iret
+ .type switch_to, @function
.global switch_to
switch_to:
# 约定
# arg1: 目标进程PCB地址 (next
- popl %ebx # next
+ movl %eax, %ebx # next
movl __current, %eax
movl proc_page_table(%eax), %ecx # __current->pagetable
movl proc_page_table(%ebx), %eax # next->pagetable
test %eax, %eax # do we have signal to handle?
jz 1f
- # 更新 tss
+ /*
+ 将tss.esp0设置为上次调度前的esp值。
+ 当处理信号时,上下文信息是不会恢复的,而是保存在用户栈中,然后直接跳转进位于用户空间的sig_wrapper进行
+ 信号的处理。当用户自定义的信号处理函数返回时,sigreturn的系统调用才开始进行上下文的恢复(或者说是进行
+ 另一次调度。
+ 由于这中间没有进行地址空间的交换,所以第二次跳转使用的是同一个内核栈,而之前默认tss.esp0的值是永远指向最顶部
+ 这样一来就有可能会覆盖更早的上下文信息(比如嵌套的信号捕获函数)
+ */
movl proc_intr_ctx(%ebx), %ecx # __current->intr_ctx
movl %ecx, (tss_esp0_off + _tss)
movl proc_intr_ctx(%ebx), %eax
jmp soft_iret
+ .type handle_signal, @function
.global handle_signal
handle_signal:
# 注意1:任何对proc_sig的布局改动,都须及时的保证这里的一致性!