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