修复jiffy时钟过快问题,启用gettimeofday测试,修改mount测试 (#680)

1. 把clock tick rate与hpet频率关联起来
2. 修复墙上时间同步错误的问题
3. 启用时间watch dog.
4. 修复时间流逝速度异常

---------

Co-authored-by: longjin <longjin@DragonOS.org>
This commit is contained in:
Donkey Kane
2024-04-05 00:06:26 +08:00
committed by GitHub
parent 9430523b46
commit b8ed38251d
22 changed files with 281 additions and 176 deletions

View File

@ -1,15 +1,29 @@
use core::{
ffi::c_void,
fmt::Debug,
sync::atomic::{AtomicBool, Ordering},
};
use alloc::{boxed::Box, collections::LinkedList, string::String, sync::Arc, vec::Vec};
use alloc::{
boxed::Box,
collections::LinkedList,
string::{String, ToString},
sync::Arc,
vec::Vec,
};
use lazy_static::__Deref;
use system_error::SystemError;
use unified_init::macros::unified_init;
use crate::{
include::bindings::bindings::run_watchdog_kthread, kdebug, kinfo, libs::spinlock::SpinLock,
arch::{sched::sched, CurrentIrqArch},
exception::InterruptArch,
init::initcall::INITCALL_LATE,
kdebug, kinfo,
libs::spinlock::SpinLock,
process::{
kthread::{KernelThreadClosure, KernelThreadMechanism},
ProcessControlBlock, ProcessManager,
},
};
use super::{
@ -33,6 +47,8 @@ lazy_static! {
}
static mut WATCHDOG_KTHREAD: Option<Arc<ProcessControlBlock>> = None;
/// 正在被使用时钟源
pub static CUR_CLOCKSOURCE: SpinLock<Option<Arc<dyn Clocksource>>> = SpinLock::new(None);
/// 是否完成加载
@ -48,17 +64,16 @@ pub const WATCHDOG_THRESHOLD: u32 = NSEC_PER_SEC >> 4;
// 时钟周期数
#[derive(Debug, Clone, Copy)]
#[repr(transparent)]
pub struct CycleNum(pub u64);
pub struct CycleNum(u64);
#[allow(dead_code)]
impl CycleNum {
#[inline(always)]
pub fn new(cycle: u64) -> Self {
pub const fn new(cycle: u64) -> Self {
Self(cycle)
}
#[inline(always)]
pub fn data(&self) -> u64 {
pub const fn data(&self) -> u64 {
self.0
}
#[inline(always)]
@ -140,7 +155,7 @@ impl ClocksouceWatchdog {
/// 启用检查器
pub fn clocksource_start_watchdog(&mut self) {
// 如果watchdog未被设置或者已经启用了就退出
let watchdog_list = &WATCHDOG_LIST.lock();
let watchdog_list = WATCHDOG_LIST.lock_irqsave();
if self.is_running || self.watchdog.is_none() || watchdog_list.is_empty() {
return;
}
@ -286,7 +301,7 @@ impl dyn Clocksource {
pub fn clocksource_enqueue(&self) {
// 根据rating由大到小排序
let cs_data = self.clocksource_data();
let list_guard = &mut CLOCKSOURCE_LIST.lock();
let mut list_guard = CLOCKSOURCE_LIST.lock();
let mut spilt_pos: usize = 0;
for (pos, ele) in list_guard.iter().enumerate() {
if ele.clocksource_data().rating < cs_data.rating {
@ -340,12 +355,12 @@ impl dyn Clocksource {
}
// 将时钟源加入到监控队列中
let mut list_guard = WATCHDOG_LIST.lock();
let mut list_guard = WATCHDOG_LIST.lock_irqsave();
list_guard.push_back(cs.clone());
drop(list_guard);
// 对比当前注册的时间源的精度和监视器的精度
let cs_watchdog = &mut CLOCKSOUCE_WATCHDOG.lock();
let mut cs_watchdog = CLOCKSOUCE_WATCHDOG.lock_irqsave();
if cs_watchdog.watchdog.is_none()
|| cs_data.rating
> cs_watchdog
@ -389,7 +404,7 @@ impl dyn Clocksource {
// 启动watchdog线程 进行后续处理
if unsafe { FINISHED_BOOTING.load(Ordering::Relaxed) } {
// TODO 在实现了工作队列后将启动线程换成schedule work
unsafe { run_watchdog_kthread() }
run_watchdog_kthread();
}
return Ok(0);
}
@ -397,14 +412,14 @@ impl dyn Clocksource {
/// # 将时间源从监视链表中弹出
fn clocksource_dequeue_watchdog(&self) {
let data = self.clocksource_data();
let mut locked_watchdog = CLOCKSOUCE_WATCHDOG.lock();
let mut locked_watchdog = CLOCKSOUCE_WATCHDOG.lock_irqsave();
let watchdog = locked_watchdog
.get_watchdog()
.clone()
.unwrap()
.clocksource_data();
let mut list = WATCHDOG_LIST.lock();
let mut list = WATCHDOG_LIST.lock_irqsave();
let mut size = list.len();
let mut del_pos: usize = size;
@ -654,10 +669,12 @@ pub fn clocksource_suspend() {
/// * `Ok()` - 检查完成
/// * `Err(SystemError)` - 错误码
pub fn clocksource_watchdog() -> Result<(), SystemError> {
let mut cs_watchdog = CLOCKSOUCE_WATCHDOG.lock();
let mut cs_watchdog = CLOCKSOUCE_WATCHDOG.lock_irqsave();
// kdebug!("clocksource_watchdog start");
// watchdog没有在运行的话直接退出
if !cs_watchdog.is_running || cs_watchdog.watchdog.is_none() {
// kdebug!("is_running = {:?},watchdog = {:?}", cs_watchdog.is_running, cs_watchdog.watchdog);
return Ok(());
}
let cur_watchdog = cs_watchdog.watchdog.as_ref().unwrap().clone();
@ -672,7 +689,7 @@ pub fn clocksource_watchdog() -> Result<(), SystemError> {
);
cs_watchdog.last_check = CycleNum(cur_wd_nowclock);
drop(cs_watchdog);
let watchdog_list = &mut WATCHDOG_LIST.lock();
let watchdog_list = WATCHDOG_LIST.lock_irqsave();
for cs in watchdog_list.iter() {
let mut cs_data = cs.clocksource_data();
// 判断时钟源是否已经被标记为不稳定
@ -680,8 +697,9 @@ pub fn clocksource_watchdog() -> Result<(), SystemError> {
.flags
.contains(ClocksourceFlags::CLOCK_SOURCE_UNSTABLE)
{
// kdebug!("clocksource_watchdog unstable");
// 启动watchdog_kthread
unsafe { run_watchdog_kthread() };
run_watchdog_kthread();
continue;
}
// 读取时钟源现在的时间
@ -692,6 +710,7 @@ pub fn clocksource_watchdog() -> Result<(), SystemError> {
.flags
.contains(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG)
{
// kdebug!("clocksource_watchdog start watch");
cs_data
.flags
.insert(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG);
@ -700,7 +719,7 @@ pub fn clocksource_watchdog() -> Result<(), SystemError> {
cs.update_clocksource_data(cs_data.clone())?;
continue;
}
// kdebug!("cs_data.watchdog_last = {:?},cs_now_clock = {:?}", cs_data.watchdog_last, cs_now_clock);
// 计算时钟源的误差
let cs_dev_nsec = clocksource_cyc2ns(
CycleNum(cs_now_clock.div(cs_data.watchdog_last).data() & cs_data.mask.bits),
@ -711,10 +730,12 @@ pub fn clocksource_watchdog() -> Result<(), SystemError> {
cs_data.watchdog_last = cs_now_clock;
cs.update_clocksource_data(cs_data.clone())?;
if cs_dev_nsec.abs_diff(wd_dev_nsec) > WATCHDOG_THRESHOLD.into() {
// kdebug!("set_unstable");
// 误差过大标记为unstable
cs.set_unstable((cs_dev_nsec - wd_dev_nsec).try_into().unwrap())?;
continue;
}
// kdebug!("clocksource_watchdog aaa");
// 判断是否要切换为高精度模式
if !cs_data
@ -733,22 +754,25 @@ pub fn clocksource_watchdog() -> Result<(), SystemError> {
cs.update_clocksource_data(cs_data)?;
// TODO 通知tick机制 切换为高精度模式
}
let mut cs_watchdog = CLOCKSOUCE_WATCHDOG.lock();
// FIXME 需要保证所有cpu时间统一
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();
}
create_new_watchdog_timer_function();
return Ok(());
}
/// # watchdog线程的逻辑执行unstable的后续操作
pub fn clocksource_watchdog_kthread() {
fn create_new_watchdog_timer_function() {
let mut cs_watchdog = CLOCKSOUCE_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 wd_list = &mut WATCHDOG_LIST.lock();
let mut wd_list = WATCHDOG_LIST.lock_irqsave();
// 将不稳定的时钟源弹出监视链表
for (pos, ele) in wd_list.iter().enumerate() {
@ -766,17 +790,47 @@ pub fn clocksource_watchdog_kthread() {
// 检查是否需要停止watchdog
CLOCKSOUCE_WATCHDOG
.lock()
.lock_irqsave()
.clocksource_stop_watchdog(wd_list.len());
// 将不稳定的时钟源精度都设置为最低
drop(wd_list);
// 将不稳定的时钟源精度都设置为最低然后删除unstable标记
for clock in del_clocks.iter() {
clock.clocksource_change_rating(0);
let mut data = clock.clocksource_data();
data.watchdog_last = clock.read();
kdebug!("kthread: watchdog_last = {:?}", data.watchdog_last);
data.flags.remove(ClocksourceFlags::CLOCK_SOURCE_UNSTABLE);
clock
.update_clocksource_data(data)
.expect("clocksource_watchdog_kthread: failed to update clocksource data");
// 重新插入监视链表
clock
.clocksource_enqueue_watchdog()
.expect("clocksource_watchdog_kthread: failed to enqueue watchdog list");
}
}
/// # watchdog线程的逻辑执行unstable的后续操作
pub fn clocksource_watchdog_kthread() -> i32 {
// return 0;
loop {
// kdebug!("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);
sched();
}
return 0;
}
/// # 清空所有时钟源的watchdog标志位
pub fn clocksource_reset_watchdog() {
let list_guard = WATCHDOG_LIST.lock();
let list_guard = WATCHDOG_LIST.lock_irqsave();
for ele in list_guard.iter() {
ele.clocksource_data()
.flags
@ -831,15 +885,28 @@ pub fn clocksource_boot_finish() {
cur_clocksource.replace(clocksource_default_clock());
unsafe { FINISHED_BOOTING.store(true, Ordering::Relaxed) };
// 清除不稳定的时钟源
clocksource_watchdog_kthread();
__clocksource_watchdog_kthread();
kdebug!("clocksource_boot_finish");
}
// ======== 以下为对C的接口 ========
/// # 启动watchdog线程的辅助函数
#[no_mangle]
pub extern "C" fn rs_clocksource_watchdog_kthread(_data: c_void) -> i32 {
clocksource_watchdog_kthread();
return 0;
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(());
}