xref: /DragonOS/kernel/src/time/timekeeping.rs (revision 8d94ea66a3eb3e02039730c8d08e9bead8c344b8)
136fd0130Shoumkh use alloc::sync::Arc;
236fd0130Shoumkh use core::sync::atomic::{compiler_fence, AtomicBool, AtomicI64, Ordering};
336fd0130Shoumkh use x86_64::align_up;
436fd0130Shoumkh 
536fd0130Shoumkh use crate::{
636fd0130Shoumkh     arch::CurrentIrqArch,
736fd0130Shoumkh     exception::InterruptArch,
840fe15e0SLoGin     kdebug, kinfo,
936fd0130Shoumkh     libs::rwlock::RwLock,
1036fd0130Shoumkh     time::{jiffies::clocksource_default_clock, timekeep::ktime_get_real_ns, TimeSpec},
1136fd0130Shoumkh };
1236fd0130Shoumkh 
1336fd0130Shoumkh use super::{
1436fd0130Shoumkh     clocksource::{clocksource_cyc2ns, Clocksource, CycleNum, HZ},
1536fd0130Shoumkh     syscall::PosixTimeval,
1636fd0130Shoumkh     NSEC_PER_SEC, USEC_PER_SEC,
1736fd0130Shoumkh };
1836fd0130Shoumkh /// NTP周期频率
1936fd0130Shoumkh pub const NTP_INTERVAL_FREQ: u64 = HZ;
2036fd0130Shoumkh /// NTP周期长度
2136fd0130Shoumkh pub const NTP_INTERVAL_LENGTH: u64 = NSEC_PER_SEC as u64 / NTP_INTERVAL_FREQ;
2236fd0130Shoumkh /// NTP转换比例
2336fd0130Shoumkh pub const NTP_SCALE_SHIFT: u32 = 32;
2436fd0130Shoumkh 
2536fd0130Shoumkh /// timekeeping休眠标志,false为未休眠
2636fd0130Shoumkh pub static TIMEKEEPING_SUSPENDED: AtomicBool = AtomicBool::new(false);
2736fd0130Shoumkh /// 已经递增的微秒数
2836fd0130Shoumkh static __ADDED_USEC: AtomicI64 = AtomicI64::new(0);
2936fd0130Shoumkh /// 已经递增的秒数
3036fd0130Shoumkh static __ADDED_SEC: AtomicI64 = AtomicI64::new(0);
3136fd0130Shoumkh /// timekeeper全局变量,用于管理timekeeper模块
3236fd0130Shoumkh static mut __TIMEKEEPER: Option<Timekeeper> = None;
3336fd0130Shoumkh 
3436fd0130Shoumkh #[derive(Debug)]
3536fd0130Shoumkh pub struct Timekeeper(RwLock<TimekeeperData>);
3636fd0130Shoumkh 
3736fd0130Shoumkh #[allow(dead_code)]
3836fd0130Shoumkh #[derive(Debug)]
3936fd0130Shoumkh pub struct TimekeeperData {
4036fd0130Shoumkh     /// 用于计时的当前时钟源。
4136fd0130Shoumkh     clock: Option<Arc<dyn Clocksource>>,
4236fd0130Shoumkh     /// 当前时钟源的移位值。
4336fd0130Shoumkh     shift: i32,
4436fd0130Shoumkh     /// 一个NTP间隔中的时钟周期数。
4536fd0130Shoumkh     cycle_interval: CycleNum,
4636fd0130Shoumkh     /// 一个NTP间隔中时钟移位的纳秒数。
4736fd0130Shoumkh     xtime_interval: u64,
4836fd0130Shoumkh     ///
4936fd0130Shoumkh     xtime_remainder: i64,
5036fd0130Shoumkh     /// 每个NTP间隔累积的原始纳米秒
5136fd0130Shoumkh     raw_interval: i64,
5236fd0130Shoumkh     /// 时钟移位纳米秒余数
5336fd0130Shoumkh     xtime_nsec: u64,
5436fd0130Shoumkh     /// 积累时间和ntp时间在ntp位移纳秒量上的差距
5536fd0130Shoumkh     ntp_error: i64,
5636fd0130Shoumkh     /// 用于转换时钟偏移纳秒和ntp偏移纳秒的偏移量
5736fd0130Shoumkh     ntp_error_shift: i32,
5836fd0130Shoumkh     /// NTP调整时钟乘法器
5936fd0130Shoumkh     mult: u32,
6036fd0130Shoumkh     raw_time: TimeSpec,
6136fd0130Shoumkh     wall_to_monotonic: TimeSpec,
6236fd0130Shoumkh     total_sleep_time: TimeSpec,
6336fd0130Shoumkh     xtime: TimeSpec,
6436fd0130Shoumkh }
6536fd0130Shoumkh impl TimekeeperData {
6636fd0130Shoumkh     pub fn new() -> Self {
6736fd0130Shoumkh         Self {
6836fd0130Shoumkh             clock: None,
6936fd0130Shoumkh             shift: Default::default(),
7036fd0130Shoumkh             cycle_interval: CycleNum(0),
7136fd0130Shoumkh             xtime_interval: Default::default(),
7236fd0130Shoumkh             xtime_remainder: Default::default(),
7336fd0130Shoumkh             raw_interval: Default::default(),
7436fd0130Shoumkh             xtime_nsec: Default::default(),
7536fd0130Shoumkh             ntp_error: Default::default(),
7636fd0130Shoumkh             ntp_error_shift: Default::default(),
7736fd0130Shoumkh             mult: Default::default(),
7836fd0130Shoumkh             xtime: TimeSpec {
7936fd0130Shoumkh                 tv_nsec: 0,
8036fd0130Shoumkh                 tv_sec: 0,
8136fd0130Shoumkh             },
8236fd0130Shoumkh             wall_to_monotonic: TimeSpec {
8336fd0130Shoumkh                 tv_nsec: 0,
8436fd0130Shoumkh                 tv_sec: 0,
8536fd0130Shoumkh             },
8636fd0130Shoumkh             total_sleep_time: TimeSpec {
8736fd0130Shoumkh                 tv_nsec: 0,
8836fd0130Shoumkh                 tv_sec: 0,
8936fd0130Shoumkh             },
9036fd0130Shoumkh             raw_time: TimeSpec {
9136fd0130Shoumkh                 tv_nsec: 0,
9236fd0130Shoumkh                 tv_sec: 0,
9336fd0130Shoumkh             },
9436fd0130Shoumkh         }
9536fd0130Shoumkh     }
9636fd0130Shoumkh }
9736fd0130Shoumkh impl Timekeeper {
9836fd0130Shoumkh     /// # 设置timekeeper的参数
9936fd0130Shoumkh     ///
10036fd0130Shoumkh     /// ## 参数
10136fd0130Shoumkh     ///
10236fd0130Shoumkh     /// * 'clock' - 指定的时钟实际类型。初始为ClocksourceJiffies
10336fd0130Shoumkh     pub fn timekeeper_setup_internals(&self, clock: Arc<dyn Clocksource>) {
10436fd0130Shoumkh         let mut timekeeper = self.0.write();
10536fd0130Shoumkh         // 更新clock
10636fd0130Shoumkh         let mut clock_data = clock.clocksource_data();
10736fd0130Shoumkh         clock_data.watchdog_last = clock.read();
10836fd0130Shoumkh         if clock.update_clocksource_data(clock_data).is_err() {
10936fd0130Shoumkh             kdebug!("timekeeper_setup_internals:update_clocksource_data run failed");
11036fd0130Shoumkh         }
11136fd0130Shoumkh         timekeeper.clock.replace(clock.clone());
11236fd0130Shoumkh 
11336fd0130Shoumkh         let clock_data = clock.clocksource_data();
11436fd0130Shoumkh         let mut temp = NTP_INTERVAL_LENGTH << clock_data.shift;
11536fd0130Shoumkh         let ntpinterval = temp;
11636fd0130Shoumkh         temp += (clock_data.mult / 2) as u64;
11736fd0130Shoumkh         // do div
11836fd0130Shoumkh 
11936fd0130Shoumkh         timekeeper.cycle_interval = CycleNum(temp);
12036fd0130Shoumkh         timekeeper.xtime_interval = temp * clock_data.mult as u64;
12140fe15e0SLoGin         // 这里可能存在下界溢出问题,debug模式下会报错panic
12236fd0130Shoumkh         timekeeper.xtime_remainder = (ntpinterval - timekeeper.xtime_interval) as i64;
12336fd0130Shoumkh         timekeeper.raw_interval = (timekeeper.xtime_interval >> clock_data.shift) as i64;
12436fd0130Shoumkh         timekeeper.xtime_nsec = 0;
12536fd0130Shoumkh         timekeeper.shift = clock_data.shift as i32;
12636fd0130Shoumkh 
12736fd0130Shoumkh         timekeeper.ntp_error = 0;
12836fd0130Shoumkh         timekeeper.ntp_error_shift = (NTP_SCALE_SHIFT - clock_data.shift) as i32;
12936fd0130Shoumkh 
13036fd0130Shoumkh         timekeeper.mult = clock_data.mult;
13136fd0130Shoumkh     }
13236fd0130Shoumkh 
13336fd0130Shoumkh     /// # 获取当前时钟源距离上次检测走过的纳秒数
13436fd0130Shoumkh     #[allow(dead_code)]
13536fd0130Shoumkh     pub fn tk_get_ns(&self) -> u64 {
13636fd0130Shoumkh         let timekeeper = self.0.read();
13736fd0130Shoumkh         let clock = timekeeper.clock.clone().unwrap();
13836fd0130Shoumkh         let clock_now = clock.read();
13936fd0130Shoumkh         let clcok_data = clock.clocksource_data();
14036fd0130Shoumkh         let clock_delta = clock_now.div(clcok_data.watchdog_last).data() & clcok_data.mask.bits();
14136fd0130Shoumkh         return clocksource_cyc2ns(CycleNum(clock_delta), clcok_data.mult, clcok_data.shift);
14236fd0130Shoumkh     }
14336fd0130Shoumkh }
14436fd0130Shoumkh pub fn timekeeper() -> &'static Timekeeper {
145*8d94ea66SYJwu2023     let r = unsafe { __TIMEKEEPER.as_ref().unwrap() };
146*8d94ea66SYJwu2023 
147*8d94ea66SYJwu2023     return r;
14836fd0130Shoumkh }
14936fd0130Shoumkh 
15036fd0130Shoumkh pub fn timekeeper_init() {
15136fd0130Shoumkh     unsafe { __TIMEKEEPER = Some(Timekeeper(RwLock::new(TimekeeperData::new()))) };
15236fd0130Shoumkh }
15336fd0130Shoumkh 
15436fd0130Shoumkh /// # 获取1970.1.1至今的UTC时间戳(最小单位:nsec)
15536fd0130Shoumkh ///
15636fd0130Shoumkh /// ## 返回值
15736fd0130Shoumkh ///
15836fd0130Shoumkh /// * 'TimeSpec' - 时间戳
15936fd0130Shoumkh pub fn getnstimeofday() -> TimeSpec {
16040fe15e0SLoGin     // kdebug!("enter getnstimeofday");
16136fd0130Shoumkh 
16236fd0130Shoumkh     // let mut nsecs: u64 = 0;0
16336fd0130Shoumkh     let mut _xtime = TimeSpec {
16436fd0130Shoumkh         tv_nsec: 0,
16536fd0130Shoumkh         tv_sec: 0,
16636fd0130Shoumkh     };
16736fd0130Shoumkh     loop {
16836fd0130Shoumkh         match timekeeper().0.try_read() {
16936fd0130Shoumkh             None => continue,
17036fd0130Shoumkh             Some(tk) => {
17136fd0130Shoumkh                 _xtime = tk.xtime;
17236fd0130Shoumkh                 drop(tk);
17336fd0130Shoumkh                 // nsecs = timekeeper().tk_get_ns();
17436fd0130Shoumkh                 // TODO 不同架构可能需要加上不同的偏移量
17536fd0130Shoumkh                 break;
17636fd0130Shoumkh             }
17736fd0130Shoumkh         }
17836fd0130Shoumkh     }
17936fd0130Shoumkh     // xtime.tv_nsec += nsecs as i64;
18036fd0130Shoumkh     let sec = __ADDED_SEC.load(Ordering::SeqCst);
18136fd0130Shoumkh     _xtime.tv_sec += sec;
18236fd0130Shoumkh     while _xtime.tv_nsec >= NSEC_PER_SEC.into() {
18336fd0130Shoumkh         _xtime.tv_nsec -= NSEC_PER_SEC as i64;
18436fd0130Shoumkh         _xtime.tv_sec += 1;
18536fd0130Shoumkh     }
18636fd0130Shoumkh 
18736fd0130Shoumkh     // TODO 将xtime和当前时间源的时间相加
18836fd0130Shoumkh 
18936fd0130Shoumkh     return _xtime;
19036fd0130Shoumkh }
19136fd0130Shoumkh 
19236fd0130Shoumkh /// # 获取1970.1.1至今的UTC时间戳(最小单位:usec)
19336fd0130Shoumkh ///
19436fd0130Shoumkh /// ## 返回值
19536fd0130Shoumkh ///
19636fd0130Shoumkh /// * 'PosixTimeval' - 时间戳
19736fd0130Shoumkh pub fn do_gettimeofday() -> PosixTimeval {
19836fd0130Shoumkh     let tp = getnstimeofday();
19936fd0130Shoumkh     return PosixTimeval {
20036fd0130Shoumkh         tv_sec: tp.tv_sec,
20136fd0130Shoumkh         tv_usec: (tp.tv_nsec / 1000) as i32,
20236fd0130Shoumkh     };
20336fd0130Shoumkh }
20436fd0130Shoumkh 
20536fd0130Shoumkh /// # 初始化timekeeping模块
20636fd0130Shoumkh pub fn timekeeping_init() {
20740fe15e0SLoGin     kinfo!("Initializing timekeeping module...");
20836fd0130Shoumkh     let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
20936fd0130Shoumkh     timekeeper_init();
21036fd0130Shoumkh 
21136fd0130Shoumkh     // TODO 有ntp模块后 在此初始化ntp模块
21236fd0130Shoumkh 
21336fd0130Shoumkh     let clock = clocksource_default_clock();
21436fd0130Shoumkh     clock
21536fd0130Shoumkh         .enable()
21636fd0130Shoumkh         .expect("clocksource_default_clock enable failed");
21736fd0130Shoumkh     timekeeper().timekeeper_setup_internals(clock);
21836fd0130Shoumkh     // 暂时不支持其他架构平台对时间的设置 所以使用x86平台对应值初始化
21936fd0130Shoumkh     let mut timekeeper = timekeeper().0.write();
22036fd0130Shoumkh     timekeeper.xtime.tv_nsec = ktime_get_real_ns();
22136fd0130Shoumkh 
22236fd0130Shoumkh     // 初始化wall time到monotonic的时间
22336fd0130Shoumkh     let mut nsec = -timekeeper.xtime.tv_nsec;
22436fd0130Shoumkh     let mut sec = -timekeeper.xtime.tv_sec;
22536fd0130Shoumkh     // FIXME: 这里有个奇怪的奇怪的bug
22636fd0130Shoumkh     let num = nsec % NSEC_PER_SEC as i64;
22736fd0130Shoumkh     nsec += num * NSEC_PER_SEC as i64;
22836fd0130Shoumkh     sec -= num;
22936fd0130Shoumkh     timekeeper.wall_to_monotonic.tv_nsec = nsec;
23036fd0130Shoumkh     timekeeper.wall_to_monotonic.tv_sec = sec;
23136fd0130Shoumkh 
23236fd0130Shoumkh     __ADDED_USEC.store(0, Ordering::SeqCst);
23336fd0130Shoumkh     __ADDED_SEC.store(0, Ordering::SeqCst);
23436fd0130Shoumkh 
23536fd0130Shoumkh     drop(irq_guard);
23640fe15e0SLoGin     kinfo!("timekeeping_init successfully");
23736fd0130Shoumkh }
23836fd0130Shoumkh 
23936fd0130Shoumkh /// # 使用当前时钟源增加wall time
24036fd0130Shoumkh pub fn update_wall_time() {
24136fd0130Shoumkh     let rsp = unsafe { crate::include::bindings::bindings::get_rsp() } as usize;
24236fd0130Shoumkh     let _stack_use = align_up(rsp as u64, 32768) - rsp as u64;
24336fd0130Shoumkh 
24436fd0130Shoumkh     // kdebug!("enter update_wall_time, stack_use = {:}",stack_use);
24536fd0130Shoumkh     compiler_fence(Ordering::SeqCst);
24636fd0130Shoumkh     let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
24736fd0130Shoumkh     // 如果在休眠那就不更新
24836fd0130Shoumkh     if TIMEKEEPING_SUSPENDED.load(Ordering::SeqCst) {
24936fd0130Shoumkh         return;
25036fd0130Shoumkh     }
25136fd0130Shoumkh 
25236fd0130Shoumkh     // ===== 请不要删除这些注释 =====
25336fd0130Shoumkh     // let clock = timekeeper.clock.clone().unwrap();
25436fd0130Shoumkh     // let clock_data = clock.clocksource_data();
25536fd0130Shoumkh     // let offset = (clock.read().div(clock_data.watchdog_last).data()) & clock_data.mask.bits();
25636fd0130Shoumkh 
25736fd0130Shoumkh     // timekeeper.xtime_nsec = (timekeeper.xtime.tv_nsec as u64) << timekeeper.shift;
25836fd0130Shoumkh     // // TODO 当有ntp模块之后 需要将timekeep与ntp进行同步并检查
25936fd0130Shoumkh     // timekeeper.xtime.tv_nsec = ((timekeeper.xtime_nsec as i64) >> timekeeper.shift) + 1;
26036fd0130Shoumkh     // timekeeper.xtime_nsec -= (timekeeper.xtime.tv_nsec as u64) << timekeeper.shift;
26136fd0130Shoumkh 
26236fd0130Shoumkh     // timekeeper.xtime.tv_nsec += offset as i64;
26336fd0130Shoumkh     // while unlikely(timekeeper.xtime.tv_nsec >= NSEC_PER_SEC.into()) {
26436fd0130Shoumkh     //     timekeeper.xtime.tv_nsec -= NSEC_PER_SEC as i64;
26536fd0130Shoumkh     //     timekeeper.xtime.tv_sec += 1;
26636fd0130Shoumkh     //     // TODO 需要处理闰秒
26736fd0130Shoumkh     // }
26836fd0130Shoumkh     // ================
26936fd0130Shoumkh     compiler_fence(Ordering::SeqCst);
27036fd0130Shoumkh     // 一分钟同步一次
27136fd0130Shoumkh     __ADDED_USEC.fetch_add(500, Ordering::SeqCst);
27236fd0130Shoumkh     compiler_fence(Ordering::SeqCst);
27336fd0130Shoumkh     let mut retry = 10;
27436fd0130Shoumkh 
27536fd0130Shoumkh     let usec = __ADDED_USEC.load(Ordering::SeqCst);
27636fd0130Shoumkh     if usec % USEC_PER_SEC as i64 == 0 {
27736fd0130Shoumkh         compiler_fence(Ordering::SeqCst);
27836fd0130Shoumkh 
27936fd0130Shoumkh         __ADDED_SEC.fetch_add(1, Ordering::SeqCst);
28036fd0130Shoumkh         compiler_fence(Ordering::SeqCst);
28136fd0130Shoumkh     }
28236fd0130Shoumkh     loop {
28336fd0130Shoumkh         if (usec & !((1 << 26) - 1)) != 0 {
28436fd0130Shoumkh             if __ADDED_USEC
28536fd0130Shoumkh                 .compare_exchange(usec, 0, Ordering::SeqCst, Ordering::SeqCst)
28636fd0130Shoumkh                 .is_ok()
28736fd0130Shoumkh                 || retry == 0
28836fd0130Shoumkh             {
28936fd0130Shoumkh                 // 同步时间
29036fd0130Shoumkh                 // 我感觉这里会出问题:多个读者不退出的话,写者就无法写入
29136fd0130Shoumkh                 // 然后这里会超时,导致在中断返回之后,会不断的进入这个中断,最终爆栈。
29236fd0130Shoumkh                 let mut timekeeper = timekeeper().0.write();
29336fd0130Shoumkh                 timekeeper.xtime.tv_nsec = ktime_get_real_ns();
29436fd0130Shoumkh                 timekeeper.xtime.tv_sec = 0;
29536fd0130Shoumkh                 __ADDED_SEC.store(0, Ordering::SeqCst);
29636fd0130Shoumkh                 drop(timekeeper);
29736fd0130Shoumkh                 break;
29836fd0130Shoumkh             }
29936fd0130Shoumkh             retry -= 1;
30036fd0130Shoumkh         } else {
30136fd0130Shoumkh             break;
30236fd0130Shoumkh         }
30336fd0130Shoumkh     }
30436fd0130Shoumkh     // TODO 需要检查是否更新时间源
30536fd0130Shoumkh     compiler_fence(Ordering::SeqCst);
30636fd0130Shoumkh     drop(irq_guard);
30736fd0130Shoumkh     compiler_fence(Ordering::SeqCst);
30836fd0130Shoumkh }
30936fd0130Shoumkh // TODO timekeeping_adjust
31036fd0130Shoumkh // TODO wall_to_monotic
31136fd0130Shoumkh 
31236fd0130Shoumkh // ========= 以下为对C的接口 =========
31336fd0130Shoumkh #[no_mangle]
31436fd0130Shoumkh pub extern "C" fn rs_timekeeping_init() {
31536fd0130Shoumkh     timekeeping_init();
31636fd0130Shoumkh }
317