xref: /DragonOS/kernel/src/time/timekeeping.rs (revision bd70d2d1f490aabd570a5301b858bd5eb04149fa)
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     xtime_remainder: i64,
5336fd0130Shoumkh     /// 每个NTP间隔累积的原始纳米秒
5436fd0130Shoumkh     raw_interval: i64,
5536fd0130Shoumkh     /// 时钟移位纳米秒余数
5636fd0130Shoumkh     xtime_nsec: u64,
5736fd0130Shoumkh     /// 积累时间和ntp时间在ntp位移纳秒量上的差距
5836fd0130Shoumkh     ntp_error: i64,
5936fd0130Shoumkh     /// 用于转换时钟偏移纳秒和ntp偏移纳秒的偏移量
6036fd0130Shoumkh     ntp_error_shift: i32,
6136fd0130Shoumkh     /// NTP调整时钟乘法器
6236fd0130Shoumkh     mult: u32,
636fc066acSJomo     raw_time: PosixTimeSpec,
646fc066acSJomo     wall_to_monotonic: PosixTimeSpec,
656fc066acSJomo     total_sleep_time: PosixTimeSpec,
666fc066acSJomo     xtime: PosixTimeSpec,
67*af097f9fS黄铭涛     /// 单调时间和实时时间的偏移量
68*af097f9fS黄铭涛     real_time_offset: ktime_t,
6936fd0130Shoumkh }
7036fd0130Shoumkh impl TimekeeperData {
new() -> Self7136fd0130Shoumkh     pub fn new() -> Self {
7236fd0130Shoumkh         Self {
7336fd0130Shoumkh             clock: None,
7436fd0130Shoumkh             shift: Default::default(),
75b8ed3825SDonkey Kane             cycle_interval: CycleNum::new(0),
7636fd0130Shoumkh             xtime_interval: Default::default(),
7736fd0130Shoumkh             xtime_remainder: Default::default(),
7836fd0130Shoumkh             raw_interval: Default::default(),
7936fd0130Shoumkh             xtime_nsec: Default::default(),
8036fd0130Shoumkh             ntp_error: Default::default(),
8136fd0130Shoumkh             ntp_error_shift: Default::default(),
8236fd0130Shoumkh             mult: Default::default(),
836fc066acSJomo             xtime: PosixTimeSpec {
8436fd0130Shoumkh                 tv_nsec: 0,
8536fd0130Shoumkh                 tv_sec: 0,
8636fd0130Shoumkh             },
876fc066acSJomo             wall_to_monotonic: PosixTimeSpec {
8836fd0130Shoumkh                 tv_nsec: 0,
8936fd0130Shoumkh                 tv_sec: 0,
9036fd0130Shoumkh             },
916fc066acSJomo             total_sleep_time: PosixTimeSpec {
9236fd0130Shoumkh                 tv_nsec: 0,
9336fd0130Shoumkh                 tv_sec: 0,
9436fd0130Shoumkh             },
956fc066acSJomo             raw_time: PosixTimeSpec {
9636fd0130Shoumkh                 tv_nsec: 0,
9736fd0130Shoumkh                 tv_sec: 0,
9836fd0130Shoumkh             },
99*af097f9fS黄铭涛             real_time_offset: 0,
10036fd0130Shoumkh         }
10136fd0130Shoumkh     }
10236fd0130Shoumkh }
10336fd0130Shoumkh impl Timekeeper {
new() -> Self104b8ed3825SDonkey Kane     fn new() -> Self {
105b8ed3825SDonkey Kane         Self {
106b8ed3825SDonkey Kane             inner: RwLock::new(TimekeeperData::new()),
107b8ed3825SDonkey Kane         }
108b8ed3825SDonkey Kane     }
109b8ed3825SDonkey Kane 
11036fd0130Shoumkh     /// # 设置timekeeper的参数
11136fd0130Shoumkh     ///
11236fd0130Shoumkh     /// ## 参数
11336fd0130Shoumkh     ///
11436fd0130Shoumkh     /// * 'clock' - 指定的时钟实际类型。初始为ClocksourceJiffies
timekeeper_setup_internals(&self, clock: Arc<dyn Clocksource>)11536fd0130Shoumkh     pub fn timekeeper_setup_internals(&self, clock: Arc<dyn Clocksource>) {
116b8ed3825SDonkey Kane         let mut timekeeper = self.inner.write_irqsave();
11736fd0130Shoumkh         // 更新clock
11836fd0130Shoumkh         let mut clock_data = clock.clocksource_data();
119*af097f9fS黄铭涛         clock_data.cycle_last = clock.read();
12036fd0130Shoumkh         if clock.update_clocksource_data(clock_data).is_err() {
1212eab6dd7S曾俊             debug!("timekeeper_setup_internals:update_clocksource_data run failed");
12236fd0130Shoumkh         }
12336fd0130Shoumkh         timekeeper.clock.replace(clock.clone());
12436fd0130Shoumkh 
12536fd0130Shoumkh         let clock_data = clock.clocksource_data();
12636fd0130Shoumkh         let mut temp = NTP_INTERVAL_LENGTH << clock_data.shift;
12736fd0130Shoumkh         let ntpinterval = temp;
12836fd0130Shoumkh         temp += (clock_data.mult / 2) as u64;
12936fd0130Shoumkh         // do div
13036fd0130Shoumkh 
131b8ed3825SDonkey Kane         timekeeper.cycle_interval = CycleNum::new(temp);
13236fd0130Shoumkh         timekeeper.xtime_interval = temp * clock_data.mult as u64;
13340fe15e0SLoGin         // 这里可能存在下界溢出问题,debug模式下会报错panic
13436fd0130Shoumkh         timekeeper.xtime_remainder = (ntpinterval - timekeeper.xtime_interval) as i64;
13536fd0130Shoumkh         timekeeper.raw_interval = (timekeeper.xtime_interval >> clock_data.shift) as i64;
13636fd0130Shoumkh         timekeeper.xtime_nsec = 0;
13736fd0130Shoumkh         timekeeper.shift = clock_data.shift as i32;
13836fd0130Shoumkh 
13936fd0130Shoumkh         timekeeper.ntp_error = 0;
14036fd0130Shoumkh         timekeeper.ntp_error_shift = (NTP_SCALE_SHIFT - clock_data.shift) as i32;
14136fd0130Shoumkh 
14236fd0130Shoumkh         timekeeper.mult = clock_data.mult;
14336fd0130Shoumkh     }
14436fd0130Shoumkh 
timekeeping_get_ns(&self) -> i64145*af097f9fS黄铭涛     pub fn timekeeping_get_ns(&self) -> i64 {
146*af097f9fS黄铭涛         let timekeeper = self.inner.read_irqsave();
14736fd0130Shoumkh         let clock = timekeeper.clock.clone().unwrap();
148b8ed3825SDonkey Kane 
149*af097f9fS黄铭涛         let cycle_now = clock.read();
150911132c4SDonkey Kane         let clock_data = clock.clocksource_data();
151*af097f9fS黄铭涛         let cycle_delta = (cycle_now.div(clock_data.cycle_last)).data() & clock_data.mask.bits();
152b8ed3825SDonkey Kane 
153b8ed3825SDonkey Kane         return clocksource_cyc2ns(
154*af097f9fS黄铭涛             CycleNum::new(cycle_delta),
155*af097f9fS黄铭涛             timekeeper.mult,
156*af097f9fS黄铭涛             timekeeper.shift as u32,
157*af097f9fS黄铭涛         ) as i64;
158*af097f9fS黄铭涛     }
159*af097f9fS黄铭涛 
160*af097f9fS黄铭涛     /// # 处理大幅度调整
timekeeping_bigadjust(&self, error: i64, interval: i64, offset: i64) -> (i64, i64, i32)161*af097f9fS黄铭涛     pub fn timekeeping_bigadjust(&self, error: i64, interval: i64, offset: i64) -> (i64, i64, i32) {
162*af097f9fS黄铭涛         let mut error = error;
163*af097f9fS黄铭涛         let mut interval = interval;
164*af097f9fS黄铭涛         let mut offset = offset;
165*af097f9fS黄铭涛 
166*af097f9fS黄铭涛         // TODO: 计算look_head并调整ntp误差
167*af097f9fS黄铭涛 
168*af097f9fS黄铭涛         let tmp = interval;
169*af097f9fS黄铭涛         let mut mult = 1;
170*af097f9fS黄铭涛         let mut adj = 0;
171*af097f9fS黄铭涛         if error < 0 {
172*af097f9fS黄铭涛             error = -error;
173*af097f9fS黄铭涛             interval = -interval;
174*af097f9fS黄铭涛             offset = -offset;
175*af097f9fS黄铭涛             mult = -1;
176*af097f9fS黄铭涛         }
177*af097f9fS黄铭涛         while error > tmp {
178*af097f9fS黄铭涛             adj += 1;
179*af097f9fS黄铭涛             error >>= 1;
180*af097f9fS黄铭涛         }
181*af097f9fS黄铭涛 
182*af097f9fS黄铭涛         interval <<= adj;
183*af097f9fS黄铭涛         offset <<= adj;
184*af097f9fS黄铭涛         mult <<= adj;
185*af097f9fS黄铭涛 
186*af097f9fS黄铭涛         return (interval, offset, mult);
187*af097f9fS黄铭涛     }
188*af097f9fS黄铭涛 
189*af097f9fS黄铭涛     /// # 调整时钟的mult减少ntp_error
timekeeping_adjust(&self, offset: i64) -> i64190*af097f9fS黄铭涛     pub fn timekeeping_adjust(&self, offset: i64) -> i64 {
191*af097f9fS黄铭涛         let mut timekeeper = self.inner.write_irqsave();
192*af097f9fS黄铭涛         let mut interval = timekeeper.cycle_interval.data() as i64;
193*af097f9fS黄铭涛         let mut offset = offset;
194*af097f9fS黄铭涛         let adj: i32;
195*af097f9fS黄铭涛 
196*af097f9fS黄铭涛         // 计算误差
197*af097f9fS黄铭涛         let mut error = timekeeper.ntp_error >> (timekeeper.ntp_error_shift - 1);
198*af097f9fS黄铭涛 
199*af097f9fS黄铭涛         // 误差超过一个interval,就要进行调整
200*af097f9fS黄铭涛         if error >= 0 {
201*af097f9fS黄铭涛             if error > interval {
202*af097f9fS黄铭涛                 error >>= 2;
203*af097f9fS黄铭涛                 if likely(error <= interval) {
204*af097f9fS黄铭涛                     adj = 1;
205*af097f9fS黄铭涛                 } else {
206*af097f9fS黄铭涛                     (interval, offset, adj) = self.timekeeping_bigadjust(error, interval, offset);
207*af097f9fS黄铭涛                 }
208*af097f9fS黄铭涛             } else {
209*af097f9fS黄铭涛                 // 不需要校准
210*af097f9fS黄铭涛                 return offset;
211*af097f9fS黄铭涛             }
212*af097f9fS黄铭涛         } else if -error > interval {
213*af097f9fS黄铭涛             if likely(-error <= interval) {
214*af097f9fS黄铭涛                 adj = -1;
215*af097f9fS黄铭涛                 interval = -interval;
216*af097f9fS黄铭涛                 offset = -offset;
217*af097f9fS黄铭涛             } else {
218*af097f9fS黄铭涛                 (interval, offset, adj) = self.timekeeping_bigadjust(error, interval, offset);
219*af097f9fS黄铭涛             }
220*af097f9fS黄铭涛         } else {
221*af097f9fS黄铭涛             // 不需要校准
222*af097f9fS黄铭涛             return offset;
223*af097f9fS黄铭涛         }
224*af097f9fS黄铭涛 
225*af097f9fS黄铭涛         // 检查最大调整值,确保调整值不会超过时钟源允许的最大值
226*af097f9fS黄铭涛         let clock_data = timekeeper.clock.clone().unwrap().clocksource_data();
227*af097f9fS黄铭涛         if unlikely(
228*af097f9fS黄铭涛             clock_data.maxadj != 0
229*af097f9fS黄铭涛                 && (timekeeper.mult as i32 + adj
230*af097f9fS黄铭涛                     > clock_data.mult as i32 + clock_data.maxadj as i32),
231*af097f9fS黄铭涛         ) {
232*af097f9fS黄铭涛             warn!(
233*af097f9fS黄铭涛                 "Adjusting {:?} more than ({} vs {})",
234*af097f9fS黄铭涛                 clock_data.name,
235*af097f9fS黄铭涛                 timekeeper.mult as i32 + adj,
236*af097f9fS黄铭涛                 clock_data.mult as i32 + clock_data.maxadj as i32
237b8ed3825SDonkey Kane             );
238b8ed3825SDonkey Kane         }
239b8ed3825SDonkey Kane 
240*af097f9fS黄铭涛         if error > 0 {
241*af097f9fS黄铭涛             timekeeper.mult += adj as u32;
242*af097f9fS黄铭涛             timekeeper.xtime_interval += interval as u64;
243*af097f9fS黄铭涛             timekeeper.xtime_nsec -= offset as u64;
244*af097f9fS黄铭涛         } else {
245*af097f9fS黄铭涛             timekeeper.mult -= adj as u32;
246*af097f9fS黄铭涛             timekeeper.xtime_interval -= interval as u64;
247*af097f9fS黄铭涛             timekeeper.xtime_nsec += offset as u64;
248*af097f9fS黄铭涛         }
249*af097f9fS黄铭涛         timekeeper.ntp_error -= (interval - offset) << timekeeper.ntp_error_shift;
250*af097f9fS黄铭涛 
251*af097f9fS黄铭涛         return offset;
252*af097f9fS黄铭涛     }
253*af097f9fS黄铭涛     /// # 用于累积时间间隔,并将其转换为纳秒时间
logarithmic_accumulation(&self, offset: u64, shift: i32) -> u64254*af097f9fS黄铭涛     pub fn logarithmic_accumulation(&self, offset: u64, shift: i32) -> u64 {
255*af097f9fS黄铭涛         let mut timekeeper = self.inner.write_irqsave();
256*af097f9fS黄铭涛         let clock = timekeeper.clock.clone().unwrap();
257*af097f9fS黄铭涛         let clock_data = clock.clocksource_data();
258*af097f9fS黄铭涛         let nsecps = (NSEC_PER_SEC as u64) << timekeeper.shift;
259*af097f9fS黄铭涛         let mut offset = offset;
260*af097f9fS黄铭涛 
261*af097f9fS黄铭涛         // 检查offset是否小于一个NTP周期间隔
262*af097f9fS黄铭涛         if offset < timekeeper.cycle_interval.data() << shift {
263*af097f9fS黄铭涛             return offset;
264b8ed3825SDonkey Kane         }
265b8ed3825SDonkey Kane 
266*af097f9fS黄铭涛         // 累积一个移位的interval
267*af097f9fS黄铭涛         offset -= timekeeper.cycle_interval.data() << shift;
268*af097f9fS黄铭涛         clock_data
269*af097f9fS黄铭涛             .cycle_last
270*af097f9fS黄铭涛             .add(CycleNum::new(timekeeper.cycle_interval.data() << shift));
271*af097f9fS黄铭涛         if clock.update_clocksource_data(clock_data).is_err() {
272*af097f9fS黄铭涛             debug!("logarithmic_accumulation:update_clocksource_data run failed");
273*af097f9fS黄铭涛         }
274*af097f9fS黄铭涛         timekeeper.clock.replace(clock.clone());
275*af097f9fS黄铭涛 
276*af097f9fS黄铭涛         // 更新xime_nsec
277*af097f9fS黄铭涛         timekeeper.xtime_nsec += timekeeper.xtime_interval << shift;
278*af097f9fS黄铭涛         while timekeeper.xtime_nsec >= nsecps {
279*af097f9fS黄铭涛             timekeeper.xtime_nsec -= nsecps;
280*af097f9fS黄铭涛             timekeeper.xtime.tv_sec += 1;
281*af097f9fS黄铭涛             // TODO: 处理闰秒
282*af097f9fS黄铭涛         }
283*af097f9fS黄铭涛 
284*af097f9fS黄铭涛         // TODO:更新raw_time
285*af097f9fS黄铭涛 
286*af097f9fS黄铭涛         // TODO:计算ntp_error
287*af097f9fS黄铭涛 
288*af097f9fS黄铭涛         return offset;
28936fd0130Shoumkh     }
29036fd0130Shoumkh }
291b8ed3825SDonkey Kane 
292b8ed3825SDonkey Kane #[inline(always)]
timekeeper() -> &'static Timekeeper29336fd0130Shoumkh pub fn timekeeper() -> &'static Timekeeper {
2948d94ea66SYJwu2023     let r = unsafe { __TIMEKEEPER.as_ref().unwrap() };
2958d94ea66SYJwu2023 
2968d94ea66SYJwu2023     return r;
29736fd0130Shoumkh }
29836fd0130Shoumkh 
timekeeper_init()29936fd0130Shoumkh pub fn timekeeper_init() {
300b8ed3825SDonkey Kane     unsafe { __TIMEKEEPER = Some(Timekeeper::new()) };
30136fd0130Shoumkh }
30236fd0130Shoumkh 
30336fd0130Shoumkh /// # 获取1970.1.1至今的UTC时间戳(最小单位:nsec)
30436fd0130Shoumkh ///
30536fd0130Shoumkh /// ## 返回值
30636fd0130Shoumkh ///
30736fd0130Shoumkh /// * 'TimeSpec' - 时间戳
getnstimeofday() -> PosixTimeSpec3086fc066acSJomo pub fn getnstimeofday() -> PosixTimeSpec {
3092eab6dd7S曾俊     // debug!("enter getnstimeofday");
31036fd0130Shoumkh 
311911132c4SDonkey Kane     let nsecs;
3126fc066acSJomo     let mut xtime: PosixTimeSpec;
31336fd0130Shoumkh     loop {
314b8ed3825SDonkey Kane         match timekeeper().inner.try_read_irqsave() {
31536fd0130Shoumkh             None => continue,
31636fd0130Shoumkh             Some(tk) => {
317b8ed3825SDonkey Kane                 xtime = tk.xtime;
31836fd0130Shoumkh                 drop(tk);
319b8ed3825SDonkey Kane 
320*af097f9fS黄铭涛                 nsecs = timekeeper().timekeeping_get_ns();
321b8ed3825SDonkey Kane 
32236fd0130Shoumkh                 // TODO 不同架构可能需要加上不同的偏移量
32336fd0130Shoumkh                 break;
32436fd0130Shoumkh             }
32536fd0130Shoumkh         }
32636fd0130Shoumkh     }
327*af097f9fS黄铭涛     xtime.tv_nsec += nsecs;
328b8ed3825SDonkey Kane     xtime.tv_sec += xtime.tv_nsec / NSEC_PER_SEC as i64;
329b8ed3825SDonkey Kane     xtime.tv_nsec %= NSEC_PER_SEC as i64;
3302eab6dd7S曾俊     // debug!("getnstimeofday: xtime = {:?}, nsecs = {:}", xtime, nsecs);
33136fd0130Shoumkh 
33236fd0130Shoumkh     // TODO 将xtime和当前时间源的时间相加
33336fd0130Shoumkh 
334b8ed3825SDonkey Kane     return xtime;
33536fd0130Shoumkh }
33636fd0130Shoumkh 
33736fd0130Shoumkh /// # 获取1970.1.1至今的UTC时间戳(最小单位:usec)
33836fd0130Shoumkh ///
33936fd0130Shoumkh /// ## 返回值
34036fd0130Shoumkh ///
34136fd0130Shoumkh /// * 'PosixTimeval' - 时间戳
do_gettimeofday() -> PosixTimeval34236fd0130Shoumkh pub fn do_gettimeofday() -> PosixTimeval {
34336fd0130Shoumkh     let tp = getnstimeofday();
34436fd0130Shoumkh     return PosixTimeval {
34536fd0130Shoumkh         tv_sec: tp.tv_sec,
34636fd0130Shoumkh         tv_usec: (tp.tv_nsec / 1000) as i32,
34736fd0130Shoumkh     };
34836fd0130Shoumkh }
34936fd0130Shoumkh 
do_settimeofday64(time: PosixTimeSpec) -> Result<(), SystemError>3506fc066acSJomo pub fn do_settimeofday64(time: PosixTimeSpec) -> Result<(), SystemError> {
351b8ed3825SDonkey Kane     timekeeper().inner.write_irqsave().xtime = time;
352da152319SLoGin     // todo: 模仿linux,实现时间误差校准。
353da152319SLoGin     // https://code.dragonos.org.cn/xref/linux-6.6.21/kernel/time/timekeeping.c?fi=do_settimeofday64#1312
354da152319SLoGin     return Ok(());
355da152319SLoGin }
356da152319SLoGin 
35736fd0130Shoumkh /// # 初始化timekeeping模块
3585b59005fSLoGin #[inline(never)]
timekeeping_init()35936fd0130Shoumkh pub fn timekeeping_init() {
3602eab6dd7S曾俊     info!("Initializing timekeeping module...");
36136fd0130Shoumkh     let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
36236fd0130Shoumkh     timekeeper_init();
36336fd0130Shoumkh 
36436fd0130Shoumkh     // TODO 有ntp模块后 在此初始化ntp模块
36536fd0130Shoumkh 
36636fd0130Shoumkh     let clock = clocksource_default_clock();
36736fd0130Shoumkh     clock
36836fd0130Shoumkh         .enable()
36936fd0130Shoumkh         .expect("clocksource_default_clock enable failed");
37036fd0130Shoumkh     timekeeper().timekeeper_setup_internals(clock);
37136fd0130Shoumkh     // 暂时不支持其他架构平台对时间的设置 所以使用x86平台对应值初始化
372b8ed3825SDonkey Kane     let mut timekeeper = timekeeper().inner.write_irqsave();
37336fd0130Shoumkh     timekeeper.xtime.tv_nsec = ktime_get_real_ns();
37436fd0130Shoumkh 
375911132c4SDonkey Kane     //参考https://elixir.bootlin.com/linux/v4.4/source/kernel/time/timekeeping.c#L1251 对wtm进行初始化
376911132c4SDonkey Kane     (
377911132c4SDonkey Kane         timekeeper.wall_to_monotonic.tv_nsec,
378911132c4SDonkey Kane         timekeeper.wall_to_monotonic.tv_sec,
379911132c4SDonkey Kane     ) = (-timekeeper.xtime.tv_nsec, -timekeeper.xtime.tv_sec);
38036fd0130Shoumkh 
38136fd0130Shoumkh     drop(irq_guard);
382b8ed3825SDonkey Kane     drop(timekeeper);
3835b59005fSLoGin     jiffies_init();
3842eab6dd7S曾俊     info!("timekeeping_init successfully");
38536fd0130Shoumkh }
38636fd0130Shoumkh 
38736fd0130Shoumkh /// # 使用当前时钟源增加wall time
388*af097f9fS黄铭涛 /// 参考:https://code.dragonos.org.cn/xref/linux-3.4.99/kernel/time/timekeeping.c#1041
update_wall_time()389*af097f9fS黄铭涛 pub fn update_wall_time() {
3902eab6dd7S曾俊     // debug!("enter update_wall_time, stack_use = {:}",stack_use);
39136fd0130Shoumkh     compiler_fence(Ordering::SeqCst);
39236fd0130Shoumkh     let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
39336fd0130Shoumkh     // 如果在休眠那就不更新
39436fd0130Shoumkh     if TIMEKEEPING_SUSPENDED.load(Ordering::SeqCst) {
39536fd0130Shoumkh         return;
39636fd0130Shoumkh     }
39736fd0130Shoumkh 
398*af097f9fS黄铭涛     let mut tk = timekeeper().inner.write_irqsave();
399*af097f9fS黄铭涛     // 获取当前时钟源
400*af097f9fS黄铭涛     let clock = tk.clock.clone().unwrap();
401*af097f9fS黄铭涛     let clock_data = clock.clocksource_data();
402*af097f9fS黄铭涛     // 计算从上一次更新周期以来经过的时钟周期数
403*af097f9fS黄铭涛     let mut offset = (clock.read().div(clock_data.cycle_last).data()) & clock_data.mask.bits();
404*af097f9fS黄铭涛     // 检查offset是否达到了一个NTP周期间隔
405*af097f9fS黄铭涛     if offset < tk.cycle_interval.data() {
406*af097f9fS黄铭涛         return;
40736fd0130Shoumkh     }
408*af097f9fS黄铭涛 
409*af097f9fS黄铭涛     // 将纳秒部分转换为更高精度的格式
410*af097f9fS黄铭涛     tk.xtime_nsec = (tk.xtime.tv_nsec as u64) << tk.shift;
411*af097f9fS黄铭涛 
412*af097f9fS黄铭涛     let mut shift = (offset.ilog2() - tk.cycle_interval.data().ilog2()) as i32;
413*af097f9fS黄铭涛     shift = shift.max(0);
414*af097f9fS黄铭涛     // let max_shift = (64 - (ntp_tick_length().ilog2()+1)) - 1;
415*af097f9fS黄铭涛     // shift = min(shift, max_shift)
416*af097f9fS黄铭涛     while offset >= tk.cycle_interval.data() {
417*af097f9fS黄铭涛         offset = timekeeper().logarithmic_accumulation(offset, shift);
418*af097f9fS黄铭涛         if offset < tk.cycle_interval.data() << shift {
419*af097f9fS黄铭涛             shift -= 1;
42036fd0130Shoumkh         }
42136fd0130Shoumkh     }
422*af097f9fS黄铭涛 
423*af097f9fS黄铭涛     timekeeper().timekeeping_adjust(offset as i64);
424*af097f9fS黄铭涛 
425*af097f9fS黄铭涛     // 处理xtime_nsec下溢问题,并对NTP误差进行调整
426*af097f9fS黄铭涛     if unlikely((tk.xtime_nsec as i64) < 0) {
427*af097f9fS黄铭涛         let neg = -(tk.xtime_nsec as i64);
428*af097f9fS黄铭涛         tk.xtime_nsec = 0;
429*af097f9fS黄铭涛         tk.ntp_error += neg << tk.ntp_error_shift;
430*af097f9fS黄铭涛     }
431*af097f9fS黄铭涛 
432*af097f9fS黄铭涛     // 将纳秒部分舍入后存储在xtime.tv_nsec中
433*af097f9fS黄铭涛     tk.xtime.tv_nsec = ((tk.xtime_nsec as i64) >> tk.shift) + 1;
434*af097f9fS黄铭涛     tk.xtime_nsec -= (tk.xtime.tv_nsec as u64) << tk.shift;
435*af097f9fS黄铭涛 
436*af097f9fS黄铭涛     // 确保经过舍入后的xtime.tv_nsec不会大于NSEC_PER_SEC,并在超过1秒的情况下进行适当的调整
437*af097f9fS黄铭涛     if unlikely(tk.xtime.tv_nsec >= NSEC_PER_SEC.into()) {
438*af097f9fS黄铭涛         tk.xtime.tv_nsec -= NSEC_PER_SEC as i64;
439*af097f9fS黄铭涛         tk.xtime.tv_sec += 1;
440*af097f9fS黄铭涛         // TODO: 处理闰秒
441*af097f9fS黄铭涛     }
442*af097f9fS黄铭涛 
443*af097f9fS黄铭涛     // 更新时间的相关信息
444*af097f9fS黄铭涛     timekeeping_update();
445*af097f9fS黄铭涛 
44636fd0130Shoumkh     compiler_fence(Ordering::SeqCst);
44736fd0130Shoumkh     drop(irq_guard);
44836fd0130Shoumkh     compiler_fence(Ordering::SeqCst);
44936fd0130Shoumkh }
45036fd0130Shoumkh // TODO wall_to_monotic
451*af097f9fS黄铭涛 
452*af097f9fS黄铭涛 /// 参考:https://code.dragonos.org.cn/xref/linux-3.4.99/kernel/time/timekeeping.c#190
timekeeping_update()453*af097f9fS黄铭涛 pub fn timekeeping_update() {
454*af097f9fS黄铭涛     // TODO:如果clearntp为true,则会清除NTP错误并调用ntp_clear()
455*af097f9fS黄铭涛 
456*af097f9fS黄铭涛     // 更新实时时钟偏移量,用于跟踪硬件时钟与系统时间的差异,以便进行时间校正
457*af097f9fS黄铭涛     update_rt_offset();
458*af097f9fS黄铭涛 }
459*af097f9fS黄铭涛 
460*af097f9fS黄铭涛 /// # 更新实时偏移量(墙上之间与单调时间的差值)
update_rt_offset()461*af097f9fS黄铭涛 pub fn update_rt_offset() {
462*af097f9fS黄铭涛     let mut timekeeper = timekeeper().inner.write_irqsave();
463*af097f9fS黄铭涛     let ts = PosixTimeSpec::new(
464*af097f9fS黄铭涛         -timekeeper.wall_to_monotonic.tv_sec,
465*af097f9fS黄铭涛         -timekeeper.wall_to_monotonic.tv_nsec,
466*af097f9fS黄铭涛     );
467*af097f9fS黄铭涛     timekeeper.real_time_offset = timespec_to_ktime(ts);
468*af097f9fS黄铭涛 }
469