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