commit
324b64c2ed
@ -0,0 +1,40 @@
|
|||||||
|
/// Interface for inter-processor interrupt.
|
||||||
|
/// This module wraps inter-processor interrupt into a broadcast-calling style.
|
||||||
|
|
||||||
|
use crate::consts::KERNEL_OFFSET;
|
||||||
|
use alloc::boxed::{Box, FnBox};
|
||||||
|
use alloc::sync::Arc;
|
||||||
|
use apic::{LocalApic, XApic, LAPIC_ADDR};
|
||||||
|
use core::sync::atomic::{spin_loop_hint, AtomicU8, Ordering};
|
||||||
|
|
||||||
|
pub type IPIEventItem = Box<FnBox()>;
|
||||||
|
|
||||||
|
unsafe fn get_apic() -> XApic {
|
||||||
|
let mut lapic = unsafe { XApic::new(KERNEL_OFFSET + LAPIC_ADDR) };
|
||||||
|
lapic
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn invoke_on_allcpu(f: impl Fn() + 'static, wait: bool) {
|
||||||
|
// Step 1: initialize
|
||||||
|
use super::interrupt::consts::IPIFuncCall;
|
||||||
|
let mut apic = unsafe { get_apic() };
|
||||||
|
let func = Arc::new(f);
|
||||||
|
let cpu_count = super::gdt::Cpu::iter().count();
|
||||||
|
let rest_count = Arc::new(AtomicU8::new(cpu_count as u8));
|
||||||
|
// Step 2: invoke
|
||||||
|
for cpu in super::gdt::Cpu::iter() {
|
||||||
|
let func_clone = func.clone();
|
||||||
|
let rest_clone = rest_count.clone();
|
||||||
|
cpu.notify_event(Box::new(move || {
|
||||||
|
func_clone();
|
||||||
|
rest_clone.fetch_sub(1, Ordering::Relaxed);
|
||||||
|
}));
|
||||||
|
apic.send_ipi(cpu.id() as u8, IPIFuncCall);
|
||||||
|
}
|
||||||
|
if wait {
|
||||||
|
// spin if remote invocation do not complete
|
||||||
|
while rest_count.load(Ordering::Relaxed) != 0 {
|
||||||
|
spin_loop_hint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1 +1 @@
|
|||||||
Subproject commit bb73d6ecce1ab0e6fae692c51e4335772b0335d4
|
Subproject commit 9fb1d459b50bc14c7ac56d9fd94b4b8485620730
|
Loading…
Reference in new issue