bugfix:修复当使用sched()运行调度器,在切换进程的时候,由于不在中断上下文内,导致当前进程的上下文丢失的问题。 (#130)

bugfix:修复当使用sched()运行调度器,在切换进程的时候,由于不在中断上下文内,导致当前进程的上下文丢失的问题。
bugfix:修复切换进程的宏的汇编代码的损坏部分,未声明rax寄存器,从而导致的编译器未定义行为问题。
This commit is contained in:
login 2022-12-31 13:47:49 +08:00 committed by GitHub
parent 882f0b7e74
commit 156949680c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 55 additions and 23 deletions

View File

@ -513,7 +513,7 @@ ul initial_kernel_thread(ul arg)
// kdebug("current_pcb->thread->rsp=%#018lx", current_pcb->thread->rsp); // kdebug("current_pcb->thread->rsp=%#018lx", current_pcb->thread->rsp);
current_pcb->flags = 0; current_pcb->flags = 0;
// 将返回用户层的代码压入堆栈向rdx传入regs的地址然后jmp到do_execve这个系统调用api的处理函数 // 将返回用户层的代码压入堆栈向rdx传入regs的地址然后jmp到do_execve这个系统调用api的处理函数
// 这里的设计思路和switch_proc类似 加载用户态程序shell.elf // 这里的设计思路和switch_to类似 加载用户态程序shell.elf
__asm__ __volatile__("movq %1, %%rsp \n\t" __asm__ __volatile__("movq %1, %%rsp \n\t"
"pushq %2 \n\t" "pushq %2 \n\t"
"jmp do_execve \n\t" ::"D"(current_pcb->thread->rsp), "jmp do_execve \n\t" ::"D"(current_pcb->thread->rsp),

View File

@ -51,23 +51,23 @@ extern uint64_t process_exit_files(struct process_control_block *pcb);
* __switch_to切换栈rax rbp * __switch_to切换栈rax rbp
*/ */
#define switch_proc(prev, next) \ #define switch_to(prev, next) \
do \ do \
{ \ { \
__asm__ __volatile__("pushq %%rbp \n\t" \ __asm__ __volatile__("pushq %%rbp \n\t" \
"pushq %%rax \n\t" \ "pushq %%rax \n\t" \
"movq %%rsp, %0 \n\t" \ "movq %%rsp, %0 \n\t" \
"movq %2, %%rsp \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" \ "movq %%rax, %1 \n\t" \
"pushq %3 \n\t" \ "pushq %3 \n\t" \
"jmp __switch_to \n\t" \ "jmp __switch_to \n\t" \
"switch_proc_ret_addr: \n\t" \ "2: \n\t" \
"popq %%rax \n\t" \ "popq %%rax \n\t" \
"popq %%rbp \n\t" \ "popq %%rbp \n\t" \
: "=m"(prev->thread->rsp), "=m"(prev->thread->rip) \ : "=m"(prev->thread->rsp), "=m"(prev->thread->rip) \
: "m"(next->thread->rsp), "m"(next->thread->rip), "D"(prev), "S"(next) \ : "m"(next->thread->rsp), "m"(next->thread->rip), "D"(prev), "S"(next) \
: "memory"); \ : "memory", "rax"); \
} while (0) } while (0)
/** /**

View File

@ -1,7 +1,7 @@
#include "cfs.h" #include "cfs.h"
#include <common/kprint.h> #include <common/kprint.h>
#include <driver/video/video.h>
#include <common/spinlock.h> #include <common/spinlock.h>
#include <driver/video/video.h>
struct sched_queue_t sched_cfs_ready_queue[MAX_CPU_NUM]; // 就绪队列 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; 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); list_del(&proc->list);
--sched_cfs_ready_queue[proc_current_cpu_id].count; --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]) if (pcb == initial_proc[proc_current_cpu_id])
return; 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) if ((list_empty(&sched_cfs_ready_queue[proc_current_cpu_id].proc_queue.list)) == 0)
{ {
while (proc->virtual_runtime < pcb->virtual_runtime) while (proc->virtual_runtime < pcb->virtual_runtime)
@ -58,12 +60,16 @@ void sched_cfs()
current_pcb->flags &= ~PF_NEED_SCHED; current_pcb->flags &= ~PF_NEED_SCHED;
// kdebug("current_pcb pid= %d", current_pcb->pid); // kdebug("current_pcb pid= %d", current_pcb->pid);
struct process_control_block *proc = sched_cfs_dequeue(); 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); // kdebug("sched_cfs_ready_queue[proc_current_cpu_id].count = %d",
if (current_pcb->virtual_runtime >= proc->virtual_runtime || !(current_pcb->state & PROC_RUNNING)) // 当前进程运行时间大于了下一进程的运行时间,进行切换 // 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); // kdebug("current_pcb->virtual_runtime = %d,proc->vt= %d", current_pcb->virtual_runtime,
if (current_pcb->state & PROC_RUNNING) // 本次切换由于时间片到期引发,则再次加入就绪队列,否则交由其它功能模块进行管理 // proc->virtual_runtime);
if (current_pcb->state &
PROC_RUNNING) // 本次切换由于时间片到期引发,则再次加入就绪队列,否则交由其它功能模块进行管理
sched_cfs_enqueue(current_pcb); sched_cfs_enqueue(current_pcb);
// kdebug("proc->pid=%d, count=%d", proc->pid, sched_cfs_ready_queue[proc_current_cpu_id].count); // 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) if (sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies <= 0)
@ -72,18 +78,20 @@ void sched_cfs()
{ {
case 0: case 0:
case 1: 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; break;
case 2: case 2:
default: 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; break;
} }
} }
process_switch_mm(proc); barrier();
switch_proc(current_pcb, proc); switch_proc(current_pcb, proc);
barrier();
} }
else // 不进行切换 else // 不进行切换
{ {
@ -96,12 +104,14 @@ void sched_cfs()
{ {
case 0: case 0:
case 1: 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; break;
case 2: case 2:
default: 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; break;
} }
} }

View File

@ -1,9 +1,9 @@
#include "sched.h" #include "sched.h"
#include <common/kprint.h> #include <common/kprint.h>
#include <common/spinlock.h> #include <common/spinlock.h>
#include <common/string.h>
#include <driver/video/video.h> #include <driver/video/video.h>
#include <sched/cfs.h> #include <sched/cfs.h>
#include <common/string.h>
/** /**
* @brief * @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(); sched_cfs();
} }
@ -73,5 +73,23 @@ void sched_init()
sched_cfs_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);
}

View File

@ -77,3 +77,4 @@ void sched_init();
*/ */
void sched_update_jiffies(); void sched_update_jiffies();
void switch_proc(struct process_control_block *prev, struct process_control_block *proc);

View File

@ -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_sigaction(struct pt_regs * regs);
extern uint64_t sys_rt_sigreturn(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_getpid(struct pt_regs * regs);
extern uint64_t sys_sched(struct pt_regs * regs);
/** /**
* @brief * @brief
@ -592,6 +593,7 @@ system_call_t system_call_table[MAX_SYSTEM_CALL_NUM] = {
[24] = sys_sigaction, [24] = sys_sigaction,
[25] = sys_rt_sigreturn, [25] = sys_rt_sigreturn,
[26] = sys_getpid, [26] = sys_getpid,
[27 ... 254] = system_call_not_exists, [27] = sys_sched,
[28 ... 254] = system_call_not_exists,
[255] = sys_ahci_end_req, [255] = sys_ahci_end_req,
}; };

View File

@ -37,6 +37,7 @@
#define SYS_KILL 23 // kill一个进程(向这个进程发出信号) #define SYS_KILL 23 // kill一个进程(向这个进程发出信号)
#define SYS_SIGACTION 24 // 设置进程的信号处理动作 #define SYS_SIGACTION 24 // 设置进程的信号处理动作
#define SYS_RT_SIGRETURN 25 // 从信号处理函数返回 #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的系统调用 #define SYS_AHCI_END_REQ 255 // AHCI DMA请求结束end_request的系统调用