mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-18 16:26:31 +00:00
修复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:
@ -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:
|
||||
|
@ -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!()
|
||||
}
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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> {
|
||||
|
@ -1,8 +0,0 @@
|
||||
|
||||
CFLAGS += -I .
|
||||
|
||||
|
||||
all: clocksource.o
|
||||
|
||||
clocksource.o: clocksource.c
|
||||
$(CC) $(CFLAGS) -c clocksource.c -o clocksource.o
|
@ -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");
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
extern int rs_clocksource_watchdog_kthread(void *_data);
|
||||
|
||||
|
||||
void run_watchdog_kthread();
|
@ -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(());
|
||||
}
|
||||
|
@ -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> {
|
||||
|
@ -492,4 +492,7 @@ pub trait TimeArch {
|
||||
///
|
||||
/// The expire cycles
|
||||
fn cal_expire_cycles(ns: usize) -> usize;
|
||||
|
||||
/// 将CPU的时钟周期数转换为纳秒
|
||||
fn cycles2ns(cycles: usize) -> usize;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Reference in New Issue
Block a user