136fd0130Shoumkh use alloc::sync::Arc; 2*af097f9fS黄铭涛 use core::intrinsics::{likely, unlikely}; 3*af097f9fS黄铭涛 use core::sync::atomic::{compiler_fence, AtomicBool, Ordering}; 4*af097f9fS黄铭涛 use log::{debug, info, warn}; 5da152319SLoGin use system_error::SystemError; 636fd0130Shoumkh 736fd0130Shoumkh use crate::{ 8*af097f9fS黄铭涛 arch::CurrentIrqArch, 936fd0130Shoumkh exception::InterruptArch, 10*af097f9fS黄铭涛 libs::rwlock::RwLock, 115b59005fSLoGin time::{ 125b59005fSLoGin jiffies::{clocksource_default_clock, jiffies_init}, 135b59005fSLoGin timekeep::ktime_get_real_ns, 146fc066acSJomo PosixTimeSpec, 155b59005fSLoGin }, 1636fd0130Shoumkh }; 1736fd0130Shoumkh 18*af097f9fS黄铭涛 use super::timekeep::{ktime_t, timespec_to_ktime}; 1936fd0130Shoumkh use super::{ 2036fd0130Shoumkh clocksource::{clocksource_cyc2ns, Clocksource, CycleNum, HZ}, 2136fd0130Shoumkh syscall::PosixTimeval, 22*af097f9fS黄铭涛 NSEC_PER_SEC, 2336fd0130Shoumkh }; 2436fd0130Shoumkh /// NTP周期频率 2536fd0130Shoumkh pub const NTP_INTERVAL_FREQ: u64 = HZ; 2636fd0130Shoumkh /// NTP周期长度 2736fd0130Shoumkh pub const NTP_INTERVAL_LENGTH: u64 = NSEC_PER_SEC as u64 / NTP_INTERVAL_FREQ; 2836fd0130Shoumkh /// NTP转换比例 2936fd0130Shoumkh pub const NTP_SCALE_SHIFT: u32 = 32; 3036fd0130Shoumkh 3136fd0130Shoumkh /// timekeeping休眠标志,false为未休眠 3236fd0130Shoumkh pub static TIMEKEEPING_SUSPENDED: AtomicBool = AtomicBool::new(false); 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 } 4036fd0130Shoumkh 4136fd0130Shoumkh #[allow(dead_code)] 4236fd0130Shoumkh #[derive(Debug)] 4336fd0130Shoumkh pub struct TimekeeperData { 4436fd0130Shoumkh /// 用于计时的当前时钟源。 4536fd0130Shoumkh clock: Option<Arc<dyn Clocksource>>, 4636fd0130Shoumkh /// 当前时钟源的移位值。 4736fd0130Shoumkh shift: i32, 4836fd0130Shoumkh /// 一个NTP间隔中的时钟周期数。 4936fd0130Shoumkh cycle_interval: CycleNum, 5036fd0130Shoumkh /// 一个NTP间隔中时钟移位的纳秒数。 5136fd0130Shoumkh xtime_interval: u64, 5236fd0130Shoumkh /// 5336fd0130Shoumkh xtime_remainder: i64, 5436fd0130Shoumkh /// 每个NTP间隔累积的原始纳米秒 5536fd0130Shoumkh raw_interval: i64, 5636fd0130Shoumkh /// 时钟移位纳米秒余数 5736fd0130Shoumkh xtime_nsec: u64, 5836fd0130Shoumkh /// 积累时间和ntp时间在ntp位移纳秒量上的差距 5936fd0130Shoumkh ntp_error: i64, 6036fd0130Shoumkh /// 用于转换时钟偏移纳秒和ntp偏移纳秒的偏移量 6136fd0130Shoumkh ntp_error_shift: i32, 6236fd0130Shoumkh /// NTP调整时钟乘法器 6336fd0130Shoumkh mult: u32, 646fc066acSJomo raw_time: PosixTimeSpec, 656fc066acSJomo wall_to_monotonic: PosixTimeSpec, 666fc066acSJomo total_sleep_time: PosixTimeSpec, 676fc066acSJomo xtime: PosixTimeSpec, 68*af097f9fS黄铭涛 /// 单调时间和实时时间的偏移量 69*af097f9fS黄铭涛 real_time_offset: ktime_t, 7036fd0130Shoumkh } 7136fd0130Shoumkh impl TimekeeperData { 7236fd0130Shoumkh pub fn new() -> Self { 7336fd0130Shoumkh Self { 7436fd0130Shoumkh clock: None, 7536fd0130Shoumkh shift: Default::default(), 76b8ed3825SDonkey Kane cycle_interval: CycleNum::new(0), 7736fd0130Shoumkh xtime_interval: Default::default(), 7836fd0130Shoumkh xtime_remainder: Default::default(), 7936fd0130Shoumkh raw_interval: Default::default(), 8036fd0130Shoumkh xtime_nsec: Default::default(), 8136fd0130Shoumkh ntp_error: Default::default(), 8236fd0130Shoumkh ntp_error_shift: Default::default(), 8336fd0130Shoumkh mult: Default::default(), 846fc066acSJomo xtime: PosixTimeSpec { 8536fd0130Shoumkh tv_nsec: 0, 8636fd0130Shoumkh tv_sec: 0, 8736fd0130Shoumkh }, 886fc066acSJomo wall_to_monotonic: PosixTimeSpec { 8936fd0130Shoumkh tv_nsec: 0, 9036fd0130Shoumkh tv_sec: 0, 9136fd0130Shoumkh }, 926fc066acSJomo total_sleep_time: PosixTimeSpec { 9336fd0130Shoumkh tv_nsec: 0, 9436fd0130Shoumkh tv_sec: 0, 9536fd0130Shoumkh }, 966fc066acSJomo raw_time: PosixTimeSpec { 9736fd0130Shoumkh tv_nsec: 0, 9836fd0130Shoumkh tv_sec: 0, 9936fd0130Shoumkh }, 100*af097f9fS黄铭涛 real_time_offset: 0, 10136fd0130Shoumkh } 10236fd0130Shoumkh } 10336fd0130Shoumkh } 10436fd0130Shoumkh impl Timekeeper { 105b8ed3825SDonkey Kane fn new() -> Self { 106b8ed3825SDonkey Kane Self { 107b8ed3825SDonkey Kane inner: RwLock::new(TimekeeperData::new()), 108b8ed3825SDonkey Kane } 109b8ed3825SDonkey Kane } 110b8ed3825SDonkey Kane 11136fd0130Shoumkh /// # 设置timekeeper的参数 11236fd0130Shoumkh /// 11336fd0130Shoumkh /// ## 参数 11436fd0130Shoumkh /// 11536fd0130Shoumkh /// * 'clock' - 指定的时钟实际类型。初始为ClocksourceJiffies 11636fd0130Shoumkh pub fn timekeeper_setup_internals(&self, clock: Arc<dyn Clocksource>) { 117b8ed3825SDonkey Kane let mut timekeeper = self.inner.write_irqsave(); 11836fd0130Shoumkh // 更新clock 11936fd0130Shoumkh let mut clock_data = clock.clocksource_data(); 120*af097f9fS黄铭涛 clock_data.cycle_last = clock.read(); 12136fd0130Shoumkh if clock.update_clocksource_data(clock_data).is_err() { 1222eab6dd7S曾俊 debug!("timekeeper_setup_internals:update_clocksource_data run failed"); 12336fd0130Shoumkh } 12436fd0130Shoumkh timekeeper.clock.replace(clock.clone()); 12536fd0130Shoumkh 12636fd0130Shoumkh let clock_data = clock.clocksource_data(); 12736fd0130Shoumkh let mut temp = NTP_INTERVAL_LENGTH << clock_data.shift; 12836fd0130Shoumkh let ntpinterval = temp; 12936fd0130Shoumkh temp += (clock_data.mult / 2) as u64; 13036fd0130Shoumkh // do div 13136fd0130Shoumkh 132b8ed3825SDonkey Kane timekeeper.cycle_interval = CycleNum::new(temp); 13336fd0130Shoumkh timekeeper.xtime_interval = temp * clock_data.mult as u64; 13440fe15e0SLoGin // 这里可能存在下界溢出问题,debug模式下会报错panic 13536fd0130Shoumkh timekeeper.xtime_remainder = (ntpinterval - timekeeper.xtime_interval) as i64; 13636fd0130Shoumkh timekeeper.raw_interval = (timekeeper.xtime_interval >> clock_data.shift) as i64; 13736fd0130Shoumkh timekeeper.xtime_nsec = 0; 13836fd0130Shoumkh timekeeper.shift = clock_data.shift as i32; 13936fd0130Shoumkh 14036fd0130Shoumkh timekeeper.ntp_error = 0; 14136fd0130Shoumkh timekeeper.ntp_error_shift = (NTP_SCALE_SHIFT - clock_data.shift) as i32; 14236fd0130Shoumkh 14336fd0130Shoumkh timekeeper.mult = clock_data.mult; 14436fd0130Shoumkh } 14536fd0130Shoumkh 146*af097f9fS黄铭涛 pub fn timekeeping_get_ns(&self) -> i64 { 147*af097f9fS黄铭涛 let timekeeper = self.inner.read_irqsave(); 14836fd0130Shoumkh let clock = timekeeper.clock.clone().unwrap(); 149b8ed3825SDonkey Kane 150*af097f9fS黄铭涛 let cycle_now = clock.read(); 151911132c4SDonkey Kane let clock_data = clock.clocksource_data(); 152*af097f9fS黄铭涛 let cycle_delta = (cycle_now.div(clock_data.cycle_last)).data() & clock_data.mask.bits(); 153b8ed3825SDonkey Kane 154b8ed3825SDonkey Kane return clocksource_cyc2ns( 155*af097f9fS黄铭涛 CycleNum::new(cycle_delta), 156*af097f9fS黄铭涛 timekeeper.mult, 157*af097f9fS黄铭涛 timekeeper.shift as u32, 158*af097f9fS黄铭涛 ) as i64; 159*af097f9fS黄铭涛 } 160*af097f9fS黄铭涛 161*af097f9fS黄铭涛 /// # 处理大幅度调整 162*af097f9fS黄铭涛 pub fn timekeeping_bigadjust(&self, error: i64, interval: i64, offset: i64) -> (i64, i64, i32) { 163*af097f9fS黄铭涛 let mut error = error; 164*af097f9fS黄铭涛 let mut interval = interval; 165*af097f9fS黄铭涛 let mut offset = offset; 166*af097f9fS黄铭涛 167*af097f9fS黄铭涛 // TODO: 计算look_head并调整ntp误差 168*af097f9fS黄铭涛 169*af097f9fS黄铭涛 let tmp = interval; 170*af097f9fS黄铭涛 let mut mult = 1; 171*af097f9fS黄铭涛 let mut adj = 0; 172*af097f9fS黄铭涛 if error < 0 { 173*af097f9fS黄铭涛 error = -error; 174*af097f9fS黄铭涛 interval = -interval; 175*af097f9fS黄铭涛 offset = -offset; 176*af097f9fS黄铭涛 mult = -1; 177*af097f9fS黄铭涛 } 178*af097f9fS黄铭涛 while error > tmp { 179*af097f9fS黄铭涛 adj += 1; 180*af097f9fS黄铭涛 error >>= 1; 181*af097f9fS黄铭涛 } 182*af097f9fS黄铭涛 183*af097f9fS黄铭涛 interval <<= adj; 184*af097f9fS黄铭涛 offset <<= adj; 185*af097f9fS黄铭涛 mult <<= adj; 186*af097f9fS黄铭涛 187*af097f9fS黄铭涛 return (interval, offset, mult); 188*af097f9fS黄铭涛 } 189*af097f9fS黄铭涛 190*af097f9fS黄铭涛 /// # 调整时钟的mult减少ntp_error 191*af097f9fS黄铭涛 pub fn timekeeping_adjust(&self, offset: i64) -> i64 { 192*af097f9fS黄铭涛 let mut timekeeper = self.inner.write_irqsave(); 193*af097f9fS黄铭涛 let mut interval = timekeeper.cycle_interval.data() as i64; 194*af097f9fS黄铭涛 let mut offset = offset; 195*af097f9fS黄铭涛 let adj: i32; 196*af097f9fS黄铭涛 197*af097f9fS黄铭涛 // 计算误差 198*af097f9fS黄铭涛 let mut error = timekeeper.ntp_error >> (timekeeper.ntp_error_shift - 1); 199*af097f9fS黄铭涛 200*af097f9fS黄铭涛 // 误差超过一个interval,就要进行调整 201*af097f9fS黄铭涛 if error >= 0 { 202*af097f9fS黄铭涛 if error > interval { 203*af097f9fS黄铭涛 error >>= 2; 204*af097f9fS黄铭涛 if likely(error <= interval) { 205*af097f9fS黄铭涛 adj = 1; 206*af097f9fS黄铭涛 } else { 207*af097f9fS黄铭涛 (interval, offset, adj) = self.timekeeping_bigadjust(error, interval, offset); 208*af097f9fS黄铭涛 } 209*af097f9fS黄铭涛 } else { 210*af097f9fS黄铭涛 // 不需要校准 211*af097f9fS黄铭涛 return offset; 212*af097f9fS黄铭涛 } 213*af097f9fS黄铭涛 } else if -error > interval { 214*af097f9fS黄铭涛 if likely(-error <= interval) { 215*af097f9fS黄铭涛 adj = -1; 216*af097f9fS黄铭涛 interval = -interval; 217*af097f9fS黄铭涛 offset = -offset; 218*af097f9fS黄铭涛 } else { 219*af097f9fS黄铭涛 (interval, offset, adj) = self.timekeeping_bigadjust(error, interval, offset); 220*af097f9fS黄铭涛 } 221*af097f9fS黄铭涛 } else { 222*af097f9fS黄铭涛 // 不需要校准 223*af097f9fS黄铭涛 return offset; 224*af097f9fS黄铭涛 } 225*af097f9fS黄铭涛 226*af097f9fS黄铭涛 // 检查最大调整值,确保调整值不会超过时钟源允许的最大值 227*af097f9fS黄铭涛 let clock_data = timekeeper.clock.clone().unwrap().clocksource_data(); 228*af097f9fS黄铭涛 if unlikely( 229*af097f9fS黄铭涛 clock_data.maxadj != 0 230*af097f9fS黄铭涛 && (timekeeper.mult as i32 + adj 231*af097f9fS黄铭涛 > clock_data.mult as i32 + clock_data.maxadj as i32), 232*af097f9fS黄铭涛 ) { 233*af097f9fS黄铭涛 warn!( 234*af097f9fS黄铭涛 "Adjusting {:?} more than ({} vs {})", 235*af097f9fS黄铭涛 clock_data.name, 236*af097f9fS黄铭涛 timekeeper.mult as i32 + adj, 237*af097f9fS黄铭涛 clock_data.mult as i32 + clock_data.maxadj as i32 238b8ed3825SDonkey Kane ); 239b8ed3825SDonkey Kane } 240b8ed3825SDonkey Kane 241*af097f9fS黄铭涛 if error > 0 { 242*af097f9fS黄铭涛 timekeeper.mult += adj as u32; 243*af097f9fS黄铭涛 timekeeper.xtime_interval += interval as u64; 244*af097f9fS黄铭涛 timekeeper.xtime_nsec -= offset as u64; 245*af097f9fS黄铭涛 } else { 246*af097f9fS黄铭涛 timekeeper.mult -= adj as u32; 247*af097f9fS黄铭涛 timekeeper.xtime_interval -= interval as u64; 248*af097f9fS黄铭涛 timekeeper.xtime_nsec += offset as u64; 249*af097f9fS黄铭涛 } 250*af097f9fS黄铭涛 timekeeper.ntp_error -= (interval - offset) << timekeeper.ntp_error_shift; 251*af097f9fS黄铭涛 252*af097f9fS黄铭涛 return offset; 253*af097f9fS黄铭涛 } 254*af097f9fS黄铭涛 /// # 用于累积时间间隔,并将其转换为纳秒时间 255*af097f9fS黄铭涛 pub fn logarithmic_accumulation(&self, offset: u64, shift: i32) -> u64 { 256*af097f9fS黄铭涛 let mut timekeeper = self.inner.write_irqsave(); 257*af097f9fS黄铭涛 let clock = timekeeper.clock.clone().unwrap(); 258*af097f9fS黄铭涛 let clock_data = clock.clocksource_data(); 259*af097f9fS黄铭涛 let nsecps = (NSEC_PER_SEC as u64) << timekeeper.shift; 260*af097f9fS黄铭涛 let mut offset = offset; 261*af097f9fS黄铭涛 262*af097f9fS黄铭涛 // 检查offset是否小于一个NTP周期间隔 263*af097f9fS黄铭涛 if offset < timekeeper.cycle_interval.data() << shift { 264*af097f9fS黄铭涛 return offset; 265b8ed3825SDonkey Kane } 266b8ed3825SDonkey Kane 267*af097f9fS黄铭涛 // 累积一个移位的interval 268*af097f9fS黄铭涛 offset -= timekeeper.cycle_interval.data() << shift; 269*af097f9fS黄铭涛 clock_data 270*af097f9fS黄铭涛 .cycle_last 271*af097f9fS黄铭涛 .add(CycleNum::new(timekeeper.cycle_interval.data() << shift)); 272*af097f9fS黄铭涛 if clock.update_clocksource_data(clock_data).is_err() { 273*af097f9fS黄铭涛 debug!("logarithmic_accumulation:update_clocksource_data run failed"); 274*af097f9fS黄铭涛 } 275*af097f9fS黄铭涛 timekeeper.clock.replace(clock.clone()); 276*af097f9fS黄铭涛 277*af097f9fS黄铭涛 // 更新xime_nsec 278*af097f9fS黄铭涛 timekeeper.xtime_nsec += timekeeper.xtime_interval << shift; 279*af097f9fS黄铭涛 while timekeeper.xtime_nsec >= nsecps { 280*af097f9fS黄铭涛 timekeeper.xtime_nsec -= nsecps; 281*af097f9fS黄铭涛 timekeeper.xtime.tv_sec += 1; 282*af097f9fS黄铭涛 // TODO: 处理闰秒 283*af097f9fS黄铭涛 } 284*af097f9fS黄铭涛 285*af097f9fS黄铭涛 // TODO:更新raw_time 286*af097f9fS黄铭涛 287*af097f9fS黄铭涛 // TODO:计算ntp_error 288*af097f9fS黄铭涛 289*af097f9fS黄铭涛 return offset; 29036fd0130Shoumkh } 29136fd0130Shoumkh } 292b8ed3825SDonkey Kane 293b8ed3825SDonkey Kane #[inline(always)] 29436fd0130Shoumkh pub fn timekeeper() -> &'static Timekeeper { 2958d94ea66SYJwu2023 let r = unsafe { __TIMEKEEPER.as_ref().unwrap() }; 2968d94ea66SYJwu2023 2978d94ea66SYJwu2023 return r; 29836fd0130Shoumkh } 29936fd0130Shoumkh 30036fd0130Shoumkh pub fn timekeeper_init() { 301b8ed3825SDonkey Kane unsafe { __TIMEKEEPER = Some(Timekeeper::new()) }; 30236fd0130Shoumkh } 30336fd0130Shoumkh 30436fd0130Shoumkh /// # 获取1970.1.1至今的UTC时间戳(最小单位:nsec) 30536fd0130Shoumkh /// 30636fd0130Shoumkh /// ## 返回值 30736fd0130Shoumkh /// 30836fd0130Shoumkh /// * 'TimeSpec' - 时间戳 3096fc066acSJomo pub fn getnstimeofday() -> PosixTimeSpec { 3102eab6dd7S曾俊 // debug!("enter getnstimeofday"); 31136fd0130Shoumkh 312911132c4SDonkey Kane let nsecs; 3136fc066acSJomo let mut xtime: PosixTimeSpec; 31436fd0130Shoumkh loop { 315b8ed3825SDonkey Kane match timekeeper().inner.try_read_irqsave() { 31636fd0130Shoumkh None => continue, 31736fd0130Shoumkh Some(tk) => { 318b8ed3825SDonkey Kane xtime = tk.xtime; 31936fd0130Shoumkh drop(tk); 320b8ed3825SDonkey Kane 321*af097f9fS黄铭涛 nsecs = timekeeper().timekeeping_get_ns(); 322b8ed3825SDonkey Kane 32336fd0130Shoumkh // TODO 不同架构可能需要加上不同的偏移量 32436fd0130Shoumkh break; 32536fd0130Shoumkh } 32636fd0130Shoumkh } 32736fd0130Shoumkh } 328*af097f9fS黄铭涛 xtime.tv_nsec += nsecs; 329b8ed3825SDonkey Kane xtime.tv_sec += xtime.tv_nsec / NSEC_PER_SEC as i64; 330b8ed3825SDonkey Kane xtime.tv_nsec %= NSEC_PER_SEC as i64; 3312eab6dd7S曾俊 // debug!("getnstimeofday: xtime = {:?}, nsecs = {:}", xtime, nsecs); 33236fd0130Shoumkh 33336fd0130Shoumkh // TODO 将xtime和当前时间源的时间相加 33436fd0130Shoumkh 335b8ed3825SDonkey Kane return xtime; 33636fd0130Shoumkh } 33736fd0130Shoumkh 33836fd0130Shoumkh /// # 获取1970.1.1至今的UTC时间戳(最小单位:usec) 33936fd0130Shoumkh /// 34036fd0130Shoumkh /// ## 返回值 34136fd0130Shoumkh /// 34236fd0130Shoumkh /// * 'PosixTimeval' - 时间戳 34336fd0130Shoumkh pub fn do_gettimeofday() -> PosixTimeval { 34436fd0130Shoumkh let tp = getnstimeofday(); 34536fd0130Shoumkh return PosixTimeval { 34636fd0130Shoumkh tv_sec: tp.tv_sec, 34736fd0130Shoumkh tv_usec: (tp.tv_nsec / 1000) as i32, 34836fd0130Shoumkh }; 34936fd0130Shoumkh } 35036fd0130Shoumkh 3516fc066acSJomo pub fn do_settimeofday64(time: PosixTimeSpec) -> Result<(), SystemError> { 352b8ed3825SDonkey Kane timekeeper().inner.write_irqsave().xtime = time; 353da152319SLoGin // todo: 模仿linux,实现时间误差校准。 354da152319SLoGin // https://code.dragonos.org.cn/xref/linux-6.6.21/kernel/time/timekeeping.c?fi=do_settimeofday64#1312 355da152319SLoGin return Ok(()); 356da152319SLoGin } 357da152319SLoGin 35836fd0130Shoumkh /// # 初始化timekeeping模块 3595b59005fSLoGin #[inline(never)] 36036fd0130Shoumkh pub fn timekeeping_init() { 3612eab6dd7S曾俊 info!("Initializing timekeeping module..."); 36236fd0130Shoumkh let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 36336fd0130Shoumkh timekeeper_init(); 36436fd0130Shoumkh 36536fd0130Shoumkh // TODO 有ntp模块后 在此初始化ntp模块 36636fd0130Shoumkh 36736fd0130Shoumkh let clock = clocksource_default_clock(); 36836fd0130Shoumkh clock 36936fd0130Shoumkh .enable() 37036fd0130Shoumkh .expect("clocksource_default_clock enable failed"); 37136fd0130Shoumkh timekeeper().timekeeper_setup_internals(clock); 37236fd0130Shoumkh // 暂时不支持其他架构平台对时间的设置 所以使用x86平台对应值初始化 373b8ed3825SDonkey Kane let mut timekeeper = timekeeper().inner.write_irqsave(); 37436fd0130Shoumkh timekeeper.xtime.tv_nsec = ktime_get_real_ns(); 37536fd0130Shoumkh 376911132c4SDonkey Kane //参考https://elixir.bootlin.com/linux/v4.4/source/kernel/time/timekeeping.c#L1251 对wtm进行初始化 377911132c4SDonkey Kane ( 378911132c4SDonkey Kane timekeeper.wall_to_monotonic.tv_nsec, 379911132c4SDonkey Kane timekeeper.wall_to_monotonic.tv_sec, 380911132c4SDonkey Kane ) = (-timekeeper.xtime.tv_nsec, -timekeeper.xtime.tv_sec); 38136fd0130Shoumkh 38236fd0130Shoumkh drop(irq_guard); 383b8ed3825SDonkey Kane drop(timekeeper); 3845b59005fSLoGin jiffies_init(); 3852eab6dd7S曾俊 info!("timekeeping_init successfully"); 38636fd0130Shoumkh } 38736fd0130Shoumkh 38836fd0130Shoumkh /// # 使用当前时钟源增加wall time 389*af097f9fS黄铭涛 /// 参考:https://code.dragonos.org.cn/xref/linux-3.4.99/kernel/time/timekeeping.c#1041 390*af097f9fS黄铭涛 pub fn update_wall_time() { 3912eab6dd7S曾俊 // debug!("enter update_wall_time, stack_use = {:}",stack_use); 39236fd0130Shoumkh compiler_fence(Ordering::SeqCst); 39336fd0130Shoumkh let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 39436fd0130Shoumkh // 如果在休眠那就不更新 39536fd0130Shoumkh if TIMEKEEPING_SUSPENDED.load(Ordering::SeqCst) { 39636fd0130Shoumkh return; 39736fd0130Shoumkh } 39836fd0130Shoumkh 399*af097f9fS黄铭涛 let mut tk = timekeeper().inner.write_irqsave(); 400*af097f9fS黄铭涛 // 获取当前时钟源 401*af097f9fS黄铭涛 let clock = tk.clock.clone().unwrap(); 402*af097f9fS黄铭涛 let clock_data = clock.clocksource_data(); 403*af097f9fS黄铭涛 // 计算从上一次更新周期以来经过的时钟周期数 404*af097f9fS黄铭涛 let mut offset = (clock.read().div(clock_data.cycle_last).data()) & clock_data.mask.bits(); 405*af097f9fS黄铭涛 // 检查offset是否达到了一个NTP周期间隔 406*af097f9fS黄铭涛 if offset < tk.cycle_interval.data() { 407*af097f9fS黄铭涛 return; 40836fd0130Shoumkh } 409*af097f9fS黄铭涛 410*af097f9fS黄铭涛 // 将纳秒部分转换为更高精度的格式 411*af097f9fS黄铭涛 tk.xtime_nsec = (tk.xtime.tv_nsec as u64) << tk.shift; 412*af097f9fS黄铭涛 413*af097f9fS黄铭涛 let mut shift = (offset.ilog2() - tk.cycle_interval.data().ilog2()) as i32; 414*af097f9fS黄铭涛 shift = shift.max(0); 415*af097f9fS黄铭涛 // let max_shift = (64 - (ntp_tick_length().ilog2()+1)) - 1; 416*af097f9fS黄铭涛 // shift = min(shift, max_shift) 417*af097f9fS黄铭涛 while offset >= tk.cycle_interval.data() { 418*af097f9fS黄铭涛 offset = timekeeper().logarithmic_accumulation(offset, shift); 419*af097f9fS黄铭涛 if offset < tk.cycle_interval.data() << shift { 420*af097f9fS黄铭涛 shift -= 1; 42136fd0130Shoumkh } 42236fd0130Shoumkh } 423*af097f9fS黄铭涛 424*af097f9fS黄铭涛 timekeeper().timekeeping_adjust(offset as i64); 425*af097f9fS黄铭涛 426*af097f9fS黄铭涛 // 处理xtime_nsec下溢问题,并对NTP误差进行调整 427*af097f9fS黄铭涛 if unlikely((tk.xtime_nsec as i64) < 0) { 428*af097f9fS黄铭涛 let neg = -(tk.xtime_nsec as i64); 429*af097f9fS黄铭涛 tk.xtime_nsec = 0; 430*af097f9fS黄铭涛 tk.ntp_error += neg << tk.ntp_error_shift; 431*af097f9fS黄铭涛 } 432*af097f9fS黄铭涛 433*af097f9fS黄铭涛 // 将纳秒部分舍入后存储在xtime.tv_nsec中 434*af097f9fS黄铭涛 tk.xtime.tv_nsec = ((tk.xtime_nsec as i64) >> tk.shift) + 1; 435*af097f9fS黄铭涛 tk.xtime_nsec -= (tk.xtime.tv_nsec as u64) << tk.shift; 436*af097f9fS黄铭涛 437*af097f9fS黄铭涛 // 确保经过舍入后的xtime.tv_nsec不会大于NSEC_PER_SEC,并在超过1秒的情况下进行适当的调整 438*af097f9fS黄铭涛 if unlikely(tk.xtime.tv_nsec >= NSEC_PER_SEC.into()) { 439*af097f9fS黄铭涛 tk.xtime.tv_nsec -= NSEC_PER_SEC as i64; 440*af097f9fS黄铭涛 tk.xtime.tv_sec += 1; 441*af097f9fS黄铭涛 // TODO: 处理闰秒 442*af097f9fS黄铭涛 } 443*af097f9fS黄铭涛 444*af097f9fS黄铭涛 // 更新时间的相关信息 445*af097f9fS黄铭涛 timekeeping_update(); 446*af097f9fS黄铭涛 44736fd0130Shoumkh compiler_fence(Ordering::SeqCst); 44836fd0130Shoumkh drop(irq_guard); 44936fd0130Shoumkh compiler_fence(Ordering::SeqCst); 45036fd0130Shoumkh } 45136fd0130Shoumkh // TODO wall_to_monotic 452*af097f9fS黄铭涛 453*af097f9fS黄铭涛 /// 参考:https://code.dragonos.org.cn/xref/linux-3.4.99/kernel/time/timekeeping.c#190 454*af097f9fS黄铭涛 pub fn timekeeping_update() { 455*af097f9fS黄铭涛 // TODO:如果clearntp为true,则会清除NTP错误并调用ntp_clear() 456*af097f9fS黄铭涛 457*af097f9fS黄铭涛 // 更新实时时钟偏移量,用于跟踪硬件时钟与系统时间的差异,以便进行时间校正 458*af097f9fS黄铭涛 update_rt_offset(); 459*af097f9fS黄铭涛 } 460*af097f9fS黄铭涛 461*af097f9fS黄铭涛 /// # 更新实时偏移量(墙上之间与单调时间的差值) 462*af097f9fS黄铭涛 pub fn update_rt_offset() { 463*af097f9fS黄铭涛 let mut timekeeper = timekeeper().inner.write_irqsave(); 464*af097f9fS黄铭涛 let ts = PosixTimeSpec::new( 465*af097f9fS黄铭涛 -timekeeper.wall_to_monotonic.tv_sec, 466*af097f9fS黄铭涛 -timekeeper.wall_to_monotonic.tv_nsec, 467*af097f9fS黄铭涛 ); 468*af097f9fS黄铭涛 timekeeper.real_time_offset = timespec_to_ktime(ts); 469*af097f9fS黄铭涛 } 470