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