xref: /DragonOS/kernel/src/time/timekeeping.rs (revision edaf015400f83967c2fc940f07be0dbb5792246f)
1 use alloc::sync::Arc;
2 use core::sync::atomic::{compiler_fence, AtomicBool, AtomicI64, Ordering};
3 
4 use crate::{
5     arch::CurrentIrqArch,
6     exception::InterruptArch,
7     kdebug, kinfo,
8     libs::rwlock::RwLock,
9     time::{jiffies::clocksource_default_clock, timekeep::ktime_get_real_ns, TimeSpec},
10 };
11 
12 use super::{
13     clocksource::{clocksource_cyc2ns, Clocksource, CycleNum, HZ},
14     syscall::PosixTimeval,
15     NSEC_PER_SEC, USEC_PER_SEC,
16 };
17 /// NTP周期频率
18 pub const NTP_INTERVAL_FREQ: u64 = HZ;
19 /// NTP周期长度
20 pub const NTP_INTERVAL_LENGTH: u64 = NSEC_PER_SEC as u64 / NTP_INTERVAL_FREQ;
21 /// NTP转换比例
22 pub const NTP_SCALE_SHIFT: u32 = 32;
23 
24 /// timekeeping休眠标志,false为未休眠
25 pub static TIMEKEEPING_SUSPENDED: AtomicBool = AtomicBool::new(false);
26 /// 已经递增的微秒数
27 static __ADDED_USEC: AtomicI64 = AtomicI64::new(0);
28 /// 已经递增的秒数
29 static __ADDED_SEC: AtomicI64 = AtomicI64::new(0);
30 /// timekeeper全局变量,用于管理timekeeper模块
31 static mut __TIMEKEEPER: Option<Timekeeper> = None;
32 
33 #[derive(Debug)]
34 pub struct Timekeeper(RwLock<TimekeeperData>);
35 
36 #[allow(dead_code)]
37 #[derive(Debug)]
38 pub struct TimekeeperData {
39     /// 用于计时的当前时钟源。
40     clock: Option<Arc<dyn Clocksource>>,
41     /// 当前时钟源的移位值。
42     shift: i32,
43     /// 一个NTP间隔中的时钟周期数。
44     cycle_interval: CycleNum,
45     /// 一个NTP间隔中时钟移位的纳秒数。
46     xtime_interval: u64,
47     ///
48     xtime_remainder: i64,
49     /// 每个NTP间隔累积的原始纳米秒
50     raw_interval: i64,
51     /// 时钟移位纳米秒余数
52     xtime_nsec: u64,
53     /// 积累时间和ntp时间在ntp位移纳秒量上的差距
54     ntp_error: i64,
55     /// 用于转换时钟偏移纳秒和ntp偏移纳秒的偏移量
56     ntp_error_shift: i32,
57     /// NTP调整时钟乘法器
58     mult: u32,
59     raw_time: TimeSpec,
60     wall_to_monotonic: TimeSpec,
61     total_sleep_time: TimeSpec,
62     xtime: TimeSpec,
63 }
64 impl TimekeeperData {
65     pub fn new() -> Self {
66         Self {
67             clock: None,
68             shift: Default::default(),
69             cycle_interval: CycleNum(0),
70             xtime_interval: Default::default(),
71             xtime_remainder: Default::default(),
72             raw_interval: Default::default(),
73             xtime_nsec: Default::default(),
74             ntp_error: Default::default(),
75             ntp_error_shift: Default::default(),
76             mult: Default::default(),
77             xtime: TimeSpec {
78                 tv_nsec: 0,
79                 tv_sec: 0,
80             },
81             wall_to_monotonic: TimeSpec {
82                 tv_nsec: 0,
83                 tv_sec: 0,
84             },
85             total_sleep_time: TimeSpec {
86                 tv_nsec: 0,
87                 tv_sec: 0,
88             },
89             raw_time: TimeSpec {
90                 tv_nsec: 0,
91                 tv_sec: 0,
92             },
93         }
94     }
95 }
96 impl Timekeeper {
97     /// # 设置timekeeper的参数
98     ///
99     /// ## 参数
100     ///
101     /// * 'clock' - 指定的时钟实际类型。初始为ClocksourceJiffies
102     pub fn timekeeper_setup_internals(&self, clock: Arc<dyn Clocksource>) {
103         let mut timekeeper = self.0.write();
104         // 更新clock
105         let mut clock_data = clock.clocksource_data();
106         clock_data.watchdog_last = clock.read();
107         if clock.update_clocksource_data(clock_data).is_err() {
108             kdebug!("timekeeper_setup_internals:update_clocksource_data run failed");
109         }
110         timekeeper.clock.replace(clock.clone());
111 
112         let clock_data = clock.clocksource_data();
113         let mut temp = NTP_INTERVAL_LENGTH << clock_data.shift;
114         let ntpinterval = temp;
115         temp += (clock_data.mult / 2) as u64;
116         // do div
117 
118         timekeeper.cycle_interval = CycleNum(temp);
119         timekeeper.xtime_interval = temp * clock_data.mult as u64;
120         // 这里可能存在下界溢出问题,debug模式下会报错panic
121         timekeeper.xtime_remainder = (ntpinterval - timekeeper.xtime_interval) as i64;
122         timekeeper.raw_interval = (timekeeper.xtime_interval >> clock_data.shift) as i64;
123         timekeeper.xtime_nsec = 0;
124         timekeeper.shift = clock_data.shift as i32;
125 
126         timekeeper.ntp_error = 0;
127         timekeeper.ntp_error_shift = (NTP_SCALE_SHIFT - clock_data.shift) as i32;
128 
129         timekeeper.mult = clock_data.mult;
130     }
131 
132     /// # 获取当前时钟源距离上次检测走过的纳秒数
133     #[allow(dead_code)]
134     pub fn tk_get_ns(&self) -> u64 {
135         let timekeeper = self.0.read();
136         let clock = timekeeper.clock.clone().unwrap();
137         let clock_now = clock.read();
138         let clcok_data = clock.clocksource_data();
139         let clock_delta = clock_now.div(clcok_data.watchdog_last).data() & clcok_data.mask.bits();
140         return clocksource_cyc2ns(CycleNum(clock_delta), clcok_data.mult, clcok_data.shift);
141     }
142 }
143 pub fn timekeeper() -> &'static Timekeeper {
144     let r = unsafe { __TIMEKEEPER.as_ref().unwrap() };
145 
146     return r;
147 }
148 
149 pub fn timekeeper_init() {
150     unsafe { __TIMEKEEPER = Some(Timekeeper(RwLock::new(TimekeeperData::new()))) };
151 }
152 
153 /// # 获取1970.1.1至今的UTC时间戳(最小单位:nsec)
154 ///
155 /// ## 返回值
156 ///
157 /// * 'TimeSpec' - 时间戳
158 pub fn getnstimeofday() -> TimeSpec {
159     // kdebug!("enter getnstimeofday");
160 
161     // let mut nsecs: u64 = 0;0
162     let mut _xtime = TimeSpec {
163         tv_nsec: 0,
164         tv_sec: 0,
165     };
166     loop {
167         match timekeeper().0.try_read() {
168             None => continue,
169             Some(tk) => {
170                 _xtime = tk.xtime;
171                 drop(tk);
172                 // nsecs = timekeeper().tk_get_ns();
173                 // TODO 不同架构可能需要加上不同的偏移量
174                 break;
175             }
176         }
177     }
178     // xtime.tv_nsec += nsecs as i64;
179     let sec = __ADDED_SEC.load(Ordering::SeqCst);
180     _xtime.tv_sec += sec;
181     while _xtime.tv_nsec >= NSEC_PER_SEC.into() {
182         _xtime.tv_nsec -= NSEC_PER_SEC as i64;
183         _xtime.tv_sec += 1;
184     }
185 
186     // TODO 将xtime和当前时间源的时间相加
187 
188     return _xtime;
189 }
190 
191 /// # 获取1970.1.1至今的UTC时间戳(最小单位:usec)
192 ///
193 /// ## 返回值
194 ///
195 /// * 'PosixTimeval' - 时间戳
196 pub fn do_gettimeofday() -> PosixTimeval {
197     let tp = getnstimeofday();
198     return PosixTimeval {
199         tv_sec: tp.tv_sec,
200         tv_usec: (tp.tv_nsec / 1000) as i32,
201     };
202 }
203 
204 /// # 初始化timekeeping模块
205 pub fn timekeeping_init() {
206     kinfo!("Initializing timekeeping module...");
207     let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
208     timekeeper_init();
209 
210     // TODO 有ntp模块后 在此初始化ntp模块
211 
212     let clock = clocksource_default_clock();
213     clock
214         .enable()
215         .expect("clocksource_default_clock enable failed");
216     timekeeper().timekeeper_setup_internals(clock);
217     // 暂时不支持其他架构平台对时间的设置 所以使用x86平台对应值初始化
218     let mut timekeeper = timekeeper().0.write();
219     timekeeper.xtime.tv_nsec = ktime_get_real_ns();
220 
221     // 初始化wall time到monotonic的时间
222     let mut nsec = -timekeeper.xtime.tv_nsec;
223     let mut sec = -timekeeper.xtime.tv_sec;
224     // FIXME: 这里有个奇怪的奇怪的bug
225     let num = nsec % NSEC_PER_SEC as i64;
226     nsec += num * NSEC_PER_SEC as i64;
227     sec -= num;
228     timekeeper.wall_to_monotonic.tv_nsec = nsec;
229     timekeeper.wall_to_monotonic.tv_sec = sec;
230 
231     __ADDED_USEC.store(0, Ordering::SeqCst);
232     __ADDED_SEC.store(0, Ordering::SeqCst);
233 
234     drop(irq_guard);
235     kinfo!("timekeeping_init successfully");
236 }
237 
238 /// # 使用当前时钟源增加wall time
239 pub fn update_wall_time() {
240     // kdebug!("enter update_wall_time, stack_use = {:}",stack_use);
241     compiler_fence(Ordering::SeqCst);
242     let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
243     // 如果在休眠那就不更新
244     if TIMEKEEPING_SUSPENDED.load(Ordering::SeqCst) {
245         return;
246     }
247 
248     // ===== 请不要删除这些注释 =====
249     // let clock = timekeeper.clock.clone().unwrap();
250     // let clock_data = clock.clocksource_data();
251     // let offset = (clock.read().div(clock_data.watchdog_last).data()) & clock_data.mask.bits();
252 
253     // timekeeper.xtime_nsec = (timekeeper.xtime.tv_nsec as u64) << timekeeper.shift;
254     // // TODO 当有ntp模块之后 需要将timekeep与ntp进行同步并检查
255     // timekeeper.xtime.tv_nsec = ((timekeeper.xtime_nsec as i64) >> timekeeper.shift) + 1;
256     // timekeeper.xtime_nsec -= (timekeeper.xtime.tv_nsec as u64) << timekeeper.shift;
257 
258     // timekeeper.xtime.tv_nsec += offset as i64;
259     // while unlikely(timekeeper.xtime.tv_nsec >= NSEC_PER_SEC.into()) {
260     //     timekeeper.xtime.tv_nsec -= NSEC_PER_SEC as i64;
261     //     timekeeper.xtime.tv_sec += 1;
262     //     // TODO 需要处理闰秒
263     // }
264     // ================
265     compiler_fence(Ordering::SeqCst);
266 
267     // !!! todo: 这里是硬编码了HPET的500us中断,需要修改
268     __ADDED_USEC.fetch_add(500, Ordering::SeqCst);
269     compiler_fence(Ordering::SeqCst);
270     let mut retry = 10;
271 
272     let usec = __ADDED_USEC.load(Ordering::SeqCst);
273     if usec % USEC_PER_SEC as i64 == 0 {
274         compiler_fence(Ordering::SeqCst);
275 
276         __ADDED_SEC.fetch_add(1, Ordering::SeqCst);
277         compiler_fence(Ordering::SeqCst);
278     }
279     // 一分钟同步一次
280     loop {
281         if (usec & !((1 << 26) - 1)) != 0 {
282             if __ADDED_USEC
283                 .compare_exchange(usec, 0, Ordering::SeqCst, Ordering::SeqCst)
284                 .is_ok()
285                 || retry == 0
286             {
287                 // 同步时间
288                 // 我感觉这里会出问题:多个读者不退出的话,写者就无法写入
289                 // 然后这里会超时,导致在中断返回之后,会不断的进入这个中断,最终爆栈。
290                 let mut timekeeper = timekeeper().0.write_irqsave();
291                 timekeeper.xtime.tv_nsec = ktime_get_real_ns();
292                 timekeeper.xtime.tv_sec = 0;
293                 __ADDED_SEC.store(0, Ordering::SeqCst);
294                 drop(timekeeper);
295                 break;
296             }
297             retry -= 1;
298         } else {
299             break;
300         }
301     }
302     // TODO 需要检查是否更新时间源
303     compiler_fence(Ordering::SeqCst);
304     drop(irq_guard);
305     compiler_fence(Ordering::SeqCst);
306 }
307 // TODO timekeeping_adjust
308 // TODO wall_to_monotic
309 
310 // ========= 以下为对C的接口 =========
311 #[no_mangle]
312 pub extern "C" fn rs_timekeeping_init() {
313     timekeeping_init();
314 }
315