From 156949680c83f2d7e3b21ed68b11698b88eaf396 Mon Sep 17 00:00:00 2001 From: login Date: Sat, 31 Dec 2022 13:47:49 +0800 Subject: [PATCH] =?UTF-8?q?bugfix:=E4=BF=AE=E5=A4=8D=E5=BD=93=E4=BD=BF?= =?UTF-8?q?=E7=94=A8sched()=E8=BF=90=E8=A1=8C=E8=B0=83=E5=BA=A6=E5=99=A8?= =?UTF-8?q?=EF=BC=8C=E5=9C=A8=E5=88=87=E6=8D=A2=E8=BF=9B=E7=A8=8B=E7=9A=84?= =?UTF-8?q?=E6=97=B6=E5=80=99=EF=BC=8C=E7=94=B1=E4=BA=8E=E4=B8=8D=E5=9C=A8?= =?UTF-8?q?=E4=B8=AD=E6=96=AD=E4=B8=8A=E4=B8=8B=E6=96=87=E5=86=85=EF=BC=8C?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E5=BD=93=E5=89=8D=E8=BF=9B=E7=A8=8B=E7=9A=84?= =?UTF-8?q?=E4=B8=8A=E4=B8=8B=E6=96=87=E4=B8=A2=E5=A4=B1=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E3=80=82=20(#130)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bugfix:修复当使用sched()运行调度器,在切换进程的时候,由于不在中断上下文内,导致当前进程的上下文丢失的问题。 bugfix:修复切换进程的宏的汇编代码的损坏部分,未声明rax寄存器,从而导致的编译器未定义行为问题。 --- kernel/src/process/process.c | 2 +- kernel/src/process/process.h | 8 +++---- kernel/src/sched/cfs.c | 36 ++++++++++++++++++++------------ kernel/src/sched/sched.c | 24 ++++++++++++++++++--- kernel/src/sched/sched.h | 1 + kernel/src/syscall/syscall.c | 4 +++- kernel/src/syscall/syscall_num.h | 3 ++- 7 files changed, 55 insertions(+), 23 deletions(-) diff --git a/kernel/src/process/process.c b/kernel/src/process/process.c index c9c10694..da269613 100644 --- a/kernel/src/process/process.c +++ b/kernel/src/process/process.c @@ -513,7 +513,7 @@ ul initial_kernel_thread(ul arg) // kdebug("current_pcb->thread->rsp=%#018lx", current_pcb->thread->rsp); current_pcb->flags = 0; // 将返回用户层的代码压入堆栈,向rdx传入regs的地址,然后jmp到do_execve这个系统调用api的处理函数 - // 这里的设计思路和switch_proc类似 加载用户态程序:shell.elf + // 这里的设计思路和switch_to类似 加载用户态程序:shell.elf __asm__ __volatile__("movq %1, %%rsp \n\t" "pushq %2 \n\t" "jmp do_execve \n\t" ::"D"(current_pcb->thread->rsp), diff --git a/kernel/src/process/process.h b/kernel/src/process/process.h index bcf12a36..cbe7fd1c 100644 --- a/kernel/src/process/process.h +++ b/kernel/src/process/process.h @@ -51,23 +51,23 @@ extern uint64_t process_exit_files(struct process_control_block *pcb); * 然后调用__switch_to切换栈,配置其他信息,最后恢复下一个进程的rax rbp。 */ -#define switch_proc(prev, next) \ +#define switch_to(prev, next) \ do \ { \ __asm__ __volatile__("pushq %%rbp \n\t" \ "pushq %%rax \n\t" \ "movq %%rsp, %0 \n\t" \ "movq %2, %%rsp \n\t" \ - "leaq switch_proc_ret_addr(%%rip), %%rax \n\t" \ + "leaq 2f(%%rip), %%rax \n\t" \ "movq %%rax, %1 \n\t" \ "pushq %3 \n\t" \ "jmp __switch_to \n\t" \ - "switch_proc_ret_addr: \n\t" \ + "2: \n\t" \ "popq %%rax \n\t" \ "popq %%rbp \n\t" \ : "=m"(prev->thread->rsp), "=m"(prev->thread->rip) \ : "m"(next->thread->rsp), "m"(next->thread->rip), "D"(prev), "S"(next) \ - : "memory"); \ + : "memory", "rax"); \ } while (0) /** diff --git a/kernel/src/sched/cfs.c b/kernel/src/sched/cfs.c index 36cd4fd4..1ffb07a6 100644 --- a/kernel/src/sched/cfs.c +++ b/kernel/src/sched/cfs.c @@ -1,7 +1,7 @@ #include "cfs.h" #include -#include #include +#include struct sched_queue_t sched_cfs_ready_queue[MAX_CPU_NUM]; // 就绪队列 @@ -18,7 +18,8 @@ struct process_control_block *sched_cfs_dequeue() return &initial_proc_union.pcb; } - struct process_control_block *proc = container_of(list_next(&sched_cfs_ready_queue[proc_current_cpu_id].proc_queue.list), struct process_control_block, list); + struct process_control_block *proc = container_of( + list_next(&sched_cfs_ready_queue[proc_current_cpu_id].proc_queue.list), struct process_control_block, list); list_del(&proc->list); --sched_cfs_ready_queue[proc_current_cpu_id].count; @@ -34,7 +35,8 @@ void sched_cfs_enqueue(struct process_control_block *pcb) { if (pcb == initial_proc[proc_current_cpu_id]) return; - struct process_control_block *proc = container_of(list_next(&sched_cfs_ready_queue[proc_current_cpu_id].proc_queue.list), struct process_control_block, list); + struct process_control_block *proc = container_of( + list_next(&sched_cfs_ready_queue[proc_current_cpu_id].proc_queue.list), struct process_control_block, list); if ((list_empty(&sched_cfs_ready_queue[proc_current_cpu_id].proc_queue.list)) == 0) { while (proc->virtual_runtime < pcb->virtual_runtime) @@ -58,12 +60,16 @@ void sched_cfs() current_pcb->flags &= ~PF_NEED_SCHED; // kdebug("current_pcb pid= %d", current_pcb->pid); struct process_control_block *proc = sched_cfs_dequeue(); - // kdebug("sched_cfs_ready_queue[proc_current_cpu_id].count = %d", sched_cfs_ready_queue[proc_current_cpu_id].count); - if (current_pcb->virtual_runtime >= proc->virtual_runtime || !(current_pcb->state & PROC_RUNNING)) // 当前进程运行时间大于了下一进程的运行时间,进行切换 + // kdebug("sched_cfs_ready_queue[proc_current_cpu_id].count = %d", + // sched_cfs_ready_queue[proc_current_cpu_id].count); + if (current_pcb->virtual_runtime >= proc->virtual_runtime || + !(current_pcb->state & PROC_RUNNING)) // 当前进程运行时间大于了下一进程的运行时间,进行切换 { - // kdebug("current_pcb->virtual_runtime = %d,proc->vt= %d", current_pcb->virtual_runtime, proc->virtual_runtime); - if (current_pcb->state & PROC_RUNNING) // 本次切换由于时间片到期引发,则再次加入就绪队列,否则交由其它功能模块进行管理 + // kdebug("current_pcb->virtual_runtime = %d,proc->vt= %d", current_pcb->virtual_runtime, + // proc->virtual_runtime); + if (current_pcb->state & + PROC_RUNNING) // 本次切换由于时间片到期引发,则再次加入就绪队列,否则交由其它功能模块进行管理 sched_cfs_enqueue(current_pcb); // kdebug("proc->pid=%d, count=%d", proc->pid, sched_cfs_ready_queue[proc_current_cpu_id].count); if (sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies <= 0) @@ -72,18 +78,20 @@ void sched_cfs() { case 0: case 1: - sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies = 4 / sched_cfs_ready_queue[proc_current_cpu_id].count; + sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies = + 4 / sched_cfs_ready_queue[proc_current_cpu_id].count; break; case 2: default: - sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies = (4 / sched_cfs_ready_queue[proc_current_cpu_id].count) << 2; + sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies = + (4 / sched_cfs_ready_queue[proc_current_cpu_id].count) << 2; break; } } - process_switch_mm(proc); - + barrier(); switch_proc(current_pcb, proc); + barrier(); } else // 不进行切换 { @@ -96,12 +104,14 @@ void sched_cfs() { case 0: case 1: - sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies = 4 / sched_cfs_ready_queue[proc_current_cpu_id].count; + sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies = + 4 / sched_cfs_ready_queue[proc_current_cpu_id].count; break; case 2: default: - sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies = (4 / sched_cfs_ready_queue[proc_current_cpu_id].count) << 2; + sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies = + (4 / sched_cfs_ready_queue[proc_current_cpu_id].count) << 2; break; } } diff --git a/kernel/src/sched/sched.c b/kernel/src/sched/sched.c index adaa4087..8b177591 100644 --- a/kernel/src/sched/sched.c +++ b/kernel/src/sched/sched.c @@ -1,9 +1,9 @@ #include "sched.h" #include #include +#include #include #include -#include /** * @brief @@ -60,10 +60,10 @@ void sched_enqueue(struct process_control_block *pcb) } /** - * @brief 包裹sched_cfs(),调度函数 + * @brief 该函数只能由sys_sched调用 * */ -void sched() +static void __sched() { sched_cfs(); } @@ -73,5 +73,23 @@ void sched_init() sched_cfs_init(); } +uint64_t sys_sched(struct pt_regs *regs) +{ + if(user_mode(regs)){ + return -EPERM; + } + __sched(); +} +void sched() +{ + + enter_syscall_int(SYS_SCHED, 0, 0, 0, 0, 0, 0, 0, 0); +} +void switch_proc(struct process_control_block *prev, struct process_control_block *proc) +{ + process_switch_mm(proc); + io_mfence(); + switch_to(prev, proc); +} diff --git a/kernel/src/sched/sched.h b/kernel/src/sched/sched.h index ea89b9fe..f2098696 100644 --- a/kernel/src/sched/sched.h +++ b/kernel/src/sched/sched.h @@ -77,3 +77,4 @@ void sched_init(); */ void sched_update_jiffies(); +void switch_proc(struct process_control_block *prev, struct process_control_block *proc); \ No newline at end of file diff --git a/kernel/src/syscall/syscall.c b/kernel/src/syscall/syscall.c index e8c30d94..e7a41ba0 100644 --- a/kernel/src/syscall/syscall.c +++ b/kernel/src/syscall/syscall.c @@ -23,6 +23,7 @@ extern uint64_t sys_kill(struct pt_regs *regs); extern uint64_t sys_sigaction(struct pt_regs * regs); extern uint64_t sys_rt_sigreturn(struct pt_regs * regs); extern uint64_t sys_getpid(struct pt_regs * regs); +extern uint64_t sys_sched(struct pt_regs * regs); /** * @brief 导出系统调用处理函数的符号 @@ -592,6 +593,7 @@ system_call_t system_call_table[MAX_SYSTEM_CALL_NUM] = { [24] = sys_sigaction, [25] = sys_rt_sigreturn, [26] = sys_getpid, - [27 ... 254] = system_call_not_exists, + [27] = sys_sched, + [28 ... 254] = system_call_not_exists, [255] = sys_ahci_end_req, }; diff --git a/kernel/src/syscall/syscall_num.h b/kernel/src/syscall/syscall_num.h index a212fae0..d6cea975 100644 --- a/kernel/src/syscall/syscall_num.h +++ b/kernel/src/syscall/syscall_num.h @@ -37,6 +37,7 @@ #define SYS_KILL 23 // kill一个进程(向这个进程发出信号) #define SYS_SIGACTION 24 // 设置进程的信号处理动作 #define SYS_RT_SIGRETURN 25 // 从信号处理函数返回 -#define SYS_GETPID 26 // 获取当前进程的pid(进程标识符) +#define SYS_GETPID 26 // 获取当前进程的pid(进程标识符) +#define SYS_SCHED 27 // 让系统立即运行调度器(该系统调用不能由运行在Ring3的程序发起) #define SYS_AHCI_END_REQ 255 // AHCI DMA请求结束end_request的系统调用 \ No newline at end of file