重写调度模块 (#679)

## PR:重写调度模块
--- 
### 完成的部分
- 实现cfs调度策略
- 搭建框架,后续功能可以迭代开发
- 目前能跑,未测试性能

### 需要后续接力的部分
- 实现组内调度(task_group)
- 实现跨核负载均衡(pelt算法)
- 接入sysfs,实现参数动态调节(sched_stat等)
- nice值以及priority等参数的设置及调优
This commit is contained in:
GnoCiYeH
2024-04-05 17:54:48 +08:00
committed by GitHub
parent e8eab1ac82
commit f0c87a897f
44 changed files with 3733 additions and 1066 deletions

View File

@ -1,4 +1,5 @@
use core::cell::RefCell;
use core::sync::atomic::{fence, Ordering};
use crate::arch::driver::tsc::TSCManager;
use crate::arch::interrupt::TrapFrame;
@ -12,7 +13,7 @@ use crate::exception::IrqNumber;
use crate::kdebug;
use crate::mm::percpu::PerCpu;
use crate::sched::core::sched_update_jiffies;
use crate::process::ProcessManager;
use crate::smp::core::smp_get_processor_id;
use crate::smp::cpu::ProcessorId;
use crate::time::clocksource::HZ;
@ -66,9 +67,10 @@ impl IrqHandler for LocalApicTimerHandler {
struct LocalApicTimerIrqFlowHandler;
impl IrqFlowHandler for LocalApicTimerIrqFlowHandler {
fn handle(&self, _irq_desc: &Arc<IrqDesc>, _trap_frame: &mut TrapFrame) {
LocalApicTimer::handle_irq().ok();
fn handle(&self, _irq_desc: &Arc<IrqDesc>, trap_frame: &mut TrapFrame) {
LocalApicTimer::handle_irq(trap_frame).ok();
CurrentApic.send_eoi();
fence(Ordering::SeqCst)
}
}
@ -274,8 +276,9 @@ impl LocalApicTimer {
return (res.ecx & (1 << 24)) != 0;
}
pub(super) fn handle_irq() -> Result<IrqReturn, SystemError> {
sched_update_jiffies();
pub(super) fn handle_irq(trap_frame: &TrapFrame) -> Result<IrqReturn, SystemError> {
// sched_update_jiffies();
ProcessManager::update_process_times(trap_frame.is_from_user());
return Ok(IrqReturn::Handled);
}
}

View File

@ -1,3 +1,5 @@
use core::sync::atomic::{fence, Ordering};
use x86::msr::{
rdmsr, wrmsr, IA32_APIC_BASE, IA32_X2APIC_APICID, IA32_X2APIC_EOI, IA32_X2APIC_SIVR,
IA32_X2APIC_VERSION,
@ -62,9 +64,12 @@ impl LocalAPIC for X2Apic {
/// 发送 EOI (End Of Interrupt)
fn send_eoi(&self) {
fence(Ordering::SeqCst);
unsafe {
wrmsr(IA32_X2APIC_EOI, 0);
}
fence(Ordering::SeqCst);
}
/// 获取 x2APIC 版本

View File

@ -1,15 +1,13 @@
use core::intrinsics::likely;
use crate::{
arch::{
driver::apic::{apic_timer::APIC_TIMER_IRQ_NUM, CurrentApic, LocalAPIC},
sched::sched,
},
arch::driver::apic::{apic_timer::APIC_TIMER_IRQ_NUM, CurrentApic, LocalAPIC},
exception::{irqdesc::irq_desc_manager, softirq::do_softirq, IrqNumber},
process::{
utils::{current_pcb_flags, current_pcb_preempt_count},
ProcessFlags,
},
sched::{SchedMode, __schedule},
};
use super::TrapFrame;
@ -47,6 +45,6 @@ unsafe extern "C" fn x86_64_do_irq(trap_frame: &mut TrapFrame, vector: u32) {
if (current_pcb_flags().contains(ProcessFlags::NEED_SCHEDULE))
&& vector == APIC_TIMER_IRQ_NUM.data()
{
sched();
__schedule(SchedMode::SM_PREEMPT);
}
}

View File

@ -254,12 +254,12 @@ impl IrqFlowHandler for X86_64IpiIrqFlowHandler {
}
IPI_NUM_FLUSH_TLB => {
FlushTLBIpiHandler.handle(irq, None, None).ok();
CurrentApic.send_eoi();
}
_ => {
kerror!("Unknown IPI: {}", irq.data());
CurrentApic.send_eoi();
}
}
CurrentApic.send_eoi();
}
}

View File

@ -7,7 +7,6 @@ use crate::{
fpu::FpState,
interrupt::TrapFrame,
process::table::{USER_CS, USER_DS},
sched::sched,
CurrentIrqArch, MMArch,
},
exception::InterruptArch,
@ -18,6 +17,7 @@ use crate::{
kerror,
mm::MemoryManagementArch,
process::ProcessManager,
sched::{schedule, SchedMode},
syscall::{user_access::UserBufferWriter, Syscall},
};
@ -715,7 +715,7 @@ fn sig_stop(sig: Signal) {
);
});
drop(guard);
sched();
schedule(SchedMode::SM_NONE);
// TODO 暂停进程
}
/// 信号默认处理函数——继续进程

View File

@ -1,11 +1,21 @@
use core::hint::spin_loop;
use crate::{arch::CurrentIrqArch, exception::InterruptArch, kBUG, process::ProcessManager};
use crate::{
arch::CurrentIrqArch,
exception::InterruptArch,
kBUG,
process::{ProcessFlags, ProcessManager},
sched::{SchedMode, __schedule},
};
impl ProcessManager {
/// 每个核的idle进程
pub fn arch_idle_func() -> ! {
loop {
let pcb = ProcessManager::current_pcb();
if pcb.flags().contains(ProcessFlags::NEED_SCHEDULE) {
__schedule(SchedMode::SM_NONE);
}
if CurrentIrqArch::is_irq_enabled() {
unsafe {
x86::halt();

View File

@ -563,6 +563,8 @@ pub unsafe fn arch_switch_to_user(path: String, argv: Vec<String>, envp: Vec<Str
current_pcb.flags().remove(ProcessFlags::KTHREAD);
current_pcb.worker_private().take();
*current_pcb.sched_info().sched_policy.write_irqsave() = crate::sched::SchedPolicy::CFS;
let mut trap_frame = TrapFrame::new();
compiler_fence(Ordering::SeqCst);
@ -591,6 +593,7 @@ unsafe extern "sysv64" fn ready_to_switch_to_user(
new_rip: usize,
) -> ! {
*(trapframe_vaddr as *mut TrapFrame) = trap_frame;
compiler_fence(Ordering::SeqCst);
asm!(
"swapgs",
"mov rsp, {trapframe_vaddr}",
@ -601,3 +604,35 @@ unsafe extern "sysv64" fn ready_to_switch_to_user(
);
unreachable!()
}
// bitflags! {
// pub struct ProcessThreadFlags: u32 {
// /*
// * thread information flags
// * - these are process state flags that various assembly files
// * may need to access
// */
// const TIF_NOTIFY_RESUME = 1 << 1; /* callback before returning to user */
// const TIF_SIGPENDING = 1 << 2; /* signal pending */
// const TIF_NEED_RESCHED = 1 << 3; /* rescheduling necessary */
// const TIF_SINGLESTEP = 1 << 4; /* reenable singlestep on user return*/
// const TIF_SSBD = 1 << 5; /* Speculative store bypass disable */
// const TIF_SPEC_IB = 1 << 9; /* Indirect branch speculation mitigation */
// const TIF_SPEC_L1D_FLUSH = 1 << 10; /* Flush L1D on mm switches (processes) */
// const TIF_USER_RETURN_NOTIFY = 1 << 11; /* notify kernel of userspace return */
// const TIF_UPROBE = 1 << 12; /* breakpointed or singlestepping */
// const TIF_PATCH_PENDING = 1 << 13; /* pending live patching update */
// const TIF_NEED_FPU_LOAD = 1 << 14; /* load FPU on return to userspace */
// const TIF_NOCPUID = 1 << 15; /* CPUID is not accessible in userland */
// const TIF_NOTSC = 1 << 16; /* TSC is not accessible in userland */
// const TIF_NOTIFY_SIGNAL = 1 << 17; /* signal notifications exist */
// const TIF_MEMDIE = 1 << 20; /* is terminating due to OOM killer */
// const TIF_POLLING_NRFLAG = 1 << 21; /* idle is polling for TIF_NEED_RESCHED */
// const TIF_IO_BITMAP = 1 << 22; /* uses I/O bitmap */
// const TIF_SPEC_FORCE_UPDATE = 1 << 23; /* Force speculation MSR update in context switch */
// const TIF_FORCED_TF = 1 << 24; /* true if TF in eflags artificially */
// const TIF_BLOCKSTEP = 1 << 25; /* set when we want DEBUGCTLMSR_BTF */
// const TIF_LAZY_MMU_UPDATES = 1 << 27; /* task is updating the mmu lazily */
// const TIF_ADDR32 = 1 << 29; /* 32-bit address space on 64 bits */
// }
// }

View File

@ -1,20 +1,19 @@
use core::hint::spin_loop;
use crate::{
exception::InterruptArch, include::bindings::bindings::enter_syscall_int, sched::SchedArch,
smp::core::smp_get_processor_id, syscall::SYS_SCHED,
};
use crate::{exception::InterruptArch, sched::SchedArch, smp::core::smp_get_processor_id};
use super::{driver::apic::apic_timer::apic_timer_init, CurrentIrqArch};
/// @brief 若内核代码不处在中断上下文中那么将可以使用本函数发起一个sys_sched系统调用然后运行调度器。
/// 由于只能在中断上下文中进行进程切换因此需要发起一个系统调用SYS_SCHED。
#[no_mangle]
pub extern "C" fn sched() {
unsafe {
enter_syscall_int(SYS_SCHED as u64, 0, 0, 0, 0, 0, 0);
}
}
// /// @brief 若内核代码不处在中断上下文中那么将可以使用本函数发起一个sys_sched系统调用然后运行调度器。
// /// 由于只能在中断上下文中进行进程切换因此需要发起一个系统调用SYS_SCHED。
// #[no_mangle]
// pub extern "C" fn sched() {
// let _guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
// __schedule(SchedMode::SM_NONE);
// // unsafe {
// // enter_syscall_int(SYS_SCHED as u64, 0, 0, 0, 0, 0, 0);
// // }
// }
static mut BSP_INIT_OK: bool = false;