|
|
|
@ -1,6 +1,13 @@
|
|
|
|
|
use core::cmp::Ordering;
|
|
|
|
|
|
|
|
|
|
use riscv::register::time;
|
|
|
|
|
use crate::sbi::set_timer;
|
|
|
|
|
use crate::config::CLOCK_FREQ;
|
|
|
|
|
use crate::task::{TaskControlBlock, add_task};
|
|
|
|
|
use crate::sync::UPSafeCell;
|
|
|
|
|
use alloc::collections::BinaryHeap;
|
|
|
|
|
use alloc::sync::Arc;
|
|
|
|
|
use lazy_static::*;
|
|
|
|
|
|
|
|
|
|
const TICKS_PER_SEC: usize = 100;
|
|
|
|
|
const MSEC_PER_SEC: usize = 1000;
|
|
|
|
@ -16,3 +23,54 @@ pub fn get_time_ms() -> usize {
|
|
|
|
|
pub fn set_next_trigger() {
|
|
|
|
|
set_timer(get_time() + CLOCK_FREQ / TICKS_PER_SEC);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct TimerCondVar {
|
|
|
|
|
pub expire_ms: usize,
|
|
|
|
|
pub task: Arc<TaskControlBlock>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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<Ordering> {
|
|
|
|
|
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: UPSafeCell<BinaryHeap<TimerCondVar>> = unsafe { UPSafeCell::new(
|
|
|
|
|
BinaryHeap::<TimerCondVar>::new()
|
|
|
|
|
)};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn add_timer(expire_ms: usize, task: Arc<TaskControlBlock>) {
|
|
|
|
|
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));
|
|
|
|
|
drop(timer);
|
|
|
|
|
timers.pop();
|
|
|
|
|
} else { break; }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|