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 44*af097f9fS黄铭涛 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)] 78b8ed3825SDonkey Kane pub const fn new(cycle: u64) -> Self { 7936fd0130Shoumkh Self(cycle) 8036fd0130Shoumkh } 8136fd0130Shoumkh #[inline(always)] 82b8ed3825SDonkey Kane pub const fn data(&self) -> u64 { 8336fd0130Shoumkh self.0 8436fd0130Shoumkh } 8536fd0130Shoumkh #[inline(always)] 8636fd0130Shoumkh #[allow(dead_code)] 8736fd0130Shoumkh pub fn add(&self, other: CycleNum) -> CycleNum { 8836fd0130Shoumkh CycleNum(self.data() + other.data()) 8936fd0130Shoumkh } 9036fd0130Shoumkh #[inline(always)] 9136fd0130Shoumkh 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 { 11736fd0130Shoumkh 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 { 12536fd0130Shoumkh pub fn new(b: u64) -> Self { 12636fd0130Shoumkh Self { bits: b } 12736fd0130Shoumkh } 12836fd0130Shoumkh } 12936fd0130Shoumkh impl ClocksourceFlags { 13036fd0130Shoumkh 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 { 14536fd0130Shoumkh pub fn new() -> Self { 14636fd0130Shoumkh Self { 14736fd0130Shoumkh watchdog: None, 14836fd0130Shoumkh is_running: false, 14936fd0130Shoumkh timer_expires: 0, 15036fd0130Shoumkh } 15136fd0130Shoumkh } 15236fd0130Shoumkh 15336fd0130Shoumkh /// 获取watchdog 15436fd0130Shoumkh fn get_watchdog(&mut self) -> &mut Option<Arc<dyn Clocksource>> { 15536fd0130Shoumkh &mut self.watchdog 15636fd0130Shoumkh } 15736fd0130Shoumkh 15836fd0130Shoumkh /// 启用检查器 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; 168*af097f9fS黄铭涛 let mut wd_data = self.watchdog.as_ref().unwrap().clone().clocksource_data(); 169*af097f9fS黄铭涛 wd_data.watchdog_last = self.watchdog.as_ref().unwrap().clone().read(); 170*af097f9fS黄铭涛 self.watchdog 171*af097f9fS黄铭涛 .as_ref() 172*af097f9fS黄铭涛 .unwrap() 173*af097f9fS黄铭涛 .update_clocksource_data(wd_data) 174*af097f9fS黄铭涛 .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长度 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 { 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 20436fd0130Shoumkh fn read(&self) -> CycleNum; 20536fd0130Shoumkh /// optional function to enable the clocksource 20636fd0130Shoumkh fn enable(&self) -> Result<i32, SystemError> { 2071074eb34SSamuel Dai return Err(SystemError::ENOSYS); 20836fd0130Shoumkh } 20936fd0130Shoumkh /// optional function to disable the clocksource 21036fd0130Shoumkh fn disable(&self) -> Result<(), SystemError> { 2111074eb34SSamuel Dai return Err(SystemError::ENOSYS); 21236fd0130Shoumkh } 21336fd0130Shoumkh /// vsyscall based read 21436fd0130Shoumkh fn vread(&self) -> Result<CycleNum, SystemError> { 2151074eb34SSamuel Dai return Err(SystemError::ENOSYS); 21636fd0130Shoumkh } 21736fd0130Shoumkh /// suspend function for the clocksource, if necessary 21836fd0130Shoumkh fn suspend(&self) -> Result<(), SystemError> { 2191074eb34SSamuel Dai return Err(SystemError::ENOSYS); 22036fd0130Shoumkh } 22136fd0130Shoumkh /// resume function for the clocksource, if necessary 22236fd0130Shoumkh fn resume(&self) -> Result<(), SystemError> { 2231074eb34SSamuel Dai return Err(SystemError::ENOSYS); 22436fd0130Shoumkh } 22536fd0130Shoumkh // 获取时钟源数据 22636fd0130Shoumkh fn clocksource_data(&self) -> ClocksourceData; 22736fd0130Shoumkh 22836fd0130Shoumkh fn update_clocksource_data(&self, _data: ClocksourceData) -> Result<(), SystemError> { 2291074eb34SSamuel Dai return Err(SystemError::ENOSYS); 23036fd0130Shoumkh } 23136fd0130Shoumkh // 获取时钟源 23236fd0130Shoumkh fn clocksource(&self) -> Arc<dyn Clocksource>; 23336fd0130Shoumkh } 23436fd0130Shoumkh 23536fd0130Shoumkh /// # 实现整数log2的运算 23636fd0130Shoumkh /// 23736fd0130Shoumkh /// ## 参数 23836fd0130Shoumkh /// 23936fd0130Shoumkh /// * `x` - 要计算的数字 24036fd0130Shoumkh /// 24136fd0130Shoumkh /// ## 返回值 24236fd0130Shoumkh /// 24336fd0130Shoumkh /// * `u32` - 返回\log_2(x)的值 24436fd0130Shoumkh fn log2(x: u32) -> u32 { 24536fd0130Shoumkh let mut result = 0; 24636fd0130Shoumkh let mut x = x; 24736fd0130Shoumkh 24836fd0130Shoumkh if x >= 1 << 16 { 24936fd0130Shoumkh x >>= 16; 25036fd0130Shoumkh result |= 16; 25136fd0130Shoumkh } 25236fd0130Shoumkh if x >= 1 << 8 { 25336fd0130Shoumkh x >>= 8; 25436fd0130Shoumkh result |= 8; 25536fd0130Shoumkh } 25636fd0130Shoumkh if x >= 1 << 4 { 25736fd0130Shoumkh x >>= 4; 25836fd0130Shoumkh result |= 4; 25936fd0130Shoumkh } 26036fd0130Shoumkh if x >= 1 << 2 { 26136fd0130Shoumkh x >>= 2; 26236fd0130Shoumkh result |= 2; 26336fd0130Shoumkh } 26436fd0130Shoumkh if x >= 1 << 1 { 26536fd0130Shoumkh result |= 1; 26636fd0130Shoumkh } 26736fd0130Shoumkh 26836fd0130Shoumkh result 26936fd0130Shoumkh } 27036fd0130Shoumkh 27136fd0130Shoumkh impl dyn Clocksource { 27236fd0130Shoumkh /// # 计算时钟源能记录的最大时间跨度 27336fd0130Shoumkh pub fn clocksource_max_deferment(&self) -> u64 { 27436fd0130Shoumkh let cs_data_guard = self.clocksource_data(); 275840045afSLoGin 27636fd0130Shoumkh let mut max_cycles: u64; 277*af097f9fS黄铭涛 max_cycles = (1 << (63 - (log2(cs_data_guard.mult + cs_data_guard.maxadj) + 1))) as u64; 27836fd0130Shoumkh max_cycles = max_cycles.min(cs_data_guard.mask.bits); 279840045afSLoGin let max_nsecs = clocksource_cyc2ns( 28036fd0130Shoumkh CycleNum(max_cycles), 281*af097f9fS黄铭涛 cs_data_guard.mult - cs_data_guard.maxadj, 28236fd0130Shoumkh cs_data_guard.shift, 28336fd0130Shoumkh ); 284*af097f9fS黄铭涛 return max_nsecs - (max_nsecs >> 3); 28536fd0130Shoumkh } 28636fd0130Shoumkh 287dd8e74efSMingtao Huang /// # 计算时钟源的mult和shift,以便将一个时钟源的频率转换为另一个时钟源的频率 288dd8e74efSMingtao Huang fn clocks_calc_mult_shift(&self, from: u32, to: u32, maxsec: u32) -> (u32, u32) { 289dd8e74efSMingtao Huang let mut sftacc: u32 = 32; 290dd8e74efSMingtao Huang let mut sft = 1; 291dd8e74efSMingtao Huang 292dd8e74efSMingtao Huang // 计算限制转换范围的shift 293dd8e74efSMingtao Huang let mut mult = (maxsec as u64 * from as u64) >> 32; 294dd8e74efSMingtao Huang while mult != 0 { 295dd8e74efSMingtao Huang mult >>= 1; 296dd8e74efSMingtao Huang sftacc -= 1; 297dd8e74efSMingtao Huang } 298dd8e74efSMingtao Huang 299dd8e74efSMingtao Huang // 找到最佳的mult和shift 300dd8e74efSMingtao Huang for i in (1..=32).rev() { 301dd8e74efSMingtao Huang sft = i; 302dd8e74efSMingtao Huang mult = (to as u64) << sft; 303dd8e74efSMingtao Huang mult += from as u64 / 2; 304dd8e74efSMingtao Huang mult /= from as u64; 305dd8e74efSMingtao Huang if (mult >> sftacc) == 0 { 306dd8e74efSMingtao Huang break; 307dd8e74efSMingtao Huang } 308dd8e74efSMingtao Huang } 309dd8e74efSMingtao Huang 310dd8e74efSMingtao Huang return (mult as u32, sft); 311dd8e74efSMingtao Huang } 312dd8e74efSMingtao Huang 313dd8e74efSMingtao Huang /// # 计算时钟源可以进行的最大调整量 314dd8e74efSMingtao Huang fn clocksource_max_adjustment(&self) -> u32 { 315dd8e74efSMingtao Huang let cs_data = self.clocksource_data(); 316dd8e74efSMingtao Huang let ret = cs_data.mult as u64 * 11 / 100; 317dd8e74efSMingtao Huang 318dd8e74efSMingtao Huang return ret as u32; 319dd8e74efSMingtao Huang } 320dd8e74efSMingtao Huang 321dd8e74efSMingtao Huang /// # 更新时钟源频率,初始化mult/shift 和 max_idle_ns 322dd8e74efSMingtao Huang fn clocksource_update_freq_scale(&self, scale: u32, freq: u32) -> Result<(), SystemError> { 323dd8e74efSMingtao Huang if freq != 0 { 324*af097f9fS黄铭涛 let mut cs_data = self.clocksource_data(); 325dd8e74efSMingtao Huang let mut sec: u64 = cs_data.mask.bits(); 326dd8e74efSMingtao Huang 327dd8e74efSMingtao Huang sec /= freq as u64; 328dd8e74efSMingtao Huang sec /= scale as u64; 329dd8e74efSMingtao Huang if sec == 0 { 330dd8e74efSMingtao Huang sec = 1; 331dd8e74efSMingtao Huang } else if sec > 600 && cs_data.mask.bits() > u32::MAX as u64 { 332dd8e74efSMingtao Huang sec = 600; 333dd8e74efSMingtao Huang } 334dd8e74efSMingtao Huang 335dd8e74efSMingtao Huang let (mult, shift) = 336dd8e74efSMingtao Huang self.clocks_calc_mult_shift(freq, NSEC_PER_SEC / scale, sec as u32 * scale); 337dd8e74efSMingtao Huang cs_data.set_mult(mult); 338dd8e74efSMingtao Huang cs_data.set_shift(shift); 339*af097f9fS黄铭涛 self.update_clocksource_data(cs_data)?; 340dd8e74efSMingtao Huang } 341dd8e74efSMingtao Huang 342*af097f9fS黄铭涛 let mut cs_data = self.clocksource_data(); 343dd8e74efSMingtao Huang if scale != 0 && freq != 0 && cs_data.uncertainty_margin == 0 { 344dd8e74efSMingtao Huang cs_data.set_uncertainty_margin(NSEC_PER_SEC / (scale * freq)); 345dd8e74efSMingtao Huang if cs_data.uncertainty_margin < 2 * WATCHDOG_MAX_SKEW { 346dd8e74efSMingtao Huang cs_data.set_uncertainty_margin(2 * WATCHDOG_MAX_SKEW); 347dd8e74efSMingtao Huang } 348dd8e74efSMingtao Huang } else if cs_data.uncertainty_margin == 0 { 349dd8e74efSMingtao Huang cs_data.set_uncertainty_margin(WATCHDOG_THRESHOLD); 350dd8e74efSMingtao Huang } 351dd8e74efSMingtao Huang 352dd8e74efSMingtao Huang // 确保时钟源没有太大的mult值造成溢出 353dd8e74efSMingtao Huang cs_data.set_maxadj(self.clocksource_max_adjustment()); 354*af097f9fS黄铭涛 self.update_clocksource_data(cs_data)?; 355*af097f9fS黄铭涛 while freq != 0 356*af097f9fS黄铭涛 && (self.clocksource_data().mult + self.clocksource_data().maxadj 357*af097f9fS黄铭涛 < self.clocksource_data().mult 358*af097f9fS黄铭涛 || self.clocksource_data().mult - self.clocksource_data().maxadj 359*af097f9fS黄铭涛 > self.clocksource_data().mult) 360*af097f9fS黄铭涛 { 361*af097f9fS黄铭涛 let mut cs_data = self.clocksource_data(); 362*af097f9fS黄铭涛 cs_data.set_mult(cs_data.mult >> 1); 363*af097f9fS黄铭涛 cs_data.set_shift(cs_data.shift - 1); 364*af097f9fS黄铭涛 self.update_clocksource_data(cs_data)?; 365*af097f9fS黄铭涛 let mut cs_data = self.clocksource_data(); 366*af097f9fS黄铭涛 cs_data.set_maxadj(self.clocksource_max_adjustment()); 367*af097f9fS黄铭涛 self.update_clocksource_data(cs_data)?; 368*af097f9fS黄铭涛 } 369dd8e74efSMingtao Huang 370*af097f9fS黄铭涛 let mut cs_data = self.clocksource_data(); 371dd8e74efSMingtao Huang let ns = self.clocksource_max_deferment(); 372dd8e74efSMingtao Huang cs_data.set_max_idle_ns(ns as u32); 373dd8e74efSMingtao Huang self.update_clocksource_data(cs_data)?; 374dd8e74efSMingtao Huang 375dd8e74efSMingtao Huang return Ok(()); 376dd8e74efSMingtao Huang } 377dd8e74efSMingtao Huang 37836fd0130Shoumkh /// # 注册时钟源 37936fd0130Shoumkh /// 380dd8e74efSMingtao Huang /// ## 参数 381dd8e74efSMingtao Huang /// 382dd8e74efSMingtao Huang /// - scale: 如果freq单位为0或hz,此值为1,如果为khz,此值为1000 383dd8e74efSMingtao Huang /// - freq: 时钟源的频率,jiffies注册时此值为0 384dd8e74efSMingtao Huang /// 38536fd0130Shoumkh /// ## 返回值 38636fd0130Shoumkh /// 38736fd0130Shoumkh /// * `Ok(0)` - 时钟源注册成功。 38836fd0130Shoumkh /// * `Err(SystemError)` - 时钟源注册失败。 389dd8e74efSMingtao Huang pub fn register(&self, scale: u32, freq: u32) -> Result<(), SystemError> { 390dd8e74efSMingtao Huang self.clocksource_update_freq_scale(scale, freq)?; 391dd8e74efSMingtao Huang 39236fd0130Shoumkh // 将时钟源加入到时钟源队列中 39336fd0130Shoumkh self.clocksource_enqueue(); 39436fd0130Shoumkh // 将时钟源加入到监视队列中 39536fd0130Shoumkh self.clocksource_enqueue_watchdog() 39636fd0130Shoumkh .expect("register: failed to enqueue watchdog list"); 39736fd0130Shoumkh // 选择一个最好的时钟源 39836fd0130Shoumkh clocksource_select(); 3992eab6dd7S曾俊 debug!("clocksource_register successfully"); 400dd8e74efSMingtao Huang return Ok(()); 40136fd0130Shoumkh } 40236fd0130Shoumkh 40336fd0130Shoumkh /// # 将时钟源插入时钟源队列 40436fd0130Shoumkh pub fn clocksource_enqueue(&self) { 40536fd0130Shoumkh // 根据rating由大到小排序 40636fd0130Shoumkh let cs_data = self.clocksource_data(); 407b8ed3825SDonkey Kane let mut list_guard = CLOCKSOURCE_LIST.lock(); 408*af097f9fS黄铭涛 let mut spilt_pos: usize = list_guard.len(); 40936fd0130Shoumkh for (pos, ele) in list_guard.iter().enumerate() { 41036fd0130Shoumkh if ele.clocksource_data().rating < cs_data.rating { 41136fd0130Shoumkh spilt_pos = pos; 41236fd0130Shoumkh break; 41336fd0130Shoumkh } 41436fd0130Shoumkh } 41536fd0130Shoumkh let mut temp_list = list_guard.split_off(spilt_pos); 41636fd0130Shoumkh let cs = self.clocksource(); 41736fd0130Shoumkh list_guard.push_back(cs); 41836fd0130Shoumkh list_guard.append(&mut temp_list); 4192eab6dd7S曾俊 // debug!( 42036fd0130Shoumkh // "CLOCKSOURCE_LIST len = {:?},clocksource_enqueue sccessfully", 42136fd0130Shoumkh // list_guard.len() 42236fd0130Shoumkh // ); 42336fd0130Shoumkh } 42436fd0130Shoumkh 42536fd0130Shoumkh /// # 将时间源插入监控队列 42636fd0130Shoumkh /// 42736fd0130Shoumkh /// ## 返回值 42836fd0130Shoumkh /// 42936fd0130Shoumkh /// * `Ok(0)` - 时间源插入监控队列成功 43036fd0130Shoumkh /// * `Err(SystemError)` - 时间源插入监控队列失败 43136fd0130Shoumkh pub fn clocksource_enqueue_watchdog(&self) -> Result<i32, SystemError> { 43236fd0130Shoumkh // BUG 可能需要lock irq 43336fd0130Shoumkh let mut cs_data = self.clocksource_data(); 43436fd0130Shoumkh 43536fd0130Shoumkh let cs = self.clocksource(); 43636fd0130Shoumkh if cs_data 43736fd0130Shoumkh .flags 43836fd0130Shoumkh .contains(ClocksourceFlags::CLOCK_SOURCE_MUST_VERIFY) 43936fd0130Shoumkh { 44036fd0130Shoumkh let mut list_guard = WATCHDOG_LIST.lock_irqsave(); 44136fd0130Shoumkh // cs是被监视的 44236fd0130Shoumkh cs_data 44336fd0130Shoumkh .flags 44436fd0130Shoumkh .remove(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG); 44536fd0130Shoumkh cs.update_clocksource_data(cs_data)?; 44636fd0130Shoumkh list_guard.push_back(cs); 44736fd0130Shoumkh } else { 44836fd0130Shoumkh // cs是监视器 44936fd0130Shoumkh if cs_data 45036fd0130Shoumkh .flags 45136fd0130Shoumkh .contains(ClocksourceFlags::CLOCK_SOURCE_IS_CONTINUOUS) 45236fd0130Shoumkh { 45336fd0130Shoumkh // 如果时钟设备是连续的 45436fd0130Shoumkh cs_data 45536fd0130Shoumkh .flags 45636fd0130Shoumkh .insert(ClocksourceFlags::CLOCK_SOURCE_VALID_FOR_HRES); 45736fd0130Shoumkh cs.update_clocksource_data(cs_data.clone())?; 45836fd0130Shoumkh } 45936fd0130Shoumkh 46036fd0130Shoumkh // 将时钟源加入到监控队列中 461b8ed3825SDonkey Kane let mut list_guard = WATCHDOG_LIST.lock_irqsave(); 46236fd0130Shoumkh list_guard.push_back(cs.clone()); 46336fd0130Shoumkh drop(list_guard); 46436fd0130Shoumkh 46536fd0130Shoumkh // 对比当前注册的时间源的精度和监视器的精度 466*af097f9fS黄铭涛 let mut cs_watchdog = CLOCKSOURCE_WATCHDOG.lock_irqsave(); 46736fd0130Shoumkh if cs_watchdog.watchdog.is_none() 46836fd0130Shoumkh || cs_data.rating 46936fd0130Shoumkh > cs_watchdog 47036fd0130Shoumkh .watchdog 47136fd0130Shoumkh .clone() 47236fd0130Shoumkh .unwrap() 47336fd0130Shoumkh .clocksource_data() 47436fd0130Shoumkh .rating 47536fd0130Shoumkh { 47636fd0130Shoumkh // 当前注册的时间源的精度更高或者没有监视器,替换监视器 47736fd0130Shoumkh cs_watchdog.watchdog.replace(cs); 47836fd0130Shoumkh clocksource_reset_watchdog(); 47936fd0130Shoumkh } 48036fd0130Shoumkh 48136fd0130Shoumkh // 启动监视器 48236fd0130Shoumkh cs_watchdog.clocksource_start_watchdog(); 48336fd0130Shoumkh } 48436fd0130Shoumkh return Ok(0); 48536fd0130Shoumkh } 48636fd0130Shoumkh 48736fd0130Shoumkh /// # 将时钟源标记为unstable 48836fd0130Shoumkh /// 48936fd0130Shoumkh /// ## 参数 49036fd0130Shoumkh /// * `delta` - 时钟源误差 49136fd0130Shoumkh pub fn set_unstable(&self, delta: i64) -> Result<i32, SystemError> { 49236fd0130Shoumkh let mut cs_data = self.clocksource_data(); 49336fd0130Shoumkh // 打印出unstable的时钟源信息 4942eab6dd7S曾俊 debug!( 49536fd0130Shoumkh "clocksource :{:?} is unstable, its delta is {:?}", 4962eab6dd7S曾俊 cs_data.name, delta 49736fd0130Shoumkh ); 49836fd0130Shoumkh cs_data.flags.remove( 49936fd0130Shoumkh ClocksourceFlags::CLOCK_SOURCE_VALID_FOR_HRES | ClocksourceFlags::CLOCK_SOURCE_WATCHDOG, 50036fd0130Shoumkh ); 50136fd0130Shoumkh cs_data 50236fd0130Shoumkh .flags 50336fd0130Shoumkh .insert(ClocksourceFlags::CLOCK_SOURCE_UNSTABLE); 50436fd0130Shoumkh self.update_clocksource_data(cs_data)?; 50536fd0130Shoumkh 50636fd0130Shoumkh // 启动watchdog线程 进行后续处理 50792deae63SLoGin if FINISHED_BOOTING.load(Ordering::Relaxed) { 50836fd0130Shoumkh // TODO 在实现了工作队列后,将启动线程换成schedule work 509b8ed3825SDonkey Kane run_watchdog_kthread(); 51036fd0130Shoumkh } 51136fd0130Shoumkh return Ok(0); 51236fd0130Shoumkh } 51336fd0130Shoumkh 51436fd0130Shoumkh /// # 将时间源从监视链表中弹出 51536fd0130Shoumkh fn clocksource_dequeue_watchdog(&self) { 51636fd0130Shoumkh let data = self.clocksource_data(); 517*af097f9fS黄铭涛 let mut locked_watchdog = CLOCKSOURCE_WATCHDOG.lock_irqsave(); 51836fd0130Shoumkh let watchdog = locked_watchdog 51936fd0130Shoumkh .get_watchdog() 52036fd0130Shoumkh .clone() 52136fd0130Shoumkh .unwrap() 52236fd0130Shoumkh .clocksource_data(); 52336fd0130Shoumkh 524b8ed3825SDonkey Kane let mut list = WATCHDOG_LIST.lock_irqsave(); 52536fd0130Shoumkh let mut size = list.len(); 52636fd0130Shoumkh 52736fd0130Shoumkh let mut del_pos: usize = size; 52836fd0130Shoumkh for (pos, ele) in list.iter().enumerate() { 52936fd0130Shoumkh let ele_data = ele.clocksource_data(); 53036fd0130Shoumkh if ele_data.name.eq(&data.name) && ele_data.rating.eq(&data.rating) { 53136fd0130Shoumkh // 记录要删除的时钟源在监视链表中的下标 53236fd0130Shoumkh del_pos = pos; 53336fd0130Shoumkh } 53436fd0130Shoumkh } 53536fd0130Shoumkh 53636fd0130Shoumkh if data 53736fd0130Shoumkh .flags 53836fd0130Shoumkh .contains(ClocksourceFlags::CLOCK_SOURCE_MUST_VERIFY) 53936fd0130Shoumkh { 54036fd0130Shoumkh // 如果时钟源是需要被检查的,直接删除时钟源 54136fd0130Shoumkh if del_pos != size { 54236fd0130Shoumkh let mut temp_list = list.split_off(del_pos); 54336fd0130Shoumkh temp_list.pop_front(); 54436fd0130Shoumkh list.append(&mut temp_list); 54536fd0130Shoumkh } 54636fd0130Shoumkh } else if watchdog.name.eq(&data.name) && watchdog.rating.eq(&data.rating) { 54736fd0130Shoumkh // 如果要删除的时钟源是监视器,则需要找到一个新的监视器 54836fd0130Shoumkh // TODO 重新设置时钟源 54936fd0130Shoumkh // 将链表解锁防止reset中双重加锁 并释放保存的旧的watchdog的数据 55036fd0130Shoumkh 55136fd0130Shoumkh // 代替了clocksource_reset_watchdog()的功能,将所有时钟源的watchdog标记清除 55236fd0130Shoumkh for ele in list.iter() { 55336fd0130Shoumkh ele.clocksource_data() 55436fd0130Shoumkh .flags 55536fd0130Shoumkh .remove(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG); 55636fd0130Shoumkh } 55736fd0130Shoumkh 55836fd0130Shoumkh // 遍历所有时间源,寻找新的监视器 55936fd0130Shoumkh let mut clocksource_list = CLOCKSOURCE_LIST.lock(); 56036fd0130Shoumkh let mut replace_pos: usize = clocksource_list.len(); 56136fd0130Shoumkh for (pos, ele) in clocksource_list.iter().enumerate() { 56236fd0130Shoumkh let ele_data = ele.clocksource_data(); 56336fd0130Shoumkh 56436fd0130Shoumkh if ele_data.name.eq(&data.name) && ele_data.rating.eq(&data.rating) 56536fd0130Shoumkh || ele_data 56636fd0130Shoumkh .flags 56736fd0130Shoumkh .contains(ClocksourceFlags::CLOCK_SOURCE_MUST_VERIFY) 56836fd0130Shoumkh { 56936fd0130Shoumkh // 当前时钟源是要被删除的时钟源或没被检查过的时钟源 57036fd0130Shoumkh // 不适合成为监视器 57136fd0130Shoumkh continue; 57236fd0130Shoumkh } 57336fd0130Shoumkh let watchdog = locked_watchdog.get_watchdog().clone(); 57436fd0130Shoumkh if watchdog.is_none() 57536fd0130Shoumkh || ele_data.rating > watchdog.unwrap().clocksource_data().rating 57636fd0130Shoumkh { 57736fd0130Shoumkh // 如果watchdog不存在或者当前时钟源的精度高于watchdog的精度,则记录当前时钟源的下标 57836fd0130Shoumkh replace_pos = pos; 57936fd0130Shoumkh } 58036fd0130Shoumkh } 58136fd0130Shoumkh // 使用刚刚找到的更好的时钟源替换旧的watchdog 58236fd0130Shoumkh if replace_pos < clocksource_list.len() { 58336fd0130Shoumkh let mut temp_list = clocksource_list.split_off(replace_pos); 58436fd0130Shoumkh let new_wd = temp_list.front().unwrap().clone(); 58536fd0130Shoumkh clocksource_list.append(&mut temp_list); 58636fd0130Shoumkh // 替换watchdog 58736fd0130Shoumkh locked_watchdog.watchdog.replace(new_wd); 58836fd0130Shoumkh // drop(locked_watchdog); 58936fd0130Shoumkh } 59036fd0130Shoumkh // 删除时钟源 59136fd0130Shoumkh if del_pos != size { 59236fd0130Shoumkh let mut temp_list = list.split_off(del_pos); 59336fd0130Shoumkh temp_list.pop_front(); 59436fd0130Shoumkh list.append(&mut temp_list); 59536fd0130Shoumkh } 59636fd0130Shoumkh } 59736fd0130Shoumkh 59836fd0130Shoumkh // 清除watchdog标记 59936fd0130Shoumkh let mut cs_data = self.clocksource_data(); 60036fd0130Shoumkh cs_data 60136fd0130Shoumkh .flags 60236fd0130Shoumkh .remove(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG); 60336fd0130Shoumkh self.update_clocksource_data(cs_data) 60436fd0130Shoumkh .expect("clocksource_dequeue_watchdog: failed to update clocksource data"); 60536fd0130Shoumkh size = list.len(); 60636fd0130Shoumkh // 停止当前的watchdog 60736fd0130Shoumkh locked_watchdog.clocksource_stop_watchdog(size - 1); 60836fd0130Shoumkh } 60936fd0130Shoumkh 61036fd0130Shoumkh /// # 将时钟源从时钟源链表中弹出 61136fd0130Shoumkh fn clocksource_dequeue(&self) { 61236fd0130Shoumkh let mut list = CLOCKSOURCE_LIST.lock(); 61336fd0130Shoumkh let data = self.clocksource_data(); 61436fd0130Shoumkh let mut del_pos: usize = list.len(); 61536fd0130Shoumkh for (pos, ele) in list.iter().enumerate() { 61636fd0130Shoumkh let ele_data = ele.clocksource_data(); 61736fd0130Shoumkh if ele_data.name.eq(&data.name) && ele_data.rating.eq(&data.rating) { 61836fd0130Shoumkh // 记录时钟源在链表中的下标 61936fd0130Shoumkh del_pos = pos; 62036fd0130Shoumkh } 62136fd0130Shoumkh } 62236fd0130Shoumkh 62336fd0130Shoumkh // 删除时钟源 62436fd0130Shoumkh if del_pos != list.len() { 62536fd0130Shoumkh let mut temp_list = list.split_off(del_pos); 62636fd0130Shoumkh temp_list.pop_front(); 62736fd0130Shoumkh list.append(&mut temp_list); 62836fd0130Shoumkh } 62936fd0130Shoumkh } 63036fd0130Shoumkh 63136fd0130Shoumkh /// # 注销时钟源 63236fd0130Shoumkh #[allow(dead_code)] 63336fd0130Shoumkh pub fn unregister(&self) { 63436fd0130Shoumkh // 将时钟源从监视链表中弹出 63536fd0130Shoumkh self.clocksource_dequeue_watchdog(); 63636fd0130Shoumkh // 将时钟源从时钟源链表中弹出 63736fd0130Shoumkh self.clocksource_dequeue(); 63836fd0130Shoumkh // 检查是否有更好的时钟源 63936fd0130Shoumkh clocksource_select(); 64036fd0130Shoumkh } 64136fd0130Shoumkh /// # 修改时钟源的精度 64236fd0130Shoumkh /// 64336fd0130Shoumkh /// ## 参数 64436fd0130Shoumkh /// 64536fd0130Shoumkh /// * `rating` - 指定的时钟精度 64636fd0130Shoumkh fn clocksource_change_rating(&self, rating: i32) { 64736fd0130Shoumkh // 将时钟源从链表中弹出 64836fd0130Shoumkh self.clocksource_dequeue(); 64936fd0130Shoumkh let mut data = self.clocksource_data(); 65036fd0130Shoumkh // 修改时钟源的精度 65136fd0130Shoumkh data.set_rating(rating); 65236fd0130Shoumkh self.update_clocksource_data(data) 65336fd0130Shoumkh .expect("clocksource_change_rating:updata clocksource failed"); 65436fd0130Shoumkh // 插入时钟源到时钟源链表中 65536fd0130Shoumkh self.clocksource_enqueue(); 65636fd0130Shoumkh // 检查是否有更好的时钟源 65736fd0130Shoumkh clocksource_select(); 65836fd0130Shoumkh } 65936fd0130Shoumkh } 66036fd0130Shoumkh 66136fd0130Shoumkh #[derive(Debug, Clone)] 66236fd0130Shoumkh pub struct ClocksourceData { 66336fd0130Shoumkh /// 时钟源名字 66436fd0130Shoumkh pub name: String, 66536fd0130Shoumkh /// 时钟精度 66636fd0130Shoumkh pub rating: i32, 66736fd0130Shoumkh pub mask: ClocksourceMask, 66836fd0130Shoumkh pub mult: u32, 66936fd0130Shoumkh pub shift: u32, 67036fd0130Shoumkh pub max_idle_ns: u32, 67136fd0130Shoumkh pub flags: ClocksourceFlags, 67236fd0130Shoumkh pub watchdog_last: CycleNum, 673*af097f9fS黄铭涛 /// 用于watchdog机制中的字段,记录主时钟源上一次被读取的周期数 674*af097f9fS黄铭涛 pub cs_last: CycleNum, 675dd8e74efSMingtao Huang // 用于描述时钟源的不确定性边界,时钟源读取的时间可能存在的不确定性和误差范围 676dd8e74efSMingtao Huang pub uncertainty_margin: u32, 677dd8e74efSMingtao Huang // 最大的时间调整量 678dd8e74efSMingtao Huang pub maxadj: u32, 679*af097f9fS黄铭涛 /// 上一次读取时钟源时的周期数 680*af097f9fS黄铭涛 pub cycle_last: CycleNum, 68136fd0130Shoumkh } 68236fd0130Shoumkh 68336fd0130Shoumkh impl ClocksourceData { 68436fd0130Shoumkh #[allow(dead_code)] 685dd8e74efSMingtao Huang #[allow(clippy::too_many_arguments)] 68636fd0130Shoumkh pub fn new( 68736fd0130Shoumkh name: String, 68836fd0130Shoumkh rating: i32, 68936fd0130Shoumkh mask: ClocksourceMask, 69036fd0130Shoumkh mult: u32, 69136fd0130Shoumkh shift: u32, 69236fd0130Shoumkh max_idle_ns: u32, 69336fd0130Shoumkh flags: ClocksourceFlags, 694dd8e74efSMingtao Huang uncertainty_margin: u32, 695dd8e74efSMingtao Huang maxadj: u32, 69636fd0130Shoumkh ) -> Self { 69736fd0130Shoumkh let csd = ClocksourceData { 69836fd0130Shoumkh name, 69936fd0130Shoumkh rating, 70036fd0130Shoumkh mask, 70136fd0130Shoumkh mult, 70236fd0130Shoumkh shift, 70336fd0130Shoumkh max_idle_ns, 70436fd0130Shoumkh flags, 70536fd0130Shoumkh watchdog_last: CycleNum(0), 706*af097f9fS黄铭涛 cs_last: CycleNum(0), 707dd8e74efSMingtao Huang uncertainty_margin, 708dd8e74efSMingtao Huang maxadj, 709*af097f9fS黄铭涛 cycle_last: CycleNum(0), 71036fd0130Shoumkh }; 71136fd0130Shoumkh return csd; 71236fd0130Shoumkh } 71336fd0130Shoumkh 71436fd0130Shoumkh pub fn set_name(&mut self, name: String) { 71536fd0130Shoumkh self.name = name; 71636fd0130Shoumkh } 71736fd0130Shoumkh pub fn set_rating(&mut self, rating: i32) { 71836fd0130Shoumkh self.rating = rating; 71936fd0130Shoumkh } 72036fd0130Shoumkh pub fn set_mask(&mut self, mask: ClocksourceMask) { 72136fd0130Shoumkh self.mask = mask; 72236fd0130Shoumkh } 72336fd0130Shoumkh pub fn set_mult(&mut self, mult: u32) { 72436fd0130Shoumkh self.mult = mult; 72536fd0130Shoumkh } 72636fd0130Shoumkh pub fn set_shift(&mut self, shift: u32) { 72736fd0130Shoumkh self.shift = shift; 72836fd0130Shoumkh } 72936fd0130Shoumkh pub fn set_max_idle_ns(&mut self, max_idle_ns: u32) { 73036fd0130Shoumkh self.max_idle_ns = max_idle_ns; 73136fd0130Shoumkh } 73236fd0130Shoumkh pub fn set_flags(&mut self, flags: ClocksourceFlags) { 73336fd0130Shoumkh self.flags = flags; 73436fd0130Shoumkh } 73536fd0130Shoumkh #[allow(dead_code)] 73636fd0130Shoumkh pub fn remove_flags(&mut self, flags: ClocksourceFlags) { 73736fd0130Shoumkh self.flags.remove(flags) 73836fd0130Shoumkh } 73936fd0130Shoumkh #[allow(dead_code)] 74036fd0130Shoumkh pub fn insert_flags(&mut self, flags: ClocksourceFlags) { 74136fd0130Shoumkh self.flags.insert(flags) 74236fd0130Shoumkh } 743dd8e74efSMingtao Huang pub fn set_uncertainty_margin(&mut self, uncertainty_margin: u32) { 744dd8e74efSMingtao Huang self.uncertainty_margin = uncertainty_margin; 745dd8e74efSMingtao Huang } 746dd8e74efSMingtao Huang pub fn set_maxadj(&mut self, maxadj: u32) { 747dd8e74efSMingtao Huang self.maxadj = maxadj; 748dd8e74efSMingtao Huang } 74936fd0130Shoumkh } 75036fd0130Shoumkh 75136fd0130Shoumkh /// converts clocksource cycles to nanoseconds 75236fd0130Shoumkh /// 75336fd0130Shoumkh pub fn clocksource_cyc2ns(cycles: CycleNum, mult: u32, shift: u32) -> u64 { 754*af097f9fS黄铭涛 // info!("<clocksource_cyc2ns>"); 755*af097f9fS黄铭涛 // info!("cycles = {:?}, mult = {:?}, shift = {:?}", cycles, mult, shift); 756*af097f9fS黄铭涛 // info!("ret = {:?}", (cycles.data() * mult as u64) >> shift); 75736fd0130Shoumkh return (cycles.data() * mult as u64) >> shift; 75836fd0130Shoumkh } 75936fd0130Shoumkh 76036fd0130Shoumkh /// # 重启所有的时间源 76136fd0130Shoumkh #[allow(dead_code)] 76236fd0130Shoumkh pub fn clocksource_resume() { 76336fd0130Shoumkh let list = CLOCKSOURCE_LIST.lock(); 76436fd0130Shoumkh for ele in list.iter() { 76536fd0130Shoumkh let data = ele.clocksource_data(); 76636fd0130Shoumkh match ele.resume() { 76736fd0130Shoumkh Ok(_) => continue, 76836fd0130Shoumkh Err(_) => { 7692eab6dd7S曾俊 debug!("clocksource {:?} resume failed", data.name); 77036fd0130Shoumkh } 77136fd0130Shoumkh } 77236fd0130Shoumkh } 77336fd0130Shoumkh clocksource_resume_watchdog(); 77436fd0130Shoumkh } 77536fd0130Shoumkh 77636fd0130Shoumkh /// # 暂停所有的时间源 77736fd0130Shoumkh #[allow(dead_code)] 77836fd0130Shoumkh pub fn clocksource_suspend() { 77936fd0130Shoumkh let list = CLOCKSOURCE_LIST.lock(); 78036fd0130Shoumkh for ele in list.iter() { 78136fd0130Shoumkh let data = ele.clocksource_data(); 78236fd0130Shoumkh match ele.suspend() { 78336fd0130Shoumkh Ok(_) => continue, 78436fd0130Shoumkh Err(_) => { 7852eab6dd7S曾俊 debug!("clocksource {:?} suspend failed", data.name); 78636fd0130Shoumkh } 78736fd0130Shoumkh } 78836fd0130Shoumkh } 78936fd0130Shoumkh } 79036fd0130Shoumkh 79136fd0130Shoumkh /// # 根据watchdog的精度,来检查被监视的时钟源的误差 79236fd0130Shoumkh /// 79336fd0130Shoumkh /// ## 返回值 79436fd0130Shoumkh /// 79536fd0130Shoumkh /// * `Ok()` - 检查完成 79636fd0130Shoumkh /// * `Err(SystemError)` - 错误码 79736fd0130Shoumkh pub fn clocksource_watchdog() -> Result<(), SystemError> { 798*af097f9fS黄铭涛 let cs_watchdog = CLOCKSOURCE_WATCHDOG.lock_irqsave(); 7992eab6dd7S曾俊 // debug!("clocksource_watchdog start"); 80036fd0130Shoumkh 80136fd0130Shoumkh // watchdog没有在运行的话直接退出 80236fd0130Shoumkh if !cs_watchdog.is_running || cs_watchdog.watchdog.is_none() { 8032eab6dd7S曾俊 // debug!("is_running = {:?},watchdog = {:?}", cs_watchdog.is_running, cs_watchdog.watchdog); 80436fd0130Shoumkh return Ok(()); 80536fd0130Shoumkh } 80636fd0130Shoumkh 80736fd0130Shoumkh drop(cs_watchdog); 808b8ed3825SDonkey Kane let watchdog_list = WATCHDOG_LIST.lock_irqsave(); 80936fd0130Shoumkh for cs in watchdog_list.iter() { 81036fd0130Shoumkh let mut cs_data = cs.clocksource_data(); 81136fd0130Shoumkh // 判断时钟源是否已经被标记为不稳定 81236fd0130Shoumkh if cs_data 81336fd0130Shoumkh .flags 81436fd0130Shoumkh .contains(ClocksourceFlags::CLOCK_SOURCE_UNSTABLE) 81536fd0130Shoumkh { 8162eab6dd7S曾俊 // debug!("clocksource_watchdog unstable"); 81736fd0130Shoumkh // 启动watchdog_kthread 818*af097f9fS黄铭涛 if FINISHED_BOOTING.load(Ordering::Relaxed) { 819*af097f9fS黄铭涛 // TODO 在实现了工作队列后,将启动线程换成schedule work 820b8ed3825SDonkey Kane run_watchdog_kthread(); 821*af097f9fS黄铭涛 } 82236fd0130Shoumkh continue; 82336fd0130Shoumkh } 824*af097f9fS黄铭涛 82536fd0130Shoumkh // 读取时钟源现在的时间 82636fd0130Shoumkh let cs_now_clock = cs.read(); 827*af097f9fS黄铭涛 // 读取watchdog现在的时间 828*af097f9fS黄铭涛 let wd = CLOCKSOURCE_WATCHDOG.lock_irqsave(); 829*af097f9fS黄铭涛 let wd_now = wd.watchdog.as_ref().unwrap().clone(); 830*af097f9fS黄铭涛 let wd_now_data = wd_now.as_ref().clocksource_data(); 831*af097f9fS黄铭涛 let wd_now_clock = wd_now.as_ref().read().data(); 832*af097f9fS黄铭涛 833*af097f9fS黄铭涛 // info!("cs_name = {:?}", cs_data.name); 834*af097f9fS黄铭涛 // info!("cs_last = {:?}", cs_data.cs_last); 835*af097f9fS黄铭涛 // info!("cs_now_clock = {:?}", cs_now_clock); 836*af097f9fS黄铭涛 // info!("wd_name"); 837*af097f9fS黄铭涛 // info!("wd_last = {:?}", cs_data.watchdog_last); 838*af097f9fS黄铭涛 // info!("wd_now_clock = {:?}", wd_now_clock); 83936fd0130Shoumkh 84036fd0130Shoumkh // 如果时钟源没有被监视,则开始监视他 84136fd0130Shoumkh if !cs_data 84236fd0130Shoumkh .flags 84336fd0130Shoumkh .contains(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG) 84436fd0130Shoumkh { 8452eab6dd7S曾俊 // debug!("clocksource_watchdog start watch"); 84636fd0130Shoumkh cs_data 84736fd0130Shoumkh .flags 84836fd0130Shoumkh .insert(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG); 84936fd0130Shoumkh // 记录此次检查的时刻 850*af097f9fS黄铭涛 cs_data.watchdog_last = CycleNum::new(wd_now_clock); 851*af097f9fS黄铭涛 cs_data.cs_last = cs_now_clock; 85236fd0130Shoumkh cs.update_clocksource_data(cs_data.clone())?; 85336fd0130Shoumkh continue; 85436fd0130Shoumkh } 855*af097f9fS黄铭涛 856*af097f9fS黄铭涛 let wd_dev_nsec = clocksource_cyc2ns( 857*af097f9fS黄铭涛 CycleNum((wd_now_clock - cs_data.watchdog_last.data()) & wd_now_data.mask.bits), 858*af097f9fS黄铭涛 wd_now_data.mult, 859*af097f9fS黄铭涛 wd_now_data.shift, 860*af097f9fS黄铭涛 ); 861*af097f9fS黄铭涛 86236fd0130Shoumkh let cs_dev_nsec = clocksource_cyc2ns( 863*af097f9fS黄铭涛 CycleNum(cs_now_clock.div(cs_data.cs_last).data() & cs_data.mask.bits), 864*af097f9fS黄铭涛 cs_data.mult, // 2343484437 865*af097f9fS黄铭涛 cs_data.shift, // 23 86636fd0130Shoumkh ); 86736fd0130Shoumkh // 记录此次检查的时刻 868*af097f9fS黄铭涛 cs_data.watchdog_last = CycleNum::new(wd_now_clock); 869*af097f9fS黄铭涛 cs_data.cs_last = cs_now_clock; 87036fd0130Shoumkh cs.update_clocksource_data(cs_data.clone())?; 871*af097f9fS黄铭涛 872*af097f9fS黄铭涛 // 判断是否有误差 87336fd0130Shoumkh if cs_dev_nsec.abs_diff(wd_dev_nsec) > WATCHDOG_THRESHOLD.into() { 8742eab6dd7S曾俊 // debug!("set_unstable"); 87536fd0130Shoumkh // 误差过大,标记为unstable 8762eab6dd7S曾俊 info!("cs_dev_nsec = {}", cs_dev_nsec); 8772eab6dd7S曾俊 info!("wd_dev_nsec = {}", wd_dev_nsec); 878*af097f9fS黄铭涛 cs.set_unstable(cs_dev_nsec.abs_diff(wd_dev_nsec).try_into().unwrap())?; 87936fd0130Shoumkh continue; 88036fd0130Shoumkh } 88136fd0130Shoumkh 88236fd0130Shoumkh // 判断是否要切换为高精度模式 88336fd0130Shoumkh if !cs_data 88436fd0130Shoumkh .flags 88536fd0130Shoumkh .contains(ClocksourceFlags::CLOCK_SOURCE_VALID_FOR_HRES) 88636fd0130Shoumkh && cs_data 88736fd0130Shoumkh .flags 88836fd0130Shoumkh .contains(ClocksourceFlags::CLOCK_SOURCE_IS_CONTINUOUS) 889*af097f9fS黄铭涛 && wd_now_data 89036fd0130Shoumkh .flags 89136fd0130Shoumkh .contains(ClocksourceFlags::CLOCK_SOURCE_IS_CONTINUOUS) 89236fd0130Shoumkh { 89336fd0130Shoumkh cs_data 89436fd0130Shoumkh .flags 89536fd0130Shoumkh .insert(ClocksourceFlags::CLOCK_SOURCE_VALID_FOR_HRES); 89636fd0130Shoumkh cs.update_clocksource_data(cs_data)?; 89736fd0130Shoumkh // TODO 通知tick机制 切换为高精度模式 89836fd0130Shoumkh } 899b8ed3825SDonkey Kane } 900b8ed3825SDonkey Kane create_new_watchdog_timer_function(); 901b8ed3825SDonkey Kane return Ok(()); 902b8ed3825SDonkey Kane } 903b8ed3825SDonkey Kane 904b8ed3825SDonkey Kane fn create_new_watchdog_timer_function() { 905*af097f9fS黄铭涛 let mut cs_watchdog = CLOCKSOURCE_WATCHDOG.lock_irqsave(); 906b8ed3825SDonkey Kane 90736fd0130Shoumkh cs_watchdog.timer_expires += WATCHDOG_INTERVAL; 90836fd0130Shoumkh //创建定时器执行watchdog 90936fd0130Shoumkh let watchdog_func = Box::new(WatchdogTimerFunc {}); 91036fd0130Shoumkh let watchdog_timer = Timer::new(watchdog_func, cs_watchdog.timer_expires); 91136fd0130Shoumkh watchdog_timer.activate(); 91236fd0130Shoumkh } 91336fd0130Shoumkh 914b8ed3825SDonkey Kane fn __clocksource_watchdog_kthread() { 91536fd0130Shoumkh let mut del_vec: Vec<usize> = Vec::new(); 91636fd0130Shoumkh let mut del_clocks: Vec<Arc<dyn Clocksource>> = Vec::new(); 917b8ed3825SDonkey Kane let mut wd_list = WATCHDOG_LIST.lock_irqsave(); 91836fd0130Shoumkh 91936fd0130Shoumkh // 将不稳定的时钟源弹出监视链表 92036fd0130Shoumkh for (pos, ele) in wd_list.iter().enumerate() { 92136fd0130Shoumkh let data = ele.clocksource_data(); 92236fd0130Shoumkh if data.flags.contains(ClocksourceFlags::CLOCK_SOURCE_UNSTABLE) { 92336fd0130Shoumkh del_vec.push(pos); 92436fd0130Shoumkh del_clocks.push(ele.clone()); 92536fd0130Shoumkh } 92636fd0130Shoumkh } 92736fd0130Shoumkh for pos in del_vec { 92836fd0130Shoumkh let mut temp_list = wd_list.split_off(pos); 92936fd0130Shoumkh temp_list.pop_front(); 93036fd0130Shoumkh wd_list.append(&mut temp_list); 93136fd0130Shoumkh } 93236fd0130Shoumkh 93336fd0130Shoumkh // 检查是否需要停止watchdog 934*af097f9fS黄铭涛 CLOCKSOURCE_WATCHDOG 935b8ed3825SDonkey Kane .lock_irqsave() 93636fd0130Shoumkh .clocksource_stop_watchdog(wd_list.len()); 937b8ed3825SDonkey Kane drop(wd_list); 938b8ed3825SDonkey Kane // 将不稳定的时钟源精度都设置为最低,然后删除unstable标记 93936fd0130Shoumkh for clock in del_clocks.iter() { 94036fd0130Shoumkh clock.clocksource_change_rating(0); 94136fd0130Shoumkh } 94236fd0130Shoumkh } 94336fd0130Shoumkh 944b8ed3825SDonkey Kane /// # watchdog线程的逻辑,执行unstable的后续操作 945b8ed3825SDonkey Kane pub fn clocksource_watchdog_kthread() -> i32 { 946b8ed3825SDonkey Kane // return 0; 947b8ed3825SDonkey Kane loop { 9482eab6dd7S曾俊 // debug!("clocksource_watchdog_kthread start"); 949b8ed3825SDonkey Kane __clocksource_watchdog_kthread(); 950b8ed3825SDonkey Kane if KernelThreadMechanism::should_stop(&ProcessManager::current_pcb()) { 951b8ed3825SDonkey Kane break; 952b8ed3825SDonkey Kane } 953b8ed3825SDonkey Kane let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 954b8ed3825SDonkey Kane ProcessManager::mark_sleep(true).expect("clocksource_watchdog_kthread:mark sleep failed"); 955b8ed3825SDonkey Kane drop(irq_guard); 956f0c87a89SGnoCiYeH schedule(SchedMode::SM_NONE); 957b8ed3825SDonkey Kane } 958b8ed3825SDonkey Kane return 0; 959b8ed3825SDonkey Kane } 960b8ed3825SDonkey Kane 96136fd0130Shoumkh /// # 清空所有时钟源的watchdog标志位 96236fd0130Shoumkh pub fn clocksource_reset_watchdog() { 963b8ed3825SDonkey Kane let list_guard = WATCHDOG_LIST.lock_irqsave(); 96436fd0130Shoumkh for ele in list_guard.iter() { 96536fd0130Shoumkh ele.clocksource_data() 96636fd0130Shoumkh .flags 96736fd0130Shoumkh .remove(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG); 96836fd0130Shoumkh } 96936fd0130Shoumkh } 97036fd0130Shoumkh 97136fd0130Shoumkh /// # 重启检查器 97236fd0130Shoumkh pub fn clocksource_resume_watchdog() { 97336fd0130Shoumkh clocksource_reset_watchdog(); 97436fd0130Shoumkh } 97536fd0130Shoumkh 97636fd0130Shoumkh /// # 根据精度选择最优的时钟源,或者接受用户指定的时间源 97736fd0130Shoumkh pub fn clocksource_select() { 97836fd0130Shoumkh let list_guard = CLOCKSOURCE_LIST.lock(); 979*af097f9fS黄铭涛 if !FINISHED_BOOTING.load(Ordering::Relaxed) || list_guard.is_empty() { 98036fd0130Shoumkh return; 98136fd0130Shoumkh } 98236fd0130Shoumkh let mut best = list_guard.front().unwrap().clone(); 98336fd0130Shoumkh let override_name = OVERRIDE_NAME.lock(); 98436fd0130Shoumkh // 判断是否有用户空间指定的时间源 98536fd0130Shoumkh for ele in list_guard.iter() { 98636fd0130Shoumkh if ele.clocksource_data().name.eq(override_name.deref()) { 98736fd0130Shoumkh // TODO 判断是否是高精度模式 98836fd0130Shoumkh // 暂时不支持高精度模式 98936fd0130Shoumkh // 如果是高精度模式,但是时钟源不支持高精度模式的话,就要退出循环 99036fd0130Shoumkh best = ele.clone(); 99136fd0130Shoumkh break; 99236fd0130Shoumkh } 99336fd0130Shoumkh } 99436fd0130Shoumkh // 对比当前的时钟源和记录到最好的时钟源的精度 99536fd0130Shoumkh if CUR_CLOCKSOURCE.lock().as_ref().is_some() { 99636fd0130Shoumkh // 当前时钟源不为空 99736fd0130Shoumkh let cur_clocksource = CUR_CLOCKSOURCE.lock().as_ref().unwrap().clone(); 99836fd0130Shoumkh let best_name = &best.clocksource_data().name; 99936fd0130Shoumkh if cur_clocksource.clocksource_data().name.ne(best_name) { 10002eab6dd7S曾俊 info!("Switching to the clocksource {:?}\n", best_name); 100136fd0130Shoumkh drop(cur_clocksource); 100292deae63SLoGin CUR_CLOCKSOURCE.lock().replace(best.clone()); 100336fd0130Shoumkh // TODO 通知timerkeeping 切换了时间源 100436fd0130Shoumkh } 100536fd0130Shoumkh } else { 100636fd0130Shoumkh // 当前时钟源为空 100792deae63SLoGin CUR_CLOCKSOURCE.lock().replace(best.clone()); 100836fd0130Shoumkh } 10092eab6dd7S曾俊 debug!("clocksource_select finish, CUR_CLOCKSOURCE = {best:?}"); 101036fd0130Shoumkh } 101136fd0130Shoumkh 101236fd0130Shoumkh /// # clocksource模块加载完成 101336fd0130Shoumkh pub fn clocksource_boot_finish() { 101436fd0130Shoumkh let mut cur_clocksource = CUR_CLOCKSOURCE.lock(); 101536fd0130Shoumkh cur_clocksource.replace(clocksource_default_clock()); 101692deae63SLoGin FINISHED_BOOTING.store(true, Ordering::Relaxed); 101736fd0130Shoumkh // 清除不稳定的时钟源 1018b8ed3825SDonkey Kane __clocksource_watchdog_kthread(); 10192eab6dd7S曾俊 debug!("clocksource_boot_finish"); 102036fd0130Shoumkh } 102136fd0130Shoumkh 1022b8ed3825SDonkey Kane fn run_watchdog_kthread() { 1023b8ed3825SDonkey Kane if let Some(watchdog_kthread) = unsafe { WATCHDOG_KTHREAD.clone() } { 1024b8ed3825SDonkey Kane ProcessManager::wakeup(&watchdog_kthread).ok(); 1025b8ed3825SDonkey Kane } 1026b8ed3825SDonkey Kane } 102736fd0130Shoumkh 1028b8ed3825SDonkey Kane #[unified_init(INITCALL_LATE)] 1029b8ed3825SDonkey Kane pub fn init_watchdog_kthread() -> Result<(), SystemError> { 1030b8ed3825SDonkey Kane assert!(CurrentIrqArch::is_irq_enabled()); 1031b8ed3825SDonkey Kane let closure = KernelThreadClosure::StaticEmptyClosure(( 1032b8ed3825SDonkey Kane &(clocksource_watchdog_kthread as fn() -> i32), 1033b8ed3825SDonkey Kane (), 1034b8ed3825SDonkey Kane )); 1035b8ed3825SDonkey Kane let pcb = KernelThreadMechanism::create_and_run(closure, "clocksource watchdog".to_string()) 1036b8ed3825SDonkey Kane .ok_or(SystemError::EPERM)?; 1037b8ed3825SDonkey Kane unsafe { 1038b8ed3825SDonkey Kane WATCHDOG_KTHREAD.replace(pcb); 1039b8ed3825SDonkey Kane } 1040b8ed3825SDonkey Kane 1041b8ed3825SDonkey Kane return Ok(()); 104236fd0130Shoumkh } 1043