diff --git a/crates/libxernel/src/sync/spin.rs b/crates/libxernel/src/sync/spin.rs index eef54265..8d26efc1 100644 --- a/crates/libxernel/src/sync/spin.rs +++ b/crates/libxernel/src/sync/spin.rs @@ -86,7 +86,11 @@ impl Spinlock { OnDrop::new(self.lock(), callback) } - //pub fn aquire_at(&self, ipl: IPL) -> OnDrop {} + pub fn aquire_at(&self, ipl: IPL) -> OnDrop, impl FnOnce()> { + let ipl = raise_ipl(ipl); + let callback = move || splx(ipl); + OnDrop::new(self.lock(), callback) + } /// Unlocking a spinlock /// diff --git a/xernel/kernel/src/cpu.rs b/xernel/kernel/src/cpu.rs index 649a0044..67fb510a 100644 --- a/xernel/kernel/src/cpu.rs +++ b/xernel/kernel/src/cpu.rs @@ -1,8 +1,9 @@ use crate::arch::amd64::apic::APIC; use crate::arch::amd64::{rdmsr, wrmsr, KERNEL_GS_BASE}; -use crate::dpc::DpcQueue; +use crate::dpc::{DpcCall, DpcQueue}; use crate::sched::process::Process; use crate::sched::thread::Thread; +use crate::timer::timer_event::TimerEvent; use crate::timer::timer_queue::TimerQueue; use alloc::boxed::Box; use alloc::collections::VecDeque; @@ -12,7 +13,8 @@ use core::cell::{Cell, UnsafeCell}; use core::ops::Deref; use core::pin::Pin; use core::sync::atomic::{AtomicUsize, Ordering}; -use libxernel::sync::{Once, RwLock, Spinlock}; +use libxernel::ipl::IPL; +use libxernel::sync::{Once, Spinlock}; static CPU_ID_COUNTER: AtomicUsize = AtomicUsize::new(0); @@ -124,14 +126,28 @@ pub struct Cpu { cpu_id: usize, pub lapic_id: u32, - pub run_queue: RwLock>>, - pub wait_queue: RwLock>>, - pub current_thread: RwLock>>, + pub run_queue: Spinlock>>, + pub wait_queue: Spinlock>>, + pub current_thread: Spinlock>>, pub idle_thread: Arc, - pub timer_queue: RwLock, - pub dpc_queue: RwLock, - pub next: RwLock>>, + pub timer_queue: Spinlock, + pub dpc_queue: Spinlock, + pub next: Spinlock>>, +} + +impl Cpu { + pub fn enqueue_timer(&self, event: TimerEvent) { + self.timer_queue.aquire_at(IPL::High).enqueue(event); + } + + pub fn enqueue_dpc(&self, dpc: Box) { + self.dpc_queue.aquire_at(IPL::High).enqueue(dpc); + } + + pub fn enqueue_thread(&self, thread: Arc) { + self.run_queue.aquire().push_back(thread) + } } pub fn register_cpu() { @@ -143,13 +159,13 @@ pub fn register_cpu() { kernel_stack: Cell::new(0), cpu_id, lapic_id, - run_queue: RwLock::new(VecDeque::new()), - wait_queue: RwLock::new(VecDeque::new()), - current_thread: RwLock::new(None), + run_queue: Spinlock::new(VecDeque::new()), + wait_queue: Spinlock::new(VecDeque::new()), + current_thread: Spinlock::new(None), idle_thread: Arc::new(Thread::idle_thread()), - timer_queue: RwLock::new(TimerQueue::new()), - dpc_queue: RwLock::new(DpcQueue::new()), - next: RwLock::new(None), + timer_queue: Spinlock::new(TimerQueue::new()), + dpc_queue: Spinlock::new(DpcQueue::new()), + next: Spinlock::new(None), })); // use KERNEL_GS_BASE to store the cpu_data @@ -167,7 +183,7 @@ pub fn current_cpu() -> Pin<&'static Cpu> { pub fn current_thread() -> Arc { current_cpu() .current_thread - .read() + .aquire() .clone() .unwrap_or(current_cpu().idle_thread.clone()) } diff --git a/xernel/kernel/src/dpc.rs b/xernel/kernel/src/dpc.rs index 423d75af..80ab06d0 100644 --- a/xernel/kernel/src/dpc.rs +++ b/xernel/kernel/src/dpc.rs @@ -79,7 +79,7 @@ pub fn enqueue_dpc(dpc: Box) { return; } - current_cpu().dpc_queue.write().enqueue(dpc); + current_cpu().enqueue_dpc(dpc); raise_dpc_interrupt() } @@ -94,7 +94,7 @@ pub fn dispatch_dpcs(_: &mut TrapFrame) { while let Some(dpc) = { let old = raise_ipl(IPL::High); - let mut lock = cpu.dpc_queue.write(); + let mut lock = cpu.dpc_queue.lock(); let dpc = lock.dequeue(); write_cr8(old); dpc @@ -102,11 +102,11 @@ pub fn dispatch_dpcs(_: &mut TrapFrame) { dpc.call(); } - let old = cpu.current_thread.read().clone(); - let new = cpu.next.read().clone(); + let old = cpu.current_thread.aquire().clone(); + let new = cpu.next.aquire().clone(); if old.is_some() && new.is_some() { - *cpu.next.write() = None; + **cpu.next.aquire() = None; let ipl = get_ipl(); switch_threads(old.unwrap(), new.unwrap()); diff --git a/xernel/kernel/src/main.rs b/xernel/kernel/src/main.rs index f4dcd8ba..976ea782 100644 --- a/xernel/kernel/src/main.rs +++ b/xernel/kernel/src/main.rs @@ -62,7 +62,6 @@ use crate::sched::process::Process; use crate::sched::process::KERNEL_PROCESS; use crate::sched::scheduler::reschedule; use crate::sched::thread::Thread; -use crate::timer::enqueue_timer; use crate::timer::hardclock; use crate::timer::timer_event::TimerEvent; use crate::utils::backtrace; @@ -193,18 +192,17 @@ extern "C" fn kernel_main() -> ! { let kernel_task2 = Thread::kernel_thread_from_fn(task2); - // TODO: use convenience functions - current_cpu().run_queue.write().push_back(Arc::new(main_task)); - current_cpu().run_queue.write().push_back(Arc::new(kernel_task)); - current_cpu().run_queue.write().push_back(Arc::new(kernel_task2)); + current_cpu().enqueue_thread(Arc::new(main_task)); + current_cpu().enqueue_thread(Arc::new(kernel_task)); + current_cpu().enqueue_thread(Arc::new(kernel_task2)); let timekeeper = TimerEvent::new(hardclock, (), Duration::from_secs(1), false); - enqueue_timer(timekeeper); + current_cpu().enqueue_timer(timekeeper); let resched = TimerEvent::new(reschedule, (), Duration::from_millis(5), false); - enqueue_timer(resched); + current_cpu().enqueue_timer(resched); amd64::interrupts::enable(); diff --git a/xernel/kernel/src/sched/scheduler.rs b/xernel/kernel/src/sched/scheduler.rs index 0036f4d7..00196f39 100644 --- a/xernel/kernel/src/sched/scheduler.rs +++ b/xernel/kernel/src/sched/scheduler.rs @@ -12,19 +12,19 @@ use super::thread::{Thread, ThreadStatus}; pub fn reschedule(_: ()) { let cpu = current_cpu(); - let next_ref = cpu.run_queue.write().pop_front(); + let next_ref = cpu.run_queue.aquire().pop_front(); - let current_ref = cpu.current_thread.read().clone(); + let current_ref = cpu.current_thread.aquire().clone(); let old = if let Some(current_thread) = current_ref { current_thread.clone() } else { - *cpu.current_thread.write() = Some(cpu.idle_thread.clone()); + **cpu.current_thread.aquire() = Some(cpu.idle_thread.clone()); cpu.idle_thread.clone() }; let new = if let Some(next_thread) = next_ref { - cpu.run_queue.write().push_back(next_thread.clone()); + cpu.run_queue.aquire().push_back(next_thread.clone()); next_thread.clone() } else { @@ -37,11 +37,11 @@ pub fn reschedule(_: ()) { return; } - *cpu.next.write() = Some(new); + **cpu.next.aquire() = Some(new); } pub fn enqueue_thread(thread: Thread) { - current_cpu().run_queue.write().push_back(Arc::new(thread)); + current_cpu().run_queue.aquire().push_back(Arc::new(thread)); } pub fn dequeue_thread(thread: Arc) -> Option> { @@ -49,14 +49,14 @@ pub fn dequeue_thread(thread: Arc) -> Option> { let mut index_to_remove = 0; - for (i, thrd) in cpu.run_queue.write().iter().enumerate() { + for (i, thrd) in cpu.run_queue.aquire().iter().enumerate() { if Arc::ptr_eq(&thread, thrd) { index_to_remove = i; break; } } - let thread = cpu.run_queue.write().remove(index_to_remove); + let thread = cpu.run_queue.aquire().remove(index_to_remove); thread } @@ -89,7 +89,7 @@ pub fn switch_threads(old: Arc, new: Arc) { } } - *current_cpu().current_thread.write() = Some(new.clone()); + **current_cpu().current_thread.aquire() = Some(new.clone()); unsafe { switch_context(old.context.get(), *new.context.get()); @@ -101,7 +101,5 @@ fn register_reschedule_event(millis: u64) { let cpu = current_cpu(); - let mut timer_queue = cpu.timer_queue.write(); - - timer_queue.enqueue(event); + cpu.enqueue_timer(event); } diff --git a/xernel/kernel/src/timer/mod.rs b/xernel/kernel/src/timer/mod.rs index 1a22d77e..b6f90a5b 100644 --- a/xernel/kernel/src/timer/mod.rs +++ b/xernel/kernel/src/timer/mod.rs @@ -37,7 +37,7 @@ pub fn timer_interrupt_handler(_frame: &mut TrapFrame) { let cpu = current_cpu(); - let mut timer_queue = cpu.timer_queue.write(); + let mut timer_queue = cpu.timer_queue.aquire_at(IPL::High); //timer_queue.deadlines(); @@ -55,12 +55,6 @@ pub fn timer_interrupt_handler(_frame: &mut TrapFrame) { } else { // No event in event queue? } - - timer_queue.unlock(); -} - -pub fn enqueue_timer(event: TimerEvent) { - current_cpu().timer_queue.write().enqueue(event); } pub fn hardclock(_: ()) { @@ -68,6 +62,5 @@ pub fn hardclock(_: ()) { UPTIME.fetch_add(1, Ordering::SeqCst); let event = TimerEvent::new(hardclock, (), Duration::from_secs(1), false); - // TODO: use convenience functions - current_cpu().timer_queue.write().enqueue(event); + current_cpu().enqueue_timer(event); }