136fd0130Shoumkh use core::{
236fd0130Shoumkh fmt::Debug,
336fd0130Shoumkh sync::atomic::{AtomicBool, Ordering},
436fd0130Shoumkh };
536fd0130Shoumkh
6b8ed3825SDonkey Kane use alloc::{
7b8ed3825SDonkey Kane boxed::Box,
8b8ed3825SDonkey Kane collections::LinkedList,
9b8ed3825SDonkey Kane string::{String, ToString},
10b8ed3825SDonkey Kane sync::Arc,
11b8ed3825SDonkey Kane vec::Vec,
12b8ed3825SDonkey Kane };
1336fd0130Shoumkh use lazy_static::__Deref;
142eab6dd7S曾俊 use log::{debug, info};
1591e9d4abSLoGin use system_error::SystemError;
16b8ed3825SDonkey Kane use unified_init::macros::unified_init;
1736fd0130Shoumkh
1836fd0130Shoumkh use crate::{
19f0c87a89SGnoCiYeH arch::CurrentIrqArch,
20b8ed3825SDonkey Kane exception::InterruptArch,
21b8ed3825SDonkey Kane init::initcall::INITCALL_LATE,
22b8ed3825SDonkey Kane libs::spinlock::SpinLock,
23b8ed3825SDonkey Kane process::{
24b8ed3825SDonkey Kane kthread::{KernelThreadClosure, KernelThreadMechanism},
25b8ed3825SDonkey Kane ProcessControlBlock, ProcessManager,
26b8ed3825SDonkey Kane },
27f0c87a89SGnoCiYeH sched::{schedule, SchedMode},
2836fd0130Shoumkh };
2936fd0130Shoumkh
3036fd0130Shoumkh use super::{
3136fd0130Shoumkh jiffies::clocksource_default_clock,
3236fd0130Shoumkh timer::{clock, Timer, TimerFunction},
33dd8e74efSMingtao Huang NSEC_PER_SEC, NSEC_PER_USEC,
3436fd0130Shoumkh };
3536fd0130Shoumkh
3636fd0130Shoumkh lazy_static! {
3736fd0130Shoumkh /// linked list with the registered clocksources
3836fd0130Shoumkh pub static ref CLOCKSOURCE_LIST: SpinLock<LinkedList<Arc<dyn Clocksource>>> =
3936fd0130Shoumkh SpinLock::new(LinkedList::new());
4036fd0130Shoumkh /// 被监视中的时钟源
4136fd0130Shoumkh pub static ref WATCHDOG_LIST: SpinLock<LinkedList<Arc<dyn Clocksource>>> =
4236fd0130Shoumkh SpinLock::new(LinkedList::new());
4336fd0130Shoumkh
44af097f9fS黄铭涛 pub static ref CLOCKSOURCE_WATCHDOG:SpinLock<ClocksouceWatchdog> = SpinLock::new(ClocksouceWatchdog::new());
4536fd0130Shoumkh
4636fd0130Shoumkh pub static ref OVERRIDE_NAME: SpinLock<String> = SpinLock::new(String::from(""));
4736fd0130Shoumkh
4836fd0130Shoumkh
4936fd0130Shoumkh }
5036fd0130Shoumkh
51b8ed3825SDonkey Kane static mut WATCHDOG_KTHREAD: Option<Arc<ProcessControlBlock>> = None;
52b8ed3825SDonkey Kane
5336fd0130Shoumkh /// 正在被使用时钟源
5436fd0130Shoumkh pub static CUR_CLOCKSOURCE: SpinLock<Option<Arc<dyn Clocksource>>> = SpinLock::new(None);
5536fd0130Shoumkh /// 是否完成加载
5692deae63SLoGin pub static FINISHED_BOOTING: AtomicBool = AtomicBool::new(false);
5736fd0130Shoumkh
5836fd0130Shoumkh /// Interval: 0.5sec Threshold: 0.0625s
5936fd0130Shoumkh /// 系统节拍率
60be8cdf4bSLoGin pub const HZ: u64 = 250;
61dd8e74efSMingtao Huang // 参考:https://code.dragonos.org.cn/xref/linux-6.6.21/kernel/time/clocksource.c#101
6236fd0130Shoumkh /// watchdog检查间隔
6336fd0130Shoumkh pub const WATCHDOG_INTERVAL: u64 = HZ >> 1;
64dd8e74efSMingtao Huang // 参考:https://code.dragonos.org.cn/xref/linux-6.6.21/kernel/time/clocksource.c#108
6536fd0130Shoumkh /// 最大能接受的误差大小
6636fd0130Shoumkh pub const WATCHDOG_THRESHOLD: u32 = NSEC_PER_SEC >> 4;
6736fd0130Shoumkh
68dd8e74efSMingtao Huang pub const MAX_SKEW_USEC: u64 = 125 * WATCHDOG_INTERVAL / HZ;
69dd8e74efSMingtao Huang pub const WATCHDOG_MAX_SKEW: u32 = MAX_SKEW_USEC as u32 * NSEC_PER_USEC;
70dd8e74efSMingtao Huang
7136fd0130Shoumkh // 时钟周期数
7236fd0130Shoumkh #[derive(Debug, Clone, Copy)]
73b8ed3825SDonkey Kane pub struct CycleNum(u64);
7436fd0130Shoumkh
7536fd0130Shoumkh #[allow(dead_code)]
7636fd0130Shoumkh impl CycleNum {
7736fd0130Shoumkh #[inline(always)]
new(cycle: u64) -> Self78b8ed3825SDonkey Kane pub const fn new(cycle: u64) -> Self {
7936fd0130Shoumkh Self(cycle)
8036fd0130Shoumkh }
8136fd0130Shoumkh #[inline(always)]
data(&self) -> u6482b8ed3825SDonkey Kane pub const fn data(&self) -> u64 {
8336fd0130Shoumkh self.0
8436fd0130Shoumkh }
8536fd0130Shoumkh #[inline(always)]
8636fd0130Shoumkh #[allow(dead_code)]
add(&self, other: CycleNum) -> CycleNum8736fd0130Shoumkh pub fn add(&self, other: CycleNum) -> CycleNum {
8836fd0130Shoumkh CycleNum(self.data() + other.data())
8936fd0130Shoumkh }
9036fd0130Shoumkh #[inline(always)]
div(&self, other: CycleNum) -> CycleNum9136fd0130Shoumkh pub fn div(&self, other: CycleNum) -> CycleNum {
9236fd0130Shoumkh CycleNum(self.data() - other.data())
9336fd0130Shoumkh }
9436fd0130Shoumkh }
9536fd0130Shoumkh
9636fd0130Shoumkh bitflags! {
9736fd0130Shoumkh
9836fd0130Shoumkh #[derive(Default)]
9936fd0130Shoumkh pub struct ClocksourceMask: u64 {
10036fd0130Shoumkh }
10136fd0130Shoumkh /// 时钟状态标记
10236fd0130Shoumkh #[derive(Default)]
10336fd0130Shoumkh pub struct ClocksourceFlags: u64 {
10436fd0130Shoumkh /// 表示时钟设备是连续的
10536fd0130Shoumkh const CLOCK_SOURCE_IS_CONTINUOUS = 0x01;
10636fd0130Shoumkh /// 表示该时钟源需要经过watchdog检查
10736fd0130Shoumkh const CLOCK_SOURCE_MUST_VERIFY = 0x02;
10836fd0130Shoumkh /// 表示该时钟源是watchdog
10936fd0130Shoumkh const CLOCK_SOURCE_WATCHDOG = 0x10;
11036fd0130Shoumkh /// 表示该时钟源是高分辨率的
11136fd0130Shoumkh const CLOCK_SOURCE_VALID_FOR_HRES = 0x20;
11236fd0130Shoumkh /// 表示该时钟源误差过大
11336fd0130Shoumkh const CLOCK_SOURCE_UNSTABLE = 0x40;
11436fd0130Shoumkh }
11536fd0130Shoumkh }
11636fd0130Shoumkh impl From<u64> for ClocksourceMask {
from(value: u64) -> Self11736fd0130Shoumkh fn from(value: u64) -> Self {
11836fd0130Shoumkh if value < 64 {
11936fd0130Shoumkh return Self::from_bits_truncate((1 << value) - 1);
12036fd0130Shoumkh }
12136fd0130Shoumkh return Self::from_bits_truncate(u64::MAX);
12236fd0130Shoumkh }
12336fd0130Shoumkh }
12436fd0130Shoumkh impl ClocksourceMask {
new(b: u64) -> Self12536fd0130Shoumkh pub fn new(b: u64) -> Self {
12636fd0130Shoumkh Self { bits: b }
12736fd0130Shoumkh }
12836fd0130Shoumkh }
12936fd0130Shoumkh impl ClocksourceFlags {
new(b: u64) -> Self13036fd0130Shoumkh pub fn new(b: u64) -> Self {
13136fd0130Shoumkh Self { bits: b }
13236fd0130Shoumkh }
13336fd0130Shoumkh }
13436fd0130Shoumkh
13536fd0130Shoumkh #[derive(Debug)]
13636fd0130Shoumkh pub struct ClocksouceWatchdog {
13736fd0130Shoumkh /// 监视器
13836fd0130Shoumkh watchdog: Option<Arc<dyn Clocksource>>,
13936fd0130Shoumkh /// 检查器是否在工作的标志
14036fd0130Shoumkh is_running: bool,
14136fd0130Shoumkh /// 定时监视器的过期时间
14236fd0130Shoumkh timer_expires: u64,
14336fd0130Shoumkh }
14436fd0130Shoumkh impl ClocksouceWatchdog {
new() -> Self14536fd0130Shoumkh pub fn new() -> Self {
14636fd0130Shoumkh Self {
14736fd0130Shoumkh watchdog: None,
14836fd0130Shoumkh is_running: false,
14936fd0130Shoumkh timer_expires: 0,
15036fd0130Shoumkh }
15136fd0130Shoumkh }
15236fd0130Shoumkh
15336fd0130Shoumkh /// 获取watchdog
get_watchdog(&mut self) -> &mut Option<Arc<dyn Clocksource>>15436fd0130Shoumkh fn get_watchdog(&mut self) -> &mut Option<Arc<dyn Clocksource>> {
15536fd0130Shoumkh &mut self.watchdog
15636fd0130Shoumkh }
15736fd0130Shoumkh
15836fd0130Shoumkh /// 启用检查器
clocksource_start_watchdog(&mut self)15936fd0130Shoumkh pub fn clocksource_start_watchdog(&mut self) {
16036fd0130Shoumkh // 如果watchdog未被设置或者已经启用了就退出
161b8ed3825SDonkey Kane let watchdog_list = WATCHDOG_LIST.lock_irqsave();
16236fd0130Shoumkh if self.is_running || self.watchdog.is_none() || watchdog_list.is_empty() {
16336fd0130Shoumkh return;
16436fd0130Shoumkh }
16536fd0130Shoumkh // 生成一个定时器
16636fd0130Shoumkh let wd_timer_func: Box<WatchdogTimerFunc> = Box::new(WatchdogTimerFunc {});
16736fd0130Shoumkh self.timer_expires += clock() + WATCHDOG_INTERVAL;
168af097f9fS黄铭涛 let mut wd_data = self.watchdog.as_ref().unwrap().clone().clocksource_data();
169af097f9fS黄铭涛 wd_data.watchdog_last = self.watchdog.as_ref().unwrap().clone().read();
170af097f9fS黄铭涛 self.watchdog
171af097f9fS黄铭涛 .as_ref()
172af097f9fS黄铭涛 .unwrap()
173af097f9fS黄铭涛 .update_clocksource_data(wd_data)
174af097f9fS黄铭涛 .expect("clocksource_start_watchdog: failed to update watchdog data");
17536fd0130Shoumkh let wd_timer = Timer::new(wd_timer_func, self.timer_expires);
17636fd0130Shoumkh wd_timer.activate();
17736fd0130Shoumkh self.is_running = true;
17836fd0130Shoumkh }
17936fd0130Shoumkh
18036fd0130Shoumkh /// 停止检查器
18136fd0130Shoumkh /// list_len WATCHDOG_LIST长度
clocksource_stop_watchdog(&mut self, list_len: usize)18236fd0130Shoumkh pub fn clocksource_stop_watchdog(&mut self, list_len: usize) {
18336fd0130Shoumkh if !self.is_running || (self.watchdog.is_some() && list_len != 0) {
18436fd0130Shoumkh return;
18536fd0130Shoumkh }
18636fd0130Shoumkh // TODO 当实现了周期性的定时器后 需要将监视用的定时器删除
18736fd0130Shoumkh self.is_running = false;
18836fd0130Shoumkh }
18936fd0130Shoumkh }
19036fd0130Shoumkh
19136fd0130Shoumkh /// 定时检查器
19236fd0130Shoumkh #[derive(Debug)]
19336fd0130Shoumkh pub struct WatchdogTimerFunc;
19436fd0130Shoumkh impl TimerFunction for WatchdogTimerFunc {
run(&mut self) -> Result<(), SystemError>19536fd0130Shoumkh fn run(&mut self) -> Result<(), SystemError> {
19636fd0130Shoumkh return clocksource_watchdog();
19736fd0130Shoumkh }
19836fd0130Shoumkh }
19936fd0130Shoumkh
20036fd0130Shoumkh /// 时钟源的特性
20136fd0130Shoumkh pub trait Clocksource: Send + Sync + Debug {
20236fd0130Shoumkh // TODO 返回值类型可能需要改变
20336fd0130Shoumkh /// returns a cycle value, passes clocksource as argument
read(&self) -> CycleNum20436fd0130Shoumkh fn read(&self) -> CycleNum;
20536fd0130Shoumkh /// optional function to enable the clocksource
enable(&self) -> Result<i32, SystemError>20636fd0130Shoumkh fn enable(&self) -> Result<i32, SystemError> {
2071074eb34SSamuel Dai return Err(SystemError::ENOSYS);
20836fd0130Shoumkh }
20936fd0130Shoumkh /// optional function to disable the clocksource
210*bd70d2d1SLoGin #[allow(dead_code)]
disable(&self) -> Result<(), SystemError>21136fd0130Shoumkh fn disable(&self) -> Result<(), SystemError> {
2121074eb34SSamuel Dai return Err(SystemError::ENOSYS);
21336fd0130Shoumkh }
21436fd0130Shoumkh /// vsyscall based read
215*bd70d2d1SLoGin #[allow(dead_code)]
vread(&self) -> Result<CycleNum, SystemError>21636fd0130Shoumkh fn vread(&self) -> Result<CycleNum, SystemError> {
2171074eb34SSamuel Dai return Err(SystemError::ENOSYS);
21836fd0130Shoumkh }
21936fd0130Shoumkh /// suspend function for the clocksource, if necessary
suspend(&self) -> Result<(), SystemError>22036fd0130Shoumkh fn suspend(&self) -> Result<(), SystemError> {
2211074eb34SSamuel Dai return Err(SystemError::ENOSYS);
22236fd0130Shoumkh }
22336fd0130Shoumkh /// resume function for the clocksource, if necessary
resume(&self) -> Result<(), SystemError>22436fd0130Shoumkh fn resume(&self) -> Result<(), SystemError> {
2251074eb34SSamuel Dai return Err(SystemError::ENOSYS);
22636fd0130Shoumkh }
22736fd0130Shoumkh // 获取时钟源数据
clocksource_data(&self) -> ClocksourceData22836fd0130Shoumkh fn clocksource_data(&self) -> ClocksourceData;
22936fd0130Shoumkh
update_clocksource_data(&self, _data: ClocksourceData) -> Result<(), SystemError>23036fd0130Shoumkh fn update_clocksource_data(&self, _data: ClocksourceData) -> Result<(), SystemError> {
2311074eb34SSamuel Dai return Err(SystemError::ENOSYS);
23236fd0130Shoumkh }
23336fd0130Shoumkh // 获取时钟源
clocksource(&self) -> Arc<dyn Clocksource>23436fd0130Shoumkh fn clocksource(&self) -> Arc<dyn Clocksource>;
23536fd0130Shoumkh }
23636fd0130Shoumkh
23736fd0130Shoumkh /// # 实现整数log2的运算
23836fd0130Shoumkh ///
23936fd0130Shoumkh /// ## 参数
24036fd0130Shoumkh ///
24136fd0130Shoumkh /// * `x` - 要计算的数字
24236fd0130Shoumkh ///
24336fd0130Shoumkh /// ## 返回值
24436fd0130Shoumkh ///
24536fd0130Shoumkh /// * `u32` - 返回\log_2(x)的值
log2(x: u32) -> u3224636fd0130Shoumkh fn log2(x: u32) -> u32 {
24736fd0130Shoumkh let mut result = 0;
24836fd0130Shoumkh let mut x = x;
24936fd0130Shoumkh
25036fd0130Shoumkh if x >= 1 << 16 {
25136fd0130Shoumkh x >>= 16;
25236fd0130Shoumkh result |= 16;
25336fd0130Shoumkh }
25436fd0130Shoumkh if x >= 1 << 8 {
25536fd0130Shoumkh x >>= 8;
25636fd0130Shoumkh result |= 8;
25736fd0130Shoumkh }
25836fd0130Shoumkh if x >= 1 << 4 {
25936fd0130Shoumkh x >>= 4;
26036fd0130Shoumkh result |= 4;
26136fd0130Shoumkh }
26236fd0130Shoumkh if x >= 1 << 2 {
26336fd0130Shoumkh x >>= 2;
26436fd0130Shoumkh result |= 2;
26536fd0130Shoumkh }
26636fd0130Shoumkh if x >= 1 << 1 {
26736fd0130Shoumkh result |= 1;
26836fd0130Shoumkh }
26936fd0130Shoumkh
27036fd0130Shoumkh result
27136fd0130Shoumkh }
27236fd0130Shoumkh
27336fd0130Shoumkh impl dyn Clocksource {
27436fd0130Shoumkh /// # 计算时钟源能记录的最大时间跨度
clocksource_max_deferment(&self) -> u6427536fd0130Shoumkh pub fn clocksource_max_deferment(&self) -> u64 {
27636fd0130Shoumkh let cs_data_guard = self.clocksource_data();
277840045afSLoGin
27836fd0130Shoumkh let mut max_cycles: u64;
279af097f9fS黄铭涛 max_cycles = (1 << (63 - (log2(cs_data_guard.mult + cs_data_guard.maxadj) + 1))) as u64;
28036fd0130Shoumkh max_cycles = max_cycles.min(cs_data_guard.mask.bits);
281840045afSLoGin let max_nsecs = clocksource_cyc2ns(
28236fd0130Shoumkh CycleNum(max_cycles),
283af097f9fS黄铭涛 cs_data_guard.mult - cs_data_guard.maxadj,
28436fd0130Shoumkh cs_data_guard.shift,
28536fd0130Shoumkh );
286af097f9fS黄铭涛 return max_nsecs - (max_nsecs >> 3);
28736fd0130Shoumkh }
28836fd0130Shoumkh
289dd8e74efSMingtao Huang /// # 计算时钟源的mult和shift,以便将一个时钟源的频率转换为另一个时钟源的频率
clocks_calc_mult_shift(&self, from: u32, to: u32, maxsec: u32) -> (u32, u32)290dd8e74efSMingtao Huang fn clocks_calc_mult_shift(&self, from: u32, to: u32, maxsec: u32) -> (u32, u32) {
291dd8e74efSMingtao Huang let mut sftacc: u32 = 32;
292dd8e74efSMingtao Huang let mut sft = 1;
293dd8e74efSMingtao Huang
294dd8e74efSMingtao Huang // 计算限制转换范围的shift
295dd8e74efSMingtao Huang let mut mult = (maxsec as u64 * from as u64) >> 32;
296dd8e74efSMingtao Huang while mult != 0 {
297dd8e74efSMingtao Huang mult >>= 1;
298dd8e74efSMingtao Huang sftacc -= 1;
299dd8e74efSMingtao Huang }
300dd8e74efSMingtao Huang
301dd8e74efSMingtao Huang // 找到最佳的mult和shift
302dd8e74efSMingtao Huang for i in (1..=32).rev() {
303dd8e74efSMingtao Huang sft = i;
304dd8e74efSMingtao Huang mult = (to as u64) << sft;
305dd8e74efSMingtao Huang mult += from as u64 / 2;
306dd8e74efSMingtao Huang mult /= from as u64;
307dd8e74efSMingtao Huang if (mult >> sftacc) == 0 {
308dd8e74efSMingtao Huang break;
309dd8e74efSMingtao Huang }
310dd8e74efSMingtao Huang }
311dd8e74efSMingtao Huang
312dd8e74efSMingtao Huang return (mult as u32, sft);
313dd8e74efSMingtao Huang }
314dd8e74efSMingtao Huang
315dd8e74efSMingtao Huang /// # 计算时钟源可以进行的最大调整量
clocksource_max_adjustment(&self) -> u32316dd8e74efSMingtao Huang fn clocksource_max_adjustment(&self) -> u32 {
317dd8e74efSMingtao Huang let cs_data = self.clocksource_data();
318dd8e74efSMingtao Huang let ret = cs_data.mult as u64 * 11 / 100;
319dd8e74efSMingtao Huang
320dd8e74efSMingtao Huang return ret as u32;
321dd8e74efSMingtao Huang }
322dd8e74efSMingtao Huang
323dd8e74efSMingtao Huang /// # 更新时钟源频率,初始化mult/shift 和 max_idle_ns
clocksource_update_freq_scale(&self, scale: u32, freq: u32) -> Result<(), SystemError>324dd8e74efSMingtao Huang fn clocksource_update_freq_scale(&self, scale: u32, freq: u32) -> Result<(), SystemError> {
325dd8e74efSMingtao Huang if freq != 0 {
326af097f9fS黄铭涛 let mut cs_data = self.clocksource_data();
327dd8e74efSMingtao Huang let mut sec: u64 = cs_data.mask.bits();
328dd8e74efSMingtao Huang
329dd8e74efSMingtao Huang sec /= freq as u64;
330dd8e74efSMingtao Huang sec /= scale as u64;
331dd8e74efSMingtao Huang if sec == 0 {
332dd8e74efSMingtao Huang sec = 1;
333dd8e74efSMingtao Huang } else if sec > 600 && cs_data.mask.bits() > u32::MAX as u64 {
334dd8e74efSMingtao Huang sec = 600;
335dd8e74efSMingtao Huang }
336dd8e74efSMingtao Huang
337dd8e74efSMingtao Huang let (mult, shift) =
338dd8e74efSMingtao Huang self.clocks_calc_mult_shift(freq, NSEC_PER_SEC / scale, sec as u32 * scale);
339dd8e74efSMingtao Huang cs_data.set_mult(mult);
340dd8e74efSMingtao Huang cs_data.set_shift(shift);
341af097f9fS黄铭涛 self.update_clocksource_data(cs_data)?;
342dd8e74efSMingtao Huang }
343dd8e74efSMingtao Huang
344af097f9fS黄铭涛 let mut cs_data = self.clocksource_data();
345dd8e74efSMingtao Huang if scale != 0 && freq != 0 && cs_data.uncertainty_margin == 0 {
346dd8e74efSMingtao Huang cs_data.set_uncertainty_margin(NSEC_PER_SEC / (scale * freq));
347dd8e74efSMingtao Huang if cs_data.uncertainty_margin < 2 * WATCHDOG_MAX_SKEW {
348dd8e74efSMingtao Huang cs_data.set_uncertainty_margin(2 * WATCHDOG_MAX_SKEW);
349dd8e74efSMingtao Huang }
350dd8e74efSMingtao Huang } else if cs_data.uncertainty_margin == 0 {
351dd8e74efSMingtao Huang cs_data.set_uncertainty_margin(WATCHDOG_THRESHOLD);
352dd8e74efSMingtao Huang }
353dd8e74efSMingtao Huang
354dd8e74efSMingtao Huang // 确保时钟源没有太大的mult值造成溢出
355dd8e74efSMingtao Huang cs_data.set_maxadj(self.clocksource_max_adjustment());
356af097f9fS黄铭涛 self.update_clocksource_data(cs_data)?;
357af097f9fS黄铭涛 while freq != 0
358af097f9fS黄铭涛 && (self.clocksource_data().mult + self.clocksource_data().maxadj
359af097f9fS黄铭涛 < self.clocksource_data().mult
360af097f9fS黄铭涛 || self.clocksource_data().mult - self.clocksource_data().maxadj
361af097f9fS黄铭涛 > self.clocksource_data().mult)
362af097f9fS黄铭涛 {
363af097f9fS黄铭涛 let mut cs_data = self.clocksource_data();
364af097f9fS黄铭涛 cs_data.set_mult(cs_data.mult >> 1);
365af097f9fS黄铭涛 cs_data.set_shift(cs_data.shift - 1);
366af097f9fS黄铭涛 self.update_clocksource_data(cs_data)?;
367af097f9fS黄铭涛 let mut cs_data = self.clocksource_data();
368af097f9fS黄铭涛 cs_data.set_maxadj(self.clocksource_max_adjustment());
369af097f9fS黄铭涛 self.update_clocksource_data(cs_data)?;
370af097f9fS黄铭涛 }
371dd8e74efSMingtao Huang
372af097f9fS黄铭涛 let mut cs_data = self.clocksource_data();
373dd8e74efSMingtao Huang let ns = self.clocksource_max_deferment();
374dd8e74efSMingtao Huang cs_data.set_max_idle_ns(ns as u32);
375dd8e74efSMingtao Huang self.update_clocksource_data(cs_data)?;
376dd8e74efSMingtao Huang
377dd8e74efSMingtao Huang return Ok(());
378dd8e74efSMingtao Huang }
379dd8e74efSMingtao Huang
38036fd0130Shoumkh /// # 注册时钟源
38136fd0130Shoumkh ///
382dd8e74efSMingtao Huang /// ## 参数
383dd8e74efSMingtao Huang ///
384dd8e74efSMingtao Huang /// - scale: 如果freq单位为0或hz,此值为1,如果为khz,此值为1000
385dd8e74efSMingtao Huang /// - freq: 时钟源的频率,jiffies注册时此值为0
386dd8e74efSMingtao Huang ///
38736fd0130Shoumkh /// ## 返回值
38836fd0130Shoumkh ///
38936fd0130Shoumkh /// * `Ok(0)` - 时钟源注册成功。
39036fd0130Shoumkh /// * `Err(SystemError)` - 时钟源注册失败。
register(&self, scale: u32, freq: u32) -> Result<(), SystemError>391dd8e74efSMingtao Huang pub fn register(&self, scale: u32, freq: u32) -> Result<(), SystemError> {
392dd8e74efSMingtao Huang self.clocksource_update_freq_scale(scale, freq)?;
393dd8e74efSMingtao Huang
39436fd0130Shoumkh // 将时钟源加入到时钟源队列中
39536fd0130Shoumkh self.clocksource_enqueue();
39636fd0130Shoumkh // 将时钟源加入到监视队列中
39736fd0130Shoumkh self.clocksource_enqueue_watchdog()
39836fd0130Shoumkh .expect("register: failed to enqueue watchdog list");
39936fd0130Shoumkh // 选择一个最好的时钟源
40036fd0130Shoumkh clocksource_select();
4012eab6dd7S曾俊 debug!("clocksource_register successfully");
402dd8e74efSMingtao Huang return Ok(());
40336fd0130Shoumkh }
40436fd0130Shoumkh
40536fd0130Shoumkh /// # 将时钟源插入时钟源队列
clocksource_enqueue(&self)40636fd0130Shoumkh pub fn clocksource_enqueue(&self) {
40736fd0130Shoumkh // 根据rating由大到小排序
40836fd0130Shoumkh let cs_data = self.clocksource_data();
409b8ed3825SDonkey Kane let mut list_guard = CLOCKSOURCE_LIST.lock();
410af097f9fS黄铭涛 let mut spilt_pos: usize = list_guard.len();
41136fd0130Shoumkh for (pos, ele) in list_guard.iter().enumerate() {
41236fd0130Shoumkh if ele.clocksource_data().rating < cs_data.rating {
41336fd0130Shoumkh spilt_pos = pos;
41436fd0130Shoumkh break;
41536fd0130Shoumkh }
41636fd0130Shoumkh }
41736fd0130Shoumkh let mut temp_list = list_guard.split_off(spilt_pos);
41836fd0130Shoumkh let cs = self.clocksource();
41936fd0130Shoumkh list_guard.push_back(cs);
42036fd0130Shoumkh list_guard.append(&mut temp_list);
4212eab6dd7S曾俊 // debug!(
42236fd0130Shoumkh // "CLOCKSOURCE_LIST len = {:?},clocksource_enqueue sccessfully",
42336fd0130Shoumkh // list_guard.len()
42436fd0130Shoumkh // );
42536fd0130Shoumkh }
42636fd0130Shoumkh
42736fd0130Shoumkh /// # 将时间源插入监控队列
42836fd0130Shoumkh ///
42936fd0130Shoumkh /// ## 返回值
43036fd0130Shoumkh ///
43136fd0130Shoumkh /// * `Ok(0)` - 时间源插入监控队列成功
43236fd0130Shoumkh /// * `Err(SystemError)` - 时间源插入监控队列失败
clocksource_enqueue_watchdog(&self) -> Result<i32, SystemError>43336fd0130Shoumkh pub fn clocksource_enqueue_watchdog(&self) -> Result<i32, SystemError> {
43436fd0130Shoumkh // BUG 可能需要lock irq
43536fd0130Shoumkh let mut cs_data = self.clocksource_data();
43636fd0130Shoumkh
43736fd0130Shoumkh let cs = self.clocksource();
43836fd0130Shoumkh if cs_data
43936fd0130Shoumkh .flags
44036fd0130Shoumkh .contains(ClocksourceFlags::CLOCK_SOURCE_MUST_VERIFY)
44136fd0130Shoumkh {
44236fd0130Shoumkh let mut list_guard = WATCHDOG_LIST.lock_irqsave();
44336fd0130Shoumkh // cs是被监视的
44436fd0130Shoumkh cs_data
44536fd0130Shoumkh .flags
44636fd0130Shoumkh .remove(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG);
44736fd0130Shoumkh cs.update_clocksource_data(cs_data)?;
44836fd0130Shoumkh list_guard.push_back(cs);
44936fd0130Shoumkh } else {
45036fd0130Shoumkh // cs是监视器
45136fd0130Shoumkh if cs_data
45236fd0130Shoumkh .flags
45336fd0130Shoumkh .contains(ClocksourceFlags::CLOCK_SOURCE_IS_CONTINUOUS)
45436fd0130Shoumkh {
45536fd0130Shoumkh // 如果时钟设备是连续的
45636fd0130Shoumkh cs_data
45736fd0130Shoumkh .flags
45836fd0130Shoumkh .insert(ClocksourceFlags::CLOCK_SOURCE_VALID_FOR_HRES);
45936fd0130Shoumkh cs.update_clocksource_data(cs_data.clone())?;
46036fd0130Shoumkh }
46136fd0130Shoumkh
46236fd0130Shoumkh // 将时钟源加入到监控队列中
463b8ed3825SDonkey Kane let mut list_guard = WATCHDOG_LIST.lock_irqsave();
46436fd0130Shoumkh list_guard.push_back(cs.clone());
46536fd0130Shoumkh drop(list_guard);
46636fd0130Shoumkh
46736fd0130Shoumkh // 对比当前注册的时间源的精度和监视器的精度
468af097f9fS黄铭涛 let mut cs_watchdog = CLOCKSOURCE_WATCHDOG.lock_irqsave();
46936fd0130Shoumkh if cs_watchdog.watchdog.is_none()
47036fd0130Shoumkh || cs_data.rating
47136fd0130Shoumkh > cs_watchdog
47236fd0130Shoumkh .watchdog
47336fd0130Shoumkh .clone()
47436fd0130Shoumkh .unwrap()
47536fd0130Shoumkh .clocksource_data()
47636fd0130Shoumkh .rating
47736fd0130Shoumkh {
47836fd0130Shoumkh // 当前注册的时间源的精度更高或者没有监视器,替换监视器
47936fd0130Shoumkh cs_watchdog.watchdog.replace(cs);
48036fd0130Shoumkh clocksource_reset_watchdog();
48136fd0130Shoumkh }
48236fd0130Shoumkh
48336fd0130Shoumkh // 启动监视器
48436fd0130Shoumkh cs_watchdog.clocksource_start_watchdog();
48536fd0130Shoumkh }
48636fd0130Shoumkh return Ok(0);
48736fd0130Shoumkh }
48836fd0130Shoumkh
48936fd0130Shoumkh /// # 将时钟源标记为unstable
49036fd0130Shoumkh ///
49136fd0130Shoumkh /// ## 参数
49236fd0130Shoumkh /// * `delta` - 时钟源误差
set_unstable(&self, delta: i64) -> Result<i32, SystemError>49336fd0130Shoumkh pub fn set_unstable(&self, delta: i64) -> Result<i32, SystemError> {
49436fd0130Shoumkh let mut cs_data = self.clocksource_data();
49536fd0130Shoumkh // 打印出unstable的时钟源信息
4962eab6dd7S曾俊 debug!(
49736fd0130Shoumkh "clocksource :{:?} is unstable, its delta is {:?}",
4982eab6dd7S曾俊 cs_data.name, delta
49936fd0130Shoumkh );
50036fd0130Shoumkh cs_data.flags.remove(
50136fd0130Shoumkh ClocksourceFlags::CLOCK_SOURCE_VALID_FOR_HRES | ClocksourceFlags::CLOCK_SOURCE_WATCHDOG,
50236fd0130Shoumkh );
50336fd0130Shoumkh cs_data
50436fd0130Shoumkh .flags
50536fd0130Shoumkh .insert(ClocksourceFlags::CLOCK_SOURCE_UNSTABLE);
50636fd0130Shoumkh self.update_clocksource_data(cs_data)?;
50736fd0130Shoumkh
50836fd0130Shoumkh // 启动watchdog线程 进行后续处理
50992deae63SLoGin if FINISHED_BOOTING.load(Ordering::Relaxed) {
51036fd0130Shoumkh // TODO 在实现了工作队列后,将启动线程换成schedule work
511b8ed3825SDonkey Kane run_watchdog_kthread();
51236fd0130Shoumkh }
51336fd0130Shoumkh return Ok(0);
51436fd0130Shoumkh }
51536fd0130Shoumkh
51636fd0130Shoumkh /// # 将时间源从监视链表中弹出
clocksource_dequeue_watchdog(&self)51736fd0130Shoumkh fn clocksource_dequeue_watchdog(&self) {
51836fd0130Shoumkh let data = self.clocksource_data();
519af097f9fS黄铭涛 let mut locked_watchdog = CLOCKSOURCE_WATCHDOG.lock_irqsave();
52036fd0130Shoumkh let watchdog = locked_watchdog
52136fd0130Shoumkh .get_watchdog()
52236fd0130Shoumkh .clone()
52336fd0130Shoumkh .unwrap()
52436fd0130Shoumkh .clocksource_data();
52536fd0130Shoumkh
526b8ed3825SDonkey Kane let mut list = WATCHDOG_LIST.lock_irqsave();
52736fd0130Shoumkh let mut size = list.len();
52836fd0130Shoumkh
52936fd0130Shoumkh let mut del_pos: usize = size;
53036fd0130Shoumkh for (pos, ele) in list.iter().enumerate() {
53136fd0130Shoumkh let ele_data = ele.clocksource_data();
53236fd0130Shoumkh if ele_data.name.eq(&data.name) && ele_data.rating.eq(&data.rating) {
53336fd0130Shoumkh // 记录要删除的时钟源在监视链表中的下标
53436fd0130Shoumkh del_pos = pos;
53536fd0130Shoumkh }
53636fd0130Shoumkh }
53736fd0130Shoumkh
53836fd0130Shoumkh if data
53936fd0130Shoumkh .flags
54036fd0130Shoumkh .contains(ClocksourceFlags::CLOCK_SOURCE_MUST_VERIFY)
54136fd0130Shoumkh {
54236fd0130Shoumkh // 如果时钟源是需要被检查的,直接删除时钟源
54336fd0130Shoumkh if del_pos != size {
54436fd0130Shoumkh let mut temp_list = list.split_off(del_pos);
54536fd0130Shoumkh temp_list.pop_front();
54636fd0130Shoumkh list.append(&mut temp_list);
54736fd0130Shoumkh }
54836fd0130Shoumkh } else if watchdog.name.eq(&data.name) && watchdog.rating.eq(&data.rating) {
54936fd0130Shoumkh // 如果要删除的时钟源是监视器,则需要找到一个新的监视器
55036fd0130Shoumkh // TODO 重新设置时钟源
55136fd0130Shoumkh // 将链表解锁防止reset中双重加锁 并释放保存的旧的watchdog的数据
55236fd0130Shoumkh
55336fd0130Shoumkh // 代替了clocksource_reset_watchdog()的功能,将所有时钟源的watchdog标记清除
55436fd0130Shoumkh for ele in list.iter() {
55536fd0130Shoumkh ele.clocksource_data()
55636fd0130Shoumkh .flags
55736fd0130Shoumkh .remove(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG);
55836fd0130Shoumkh }
55936fd0130Shoumkh
56036fd0130Shoumkh // 遍历所有时间源,寻找新的监视器
56136fd0130Shoumkh let mut clocksource_list = CLOCKSOURCE_LIST.lock();
56236fd0130Shoumkh let mut replace_pos: usize = clocksource_list.len();
56336fd0130Shoumkh for (pos, ele) in clocksource_list.iter().enumerate() {
56436fd0130Shoumkh let ele_data = ele.clocksource_data();
56536fd0130Shoumkh
56636fd0130Shoumkh if ele_data.name.eq(&data.name) && ele_data.rating.eq(&data.rating)
56736fd0130Shoumkh || ele_data
56836fd0130Shoumkh .flags
56936fd0130Shoumkh .contains(ClocksourceFlags::CLOCK_SOURCE_MUST_VERIFY)
57036fd0130Shoumkh {
57136fd0130Shoumkh // 当前时钟源是要被删除的时钟源或没被检查过的时钟源
57236fd0130Shoumkh // 不适合成为监视器
57336fd0130Shoumkh continue;
57436fd0130Shoumkh }
57536fd0130Shoumkh let watchdog = locked_watchdog.get_watchdog().clone();
57636fd0130Shoumkh if watchdog.is_none()
57736fd0130Shoumkh || ele_data.rating > watchdog.unwrap().clocksource_data().rating
57836fd0130Shoumkh {
57936fd0130Shoumkh // 如果watchdog不存在或者当前时钟源的精度高于watchdog的精度,则记录当前时钟源的下标
58036fd0130Shoumkh replace_pos = pos;
58136fd0130Shoumkh }
58236fd0130Shoumkh }
58336fd0130Shoumkh // 使用刚刚找到的更好的时钟源替换旧的watchdog
58436fd0130Shoumkh if replace_pos < clocksource_list.len() {
58536fd0130Shoumkh let mut temp_list = clocksource_list.split_off(replace_pos);
58636fd0130Shoumkh let new_wd = temp_list.front().unwrap().clone();
58736fd0130Shoumkh clocksource_list.append(&mut temp_list);
58836fd0130Shoumkh // 替换watchdog
58936fd0130Shoumkh locked_watchdog.watchdog.replace(new_wd);
59036fd0130Shoumkh // drop(locked_watchdog);
59136fd0130Shoumkh }
59236fd0130Shoumkh // 删除时钟源
59336fd0130Shoumkh if del_pos != size {
59436fd0130Shoumkh let mut temp_list = list.split_off(del_pos);
59536fd0130Shoumkh temp_list.pop_front();
59636fd0130Shoumkh list.append(&mut temp_list);
59736fd0130Shoumkh }
59836fd0130Shoumkh }
59936fd0130Shoumkh
60036fd0130Shoumkh // 清除watchdog标记
60136fd0130Shoumkh let mut cs_data = self.clocksource_data();
60236fd0130Shoumkh cs_data
60336fd0130Shoumkh .flags
60436fd0130Shoumkh .remove(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG);
60536fd0130Shoumkh self.update_clocksource_data(cs_data)
60636fd0130Shoumkh .expect("clocksource_dequeue_watchdog: failed to update clocksource data");
60736fd0130Shoumkh size = list.len();
60836fd0130Shoumkh // 停止当前的watchdog
60936fd0130Shoumkh locked_watchdog.clocksource_stop_watchdog(size - 1);
61036fd0130Shoumkh }
61136fd0130Shoumkh
61236fd0130Shoumkh /// # 将时钟源从时钟源链表中弹出
clocksource_dequeue(&self)61336fd0130Shoumkh fn clocksource_dequeue(&self) {
61436fd0130Shoumkh let mut list = CLOCKSOURCE_LIST.lock();
61536fd0130Shoumkh let data = self.clocksource_data();
61636fd0130Shoumkh let mut del_pos: usize = list.len();
61736fd0130Shoumkh for (pos, ele) in list.iter().enumerate() {
61836fd0130Shoumkh let ele_data = ele.clocksource_data();
61936fd0130Shoumkh if ele_data.name.eq(&data.name) && ele_data.rating.eq(&data.rating) {
62036fd0130Shoumkh // 记录时钟源在链表中的下标
62136fd0130Shoumkh del_pos = pos;
62236fd0130Shoumkh }
62336fd0130Shoumkh }
62436fd0130Shoumkh
62536fd0130Shoumkh // 删除时钟源
62636fd0130Shoumkh if del_pos != list.len() {
62736fd0130Shoumkh let mut temp_list = list.split_off(del_pos);
62836fd0130Shoumkh temp_list.pop_front();
62936fd0130Shoumkh list.append(&mut temp_list);
63036fd0130Shoumkh }
63136fd0130Shoumkh }
63236fd0130Shoumkh
63336fd0130Shoumkh /// # 注销时钟源
63436fd0130Shoumkh #[allow(dead_code)]
unregister(&self)63536fd0130Shoumkh pub fn unregister(&self) {
63636fd0130Shoumkh // 将时钟源从监视链表中弹出
63736fd0130Shoumkh self.clocksource_dequeue_watchdog();
63836fd0130Shoumkh // 将时钟源从时钟源链表中弹出
63936fd0130Shoumkh self.clocksource_dequeue();
64036fd0130Shoumkh // 检查是否有更好的时钟源
64136fd0130Shoumkh clocksource_select();
64236fd0130Shoumkh }
64336fd0130Shoumkh /// # 修改时钟源的精度
64436fd0130Shoumkh ///
64536fd0130Shoumkh /// ## 参数
64636fd0130Shoumkh ///
64736fd0130Shoumkh /// * `rating` - 指定的时钟精度
clocksource_change_rating(&self, rating: i32)64836fd0130Shoumkh fn clocksource_change_rating(&self, rating: i32) {
64936fd0130Shoumkh // 将时钟源从链表中弹出
65036fd0130Shoumkh self.clocksource_dequeue();
65136fd0130Shoumkh let mut data = self.clocksource_data();
65236fd0130Shoumkh // 修改时钟源的精度
65336fd0130Shoumkh data.set_rating(rating);
65436fd0130Shoumkh self.update_clocksource_data(data)
65536fd0130Shoumkh .expect("clocksource_change_rating:updata clocksource failed");
65636fd0130Shoumkh // 插入时钟源到时钟源链表中
65736fd0130Shoumkh self.clocksource_enqueue();
65836fd0130Shoumkh // 检查是否有更好的时钟源
65936fd0130Shoumkh clocksource_select();
66036fd0130Shoumkh }
66136fd0130Shoumkh }
66236fd0130Shoumkh
66336fd0130Shoumkh #[derive(Debug, Clone)]
66436fd0130Shoumkh pub struct ClocksourceData {
66536fd0130Shoumkh /// 时钟源名字
66636fd0130Shoumkh pub name: String,
66736fd0130Shoumkh /// 时钟精度
66836fd0130Shoumkh pub rating: i32,
66936fd0130Shoumkh pub mask: ClocksourceMask,
67036fd0130Shoumkh pub mult: u32,
67136fd0130Shoumkh pub shift: u32,
67236fd0130Shoumkh pub max_idle_ns: u32,
67336fd0130Shoumkh pub flags: ClocksourceFlags,
67436fd0130Shoumkh pub watchdog_last: CycleNum,
675af097f9fS黄铭涛 /// 用于watchdog机制中的字段,记录主时钟源上一次被读取的周期数
676af097f9fS黄铭涛 pub cs_last: CycleNum,
677dd8e74efSMingtao Huang // 用于描述时钟源的不确定性边界,时钟源读取的时间可能存在的不确定性和误差范围
678dd8e74efSMingtao Huang pub uncertainty_margin: u32,
679dd8e74efSMingtao Huang // 最大的时间调整量
680dd8e74efSMingtao Huang pub maxadj: u32,
681af097f9fS黄铭涛 /// 上一次读取时钟源时的周期数
682af097f9fS黄铭涛 pub cycle_last: CycleNum,
68336fd0130Shoumkh }
68436fd0130Shoumkh
68536fd0130Shoumkh impl ClocksourceData {
68636fd0130Shoumkh #[allow(dead_code)]
687dd8e74efSMingtao Huang #[allow(clippy::too_many_arguments)]
new( name: String, rating: i32, mask: ClocksourceMask, mult: u32, shift: u32, max_idle_ns: u32, flags: ClocksourceFlags, uncertainty_margin: u32, maxadj: u32, ) -> Self68836fd0130Shoumkh pub fn new(
68936fd0130Shoumkh name: String,
69036fd0130Shoumkh rating: i32,
69136fd0130Shoumkh mask: ClocksourceMask,
69236fd0130Shoumkh mult: u32,
69336fd0130Shoumkh shift: u32,
69436fd0130Shoumkh max_idle_ns: u32,
69536fd0130Shoumkh flags: ClocksourceFlags,
696dd8e74efSMingtao Huang uncertainty_margin: u32,
697dd8e74efSMingtao Huang maxadj: u32,
69836fd0130Shoumkh ) -> Self {
69936fd0130Shoumkh let csd = ClocksourceData {
70036fd0130Shoumkh name,
70136fd0130Shoumkh rating,
70236fd0130Shoumkh mask,
70336fd0130Shoumkh mult,
70436fd0130Shoumkh shift,
70536fd0130Shoumkh max_idle_ns,
70636fd0130Shoumkh flags,
70736fd0130Shoumkh watchdog_last: CycleNum(0),
708af097f9fS黄铭涛 cs_last: CycleNum(0),
709dd8e74efSMingtao Huang uncertainty_margin,
710dd8e74efSMingtao Huang maxadj,
711af097f9fS黄铭涛 cycle_last: CycleNum(0),
71236fd0130Shoumkh };
71336fd0130Shoumkh return csd;
71436fd0130Shoumkh }
71536fd0130Shoumkh
set_name(&mut self, name: String)71636fd0130Shoumkh pub fn set_name(&mut self, name: String) {
71736fd0130Shoumkh self.name = name;
71836fd0130Shoumkh }
set_rating(&mut self, rating: i32)71936fd0130Shoumkh pub fn set_rating(&mut self, rating: i32) {
72036fd0130Shoumkh self.rating = rating;
72136fd0130Shoumkh }
set_mask(&mut self, mask: ClocksourceMask)72236fd0130Shoumkh pub fn set_mask(&mut self, mask: ClocksourceMask) {
72336fd0130Shoumkh self.mask = mask;
72436fd0130Shoumkh }
set_mult(&mut self, mult: u32)72536fd0130Shoumkh pub fn set_mult(&mut self, mult: u32) {
72636fd0130Shoumkh self.mult = mult;
72736fd0130Shoumkh }
set_shift(&mut self, shift: u32)72836fd0130Shoumkh pub fn set_shift(&mut self, shift: u32) {
72936fd0130Shoumkh self.shift = shift;
73036fd0130Shoumkh }
set_max_idle_ns(&mut self, max_idle_ns: u32)73136fd0130Shoumkh pub fn set_max_idle_ns(&mut self, max_idle_ns: u32) {
73236fd0130Shoumkh self.max_idle_ns = max_idle_ns;
73336fd0130Shoumkh }
set_flags(&mut self, flags: ClocksourceFlags)73436fd0130Shoumkh pub fn set_flags(&mut self, flags: ClocksourceFlags) {
73536fd0130Shoumkh self.flags = flags;
73636fd0130Shoumkh }
73736fd0130Shoumkh #[allow(dead_code)]
remove_flags(&mut self, flags: ClocksourceFlags)73836fd0130Shoumkh pub fn remove_flags(&mut self, flags: ClocksourceFlags) {
73936fd0130Shoumkh self.flags.remove(flags)
74036fd0130Shoumkh }
74136fd0130Shoumkh #[allow(dead_code)]
insert_flags(&mut self, flags: ClocksourceFlags)74236fd0130Shoumkh pub fn insert_flags(&mut self, flags: ClocksourceFlags) {
74336fd0130Shoumkh self.flags.insert(flags)
74436fd0130Shoumkh }
set_uncertainty_margin(&mut self, uncertainty_margin: u32)745dd8e74efSMingtao Huang pub fn set_uncertainty_margin(&mut self, uncertainty_margin: u32) {
746dd8e74efSMingtao Huang self.uncertainty_margin = uncertainty_margin;
747dd8e74efSMingtao Huang }
set_maxadj(&mut self, maxadj: u32)748dd8e74efSMingtao Huang pub fn set_maxadj(&mut self, maxadj: u32) {
749dd8e74efSMingtao Huang self.maxadj = maxadj;
750dd8e74efSMingtao Huang }
75136fd0130Shoumkh }
75236fd0130Shoumkh
75336fd0130Shoumkh /// converts clocksource cycles to nanoseconds
75436fd0130Shoumkh ///
clocksource_cyc2ns(cycles: CycleNum, mult: u32, shift: u32) -> u6475536fd0130Shoumkh pub fn clocksource_cyc2ns(cycles: CycleNum, mult: u32, shift: u32) -> u64 {
756af097f9fS黄铭涛 // info!("<clocksource_cyc2ns>");
757af097f9fS黄铭涛 // info!("cycles = {:?}, mult = {:?}, shift = {:?}", cycles, mult, shift);
758af097f9fS黄铭涛 // info!("ret = {:?}", (cycles.data() * mult as u64) >> shift);
75936fd0130Shoumkh return (cycles.data() * mult as u64) >> shift;
76036fd0130Shoumkh }
76136fd0130Shoumkh
76236fd0130Shoumkh /// # 重启所有的时间源
76336fd0130Shoumkh #[allow(dead_code)]
clocksource_resume()76436fd0130Shoumkh pub fn clocksource_resume() {
76536fd0130Shoumkh let list = CLOCKSOURCE_LIST.lock();
76636fd0130Shoumkh for ele in list.iter() {
76736fd0130Shoumkh let data = ele.clocksource_data();
76836fd0130Shoumkh match ele.resume() {
76936fd0130Shoumkh Ok(_) => continue,
77036fd0130Shoumkh Err(_) => {
7712eab6dd7S曾俊 debug!("clocksource {:?} resume failed", data.name);
77236fd0130Shoumkh }
77336fd0130Shoumkh }
77436fd0130Shoumkh }
77536fd0130Shoumkh clocksource_resume_watchdog();
77636fd0130Shoumkh }
77736fd0130Shoumkh
77836fd0130Shoumkh /// # 暂停所有的时间源
77936fd0130Shoumkh #[allow(dead_code)]
clocksource_suspend()78036fd0130Shoumkh pub fn clocksource_suspend() {
78136fd0130Shoumkh let list = CLOCKSOURCE_LIST.lock();
78236fd0130Shoumkh for ele in list.iter() {
78336fd0130Shoumkh let data = ele.clocksource_data();
78436fd0130Shoumkh match ele.suspend() {
78536fd0130Shoumkh Ok(_) => continue,
78636fd0130Shoumkh Err(_) => {
7872eab6dd7S曾俊 debug!("clocksource {:?} suspend failed", data.name);
78836fd0130Shoumkh }
78936fd0130Shoumkh }
79036fd0130Shoumkh }
79136fd0130Shoumkh }
79236fd0130Shoumkh
79336fd0130Shoumkh /// # 根据watchdog的精度,来检查被监视的时钟源的误差
79436fd0130Shoumkh ///
79536fd0130Shoumkh /// ## 返回值
79636fd0130Shoumkh ///
79736fd0130Shoumkh /// * `Ok()` - 检查完成
79836fd0130Shoumkh /// * `Err(SystemError)` - 错误码
clocksource_watchdog() -> Result<(), SystemError>79936fd0130Shoumkh pub fn clocksource_watchdog() -> Result<(), SystemError> {
800af097f9fS黄铭涛 let cs_watchdog = CLOCKSOURCE_WATCHDOG.lock_irqsave();
8012eab6dd7S曾俊 // debug!("clocksource_watchdog start");
80236fd0130Shoumkh
80336fd0130Shoumkh // watchdog没有在运行的话直接退出
80436fd0130Shoumkh if !cs_watchdog.is_running || cs_watchdog.watchdog.is_none() {
8052eab6dd7S曾俊 // debug!("is_running = {:?},watchdog = {:?}", cs_watchdog.is_running, cs_watchdog.watchdog);
80636fd0130Shoumkh return Ok(());
80736fd0130Shoumkh }
80836fd0130Shoumkh
80936fd0130Shoumkh drop(cs_watchdog);
810b8ed3825SDonkey Kane let watchdog_list = WATCHDOG_LIST.lock_irqsave();
81136fd0130Shoumkh for cs in watchdog_list.iter() {
81236fd0130Shoumkh let mut cs_data = cs.clocksource_data();
81336fd0130Shoumkh // 判断时钟源是否已经被标记为不稳定
81436fd0130Shoumkh if cs_data
81536fd0130Shoumkh .flags
81636fd0130Shoumkh .contains(ClocksourceFlags::CLOCK_SOURCE_UNSTABLE)
81736fd0130Shoumkh {
8182eab6dd7S曾俊 // debug!("clocksource_watchdog unstable");
81936fd0130Shoumkh // 启动watchdog_kthread
820af097f9fS黄铭涛 if FINISHED_BOOTING.load(Ordering::Relaxed) {
821af097f9fS黄铭涛 // TODO 在实现了工作队列后,将启动线程换成schedule work
822b8ed3825SDonkey Kane run_watchdog_kthread();
823af097f9fS黄铭涛 }
82436fd0130Shoumkh continue;
82536fd0130Shoumkh }
826af097f9fS黄铭涛
82736fd0130Shoumkh // 读取时钟源现在的时间
82836fd0130Shoumkh let cs_now_clock = cs.read();
829af097f9fS黄铭涛 // 读取watchdog现在的时间
830af097f9fS黄铭涛 let wd = CLOCKSOURCE_WATCHDOG.lock_irqsave();
831af097f9fS黄铭涛 let wd_now = wd.watchdog.as_ref().unwrap().clone();
832af097f9fS黄铭涛 let wd_now_data = wd_now.as_ref().clocksource_data();
833af097f9fS黄铭涛 let wd_now_clock = wd_now.as_ref().read().data();
834af097f9fS黄铭涛
835af097f9fS黄铭涛 // info!("cs_name = {:?}", cs_data.name);
836af097f9fS黄铭涛 // info!("cs_last = {:?}", cs_data.cs_last);
837af097f9fS黄铭涛 // info!("cs_now_clock = {:?}", cs_now_clock);
838af097f9fS黄铭涛 // info!("wd_name");
839af097f9fS黄铭涛 // info!("wd_last = {:?}", cs_data.watchdog_last);
840af097f9fS黄铭涛 // info!("wd_now_clock = {:?}", wd_now_clock);
84136fd0130Shoumkh
84236fd0130Shoumkh // 如果时钟源没有被监视,则开始监视他
84336fd0130Shoumkh if !cs_data
84436fd0130Shoumkh .flags
84536fd0130Shoumkh .contains(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG)
84636fd0130Shoumkh {
8472eab6dd7S曾俊 // debug!("clocksource_watchdog start watch");
84836fd0130Shoumkh cs_data
84936fd0130Shoumkh .flags
85036fd0130Shoumkh .insert(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG);
85136fd0130Shoumkh // 记录此次检查的时刻
852af097f9fS黄铭涛 cs_data.watchdog_last = CycleNum::new(wd_now_clock);
853af097f9fS黄铭涛 cs_data.cs_last = cs_now_clock;
85436fd0130Shoumkh cs.update_clocksource_data(cs_data.clone())?;
85536fd0130Shoumkh continue;
85636fd0130Shoumkh }
857af097f9fS黄铭涛
858af097f9fS黄铭涛 let wd_dev_nsec = clocksource_cyc2ns(
859af097f9fS黄铭涛 CycleNum((wd_now_clock - cs_data.watchdog_last.data()) & wd_now_data.mask.bits),
860af097f9fS黄铭涛 wd_now_data.mult,
861af097f9fS黄铭涛 wd_now_data.shift,
862af097f9fS黄铭涛 );
863af097f9fS黄铭涛
86436fd0130Shoumkh let cs_dev_nsec = clocksource_cyc2ns(
865af097f9fS黄铭涛 CycleNum(cs_now_clock.div(cs_data.cs_last).data() & cs_data.mask.bits),
866af097f9fS黄铭涛 cs_data.mult, // 2343484437
867af097f9fS黄铭涛 cs_data.shift, // 23
86836fd0130Shoumkh );
86936fd0130Shoumkh // 记录此次检查的时刻
870af097f9fS黄铭涛 cs_data.watchdog_last = CycleNum::new(wd_now_clock);
871af097f9fS黄铭涛 cs_data.cs_last = cs_now_clock;
87236fd0130Shoumkh cs.update_clocksource_data(cs_data.clone())?;
873af097f9fS黄铭涛
874af097f9fS黄铭涛 // 判断是否有误差
87536fd0130Shoumkh if cs_dev_nsec.abs_diff(wd_dev_nsec) > WATCHDOG_THRESHOLD.into() {
8762eab6dd7S曾俊 // debug!("set_unstable");
87736fd0130Shoumkh // 误差过大,标记为unstable
8782eab6dd7S曾俊 info!("cs_dev_nsec = {}", cs_dev_nsec);
8792eab6dd7S曾俊 info!("wd_dev_nsec = {}", wd_dev_nsec);
880af097f9fS黄铭涛 cs.set_unstable(cs_dev_nsec.abs_diff(wd_dev_nsec).try_into().unwrap())?;
88136fd0130Shoumkh continue;
88236fd0130Shoumkh }
88336fd0130Shoumkh
88436fd0130Shoumkh // 判断是否要切换为高精度模式
88536fd0130Shoumkh if !cs_data
88636fd0130Shoumkh .flags
88736fd0130Shoumkh .contains(ClocksourceFlags::CLOCK_SOURCE_VALID_FOR_HRES)
88836fd0130Shoumkh && cs_data
88936fd0130Shoumkh .flags
89036fd0130Shoumkh .contains(ClocksourceFlags::CLOCK_SOURCE_IS_CONTINUOUS)
891af097f9fS黄铭涛 && wd_now_data
89236fd0130Shoumkh .flags
89336fd0130Shoumkh .contains(ClocksourceFlags::CLOCK_SOURCE_IS_CONTINUOUS)
89436fd0130Shoumkh {
89536fd0130Shoumkh cs_data
89636fd0130Shoumkh .flags
89736fd0130Shoumkh .insert(ClocksourceFlags::CLOCK_SOURCE_VALID_FOR_HRES);
89836fd0130Shoumkh cs.update_clocksource_data(cs_data)?;
89936fd0130Shoumkh // TODO 通知tick机制 切换为高精度模式
90036fd0130Shoumkh }
901b8ed3825SDonkey Kane }
902b8ed3825SDonkey Kane create_new_watchdog_timer_function();
903b8ed3825SDonkey Kane return Ok(());
904b8ed3825SDonkey Kane }
905b8ed3825SDonkey Kane
create_new_watchdog_timer_function()906b8ed3825SDonkey Kane fn create_new_watchdog_timer_function() {
907af097f9fS黄铭涛 let mut cs_watchdog = CLOCKSOURCE_WATCHDOG.lock_irqsave();
908b8ed3825SDonkey Kane
90936fd0130Shoumkh cs_watchdog.timer_expires += WATCHDOG_INTERVAL;
91036fd0130Shoumkh //创建定时器执行watchdog
91136fd0130Shoumkh let watchdog_func = Box::new(WatchdogTimerFunc {});
91236fd0130Shoumkh let watchdog_timer = Timer::new(watchdog_func, cs_watchdog.timer_expires);
91336fd0130Shoumkh watchdog_timer.activate();
91436fd0130Shoumkh }
91536fd0130Shoumkh
__clocksource_watchdog_kthread()916b8ed3825SDonkey Kane fn __clocksource_watchdog_kthread() {
91736fd0130Shoumkh let mut del_vec: Vec<usize> = Vec::new();
91836fd0130Shoumkh let mut del_clocks: Vec<Arc<dyn Clocksource>> = Vec::new();
919b8ed3825SDonkey Kane let mut wd_list = WATCHDOG_LIST.lock_irqsave();
92036fd0130Shoumkh
92136fd0130Shoumkh // 将不稳定的时钟源弹出监视链表
92236fd0130Shoumkh for (pos, ele) in wd_list.iter().enumerate() {
92336fd0130Shoumkh let data = ele.clocksource_data();
92436fd0130Shoumkh if data.flags.contains(ClocksourceFlags::CLOCK_SOURCE_UNSTABLE) {
92536fd0130Shoumkh del_vec.push(pos);
92636fd0130Shoumkh del_clocks.push(ele.clone());
92736fd0130Shoumkh }
92836fd0130Shoumkh }
92936fd0130Shoumkh for pos in del_vec {
93036fd0130Shoumkh let mut temp_list = wd_list.split_off(pos);
93136fd0130Shoumkh temp_list.pop_front();
93236fd0130Shoumkh wd_list.append(&mut temp_list);
93336fd0130Shoumkh }
93436fd0130Shoumkh
93536fd0130Shoumkh // 检查是否需要停止watchdog
936af097f9fS黄铭涛 CLOCKSOURCE_WATCHDOG
937b8ed3825SDonkey Kane .lock_irqsave()
93836fd0130Shoumkh .clocksource_stop_watchdog(wd_list.len());
939b8ed3825SDonkey Kane drop(wd_list);
940b8ed3825SDonkey Kane // 将不稳定的时钟源精度都设置为最低,然后删除unstable标记
94136fd0130Shoumkh for clock in del_clocks.iter() {
94236fd0130Shoumkh clock.clocksource_change_rating(0);
94336fd0130Shoumkh }
94436fd0130Shoumkh }
94536fd0130Shoumkh
946b8ed3825SDonkey Kane /// # watchdog线程的逻辑,执行unstable的后续操作
clocksource_watchdog_kthread() -> i32947b8ed3825SDonkey Kane pub fn clocksource_watchdog_kthread() -> i32 {
948b8ed3825SDonkey Kane // return 0;
949b8ed3825SDonkey Kane loop {
9502eab6dd7S曾俊 // debug!("clocksource_watchdog_kthread start");
951b8ed3825SDonkey Kane __clocksource_watchdog_kthread();
952b8ed3825SDonkey Kane if KernelThreadMechanism::should_stop(&ProcessManager::current_pcb()) {
953b8ed3825SDonkey Kane break;
954b8ed3825SDonkey Kane }
955b8ed3825SDonkey Kane let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
956b8ed3825SDonkey Kane ProcessManager::mark_sleep(true).expect("clocksource_watchdog_kthread:mark sleep failed");
957b8ed3825SDonkey Kane drop(irq_guard);
958f0c87a89SGnoCiYeH schedule(SchedMode::SM_NONE);
959b8ed3825SDonkey Kane }
960b8ed3825SDonkey Kane return 0;
961b8ed3825SDonkey Kane }
962b8ed3825SDonkey Kane
96336fd0130Shoumkh /// # 清空所有时钟源的watchdog标志位
clocksource_reset_watchdog()96436fd0130Shoumkh pub fn clocksource_reset_watchdog() {
965b8ed3825SDonkey Kane let list_guard = WATCHDOG_LIST.lock_irqsave();
96636fd0130Shoumkh for ele in list_guard.iter() {
96736fd0130Shoumkh ele.clocksource_data()
96836fd0130Shoumkh .flags
96936fd0130Shoumkh .remove(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG);
97036fd0130Shoumkh }
97136fd0130Shoumkh }
97236fd0130Shoumkh
97336fd0130Shoumkh /// # 重启检查器
clocksource_resume_watchdog()97436fd0130Shoumkh pub fn clocksource_resume_watchdog() {
97536fd0130Shoumkh clocksource_reset_watchdog();
97636fd0130Shoumkh }
97736fd0130Shoumkh
97836fd0130Shoumkh /// # 根据精度选择最优的时钟源,或者接受用户指定的时间源
clocksource_select()97936fd0130Shoumkh pub fn clocksource_select() {
98036fd0130Shoumkh let list_guard = CLOCKSOURCE_LIST.lock();
981af097f9fS黄铭涛 if !FINISHED_BOOTING.load(Ordering::Relaxed) || list_guard.is_empty() {
98236fd0130Shoumkh return;
98336fd0130Shoumkh }
98436fd0130Shoumkh let mut best = list_guard.front().unwrap().clone();
98536fd0130Shoumkh let override_name = OVERRIDE_NAME.lock();
98636fd0130Shoumkh // 判断是否有用户空间指定的时间源
98736fd0130Shoumkh for ele in list_guard.iter() {
98836fd0130Shoumkh if ele.clocksource_data().name.eq(override_name.deref()) {
98936fd0130Shoumkh // TODO 判断是否是高精度模式
99036fd0130Shoumkh // 暂时不支持高精度模式
99136fd0130Shoumkh // 如果是高精度模式,但是时钟源不支持高精度模式的话,就要退出循环
99236fd0130Shoumkh best = ele.clone();
99336fd0130Shoumkh break;
99436fd0130Shoumkh }
99536fd0130Shoumkh }
99636fd0130Shoumkh // 对比当前的时钟源和记录到最好的时钟源的精度
99736fd0130Shoumkh if CUR_CLOCKSOURCE.lock().as_ref().is_some() {
99836fd0130Shoumkh // 当前时钟源不为空
99936fd0130Shoumkh let cur_clocksource = CUR_CLOCKSOURCE.lock().as_ref().unwrap().clone();
100036fd0130Shoumkh let best_name = &best.clocksource_data().name;
100136fd0130Shoumkh if cur_clocksource.clocksource_data().name.ne(best_name) {
10022eab6dd7S曾俊 info!("Switching to the clocksource {:?}\n", best_name);
100336fd0130Shoumkh drop(cur_clocksource);
100492deae63SLoGin CUR_CLOCKSOURCE.lock().replace(best.clone());
100536fd0130Shoumkh // TODO 通知timerkeeping 切换了时间源
100636fd0130Shoumkh }
100736fd0130Shoumkh } else {
100836fd0130Shoumkh // 当前时钟源为空
100992deae63SLoGin CUR_CLOCKSOURCE.lock().replace(best.clone());
101036fd0130Shoumkh }
10112eab6dd7S曾俊 debug!("clocksource_select finish, CUR_CLOCKSOURCE = {best:?}");
101236fd0130Shoumkh }
101336fd0130Shoumkh
101436fd0130Shoumkh /// # clocksource模块加载完成
clocksource_boot_finish()101536fd0130Shoumkh pub fn clocksource_boot_finish() {
101636fd0130Shoumkh let mut cur_clocksource = CUR_CLOCKSOURCE.lock();
101736fd0130Shoumkh cur_clocksource.replace(clocksource_default_clock());
101892deae63SLoGin FINISHED_BOOTING.store(true, Ordering::Relaxed);
101936fd0130Shoumkh // 清除不稳定的时钟源
1020b8ed3825SDonkey Kane __clocksource_watchdog_kthread();
10212eab6dd7S曾俊 debug!("clocksource_boot_finish");
102236fd0130Shoumkh }
102336fd0130Shoumkh
run_watchdog_kthread()1024b8ed3825SDonkey Kane fn run_watchdog_kthread() {
1025b8ed3825SDonkey Kane if let Some(watchdog_kthread) = unsafe { WATCHDOG_KTHREAD.clone() } {
1026b8ed3825SDonkey Kane ProcessManager::wakeup(&watchdog_kthread).ok();
1027b8ed3825SDonkey Kane }
1028b8ed3825SDonkey Kane }
102936fd0130Shoumkh
1030b8ed3825SDonkey Kane #[unified_init(INITCALL_LATE)]
init_watchdog_kthread() -> Result<(), SystemError>1031b8ed3825SDonkey Kane pub fn init_watchdog_kthread() -> Result<(), SystemError> {
1032b8ed3825SDonkey Kane assert!(CurrentIrqArch::is_irq_enabled());
1033b8ed3825SDonkey Kane let closure = KernelThreadClosure::StaticEmptyClosure((
1034b8ed3825SDonkey Kane &(clocksource_watchdog_kthread as fn() -> i32),
1035b8ed3825SDonkey Kane (),
1036b8ed3825SDonkey Kane ));
1037b8ed3825SDonkey Kane let pcb = KernelThreadMechanism::create_and_run(closure, "clocksource watchdog".to_string())
1038b8ed3825SDonkey Kane .ok_or(SystemError::EPERM)?;
1039b8ed3825SDonkey Kane unsafe {
1040b8ed3825SDonkey Kane WATCHDOG_KTHREAD.replace(pcb);
1041b8ed3825SDonkey Kane }
1042b8ed3825SDonkey Kane
1043b8ed3825SDonkey Kane return Ok(());
104436fd0130Shoumkh }
1045