Browse Source

修复jiffy时钟过快问题,启用gettimeofday测试,修改mount测试 (#680)

1. 把clock tick rate与hpet频率关联起来
2. 修复墙上时间同步错误的问题
3. 启用时间watch dog.
4. 修复时间流逝速度异常

---------

Co-authored-by: longjin <longjin@DragonOS.org>
Donkey Kane 1 year ago
parent
commit
b8ed38251d

+ 1 - 1
kernel/src/Makefile

@@ -36,7 +36,7 @@ export ASFLAGS := --64
 LD_LIST := ""
 
 
-kernel_subdirs := common driver debug syscall libs time
+kernel_subdirs := common driver debug syscall libs
 
 
 kernel_rust:

+ 9 - 1
kernel/src/arch/riscv64/time.rs

@@ -1,6 +1,9 @@
-use crate::time::TimeArch;
+use crate::time::{clocksource::HZ, TimeArch};
 pub struct RiscV64TimeArch;
 
+/// 这个是系统jiffies时钟源的固有频率(不是调频之后的)
+pub const CLOCK_TICK_RATE: u32 = HZ as u32 * 1000000;
+
 impl TimeArch for RiscV64TimeArch {
     fn get_cycles() -> usize {
         riscv::register::cycle::read()
@@ -9,4 +12,9 @@ impl TimeArch for RiscV64TimeArch {
     fn cal_expire_cycles(ns: usize) -> usize {
         todo!()
     }
+    /// 将CPU的时钟周期数转换为纳秒
+    #[inline(always)]
+    fn cycles2ns(cycles: usize) -> usize {
+        todo!()
+    }
 }

+ 8 - 4
kernel/src/arch/x86_64/driver/hpet.rs

@@ -31,7 +31,10 @@ use crate::{
         mmio_buddy::{mmio_pool, MMIOSpaceGuard},
         PhysAddr,
     },
-    time::timer::{clock, timer_get_first_expire, update_timer_jiffies},
+    time::{
+        jiffies::NSEC_PER_JIFFY,
+        timer::{clock, timer_get_first_expire, update_timer_jiffies},
+    },
 };
 
 static mut HPET_INSTANCE: Option<Hpet> = None;
@@ -54,8 +57,8 @@ struct InnerHpet {
 }
 
 impl Hpet {
-    /// HPET0 中断间隔为 10ms
-    pub const HPET0_INTERVAL_USEC: u64 = 10000;
+    /// HPET0 中断间隔
+    pub const HPET0_INTERVAL_USEC: u64 = NSEC_PER_JIFFY as u64 / 1000;
 
     const HPET0_IRQ: IrqNumber = IrqNumber::new(34);
 
@@ -70,6 +73,7 @@ impl Hpet {
                 .unwrap()
         };
         let tm_num = hpet.timers_num();
+        kdebug!("HPET0_INTERVAL_USEC: {}", Self::HPET0_INTERVAL_USEC);
         kinfo!("HPET has {} timers", tm_num);
         hpet_info.hpet_number = tm_num as u8;
 
@@ -238,7 +242,7 @@ impl Hpet {
     pub(super) fn handle_irq(&self, timer_num: u32) {
         if timer_num == 0 {
             assert!(!CurrentIrqArch::is_irq_enabled());
-            update_timer_jiffies(Self::HPET0_INTERVAL_USEC, Self::HPET0_INTERVAL_USEC as i64);
+            update_timer_jiffies(1, Self::HPET0_INTERVAL_USEC as i64);
 
             if let Ok(first_expire) = timer_get_first_expire() {
                 if first_expire <= clock() {

+ 11 - 1
kernel/src/arch/x86_64/time.rs

@@ -1,10 +1,14 @@
-use crate::time::TimeArch;
+use crate::time::{clocksource::HZ, TimeArch};
 
 use super::driver::tsc::TSCManager;
 
+/// 这个是系统jiffies时钟源的固有频率(不是调频之后的)
+pub const CLOCK_TICK_RATE: u32 = HZ as u32 * 1000000;
+
 pub struct X86_64TimeArch;
 
 impl TimeArch for X86_64TimeArch {
+    #[inline(always)]
     fn get_cycles() -> usize {
         unsafe { x86::time::rdtsc() as usize }
     }
@@ -12,4 +16,10 @@ impl TimeArch for X86_64TimeArch {
     fn cal_expire_cycles(ns: usize) -> usize {
         Self::get_cycles() + ns * TSCManager::cpu_khz() as usize / 1000000
     }
+
+    /// 将CPU的时钟周期数转换为纳秒
+    #[inline(always)]
+    fn cycles2ns(cycles: usize) -> usize {
+        cycles * 1000000 / TSCManager::cpu_khz() as usize
+    }
 }

+ 1 - 1
kernel/src/common/glib.h

@@ -65,4 +65,4 @@ static __always_inline ul ALIGN(const ul addr, const ul _align)
  * @param size 大小
  * @return void* 指向目标地址的指针
  */
-void *memmove(void *dst, const void *src, uint64_t size);
+void *c_memmove(void *dst, const void *src, uint64_t size);

+ 9 - 1
kernel/src/debug/klog/mm.rs

@@ -1,6 +1,9 @@
 extern crate klog_types;
 
-use core::intrinsics::unlikely;
+use core::{
+    intrinsics::unlikely,
+    sync::atomic::{compiler_fence, Ordering},
+};
 
 use klog_types::{AllocatorLog, AllocatorLogType, LogSource, MMLogChannel};
 
@@ -63,13 +66,18 @@ impl MMDebugLogManager {
 
         let mut log = log;
         loop {
+            compiler_fence(Ordering::SeqCst);
             let r = __MM_ALLOCATOR_LOG_CHANNEL.buf.push(log);
+            compiler_fence(Ordering::SeqCst);
             if let Err(r) = r {
                 // 如果日志通道满了,就把最早的日志丢弃
                 if __MM_ALLOCATOR_LOG_CHANNEL.buf.remaining() == 0 {
+                    compiler_fence(Ordering::SeqCst);
                     __MM_ALLOCATOR_LOG_CHANNEL.buf.pop();
+                    compiler_fence(Ordering::SeqCst);
                 }
                 log = r.into_inner();
+                compiler_fence(Ordering::SeqCst);
             } else {
                 break;
             }

+ 1 - 1
kernel/src/driver/hid/hidparse.c

@@ -95,7 +95,7 @@ static __always_inline void __pop_usage_stack(struct hid_parser *parser)
     if (parser->usage_size > 0)
     {
         for (int js = 0; js < parser->usage_size - 1; ++js)
-            memmove(&parser->usage_table[js], &parser->usage_table[js + 1], sizeof(struct hid_node_t));
+            c_memmove(&parser->usage_table[js], &parser->usage_table[js + 1], sizeof(struct hid_node_t));
 
         --parser->usage_size;
     }

+ 0 - 1
kernel/src/include/bindings/wrapper.h

@@ -25,6 +25,5 @@
 #include <mm/slab.h>
 #include <process/process.h>
 #include <sched/sched.h>
-#include <time/clocksource.h>
 #include <time/sleep.h>
 #include <common/errno.h>

+ 1 - 1
kernel/src/libs/glib.c

@@ -10,7 +10,7 @@
  * @param size 大小
  * @return void* 指向目标地址的指针
  */
-void *memmove(void *dst, const void *src, uint64_t size)
+void *c_memmove(void *dst, const void *src, uint64_t size)
 {
     const char *_src = src;
 	char *_dst = dst;

+ 1 - 3
kernel/src/process/kthread.rs

@@ -16,7 +16,7 @@ use crate::{
     arch::{sched::sched, CurrentIrqArch},
     exception::{irqdesc::IrqAction, InterruptArch},
     init::initial_kthread::initial_kernel_thread,
-    kdebug, kinfo,
+    kinfo,
     libs::{once::Once, spinlock::SpinLock},
     process::{ProcessManager, ProcessState},
 };
@@ -439,7 +439,6 @@ impl KernelThreadMechanism {
     #[inline(never)]
     fn kthread_daemon() -> i32 {
         let current_pcb = ProcessManager::current_pcb();
-        kdebug!("kthread_daemon: pid: {:?}", current_pcb.pid());
         {
             // 初始化worker_private
             let mut worker_private_guard = current_pcb.worker_private();
@@ -454,7 +453,6 @@ impl KernelThreadMechanism {
             let mut list = KTHREAD_CREATE_LIST.lock();
             while let Some(info) = list.pop_front() {
                 drop(list);
-
                 // create a new kernel thread
                 let result: Result<Pid, SystemError> = Self::__inner_create(
                     &info,

+ 1 - 1
kernel/src/sched/completion.rs

@@ -24,7 +24,7 @@ impl Completion {
 
     /// @brief 基本函数:通用的处理wait命令的函数(即所有wait_for_completion函数最核心部分在这里)
     ///
-    /// @param timeout 非负整数
+    /// @param timeout jiffies
     /// @param interuptible 设置进程是否能被打断
     /// @return 返回剩余时间或者SystemError
     fn do_wait_for_common(&self, mut timeout: i64, interuptible: bool) -> Result<i64, SystemError> {

+ 0 - 8
kernel/src/time/Makefile

@@ -1,8 +0,0 @@
-
-CFLAGS += -I .
-
-
-all: clocksource.o
-
-clocksource.o: clocksource.c
-	$(CC) $(CFLAGS) -c clocksource.c -o clocksource.o

+ 0 - 10
kernel/src/time/clocksource.c

@@ -1,10 +0,0 @@
-#include "clocksource.h"
-#include <common/kprint.h>
-
-void run_watchdog_kthread()
-{
-    kerror("run_watchdog_kthread");
-    while(1);
-    // todo: 进程管理重构后,改掉这里,换到rust的实现
-    // kthread_run(rs_clocksource_watchdog_kthread, NULL, "clocksource_watchdog");
-}

+ 0 - 7
kernel/src/time/clocksource.h

@@ -1,7 +0,0 @@
-#pragma once
-
-
-extern int rs_clocksource_watchdog_kthread(void *_data);
-
-
-void run_watchdog_kthread();

+ 105 - 38
kernel/src/time/clocksource.rs

@@ -1,15 +1,29 @@
 use core::{
-    ffi::c_void,
     fmt::Debug,
     sync::atomic::{AtomicBool, Ordering},
 };
 
-use alloc::{boxed::Box, collections::LinkedList, string::String, sync::Arc, vec::Vec};
+use alloc::{
+    boxed::Box,
+    collections::LinkedList,
+    string::{String, ToString},
+    sync::Arc,
+    vec::Vec,
+};
 use lazy_static::__Deref;
 use system_error::SystemError;
+use unified_init::macros::unified_init;
 
 use crate::{
-    include::bindings::bindings::run_watchdog_kthread, kdebug, kinfo, libs::spinlock::SpinLock,
+    arch::{sched::sched, CurrentIrqArch},
+    exception::InterruptArch,
+    init::initcall::INITCALL_LATE,
+    kdebug, kinfo,
+    libs::spinlock::SpinLock,
+    process::{
+        kthread::{KernelThreadClosure, KernelThreadMechanism},
+        ProcessControlBlock, ProcessManager,
+    },
 };
 
 use super::{
@@ -33,6 +47,8 @@ lazy_static! {
 
 }
 
+static mut WATCHDOG_KTHREAD: Option<Arc<ProcessControlBlock>> = None;
+
 /// 正在被使用时钟源
 pub static CUR_CLOCKSOURCE: SpinLock<Option<Arc<dyn Clocksource>>> = SpinLock::new(None);
 /// 是否完成加载
@@ -48,17 +64,16 @@ pub const WATCHDOG_THRESHOLD: u32 = NSEC_PER_SEC >> 4;
 
 // 时钟周期数
 #[derive(Debug, Clone, Copy)]
-#[repr(transparent)]
-pub struct CycleNum(pub u64);
+pub struct CycleNum(u64);
 
 #[allow(dead_code)]
 impl CycleNum {
     #[inline(always)]
-    pub fn new(cycle: u64) -> Self {
+    pub const fn new(cycle: u64) -> Self {
         Self(cycle)
     }
     #[inline(always)]
-    pub fn data(&self) -> u64 {
+    pub const fn data(&self) -> u64 {
         self.0
     }
     #[inline(always)]
@@ -140,7 +155,7 @@ impl ClocksouceWatchdog {
     /// 启用检查器
     pub fn clocksource_start_watchdog(&mut self) {
         // 如果watchdog未被设置或者已经启用了就退出
-        let watchdog_list = &WATCHDOG_LIST.lock();
+        let watchdog_list = WATCHDOG_LIST.lock_irqsave();
         if self.is_running || self.watchdog.is_none() || watchdog_list.is_empty() {
             return;
         }
@@ -286,7 +301,7 @@ impl dyn Clocksource {
     pub fn clocksource_enqueue(&self) {
         // 根据rating由大到小排序
         let cs_data = self.clocksource_data();
-        let list_guard = &mut CLOCKSOURCE_LIST.lock();
+        let mut list_guard = CLOCKSOURCE_LIST.lock();
         let mut spilt_pos: usize = 0;
         for (pos, ele) in list_guard.iter().enumerate() {
             if ele.clocksource_data().rating < cs_data.rating {
@@ -340,12 +355,12 @@ impl dyn Clocksource {
             }
 
             // 将时钟源加入到监控队列中
-            let mut list_guard = WATCHDOG_LIST.lock();
+            let mut list_guard = WATCHDOG_LIST.lock_irqsave();
             list_guard.push_back(cs.clone());
             drop(list_guard);
 
             // 对比当前注册的时间源的精度和监视器的精度
-            let cs_watchdog = &mut CLOCKSOUCE_WATCHDOG.lock();
+            let mut cs_watchdog = CLOCKSOUCE_WATCHDOG.lock_irqsave();
             if cs_watchdog.watchdog.is_none()
                 || cs_data.rating
                     > cs_watchdog
@@ -389,7 +404,7 @@ impl dyn Clocksource {
         // 启动watchdog线程 进行后续处理
         if unsafe { FINISHED_BOOTING.load(Ordering::Relaxed) } {
             // TODO 在实现了工作队列后,将启动线程换成schedule work
-            unsafe { run_watchdog_kthread() }
+            run_watchdog_kthread();
         }
         return Ok(0);
     }
@@ -397,14 +412,14 @@ impl dyn Clocksource {
     /// # 将时间源从监视链表中弹出
     fn clocksource_dequeue_watchdog(&self) {
         let data = self.clocksource_data();
-        let mut locked_watchdog = CLOCKSOUCE_WATCHDOG.lock();
+        let mut locked_watchdog = CLOCKSOUCE_WATCHDOG.lock_irqsave();
         let watchdog = locked_watchdog
             .get_watchdog()
             .clone()
             .unwrap()
             .clocksource_data();
 
-        let mut list = WATCHDOG_LIST.lock();
+        let mut list = WATCHDOG_LIST.lock_irqsave();
         let mut size = list.len();
 
         let mut del_pos: usize = size;
@@ -654,10 +669,12 @@ pub fn clocksource_suspend() {
 /// * `Ok()` - 检查完成
 /// * `Err(SystemError)` - 错误码
 pub fn clocksource_watchdog() -> Result<(), SystemError> {
-    let mut cs_watchdog = CLOCKSOUCE_WATCHDOG.lock();
+    let mut cs_watchdog = CLOCKSOUCE_WATCHDOG.lock_irqsave();
+    // kdebug!("clocksource_watchdog start");
 
     // watchdog没有在运行的话直接退出
     if !cs_watchdog.is_running || cs_watchdog.watchdog.is_none() {
+        // kdebug!("is_running = {:?},watchdog = {:?}", cs_watchdog.is_running, cs_watchdog.watchdog);
         return Ok(());
     }
     let cur_watchdog = cs_watchdog.watchdog.as_ref().unwrap().clone();
@@ -672,7 +689,7 @@ pub fn clocksource_watchdog() -> Result<(), SystemError> {
     );
     cs_watchdog.last_check = CycleNum(cur_wd_nowclock);
     drop(cs_watchdog);
-    let watchdog_list = &mut WATCHDOG_LIST.lock();
+    let watchdog_list = WATCHDOG_LIST.lock_irqsave();
     for cs in watchdog_list.iter() {
         let mut cs_data = cs.clocksource_data();
         // 判断时钟源是否已经被标记为不稳定
@@ -680,8 +697,9 @@ pub fn clocksource_watchdog() -> Result<(), SystemError> {
             .flags
             .contains(ClocksourceFlags::CLOCK_SOURCE_UNSTABLE)
         {
+            // kdebug!("clocksource_watchdog unstable");
             // 启动watchdog_kthread
-            unsafe { run_watchdog_kthread() };
+            run_watchdog_kthread();
             continue;
         }
         // 读取时钟源现在的时间
@@ -692,6 +710,7 @@ pub fn clocksource_watchdog() -> Result<(), SystemError> {
             .flags
             .contains(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG)
         {
+            // kdebug!("clocksource_watchdog start watch");
             cs_data
                 .flags
                 .insert(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG);
@@ -700,7 +719,7 @@ pub fn clocksource_watchdog() -> Result<(), SystemError> {
             cs.update_clocksource_data(cs_data.clone())?;
             continue;
         }
-
+        // kdebug!("cs_data.watchdog_last = {:?},cs_now_clock = {:?}", cs_data.watchdog_last, cs_now_clock);
         // 计算时钟源的误差
         let cs_dev_nsec = clocksource_cyc2ns(
             CycleNum(cs_now_clock.div(cs_data.watchdog_last).data() & cs_data.mask.bits),
@@ -711,10 +730,12 @@ pub fn clocksource_watchdog() -> Result<(), SystemError> {
         cs_data.watchdog_last = cs_now_clock;
         cs.update_clocksource_data(cs_data.clone())?;
         if cs_dev_nsec.abs_diff(wd_dev_nsec) > WATCHDOG_THRESHOLD.into() {
+            // kdebug!("set_unstable");
             // 误差过大,标记为unstable
             cs.set_unstable((cs_dev_nsec - wd_dev_nsec).try_into().unwrap())?;
             continue;
         }
+        // kdebug!("clocksource_watchdog aaa");
 
         // 判断是否要切换为高精度模式
         if !cs_data
@@ -733,22 +754,25 @@ pub fn clocksource_watchdog() -> Result<(), SystemError> {
             cs.update_clocksource_data(cs_data)?;
             // TODO 通知tick机制 切换为高精度模式
         }
-        let mut cs_watchdog = CLOCKSOUCE_WATCHDOG.lock();
-        // FIXME 需要保证所有cpu时间统一
-        cs_watchdog.timer_expires += WATCHDOG_INTERVAL;
-        //创建定时器执行watchdog
-        let watchdog_func = Box::new(WatchdogTimerFunc {});
-        let watchdog_timer = Timer::new(watchdog_func, cs_watchdog.timer_expires);
-        watchdog_timer.activate();
     }
+    create_new_watchdog_timer_function();
     return Ok(());
 }
 
-/// # watchdog线程的逻辑,执行unstable的后续操作
-pub fn clocksource_watchdog_kthread() {
+fn create_new_watchdog_timer_function() {
+    let mut cs_watchdog = CLOCKSOUCE_WATCHDOG.lock_irqsave();
+
+    cs_watchdog.timer_expires += WATCHDOG_INTERVAL;
+    //创建定时器执行watchdog
+    let watchdog_func = Box::new(WatchdogTimerFunc {});
+    let watchdog_timer = Timer::new(watchdog_func, cs_watchdog.timer_expires);
+    watchdog_timer.activate();
+}
+
+fn __clocksource_watchdog_kthread() {
     let mut del_vec: Vec<usize> = Vec::new();
     let mut del_clocks: Vec<Arc<dyn Clocksource>> = Vec::new();
-    let wd_list = &mut WATCHDOG_LIST.lock();
+    let mut wd_list = WATCHDOG_LIST.lock_irqsave();
 
     // 将不稳定的时钟源弹出监视链表
     for (pos, ele) in wd_list.iter().enumerate() {
@@ -766,17 +790,47 @@ pub fn clocksource_watchdog_kthread() {
 
     // 检查是否需要停止watchdog
     CLOCKSOUCE_WATCHDOG
-        .lock()
+        .lock_irqsave()
         .clocksource_stop_watchdog(wd_list.len());
-    // 将不稳定的时钟源精度都设置为最低
+    drop(wd_list);
+    // 将不稳定的时钟源精度都设置为最低,然后删除unstable标记
     for clock in del_clocks.iter() {
         clock.clocksource_change_rating(0);
+        let mut data = clock.clocksource_data();
+        data.watchdog_last = clock.read();
+        kdebug!("kthread: watchdog_last = {:?}", data.watchdog_last);
+        data.flags.remove(ClocksourceFlags::CLOCK_SOURCE_UNSTABLE);
+        clock
+            .update_clocksource_data(data)
+            .expect("clocksource_watchdog_kthread: failed to update clocksource data");
+
+        // 重新插入监视链表
+        clock
+            .clocksource_enqueue_watchdog()
+            .expect("clocksource_watchdog_kthread: failed to enqueue watchdog list");
     }
 }
 
+/// # watchdog线程的逻辑,执行unstable的后续操作
+pub fn clocksource_watchdog_kthread() -> i32 {
+    // return 0;
+    loop {
+        // kdebug!("clocksource_watchdog_kthread start");
+        __clocksource_watchdog_kthread();
+        if KernelThreadMechanism::should_stop(&ProcessManager::current_pcb()) {
+            break;
+        }
+        let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
+        ProcessManager::mark_sleep(true).expect("clocksource_watchdog_kthread:mark sleep failed");
+        drop(irq_guard);
+        sched();
+    }
+    return 0;
+}
+
 /// # 清空所有时钟源的watchdog标志位
 pub fn clocksource_reset_watchdog() {
-    let list_guard = WATCHDOG_LIST.lock();
+    let list_guard = WATCHDOG_LIST.lock_irqsave();
     for ele in list_guard.iter() {
         ele.clocksource_data()
             .flags
@@ -831,15 +885,28 @@ pub fn clocksource_boot_finish() {
     cur_clocksource.replace(clocksource_default_clock());
     unsafe { FINISHED_BOOTING.store(true, Ordering::Relaxed) };
     // 清除不稳定的时钟源
-    clocksource_watchdog_kthread();
+    __clocksource_watchdog_kthread();
     kdebug!("clocksource_boot_finish");
 }
 
-// ======== 以下为对C的接口 ========
+fn run_watchdog_kthread() {
+    if let Some(watchdog_kthread) = unsafe { WATCHDOG_KTHREAD.clone() } {
+        ProcessManager::wakeup(&watchdog_kthread).ok();
+    }
+}
+
+#[unified_init(INITCALL_LATE)]
+pub fn init_watchdog_kthread() -> Result<(), SystemError> {
+    assert!(CurrentIrqArch::is_irq_enabled());
+    let closure = KernelThreadClosure::StaticEmptyClosure((
+        &(clocksource_watchdog_kthread as fn() -> i32),
+        (),
+    ));
+    let pcb = KernelThreadMechanism::create_and_run(closure, "clocksource watchdog".to_string())
+        .ok_or(SystemError::EPERM)?;
+    unsafe {
+        WATCHDOG_KTHREAD.replace(pcb);
+    }
 
-/// # 启动watchdog线程的辅助函数
-#[no_mangle]
-pub extern "C" fn rs_clocksource_watchdog_kthread(_data: c_void) -> i32 {
-    clocksource_watchdog_kthread();
-    return 0;
+    return Ok(());
 }

+ 13 - 11
kernel/src/time/jiffies.rs

@@ -4,7 +4,7 @@ use alloc::{
 };
 use system_error::SystemError;
 
-use crate::{kerror, kinfo, libs::spinlock::SpinLock};
+use crate::{arch::time::CLOCK_TICK_RATE, kerror, kinfo, libs::spinlock::SpinLock};
 
 use super::{
     clocksource::{Clocksource, ClocksourceData, ClocksourceFlags, ClocksourceMask, CycleNum, HZ},
@@ -14,11 +14,12 @@ use super::{
 lazy_static! {
     pub static ref DEFAULT_CLOCK: Arc<ClocksourceJiffies> = ClocksourceJiffies::new();
 }
-pub const CLOCK_TICK_RATE: u32 = HZ as u32 * 100000;
+
 pub const JIFFIES_SHIFT: u32 = 8;
 pub const LATCH: u32 = (CLOCK_TICK_RATE + (HZ as u32) / 2) / HZ as u32;
 pub const ACTHZ: u32 = sh_div(CLOCK_TICK_RATE, LATCH, 8);
-pub const NSEC_PER_JIFFY: u32 = (NSEC_PER_SEC << 8) / ACTHZ;
+//TODO 编写测试,保证始终跳动间隔与现实一致(两种时钟源进行对拍)
+pub const NSEC_PER_JIFFY: u32 = (((NSEC_PER_SEC as u64) << 8) / ACTHZ as u64) as u32;
 pub const fn sh_div(nom: u32, den: u32, lsh: u32) -> u32 {
     (((nom) / (den)) << (lsh)) + ((((nom) % (den)) << (lsh)) + (den) / 2) / (den)
 }
@@ -34,19 +35,19 @@ pub struct InnerJiffies {
 
 impl Clocksource for ClocksourceJiffies {
     fn read(&self) -> CycleNum {
-        CycleNum(clock())
+        CycleNum::new(clock())
     }
 
     fn clocksource_data(&self) -> ClocksourceData {
-        let inner = self.0.lock();
+        let inner = self.0.lock_irqsave();
         return inner.data.clone();
     }
 
     fn clocksource(&self) -> Arc<dyn Clocksource> {
-        self.0.lock().self_ref.upgrade().unwrap()
+        self.0.lock_irqsave().self_ref.upgrade().unwrap()
     }
     fn update_clocksource_data(&self, _data: ClocksourceData) -> Result<(), SystemError> {
-        let d = &mut self.0.lock().data;
+        let d = &mut self.0.lock_irqsave().data;
         d.set_flags(_data.flags);
         d.set_mask(_data.mask);
         d.set_max_idle_ns(_data.max_idle_ns);
@@ -54,6 +55,7 @@ impl Clocksource for ClocksourceJiffies {
         d.set_name(_data.name);
         d.set_rating(_data.rating);
         d.set_shift(_data.shift);
+        d.watchdog_last = _data.watchdog_last;
         return Ok(());
     }
 
@@ -71,15 +73,15 @@ impl ClocksourceJiffies {
             shift: JIFFIES_SHIFT,
             max_idle_ns: Default::default(),
             flags: ClocksourceFlags::new(0),
-            watchdog_last: CycleNum(0),
+            watchdog_last: CycleNum::new(0),
         };
-        let jieffies = Arc::new(ClocksourceJiffies(SpinLock::new(InnerJiffies {
+        let jiffies = Arc::new(ClocksourceJiffies(SpinLock::new(InnerJiffies {
             data,
             self_ref: Default::default(),
         })));
-        jieffies.0.lock().self_ref = Arc::downgrade(&jieffies);
+        jiffies.0.lock().self_ref = Arc::downgrade(&jiffies);
 
-        return jieffies;
+        return jiffies;
     }
 }
 pub fn clocksource_default_clock() -> Arc<ClocksourceJiffies> {

+ 3 - 0
kernel/src/time/mod.rs

@@ -492,4 +492,7 @@ pub trait TimeArch {
     ///
     /// The expire cycles
     fn cal_expire_cycles(ns: usize) -> usize;
+
+    /// 将CPU的时钟周期数转换为纳秒
+    fn cycles2ns(cycles: usize) -> usize;
 }

+ 67 - 40
kernel/src/time/timekeeping.rs

@@ -1,12 +1,12 @@
 use alloc::sync::Arc;
-use core::sync::atomic::{compiler_fence, AtomicBool, AtomicI64, Ordering};
+use core::sync::atomic::{compiler_fence, AtomicBool, AtomicI64, AtomicUsize, Ordering};
 use system_error::SystemError;
 
 use crate::{
-    arch::CurrentIrqArch,
+    arch::{CurrentIrqArch, CurrentTimeArch},
     exception::InterruptArch,
     kdebug, kinfo,
-    libs::rwlock::RwLock,
+    libs::rwlock::{RwLock, RwLockReadGuard},
     time::{
         jiffies::{clocksource_default_clock, jiffies_init},
         timekeep::ktime_get_real_ns,
@@ -17,7 +17,7 @@ use crate::{
 use super::{
     clocksource::{clocksource_cyc2ns, Clocksource, CycleNum, HZ},
     syscall::PosixTimeval,
-    NSEC_PER_SEC, USEC_PER_SEC,
+    TimeArch, NSEC_PER_SEC,
 };
 /// NTP周期频率
 pub const NTP_INTERVAL_FREQ: u64 = HZ;
@@ -30,13 +30,16 @@ pub const NTP_SCALE_SHIFT: u32 = 32;
 pub static TIMEKEEPING_SUSPENDED: AtomicBool = AtomicBool::new(false);
 /// 已经递增的微秒数
 static __ADDED_USEC: AtomicI64 = AtomicI64::new(0);
-/// 已经递增的秒数
-static __ADDED_SEC: AtomicI64 = AtomicI64::new(0);
 /// timekeeper全局变量,用于管理timekeeper模块
 static mut __TIMEKEEPER: Option<Timekeeper> = None;
 
 #[derive(Debug)]
-pub struct Timekeeper(RwLock<TimekeeperData>);
+pub struct Timekeeper {
+    inner: RwLock<TimekeeperData>,
+
+    /// 上一次更新墙上时间时的CPU周期数
+    last_update_cpu_cycle: AtomicUsize,
+}
 
 #[allow(dead_code)]
 #[derive(Debug)]
@@ -71,7 +74,7 @@ impl TimekeeperData {
         Self {
             clock: None,
             shift: Default::default(),
-            cycle_interval: CycleNum(0),
+            cycle_interval: CycleNum::new(0),
             xtime_interval: Default::default(),
             xtime_remainder: Default::default(),
             raw_interval: Default::default(),
@@ -99,13 +102,20 @@ impl TimekeeperData {
     }
 }
 impl Timekeeper {
+    fn new() -> Self {
+        Self {
+            inner: RwLock::new(TimekeeperData::new()),
+            last_update_cpu_cycle: AtomicUsize::new(0),
+        }
+    }
+
     /// # 设置timekeeper的参数
     ///
     /// ## 参数
     ///
     /// * 'clock' - 指定的时钟实际类型。初始为ClocksourceJiffies
     pub fn timekeeper_setup_internals(&self, clock: Arc<dyn Clocksource>) {
-        let mut timekeeper = self.0.write_irqsave();
+        let mut timekeeper = self.inner.write_irqsave();
         // 更新clock
         let mut clock_data = clock.clocksource_data();
         clock_data.watchdog_last = clock.read();
@@ -120,7 +130,7 @@ impl Timekeeper {
         temp += (clock_data.mult / 2) as u64;
         // do div
 
-        timekeeper.cycle_interval = CycleNum(temp);
+        timekeeper.cycle_interval = CycleNum::new(temp);
         timekeeper.xtime_interval = temp * clock_data.mult as u64;
         // 这里可能存在下界溢出问题,debug模式下会报错panic
         timekeeper.xtime_remainder = (ntpinterval - timekeeper.xtime_interval) as i64;
@@ -134,19 +144,39 @@ impl Timekeeper {
         timekeeper.mult = clock_data.mult;
     }
 
-    /// # 获取当前时钟源距离上次检测走过的纳秒数
+    /// # 获取当前时钟源距离上次watchdog检测走过的纳秒数
     #[allow(dead_code)]
     pub fn tk_get_ns(&self) -> u64 {
-        let timekeeper = self.0.read_irqsave();
+        let timekeeper: RwLockReadGuard<'_, TimekeeperData> = self.inner.read_irqsave();
         let clock = timekeeper.clock.clone().unwrap();
         drop(timekeeper);
+
         let clock_now = clock.read();
         let clock_data = clock.clocksource_data();
         let clock_delta = clock_now.div(clock_data.watchdog_last).data() & clock_data.mask.bits();
-        // clock_shift的值错误导致时间流逝速度异常,+5为临时修改以确保系统正常运作,目前追踪到的设置在DragonOS-dev/blob/fix_time/kernel/src/time/jiffies.rs#L18,但是修改无效
-        return clocksource_cyc2ns(CycleNum(clock_delta), clock_data.mult, clock_data.shift + 5);
+
+        return clocksource_cyc2ns(
+            CycleNum::new(clock_delta),
+            clock_data.mult,
+            clock_data.shift,
+        );
+    }
+
+    #[inline]
+    fn do_read_cpu_cycle_ns(&self) -> usize {
+        CurrentTimeArch::cycles2ns(
+            CurrentTimeArch::get_cycles()
+                .wrapping_sub(self.last_update_cpu_cycle.load(Ordering::SeqCst)),
+        )
+    }
+
+    fn mark_update_wall_time_ok(&self) {
+        self.last_update_cpu_cycle
+            .store(CurrentTimeArch::get_cycles(), Ordering::SeqCst);
     }
 }
+
+#[inline(always)]
 pub fn timekeeper() -> &'static Timekeeper {
     let r = unsafe { __TIMEKEEPER.as_ref().unwrap() };
 
@@ -154,7 +184,7 @@ pub fn timekeeper() -> &'static Timekeeper {
 }
 
 pub fn timekeeper_init() {
-    unsafe { __TIMEKEEPER = Some(Timekeeper(RwLock::new(TimekeeperData::new()))) };
+    unsafe { __TIMEKEEPER = Some(Timekeeper::new()) };
 }
 
 /// # 获取1970.1.1至今的UTC时间戳(最小单位:nsec)
@@ -166,33 +196,33 @@ pub fn getnstimeofday() -> TimeSpec {
     // kdebug!("enter getnstimeofday");
 
     let nsecs;
-    let mut _xtime = TimeSpec {
-        tv_nsec: 0,
-        tv_sec: 0,
-    };
+    let mut xtime: TimeSpec;
     loop {
-        match timekeeper().0.try_read_irqsave() {
+        match timekeeper().inner.try_read_irqsave() {
             None => continue,
             Some(tk) => {
-                _xtime = tk.xtime;
+                xtime = tk.xtime;
                 drop(tk);
-                nsecs = timekeeper().tk_get_ns();
+                // 提供基于cpu周期数的ns时间,以便在两次update_wall_time之间提供更好的精度
+                let cpu_delta_ns = timekeeper().do_read_cpu_cycle_ns() as u64;
+
+                // 尚未同步到xtime的时间
+                let tmp_delta_ns = __ADDED_USEC.load(Ordering::SeqCst) as u64 * 1000;
+
+                nsecs = cpu_delta_ns + tmp_delta_ns;
                 // TODO 不同架构可能需要加上不同的偏移量
                 break;
             }
         }
     }
-    _xtime.tv_nsec += nsecs as i64;
-    // let sec = __ADDED_SEC.load(Ordering::SeqCst);
-    // _xtime.tv_sec += sec;
-    while _xtime.tv_nsec >= NSEC_PER_SEC.into() {
-        _xtime.tv_nsec -= NSEC_PER_SEC as i64;
-        _xtime.tv_sec += 1;
-    }
+    xtime.tv_nsec += nsecs as i64;
+    xtime.tv_sec += xtime.tv_nsec / NSEC_PER_SEC as i64;
+    xtime.tv_nsec %= NSEC_PER_SEC as i64;
+    // kdebug!("getnstimeofday: xtime = {:?}, nsecs = {:}", xtime, nsecs);
 
     // TODO 将xtime和当前时间源的时间相加
 
-    return _xtime;
+    return xtime;
 }
 
 /// # 获取1970.1.1至今的UTC时间戳(最小单位:usec)
@@ -209,7 +239,7 @@ pub fn do_gettimeofday() -> PosixTimeval {
 }
 
 pub fn do_settimeofday64(time: TimeSpec) -> Result<(), SystemError> {
-    timekeeper().0.write_irqsave().xtime = time;
+    timekeeper().inner.write_irqsave().xtime = time;
     // todo: 模仿linux,实现时间误差校准。
     // https://code.dragonos.org.cn/xref/linux-6.6.21/kernel/time/timekeeping.c?fi=do_settimeofday64#1312
     return Ok(());
@@ -230,7 +260,7 @@ pub fn timekeeping_init() {
         .expect("clocksource_default_clock enable failed");
     timekeeper().timekeeper_setup_internals(clock);
     // 暂时不支持其他架构平台对时间的设置 所以使用x86平台对应值初始化
-    let mut timekeeper = timekeeper().0.write_irqsave();
+    let mut timekeeper = timekeeper().inner.write_irqsave();
     timekeeper.xtime.tv_nsec = ktime_get_real_ns();
 
     //参考https://elixir.bootlin.com/linux/v4.4/source/kernel/time/timekeeping.c#L1251 对wtm进行初始化
@@ -240,9 +270,9 @@ pub fn timekeeping_init() {
     ) = (-timekeeper.xtime.tv_nsec, -timekeeper.xtime.tv_sec);
 
     __ADDED_USEC.store(0, Ordering::SeqCst);
-    __ADDED_SEC.store(0, Ordering::SeqCst);
 
     drop(irq_guard);
+    drop(timekeeper);
     jiffies_init();
     kinfo!("timekeeping_init successfully");
 }
@@ -281,12 +311,7 @@ pub fn update_wall_time(delta_us: i64) {
     let mut retry = 10;
 
     let usec = __ADDED_USEC.load(Ordering::SeqCst);
-    if usec % USEC_PER_SEC as i64 == 0 {
-        compiler_fence(Ordering::SeqCst);
 
-        __ADDED_SEC.fetch_add(1, Ordering::SeqCst);
-        compiler_fence(Ordering::SeqCst);
-    }
     // 一分钟同步一次
     loop {
         if (usec & !((1 << 26) - 1)) != 0 {
@@ -298,10 +323,11 @@ pub fn update_wall_time(delta_us: i64) {
                 // 同步时间
                 // 我感觉这里会出问题:多个读者不退出的话,写者就无法写入
                 // 然后这里会超时,导致在中断返回之后,会不断的进入这个中断,最终爆栈。
-                let mut timekeeper = timekeeper().0.write_irqsave();
+                let mut timekeeper = timekeeper().inner.write_irqsave();
                 timekeeper.xtime.tv_nsec = ktime_get_real_ns();
                 timekeeper.xtime.tv_sec = 0;
-                __ADDED_SEC.store(0, Ordering::SeqCst);
+                __ADDED_USEC.store(0, Ordering::SeqCst);
+
                 drop(timekeeper);
                 break;
             }
@@ -310,6 +336,7 @@ pub fn update_wall_time(delta_us: i64) {
             break;
         }
     }
+    timekeeper().mark_update_wall_time_ok();
     // TODO 需要检查是否更新时间源
     compiler_fence(Ordering::SeqCst);
     drop(irq_guard);

+ 24 - 33
kernel/src/time/timer.rs

@@ -6,8 +6,8 @@ use core::{
 
 use alloc::{
     boxed::Box,
-    collections::LinkedList,
     sync::{Arc, Weak},
+    vec::Vec,
 };
 use system_error::SystemError;
 
@@ -22,14 +22,14 @@ use crate::{
     process::{ProcessControlBlock, ProcessManager},
 };
 
-use super::timekeeping::update_wall_time;
+use super::{jiffies::NSEC_PER_JIFFY, timekeeping::update_wall_time};
 
 const MAX_TIMEOUT: i64 = i64::MAX;
 const TIMER_RUN_CYCLE_THRESHOLD: usize = 20;
 static TIMER_JIFFIES: AtomicU64 = AtomicU64::new(0);
 
 lazy_static! {
-    pub static ref TIMER_LIST: SpinLock<LinkedList<Arc<Timer>>> = SpinLock::new(LinkedList::new());
+    pub static ref TIMER_LIST: SpinLock<Vec<(u64, Arc<Timer>)>> = SpinLock::new(Vec::new());
 }
 
 /// 定时器要执行的函数的特征
@@ -96,8 +96,10 @@ impl Timer {
         // 链表为空,则直接插入
         if timer_list.is_empty() {
             // FIXME push_timer
-
-            timer_list.push_back(inner_guard.self_ref.upgrade().unwrap());
+            timer_list.push((
+                inner_guard.expire_jiffies,
+                inner_guard.self_ref.upgrade().unwrap(),
+            ));
 
             drop(inner_guard);
             drop(timer_list);
@@ -105,17 +107,21 @@ impl Timer {
 
             return;
         }
+        let expire_jiffies = inner_guard.expire_jiffies;
+        let self_arc = inner_guard.self_ref.upgrade().unwrap();
+        drop(inner_guard);
         let mut split_pos: usize = 0;
         for (pos, elt) in timer_list.iter().enumerate() {
-            if elt.inner().expire_jiffies > inner_guard.expire_jiffies {
+            if Arc::ptr_eq(&self_arc, &elt.1) {
+                kwarn!("Timer already in list");
+            }
+            if elt.0 > expire_jiffies {
                 split_pos = pos;
                 break;
             }
         }
-        let mut temp_list: LinkedList<Arc<Timer>> = timer_list.split_off(split_pos);
-        timer_list.push_back(inner_guard.self_ref.upgrade().unwrap());
-        timer_list.append(&mut temp_list);
-        drop(inner_guard);
+        timer_list.insert(split_pos, (expire_jiffies, self_arc));
+
         drop(timer_list);
     }
 
@@ -144,7 +150,7 @@ impl Timer {
         let this_arc = self.inner().self_ref.upgrade().unwrap();
         TIMER_LIST
             .lock_irqsave()
-            .extract_if(|x| Arc::ptr_eq(&this_arc, x))
+            .extract_if(|x| Arc::ptr_eq(&this_arc, &x.1))
             .for_each(drop);
         true
     }
@@ -204,26 +210,13 @@ impl SoftirqVec for DoTimerSoftirq {
                 break;
             }
 
-            let timer_list_front = timer_list.pop_front().unwrap();
+            let (front_jiffies, timer_list_front) = timer_list.first().unwrap().clone();
             // kdebug!("to lock timer_list_front");
-            let mut timer_list_front_guard = None;
-            for _ in 0..10 {
-                let x = timer_list_front.inner.try_lock_irqsave();
-                if x.is_err() {
-                    continue;
-                }
-                timer_list_front_guard = Some(x.unwrap());
-            }
-            if timer_list_front_guard.is_none() {
-                continue;
-            }
-            let timer_list_front_guard = timer_list_front_guard.unwrap();
-            if timer_list_front_guard.expire_jiffies > TIMER_JIFFIES.load(Ordering::SeqCst) {
-                drop(timer_list_front_guard);
-                timer_list.push_front(timer_list_front);
+
+            if front_jiffies >= TIMER_JIFFIES.load(Ordering::SeqCst) {
                 break;
             }
-            drop(timer_list_front_guard);
+            timer_list.remove(0);
             drop(timer_list);
             timer_list_front.run();
         }
@@ -245,11 +238,11 @@ pub fn timer_init() {
 
 /// 计算接下来n毫秒对应的定时器时间片
 pub fn next_n_ms_timer_jiffies(expire_ms: u64) -> u64 {
-    return TIMER_JIFFIES.load(Ordering::SeqCst) + 1000 * (expire_ms);
+    return TIMER_JIFFIES.load(Ordering::SeqCst) + expire_ms * 1000000 / NSEC_PER_JIFFY as u64;
 }
 /// 计算接下来n微秒对应的定时器时间片
 pub fn next_n_us_timer_jiffies(expire_us: u64) -> u64 {
-    return TIMER_JIFFIES.load(Ordering::SeqCst) + (expire_us);
+    return TIMER_JIFFIES.load(Ordering::SeqCst) + expire_us * 1000 / NSEC_PER_JIFFY as u64;
 }
 
 /// @brief 让pcb休眠timeout个jiffies
@@ -307,7 +300,7 @@ pub fn timer_get_first_expire() -> Result<u64, SystemError> {
                     return Ok(0);
                 } else {
                     // kdebug!("timer_list not empty");
-                    return Ok(timer_list.front().unwrap().inner().expire_jiffies);
+                    return Ok(timer_list.first().unwrap().0);
                 }
             }
             // 加锁失败返回啥??
@@ -318,8 +311,6 @@ pub fn timer_get_first_expire() -> Result<u64, SystemError> {
 }
 
 /// 更新系统时间片
-///
-/// todo: 这里的实现有问题,貌似把HPET的500us当成了500个jiffies,然后update_wall_time()里面也硬编码了这个500us
 pub fn update_timer_jiffies(add_jiffies: u64, time_us: i64) -> u64 {
     let prev = TIMER_JIFFIES.fetch_add(add_jiffies, Ordering::SeqCst);
     compiler_fence(Ordering::SeqCst);

+ 14 - 1
user/apps/test-mount/src/main.rs

@@ -1,7 +1,14 @@
 use core::ffi::{c_char, c_void};
 use libc::{mount, MS_BIND};
+use std::fs;
+use std::path::Path;
 use std::time;
 fn main() {
+    let path = Path::new("mnt/tmp");
+    let dir = fs::create_dir_all(path);
+    if dir.is_err() {
+        panic!("mkdir /mnt/tmp fail.");
+    }
     let clock = time::Instant::now();
     let source = b"\0".as_ptr() as *const c_char;
     let target = b"/mnt/tmp\0".as_ptr() as *const c_char;
@@ -9,7 +16,13 @@ fn main() {
     let flags = MS_BIND;
     let data = std::ptr::null() as *const c_void;
     let result = unsafe { mount(source, target, fstype, flags, data) };
-
+    let path = Path::new("mnt/tmp/tmp");
+    let dir = fs::create_dir_all(path);
+    if dir.is_err() {
+        panic!("mkdir /mnt/tmp/tmp fail.");
+    }
+    let target = b"/mnt/tmp/tmp\0".as_ptr() as *const c_char;
+    let result = unsafe { mount(source, target, fstype, flags, data) };
     if result == 0 {
         println!("Mount successful");
     } else {

+ 10 - 10
user/apps/test_gettimeofday/main.c

@@ -8,16 +8,16 @@
 int main()
 {
     struct timeval *tv = malloc(sizeof(struct timeval));
-    // struct timezone *tz = malloc(sizeof(struct timezone));
-    // for (int i = 0; i < 15; i++)
-    // {
-    //     gettimeofday(tv, NULL);
-    //     printf("%ld.%06ld\n", tv->tv_sec, tv->tv_usec);
-    //     for (int i = 0; i < 10; i++)
-    //     {
-    //         usleep(500000);
-    //     }
-    // }
+    struct timezone *tz = malloc(sizeof(struct timezone));
+    for (int i = 0; i < 15; i++)
+    {
+        gettimeofday(tv, NULL);
+        printf("%ld.%06ld\n", tv->tv_sec, tv->tv_usec);
+        for (int i = 0; i < 10; i++)
+        {
+            usleep(500000);
+        }
+    }
     gettimeofday(tv, NULL);
     printf("tv = %ld.%06ld\n", tv->tv_sec, tv->tv_usec);
     // printf("tz_minuteswest = %d,tz_dsttime = %d", (*tz).tz_minuteswest, (*tz).tz_dsttime);

+ 1 - 1
user/dadk/config/test_mount_1_0_0.dadk

@@ -1,5 +1,5 @@
 {
-  "name": "test-mount",
+  "name": "test_mount",
   "version": "1.0.0",
   "description": "to test user mode mount",
   "task_type": {