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