mirror of
https://github.com/LearningOS/rust-based-os-comp2022.git
synced 2026-05-09 07:11:25 +08:00
add os[1-8]-ref for os refereces, add guide, add README
This commit is contained in:
83
os8-ref/src/timer.rs
Normal file
83
os8-ref/src/timer.rs
Normal file
@@ -0,0 +1,83 @@
|
||||
//! RISC-V timer-related functionality
|
||||
|
||||
use crate::config::CLOCK_FREQ;
|
||||
use crate::sbi::set_timer;
|
||||
use crate::sync::UPSafeCell;
|
||||
use crate::task::{add_task, TaskControlBlock};
|
||||
use alloc::collections::BinaryHeap;
|
||||
use alloc::sync::Arc;
|
||||
use core::cmp::Ordering;
|
||||
use lazy_static::*;
|
||||
use riscv::register::time;
|
||||
|
||||
const TICKS_PER_SEC: usize = 100;
|
||||
const MILLI_PER_SEC: usize = 1_000;
|
||||
const MICRO_PER_SEC: usize = 1_000_000;
|
||||
|
||||
/// read the `mtime` register
|
||||
pub fn get_time() -> usize {
|
||||
time::read()
|
||||
}
|
||||
|
||||
/// get current time in microseconds
|
||||
pub fn get_time_us() -> usize {
|
||||
time::read() / (CLOCK_FREQ / MICRO_PER_SEC)
|
||||
}
|
||||
|
||||
/// get current time in milliseconds
|
||||
pub fn get_time_ms() -> usize {
|
||||
time::read() / (CLOCK_FREQ / MILLI_PER_SEC)
|
||||
}
|
||||
|
||||
/// set the next timer interrupt
|
||||
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));
|
||||
timers.pop();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user