1 use alloc::sync::Arc;
2 use core::intrinsics::{likely, unlikely};
3 use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
4 use log::{debug, info, warn};
5 use system_error::SystemError;
6
7 use crate::{
8 arch::CurrentIrqArch,
9 exception::InterruptArch,
10 libs::rwlock::RwLock,
11 time::{
12 jiffies::{clocksource_default_clock, jiffies_init},
13 timekeep::ktime_get_real_ns,
14 PosixTimeSpec,
15 },
16 };
17
18 use super::timekeep::{ktime_t, timespec_to_ktime};
19 use super::{
20 clocksource::{clocksource_cyc2ns, Clocksource, CycleNum, HZ},
21 syscall::PosixTimeval,
22 NSEC_PER_SEC,
23 };
24 /// NTP周期频率
25 pub const NTP_INTERVAL_FREQ: u64 = HZ;
26 /// NTP周期长度
27 pub const NTP_INTERVAL_LENGTH: u64 = NSEC_PER_SEC as u64 / NTP_INTERVAL_FREQ;
28 /// NTP转换比例
29 pub const NTP_SCALE_SHIFT: u32 = 32;
30
31 /// timekeeping休眠标志,false为未休眠
32 pub static TIMEKEEPING_SUSPENDED: AtomicBool = AtomicBool::new(false);
33 /// timekeeper全局变量,用于管理timekeeper模块
34 static mut __TIMEKEEPER: Option<Timekeeper> = None;
35
36 #[derive(Debug)]
37 pub struct Timekeeper {
38 inner: RwLock<TimekeeperData>,
39 }
40
41 #[allow(dead_code)]
42 #[derive(Debug)]
43 pub struct TimekeeperData {
44 /// 用于计时的当前时钟源。
45 clock: Option<Arc<dyn Clocksource>>,
46 /// 当前时钟源的移位值。
47 shift: i32,
48 /// 一个NTP间隔中的时钟周期数。
49 cycle_interval: CycleNum,
50 /// 一个NTP间隔中时钟移位的纳秒数。
51 xtime_interval: u64,
52 xtime_remainder: i64,
53 /// 每个NTP间隔累积的原始纳米秒
54 raw_interval: i64,
55 /// 时钟移位纳米秒余数
56 xtime_nsec: u64,
57 /// 积累时间和ntp时间在ntp位移纳秒量上的差距
58 ntp_error: i64,
59 /// 用于转换时钟偏移纳秒和ntp偏移纳秒的偏移量
60 ntp_error_shift: i32,
61 /// NTP调整时钟乘法器
62 mult: u32,
63 raw_time: PosixTimeSpec,
64 wall_to_monotonic: PosixTimeSpec,
65 total_sleep_time: PosixTimeSpec,
66 xtime: PosixTimeSpec,
67 /// 单调时间和实时时间的偏移量
68 real_time_offset: ktime_t,
69 }
70 impl TimekeeperData {
new() -> Self71 pub fn new() -> Self {
72 Self {
73 clock: None,
74 shift: Default::default(),
75 cycle_interval: CycleNum::new(0),
76 xtime_interval: Default::default(),
77 xtime_remainder: Default::default(),
78 raw_interval: Default::default(),
79 xtime_nsec: Default::default(),
80 ntp_error: Default::default(),
81 ntp_error_shift: Default::default(),
82 mult: Default::default(),
83 xtime: PosixTimeSpec {
84 tv_nsec: 0,
85 tv_sec: 0,
86 },
87 wall_to_monotonic: PosixTimeSpec {
88 tv_nsec: 0,
89 tv_sec: 0,
90 },
91 total_sleep_time: PosixTimeSpec {
92 tv_nsec: 0,
93 tv_sec: 0,
94 },
95 raw_time: PosixTimeSpec {
96 tv_nsec: 0,
97 tv_sec: 0,
98 },
99 real_time_offset: 0,
100 }
101 }
102 }
103 impl Timekeeper {
new() -> Self104 fn new() -> Self {
105 Self {
106 inner: RwLock::new(TimekeeperData::new()),
107 }
108 }
109
110 /// # 设置timekeeper的参数
111 ///
112 /// ## 参数
113 ///
114 /// * 'clock' - 指定的时钟实际类型。初始为ClocksourceJiffies
timekeeper_setup_internals(&self, clock: Arc<dyn Clocksource>)115 pub fn timekeeper_setup_internals(&self, clock: Arc<dyn Clocksource>) {
116 let mut timekeeper = self.inner.write_irqsave();
117 // 更新clock
118 let mut clock_data = clock.clocksource_data();
119 clock_data.cycle_last = clock.read();
120 if clock.update_clocksource_data(clock_data).is_err() {
121 debug!("timekeeper_setup_internals:update_clocksource_data run failed");
122 }
123 timekeeper.clock.replace(clock.clone());
124
125 let clock_data = clock.clocksource_data();
126 let mut temp = NTP_INTERVAL_LENGTH << clock_data.shift;
127 let ntpinterval = temp;
128 temp += (clock_data.mult / 2) as u64;
129 // do div
130
131 timekeeper.cycle_interval = CycleNum::new(temp);
132 timekeeper.xtime_interval = temp * clock_data.mult as u64;
133 // 这里可能存在下界溢出问题,debug模式下会报错panic
134 timekeeper.xtime_remainder = (ntpinterval - timekeeper.xtime_interval) as i64;
135 timekeeper.raw_interval = (timekeeper.xtime_interval >> clock_data.shift) as i64;
136 timekeeper.xtime_nsec = 0;
137 timekeeper.shift = clock_data.shift as i32;
138
139 timekeeper.ntp_error = 0;
140 timekeeper.ntp_error_shift = (NTP_SCALE_SHIFT - clock_data.shift) as i32;
141
142 timekeeper.mult = clock_data.mult;
143 }
144
timekeeping_get_ns(&self) -> i64145 pub fn timekeeping_get_ns(&self) -> i64 {
146 let timekeeper = self.inner.read_irqsave();
147 let clock = timekeeper.clock.clone().unwrap();
148
149 let cycle_now = clock.read();
150 let clock_data = clock.clocksource_data();
151 let cycle_delta = (cycle_now.div(clock_data.cycle_last)).data() & clock_data.mask.bits();
152
153 return clocksource_cyc2ns(
154 CycleNum::new(cycle_delta),
155 timekeeper.mult,
156 timekeeper.shift as u32,
157 ) as i64;
158 }
159
160 /// # 处理大幅度调整
timekeeping_bigadjust(&self, error: i64, interval: i64, offset: i64) -> (i64, i64, i32)161 pub fn timekeeping_bigadjust(&self, error: i64, interval: i64, offset: i64) -> (i64, i64, i32) {
162 let mut error = error;
163 let mut interval = interval;
164 let mut offset = offset;
165
166 // TODO: 计算look_head并调整ntp误差
167
168 let tmp = interval;
169 let mut mult = 1;
170 let mut adj = 0;
171 if error < 0 {
172 error = -error;
173 interval = -interval;
174 offset = -offset;
175 mult = -1;
176 }
177 while error > tmp {
178 adj += 1;
179 error >>= 1;
180 }
181
182 interval <<= adj;
183 offset <<= adj;
184 mult <<= adj;
185
186 return (interval, offset, mult);
187 }
188
189 /// # 调整时钟的mult减少ntp_error
timekeeping_adjust(&self, offset: i64) -> i64190 pub fn timekeeping_adjust(&self, offset: i64) -> i64 {
191 let mut timekeeper = self.inner.write_irqsave();
192 let mut interval = timekeeper.cycle_interval.data() as i64;
193 let mut offset = offset;
194 let adj: i32;
195
196 // 计算误差
197 let mut error = timekeeper.ntp_error >> (timekeeper.ntp_error_shift - 1);
198
199 // 误差超过一个interval,就要进行调整
200 if error >= 0 {
201 if error > interval {
202 error >>= 2;
203 if likely(error <= interval) {
204 adj = 1;
205 } else {
206 (interval, offset, adj) = self.timekeeping_bigadjust(error, interval, offset);
207 }
208 } else {
209 // 不需要校准
210 return offset;
211 }
212 } else if -error > interval {
213 if likely(-error <= interval) {
214 adj = -1;
215 interval = -interval;
216 offset = -offset;
217 } else {
218 (interval, offset, adj) = self.timekeeping_bigadjust(error, interval, offset);
219 }
220 } else {
221 // 不需要校准
222 return offset;
223 }
224
225 // 检查最大调整值,确保调整值不会超过时钟源允许的最大值
226 let clock_data = timekeeper.clock.clone().unwrap().clocksource_data();
227 if unlikely(
228 clock_data.maxadj != 0
229 && (timekeeper.mult as i32 + adj
230 > clock_data.mult as i32 + clock_data.maxadj as i32),
231 ) {
232 warn!(
233 "Adjusting {:?} more than ({} vs {})",
234 clock_data.name,
235 timekeeper.mult as i32 + adj,
236 clock_data.mult as i32 + clock_data.maxadj as i32
237 );
238 }
239
240 if error > 0 {
241 timekeeper.mult += adj as u32;
242 timekeeper.xtime_interval += interval as u64;
243 timekeeper.xtime_nsec -= offset as u64;
244 } else {
245 timekeeper.mult -= adj as u32;
246 timekeeper.xtime_interval -= interval as u64;
247 timekeeper.xtime_nsec += offset as u64;
248 }
249 timekeeper.ntp_error -= (interval - offset) << timekeeper.ntp_error_shift;
250
251 return offset;
252 }
253 /// # 用于累积时间间隔,并将其转换为纳秒时间
logarithmic_accumulation(&self, offset: u64, shift: i32) -> u64254 pub fn logarithmic_accumulation(&self, offset: u64, shift: i32) -> u64 {
255 let mut timekeeper = self.inner.write_irqsave();
256 let clock = timekeeper.clock.clone().unwrap();
257 let clock_data = clock.clocksource_data();
258 let nsecps = (NSEC_PER_SEC as u64) << timekeeper.shift;
259 let mut offset = offset;
260
261 // 检查offset是否小于一个NTP周期间隔
262 if offset < timekeeper.cycle_interval.data() << shift {
263 return offset;
264 }
265
266 // 累积一个移位的interval
267 offset -= timekeeper.cycle_interval.data() << shift;
268 clock_data
269 .cycle_last
270 .add(CycleNum::new(timekeeper.cycle_interval.data() << shift));
271 if clock.update_clocksource_data(clock_data).is_err() {
272 debug!("logarithmic_accumulation:update_clocksource_data run failed");
273 }
274 timekeeper.clock.replace(clock.clone());
275
276 // 更新xime_nsec
277 timekeeper.xtime_nsec += timekeeper.xtime_interval << shift;
278 while timekeeper.xtime_nsec >= nsecps {
279 timekeeper.xtime_nsec -= nsecps;
280 timekeeper.xtime.tv_sec += 1;
281 // TODO: 处理闰秒
282 }
283
284 // TODO:更新raw_time
285
286 // TODO:计算ntp_error
287
288 return offset;
289 }
290 }
291
292 #[inline(always)]
timekeeper() -> &'static Timekeeper293 pub fn timekeeper() -> &'static Timekeeper {
294 let r = unsafe { __TIMEKEEPER.as_ref().unwrap() };
295
296 return r;
297 }
298
timekeeper_init()299 pub fn timekeeper_init() {
300 unsafe { __TIMEKEEPER = Some(Timekeeper::new()) };
301 }
302
303 /// # 获取1970.1.1至今的UTC时间戳(最小单位:nsec)
304 ///
305 /// ## 返回值
306 ///
307 /// * 'TimeSpec' - 时间戳
getnstimeofday() -> PosixTimeSpec308 pub fn getnstimeofday() -> PosixTimeSpec {
309 // debug!("enter getnstimeofday");
310
311 let nsecs;
312 let mut xtime: PosixTimeSpec;
313 loop {
314 match timekeeper().inner.try_read_irqsave() {
315 None => continue,
316 Some(tk) => {
317 xtime = tk.xtime;
318 drop(tk);
319
320 nsecs = timekeeper().timekeeping_get_ns();
321
322 // TODO 不同架构可能需要加上不同的偏移量
323 break;
324 }
325 }
326 }
327 xtime.tv_nsec += nsecs;
328 xtime.tv_sec += xtime.tv_nsec / NSEC_PER_SEC as i64;
329 xtime.tv_nsec %= NSEC_PER_SEC as i64;
330 // debug!("getnstimeofday: xtime = {:?}, nsecs = {:}", xtime, nsecs);
331
332 // TODO 将xtime和当前时间源的时间相加
333
334 return xtime;
335 }
336
337 /// # 获取1970.1.1至今的UTC时间戳(最小单位:usec)
338 ///
339 /// ## 返回值
340 ///
341 /// * 'PosixTimeval' - 时间戳
do_gettimeofday() -> PosixTimeval342 pub fn do_gettimeofday() -> PosixTimeval {
343 let tp = getnstimeofday();
344 return PosixTimeval {
345 tv_sec: tp.tv_sec,
346 tv_usec: (tp.tv_nsec / 1000) as i32,
347 };
348 }
349
do_settimeofday64(time: PosixTimeSpec) -> Result<(), SystemError>350 pub fn do_settimeofday64(time: PosixTimeSpec) -> Result<(), SystemError> {
351 timekeeper().inner.write_irqsave().xtime = time;
352 // todo: 模仿linux,实现时间误差校准。
353 // https://code.dragonos.org.cn/xref/linux-6.6.21/kernel/time/timekeeping.c?fi=do_settimeofday64#1312
354 return Ok(());
355 }
356
357 /// # 初始化timekeeping模块
358 #[inline(never)]
timekeeping_init()359 pub fn timekeeping_init() {
360 info!("Initializing timekeeping module...");
361 let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
362 timekeeper_init();
363
364 // TODO 有ntp模块后 在此初始化ntp模块
365
366 let clock = clocksource_default_clock();
367 clock
368 .enable()
369 .expect("clocksource_default_clock enable failed");
370 timekeeper().timekeeper_setup_internals(clock);
371 // 暂时不支持其他架构平台对时间的设置 所以使用x86平台对应值初始化
372 let mut timekeeper = timekeeper().inner.write_irqsave();
373 timekeeper.xtime.tv_nsec = ktime_get_real_ns();
374
375 //参考https://elixir.bootlin.com/linux/v4.4/source/kernel/time/timekeeping.c#L1251 对wtm进行初始化
376 (
377 timekeeper.wall_to_monotonic.tv_nsec,
378 timekeeper.wall_to_monotonic.tv_sec,
379 ) = (-timekeeper.xtime.tv_nsec, -timekeeper.xtime.tv_sec);
380
381 drop(irq_guard);
382 drop(timekeeper);
383 jiffies_init();
384 info!("timekeeping_init successfully");
385 }
386
387 /// # 使用当前时钟源增加wall time
388 /// 参考:https://code.dragonos.org.cn/xref/linux-3.4.99/kernel/time/timekeeping.c#1041
update_wall_time()389 pub fn update_wall_time() {
390 // debug!("enter update_wall_time, stack_use = {:}",stack_use);
391 compiler_fence(Ordering::SeqCst);
392 let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
393 // 如果在休眠那就不更新
394 if TIMEKEEPING_SUSPENDED.load(Ordering::SeqCst) {
395 return;
396 }
397
398 let mut tk = timekeeper().inner.write_irqsave();
399 // 获取当前时钟源
400 let clock = tk.clock.clone().unwrap();
401 let clock_data = clock.clocksource_data();
402 // 计算从上一次更新周期以来经过的时钟周期数
403 let mut offset = (clock.read().div(clock_data.cycle_last).data()) & clock_data.mask.bits();
404 // 检查offset是否达到了一个NTP周期间隔
405 if offset < tk.cycle_interval.data() {
406 return;
407 }
408
409 // 将纳秒部分转换为更高精度的格式
410 tk.xtime_nsec = (tk.xtime.tv_nsec as u64) << tk.shift;
411
412 let mut shift = (offset.ilog2() - tk.cycle_interval.data().ilog2()) as i32;
413 shift = shift.max(0);
414 // let max_shift = (64 - (ntp_tick_length().ilog2()+1)) - 1;
415 // shift = min(shift, max_shift)
416 while offset >= tk.cycle_interval.data() {
417 offset = timekeeper().logarithmic_accumulation(offset, shift);
418 if offset < tk.cycle_interval.data() << shift {
419 shift -= 1;
420 }
421 }
422
423 timekeeper().timekeeping_adjust(offset as i64);
424
425 // 处理xtime_nsec下溢问题,并对NTP误差进行调整
426 if unlikely((tk.xtime_nsec as i64) < 0) {
427 let neg = -(tk.xtime_nsec as i64);
428 tk.xtime_nsec = 0;
429 tk.ntp_error += neg << tk.ntp_error_shift;
430 }
431
432 // 将纳秒部分舍入后存储在xtime.tv_nsec中
433 tk.xtime.tv_nsec = ((tk.xtime_nsec as i64) >> tk.shift) + 1;
434 tk.xtime_nsec -= (tk.xtime.tv_nsec as u64) << tk.shift;
435
436 // 确保经过舍入后的xtime.tv_nsec不会大于NSEC_PER_SEC,并在超过1秒的情况下进行适当的调整
437 if unlikely(tk.xtime.tv_nsec >= NSEC_PER_SEC.into()) {
438 tk.xtime.tv_nsec -= NSEC_PER_SEC as i64;
439 tk.xtime.tv_sec += 1;
440 // TODO: 处理闰秒
441 }
442
443 // 更新时间的相关信息
444 timekeeping_update();
445
446 compiler_fence(Ordering::SeqCst);
447 drop(irq_guard);
448 compiler_fence(Ordering::SeqCst);
449 }
450 // TODO wall_to_monotic
451
452 /// 参考:https://code.dragonos.org.cn/xref/linux-3.4.99/kernel/time/timekeeping.c#190
timekeeping_update()453 pub fn timekeeping_update() {
454 // TODO:如果clearntp为true,则会清除NTP错误并调用ntp_clear()
455
456 // 更新实时时钟偏移量,用于跟踪硬件时钟与系统时间的差异,以便进行时间校正
457 update_rt_offset();
458 }
459
460 /// # 更新实时偏移量(墙上之间与单调时间的差值)
update_rt_offset()461 pub fn update_rt_offset() {
462 let mut timekeeper = timekeeper().inner.write_irqsave();
463 let ts = PosixTimeSpec::new(
464 -timekeeper.wall_to_monotonic.tv_sec,
465 -timekeeper.wall_to_monotonic.tv_nsec,
466 );
467 timekeeper.real_time_offset = timespec_to_ktime(ts);
468 }
469