xref: /DragonOS/kernel/src/time/timekeeping.rs (revision af097f9f4b317337fe74aaa5070c34a14b8635fd)
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