1 use core::intrinsics::likely; 2 3 use crate::{ 4 arch::driver::apic::{apic_timer::APIC_TIMER_IRQ_NUM, CurrentApic, LocalAPIC}, 5 exception::{irqdesc::irq_desc_manager, softirq::do_softirq, IrqNumber}, 6 process::{ 7 utils::{current_pcb_flags, current_pcb_preempt_count}, 8 ProcessFlags, 9 }, 10 sched::{SchedMode, __schedule}, 11 }; 12 13 use super::TrapFrame; 14 15 #[no_mangle] 16 unsafe extern "C" fn x86_64_do_irq(trap_frame: &mut TrapFrame, vector: u32) { 17 // swapgs 18 19 if trap_frame.is_from_user() { 20 x86_64::registers::segmentation::GS::swap(); 21 } 22 23 // 由于x86上面,虚拟中断号与物理中断号是一一对应的,所以这里直接使用vector作为中断号来查询irqdesc 24 25 let desc = irq_desc_manager().lookup(IrqNumber::new(vector)); 26 27 if likely(desc.is_some()) { 28 let desc = desc.unwrap(); 29 let handler = desc.handler(); 30 if likely(handler.is_some()) { 31 handler.unwrap().handle(&desc, trap_frame); 32 } else { 33 CurrentApic.send_eoi(); 34 } 35 } else { 36 CurrentApic.send_eoi(); 37 } 38 39 do_softirq(); 40 41 if current_pcb_preempt_count() > 0 { 42 return; 43 } 44 // 检测当前进程是否可被调度 45 if (current_pcb_flags().contains(ProcessFlags::NEED_SCHEDULE)) 46 && vector == APIC_TIMER_IRQ_NUM.data() 47 { 48 __schedule(SchedMode::SM_PREEMPT); 49 } 50 } 51