mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 07:06:47 +00:00
fix(time): modify update wall time (#836)
更改了时间子系统的update_wall_time函数,通过读取当前周期数,计算delta值进行更新,而不是通过传入delta值进行更新
This commit is contained in:
parent
38458c7267
commit
af097f9f4b
@ -12,10 +12,10 @@ use crate::exception::manage::irq_manager;
|
|||||||
use crate::exception::IrqNumber;
|
use crate::exception::IrqNumber;
|
||||||
|
|
||||||
use crate::mm::percpu::PerCpu;
|
use crate::mm::percpu::PerCpu;
|
||||||
use crate::process::ProcessManager;
|
|
||||||
use crate::smp::core::smp_get_processor_id;
|
use crate::smp::core::smp_get_processor_id;
|
||||||
use crate::smp::cpu::ProcessorId;
|
use crate::smp::cpu::ProcessorId;
|
||||||
use crate::time::clocksource::HZ;
|
use crate::time::clocksource::HZ;
|
||||||
|
use crate::time::tick_common::tick_handle_periodic;
|
||||||
use alloc::string::ToString;
|
use alloc::string::ToString;
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
pub use drop;
|
pub use drop;
|
||||||
@ -277,7 +277,7 @@ impl LocalApicTimer {
|
|||||||
|
|
||||||
pub(super) fn handle_irq(trap_frame: &TrapFrame) -> Result<IrqReturn, SystemError> {
|
pub(super) fn handle_irq(trap_frame: &TrapFrame) -> Result<IrqReturn, SystemError> {
|
||||||
// sched_update_jiffies();
|
// sched_update_jiffies();
|
||||||
ProcessManager::update_process_times(trap_frame.is_from_user());
|
tick_handle_periodic(trap_frame);
|
||||||
return Ok(IrqReturn::Handled);
|
return Ok(IrqReturn::Handled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,10 +30,7 @@ use crate::{
|
|||||||
mmio_buddy::{mmio_pool, MMIOSpaceGuard},
|
mmio_buddy::{mmio_pool, MMIOSpaceGuard},
|
||||||
PhysAddr,
|
PhysAddr,
|
||||||
},
|
},
|
||||||
time::{
|
time::jiffies::NSEC_PER_JIFFY,
|
||||||
jiffies::NSEC_PER_JIFFY,
|
|
||||||
timer::{try_raise_timer_softirq, update_timer_jiffies},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static mut HPET_INSTANCE: Option<Hpet> = None;
|
static mut HPET_INSTANCE: Option<Hpet> = None;
|
||||||
@ -249,9 +246,6 @@ impl Hpet {
|
|||||||
pub(super) fn handle_irq(&self, timer_num: u32) {
|
pub(super) fn handle_irq(&self, timer_num: u32) {
|
||||||
if timer_num == 0 {
|
if timer_num == 0 {
|
||||||
assert!(!CurrentIrqArch::is_irq_enabled());
|
assert!(!CurrentIrqArch::is_irq_enabled());
|
||||||
update_timer_jiffies(1, Self::HPET0_INTERVAL_USEC as i64);
|
|
||||||
|
|
||||||
try_raise_timer_softirq();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,8 +88,10 @@ impl Acpipm {
|
|||||||
max_idle_ns: Default::default(),
|
max_idle_ns: Default::default(),
|
||||||
flags: ClocksourceFlags::CLOCK_SOURCE_IS_CONTINUOUS,
|
flags: ClocksourceFlags::CLOCK_SOURCE_IS_CONTINUOUS,
|
||||||
watchdog_last: CycleNum::new(0),
|
watchdog_last: CycleNum::new(0),
|
||||||
|
cs_last: CycleNum::new(0),
|
||||||
uncertainty_margin: 0,
|
uncertainty_margin: 0,
|
||||||
maxadj: 0,
|
maxadj: 0,
|
||||||
|
cycle_last: CycleNum::new(0),
|
||||||
};
|
};
|
||||||
let acpi_pm = Arc::new(Acpipm(SpinLock::new(InnerAcpipm {
|
let acpi_pm = Arc::new(Acpipm(SpinLock::new(InnerAcpipm {
|
||||||
data,
|
data,
|
||||||
@ -117,14 +119,18 @@ impl Clocksource for Acpipm {
|
|||||||
|
|
||||||
fn update_clocksource_data(&self, data: ClocksourceData) -> Result<(), SystemError> {
|
fn update_clocksource_data(&self, data: ClocksourceData) -> Result<(), SystemError> {
|
||||||
let d = &mut self.0.lock_irqsave().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);
|
|
||||||
d.set_mult(data.mult);
|
|
||||||
d.set_name(data.name);
|
d.set_name(data.name);
|
||||||
d.set_rating(data.rating);
|
d.set_rating(data.rating);
|
||||||
|
d.set_mask(data.mask);
|
||||||
|
d.set_mult(data.mult);
|
||||||
d.set_shift(data.shift);
|
d.set_shift(data.shift);
|
||||||
|
d.set_max_idle_ns(data.max_idle_ns);
|
||||||
|
d.set_flags(data.flags);
|
||||||
d.watchdog_last = data.watchdog_last;
|
d.watchdog_last = data.watchdog_last;
|
||||||
|
d.cs_last = data.cs_last;
|
||||||
|
d.set_uncertainty_margin(data.uncertainty_margin);
|
||||||
|
d.set_maxadj(data.maxadj);
|
||||||
|
d.cycle_last = data.cycle_last;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -281,7 +287,7 @@ pub fn init_acpi_pm_clocksource() -> Result<(), SystemError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 检查TSC时钟源的监视器是否被禁用,如果被禁用则将时钟源的标志设置为CLOCK_SOURCE_MUST_VERIFY
|
// 检查TSC时钟源的监视器是否被禁用,如果被禁用则将时钟源的标志设置为CLOCK_SOURCE_MUST_VERIFY
|
||||||
// 没有实现clocksource_selecet_watchdog函数,所以这里设置为false
|
// 是因为jiffies精度小于acpi pm,所以不需要被jiffies监视
|
||||||
let tsc_clocksource_watchdog_disabled = false;
|
let tsc_clocksource_watchdog_disabled = false;
|
||||||
if tsc_clocksource_watchdog_disabled {
|
if tsc_clocksource_watchdog_disabled {
|
||||||
clocksource_acpi_pm().0.lock_irqsave().data.flags |=
|
clocksource_acpi_pm().0.lock_irqsave().data.flags |=
|
||||||
@ -290,7 +296,7 @@ pub fn init_acpi_pm_clocksource() -> Result<(), SystemError> {
|
|||||||
|
|
||||||
// 注册ACPI PM Timer
|
// 注册ACPI PM Timer
|
||||||
let acpi_pmtmr = clocksource_acpi_pm() as Arc<dyn Clocksource>;
|
let acpi_pmtmr = clocksource_acpi_pm() as Arc<dyn Clocksource>;
|
||||||
match acpi_pmtmr.register(100, PMTMR_TICKS_PER_SEC as u32) {
|
match acpi_pmtmr.register(1, PMTMR_TICKS_PER_SEC as u32) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
info!("ACPI PM Timer registered as clocksource sccessfully");
|
info!("ACPI PM Timer registered as clocksource sccessfully");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -20,12 +20,9 @@ use crate::{
|
|||||||
},
|
},
|
||||||
libs::spinlock::SpinLock,
|
libs::spinlock::SpinLock,
|
||||||
mm::percpu::PerCpu,
|
mm::percpu::PerCpu,
|
||||||
process::ProcessManager,
|
|
||||||
smp::core::smp_get_processor_id,
|
smp::core::smp_get_processor_id,
|
||||||
time::{
|
time::{
|
||||||
clocksource::HZ,
|
clocksource::HZ, tick_common::tick_handle_periodic, timer::try_raise_timer_softirq,
|
||||||
jiffies::NSEC_PER_JIFFY,
|
|
||||||
timer::{try_raise_timer_softirq, update_timer_jiffies},
|
|
||||||
TimeArch,
|
TimeArch,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -37,13 +34,6 @@ static SBI_TIMER_INIT_BMP: SpinLock<StaticBitmap<{ PerCpu::MAX_CPU_NUM as usize
|
|||||||
|
|
||||||
static mut INTERVAL_CNT: usize = 0;
|
static mut INTERVAL_CNT: usize = 0;
|
||||||
|
|
||||||
/// 已经过去的纳秒数
|
|
||||||
///
|
|
||||||
/// 0号核心用这个值来更新墙上时钟,他只能被0号核心访问
|
|
||||||
static mut HART0_NSEC_PASSED: usize = 0;
|
|
||||||
/// hart0上一次更新墙上时钟的时间
|
|
||||||
static mut HART0_LAST_UPDATED: u64 = 0;
|
|
||||||
|
|
||||||
impl RiscVSbiTimer {
|
impl RiscVSbiTimer {
|
||||||
pub const TIMER_IRQ: HardwareIrqNumber = HardwareIrqNumber::new(5);
|
pub const TIMER_IRQ: HardwareIrqNumber = HardwareIrqNumber::new(5);
|
||||||
|
|
||||||
@ -54,8 +44,8 @@ impl RiscVSbiTimer {
|
|||||||
// smp_get_processor_id().data(),
|
// smp_get_processor_id().data(),
|
||||||
// CurrentTimeArch::get_cycles() as u64
|
// CurrentTimeArch::get_cycles() as u64
|
||||||
// );
|
// );
|
||||||
ProcessManager::update_process_times(trap_frame.is_from_user());
|
tick_handle_periodic(trap_frame);
|
||||||
Self::update_nsec_passed_and_walltime();
|
compiler_fence(Ordering::SeqCst);
|
||||||
sbi_rt::set_timer(CurrentTimeArch::get_cycles() as u64 + unsafe { INTERVAL_CNT } as u64);
|
sbi_rt::set_timer(CurrentTimeArch::get_cycles() as u64 + unsafe { INTERVAL_CNT } as u64);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -68,30 +58,6 @@ impl RiscVSbiTimer {
|
|||||||
fn disable() {
|
fn disable() {
|
||||||
unsafe { riscv::register::sie::clear_stimer() };
|
unsafe { riscv::register::sie::clear_stimer() };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_nsec_passed_and_walltime() {
|
|
||||||
if smp_get_processor_id().data() != 0 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let cycles = CurrentTimeArch::get_cycles() as u64;
|
|
||||||
let nsec_passed =
|
|
||||||
CurrentTimeArch::cycles2ns((cycles - unsafe { HART0_LAST_UPDATED }) as usize);
|
|
||||||
unsafe {
|
|
||||||
HART0_LAST_UPDATED = cycles;
|
|
||||||
HART0_NSEC_PASSED += nsec_passed;
|
|
||||||
}
|
|
||||||
|
|
||||||
let jiffies = unsafe { HART0_NSEC_PASSED } / NSEC_PER_JIFFY as usize;
|
|
||||||
unsafe { HART0_NSEC_PASSED %= NSEC_PER_JIFFY as usize };
|
|
||||||
|
|
||||||
update_timer_jiffies(
|
|
||||||
jiffies as u64,
|
|
||||||
(jiffies * NSEC_PER_JIFFY as usize / 1000) as i64,
|
|
||||||
);
|
|
||||||
try_raise_timer_softirq();
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// riscv 初始化本地调度时钟源
|
/// riscv 初始化本地调度时钟源
|
||||||
|
@ -41,7 +41,7 @@ lazy_static! {
|
|||||||
pub static ref WATCHDOG_LIST: SpinLock<LinkedList<Arc<dyn Clocksource>>> =
|
pub static ref WATCHDOG_LIST: SpinLock<LinkedList<Arc<dyn Clocksource>>> =
|
||||||
SpinLock::new(LinkedList::new());
|
SpinLock::new(LinkedList::new());
|
||||||
|
|
||||||
pub static ref CLOCKSOUCE_WATCHDOG:SpinLock<ClocksouceWatchdog> = SpinLock::new(ClocksouceWatchdog::new());
|
pub static ref CLOCKSOURCE_WATCHDOG:SpinLock<ClocksouceWatchdog> = SpinLock::new(ClocksouceWatchdog::new());
|
||||||
|
|
||||||
pub static ref OVERRIDE_NAME: SpinLock<String> = SpinLock::new(String::from(""));
|
pub static ref OVERRIDE_NAME: SpinLock<String> = SpinLock::new(String::from(""));
|
||||||
|
|
||||||
@ -138,8 +138,6 @@ pub struct ClocksouceWatchdog {
|
|||||||
watchdog: Option<Arc<dyn Clocksource>>,
|
watchdog: Option<Arc<dyn Clocksource>>,
|
||||||
/// 检查器是否在工作的标志
|
/// 检查器是否在工作的标志
|
||||||
is_running: bool,
|
is_running: bool,
|
||||||
/// 上一次检查的时刻
|
|
||||||
last_check: CycleNum,
|
|
||||||
/// 定时监视器的过期时间
|
/// 定时监视器的过期时间
|
||||||
timer_expires: u64,
|
timer_expires: u64,
|
||||||
}
|
}
|
||||||
@ -148,7 +146,6 @@ impl ClocksouceWatchdog {
|
|||||||
Self {
|
Self {
|
||||||
watchdog: None,
|
watchdog: None,
|
||||||
is_running: false,
|
is_running: false,
|
||||||
last_check: CycleNum(0),
|
|
||||||
timer_expires: 0,
|
timer_expires: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,7 +165,13 @@ impl ClocksouceWatchdog {
|
|||||||
// 生成一个定时器
|
// 生成一个定时器
|
||||||
let wd_timer_func: Box<WatchdogTimerFunc> = Box::new(WatchdogTimerFunc {});
|
let wd_timer_func: Box<WatchdogTimerFunc> = Box::new(WatchdogTimerFunc {});
|
||||||
self.timer_expires += clock() + WATCHDOG_INTERVAL;
|
self.timer_expires += clock() + WATCHDOG_INTERVAL;
|
||||||
self.last_check = self.watchdog.as_ref().unwrap().clone().read();
|
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);
|
let wd_timer = Timer::new(wd_timer_func, self.timer_expires);
|
||||||
wd_timer.activate();
|
wd_timer.activate();
|
||||||
self.is_running = true;
|
self.is_running = true;
|
||||||
@ -271,15 +274,14 @@ impl dyn Clocksource {
|
|||||||
let cs_data_guard = self.clocksource_data();
|
let cs_data_guard = self.clocksource_data();
|
||||||
|
|
||||||
let mut max_cycles: u64;
|
let mut max_cycles: u64;
|
||||||
// 这里我有问题,不知道要不要修改,暂时不修改它
|
max_cycles = (1 << (63 - (log2(cs_data_guard.mult + cs_data_guard.maxadj) + 1))) as u64;
|
||||||
max_cycles = (1 << (63 - (log2(cs_data_guard.mult) + 1))) as u64;
|
|
||||||
max_cycles = max_cycles.min(cs_data_guard.mask.bits);
|
max_cycles = max_cycles.min(cs_data_guard.mask.bits);
|
||||||
let max_nsecs = clocksource_cyc2ns(
|
let max_nsecs = clocksource_cyc2ns(
|
||||||
CycleNum(max_cycles),
|
CycleNum(max_cycles),
|
||||||
cs_data_guard.mult,
|
cs_data_guard.mult - cs_data_guard.maxadj,
|
||||||
cs_data_guard.shift,
|
cs_data_guard.shift,
|
||||||
);
|
);
|
||||||
return max_nsecs - (max_nsecs >> 5);
|
return max_nsecs - (max_nsecs >> 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # 计算时钟源的mult和shift,以便将一个时钟源的频率转换为另一个时钟源的频率
|
/// # 计算时钟源的mult和shift,以便将一个时钟源的频率转换为另一个时钟源的频率
|
||||||
@ -318,9 +320,8 @@ impl dyn Clocksource {
|
|||||||
|
|
||||||
/// # 更新时钟源频率,初始化mult/shift 和 max_idle_ns
|
/// # 更新时钟源频率,初始化mult/shift 和 max_idle_ns
|
||||||
fn clocksource_update_freq_scale(&self, scale: u32, freq: u32) -> Result<(), SystemError> {
|
fn clocksource_update_freq_scale(&self, scale: u32, freq: u32) -> Result<(), SystemError> {
|
||||||
let mut cs_data = self.clocksource_data();
|
|
||||||
|
|
||||||
if freq != 0 {
|
if freq != 0 {
|
||||||
|
let mut cs_data = self.clocksource_data();
|
||||||
let mut sec: u64 = cs_data.mask.bits();
|
let mut sec: u64 = cs_data.mask.bits();
|
||||||
|
|
||||||
sec /= freq as u64;
|
sec /= freq as u64;
|
||||||
@ -335,8 +336,10 @@ impl dyn Clocksource {
|
|||||||
self.clocks_calc_mult_shift(freq, NSEC_PER_SEC / scale, sec as u32 * scale);
|
self.clocks_calc_mult_shift(freq, NSEC_PER_SEC / scale, sec as u32 * scale);
|
||||||
cs_data.set_mult(mult);
|
cs_data.set_mult(mult);
|
||||||
cs_data.set_shift(shift);
|
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 {
|
if scale != 0 && freq != 0 && cs_data.uncertainty_margin == 0 {
|
||||||
cs_data.set_uncertainty_margin(NSEC_PER_SEC / (scale * freq));
|
cs_data.set_uncertainty_margin(NSEC_PER_SEC / (scale * freq));
|
||||||
if cs_data.uncertainty_margin < 2 * WATCHDOG_MAX_SKEW {
|
if cs_data.uncertainty_margin < 2 * WATCHDOG_MAX_SKEW {
|
||||||
@ -348,10 +351,25 @@ impl dyn Clocksource {
|
|||||||
|
|
||||||
// 确保时钟源没有太大的mult值造成溢出
|
// 确保时钟源没有太大的mult值造成溢出
|
||||||
cs_data.set_maxadj(self.clocksource_max_adjustment());
|
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();
|
let ns = self.clocksource_max_deferment();
|
||||||
cs_data.set_max_idle_ns(ns as u32);
|
cs_data.set_max_idle_ns(ns as u32);
|
||||||
|
|
||||||
self.update_clocksource_data(cs_data)?;
|
self.update_clocksource_data(cs_data)?;
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@ -387,7 +405,7 @@ impl dyn Clocksource {
|
|||||||
// 根据rating由大到小排序
|
// 根据rating由大到小排序
|
||||||
let cs_data = self.clocksource_data();
|
let cs_data = self.clocksource_data();
|
||||||
let mut list_guard = CLOCKSOURCE_LIST.lock();
|
let mut list_guard = CLOCKSOURCE_LIST.lock();
|
||||||
let mut spilt_pos: usize = 0;
|
let mut spilt_pos: usize = list_guard.len();
|
||||||
for (pos, ele) in list_guard.iter().enumerate() {
|
for (pos, ele) in list_guard.iter().enumerate() {
|
||||||
if ele.clocksource_data().rating < cs_data.rating {
|
if ele.clocksource_data().rating < cs_data.rating {
|
||||||
spilt_pos = pos;
|
spilt_pos = pos;
|
||||||
@ -445,7 +463,7 @@ impl dyn Clocksource {
|
|||||||
drop(list_guard);
|
drop(list_guard);
|
||||||
|
|
||||||
// 对比当前注册的时间源的精度和监视器的精度
|
// 对比当前注册的时间源的精度和监视器的精度
|
||||||
let mut cs_watchdog = CLOCKSOUCE_WATCHDOG.lock_irqsave();
|
let mut cs_watchdog = CLOCKSOURCE_WATCHDOG.lock_irqsave();
|
||||||
if cs_watchdog.watchdog.is_none()
|
if cs_watchdog.watchdog.is_none()
|
||||||
|| cs_data.rating
|
|| cs_data.rating
|
||||||
> cs_watchdog
|
> cs_watchdog
|
||||||
@ -496,7 +514,7 @@ impl dyn Clocksource {
|
|||||||
/// # 将时间源从监视链表中弹出
|
/// # 将时间源从监视链表中弹出
|
||||||
fn clocksource_dequeue_watchdog(&self) {
|
fn clocksource_dequeue_watchdog(&self) {
|
||||||
let data = self.clocksource_data();
|
let data = self.clocksource_data();
|
||||||
let mut locked_watchdog = CLOCKSOUCE_WATCHDOG.lock_irqsave();
|
let mut locked_watchdog = CLOCKSOURCE_WATCHDOG.lock_irqsave();
|
||||||
let watchdog = locked_watchdog
|
let watchdog = locked_watchdog
|
||||||
.get_watchdog()
|
.get_watchdog()
|
||||||
.clone()
|
.clone()
|
||||||
@ -652,10 +670,14 @@ pub struct ClocksourceData {
|
|||||||
pub max_idle_ns: u32,
|
pub max_idle_ns: u32,
|
||||||
pub flags: ClocksourceFlags,
|
pub flags: ClocksourceFlags,
|
||||||
pub watchdog_last: CycleNum,
|
pub watchdog_last: CycleNum,
|
||||||
|
/// 用于watchdog机制中的字段,记录主时钟源上一次被读取的周期数
|
||||||
|
pub cs_last: CycleNum,
|
||||||
// 用于描述时钟源的不确定性边界,时钟源读取的时间可能存在的不确定性和误差范围
|
// 用于描述时钟源的不确定性边界,时钟源读取的时间可能存在的不确定性和误差范围
|
||||||
pub uncertainty_margin: u32,
|
pub uncertainty_margin: u32,
|
||||||
// 最大的时间调整量
|
// 最大的时间调整量
|
||||||
pub maxadj: u32,
|
pub maxadj: u32,
|
||||||
|
/// 上一次读取时钟源时的周期数
|
||||||
|
pub cycle_last: CycleNum,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClocksourceData {
|
impl ClocksourceData {
|
||||||
@ -681,8 +703,10 @@ impl ClocksourceData {
|
|||||||
max_idle_ns,
|
max_idle_ns,
|
||||||
flags,
|
flags,
|
||||||
watchdog_last: CycleNum(0),
|
watchdog_last: CycleNum(0),
|
||||||
|
cs_last: CycleNum(0),
|
||||||
uncertainty_margin,
|
uncertainty_margin,
|
||||||
maxadj,
|
maxadj,
|
||||||
|
cycle_last: CycleNum(0),
|
||||||
};
|
};
|
||||||
return csd;
|
return csd;
|
||||||
}
|
}
|
||||||
@ -727,6 +751,9 @@ impl ClocksourceData {
|
|||||||
/// converts clocksource cycles to nanoseconds
|
/// converts clocksource cycles to nanoseconds
|
||||||
///
|
///
|
||||||
pub fn clocksource_cyc2ns(cycles: CycleNum, mult: u32, shift: u32) -> u64 {
|
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;
|
return (cycles.data() * mult as u64) >> shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -768,7 +795,7 @@ pub fn clocksource_suspend() {
|
|||||||
/// * `Ok()` - 检查完成
|
/// * `Ok()` - 检查完成
|
||||||
/// * `Err(SystemError)` - 错误码
|
/// * `Err(SystemError)` - 错误码
|
||||||
pub fn clocksource_watchdog() -> Result<(), SystemError> {
|
pub fn clocksource_watchdog() -> Result<(), SystemError> {
|
||||||
let mut cs_watchdog = CLOCKSOUCE_WATCHDOG.lock_irqsave();
|
let cs_watchdog = CLOCKSOURCE_WATCHDOG.lock_irqsave();
|
||||||
// debug!("clocksource_watchdog start");
|
// debug!("clocksource_watchdog start");
|
||||||
|
|
||||||
// watchdog没有在运行的话直接退出
|
// watchdog没有在运行的话直接退出
|
||||||
@ -776,17 +803,7 @@ pub fn clocksource_watchdog() -> Result<(), SystemError> {
|
|||||||
// debug!("is_running = {:?},watchdog = {:?}", cs_watchdog.is_running, cs_watchdog.watchdog);
|
// debug!("is_running = {:?},watchdog = {:?}", cs_watchdog.is_running, cs_watchdog.watchdog);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let cur_watchdog = cs_watchdog.watchdog.as_ref().unwrap().clone();
|
|
||||||
let cur_wd_data = cur_watchdog.as_ref().clocksource_data();
|
|
||||||
let cur_wd_nowclock = cur_watchdog.as_ref().read().data();
|
|
||||||
|
|
||||||
let wd_last = cs_watchdog.last_check.data();
|
|
||||||
let wd_dev_nsec = clocksource_cyc2ns(
|
|
||||||
CycleNum((cur_wd_nowclock - wd_last) & cur_wd_data.mask.bits),
|
|
||||||
cur_wd_data.mult,
|
|
||||||
cur_wd_data.shift,
|
|
||||||
);
|
|
||||||
cs_watchdog.last_check = CycleNum(cur_wd_nowclock);
|
|
||||||
drop(cs_watchdog);
|
drop(cs_watchdog);
|
||||||
let watchdog_list = WATCHDOG_LIST.lock_irqsave();
|
let watchdog_list = WATCHDOG_LIST.lock_irqsave();
|
||||||
for cs in watchdog_list.iter() {
|
for cs in watchdog_list.iter() {
|
||||||
@ -798,11 +815,27 @@ pub fn clocksource_watchdog() -> Result<(), SystemError> {
|
|||||||
{
|
{
|
||||||
// debug!("clocksource_watchdog unstable");
|
// debug!("clocksource_watchdog unstable");
|
||||||
// 启动watchdog_kthread
|
// 启动watchdog_kthread
|
||||||
run_watchdog_kthread();
|
if FINISHED_BOOTING.load(Ordering::Relaxed) {
|
||||||
|
// TODO 在实现了工作队列后,将启动线程换成schedule work
|
||||||
|
run_watchdog_kthread();
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 读取时钟源现在的时间
|
// 读取时钟源现在的时间
|
||||||
let cs_now_clock = cs.read();
|
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
|
if !cs_data
|
||||||
@ -814,29 +847,37 @@ pub fn clocksource_watchdog() -> Result<(), SystemError> {
|
|||||||
.flags
|
.flags
|
||||||
.insert(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG);
|
.insert(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG);
|
||||||
// 记录此次检查的时刻
|
// 记录此次检查的时刻
|
||||||
cs_data.watchdog_last = cs_now_clock;
|
cs_data.watchdog_last = CycleNum::new(wd_now_clock);
|
||||||
|
cs_data.cs_last = cs_now_clock;
|
||||||
cs.update_clocksource_data(cs_data.clone())?;
|
cs.update_clocksource_data(cs_data.clone())?;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// debug!("cs_data.watchdog_last = {:?},cs_now_clock = {:?}", cs_data.watchdog_last, cs_now_clock);
|
|
||||||
// 计算时钟源的误差
|
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(
|
let cs_dev_nsec = clocksource_cyc2ns(
|
||||||
CycleNum(cs_now_clock.div(cs_data.watchdog_last).data() & cs_data.mask.bits),
|
CycleNum(cs_now_clock.div(cs_data.cs_last).data() & cs_data.mask.bits),
|
||||||
cs_data.mult,
|
cs_data.mult, // 2343484437
|
||||||
cs_data.shift,
|
cs_data.shift, // 23
|
||||||
);
|
);
|
||||||
// 记录此次检查的时刻
|
// 记录此次检查的时刻
|
||||||
cs_data.watchdog_last = cs_now_clock;
|
cs_data.watchdog_last = CycleNum::new(wd_now_clock);
|
||||||
|
cs_data.cs_last = cs_now_clock;
|
||||||
cs.update_clocksource_data(cs_data.clone())?;
|
cs.update_clocksource_data(cs_data.clone())?;
|
||||||
|
|
||||||
|
// 判断是否有误差
|
||||||
if cs_dev_nsec.abs_diff(wd_dev_nsec) > WATCHDOG_THRESHOLD.into() {
|
if cs_dev_nsec.abs_diff(wd_dev_nsec) > WATCHDOG_THRESHOLD.into() {
|
||||||
// debug!("set_unstable");
|
// debug!("set_unstable");
|
||||||
// 误差过大,标记为unstable
|
// 误差过大,标记为unstable
|
||||||
info!("cs_dev_nsec = {}", cs_dev_nsec);
|
info!("cs_dev_nsec = {}", cs_dev_nsec);
|
||||||
info!("wd_dev_nsec = {}", wd_dev_nsec);
|
info!("wd_dev_nsec = {}", wd_dev_nsec);
|
||||||
cs.set_unstable((cs_dev_nsec - wd_dev_nsec).try_into().unwrap())?;
|
cs.set_unstable(cs_dev_nsec.abs_diff(wd_dev_nsec).try_into().unwrap())?;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// debug!("clocksource_watchdog aaa");
|
|
||||||
|
|
||||||
// 判断是否要切换为高精度模式
|
// 判断是否要切换为高精度模式
|
||||||
if !cs_data
|
if !cs_data
|
||||||
@ -845,7 +886,7 @@ pub fn clocksource_watchdog() -> Result<(), SystemError> {
|
|||||||
&& cs_data
|
&& cs_data
|
||||||
.flags
|
.flags
|
||||||
.contains(ClocksourceFlags::CLOCK_SOURCE_IS_CONTINUOUS)
|
.contains(ClocksourceFlags::CLOCK_SOURCE_IS_CONTINUOUS)
|
||||||
&& cur_wd_data
|
&& wd_now_data
|
||||||
.flags
|
.flags
|
||||||
.contains(ClocksourceFlags::CLOCK_SOURCE_IS_CONTINUOUS)
|
.contains(ClocksourceFlags::CLOCK_SOURCE_IS_CONTINUOUS)
|
||||||
{
|
{
|
||||||
@ -861,7 +902,7 @@ pub fn clocksource_watchdog() -> Result<(), SystemError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn create_new_watchdog_timer_function() {
|
fn create_new_watchdog_timer_function() {
|
||||||
let mut cs_watchdog = CLOCKSOUCE_WATCHDOG.lock_irqsave();
|
let mut cs_watchdog = CLOCKSOURCE_WATCHDOG.lock_irqsave();
|
||||||
|
|
||||||
cs_watchdog.timer_expires += WATCHDOG_INTERVAL;
|
cs_watchdog.timer_expires += WATCHDOG_INTERVAL;
|
||||||
//创建定时器执行watchdog
|
//创建定时器执行watchdog
|
||||||
@ -890,25 +931,13 @@ fn __clocksource_watchdog_kthread() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 检查是否需要停止watchdog
|
// 检查是否需要停止watchdog
|
||||||
CLOCKSOUCE_WATCHDOG
|
CLOCKSOURCE_WATCHDOG
|
||||||
.lock_irqsave()
|
.lock_irqsave()
|
||||||
.clocksource_stop_watchdog(wd_list.len());
|
.clocksource_stop_watchdog(wd_list.len());
|
||||||
drop(wd_list);
|
drop(wd_list);
|
||||||
// 将不稳定的时钟源精度都设置为最低,然后删除unstable标记
|
// 将不稳定的时钟源精度都设置为最低,然后删除unstable标记
|
||||||
for clock in del_clocks.iter() {
|
for clock in del_clocks.iter() {
|
||||||
clock.clocksource_change_rating(0);
|
clock.clocksource_change_rating(0);
|
||||||
let mut data = clock.clocksource_data();
|
|
||||||
data.watchdog_last = clock.read();
|
|
||||||
debug!("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");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -947,7 +976,7 @@ pub fn clocksource_resume_watchdog() {
|
|||||||
/// # 根据精度选择最优的时钟源,或者接受用户指定的时间源
|
/// # 根据精度选择最优的时钟源,或者接受用户指定的时间源
|
||||||
pub fn clocksource_select() {
|
pub fn clocksource_select() {
|
||||||
let list_guard = CLOCKSOURCE_LIST.lock();
|
let list_guard = CLOCKSOURCE_LIST.lock();
|
||||||
if FINISHED_BOOTING.load(Ordering::Relaxed) || list_guard.is_empty() {
|
if !FINISHED_BOOTING.load(Ordering::Relaxed) || list_guard.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let mut best = list_guard.front().unwrap().clone();
|
let mut best = list_guard.front().unwrap().clone();
|
||||||
|
@ -48,16 +48,20 @@ impl Clocksource for ClocksourceJiffies {
|
|||||||
fn clocksource(&self) -> Arc<dyn Clocksource> {
|
fn clocksource(&self) -> Arc<dyn Clocksource> {
|
||||||
self.0.lock_irqsave().self_ref.upgrade().unwrap()
|
self.0.lock_irqsave().self_ref.upgrade().unwrap()
|
||||||
}
|
}
|
||||||
fn update_clocksource_data(&self, _data: ClocksourceData) -> Result<(), SystemError> {
|
fn update_clocksource_data(&self, data: ClocksourceData) -> Result<(), SystemError> {
|
||||||
let d = &mut self.0.lock_irqsave().data;
|
let d = &mut self.0.lock_irqsave().data;
|
||||||
d.set_flags(_data.flags);
|
d.set_name(data.name);
|
||||||
d.set_mask(_data.mask);
|
d.set_rating(data.rating);
|
||||||
d.set_max_idle_ns(_data.max_idle_ns);
|
d.set_mask(data.mask);
|
||||||
d.set_mult(_data.mult);
|
d.set_mult(data.mult);
|
||||||
d.set_name(_data.name);
|
d.set_shift(data.shift);
|
||||||
d.set_rating(_data.rating);
|
d.set_max_idle_ns(data.max_idle_ns);
|
||||||
d.set_shift(_data.shift);
|
d.set_flags(data.flags);
|
||||||
d.watchdog_last = _data.watchdog_last;
|
d.watchdog_last = data.watchdog_last;
|
||||||
|
d.cs_last = data.cs_last;
|
||||||
|
d.set_uncertainty_margin(data.uncertainty_margin);
|
||||||
|
d.set_maxadj(data.maxadj);
|
||||||
|
d.cycle_last = data.cycle_last;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,8 +80,10 @@ impl ClocksourceJiffies {
|
|||||||
max_idle_ns: Default::default(),
|
max_idle_ns: Default::default(),
|
||||||
flags: ClocksourceFlags::new(0),
|
flags: ClocksourceFlags::new(0),
|
||||||
watchdog_last: CycleNum::new(0),
|
watchdog_last: CycleNum::new(0),
|
||||||
|
cs_last: CycleNum::new(0),
|
||||||
uncertainty_margin: 0,
|
uncertainty_margin: 0,
|
||||||
maxadj: 0,
|
maxadj: 0,
|
||||||
|
cycle_last: CycleNum::new(0),
|
||||||
};
|
};
|
||||||
let jiffies = Arc::new(ClocksourceJiffies(SpinLock::new(InnerJiffies {
|
let jiffies = Arc::new(ClocksourceJiffies(SpinLock::new(InnerJiffies {
|
||||||
data,
|
data,
|
||||||
|
@ -13,6 +13,7 @@ pub mod clocksource;
|
|||||||
pub mod jiffies;
|
pub mod jiffies;
|
||||||
pub mod sleep;
|
pub mod sleep;
|
||||||
pub mod syscall;
|
pub mod syscall;
|
||||||
|
pub mod tick_common;
|
||||||
pub mod timeconv;
|
pub mod timeconv;
|
||||||
pub mod timekeep;
|
pub mod timekeep;
|
||||||
pub mod timekeeping;
|
pub mod timekeeping;
|
||||||
|
25
kernel/src/time/tick_common.rs
Normal file
25
kernel/src/time/tick_common.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
use crate::{
|
||||||
|
arch::interrupt::TrapFrame,
|
||||||
|
process::ProcessManager,
|
||||||
|
smp::{core::smp_get_processor_id, cpu::ProcessorId},
|
||||||
|
time::timer::run_local_timer,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::timer::update_timer_jiffies;
|
||||||
|
|
||||||
|
/// # 函数的功能
|
||||||
|
/// 用于周期滴答的事件处理
|
||||||
|
pub fn tick_handle_periodic(trap_frame: &TrapFrame) {
|
||||||
|
let cpu_id = smp_get_processor_id();
|
||||||
|
|
||||||
|
tick_periodic(cpu_id, trap_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tick_periodic(cpu_id: ProcessorId, trap_frame: &TrapFrame) {
|
||||||
|
if cpu_id.data() == 0 {
|
||||||
|
update_timer_jiffies(1);
|
||||||
|
run_local_timer();
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessManager::update_process_times(trap_frame.is_from_user());
|
||||||
|
}
|
@ -1,10 +1,16 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
use core::intrinsics::unlikely;
|
||||||
|
|
||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
|
|
||||||
use crate::driver::rtc::interface::rtc_read_time_default;
|
use crate::driver::rtc::interface::rtc_read_time_default;
|
||||||
|
|
||||||
use super::PosixTimeSpec;
|
use super::{PosixTimeSpec, NSEC_PER_SEC};
|
||||||
|
|
||||||
|
// 参考:https://code.dragonos.org.cn/xref/linux-3.4.99/include/linux/time.h#110
|
||||||
|
const KTIME_MAX: i64 = !(1u64 << 63) as i64;
|
||||||
|
const KTIME_SEC_MAX: i64 = KTIME_MAX / NSEC_PER_SEC as i64;
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
pub type ktime_t = i64;
|
pub type ktime_t = i64;
|
||||||
@ -31,3 +37,25 @@ pub fn ktime_get_real_ns() -> i64 {
|
|||||||
let kt: ktime_t = ktime_get_real().unwrap_or(0);
|
let kt: ktime_t = ktime_get_real().unwrap_or(0);
|
||||||
return ktime_to_ns(kt);
|
return ktime_to_ns(kt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// # 用于将两个ktime_t类型的变量相加
|
||||||
|
// #[inline(always)]
|
||||||
|
// pub(super) fn ktime_add(add1: ktime_t, add2: ktime_t) -> ktime_t {
|
||||||
|
// let res = add1 + add2;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/// # 通过sec和nsec构造一个ktime_t
|
||||||
|
#[inline(always)]
|
||||||
|
fn ktime_set(secs: i64, nsecs: u64) -> ktime_t {
|
||||||
|
if unlikely(secs >= KTIME_SEC_MAX) {
|
||||||
|
return KTIME_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
return secs * NSEC_PER_SEC as i64 + nsecs as i64;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # 将PosixTimeSpec转换成ktime_t
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn timespec_to_ktime(ts: PosixTimeSpec) -> ktime_t {
|
||||||
|
return ktime_set(ts.tv_sec, ts.tv_nsec as u64);
|
||||||
|
}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use core::sync::atomic::{compiler_fence, AtomicBool, AtomicI64, AtomicUsize, Ordering};
|
use core::intrinsics::{likely, unlikely};
|
||||||
use log::{debug, info};
|
use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
|
||||||
|
use log::{debug, info, warn};
|
||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{CurrentIrqArch, CurrentTimeArch},
|
arch::CurrentIrqArch,
|
||||||
exception::InterruptArch,
|
exception::InterruptArch,
|
||||||
libs::rwlock::{RwLock, RwLockReadGuard},
|
libs::rwlock::RwLock,
|
||||||
time::{
|
time::{
|
||||||
jiffies::{clocksource_default_clock, jiffies_init},
|
jiffies::{clocksource_default_clock, jiffies_init},
|
||||||
timekeep::ktime_get_real_ns,
|
timekeep::ktime_get_real_ns,
|
||||||
@ -14,10 +15,11 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::timekeep::{ktime_t, timespec_to_ktime};
|
||||||
use super::{
|
use super::{
|
||||||
clocksource::{clocksource_cyc2ns, Clocksource, CycleNum, HZ},
|
clocksource::{clocksource_cyc2ns, Clocksource, CycleNum, HZ},
|
||||||
syscall::PosixTimeval,
|
syscall::PosixTimeval,
|
||||||
TimeArch, NSEC_PER_SEC,
|
NSEC_PER_SEC,
|
||||||
};
|
};
|
||||||
/// NTP周期频率
|
/// NTP周期频率
|
||||||
pub const NTP_INTERVAL_FREQ: u64 = HZ;
|
pub const NTP_INTERVAL_FREQ: u64 = HZ;
|
||||||
@ -28,17 +30,12 @@ pub const NTP_SCALE_SHIFT: u32 = 32;
|
|||||||
|
|
||||||
/// timekeeping休眠标志,false为未休眠
|
/// timekeeping休眠标志,false为未休眠
|
||||||
pub static TIMEKEEPING_SUSPENDED: AtomicBool = AtomicBool::new(false);
|
pub static TIMEKEEPING_SUSPENDED: AtomicBool = AtomicBool::new(false);
|
||||||
/// 已经递增的微秒数
|
|
||||||
static __ADDED_USEC: AtomicI64 = AtomicI64::new(0);
|
|
||||||
/// timekeeper全局变量,用于管理timekeeper模块
|
/// timekeeper全局变量,用于管理timekeeper模块
|
||||||
static mut __TIMEKEEPER: Option<Timekeeper> = None;
|
static mut __TIMEKEEPER: Option<Timekeeper> = None;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Timekeeper {
|
pub struct Timekeeper {
|
||||||
inner: RwLock<TimekeeperData>,
|
inner: RwLock<TimekeeperData>,
|
||||||
|
|
||||||
/// 上一次更新墙上时间时的CPU周期数
|
|
||||||
last_update_cpu_cycle: AtomicUsize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -68,6 +65,8 @@ pub struct TimekeeperData {
|
|||||||
wall_to_monotonic: PosixTimeSpec,
|
wall_to_monotonic: PosixTimeSpec,
|
||||||
total_sleep_time: PosixTimeSpec,
|
total_sleep_time: PosixTimeSpec,
|
||||||
xtime: PosixTimeSpec,
|
xtime: PosixTimeSpec,
|
||||||
|
/// 单调时间和实时时间的偏移量
|
||||||
|
real_time_offset: ktime_t,
|
||||||
}
|
}
|
||||||
impl TimekeeperData {
|
impl TimekeeperData {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
@ -98,6 +97,7 @@ impl TimekeeperData {
|
|||||||
tv_nsec: 0,
|
tv_nsec: 0,
|
||||||
tv_sec: 0,
|
tv_sec: 0,
|
||||||
},
|
},
|
||||||
|
real_time_offset: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,7 +105,6 @@ impl Timekeeper {
|
|||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: RwLock::new(TimekeeperData::new()),
|
inner: RwLock::new(TimekeeperData::new()),
|
||||||
last_update_cpu_cycle: AtomicUsize::new(0),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +117,7 @@ impl Timekeeper {
|
|||||||
let mut timekeeper = self.inner.write_irqsave();
|
let mut timekeeper = self.inner.write_irqsave();
|
||||||
// 更新clock
|
// 更新clock
|
||||||
let mut clock_data = clock.clocksource_data();
|
let mut clock_data = clock.clocksource_data();
|
||||||
clock_data.watchdog_last = clock.read();
|
clock_data.cycle_last = clock.read();
|
||||||
if clock.update_clocksource_data(clock_data).is_err() {
|
if clock.update_clocksource_data(clock_data).is_err() {
|
||||||
debug!("timekeeper_setup_internals:update_clocksource_data run failed");
|
debug!("timekeeper_setup_internals:update_clocksource_data run failed");
|
||||||
}
|
}
|
||||||
@ -144,33 +143,150 @@ impl Timekeeper {
|
|||||||
timekeeper.mult = clock_data.mult;
|
timekeeper.mult = clock_data.mult;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # 获取当前时钟源距离上次watchdog检测走过的纳秒数
|
pub fn timekeeping_get_ns(&self) -> i64 {
|
||||||
#[allow(dead_code)]
|
let timekeeper = self.inner.read_irqsave();
|
||||||
pub fn tk_get_ns(&self) -> u64 {
|
|
||||||
let timekeeper: RwLockReadGuard<'_, TimekeeperData> = self.inner.read_irqsave();
|
|
||||||
let clock = timekeeper.clock.clone().unwrap();
|
let clock = timekeeper.clock.clone().unwrap();
|
||||||
drop(timekeeper);
|
|
||||||
|
|
||||||
let clock_now = clock.read();
|
let cycle_now = clock.read();
|
||||||
let clock_data = clock.clocksource_data();
|
let clock_data = clock.clocksource_data();
|
||||||
let clock_delta = clock_now.div(clock_data.watchdog_last).data() & clock_data.mask.bits();
|
let cycle_delta = (cycle_now.div(clock_data.cycle_last)).data() & clock_data.mask.bits();
|
||||||
|
|
||||||
return clocksource_cyc2ns(
|
return clocksource_cyc2ns(
|
||||||
CycleNum::new(clock_delta),
|
CycleNum::new(cycle_delta),
|
||||||
clock_data.mult,
|
timekeeper.mult,
|
||||||
clock_data.shift,
|
timekeeper.shift as u32,
|
||||||
);
|
) as i64;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
/// # 处理大幅度调整
|
||||||
fn do_read_cpu_cycle_ns(&self) -> usize {
|
pub fn timekeeping_bigadjust(&self, error: i64, interval: i64, offset: i64) -> (i64, i64, i32) {
|
||||||
let prev = self.last_update_cpu_cycle.load(Ordering::SeqCst);
|
let mut error = error;
|
||||||
CurrentTimeArch::cycles2ns(CurrentTimeArch::get_cycles().wrapping_sub(prev))
|
let mut interval = interval;
|
||||||
|
let mut offset = offset;
|
||||||
|
|
||||||
|
// TODO: 计算look_head并调整ntp误差
|
||||||
|
|
||||||
|
let tmp = interval;
|
||||||
|
let mut mult = 1;
|
||||||
|
let mut adj = 0;
|
||||||
|
if error < 0 {
|
||||||
|
error = -error;
|
||||||
|
interval = -interval;
|
||||||
|
offset = -offset;
|
||||||
|
mult = -1;
|
||||||
|
}
|
||||||
|
while error > tmp {
|
||||||
|
adj += 1;
|
||||||
|
error >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
interval <<= adj;
|
||||||
|
offset <<= adj;
|
||||||
|
mult <<= adj;
|
||||||
|
|
||||||
|
return (interval, offset, mult);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mark_update_wall_time_ok(&self) {
|
/// # 调整时钟的mult减少ntp_error
|
||||||
self.last_update_cpu_cycle
|
pub fn timekeeping_adjust(&self, offset: i64) -> i64 {
|
||||||
.store(CurrentTimeArch::get_cycles(), Ordering::SeqCst);
|
let mut timekeeper = self.inner.write_irqsave();
|
||||||
|
let mut interval = timekeeper.cycle_interval.data() as i64;
|
||||||
|
let mut offset = offset;
|
||||||
|
let adj: i32;
|
||||||
|
|
||||||
|
// 计算误差
|
||||||
|
let mut error = timekeeper.ntp_error >> (timekeeper.ntp_error_shift - 1);
|
||||||
|
|
||||||
|
// 误差超过一个interval,就要进行调整
|
||||||
|
if error >= 0 {
|
||||||
|
if error > interval {
|
||||||
|
error >>= 2;
|
||||||
|
if likely(error <= interval) {
|
||||||
|
adj = 1;
|
||||||
|
} else {
|
||||||
|
(interval, offset, adj) = self.timekeeping_bigadjust(error, interval, offset);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 不需要校准
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
} else if -error > interval {
|
||||||
|
if likely(-error <= interval) {
|
||||||
|
adj = -1;
|
||||||
|
interval = -interval;
|
||||||
|
offset = -offset;
|
||||||
|
} else {
|
||||||
|
(interval, offset, adj) = self.timekeeping_bigadjust(error, interval, offset);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 不需要校准
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查最大调整值,确保调整值不会超过时钟源允许的最大值
|
||||||
|
let clock_data = timekeeper.clock.clone().unwrap().clocksource_data();
|
||||||
|
if unlikely(
|
||||||
|
clock_data.maxadj != 0
|
||||||
|
&& (timekeeper.mult as i32 + adj
|
||||||
|
> clock_data.mult as i32 + clock_data.maxadj as i32),
|
||||||
|
) {
|
||||||
|
warn!(
|
||||||
|
"Adjusting {:?} more than ({} vs {})",
|
||||||
|
clock_data.name,
|
||||||
|
timekeeper.mult as i32 + adj,
|
||||||
|
clock_data.mult as i32 + clock_data.maxadj as i32
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if error > 0 {
|
||||||
|
timekeeper.mult += adj as u32;
|
||||||
|
timekeeper.xtime_interval += interval as u64;
|
||||||
|
timekeeper.xtime_nsec -= offset as u64;
|
||||||
|
} else {
|
||||||
|
timekeeper.mult -= adj as u32;
|
||||||
|
timekeeper.xtime_interval -= interval as u64;
|
||||||
|
timekeeper.xtime_nsec += offset as u64;
|
||||||
|
}
|
||||||
|
timekeeper.ntp_error -= (interval - offset) << timekeeper.ntp_error_shift;
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
/// # 用于累积时间间隔,并将其转换为纳秒时间
|
||||||
|
pub fn logarithmic_accumulation(&self, offset: u64, shift: i32) -> u64 {
|
||||||
|
let mut timekeeper = self.inner.write_irqsave();
|
||||||
|
let clock = timekeeper.clock.clone().unwrap();
|
||||||
|
let clock_data = clock.clocksource_data();
|
||||||
|
let nsecps = (NSEC_PER_SEC as u64) << timekeeper.shift;
|
||||||
|
let mut offset = offset;
|
||||||
|
|
||||||
|
// 检查offset是否小于一个NTP周期间隔
|
||||||
|
if offset < timekeeper.cycle_interval.data() << shift {
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 累积一个移位的interval
|
||||||
|
offset -= timekeeper.cycle_interval.data() << shift;
|
||||||
|
clock_data
|
||||||
|
.cycle_last
|
||||||
|
.add(CycleNum::new(timekeeper.cycle_interval.data() << shift));
|
||||||
|
if clock.update_clocksource_data(clock_data).is_err() {
|
||||||
|
debug!("logarithmic_accumulation:update_clocksource_data run failed");
|
||||||
|
}
|
||||||
|
timekeeper.clock.replace(clock.clone());
|
||||||
|
|
||||||
|
// 更新xime_nsec
|
||||||
|
timekeeper.xtime_nsec += timekeeper.xtime_interval << shift;
|
||||||
|
while timekeeper.xtime_nsec >= nsecps {
|
||||||
|
timekeeper.xtime_nsec -= nsecps;
|
||||||
|
timekeeper.xtime.tv_sec += 1;
|
||||||
|
// TODO: 处理闰秒
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO:更新raw_time
|
||||||
|
|
||||||
|
// TODO:计算ntp_error
|
||||||
|
|
||||||
|
return offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,19 +317,15 @@ pub fn getnstimeofday() -> PosixTimeSpec {
|
|||||||
Some(tk) => {
|
Some(tk) => {
|
||||||
xtime = tk.xtime;
|
xtime = tk.xtime;
|
||||||
drop(tk);
|
drop(tk);
|
||||||
// 提供基于cpu周期数的ns时间,以便在两次update_wall_time之间提供更好的精度
|
|
||||||
let cpu_delta_ns = timekeeper().do_read_cpu_cycle_ns() as u64;
|
|
||||||
|
|
||||||
// 尚未同步到xtime的时间
|
nsecs = timekeeper().timekeeping_get_ns();
|
||||||
let tmp_delta_ns = __ADDED_USEC.load(Ordering::SeqCst) as u64 * 1000;
|
|
||||||
|
|
||||||
nsecs = cpu_delta_ns + tmp_delta_ns;
|
|
||||||
// TODO 不同架构可能需要加上不同的偏移量
|
// TODO 不同架构可能需要加上不同的偏移量
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xtime.tv_nsec += nsecs as i64;
|
xtime.tv_nsec += nsecs;
|
||||||
xtime.tv_sec += xtime.tv_nsec / NSEC_PER_SEC as i64;
|
xtime.tv_sec += xtime.tv_nsec / NSEC_PER_SEC as i64;
|
||||||
xtime.tv_nsec %= NSEC_PER_SEC as i64;
|
xtime.tv_nsec %= NSEC_PER_SEC as i64;
|
||||||
// debug!("getnstimeofday: xtime = {:?}, nsecs = {:}", xtime, nsecs);
|
// debug!("getnstimeofday: xtime = {:?}, nsecs = {:}", xtime, nsecs);
|
||||||
@ -267,8 +379,6 @@ pub fn timekeeping_init() {
|
|||||||
timekeeper.wall_to_monotonic.tv_sec,
|
timekeeper.wall_to_monotonic.tv_sec,
|
||||||
) = (-timekeeper.xtime.tv_nsec, -timekeeper.xtime.tv_sec);
|
) = (-timekeeper.xtime.tv_nsec, -timekeeper.xtime.tv_sec);
|
||||||
|
|
||||||
__ADDED_USEC.store(0, Ordering::SeqCst);
|
|
||||||
|
|
||||||
drop(irq_guard);
|
drop(irq_guard);
|
||||||
drop(timekeeper);
|
drop(timekeeper);
|
||||||
jiffies_init();
|
jiffies_init();
|
||||||
@ -276,7 +386,8 @@ pub fn timekeeping_init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// # 使用当前时钟源增加wall time
|
/// # 使用当前时钟源增加wall time
|
||||||
pub fn update_wall_time(delta_us: i64) {
|
/// 参考:https://code.dragonos.org.cn/xref/linux-3.4.99/kernel/time/timekeeping.c#1041
|
||||||
|
pub fn update_wall_time() {
|
||||||
// debug!("enter update_wall_time, stack_use = {:}",stack_use);
|
// debug!("enter update_wall_time, stack_use = {:}",stack_use);
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||||
@ -285,60 +396,74 @@ pub fn update_wall_time(delta_us: i64) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== 请不要删除这些注释 =====
|
let mut tk = timekeeper().inner.write_irqsave();
|
||||||
// let clock = timekeeper.clock.clone().unwrap();
|
// 获取当前时钟源
|
||||||
// let clock_data = clock.clocksource_data();
|
let clock = tk.clock.clone().unwrap();
|
||||||
// let offset = (clock.read().div(clock_data.watchdog_last).data()) & clock_data.mask.bits();
|
let clock_data = clock.clocksource_data();
|
||||||
|
// 计算从上一次更新周期以来经过的时钟周期数
|
||||||
|
let mut offset = (clock.read().div(clock_data.cycle_last).data()) & clock_data.mask.bits();
|
||||||
|
// 检查offset是否达到了一个NTP周期间隔
|
||||||
|
if offset < tk.cycle_interval.data() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// timekeeper.xtime_nsec = (timekeeper.xtime.tv_nsec as u64) << timekeeper.shift;
|
// 将纳秒部分转换为更高精度的格式
|
||||||
// // TODO 当有ntp模块之后 需要将timekeep与ntp进行同步并检查
|
tk.xtime_nsec = (tk.xtime.tv_nsec as u64) << tk.shift;
|
||||||
// timekeeper.xtime.tv_nsec = ((timekeeper.xtime_nsec as i64) >> timekeeper.shift) + 1;
|
|
||||||
// timekeeper.xtime_nsec -= (timekeeper.xtime.tv_nsec as u64) << timekeeper.shift;
|
|
||||||
|
|
||||||
// timekeeper.xtime.tv_nsec += offset as i64;
|
let mut shift = (offset.ilog2() - tk.cycle_interval.data().ilog2()) as i32;
|
||||||
// while unlikely(timekeeper.xtime.tv_nsec >= NSEC_PER_SEC.into()) {
|
shift = shift.max(0);
|
||||||
// timekeeper.xtime.tv_nsec -= NSEC_PER_SEC as i64;
|
// let max_shift = (64 - (ntp_tick_length().ilog2()+1)) - 1;
|
||||||
// timekeeper.xtime.tv_sec += 1;
|
// shift = min(shift, max_shift)
|
||||||
// // TODO 需要处理闰秒
|
while offset >= tk.cycle_interval.data() {
|
||||||
// }
|
offset = timekeeper().logarithmic_accumulation(offset, shift);
|
||||||
// ================
|
if offset < tk.cycle_interval.data() << shift {
|
||||||
compiler_fence(Ordering::SeqCst);
|
shift -= 1;
|
||||||
|
|
||||||
__ADDED_USEC.fetch_add(delta_us, Ordering::SeqCst);
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
let mut retry = 10;
|
|
||||||
|
|
||||||
let usec = __ADDED_USEC.load(Ordering::SeqCst);
|
|
||||||
|
|
||||||
// 一分钟同步一次
|
|
||||||
loop {
|
|
||||||
if (usec & !((1 << 26) - 1)) != 0 {
|
|
||||||
if __ADDED_USEC
|
|
||||||
.compare_exchange(usec, 0, Ordering::SeqCst, Ordering::SeqCst)
|
|
||||||
.is_ok()
|
|
||||||
|| retry == 0
|
|
||||||
{
|
|
||||||
// 同步时间
|
|
||||||
// 我感觉这里会出问题:多个读者不退出的话,写者就无法写入
|
|
||||||
// 然后这里会超时,导致在中断返回之后,会不断的进入这个中断,最终爆栈。
|
|
||||||
let mut timekeeper = timekeeper().inner.write_irqsave();
|
|
||||||
timekeeper.xtime.tv_nsec = ktime_get_real_ns();
|
|
||||||
timekeeper.xtime.tv_sec = 0;
|
|
||||||
__ADDED_USEC.store(0, Ordering::SeqCst);
|
|
||||||
|
|
||||||
drop(timekeeper);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
retry -= 1;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
timekeeper().mark_update_wall_time_ok();
|
|
||||||
// TODO 需要检查是否更新时间源
|
timekeeper().timekeeping_adjust(offset as i64);
|
||||||
|
|
||||||
|
// 处理xtime_nsec下溢问题,并对NTP误差进行调整
|
||||||
|
if unlikely((tk.xtime_nsec as i64) < 0) {
|
||||||
|
let neg = -(tk.xtime_nsec as i64);
|
||||||
|
tk.xtime_nsec = 0;
|
||||||
|
tk.ntp_error += neg << tk.ntp_error_shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将纳秒部分舍入后存储在xtime.tv_nsec中
|
||||||
|
tk.xtime.tv_nsec = ((tk.xtime_nsec as i64) >> tk.shift) + 1;
|
||||||
|
tk.xtime_nsec -= (tk.xtime.tv_nsec as u64) << tk.shift;
|
||||||
|
|
||||||
|
// 确保经过舍入后的xtime.tv_nsec不会大于NSEC_PER_SEC,并在超过1秒的情况下进行适当的调整
|
||||||
|
if unlikely(tk.xtime.tv_nsec >= NSEC_PER_SEC.into()) {
|
||||||
|
tk.xtime.tv_nsec -= NSEC_PER_SEC as i64;
|
||||||
|
tk.xtime.tv_sec += 1;
|
||||||
|
// TODO: 处理闰秒
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新时间的相关信息
|
||||||
|
timekeeping_update();
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
drop(irq_guard);
|
drop(irq_guard);
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
// TODO timekeeping_adjust
|
|
||||||
// TODO wall_to_monotic
|
// TODO wall_to_monotic
|
||||||
|
|
||||||
|
/// 参考:https://code.dragonos.org.cn/xref/linux-3.4.99/kernel/time/timekeeping.c#190
|
||||||
|
pub fn timekeeping_update() {
|
||||||
|
// TODO:如果clearntp为true,则会清除NTP错误并调用ntp_clear()
|
||||||
|
|
||||||
|
// 更新实时时钟偏移量,用于跟踪硬件时钟与系统时间的差异,以便进行时间校正
|
||||||
|
update_rt_offset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # 更新实时偏移量(墙上之间与单调时间的差值)
|
||||||
|
pub fn update_rt_offset() {
|
||||||
|
let mut timekeeper = timekeeper().inner.write_irqsave();
|
||||||
|
let ts = PosixTimeSpec::new(
|
||||||
|
-timekeeper.wall_to_monotonic.tv_sec,
|
||||||
|
-timekeeper.wall_to_monotonic.tv_nsec,
|
||||||
|
);
|
||||||
|
timekeeper.real_time_offset = timespec_to_ktime(ts);
|
||||||
|
}
|
||||||
|
@ -366,11 +366,17 @@ pub fn try_raise_timer_softirq() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 处理本地定时器中断
|
||||||
|
pub fn run_local_timer() {
|
||||||
|
assert!(!CurrentIrqArch::is_irq_enabled());
|
||||||
|
try_raise_timer_softirq();
|
||||||
|
}
|
||||||
|
|
||||||
/// 更新系统时间片
|
/// 更新系统时间片
|
||||||
pub fn update_timer_jiffies(add_jiffies: u64, time_us: i64) -> u64 {
|
pub fn update_timer_jiffies(add_jiffies: u64) -> u64 {
|
||||||
let prev = TIMER_JIFFIES.fetch_add(add_jiffies, Ordering::SeqCst);
|
let prev = TIMER_JIFFIES.fetch_add(add_jiffies, Ordering::SeqCst);
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
update_wall_time(time_us);
|
update_wall_time();
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
return prev + add_jiffies;
|
return prev + add_jiffies;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user