修复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

@ -36,7 +36,7 @@ export ASFLAGS := --64
LD_LIST := ""
kernel_subdirs := common driver debug syscall libs time
kernel_subdirs := common driver debug syscall libs
kernel_rust:

View File

@ -1,6 +1,9 @@
use crate::time::TimeArch;
use crate::time::{clocksource::HZ, TimeArch};
pub struct RiscV64TimeArch;
/// 这个是系统jiffies时钟源的固有频率不是调频之后的
pub const CLOCK_TICK_RATE: u32 = HZ as u32 * 1000000;
impl TimeArch for RiscV64TimeArch {
fn get_cycles() -> usize {
riscv::register::cycle::read()
@ -9,4 +12,9 @@ impl TimeArch for RiscV64TimeArch {
fn cal_expire_cycles(ns: usize) -> usize {
todo!()
}
/// 将CPU的时钟周期数转换为纳秒
#[inline(always)]
fn cycles2ns(cycles: usize) -> usize {
todo!()
}
}

View File

@ -31,7 +31,10 @@ use crate::{
mmio_buddy::{mmio_pool, MMIOSpaceGuard},
PhysAddr,
},
time::timer::{clock, timer_get_first_expire, update_timer_jiffies},
time::{
jiffies::NSEC_PER_JIFFY,
timer::{clock, timer_get_first_expire, update_timer_jiffies},
},
};
static mut HPET_INSTANCE: Option<Hpet> = None;
@ -54,8 +57,8 @@ struct InnerHpet {
}
impl Hpet {
/// HPET0 中断间隔为 10ms
pub const HPET0_INTERVAL_USEC: u64 = 10000;
/// HPET0 中断间隔
pub const HPET0_INTERVAL_USEC: u64 = NSEC_PER_JIFFY as u64 / 1000;
const HPET0_IRQ: IrqNumber = IrqNumber::new(34);
@ -70,6 +73,7 @@ impl Hpet {
.unwrap()
};
let tm_num = hpet.timers_num();
kdebug!("HPET0_INTERVAL_USEC: {}", Self::HPET0_INTERVAL_USEC);
kinfo!("HPET has {} timers", tm_num);
hpet_info.hpet_number = tm_num as u8;
@ -238,7 +242,7 @@ impl Hpet {
pub(super) fn handle_irq(&self, timer_num: u32) {
if timer_num == 0 {
assert!(!CurrentIrqArch::is_irq_enabled());
update_timer_jiffies(Self::HPET0_INTERVAL_USEC, Self::HPET0_INTERVAL_USEC as i64);
update_timer_jiffies(1, Self::HPET0_INTERVAL_USEC as i64);
if let Ok(first_expire) = timer_get_first_expire() {
if first_expire <= clock() {

View File

@ -1,10 +1,14 @@
use crate::time::TimeArch;
use crate::time::{clocksource::HZ, TimeArch};
use super::driver::tsc::TSCManager;
/// 这个是系统jiffies时钟源的固有频率不是调频之后的
pub const CLOCK_TICK_RATE: u32 = HZ as u32 * 1000000;
pub struct X86_64TimeArch;
impl TimeArch for X86_64TimeArch {
#[inline(always)]
fn get_cycles() -> usize {
unsafe { x86::time::rdtsc() as usize }
}
@ -12,4 +16,10 @@ impl TimeArch for X86_64TimeArch {
fn cal_expire_cycles(ns: usize) -> usize {
Self::get_cycles() + ns * TSCManager::cpu_khz() as usize / 1000000
}
/// 将CPU的时钟周期数转换为纳秒
#[inline(always)]
fn cycles2ns(cycles: usize) -> usize {
cycles * 1000000 / TSCManager::cpu_khz() as usize
}
}

View File

@ -65,4 +65,4 @@ static __always_inline ul ALIGN(const ul addr, const ul _align)
* @param size 大小
* @return void* 指向目标地址的指针
*/
void *memmove(void *dst, const void *src, uint64_t size);
void *c_memmove(void *dst, const void *src, uint64_t size);

View File

@ -1,6 +1,9 @@
extern crate klog_types;
use core::intrinsics::unlikely;
use core::{
intrinsics::unlikely,
sync::atomic::{compiler_fence, Ordering},
};
use klog_types::{AllocatorLog, AllocatorLogType, LogSource, MMLogChannel};
@ -63,13 +66,18 @@ impl MMDebugLogManager {
let mut log = log;
loop {
compiler_fence(Ordering::SeqCst);
let r = __MM_ALLOCATOR_LOG_CHANNEL.buf.push(log);
compiler_fence(Ordering::SeqCst);
if let Err(r) = r {
// 如果日志通道满了,就把最早的日志丢弃
if __MM_ALLOCATOR_LOG_CHANNEL.buf.remaining() == 0 {
compiler_fence(Ordering::SeqCst);
__MM_ALLOCATOR_LOG_CHANNEL.buf.pop();
compiler_fence(Ordering::SeqCst);
}
log = r.into_inner();
compiler_fence(Ordering::SeqCst);
} else {
break;
}

View File

@ -95,7 +95,7 @@ static __always_inline void __pop_usage_stack(struct hid_parser *parser)
if (parser->usage_size > 0)
{
for (int js = 0; js < parser->usage_size - 1; ++js)
memmove(&parser->usage_table[js], &parser->usage_table[js + 1], sizeof(struct hid_node_t));
c_memmove(&parser->usage_table[js], &parser->usage_table[js + 1], sizeof(struct hid_node_t));
--parser->usage_size;
}

View File

@ -25,6 +25,5 @@
#include <mm/slab.h>
#include <process/process.h>
#include <sched/sched.h>
#include <time/clocksource.h>
#include <time/sleep.h>
#include <common/errno.h>

View File

@ -10,7 +10,7 @@
* @param size 大小
* @return void* 指向目标地址的指针
*/
void *memmove(void *dst, const void *src, uint64_t size)
void *c_memmove(void *dst, const void *src, uint64_t size)
{
const char *_src = src;
char *_dst = dst;

View File

@ -16,7 +16,7 @@ use crate::{
arch::{sched::sched, CurrentIrqArch},
exception::{irqdesc::IrqAction, InterruptArch},
init::initial_kthread::initial_kernel_thread,
kdebug, kinfo,
kinfo,
libs::{once::Once, spinlock::SpinLock},
process::{ProcessManager, ProcessState},
};
@ -439,7 +439,6 @@ impl KernelThreadMechanism {
#[inline(never)]
fn kthread_daemon() -> i32 {
let current_pcb = ProcessManager::current_pcb();
kdebug!("kthread_daemon: pid: {:?}", current_pcb.pid());
{
// 初始化worker_private
let mut worker_private_guard = current_pcb.worker_private();
@ -454,7 +453,6 @@ impl KernelThreadMechanism {
let mut list = KTHREAD_CREATE_LIST.lock();
while let Some(info) = list.pop_front() {
drop(list);
// create a new kernel thread
let result: Result<Pid, SystemError> = Self::__inner_create(
&info,

View File

@ -24,7 +24,7 @@ impl Completion {
/// @brief 基本函数通用的处理wait命令的函数(即所有wait_for_completion函数最核心部分在这里)
///
/// @param timeout 非负整数
/// @param timeout jiffies
/// @param interuptible 设置进程是否能被打断
/// @return 返回剩余时间或者SystemError
fn do_wait_for_common(&self, mut timeout: i64, interuptible: bool) -> Result<i64, SystemError> {

View File

@ -1,8 +0,0 @@
CFLAGS += -I .
all: clocksource.o
clocksource.o: clocksource.c
$(CC) $(CFLAGS) -c clocksource.c -o clocksource.o

View File

@ -1,10 +0,0 @@
#include "clocksource.h"
#include <common/kprint.h>
void run_watchdog_kthread()
{
kerror("run_watchdog_kthread");
while(1);
// todo: 进程管理重构后改掉这里换到rust的实现
// kthread_run(rs_clocksource_watchdog_kthread, NULL, "clocksource_watchdog");
}

View File

@ -1,7 +0,0 @@
#pragma once
extern int rs_clocksource_watchdog_kthread(void *_data);
void run_watchdog_kthread();

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(());
}

View File

@ -4,7 +4,7 @@ use alloc::{
};
use system_error::SystemError;
use crate::{kerror, kinfo, libs::spinlock::SpinLock};
use crate::{arch::time::CLOCK_TICK_RATE, kerror, kinfo, libs::spinlock::SpinLock};
use super::{
clocksource::{Clocksource, ClocksourceData, ClocksourceFlags, ClocksourceMask, CycleNum, HZ},
@ -14,11 +14,12 @@ use super::{
lazy_static! {
pub static ref DEFAULT_CLOCK: Arc<ClocksourceJiffies> = ClocksourceJiffies::new();
}
pub const CLOCK_TICK_RATE: u32 = HZ as u32 * 100000;
pub const JIFFIES_SHIFT: u32 = 8;
pub const LATCH: u32 = (CLOCK_TICK_RATE + (HZ as u32) / 2) / HZ as u32;
pub const ACTHZ: u32 = sh_div(CLOCK_TICK_RATE, LATCH, 8);
pub const NSEC_PER_JIFFY: u32 = (NSEC_PER_SEC << 8) / ACTHZ;
//TODO 编写测试,保证始终跳动间隔与现实一致(两种时钟源进行对拍)
pub const NSEC_PER_JIFFY: u32 = (((NSEC_PER_SEC as u64) << 8) / ACTHZ as u64) as u32;
pub const fn sh_div(nom: u32, den: u32, lsh: u32) -> u32 {
(((nom) / (den)) << (lsh)) + ((((nom) % (den)) << (lsh)) + (den) / 2) / (den)
}
@ -34,19 +35,19 @@ pub struct InnerJiffies {
impl Clocksource for ClocksourceJiffies {
fn read(&self) -> CycleNum {
CycleNum(clock())
CycleNum::new(clock())
}
fn clocksource_data(&self) -> ClocksourceData {
let inner = self.0.lock();
let inner = self.0.lock_irqsave();
return inner.data.clone();
}
fn clocksource(&self) -> Arc<dyn Clocksource> {
self.0.lock().self_ref.upgrade().unwrap()
self.0.lock_irqsave().self_ref.upgrade().unwrap()
}
fn update_clocksource_data(&self, _data: ClocksourceData) -> Result<(), SystemError> {
let d = &mut self.0.lock().data;
let d = &mut self.0.lock_irqsave().data;
d.set_flags(_data.flags);
d.set_mask(_data.mask);
d.set_max_idle_ns(_data.max_idle_ns);
@ -54,6 +55,7 @@ impl Clocksource for ClocksourceJiffies {
d.set_name(_data.name);
d.set_rating(_data.rating);
d.set_shift(_data.shift);
d.watchdog_last = _data.watchdog_last;
return Ok(());
}
@ -71,15 +73,15 @@ impl ClocksourceJiffies {
shift: JIFFIES_SHIFT,
max_idle_ns: Default::default(),
flags: ClocksourceFlags::new(0),
watchdog_last: CycleNum(0),
watchdog_last: CycleNum::new(0),
};
let jieffies = Arc::new(ClocksourceJiffies(SpinLock::new(InnerJiffies {
let jiffies = Arc::new(ClocksourceJiffies(SpinLock::new(InnerJiffies {
data,
self_ref: Default::default(),
})));
jieffies.0.lock().self_ref = Arc::downgrade(&jieffies);
jiffies.0.lock().self_ref = Arc::downgrade(&jiffies);
return jieffies;
return jiffies;
}
}
pub fn clocksource_default_clock() -> Arc<ClocksourceJiffies> {

View File

@ -492,4 +492,7 @@ pub trait TimeArch {
///
/// The expire cycles
fn cal_expire_cycles(ns: usize) -> usize;
/// 将CPU的时钟周期数转换为纳秒
fn cycles2ns(cycles: usize) -> usize;
}

View File

@ -1,12 +1,12 @@
use alloc::sync::Arc;
use core::sync::atomic::{compiler_fence, AtomicBool, AtomicI64, Ordering};
use core::sync::atomic::{compiler_fence, AtomicBool, AtomicI64, AtomicUsize, Ordering};
use system_error::SystemError;
use crate::{
arch::CurrentIrqArch,
arch::{CurrentIrqArch, CurrentTimeArch},
exception::InterruptArch,
kdebug, kinfo,
libs::rwlock::RwLock,
libs::rwlock::{RwLock, RwLockReadGuard},
time::{
jiffies::{clocksource_default_clock, jiffies_init},
timekeep::ktime_get_real_ns,
@ -17,7 +17,7 @@ use crate::{
use super::{
clocksource::{clocksource_cyc2ns, Clocksource, CycleNum, HZ},
syscall::PosixTimeval,
NSEC_PER_SEC, USEC_PER_SEC,
TimeArch, NSEC_PER_SEC,
};
/// NTP周期频率
pub const NTP_INTERVAL_FREQ: u64 = HZ;
@ -30,13 +30,16 @@ pub const NTP_SCALE_SHIFT: u32 = 32;
pub static TIMEKEEPING_SUSPENDED: AtomicBool = AtomicBool::new(false);
/// 已经递增的微秒数
static __ADDED_USEC: AtomicI64 = AtomicI64::new(0);
/// 已经递增的秒数
static __ADDED_SEC: AtomicI64 = AtomicI64::new(0);
/// timekeeper全局变量用于管理timekeeper模块
static mut __TIMEKEEPER: Option<Timekeeper> = None;
#[derive(Debug)]
pub struct Timekeeper(RwLock<TimekeeperData>);
pub struct Timekeeper {
inner: RwLock<TimekeeperData>,
/// 上一次更新墙上时间时的CPU周期数
last_update_cpu_cycle: AtomicUsize,
}
#[allow(dead_code)]
#[derive(Debug)]
@ -71,7 +74,7 @@ impl TimekeeperData {
Self {
clock: None,
shift: Default::default(),
cycle_interval: CycleNum(0),
cycle_interval: CycleNum::new(0),
xtime_interval: Default::default(),
xtime_remainder: Default::default(),
raw_interval: Default::default(),
@ -99,13 +102,20 @@ impl TimekeeperData {
}
}
impl Timekeeper {
fn new() -> Self {
Self {
inner: RwLock::new(TimekeeperData::new()),
last_update_cpu_cycle: AtomicUsize::new(0),
}
}
/// # 设置timekeeper的参数
///
/// ## 参数
///
/// * 'clock' - 指定的时钟实际类型。初始为ClocksourceJiffies
pub fn timekeeper_setup_internals(&self, clock: Arc<dyn Clocksource>) {
let mut timekeeper = self.0.write_irqsave();
let mut timekeeper = self.inner.write_irqsave();
// 更新clock
let mut clock_data = clock.clocksource_data();
clock_data.watchdog_last = clock.read();
@ -120,7 +130,7 @@ impl Timekeeper {
temp += (clock_data.mult / 2) as u64;
// do div
timekeeper.cycle_interval = CycleNum(temp);
timekeeper.cycle_interval = CycleNum::new(temp);
timekeeper.xtime_interval = temp * clock_data.mult as u64;
// 这里可能存在下界溢出问题debug模式下会报错panic
timekeeper.xtime_remainder = (ntpinterval - timekeeper.xtime_interval) as i64;
@ -134,19 +144,39 @@ impl Timekeeper {
timekeeper.mult = clock_data.mult;
}
/// # 获取当前时钟源距离上次检测走过的纳秒数
/// # 获取当前时钟源距离上次watchdog检测走过的纳秒数
#[allow(dead_code)]
pub fn tk_get_ns(&self) -> u64 {
let timekeeper = self.0.read_irqsave();
let timekeeper: RwLockReadGuard<'_, TimekeeperData> = self.inner.read_irqsave();
let clock = timekeeper.clock.clone().unwrap();
drop(timekeeper);
let clock_now = clock.read();
let clock_data = clock.clocksource_data();
let clock_delta = clock_now.div(clock_data.watchdog_last).data() & clock_data.mask.bits();
// clock_shift的值错误导致时间流逝速度异常+5为临时修改以确保系统正常运作目前追踪到的设置在DragonOS-dev/blob/fix_time/kernel/src/time/jiffies.rs#L18但是修改无效
return clocksource_cyc2ns(CycleNum(clock_delta), clock_data.mult, clock_data.shift + 5);
return clocksource_cyc2ns(
CycleNum::new(clock_delta),
clock_data.mult,
clock_data.shift,
);
}
#[inline]
fn do_read_cpu_cycle_ns(&self) -> usize {
CurrentTimeArch::cycles2ns(
CurrentTimeArch::get_cycles()
.wrapping_sub(self.last_update_cpu_cycle.load(Ordering::SeqCst)),
)
}
fn mark_update_wall_time_ok(&self) {
self.last_update_cpu_cycle
.store(CurrentTimeArch::get_cycles(), Ordering::SeqCst);
}
}
#[inline(always)]
pub fn timekeeper() -> &'static Timekeeper {
let r = unsafe { __TIMEKEEPER.as_ref().unwrap() };
@ -154,7 +184,7 @@ pub fn timekeeper() -> &'static Timekeeper {
}
pub fn timekeeper_init() {
unsafe { __TIMEKEEPER = Some(Timekeeper(RwLock::new(TimekeeperData::new()))) };
unsafe { __TIMEKEEPER = Some(Timekeeper::new()) };
}
/// # 获取1970.1.1至今的UTC时间戳(最小单位:nsec)
@ -166,33 +196,33 @@ pub fn getnstimeofday() -> TimeSpec {
// kdebug!("enter getnstimeofday");
let nsecs;
let mut _xtime = TimeSpec {
tv_nsec: 0,
tv_sec: 0,
};
let mut xtime: TimeSpec;
loop {
match timekeeper().0.try_read_irqsave() {
match timekeeper().inner.try_read_irqsave() {
None => continue,
Some(tk) => {
_xtime = tk.xtime;
xtime = tk.xtime;
drop(tk);
nsecs = timekeeper().tk_get_ns();
// 提供基于cpu周期数的ns时间以便在两次update_wall_time之间提供更好的精度
let cpu_delta_ns = timekeeper().do_read_cpu_cycle_ns() as u64;
// 尚未同步到xtime的时间
let tmp_delta_ns = __ADDED_USEC.load(Ordering::SeqCst) as u64 * 1000;
nsecs = cpu_delta_ns + tmp_delta_ns;
// TODO 不同架构可能需要加上不同的偏移量
break;
}
}
}
_xtime.tv_nsec += nsecs as i64;
// let sec = __ADDED_SEC.load(Ordering::SeqCst);
// _xtime.tv_sec += sec;
while _xtime.tv_nsec >= NSEC_PER_SEC.into() {
_xtime.tv_nsec -= NSEC_PER_SEC as i64;
_xtime.tv_sec += 1;
}
xtime.tv_nsec += nsecs as i64;
xtime.tv_sec += xtime.tv_nsec / NSEC_PER_SEC as i64;
xtime.tv_nsec %= NSEC_PER_SEC as i64;
// kdebug!("getnstimeofday: xtime = {:?}, nsecs = {:}", xtime, nsecs);
// TODO 将xtime和当前时间源的时间相加
return _xtime;
return xtime;
}
/// # 获取1970.1.1至今的UTC时间戳(最小单位:usec)
@ -209,7 +239,7 @@ pub fn do_gettimeofday() -> PosixTimeval {
}
pub fn do_settimeofday64(time: TimeSpec) -> Result<(), SystemError> {
timekeeper().0.write_irqsave().xtime = time;
timekeeper().inner.write_irqsave().xtime = time;
// todo: 模仿linux实现时间误差校准。
// https://code.dragonos.org.cn/xref/linux-6.6.21/kernel/time/timekeeping.c?fi=do_settimeofday64#1312
return Ok(());
@ -230,7 +260,7 @@ pub fn timekeeping_init() {
.expect("clocksource_default_clock enable failed");
timekeeper().timekeeper_setup_internals(clock);
// 暂时不支持其他架构平台对时间的设置 所以使用x86平台对应值初始化
let mut timekeeper = timekeeper().0.write_irqsave();
let mut timekeeper = timekeeper().inner.write_irqsave();
timekeeper.xtime.tv_nsec = ktime_get_real_ns();
//参考https://elixir.bootlin.com/linux/v4.4/source/kernel/time/timekeeping.c#L1251 对wtm进行初始化
@ -240,9 +270,9 @@ pub fn timekeeping_init() {
) = (-timekeeper.xtime.tv_nsec, -timekeeper.xtime.tv_sec);
__ADDED_USEC.store(0, Ordering::SeqCst);
__ADDED_SEC.store(0, Ordering::SeqCst);
drop(irq_guard);
drop(timekeeper);
jiffies_init();
kinfo!("timekeeping_init successfully");
}
@ -281,12 +311,7 @@ pub fn update_wall_time(delta_us: i64) {
let mut retry = 10;
let usec = __ADDED_USEC.load(Ordering::SeqCst);
if usec % USEC_PER_SEC as i64 == 0 {
compiler_fence(Ordering::SeqCst);
__ADDED_SEC.fetch_add(1, Ordering::SeqCst);
compiler_fence(Ordering::SeqCst);
}
// 一分钟同步一次
loop {
if (usec & !((1 << 26) - 1)) != 0 {
@ -298,10 +323,11 @@ pub fn update_wall_time(delta_us: i64) {
// 同步时间
// 我感觉这里会出问题:多个读者不退出的话,写者就无法写入
// 然后这里会超时,导致在中断返回之后,会不断的进入这个中断,最终爆栈。
let mut timekeeper = timekeeper().0.write_irqsave();
let mut timekeeper = timekeeper().inner.write_irqsave();
timekeeper.xtime.tv_nsec = ktime_get_real_ns();
timekeeper.xtime.tv_sec = 0;
__ADDED_SEC.store(0, Ordering::SeqCst);
__ADDED_USEC.store(0, Ordering::SeqCst);
drop(timekeeper);
break;
}
@ -310,6 +336,7 @@ pub fn update_wall_time(delta_us: i64) {
break;
}
}
timekeeper().mark_update_wall_time_ok();
// TODO 需要检查是否更新时间源
compiler_fence(Ordering::SeqCst);
drop(irq_guard);

View File

@ -6,8 +6,8 @@ use core::{
use alloc::{
boxed::Box,
collections::LinkedList,
sync::{Arc, Weak},
vec::Vec,
};
use system_error::SystemError;
@ -22,14 +22,14 @@ use crate::{
process::{ProcessControlBlock, ProcessManager},
};
use super::timekeeping::update_wall_time;
use super::{jiffies::NSEC_PER_JIFFY, timekeeping::update_wall_time};
const MAX_TIMEOUT: i64 = i64::MAX;
const TIMER_RUN_CYCLE_THRESHOLD: usize = 20;
static TIMER_JIFFIES: AtomicU64 = AtomicU64::new(0);
lazy_static! {
pub static ref TIMER_LIST: SpinLock<LinkedList<Arc<Timer>>> = SpinLock::new(LinkedList::new());
pub static ref TIMER_LIST: SpinLock<Vec<(u64, Arc<Timer>)>> = SpinLock::new(Vec::new());
}
/// 定时器要执行的函数的特征
@ -96,8 +96,10 @@ impl Timer {
// 链表为空,则直接插入
if timer_list.is_empty() {
// FIXME push_timer
timer_list.push_back(inner_guard.self_ref.upgrade().unwrap());
timer_list.push((
inner_guard.expire_jiffies,
inner_guard.self_ref.upgrade().unwrap(),
));
drop(inner_guard);
drop(timer_list);
@ -105,17 +107,21 @@ impl Timer {
return;
}
let expire_jiffies = inner_guard.expire_jiffies;
let self_arc = inner_guard.self_ref.upgrade().unwrap();
drop(inner_guard);
let mut split_pos: usize = 0;
for (pos, elt) in timer_list.iter().enumerate() {
if elt.inner().expire_jiffies > inner_guard.expire_jiffies {
if Arc::ptr_eq(&self_arc, &elt.1) {
kwarn!("Timer already in list");
}
if elt.0 > expire_jiffies {
split_pos = pos;
break;
}
}
let mut temp_list: LinkedList<Arc<Timer>> = timer_list.split_off(split_pos);
timer_list.push_back(inner_guard.self_ref.upgrade().unwrap());
timer_list.append(&mut temp_list);
drop(inner_guard);
timer_list.insert(split_pos, (expire_jiffies, self_arc));
drop(timer_list);
}
@ -144,7 +150,7 @@ impl Timer {
let this_arc = self.inner().self_ref.upgrade().unwrap();
TIMER_LIST
.lock_irqsave()
.extract_if(|x| Arc::ptr_eq(&this_arc, x))
.extract_if(|x| Arc::ptr_eq(&this_arc, &x.1))
.for_each(drop);
true
}
@ -204,26 +210,13 @@ impl SoftirqVec for DoTimerSoftirq {
break;
}
let timer_list_front = timer_list.pop_front().unwrap();
let (front_jiffies, timer_list_front) = timer_list.first().unwrap().clone();
// kdebug!("to lock timer_list_front");
let mut timer_list_front_guard = None;
for _ in 0..10 {
let x = timer_list_front.inner.try_lock_irqsave();
if x.is_err() {
continue;
}
timer_list_front_guard = Some(x.unwrap());
}
if timer_list_front_guard.is_none() {
continue;
}
let timer_list_front_guard = timer_list_front_guard.unwrap();
if timer_list_front_guard.expire_jiffies > TIMER_JIFFIES.load(Ordering::SeqCst) {
drop(timer_list_front_guard);
timer_list.push_front(timer_list_front);
if front_jiffies >= TIMER_JIFFIES.load(Ordering::SeqCst) {
break;
}
drop(timer_list_front_guard);
timer_list.remove(0);
drop(timer_list);
timer_list_front.run();
}
@ -245,11 +238,11 @@ pub fn timer_init() {
/// 计算接下来n毫秒对应的定时器时间片
pub fn next_n_ms_timer_jiffies(expire_ms: u64) -> u64 {
return TIMER_JIFFIES.load(Ordering::SeqCst) + 1000 * (expire_ms);
return TIMER_JIFFIES.load(Ordering::SeqCst) + expire_ms * 1000000 / NSEC_PER_JIFFY as u64;
}
/// 计算接下来n微秒对应的定时器时间片
pub fn next_n_us_timer_jiffies(expire_us: u64) -> u64 {
return TIMER_JIFFIES.load(Ordering::SeqCst) + (expire_us);
return TIMER_JIFFIES.load(Ordering::SeqCst) + expire_us * 1000 / NSEC_PER_JIFFY as u64;
}
/// @brief 让pcb休眠timeout个jiffies
@ -307,7 +300,7 @@ pub fn timer_get_first_expire() -> Result<u64, SystemError> {
return Ok(0);
} else {
// kdebug!("timer_list not empty");
return Ok(timer_list.front().unwrap().inner().expire_jiffies);
return Ok(timer_list.first().unwrap().0);
}
}
// 加锁失败返回啥??
@ -318,8 +311,6 @@ pub fn timer_get_first_expire() -> Result<u64, SystemError> {
}
/// 更新系统时间片
///
/// todo: 这里的实现有问题貌似把HPET的500us当成了500个jiffies然后update_wall_time()里面也硬编码了这个500us
pub fn update_timer_jiffies(add_jiffies: u64, time_us: i64) -> u64 {
let prev = TIMER_JIFFIES.fetch_add(add_jiffies, Ordering::SeqCst);
compiler_fence(Ordering::SeqCst);