diff --git a/src/driver/mod.rs b/src/driver/mod.rs index 45f5b56d..a80b91dc 100644 --- a/src/driver/mod.rs +++ b/src/driver/mod.rs @@ -1 +1,2 @@ pub mod keyboard; +pub mod timer; diff --git a/src/driver/timer.rs b/src/driver/timer.rs new file mode 100644 index 00000000..ad73322b --- /dev/null +++ b/src/driver/timer.rs @@ -0,0 +1,48 @@ +use crate::{interrupts, print}; +use core::future::Future; +use core::{ + pin::Pin, + sync::atomic::Ordering, + task::{Context, Poll}, +}; + +fn next_tick(current_tick: u64) -> impl Future { + NextTick { + ticks: current_tick, + } +} + +struct NextTick { + ticks: u64, +} + +impl Future for NextTick { + type Output = u64; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { + let current_ticks = interrupts::TIMER_TICKS.load(Ordering::Acquire); + + if self.ticks < current_ticks { + self.ticks += 1; + return Poll::Ready(self.ticks); + } + + interrupts::TIMER_INTERRUPT_WAKER.register(&cx.waker()); + let current_ticks = interrupts::TIMER_TICKS.load(Ordering::Acquire); + if self.ticks < current_ticks { + self.ticks += 1; + Poll::Ready(self.ticks) + } else { + Poll::Pending + } + } +} + +pub async fn print_ticks() { + let mut current_ticks = interrupts::TIMER_TICKS.load(Ordering::Acquire); + + loop { + current_ticks = next_tick(current_ticks).await; + print!("."); + } +} diff --git a/src/interrupts.rs b/src/interrupts.rs index 6fe17c4a..6ba1eed8 100644 --- a/src/interrupts.rs +++ b/src/interrupts.rs @@ -1,6 +1,9 @@ -use crate::{gdt, hlt_loop, print, println}; +use crate::{gdt, hlt_loop, println}; use conquer_once::spin::OnceCell; -use core::task::Waker; +use core::{ + sync::atomic::{AtomicU64, Ordering}, + task::Waker, +}; use crossbeam_queue::ArrayQueue; use futures_util::task::AtomicWaker; use lazy_static::lazy_static; @@ -92,8 +95,16 @@ extern "x86-interrupt" fn double_fault_handler( panic!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame); } +pub(crate) static TIMER_TICKS: AtomicU64 = AtomicU64::new(0); +pub(crate) static TIMER_INTERRUPT_WAKER: AtomicWaker = AtomicWaker::new(); + extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: &mut InterruptStackFrame) { - print!("."); + TIMER_TICKS.fetch_add(1, Ordering::Release); + if let Some(waker) = TIMER_INTERRUPT_WAKER.take() { + if let Err(_) = interrupt_wakeups().push(waker) { + println!("WARNING: dropping interrupt wakeup"); + } + } unsafe { PICS.lock() .notify_end_of_interrupt(InterruptIndex::Timer.as_u8()); diff --git a/src/main.rs b/src/main.rs index 5640cb70..88173350 100644 --- a/src/main.rs +++ b/src/main.rs @@ -68,6 +68,7 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { println!("It did not crash!"); }); + spawner.spawn(blog_os::driver::timer::print_ticks()); spawner.spawn(blog_os::driver::keyboard::print_keypresses()); executor.run();