From b744e1ecfe0ee39addd8626281b30206eeeeec08 Mon Sep 17 00:00:00 2001 From: AceVest Date: Thu, 8 May 2014 00:40:27 +0800 Subject: [PATCH] support preempt --- boot/multiboot.S | 2 +- include/system.h | 46 ++++++++++++++++++++++++++++++++++++--------- include/task.h | 9 ++++++--- kernel/interrupts.S | 24 +++++++++++++++++++---- kernel/irq.c | 7 +++++++ kernel/sched.c | 5 +++++ kernel/syscall.S | 7 ++----- lib/string.c | 2 +- setup/setup.c | 4 ++-- 9 files changed, 81 insertions(+), 25 deletions(-) diff --git a/boot/multiboot.S b/boot/multiboot.S index dcce87b..7b8feb3 100644 --- a/boot/multiboot.S +++ b/boot/multiboot.S @@ -1,6 +1,6 @@ /* *-------------------------------------------------------------------------- - * File Name: reboot.S + * File Name: multiboot.S * * Description: none * diff --git a/include/system.h b/include/system.h index f0f66e9..61c8167 100644 --- a/include/system.h +++ b/include/system.h @@ -21,6 +21,24 @@ #include #define KRNLADDR PAGE_OFFSET +#define PT_REGS_EDI 0 +#define PT_REGS_ESI 4 +#define PT_REGS_EBP 8 +#define PT_REGS_EBX 12 +#define PT_REGS_EDX 16 +#define PT_REGS_ECX 20 +#define PT_REGS_EAX 24 +#define PT_REGS_DS 28 +#define PT_REGS_ES 32 +#define PT_REGS_FS 36 +#define PT_REGS_GS 40 +#define PT_REGS_IRQ 44 +#define PT_REGS_EIP 48 +#define PT_REGS_CS 52 +#define PT_REGS_EFLAGS 56 +#define PT_REGS_ESP 60 +#define PT_REGS_SS 64 + #ifndef ASM #include "types.h" #include "printk.h" @@ -105,7 +123,6 @@ typedef struct pt_regs u32 edi; u32 esi; u32 ebp; - u32 esp; u32 ebx; u32 edx; u32 ecx; @@ -122,7 +139,7 @@ typedef struct pt_regs u32 eip; u16 cs, _cs; u32 eflags; - u32 _esp; + u32 esp; u16 ss, _ss; } __attribute__((packed)) pt_regs_t; @@ -168,17 +185,28 @@ extern System system; #endif - #define SAVE_REGS \ cld; \ - pushl %gs; \ - pushl %fs; \ - pushl %es; \ - pushl %ds; \ - pushal; + pushl %gs; \ + pushl %fs; \ + pushl %es; \ + pushl %ds; \ + pushl %eax; \ + pushl %ecx; \ + pushl %edx; \ + pushl %ebx; \ + pushl %ebp; \ + pushl %esi; \ + pushl %edi; #define RESTORE_REGS \ - popal; \ + popl %edi; \ + popl %esi; \ + popl %ebp; \ + popl %ebx; \ + popl %edx; \ + popl %ecx; \ + popl %eax; \ popl %ds; \ popl %es; \ popl %fs; \ diff --git a/include/task.h b/include/task.h index 73df36f..f16cb61 100644 --- a/include/task.h +++ b/include/task.h @@ -15,6 +15,8 @@ #define TASK_SIZE 4096 +#define TI_preempt_cnt 0 + #ifndef ASM #include #include @@ -37,12 +39,13 @@ typedef union task_union { struct { + unsigned long preempt_cnt; + pt_regs_t regs; - unsigned long esp0; /* 指示发生在用户态的中断在进入 - 内核态后的栈位置 */ + unsigned long esp0; /* kernel stack */ - /* 进程切换时用 */ + /* for context switch */ unsigned long esp; unsigned long eip; diff --git a/kernel/interrupts.S b/kernel/interrupts.S index 942f8cf..8ddd209 100644 --- a/kernel/interrupts.S +++ b/kernel/interrupts.S @@ -16,6 +16,7 @@ #define ASM #include #include +#include #define IRQ_SYMBL(a,b) irq_0x##a##b_handler #define IRQ_LIST(x) \ @@ -68,7 +69,7 @@ DEF_IRQ(0,F) _irq_handler: SAVE_REGS - movw %ss,%ax + movw %ss, %ax movw %ax, %ds movw %ax, %es movw %ax, %fs @@ -77,11 +78,26 @@ _irq_handler: movl %esp, %eax call irq_handler + movl $-TASK_SIZE, %ebp + andl %esp, %ebp + + movl PT_REGS_CS(%esp), %eax + testl $0x0003, %eax + jz resume_kernel + +resched: + call schedule - # movl current, %esp - +restore_regs: + RESTORE_REGS - addl $4,%esp /* 跳过中断号. */ + addl $4, %esp + iret + +resume_kernel: + cmpl $0, TI_preempt_cnt(%ebp) + jz resched + jmp restore_regs diff --git a/kernel/irq.c b/kernel/irq.c index 5ce8c42..f92fac0 100644 --- a/kernel/irq.c +++ b/kernel/irq.c @@ -17,6 +17,7 @@ #include #include #include +#include irq_desc_t irq_desc[NR_IRQS]; @@ -45,8 +46,11 @@ __attribute__ ((regparm(1))) void irq_handler(pt_regs_t *regs) irq_desc_t *p = irq_desc + irq; irq_action_t *action = p->action; + current->preempt_cnt++; + p->chip->ack(irq); sti(); + while(action) { //action->handler(regs, irq); @@ -54,7 +58,10 @@ __attribute__ ((regparm(1))) void irq_handler(pt_regs_t *regs) action = action->next; } + cli(); p->chip->enable(irq); + + current->preempt_cnt--; } diff --git a/kernel/sched.c b/kernel/sched.c index 3afe834..0a5ea9c 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -55,6 +55,11 @@ void init_root_tsk() { int i; + // never use memset to init root_task + // because the stack is at top of the root_task + // memset((char*)&root_task, 0, sizeof(root_task)); + + root_task.preempt_cnt = 0; root_task.pid = get_next_pid(); root_task.ppid = 0; INIT_LIST_HEAD(&root_task.list); diff --git a/kernel/syscall.S b/kernel/syscall.S index d0b0c90..6dbce73 100644 --- a/kernel/syscall.S +++ b/kernel/syscall.S @@ -28,9 +28,6 @@ .global ret_from_fork_krnl .global sysexit -#define EAX 28 -#define EDX 20 - syscall_entry: movl (%esp),%esp @@ -57,7 +54,7 @@ syscall_entry: call *sysc_handler_table(,%eax,4) syscall_exit: - movl %eax, EAX(%esp) + movl %eax, PT_REGS_EAX(%esp) RESTORE_REGS @@ -78,7 +75,7 @@ ret_from_fork_user: jmp syscall_exit ret_from_fork_krnl: - movl EDX(%esp), %edx + movl PT_REGS_EDX(%esp), %edx call *%edx #call do_exit diff --git a/lib/string.c b/lib/string.c index c8bae0f..87d01b7 100644 --- a/lib/string.c +++ b/lib/string.c @@ -67,7 +67,7 @@ void *memcpy(void *dest, const void *src, size_t size) return dest; } -void memset(char *dest, char ch, size_t size) +void memset(char *dest, char ch, size_t size) { while(size--) *dest++ = ch; } diff --git a/setup/setup.c b/setup/setup.c index fe42875..ee845f5 100644 --- a/setup/setup.c +++ b/setup/setup.c @@ -66,10 +66,10 @@ void setup_kernel() setup_sysc(); setup_pci(); - setup_irqs(); - setup_tasks(); + setup_irqs(); + return; while(1); // TODO MODIFY CODE BELOW -- 2.44.0