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);
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),

View File

@ -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)
/**

View File

@ -1,7 +1,7 @@
#include "cfs.h"
#include <common/kprint.h>
#include <driver/video/video.h>
#include <common/spinlock.h>
#include <driver/video/video.h>
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;
}
}

View File

@ -1,9 +1,9 @@
#include "sched.h"
#include <common/kprint.h>
#include <common/spinlock.h>
#include <common/string.h>
#include <driver/video/video.h>
#include <sched/cfs.h>
#include <common/string.h>
/**
* @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);
}

View File

@ -77,3 +77,4 @@ void sched_init();
*/
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_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,
};

View File

@ -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的系统调用