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 { 71 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 { 104 fn new() -> Self { 105 Self { 106 inner: RwLock::new(TimekeeperData::new()), 107 } 108 } 109 110 /// # 设置timekeeper的参数 111 /// 112 /// ## 参数 113 /// 114 /// * 'clock' - 指定的时钟实际类型。初始为ClocksourceJiffies 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 145 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 /// # 处理大幅度调整 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 190 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 /// # 用于累积时间间隔,并将其转换为纳秒时间 254 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)] 293 pub fn timekeeper() -> &'static Timekeeper { 294 let r = unsafe { __TIMEKEEPER.as_ref().unwrap() }; 295 296 return r; 297 } 298 299 pub fn timekeeper_init() { 300 unsafe { __TIMEKEEPER = Some(Timekeeper::new()) }; 301 } 302 303 /// # 获取1970.1.1至今的UTC时间戳(最小单位:nsec) 304 /// 305 /// ## 返回值 306 /// 307 /// * 'TimeSpec' - 时间戳 308 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' - 时间戳 342 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 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)] 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 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 453 pub fn timekeeping_update() { 454 // TODO:如果clearntp为true,则会清除NTP错误并调用ntp_clear() 455 456 // 更新实时时钟偏移量,用于跟踪硬件时钟与系统时间的差异,以便进行时间校正 457 update_rt_offset(); 458 } 459 460 /// # 更新实时偏移量(墙上之间与单调时间的差值) 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