136fd0130Shoumkh use alloc::sync::Arc; 2b8ed3825SDonkey Kane use core::sync::atomic::{compiler_fence, AtomicBool, AtomicI64, AtomicUsize, Ordering}; 3da152319SLoGin use system_error::SystemError; 436fd0130Shoumkh 536fd0130Shoumkh use crate::{ 6b8ed3825SDonkey Kane arch::{CurrentIrqArch, CurrentTimeArch}, 736fd0130Shoumkh exception::InterruptArch, 840fe15e0SLoGin kdebug, kinfo, 9b8ed3825SDonkey Kane libs::rwlock::{RwLock, RwLockReadGuard}, 105b59005fSLoGin time::{ 115b59005fSLoGin jiffies::{clocksource_default_clock, jiffies_init}, 125b59005fSLoGin timekeep::ktime_get_real_ns, 13*6fc066acSJomo PosixTimeSpec, 145b59005fSLoGin }, 1536fd0130Shoumkh }; 1636fd0130Shoumkh 1736fd0130Shoumkh use super::{ 1836fd0130Shoumkh clocksource::{clocksource_cyc2ns, Clocksource, CycleNum, HZ}, 1936fd0130Shoumkh syscall::PosixTimeval, 20b8ed3825SDonkey Kane TimeArch, NSEC_PER_SEC, 2136fd0130Shoumkh }; 2236fd0130Shoumkh /// NTP周期频率 2336fd0130Shoumkh pub const NTP_INTERVAL_FREQ: u64 = HZ; 2436fd0130Shoumkh /// NTP周期长度 2536fd0130Shoumkh pub const NTP_INTERVAL_LENGTH: u64 = NSEC_PER_SEC as u64 / NTP_INTERVAL_FREQ; 2636fd0130Shoumkh /// NTP转换比例 2736fd0130Shoumkh pub const NTP_SCALE_SHIFT: u32 = 32; 2836fd0130Shoumkh 2936fd0130Shoumkh /// timekeeping休眠标志,false为未休眠 3036fd0130Shoumkh pub static TIMEKEEPING_SUSPENDED: AtomicBool = AtomicBool::new(false); 3136fd0130Shoumkh /// 已经递增的微秒数 3236fd0130Shoumkh static __ADDED_USEC: AtomicI64 = AtomicI64::new(0); 3336fd0130Shoumkh /// timekeeper全局变量,用于管理timekeeper模块 3436fd0130Shoumkh static mut __TIMEKEEPER: Option<Timekeeper> = None; 3536fd0130Shoumkh 3636fd0130Shoumkh #[derive(Debug)] 37b8ed3825SDonkey Kane pub struct Timekeeper { 38b8ed3825SDonkey Kane inner: RwLock<TimekeeperData>, 39b8ed3825SDonkey Kane 40b8ed3825SDonkey Kane /// 上一次更新墙上时间时的CPU周期数 41b8ed3825SDonkey Kane last_update_cpu_cycle: AtomicUsize, 42b8ed3825SDonkey Kane } 4336fd0130Shoumkh 4436fd0130Shoumkh #[allow(dead_code)] 4536fd0130Shoumkh #[derive(Debug)] 4636fd0130Shoumkh pub struct TimekeeperData { 4736fd0130Shoumkh /// 用于计时的当前时钟源。 4836fd0130Shoumkh clock: Option<Arc<dyn Clocksource>>, 4936fd0130Shoumkh /// 当前时钟源的移位值。 5036fd0130Shoumkh shift: i32, 5136fd0130Shoumkh /// 一个NTP间隔中的时钟周期数。 5236fd0130Shoumkh cycle_interval: CycleNum, 5336fd0130Shoumkh /// 一个NTP间隔中时钟移位的纳秒数。 5436fd0130Shoumkh xtime_interval: u64, 5536fd0130Shoumkh /// 5636fd0130Shoumkh xtime_remainder: i64, 5736fd0130Shoumkh /// 每个NTP间隔累积的原始纳米秒 5836fd0130Shoumkh raw_interval: i64, 5936fd0130Shoumkh /// 时钟移位纳米秒余数 6036fd0130Shoumkh xtime_nsec: u64, 6136fd0130Shoumkh /// 积累时间和ntp时间在ntp位移纳秒量上的差距 6236fd0130Shoumkh ntp_error: i64, 6336fd0130Shoumkh /// 用于转换时钟偏移纳秒和ntp偏移纳秒的偏移量 6436fd0130Shoumkh ntp_error_shift: i32, 6536fd0130Shoumkh /// NTP调整时钟乘法器 6636fd0130Shoumkh mult: u32, 67*6fc066acSJomo raw_time: PosixTimeSpec, 68*6fc066acSJomo wall_to_monotonic: PosixTimeSpec, 69*6fc066acSJomo total_sleep_time: PosixTimeSpec, 70*6fc066acSJomo xtime: PosixTimeSpec, 7136fd0130Shoumkh } 7236fd0130Shoumkh impl TimekeeperData { 7336fd0130Shoumkh pub fn new() -> Self { 7436fd0130Shoumkh Self { 7536fd0130Shoumkh clock: None, 7636fd0130Shoumkh shift: Default::default(), 77b8ed3825SDonkey Kane cycle_interval: CycleNum::new(0), 7836fd0130Shoumkh xtime_interval: Default::default(), 7936fd0130Shoumkh xtime_remainder: Default::default(), 8036fd0130Shoumkh raw_interval: Default::default(), 8136fd0130Shoumkh xtime_nsec: Default::default(), 8236fd0130Shoumkh ntp_error: Default::default(), 8336fd0130Shoumkh ntp_error_shift: Default::default(), 8436fd0130Shoumkh mult: Default::default(), 85*6fc066acSJomo xtime: PosixTimeSpec { 8636fd0130Shoumkh tv_nsec: 0, 8736fd0130Shoumkh tv_sec: 0, 8836fd0130Shoumkh }, 89*6fc066acSJomo wall_to_monotonic: PosixTimeSpec { 9036fd0130Shoumkh tv_nsec: 0, 9136fd0130Shoumkh tv_sec: 0, 9236fd0130Shoumkh }, 93*6fc066acSJomo total_sleep_time: PosixTimeSpec { 9436fd0130Shoumkh tv_nsec: 0, 9536fd0130Shoumkh tv_sec: 0, 9636fd0130Shoumkh }, 97*6fc066acSJomo raw_time: PosixTimeSpec { 9836fd0130Shoumkh tv_nsec: 0, 9936fd0130Shoumkh tv_sec: 0, 10036fd0130Shoumkh }, 10136fd0130Shoumkh } 10236fd0130Shoumkh } 10336fd0130Shoumkh } 10436fd0130Shoumkh impl Timekeeper { 105b8ed3825SDonkey Kane fn new() -> Self { 106b8ed3825SDonkey Kane Self { 107b8ed3825SDonkey Kane inner: RwLock::new(TimekeeperData::new()), 108b8ed3825SDonkey Kane last_update_cpu_cycle: AtomicUsize::new(0), 109b8ed3825SDonkey Kane } 110b8ed3825SDonkey Kane } 111b8ed3825SDonkey Kane 11236fd0130Shoumkh /// # 设置timekeeper的参数 11336fd0130Shoumkh /// 11436fd0130Shoumkh /// ## 参数 11536fd0130Shoumkh /// 11636fd0130Shoumkh /// * 'clock' - 指定的时钟实际类型。初始为ClocksourceJiffies 11736fd0130Shoumkh pub fn timekeeper_setup_internals(&self, clock: Arc<dyn Clocksource>) { 118b8ed3825SDonkey Kane let mut timekeeper = self.inner.write_irqsave(); 11936fd0130Shoumkh // 更新clock 12036fd0130Shoumkh let mut clock_data = clock.clocksource_data(); 12136fd0130Shoumkh clock_data.watchdog_last = clock.read(); 12236fd0130Shoumkh if clock.update_clocksource_data(clock_data).is_err() { 12336fd0130Shoumkh kdebug!("timekeeper_setup_internals:update_clocksource_data run failed"); 12436fd0130Shoumkh } 12536fd0130Shoumkh timekeeper.clock.replace(clock.clone()); 12636fd0130Shoumkh 12736fd0130Shoumkh let clock_data = clock.clocksource_data(); 12836fd0130Shoumkh let mut temp = NTP_INTERVAL_LENGTH << clock_data.shift; 12936fd0130Shoumkh let ntpinterval = temp; 13036fd0130Shoumkh temp += (clock_data.mult / 2) as u64; 13136fd0130Shoumkh // do div 13236fd0130Shoumkh 133b8ed3825SDonkey Kane timekeeper.cycle_interval = CycleNum::new(temp); 13436fd0130Shoumkh timekeeper.xtime_interval = temp * clock_data.mult as u64; 13540fe15e0SLoGin // 这里可能存在下界溢出问题,debug模式下会报错panic 13636fd0130Shoumkh timekeeper.xtime_remainder = (ntpinterval - timekeeper.xtime_interval) as i64; 13736fd0130Shoumkh timekeeper.raw_interval = (timekeeper.xtime_interval >> clock_data.shift) as i64; 13836fd0130Shoumkh timekeeper.xtime_nsec = 0; 13936fd0130Shoumkh timekeeper.shift = clock_data.shift as i32; 14036fd0130Shoumkh 14136fd0130Shoumkh timekeeper.ntp_error = 0; 14236fd0130Shoumkh timekeeper.ntp_error_shift = (NTP_SCALE_SHIFT - clock_data.shift) as i32; 14336fd0130Shoumkh 14436fd0130Shoumkh timekeeper.mult = clock_data.mult; 14536fd0130Shoumkh } 14636fd0130Shoumkh 147b8ed3825SDonkey Kane /// # 获取当前时钟源距离上次watchdog检测走过的纳秒数 14836fd0130Shoumkh #[allow(dead_code)] 14936fd0130Shoumkh pub fn tk_get_ns(&self) -> u64 { 150b8ed3825SDonkey Kane let timekeeper: RwLockReadGuard<'_, TimekeeperData> = self.inner.read_irqsave(); 15136fd0130Shoumkh let clock = timekeeper.clock.clone().unwrap(); 1520d6cf65aSLoGin drop(timekeeper); 153b8ed3825SDonkey Kane 15436fd0130Shoumkh let clock_now = clock.read(); 155911132c4SDonkey Kane let clock_data = clock.clocksource_data(); 156911132c4SDonkey Kane let clock_delta = clock_now.div(clock_data.watchdog_last).data() & clock_data.mask.bits(); 157b8ed3825SDonkey Kane 158b8ed3825SDonkey Kane return clocksource_cyc2ns( 159b8ed3825SDonkey Kane CycleNum::new(clock_delta), 160b8ed3825SDonkey Kane clock_data.mult, 161b8ed3825SDonkey Kane clock_data.shift, 162b8ed3825SDonkey Kane ); 163b8ed3825SDonkey Kane } 164b8ed3825SDonkey Kane 165b8ed3825SDonkey Kane #[inline] 166b8ed3825SDonkey Kane fn do_read_cpu_cycle_ns(&self) -> usize { 167b8ed3825SDonkey Kane CurrentTimeArch::cycles2ns( 168b8ed3825SDonkey Kane CurrentTimeArch::get_cycles() 169b8ed3825SDonkey Kane .wrapping_sub(self.last_update_cpu_cycle.load(Ordering::SeqCst)), 170b8ed3825SDonkey Kane ) 171b8ed3825SDonkey Kane } 172b8ed3825SDonkey Kane 173b8ed3825SDonkey Kane fn mark_update_wall_time_ok(&self) { 174b8ed3825SDonkey Kane self.last_update_cpu_cycle 175b8ed3825SDonkey Kane .store(CurrentTimeArch::get_cycles(), Ordering::SeqCst); 17636fd0130Shoumkh } 17736fd0130Shoumkh } 178b8ed3825SDonkey Kane 179b8ed3825SDonkey Kane #[inline(always)] 18036fd0130Shoumkh pub fn timekeeper() -> &'static Timekeeper { 1818d94ea66SYJwu2023 let r = unsafe { __TIMEKEEPER.as_ref().unwrap() }; 1828d94ea66SYJwu2023 1838d94ea66SYJwu2023 return r; 18436fd0130Shoumkh } 18536fd0130Shoumkh 18636fd0130Shoumkh pub fn timekeeper_init() { 187b8ed3825SDonkey Kane unsafe { __TIMEKEEPER = Some(Timekeeper::new()) }; 18836fd0130Shoumkh } 18936fd0130Shoumkh 19036fd0130Shoumkh /// # 获取1970.1.1至今的UTC时间戳(最小单位:nsec) 19136fd0130Shoumkh /// 19236fd0130Shoumkh /// ## 返回值 19336fd0130Shoumkh /// 19436fd0130Shoumkh /// * 'TimeSpec' - 时间戳 195*6fc066acSJomo pub fn getnstimeofday() -> PosixTimeSpec { 19640fe15e0SLoGin // kdebug!("enter getnstimeofday"); 19736fd0130Shoumkh 198911132c4SDonkey Kane let nsecs; 199*6fc066acSJomo let mut xtime: PosixTimeSpec; 20036fd0130Shoumkh loop { 201b8ed3825SDonkey Kane match timekeeper().inner.try_read_irqsave() { 20236fd0130Shoumkh None => continue, 20336fd0130Shoumkh Some(tk) => { 204b8ed3825SDonkey Kane xtime = tk.xtime; 20536fd0130Shoumkh drop(tk); 206b8ed3825SDonkey Kane // 提供基于cpu周期数的ns时间,以便在两次update_wall_time之间提供更好的精度 207b8ed3825SDonkey Kane let cpu_delta_ns = timekeeper().do_read_cpu_cycle_ns() as u64; 208b8ed3825SDonkey Kane 209b8ed3825SDonkey Kane // 尚未同步到xtime的时间 210b8ed3825SDonkey Kane let tmp_delta_ns = __ADDED_USEC.load(Ordering::SeqCst) as u64 * 1000; 211b8ed3825SDonkey Kane 212b8ed3825SDonkey Kane nsecs = cpu_delta_ns + tmp_delta_ns; 21336fd0130Shoumkh // TODO 不同架构可能需要加上不同的偏移量 21436fd0130Shoumkh break; 21536fd0130Shoumkh } 21636fd0130Shoumkh } 21736fd0130Shoumkh } 218b8ed3825SDonkey Kane xtime.tv_nsec += nsecs as i64; 219b8ed3825SDonkey Kane xtime.tv_sec += xtime.tv_nsec / NSEC_PER_SEC as i64; 220b8ed3825SDonkey Kane xtime.tv_nsec %= NSEC_PER_SEC as i64; 221b8ed3825SDonkey Kane // kdebug!("getnstimeofday: xtime = {:?}, nsecs = {:}", xtime, nsecs); 22236fd0130Shoumkh 22336fd0130Shoumkh // TODO 将xtime和当前时间源的时间相加 22436fd0130Shoumkh 225b8ed3825SDonkey Kane return xtime; 22636fd0130Shoumkh } 22736fd0130Shoumkh 22836fd0130Shoumkh /// # 获取1970.1.1至今的UTC时间戳(最小单位:usec) 22936fd0130Shoumkh /// 23036fd0130Shoumkh /// ## 返回值 23136fd0130Shoumkh /// 23236fd0130Shoumkh /// * 'PosixTimeval' - 时间戳 23336fd0130Shoumkh pub fn do_gettimeofday() -> PosixTimeval { 23436fd0130Shoumkh let tp = getnstimeofday(); 23536fd0130Shoumkh return PosixTimeval { 23636fd0130Shoumkh tv_sec: tp.tv_sec, 23736fd0130Shoumkh tv_usec: (tp.tv_nsec / 1000) as i32, 23836fd0130Shoumkh }; 23936fd0130Shoumkh } 24036fd0130Shoumkh 241*6fc066acSJomo pub fn do_settimeofday64(time: PosixTimeSpec) -> Result<(), SystemError> { 242b8ed3825SDonkey Kane timekeeper().inner.write_irqsave().xtime = time; 243da152319SLoGin // todo: 模仿linux,实现时间误差校准。 244da152319SLoGin // https://code.dragonos.org.cn/xref/linux-6.6.21/kernel/time/timekeeping.c?fi=do_settimeofday64#1312 245da152319SLoGin return Ok(()); 246da152319SLoGin } 247da152319SLoGin 24836fd0130Shoumkh /// # 初始化timekeeping模块 2495b59005fSLoGin #[inline(never)] 25036fd0130Shoumkh pub fn timekeeping_init() { 25140fe15e0SLoGin kinfo!("Initializing timekeeping module..."); 25236fd0130Shoumkh let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 25336fd0130Shoumkh timekeeper_init(); 25436fd0130Shoumkh 25536fd0130Shoumkh // TODO 有ntp模块后 在此初始化ntp模块 25636fd0130Shoumkh 25736fd0130Shoumkh let clock = clocksource_default_clock(); 25836fd0130Shoumkh clock 25936fd0130Shoumkh .enable() 26036fd0130Shoumkh .expect("clocksource_default_clock enable failed"); 26136fd0130Shoumkh timekeeper().timekeeper_setup_internals(clock); 26236fd0130Shoumkh // 暂时不支持其他架构平台对时间的设置 所以使用x86平台对应值初始化 263b8ed3825SDonkey Kane let mut timekeeper = timekeeper().inner.write_irqsave(); 26436fd0130Shoumkh timekeeper.xtime.tv_nsec = ktime_get_real_ns(); 26536fd0130Shoumkh 266911132c4SDonkey Kane //参考https://elixir.bootlin.com/linux/v4.4/source/kernel/time/timekeeping.c#L1251 对wtm进行初始化 267911132c4SDonkey Kane ( 268911132c4SDonkey Kane timekeeper.wall_to_monotonic.tv_nsec, 269911132c4SDonkey Kane timekeeper.wall_to_monotonic.tv_sec, 270911132c4SDonkey Kane ) = (-timekeeper.xtime.tv_nsec, -timekeeper.xtime.tv_sec); 27136fd0130Shoumkh 27236fd0130Shoumkh __ADDED_USEC.store(0, Ordering::SeqCst); 27336fd0130Shoumkh 27436fd0130Shoumkh drop(irq_guard); 275b8ed3825SDonkey Kane drop(timekeeper); 2765b59005fSLoGin jiffies_init(); 27740fe15e0SLoGin kinfo!("timekeeping_init successfully"); 27836fd0130Shoumkh } 27936fd0130Shoumkh 28036fd0130Shoumkh /// # 使用当前时钟源增加wall time 2810d6cf65aSLoGin pub fn update_wall_time(delta_us: i64) { 28236fd0130Shoumkh // kdebug!("enter update_wall_time, stack_use = {:}",stack_use); 28336fd0130Shoumkh compiler_fence(Ordering::SeqCst); 28436fd0130Shoumkh let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 28536fd0130Shoumkh // 如果在休眠那就不更新 28636fd0130Shoumkh if TIMEKEEPING_SUSPENDED.load(Ordering::SeqCst) { 28736fd0130Shoumkh return; 28836fd0130Shoumkh } 28936fd0130Shoumkh 29036fd0130Shoumkh // ===== 请不要删除这些注释 ===== 29136fd0130Shoumkh // let clock = timekeeper.clock.clone().unwrap(); 29236fd0130Shoumkh // let clock_data = clock.clocksource_data(); 29336fd0130Shoumkh // let offset = (clock.read().div(clock_data.watchdog_last).data()) & clock_data.mask.bits(); 29436fd0130Shoumkh 29536fd0130Shoumkh // timekeeper.xtime_nsec = (timekeeper.xtime.tv_nsec as u64) << timekeeper.shift; 29636fd0130Shoumkh // // TODO 当有ntp模块之后 需要将timekeep与ntp进行同步并检查 29736fd0130Shoumkh // timekeeper.xtime.tv_nsec = ((timekeeper.xtime_nsec as i64) >> timekeeper.shift) + 1; 29836fd0130Shoumkh // timekeeper.xtime_nsec -= (timekeeper.xtime.tv_nsec as u64) << timekeeper.shift; 29936fd0130Shoumkh 30036fd0130Shoumkh // timekeeper.xtime.tv_nsec += offset as i64; 30136fd0130Shoumkh // while unlikely(timekeeper.xtime.tv_nsec >= NSEC_PER_SEC.into()) { 30236fd0130Shoumkh // timekeeper.xtime.tv_nsec -= NSEC_PER_SEC as i64; 30336fd0130Shoumkh // timekeeper.xtime.tv_sec += 1; 30436fd0130Shoumkh // // TODO 需要处理闰秒 30536fd0130Shoumkh // } 30636fd0130Shoumkh // ================ 30736fd0130Shoumkh compiler_fence(Ordering::SeqCst); 308be8cdf4bSLoGin 3090d6cf65aSLoGin __ADDED_USEC.fetch_add(delta_us, Ordering::SeqCst); 31036fd0130Shoumkh compiler_fence(Ordering::SeqCst); 31136fd0130Shoumkh let mut retry = 10; 31236fd0130Shoumkh 31336fd0130Shoumkh let usec = __ADDED_USEC.load(Ordering::SeqCst); 31436fd0130Shoumkh 315be8cdf4bSLoGin // 一分钟同步一次 31636fd0130Shoumkh loop { 31736fd0130Shoumkh if (usec & !((1 << 26) - 1)) != 0 { 31836fd0130Shoumkh if __ADDED_USEC 31936fd0130Shoumkh .compare_exchange(usec, 0, Ordering::SeqCst, Ordering::SeqCst) 32036fd0130Shoumkh .is_ok() 32136fd0130Shoumkh || retry == 0 32236fd0130Shoumkh { 32336fd0130Shoumkh // 同步时间 32436fd0130Shoumkh // 我感觉这里会出问题:多个读者不退出的话,写者就无法写入 32536fd0130Shoumkh // 然后这里会超时,导致在中断返回之后,会不断的进入这个中断,最终爆栈。 326b8ed3825SDonkey Kane let mut timekeeper = timekeeper().inner.write_irqsave(); 32736fd0130Shoumkh timekeeper.xtime.tv_nsec = ktime_get_real_ns(); 32836fd0130Shoumkh timekeeper.xtime.tv_sec = 0; 329b8ed3825SDonkey Kane __ADDED_USEC.store(0, Ordering::SeqCst); 330b8ed3825SDonkey Kane 33136fd0130Shoumkh drop(timekeeper); 33236fd0130Shoumkh break; 33336fd0130Shoumkh } 33436fd0130Shoumkh retry -= 1; 33536fd0130Shoumkh } else { 33636fd0130Shoumkh break; 33736fd0130Shoumkh } 33836fd0130Shoumkh } 339b8ed3825SDonkey Kane timekeeper().mark_update_wall_time_ok(); 34036fd0130Shoumkh // TODO 需要检查是否更新时间源 34136fd0130Shoumkh compiler_fence(Ordering::SeqCst); 34236fd0130Shoumkh drop(irq_guard); 34336fd0130Shoumkh compiler_fence(Ordering::SeqCst); 34436fd0130Shoumkh } 34536fd0130Shoumkh // TODO timekeeping_adjust 34636fd0130Shoumkh // TODO wall_to_monotic 347