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]
x86_64_do_irq(trap_frame: &mut TrapFrame, vector: u32)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