Files
DragonOS/kernel/src/time/clocksource.rs
黄铭涛 af097f9f4b fix(time): modify update wall time (#836)
更改了时间子系统的update_wall_time函数,通过读取当前周期数,计算delta值进行更新,而不是通过传入delta值进行更新
2024-07-16 21:51:21 +08:00

1043 lines
34 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use core::{
fmt::Debug,
sync::atomic::{AtomicBool, Ordering},
};
use alloc::{
boxed::Box,
collections::LinkedList,
string::{String, ToString},
sync::Arc,
vec::Vec,
};
use lazy_static::__Deref;
use log::{debug, info};
use system_error::SystemError;
use unified_init::macros::unified_init;
use crate::{
arch::CurrentIrqArch,
exception::InterruptArch,
init::initcall::INITCALL_LATE,
libs::spinlock::SpinLock,
process::{
kthread::{KernelThreadClosure, KernelThreadMechanism},
ProcessControlBlock, ProcessManager,
},
sched::{schedule, SchedMode},
};
use super::{
jiffies::clocksource_default_clock,
timer::{clock, Timer, TimerFunction},
NSEC_PER_SEC, NSEC_PER_USEC,
};
lazy_static! {
/// linked list with the registered clocksources
pub static ref CLOCKSOURCE_LIST: SpinLock<LinkedList<Arc<dyn Clocksource>>> =
SpinLock::new(LinkedList::new());
/// 被监视中的时钟源
pub static ref WATCHDOG_LIST: SpinLock<LinkedList<Arc<dyn Clocksource>>> =
SpinLock::new(LinkedList::new());
pub static ref CLOCKSOURCE_WATCHDOG:SpinLock<ClocksouceWatchdog> = SpinLock::new(ClocksouceWatchdog::new());
pub static ref OVERRIDE_NAME: SpinLock<String> = SpinLock::new(String::from(""));
}
static mut WATCHDOG_KTHREAD: Option<Arc<ProcessControlBlock>> = None;
/// 正在被使用时钟源
pub static CUR_CLOCKSOURCE: SpinLock<Option<Arc<dyn Clocksource>>> = SpinLock::new(None);
/// 是否完成加载
pub static FINISHED_BOOTING: AtomicBool = AtomicBool::new(false);
/// Interval: 0.5sec Threshold: 0.0625s
/// 系统节拍率
pub const HZ: u64 = 250;
// 参考https://code.dragonos.org.cn/xref/linux-6.6.21/kernel/time/clocksource.c#101
/// watchdog检查间隔
pub const WATCHDOG_INTERVAL: u64 = HZ >> 1;
// 参考https://code.dragonos.org.cn/xref/linux-6.6.21/kernel/time/clocksource.c#108
/// 最大能接受的误差大小
pub const WATCHDOG_THRESHOLD: u32 = NSEC_PER_SEC >> 4;
pub const MAX_SKEW_USEC: u64 = 125 * WATCHDOG_INTERVAL / HZ;
pub const WATCHDOG_MAX_SKEW: u32 = MAX_SKEW_USEC as u32 * NSEC_PER_USEC;
// 时钟周期数
#[derive(Debug, Clone, Copy)]
pub struct CycleNum(u64);
#[allow(dead_code)]
impl CycleNum {
#[inline(always)]
pub const fn new(cycle: u64) -> Self {
Self(cycle)
}
#[inline(always)]
pub const fn data(&self) -> u64 {
self.0
}
#[inline(always)]
#[allow(dead_code)]
pub fn add(&self, other: CycleNum) -> CycleNum {
CycleNum(self.data() + other.data())
}
#[inline(always)]
pub fn div(&self, other: CycleNum) -> CycleNum {
CycleNum(self.data() - other.data())
}
}
bitflags! {
#[derive(Default)]
pub struct ClocksourceMask: u64 {
}
/// 时钟状态标记
#[derive(Default)]
pub struct ClocksourceFlags: u64 {
/// 表示时钟设备是连续的
const CLOCK_SOURCE_IS_CONTINUOUS = 0x01;
/// 表示该时钟源需要经过watchdog检查
const CLOCK_SOURCE_MUST_VERIFY = 0x02;
/// 表示该时钟源是watchdog
const CLOCK_SOURCE_WATCHDOG = 0x10;
/// 表示该时钟源是高分辨率的
const CLOCK_SOURCE_VALID_FOR_HRES = 0x20;
/// 表示该时钟源误差过大
const CLOCK_SOURCE_UNSTABLE = 0x40;
}
}
impl From<u64> for ClocksourceMask {
fn from(value: u64) -> Self {
if value < 64 {
return Self::from_bits_truncate((1 << value) - 1);
}
return Self::from_bits_truncate(u64::MAX);
}
}
impl ClocksourceMask {
pub fn new(b: u64) -> Self {
Self { bits: b }
}
}
impl ClocksourceFlags {
pub fn new(b: u64) -> Self {
Self { bits: b }
}
}
#[derive(Debug)]
pub struct ClocksouceWatchdog {
/// 监视器
watchdog: Option<Arc<dyn Clocksource>>,
/// 检查器是否在工作的标志
is_running: bool,
/// 定时监视器的过期时间
timer_expires: u64,
}
impl ClocksouceWatchdog {
pub fn new() -> Self {
Self {
watchdog: None,
is_running: false,
timer_expires: 0,
}
}
/// 获取watchdog
fn get_watchdog(&mut self) -> &mut Option<Arc<dyn Clocksource>> {
&mut self.watchdog
}
/// 启用检查器
pub fn clocksource_start_watchdog(&mut self) {
// 如果watchdog未被设置或者已经启用了就退出
let watchdog_list = WATCHDOG_LIST.lock_irqsave();
if self.is_running || self.watchdog.is_none() || watchdog_list.is_empty() {
return;
}
// 生成一个定时器
let wd_timer_func: Box<WatchdogTimerFunc> = Box::new(WatchdogTimerFunc {});
self.timer_expires += clock() + WATCHDOG_INTERVAL;
let mut wd_data = self.watchdog.as_ref().unwrap().clone().clocksource_data();
wd_data.watchdog_last = self.watchdog.as_ref().unwrap().clone().read();
self.watchdog
.as_ref()
.unwrap()
.update_clocksource_data(wd_data)
.expect("clocksource_start_watchdog: failed to update watchdog data");
let wd_timer = Timer::new(wd_timer_func, self.timer_expires);
wd_timer.activate();
self.is_running = true;
}
/// 停止检查器
/// list_len WATCHDOG_LIST长度
pub fn clocksource_stop_watchdog(&mut self, list_len: usize) {
if !self.is_running || (self.watchdog.is_some() && list_len != 0) {
return;
}
// TODO 当实现了周期性的定时器后 需要将监视用的定时器删除
self.is_running = false;
}
}
/// 定时检查器
#[derive(Debug)]
pub struct WatchdogTimerFunc;
impl TimerFunction for WatchdogTimerFunc {
fn run(&mut self) -> Result<(), SystemError> {
return clocksource_watchdog();
}
}
/// 时钟源的特性
pub trait Clocksource: Send + Sync + Debug {
// TODO 返回值类型可能需要改变
/// returns a cycle value, passes clocksource as argument
fn read(&self) -> CycleNum;
/// optional function to enable the clocksource
fn enable(&self) -> Result<i32, SystemError> {
return Err(SystemError::ENOSYS);
}
/// optional function to disable the clocksource
fn disable(&self) -> Result<(), SystemError> {
return Err(SystemError::ENOSYS);
}
/// vsyscall based read
fn vread(&self) -> Result<CycleNum, SystemError> {
return Err(SystemError::ENOSYS);
}
/// suspend function for the clocksource, if necessary
fn suspend(&self) -> Result<(), SystemError> {
return Err(SystemError::ENOSYS);
}
/// resume function for the clocksource, if necessary
fn resume(&self) -> Result<(), SystemError> {
return Err(SystemError::ENOSYS);
}
// 获取时钟源数据
fn clocksource_data(&self) -> ClocksourceData;
fn update_clocksource_data(&self, _data: ClocksourceData) -> Result<(), SystemError> {
return Err(SystemError::ENOSYS);
}
// 获取时钟源
fn clocksource(&self) -> Arc<dyn Clocksource>;
}
/// # 实现整数log2的运算
///
/// ## 参数
///
/// * `x` - 要计算的数字
///
/// ## 返回值
///
/// * `u32` - 返回\log_2(x)的值
fn log2(x: u32) -> u32 {
let mut result = 0;
let mut x = x;
if x >= 1 << 16 {
x >>= 16;
result |= 16;
}
if x >= 1 << 8 {
x >>= 8;
result |= 8;
}
if x >= 1 << 4 {
x >>= 4;
result |= 4;
}
if x >= 1 << 2 {
x >>= 2;
result |= 2;
}
if x >= 1 << 1 {
result |= 1;
}
result
}
impl dyn Clocksource {
/// # 计算时钟源能记录的最大时间跨度
pub fn clocksource_max_deferment(&self) -> u64 {
let cs_data_guard = self.clocksource_data();
let mut max_cycles: u64;
max_cycles = (1 << (63 - (log2(cs_data_guard.mult + cs_data_guard.maxadj) + 1))) as u64;
max_cycles = max_cycles.min(cs_data_guard.mask.bits);
let max_nsecs = clocksource_cyc2ns(
CycleNum(max_cycles),
cs_data_guard.mult - cs_data_guard.maxadj,
cs_data_guard.shift,
);
return max_nsecs - (max_nsecs >> 3);
}
/// # 计算时钟源的mult和shift以便将一个时钟源的频率转换为另一个时钟源的频率
fn clocks_calc_mult_shift(&self, from: u32, to: u32, maxsec: u32) -> (u32, u32) {
let mut sftacc: u32 = 32;
let mut sft = 1;
// 计算限制转换范围的shift
let mut mult = (maxsec as u64 * from as u64) >> 32;
while mult != 0 {
mult >>= 1;
sftacc -= 1;
}
// 找到最佳的mult和shift
for i in (1..=32).rev() {
sft = i;
mult = (to as u64) << sft;
mult += from as u64 / 2;
mult /= from as u64;
if (mult >> sftacc) == 0 {
break;
}
}
return (mult as u32, sft);
}
/// # 计算时钟源可以进行的最大调整量
fn clocksource_max_adjustment(&self) -> u32 {
let cs_data = self.clocksource_data();
let ret = cs_data.mult as u64 * 11 / 100;
return ret as u32;
}
/// # 更新时钟源频率初始化mult/shift 和 max_idle_ns
fn clocksource_update_freq_scale(&self, scale: u32, freq: u32) -> Result<(), SystemError> {
if freq != 0 {
let mut cs_data = self.clocksource_data();
let mut sec: u64 = cs_data.mask.bits();
sec /= freq as u64;
sec /= scale as u64;
if sec == 0 {
sec = 1;
} else if sec > 600 && cs_data.mask.bits() > u32::MAX as u64 {
sec = 600;
}
let (mult, shift) =
self.clocks_calc_mult_shift(freq, NSEC_PER_SEC / scale, sec as u32 * scale);
cs_data.set_mult(mult);
cs_data.set_shift(shift);
self.update_clocksource_data(cs_data)?;
}
let mut cs_data = self.clocksource_data();
if scale != 0 && freq != 0 && cs_data.uncertainty_margin == 0 {
cs_data.set_uncertainty_margin(NSEC_PER_SEC / (scale * freq));
if cs_data.uncertainty_margin < 2 * WATCHDOG_MAX_SKEW {
cs_data.set_uncertainty_margin(2 * WATCHDOG_MAX_SKEW);
}
} else if cs_data.uncertainty_margin == 0 {
cs_data.set_uncertainty_margin(WATCHDOG_THRESHOLD);
}
// 确保时钟源没有太大的mult值造成溢出
cs_data.set_maxadj(self.clocksource_max_adjustment());
self.update_clocksource_data(cs_data)?;
while freq != 0
&& (self.clocksource_data().mult + self.clocksource_data().maxadj
< self.clocksource_data().mult
|| self.clocksource_data().mult - self.clocksource_data().maxadj
> self.clocksource_data().mult)
{
let mut cs_data = self.clocksource_data();
cs_data.set_mult(cs_data.mult >> 1);
cs_data.set_shift(cs_data.shift - 1);
self.update_clocksource_data(cs_data)?;
let mut cs_data = self.clocksource_data();
cs_data.set_maxadj(self.clocksource_max_adjustment());
self.update_clocksource_data(cs_data)?;
}
let mut cs_data = self.clocksource_data();
let ns = self.clocksource_max_deferment();
cs_data.set_max_idle_ns(ns as u32);
self.update_clocksource_data(cs_data)?;
return Ok(());
}
/// # 注册时钟源
///
/// ## 参数
///
/// - scale: 如果freq单位为0或hz此值为1如果为khz,此值为1000
/// - freq: 时钟源的频率jiffies注册时此值为0
///
/// ## 返回值
///
/// * `Ok(0)` - 时钟源注册成功。
/// * `Err(SystemError)` - 时钟源注册失败。
pub fn register(&self, scale: u32, freq: u32) -> Result<(), SystemError> {
self.clocksource_update_freq_scale(scale, freq)?;
// 将时钟源加入到时钟源队列中
self.clocksource_enqueue();
// 将时钟源加入到监视队列中
self.clocksource_enqueue_watchdog()
.expect("register: failed to enqueue watchdog list");
// 选择一个最好的时钟源
clocksource_select();
debug!("clocksource_register successfully");
return Ok(());
}
/// # 将时钟源插入时钟源队列
pub fn clocksource_enqueue(&self) {
// 根据rating由大到小排序
let cs_data = self.clocksource_data();
let mut list_guard = CLOCKSOURCE_LIST.lock();
let mut spilt_pos: usize = list_guard.len();
for (pos, ele) in list_guard.iter().enumerate() {
if ele.clocksource_data().rating < cs_data.rating {
spilt_pos = pos;
break;
}
}
let mut temp_list = list_guard.split_off(spilt_pos);
let cs = self.clocksource();
list_guard.push_back(cs);
list_guard.append(&mut temp_list);
// debug!(
// "CLOCKSOURCE_LIST len = {:?},clocksource_enqueue sccessfully",
// list_guard.len()
// );
}
/// # 将时间源插入监控队列
///
/// ## 返回值
///
/// * `Ok(0)` - 时间源插入监控队列成功
/// * `Err(SystemError)` - 时间源插入监控队列失败
pub fn clocksource_enqueue_watchdog(&self) -> Result<i32, SystemError> {
// BUG 可能需要lock irq
let mut cs_data = self.clocksource_data();
let cs = self.clocksource();
if cs_data
.flags
.contains(ClocksourceFlags::CLOCK_SOURCE_MUST_VERIFY)
{
let mut list_guard = WATCHDOG_LIST.lock_irqsave();
// cs是被监视的
cs_data
.flags
.remove(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG);
cs.update_clocksource_data(cs_data)?;
list_guard.push_back(cs);
} else {
// cs是监视器
if cs_data
.flags
.contains(ClocksourceFlags::CLOCK_SOURCE_IS_CONTINUOUS)
{
// 如果时钟设备是连续的
cs_data
.flags
.insert(ClocksourceFlags::CLOCK_SOURCE_VALID_FOR_HRES);
cs.update_clocksource_data(cs_data.clone())?;
}
// 将时钟源加入到监控队列中
let mut list_guard = WATCHDOG_LIST.lock_irqsave();
list_guard.push_back(cs.clone());
drop(list_guard);
// 对比当前注册的时间源的精度和监视器的精度
let mut cs_watchdog = CLOCKSOURCE_WATCHDOG.lock_irqsave();
if cs_watchdog.watchdog.is_none()
|| cs_data.rating
> cs_watchdog
.watchdog
.clone()
.unwrap()
.clocksource_data()
.rating
{
// 当前注册的时间源的精度更高或者没有监视器,替换监视器
cs_watchdog.watchdog.replace(cs);
clocksource_reset_watchdog();
}
// 启动监视器
cs_watchdog.clocksource_start_watchdog();
}
return Ok(0);
}
/// # 将时钟源标记为unstable
///
/// ## 参数
/// * `delta` - 时钟源误差
pub fn set_unstable(&self, delta: i64) -> Result<i32, SystemError> {
let mut cs_data = self.clocksource_data();
// 打印出unstable的时钟源信息
debug!(
"clocksource :{:?} is unstable, its delta is {:?}",
cs_data.name, delta
);
cs_data.flags.remove(
ClocksourceFlags::CLOCK_SOURCE_VALID_FOR_HRES | ClocksourceFlags::CLOCK_SOURCE_WATCHDOG,
);
cs_data
.flags
.insert(ClocksourceFlags::CLOCK_SOURCE_UNSTABLE);
self.update_clocksource_data(cs_data)?;
// 启动watchdog线程 进行后续处理
if FINISHED_BOOTING.load(Ordering::Relaxed) {
// TODO 在实现了工作队列后将启动线程换成schedule work
run_watchdog_kthread();
}
return Ok(0);
}
/// # 将时间源从监视链表中弹出
fn clocksource_dequeue_watchdog(&self) {
let data = self.clocksource_data();
let mut locked_watchdog = CLOCKSOURCE_WATCHDOG.lock_irqsave();
let watchdog = locked_watchdog
.get_watchdog()
.clone()
.unwrap()
.clocksource_data();
let mut list = WATCHDOG_LIST.lock_irqsave();
let mut size = list.len();
let mut del_pos: usize = size;
for (pos, ele) in list.iter().enumerate() {
let ele_data = ele.clocksource_data();
if ele_data.name.eq(&data.name) && ele_data.rating.eq(&data.rating) {
// 记录要删除的时钟源在监视链表中的下标
del_pos = pos;
}
}
if data
.flags
.contains(ClocksourceFlags::CLOCK_SOURCE_MUST_VERIFY)
{
// 如果时钟源是需要被检查的,直接删除时钟源
if del_pos != size {
let mut temp_list = list.split_off(del_pos);
temp_list.pop_front();
list.append(&mut temp_list);
}
} else if watchdog.name.eq(&data.name) && watchdog.rating.eq(&data.rating) {
// 如果要删除的时钟源是监视器,则需要找到一个新的监视器
// TODO 重新设置时钟源
// 将链表解锁防止reset中双重加锁 并释放保存的旧的watchdog的数据
// 代替了clocksource_reset_watchdog()的功能将所有时钟源的watchdog标记清除
for ele in list.iter() {
ele.clocksource_data()
.flags
.remove(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG);
}
// 遍历所有时间源,寻找新的监视器
let mut clocksource_list = CLOCKSOURCE_LIST.lock();
let mut replace_pos: usize = clocksource_list.len();
for (pos, ele) in clocksource_list.iter().enumerate() {
let ele_data = ele.clocksource_data();
if ele_data.name.eq(&data.name) && ele_data.rating.eq(&data.rating)
|| ele_data
.flags
.contains(ClocksourceFlags::CLOCK_SOURCE_MUST_VERIFY)
{
// 当前时钟源是要被删除的时钟源或没被检查过的时钟源
// 不适合成为监视器
continue;
}
let watchdog = locked_watchdog.get_watchdog().clone();
if watchdog.is_none()
|| ele_data.rating > watchdog.unwrap().clocksource_data().rating
{
// 如果watchdog不存在或者当前时钟源的精度高于watchdog的精度则记录当前时钟源的下标
replace_pos = pos;
}
}
// 使用刚刚找到的更好的时钟源替换旧的watchdog
if replace_pos < clocksource_list.len() {
let mut temp_list = clocksource_list.split_off(replace_pos);
let new_wd = temp_list.front().unwrap().clone();
clocksource_list.append(&mut temp_list);
// 替换watchdog
locked_watchdog.watchdog.replace(new_wd);
// drop(locked_watchdog);
}
// 删除时钟源
if del_pos != size {
let mut temp_list = list.split_off(del_pos);
temp_list.pop_front();
list.append(&mut temp_list);
}
}
// 清除watchdog标记
let mut cs_data = self.clocksource_data();
cs_data
.flags
.remove(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG);
self.update_clocksource_data(cs_data)
.expect("clocksource_dequeue_watchdog: failed to update clocksource data");
size = list.len();
// 停止当前的watchdog
locked_watchdog.clocksource_stop_watchdog(size - 1);
}
/// # 将时钟源从时钟源链表中弹出
fn clocksource_dequeue(&self) {
let mut list = CLOCKSOURCE_LIST.lock();
let data = self.clocksource_data();
let mut del_pos: usize = list.len();
for (pos, ele) in list.iter().enumerate() {
let ele_data = ele.clocksource_data();
if ele_data.name.eq(&data.name) && ele_data.rating.eq(&data.rating) {
// 记录时钟源在链表中的下标
del_pos = pos;
}
}
// 删除时钟源
if del_pos != list.len() {
let mut temp_list = list.split_off(del_pos);
temp_list.pop_front();
list.append(&mut temp_list);
}
}
/// # 注销时钟源
#[allow(dead_code)]
pub fn unregister(&self) {
// 将时钟源从监视链表中弹出
self.clocksource_dequeue_watchdog();
// 将时钟源从时钟源链表中弹出
self.clocksource_dequeue();
// 检查是否有更好的时钟源
clocksource_select();
}
/// # 修改时钟源的精度
///
/// ## 参数
///
/// * `rating` - 指定的时钟精度
fn clocksource_change_rating(&self, rating: i32) {
// 将时钟源从链表中弹出
self.clocksource_dequeue();
let mut data = self.clocksource_data();
// 修改时钟源的精度
data.set_rating(rating);
self.update_clocksource_data(data)
.expect("clocksource_change_rating:updata clocksource failed");
// 插入时钟源到时钟源链表中
self.clocksource_enqueue();
// 检查是否有更好的时钟源
clocksource_select();
}
}
#[derive(Debug, Clone)]
pub struct ClocksourceData {
/// 时钟源名字
pub name: String,
/// 时钟精度
pub rating: i32,
pub mask: ClocksourceMask,
pub mult: u32,
pub shift: u32,
pub max_idle_ns: u32,
pub flags: ClocksourceFlags,
pub watchdog_last: CycleNum,
/// 用于watchdog机制中的字段记录主时钟源上一次被读取的周期数
pub cs_last: CycleNum,
// 用于描述时钟源的不确定性边界,时钟源读取的时间可能存在的不确定性和误差范围
pub uncertainty_margin: u32,
// 最大的时间调整量
pub maxadj: u32,
/// 上一次读取时钟源时的周期数
pub cycle_last: CycleNum,
}
impl ClocksourceData {
#[allow(dead_code)]
#[allow(clippy::too_many_arguments)]
pub fn new(
name: String,
rating: i32,
mask: ClocksourceMask,
mult: u32,
shift: u32,
max_idle_ns: u32,
flags: ClocksourceFlags,
uncertainty_margin: u32,
maxadj: u32,
) -> Self {
let csd = ClocksourceData {
name,
rating,
mask,
mult,
shift,
max_idle_ns,
flags,
watchdog_last: CycleNum(0),
cs_last: CycleNum(0),
uncertainty_margin,
maxadj,
cycle_last: CycleNum(0),
};
return csd;
}
pub fn set_name(&mut self, name: String) {
self.name = name;
}
pub fn set_rating(&mut self, rating: i32) {
self.rating = rating;
}
pub fn set_mask(&mut self, mask: ClocksourceMask) {
self.mask = mask;
}
pub fn set_mult(&mut self, mult: u32) {
self.mult = mult;
}
pub fn set_shift(&mut self, shift: u32) {
self.shift = shift;
}
pub fn set_max_idle_ns(&mut self, max_idle_ns: u32) {
self.max_idle_ns = max_idle_ns;
}
pub fn set_flags(&mut self, flags: ClocksourceFlags) {
self.flags = flags;
}
#[allow(dead_code)]
pub fn remove_flags(&mut self, flags: ClocksourceFlags) {
self.flags.remove(flags)
}
#[allow(dead_code)]
pub fn insert_flags(&mut self, flags: ClocksourceFlags) {
self.flags.insert(flags)
}
pub fn set_uncertainty_margin(&mut self, uncertainty_margin: u32) {
self.uncertainty_margin = uncertainty_margin;
}
pub fn set_maxadj(&mut self, maxadj: u32) {
self.maxadj = maxadj;
}
}
/// converts clocksource cycles to nanoseconds
///
pub fn clocksource_cyc2ns(cycles: CycleNum, mult: u32, shift: u32) -> u64 {
// info!("<clocksource_cyc2ns>");
// info!("cycles = {:?}, mult = {:?}, shift = {:?}", cycles, mult, shift);
// info!("ret = {:?}", (cycles.data() * mult as u64) >> shift);
return (cycles.data() * mult as u64) >> shift;
}
/// # 重启所有的时间源
#[allow(dead_code)]
pub fn clocksource_resume() {
let list = CLOCKSOURCE_LIST.lock();
for ele in list.iter() {
let data = ele.clocksource_data();
match ele.resume() {
Ok(_) => continue,
Err(_) => {
debug!("clocksource {:?} resume failed", data.name);
}
}
}
clocksource_resume_watchdog();
}
/// # 暂停所有的时间源
#[allow(dead_code)]
pub fn clocksource_suspend() {
let list = CLOCKSOURCE_LIST.lock();
for ele in list.iter() {
let data = ele.clocksource_data();
match ele.suspend() {
Ok(_) => continue,
Err(_) => {
debug!("clocksource {:?} suspend failed", data.name);
}
}
}
}
/// # 根据watchdog的精度来检查被监视的时钟源的误差
///
/// ## 返回值
///
/// * `Ok()` - 检查完成
/// * `Err(SystemError)` - 错误码
pub fn clocksource_watchdog() -> Result<(), SystemError> {
let cs_watchdog = CLOCKSOURCE_WATCHDOG.lock_irqsave();
// debug!("clocksource_watchdog start");
// watchdog没有在运行的话直接退出
if !cs_watchdog.is_running || cs_watchdog.watchdog.is_none() {
// debug!("is_running = {:?},watchdog = {:?}", cs_watchdog.is_running, cs_watchdog.watchdog);
return Ok(());
}
drop(cs_watchdog);
let watchdog_list = WATCHDOG_LIST.lock_irqsave();
for cs in watchdog_list.iter() {
let mut cs_data = cs.clocksource_data();
// 判断时钟源是否已经被标记为不稳定
if cs_data
.flags
.contains(ClocksourceFlags::CLOCK_SOURCE_UNSTABLE)
{
// debug!("clocksource_watchdog unstable");
// 启动watchdog_kthread
if FINISHED_BOOTING.load(Ordering::Relaxed) {
// TODO 在实现了工作队列后将启动线程换成schedule work
run_watchdog_kthread();
}
continue;
}
// 读取时钟源现在的时间
let cs_now_clock = cs.read();
// 读取watchdog现在的时间
let wd = CLOCKSOURCE_WATCHDOG.lock_irqsave();
let wd_now = wd.watchdog.as_ref().unwrap().clone();
let wd_now_data = wd_now.as_ref().clocksource_data();
let wd_now_clock = wd_now.as_ref().read().data();
// info!("cs_name = {:?}", cs_data.name);
// info!("cs_last = {:?}", cs_data.cs_last);
// info!("cs_now_clock = {:?}", cs_now_clock);
// info!("wd_name");
// info!("wd_last = {:?}", cs_data.watchdog_last);
// info!("wd_now_clock = {:?}", wd_now_clock);
// 如果时钟源没有被监视,则开始监视他
if !cs_data
.flags
.contains(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG)
{
// debug!("clocksource_watchdog start watch");
cs_data
.flags
.insert(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG);
// 记录此次检查的时刻
cs_data.watchdog_last = CycleNum::new(wd_now_clock);
cs_data.cs_last = cs_now_clock;
cs.update_clocksource_data(cs_data.clone())?;
continue;
}
let wd_dev_nsec = clocksource_cyc2ns(
CycleNum((wd_now_clock - cs_data.watchdog_last.data()) & wd_now_data.mask.bits),
wd_now_data.mult,
wd_now_data.shift,
);
let cs_dev_nsec = clocksource_cyc2ns(
CycleNum(cs_now_clock.div(cs_data.cs_last).data() & cs_data.mask.bits),
cs_data.mult, // 2343484437
cs_data.shift, // 23
);
// 记录此次检查的时刻
cs_data.watchdog_last = CycleNum::new(wd_now_clock);
cs_data.cs_last = cs_now_clock;
cs.update_clocksource_data(cs_data.clone())?;
// 判断是否有误差
if cs_dev_nsec.abs_diff(wd_dev_nsec) > WATCHDOG_THRESHOLD.into() {
// debug!("set_unstable");
// 误差过大标记为unstable
info!("cs_dev_nsec = {}", cs_dev_nsec);
info!("wd_dev_nsec = {}", wd_dev_nsec);
cs.set_unstable(cs_dev_nsec.abs_diff(wd_dev_nsec).try_into().unwrap())?;
continue;
}
// 判断是否要切换为高精度模式
if !cs_data
.flags
.contains(ClocksourceFlags::CLOCK_SOURCE_VALID_FOR_HRES)
&& cs_data
.flags
.contains(ClocksourceFlags::CLOCK_SOURCE_IS_CONTINUOUS)
&& wd_now_data
.flags
.contains(ClocksourceFlags::CLOCK_SOURCE_IS_CONTINUOUS)
{
cs_data
.flags
.insert(ClocksourceFlags::CLOCK_SOURCE_VALID_FOR_HRES);
cs.update_clocksource_data(cs_data)?;
// TODO 通知tick机制 切换为高精度模式
}
}
create_new_watchdog_timer_function();
return Ok(());
}
fn create_new_watchdog_timer_function() {
let mut cs_watchdog = CLOCKSOURCE_WATCHDOG.lock_irqsave();
cs_watchdog.timer_expires += WATCHDOG_INTERVAL;
//创建定时器执行watchdog
let watchdog_func = Box::new(WatchdogTimerFunc {});
let watchdog_timer = Timer::new(watchdog_func, cs_watchdog.timer_expires);
watchdog_timer.activate();
}
fn __clocksource_watchdog_kthread() {
let mut del_vec: Vec<usize> = Vec::new();
let mut del_clocks: Vec<Arc<dyn Clocksource>> = Vec::new();
let mut wd_list = WATCHDOG_LIST.lock_irqsave();
// 将不稳定的时钟源弹出监视链表
for (pos, ele) in wd_list.iter().enumerate() {
let data = ele.clocksource_data();
if data.flags.contains(ClocksourceFlags::CLOCK_SOURCE_UNSTABLE) {
del_vec.push(pos);
del_clocks.push(ele.clone());
}
}
for pos in del_vec {
let mut temp_list = wd_list.split_off(pos);
temp_list.pop_front();
wd_list.append(&mut temp_list);
}
// 检查是否需要停止watchdog
CLOCKSOURCE_WATCHDOG
.lock_irqsave()
.clocksource_stop_watchdog(wd_list.len());
drop(wd_list);
// 将不稳定的时钟源精度都设置为最低然后删除unstable标记
for clock in del_clocks.iter() {
clock.clocksource_change_rating(0);
}
}
/// # watchdog线程的逻辑执行unstable的后续操作
pub fn clocksource_watchdog_kthread() -> i32 {
// return 0;
loop {
// debug!("clocksource_watchdog_kthread start");
__clocksource_watchdog_kthread();
if KernelThreadMechanism::should_stop(&ProcessManager::current_pcb()) {
break;
}
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
ProcessManager::mark_sleep(true).expect("clocksource_watchdog_kthread:mark sleep failed");
drop(irq_guard);
schedule(SchedMode::SM_NONE);
}
return 0;
}
/// # 清空所有时钟源的watchdog标志位
pub fn clocksource_reset_watchdog() {
let list_guard = WATCHDOG_LIST.lock_irqsave();
for ele in list_guard.iter() {
ele.clocksource_data()
.flags
.remove(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG);
}
}
/// # 重启检查器
pub fn clocksource_resume_watchdog() {
clocksource_reset_watchdog();
}
/// # 根据精度选择最优的时钟源,或者接受用户指定的时间源
pub fn clocksource_select() {
let list_guard = CLOCKSOURCE_LIST.lock();
if !FINISHED_BOOTING.load(Ordering::Relaxed) || list_guard.is_empty() {
return;
}
let mut best = list_guard.front().unwrap().clone();
let override_name = OVERRIDE_NAME.lock();
// 判断是否有用户空间指定的时间源
for ele in list_guard.iter() {
if ele.clocksource_data().name.eq(override_name.deref()) {
// TODO 判断是否是高精度模式
// 暂时不支持高精度模式
// 如果是高精度模式,但是时钟源不支持高精度模式的话,就要退出循环
best = ele.clone();
break;
}
}
// 对比当前的时钟源和记录到最好的时钟源的精度
if CUR_CLOCKSOURCE.lock().as_ref().is_some() {
// 当前时钟源不为空
let cur_clocksource = CUR_CLOCKSOURCE.lock().as_ref().unwrap().clone();
let best_name = &best.clocksource_data().name;
if cur_clocksource.clocksource_data().name.ne(best_name) {
info!("Switching to the clocksource {:?}\n", best_name);
drop(cur_clocksource);
CUR_CLOCKSOURCE.lock().replace(best.clone());
// TODO 通知timerkeeping 切换了时间源
}
} else {
// 当前时钟源为空
CUR_CLOCKSOURCE.lock().replace(best.clone());
}
debug!("clocksource_select finish, CUR_CLOCKSOURCE = {best:?}");
}
/// # clocksource模块加载完成
pub fn clocksource_boot_finish() {
let mut cur_clocksource = CUR_CLOCKSOURCE.lock();
cur_clocksource.replace(clocksource_default_clock());
FINISHED_BOOTING.store(true, Ordering::Relaxed);
// 清除不稳定的时钟源
__clocksource_watchdog_kthread();
debug!("clocksource_boot_finish");
}
fn run_watchdog_kthread() {
if let Some(watchdog_kthread) = unsafe { WATCHDOG_KTHREAD.clone() } {
ProcessManager::wakeup(&watchdog_kthread).ok();
}
}
#[unified_init(INITCALL_LATE)]
pub fn init_watchdog_kthread() -> Result<(), SystemError> {
assert!(CurrentIrqArch::is_irq_enabled());
let closure = KernelThreadClosure::StaticEmptyClosure((
&(clocksource_watchdog_kthread as fn() -> i32),
(),
));
let pcb = KernelThreadMechanism::create_and_run(closure, "clocksource watchdog".to_string())
.ok_or(SystemError::EPERM)?;
unsafe {
WATCHDOG_KTHREAD.replace(pcb);
}
return Ok(());
}