|
@@ -1,4 +1,4 @@
|
|
|
-use core::sync::atomic::{fence, Ordering};
|
|
|
+use core::sync::atomic::{compiler_fence, fence, Ordering};
|
|
|
|
|
|
use alloc::{string::ToString, sync::Arc};
|
|
|
use bitmap::{traits::BitMapOps, StaticBitmap};
|
|
@@ -19,7 +19,12 @@ use crate::{
|
|
|
mm::percpu::PerCpu,
|
|
|
process::ProcessManager,
|
|
|
smp::core::smp_get_processor_id,
|
|
|
- time::{clocksource::HZ, TimeArch},
|
|
|
+ time::{
|
|
|
+ clocksource::HZ,
|
|
|
+ jiffies::NSEC_PER_JIFFY,
|
|
|
+ timer::{try_raise_timer_softirq, update_timer_jiffies},
|
|
|
+ TimeArch,
|
|
|
+ },
|
|
|
};
|
|
|
|
|
|
pub struct RiscVSbiTimer;
|
|
@@ -29,6 +34,13 @@ static SBI_TIMER_INIT_BMP: SpinLock<StaticBitmap<{ PerCpu::MAX_CPU_NUM as usize
|
|
|
|
|
|
static mut INTERVAL_CNT: usize = 0;
|
|
|
|
|
|
+/// 已经过去的纳秒数
|
|
|
+///
|
|
|
+/// 0号核心用这个值来更新墙上时钟,他只能被0号核心访问
|
|
|
+static mut HART0_NSEC_PASSED: usize = 0;
|
|
|
+/// hart0上一次更新墙上时钟的时间
|
|
|
+static mut HART0_LAST_UPDATED: u64 = 0;
|
|
|
+
|
|
|
impl RiscVSbiTimer {
|
|
|
pub const TIMER_IRQ: IrqNumber = IrqNumber::from(5);
|
|
|
|
|
@@ -39,8 +51,9 @@ impl RiscVSbiTimer {
|
|
|
// smp_get_processor_id().data(),
|
|
|
// CurrentTimeArch::get_cycles() as u64
|
|
|
// );
|
|
|
- sbi_rt::set_timer(CurrentTimeArch::get_cycles() as u64 + unsafe { INTERVAL_CNT } as u64);
|
|
|
ProcessManager::update_process_times(trap_frame.is_from_user());
|
|
|
+ Self::update_nsec_passed_and_walltime();
|
|
|
+ sbi_rt::set_timer(CurrentTimeArch::get_cycles() as u64 + unsafe { INTERVAL_CNT } as u64);
|
|
|
Ok(())
|
|
|
}
|
|
|
|
|
@@ -52,6 +65,30 @@ impl RiscVSbiTimer {
|
|
|
fn disable() {
|
|
|
unsafe { riscv::register::sie::clear_stimer() };
|
|
|
}
|
|
|
+
|
|
|
+ fn update_nsec_passed_and_walltime() {
|
|
|
+ if smp_get_processor_id().data() != 0 {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ let cycles = CurrentTimeArch::get_cycles() as u64;
|
|
|
+ let nsec_passed =
|
|
|
+ CurrentTimeArch::cycles2ns((cycles - unsafe { HART0_LAST_UPDATED }) as usize);
|
|
|
+ unsafe {
|
|
|
+ HART0_LAST_UPDATED = cycles;
|
|
|
+ HART0_NSEC_PASSED += nsec_passed;
|
|
|
+ }
|
|
|
+
|
|
|
+ let jiffies = unsafe { HART0_NSEC_PASSED } / NSEC_PER_JIFFY as usize;
|
|
|
+ unsafe { HART0_NSEC_PASSED %= NSEC_PER_JIFFY as usize };
|
|
|
+
|
|
|
+ update_timer_jiffies(
|
|
|
+ jiffies as u64,
|
|
|
+ (jiffies * NSEC_PER_JIFFY as usize / 1000) as i64,
|
|
|
+ );
|
|
|
+ try_raise_timer_softirq();
|
|
|
+ compiler_fence(Ordering::SeqCst);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/// riscv 初始化本地调度时钟源
|