第二节 抢占式调度框架

抢占式调度由时钟中断推动,现在就让调度与时钟中断关联起来,在注册响应函数时调用 axtask::on_timer_tick():

// axruntime/src/lib.rs
#[cfg(all(target_os = "none", not(test)))]
fn init_interrupt() {
	... ...
    axhal::irq::register_handler(TIMER_IRQ_NUM, || {
        update_timer();
        debug!("On timer tick!");
        axtask::on_timer_tick();
    });

    // Enable IRQs before starting app
    axhal::irq::enable_irqs();
}

// axtask/src/lib.rs
pub fn on_timer_tick() {
    run_queue::RUN_QUEUE.lock().scheduler_timer_tick();
}

// axtask/src/run_queue.rs
impl AxRunQueue {
    pub fn scheduler_timer_tick(&mut self) {
        let curr = current();
        if !curr.is_idle() && curr.task_tick() {
            curr.set_preempt_pending(true);
        }
    }
}

每次时钟中断时,最后会调用 scheduler_timer_tick(...),对于当前任务,如果 task_tick 返回 true,设置抢占标志表示任务本身已经具备了被抢占的条件。当然,这只是满足了内部条件,能否真正触发抢占调度,还要看外部条件。在此之前,先来测试一下当前的功能,执行 make run LOG=trace 查看任务内部状态的变化,在几次时钟中断触发后,任务的 need_resched 被设置为 true。