use core::cmp::Ordering; use crate::config::CLOCK_FREQ; use crate::sbi::set_timer; use crate::sync::UPIntrFreeCell; use crate::task::{add_task, TaskControlBlock}; use alloc::collections::BinaryHeap; use alloc::sync::Arc; use lazy_static::*; use riscv::register::time; const TICKS_PER_SEC: usize = 100; const MSEC_PER_SEC: usize = 1000; pub fn get_time() -> usize { time::read() } pub fn get_time_ms() -> usize { time::read() / (CLOCK_FREQ / MSEC_PER_SEC) } pub fn set_next_trigger() { set_timer(get_time() + CLOCK_FREQ / TICKS_PER_SEC); } pub struct TimerCondVar { pub expire_ms: usize, pub task: Arc, } impl PartialEq for TimerCondVar { fn eq(&self, other: &Self) -> bool { self.expire_ms == other.expire_ms } } impl Eq for TimerCondVar {} impl PartialOrd for TimerCondVar { fn partial_cmp(&self, other: &Self) -> Option { let a = -(self.expire_ms as isize); let b = -(other.expire_ms as isize); Some(a.cmp(&b)) } } impl Ord for TimerCondVar { fn cmp(&self, other: &Self) -> Ordering { self.partial_cmp(other).unwrap() } } lazy_static! { static ref TIMERS: UPIntrFreeCell> = unsafe { UPIntrFreeCell::new(BinaryHeap::::new()) }; } pub fn add_timer(expire_ms: usize, task: Arc) { let mut timers = TIMERS.exclusive_access(); timers.push(TimerCondVar { expire_ms, task }); } pub fn check_timer() { let current_ms = get_time_ms(); let mut timers = TIMERS.exclusive_access(); while let Some(timer) = timers.peek() { if timer.expire_ms <= current_ms { add_task(Arc::clone(&timer.task)); timers.pop(); } else { break; } } }