timekeeping.rs 15 KB

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