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 {
new() -> Self66 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
timekeeper_setup_internals(&self, clock: Arc<dyn Clocksource>)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)]
tk_get_ns(&self) -> u64135 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 }
timekeeper() -> &'static Timekeeper144 pub fn timekeeper() -> &'static Timekeeper {
145 return unsafe { __TIMEKEEPER.as_ref().unwrap() };
146 }
147
timekeeper_init()148 pub fn timekeeper_init() {
149 unsafe { __TIMEKEEPER = Some(Timekeeper(RwLock::new(TimekeeperData::new()))) };
150 }
151
152 /// # 获取1970.1.1至今的UTC时间戳(最小单位:nsec)
153 ///
154 /// ## 返回值
155 ///
156 /// * 'TimeSpec' - 时间戳
getnstimeofday() -> TimeSpec157 pub fn getnstimeofday() -> TimeSpec {
158 // kdebug!("enter getnstimeofday");
159
160 // let mut nsecs: u64 = 0;0
161 let mut _xtime = TimeSpec {
162 tv_nsec: 0,
163 tv_sec: 0,
164 };
165 loop {
166 match timekeeper().0.try_read() {
167 None => continue,
168 Some(tk) => {
169 _xtime = tk.xtime;
170 drop(tk);
171 // nsecs = timekeeper().tk_get_ns();
172 // TODO 不同架构可能需要加上不同的偏移量
173 break;
174 }
175 }
176 }
177 // xtime.tv_nsec += nsecs as i64;
178 let sec = __ADDED_SEC.load(Ordering::SeqCst);
179 _xtime.tv_sec += sec;
180 while _xtime.tv_nsec >= NSEC_PER_SEC.into() {
181 _xtime.tv_nsec -= NSEC_PER_SEC as i64;
182 _xtime.tv_sec += 1;
183 }
184
185 // TODO 将xtime和当前时间源的时间相加
186
187 return _xtime;
188 }
189
190 /// # 获取1970.1.1至今的UTC时间戳(最小单位:usec)
191 ///
192 /// ## 返回值
193 ///
194 /// * 'PosixTimeval' - 时间戳
do_gettimeofday() -> PosixTimeval195 pub fn do_gettimeofday() -> PosixTimeval {
196 let tp = getnstimeofday();
197 return PosixTimeval {
198 tv_sec: tp.tv_sec,
199 tv_usec: (tp.tv_nsec / 1000) as i32,
200 };
201 }
202
203 /// # 初始化timekeeping模块
timekeeping_init()204 pub fn timekeeping_init() {
205 kinfo!("Initializing timekeeping module...");
206 let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
207 timekeeper_init();
208
209 // TODO 有ntp模块后 在此初始化ntp模块
210
211 let clock = clocksource_default_clock();
212 clock
213 .enable()
214 .expect("clocksource_default_clock enable failed");
215 timekeeper().timekeeper_setup_internals(clock);
216 // 暂时不支持其他架构平台对时间的设置 所以使用x86平台对应值初始化
217 let mut timekeeper = timekeeper().0.write();
218 timekeeper.xtime.tv_nsec = ktime_get_real_ns();
219
220 // 初始化wall time到monotonic的时间
221 let mut nsec = -timekeeper.xtime.tv_nsec;
222 let mut sec = -timekeeper.xtime.tv_sec;
223 // FIXME: 这里有个奇怪的奇怪的bug
224 let num = nsec % NSEC_PER_SEC as i64;
225 nsec += num * NSEC_PER_SEC as i64;
226 sec -= num;
227 timekeeper.wall_to_monotonic.tv_nsec = nsec;
228 timekeeper.wall_to_monotonic.tv_sec = sec;
229
230 __ADDED_USEC.store(0, Ordering::SeqCst);
231 __ADDED_SEC.store(0, Ordering::SeqCst);
232
233 drop(irq_guard);
234 kinfo!("timekeeping_init successfully");
235 }
236
237 /// # 使用当前时钟源增加wall time
update_wall_time()238 pub fn update_wall_time() {
239 let rsp = unsafe { crate::include::bindings::bindings::get_rsp() } as usize;
240 let _stack_use = align_up(rsp as u64, 32768) - rsp as u64;
241
242 // kdebug!("enter update_wall_time, stack_use = {:}",stack_use);
243 compiler_fence(Ordering::SeqCst);
244 let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
245 // 如果在休眠那就不更新
246 if TIMEKEEPING_SUSPENDED.load(Ordering::SeqCst) {
247 return;
248 }
249
250 // ===== 请不要删除这些注释 =====
251 // let clock = timekeeper.clock.clone().unwrap();
252 // let clock_data = clock.clocksource_data();
253 // let offset = (clock.read().div(clock_data.watchdog_last).data()) & clock_data.mask.bits();
254
255 // timekeeper.xtime_nsec = (timekeeper.xtime.tv_nsec as u64) << timekeeper.shift;
256 // // TODO 当有ntp模块之后 需要将timekeep与ntp进行同步并检查
257 // timekeeper.xtime.tv_nsec = ((timekeeper.xtime_nsec as i64) >> timekeeper.shift) + 1;
258 // timekeeper.xtime_nsec -= (timekeeper.xtime.tv_nsec as u64) << timekeeper.shift;
259
260 // timekeeper.xtime.tv_nsec += offset as i64;
261 // while unlikely(timekeeper.xtime.tv_nsec >= NSEC_PER_SEC.into()) {
262 // timekeeper.xtime.tv_nsec -= NSEC_PER_SEC as i64;
263 // timekeeper.xtime.tv_sec += 1;
264 // // TODO 需要处理闰秒
265 // }
266 // ================
267 compiler_fence(Ordering::SeqCst);
268 // 一分钟同步一次
269 __ADDED_USEC.fetch_add(500, Ordering::SeqCst);
270 compiler_fence(Ordering::SeqCst);
271 let mut retry = 10;
272
273 let usec = __ADDED_USEC.load(Ordering::SeqCst);
274 if usec % USEC_PER_SEC as i64 == 0 {
275 compiler_fence(Ordering::SeqCst);
276
277 __ADDED_SEC.fetch_add(1, Ordering::SeqCst);
278 compiler_fence(Ordering::SeqCst);
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();
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]
rs_timekeeping_init()312 pub extern "C" fn rs_timekeeping_init() {
313 timekeeping_init();
314 }
315