Improve multi_core support
This commit is contained in:
@@ -45,7 +45,7 @@ impl Madt {
|
||||
println!(" XAPIC {}: {:>08X}", me, local_apic.address);
|
||||
}
|
||||
|
||||
if cfg!(feature = "multi_core"){
|
||||
if cfg!(feature = "multi_core") {
|
||||
let trampoline_frame = Frame::containing_address(PhysicalAddress::new(TRAMPOLINE));
|
||||
let trampoline_page = Page::containing_address(VirtualAddress::new(TRAMPOLINE));
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ pub unsafe fn init() {
|
||||
|
||||
// Set IPI handler (null)
|
||||
IDT[0x40].set_func(ipi::ipi);
|
||||
IDT[0x41].set_func(ipi::pit);
|
||||
|
||||
// Set syscall function
|
||||
IDT[0x80].set_func(syscall::syscall);
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
use core::sync::atomic::Ordering;
|
||||
|
||||
use context;
|
||||
use device::local_apic::LOCAL_APIC;
|
||||
use super::irq::PIT_TICKS;
|
||||
|
||||
interrupt!(ipi, {
|
||||
LOCAL_APIC.eoi();
|
||||
});
|
||||
|
||||
interrupt!(pit, {
|
||||
LOCAL_APIC.eoi();
|
||||
|
||||
if PIT_TICKS.fetch_add(1, Ordering::SeqCst) >= 10 {
|
||||
let _ = context::switch();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use context::timeout;
|
||||
use device::pic;
|
||||
use device::serial::{COM1, COM2};
|
||||
use core::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
|
||||
|
||||
use time;
|
||||
use context;
|
||||
use context::timeout;
|
||||
use device::{local_apic, pic};
|
||||
use device::serial::{COM1, COM2};
|
||||
use time;
|
||||
|
||||
//resets to 0 in context::switch()
|
||||
pub static PIT_TICKS: AtomicUsize = ATOMIC_USIZE_INIT;
|
||||
@@ -39,6 +39,11 @@ pub unsafe fn acknowledge(irq: usize) {
|
||||
}
|
||||
|
||||
interrupt!(pit, {
|
||||
// Wake up other CPUs
|
||||
if cfg!(feature = "multi_core") {
|
||||
local_apic::LOCAL_APIC.set_icr(3 << 18 | 1 << 14 | 0x41);
|
||||
}
|
||||
|
||||
// Saves CPU time by not sending IRQ event irq_trigger(0);
|
||||
|
||||
const PIT_RATE: u64 = 2250286;
|
||||
@@ -52,12 +57,12 @@ interrupt!(pit, {
|
||||
|
||||
pic::MASTER.ack();
|
||||
|
||||
// Any better way of doing this?
|
||||
timeout::trigger();
|
||||
|
||||
if PIT_TICKS.fetch_add(1, Ordering::SeqCst) >= 10 {
|
||||
let _ = context::switch();
|
||||
}
|
||||
|
||||
// Any better way of doing this?
|
||||
timeout::trigger();
|
||||
});
|
||||
|
||||
interrupt!(keyboard, {
|
||||
|
||||
@@ -231,11 +231,13 @@ impl Context {
|
||||
pub fn unblock(&mut self) -> bool {
|
||||
if self.status == Status::Blocked {
|
||||
self.status = Status::Runnable;
|
||||
if let Some(cpu_id) = self.cpu_id {
|
||||
if cpu_id != ::cpu_id() {
|
||||
// Send IPI if not on current CPU
|
||||
// TODO: Make this more architecture independent
|
||||
unsafe { device::local_apic::LOCAL_APIC.ipi(cpu_id) };
|
||||
if cfg!(feature = "multi_core") {
|
||||
if let Some(cpu_id) = self.cpu_id {
|
||||
if cpu_id != ::cpu_id() {
|
||||
// Send IPI if not on current CPU
|
||||
// TODO: Make this more architecture independent
|
||||
unsafe { device::local_apic::LOCAL_APIC.set_icr(3 << 18 | 1 << 14 | 0x40) };
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
|
||||
@@ -42,14 +42,14 @@ pub unsafe fn switch() -> bool {
|
||||
}
|
||||
|
||||
let check_context = |context: &mut Context| -> bool {
|
||||
// Take ownership if not already owned
|
||||
if context.cpu_id == None {
|
||||
context.cpu_id = Some(cpu_id);
|
||||
// println!("{}: take {} {}", cpu_id, context.id, ::core::str::from_utf8_unchecked(&context.name.lock()));
|
||||
}
|
||||
|
||||
// Restore from signal
|
||||
if context.ksig_restore {
|
||||
println!("Restore from ksig");
|
||||
|
||||
let ksig = context.ksig.take().expect("context::switch: ksig not set with ksig_restore");
|
||||
context.arch = ksig.0;
|
||||
if let Some(ref mut kfx) = context.kfx {
|
||||
@@ -64,16 +64,15 @@ pub unsafe fn switch() -> bool {
|
||||
}
|
||||
context.ksig_restore = false;
|
||||
|
||||
//TODO: Interrupt
|
||||
if context.status == Status::Blocked {
|
||||
context.unblock();
|
||||
}
|
||||
context.unblock();
|
||||
}
|
||||
|
||||
// Unblock when there are pending signals
|
||||
if context.status == Status::Blocked && !context.pending.is_empty() {
|
||||
context.unblock();
|
||||
}
|
||||
|
||||
// Wake from sleep
|
||||
if context.status == Status::Blocked && context.wake.is_some() {
|
||||
let wake = context.wake.expect("context::switch: wake not set");
|
||||
|
||||
@@ -84,13 +83,8 @@ pub unsafe fn switch() -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
if context.cpu_id == Some(cpu_id) {
|
||||
if context.status == Status::Runnable && !context.running {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
// Switch to context if it needs to run, is not currently running, and is owned by the current CPU
|
||||
!context.running && context.status == Status::Runnable && context.cpu_id == Some(cpu_id)
|
||||
};
|
||||
|
||||
for (pid, context_lock) in contexts.iter() {
|
||||
|
||||
@@ -184,7 +184,7 @@ pub fn kmain(cpus: usize, env: &[u8]) -> ! {
|
||||
pub fn kmain_ap(id: usize) -> ! {
|
||||
CPU_ID.store(id, Ordering::SeqCst);
|
||||
|
||||
if cfg!(feature = "multi_core"){
|
||||
if cfg!(feature = "multi_core") {
|
||||
context::init();
|
||||
|
||||
let pid = syscall::getpid();
|
||||
|
||||
Reference in New Issue
Block a user