实现gettimeofday()系统调用和clocksource+timekeeping子模块 (#278)

- 实现gettimeofday()系统调用
- 实现clocksource+timekeeping子模块部分功能
- 实现了timespec转换成日期时间
This commit is contained in:
houmkh
2023-06-17 22:48:15 +08:00
committed by GitHub
parent a55ac7b928
commit 36fd013004
34 changed files with 1988 additions and 78 deletions

View File

@ -17,7 +17,7 @@ export ASFLAGS := --64
LD_LIST := head.o
kernel_subdirs := common driver process debug arch exception mm smp sched syscall ktest libs ipc io
kernel_subdirs := common driver process debug arch exception mm smp sched syscall ktest libs ipc io time

View File

@ -1,18 +1,18 @@
use core::{arch::asm, ptr::read_volatile};
use core::arch::asm;
#[inline]
pub fn local_irq_save(flags: &mut u64) {
pub fn local_irq_save() -> usize {
let x: usize;
unsafe {
asm!("pushfq", "pop rax", "mov rax, {0}", "cli", out(reg)(*flags),);
asm!("pushfq ; pop {} ; cli", out(reg) x, options(nostack));
}
x
}
#[inline]
pub fn local_irq_restore(flags: &u64) {
let x = unsafe { read_volatile(flags) };
// 恢复先前保存的rflags的值x
pub fn local_irq_restore(x: usize) {
unsafe {
asm!("push r15",
"popfq", in("r15")(x));
asm!("push {} ; popfq", in(reg) x, options(nostack));
}
}

View File

@ -79,8 +79,7 @@ impl FpState {
/// @brief 从用户态进入内核时,保存浮点寄存器,并关闭浮点功能
pub fn fp_state_save(pcb: &mut process_control_block) {
// 该过程中不允许中断
let mut rflags: u64 = 0;
local_irq_save(&mut rflags);
let rflags = local_irq_save();
let fp: &mut FpState = if pcb.fp_state == null_mut() {
let f = Box::leak(Box::new(FpState::default()));
@ -112,14 +111,13 @@ pub fn fp_state_save(pcb: &mut process_control_block) {
"mov cr4, rax" */
)
}
local_irq_restore(&rflags);
local_irq_restore(rflags);
}
/// @brief 从内核态返回用户态时,恢复浮点寄存器,并开启浮点功能
pub fn fp_state_restore(pcb: &mut process_control_block) {
// 该过程中不允许中断
let mut rflags: u64 = 0;
local_irq_save(&mut rflags);
let rflags = local_irq_save();
if pcb.fp_state == null_mut() {
panic!("fp_state_restore: fp_state is null. pid={}", pcb.pid);
@ -143,5 +141,5 @@ pub fn fp_state_restore(pcb: &mut process_control_block) {
fp.restore();
fp.clear();
local_irq_restore(&rflags);
local_irq_restore(rflags);
}

View File

@ -48,8 +48,7 @@ impl InterruptArch for X86_64InterruptArch {
unsafe fn save_and_disable_irq() -> IrqFlagsGuard {
compiler_fence(Ordering::SeqCst);
let mut rflags: u64 = 0;
local_irq_save(&mut rflags);
let rflags = local_irq_save() as u64;
let flags = IrqFlags::new(rflags);
let guard = IrqFlagsGuard::new(flags);
compiler_fence(Ordering::SeqCst);
@ -58,7 +57,7 @@ impl InterruptArch for X86_64InterruptArch {
unsafe fn restore_irq(flags: IrqFlags) {
compiler_fence(Ordering::SeqCst);
local_irq_restore(&flags.flags());
local_irq_restore(flags.flags() as usize);
compiler_fence(Ordering::SeqCst);
}
}

View File

@ -66,4 +66,11 @@ extern struct cpu_core_info_t cpu_core_info[MAX_CPU_NUM];
*
* @return uint32_t 当前cpu核心晶振频率
*/
uint32_t cpu_get_core_crysral_freq();
uint32_t cpu_get_core_crysral_freq();
/**
* @brief 获取处理器的tsc频率单位hz
*
* @return uint64_t
*/
uint64_t cpu_get_tsc_freq();

View File

@ -207,12 +207,13 @@ void HPET_enable()
// kdebug("[HPET0] conf register after modify=%#018lx", ((*(uint64_t *)(HPET_REG_BASE + TIM0_CONF))));
// kdebug("[HPET1] conf register =%#018lx", ((*(uint64_t *)(HPET_REG_BASE + TIM1_CONF))));
kinfo("HPET0 enabled.");
__write8b(HPET_REG_BASE + GEN_CONF, 3); // 置位旧设备中断路由兼容标志位、定时器组使能标志位
io_mfence();
// 注册中断
irq_register(34, &entry, &HPET_handler, 0, &HPET_intr_controller, "HPET0");
io_mfence();
__write8b(HPET_REG_BASE + GEN_CONF, 3); // 置位旧设备中断路由兼容标志位、定时器组使能标志位
kinfo("HPET0 enabled.");
io_mfence();
}
int HPET_init()

View File

@ -1,5 +1,6 @@
use crate::{
arch::interrupt::{cli, sti},
arch::CurrentIrqArch,
exception::InterruptArch,
include::bindings::bindings::{io_in8, io_out8},
syscall::SystemError,
};
@ -33,7 +34,7 @@ impl RtcTime {
///@return int 成功则为0
pub fn get(&mut self) -> Result<i32, SystemError> {
// 为防止中断请求打断该过程,需要先关中断
cli();
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
//0x0B
let status_register_b: u8 = read_cmos(0x0B); // 读取状态寄存器B
let is_24h: bool = if (status_register_b & 0x02) != 0 {
@ -81,7 +82,7 @@ impl RtcTime {
self.hour = ((self.hour & 0x7f) + 12) % 24;
} // 将十二小时制转为24小时
sti();
drop(irq_guard);
return Ok(0);
}

View File

@ -225,15 +225,14 @@ impl Softirq {
}
pub fn raise_softirq(&self, softirq_num: SoftirqNumber) {
let mut flags = 0;
local_irq_save(&mut flags);
let flags = local_irq_save();
let processor_id = smp_get_processor_id() as usize;
cpu_pending(processor_id).insert(VecStatus::from(softirq_num));
compiler_fence(Ordering::SeqCst);
local_irq_restore(&flags);
local_irq_restore(flags);
// kdebug!("raise_softirq exited");
}
pub unsafe fn clear_softirq_pending(&self, softirq_num: SoftirqNumber) {

View File

@ -46,4 +46,5 @@
#include <process/process.h>
#include <sched/sched.h>
#include <smp/smp.h>
#include <time/clocksource.h>
#include <time/sleep.h>

View File

@ -120,3 +120,12 @@ uint32_t cpu_get_core_crysral_freq()
return c;
}
/**
* @brief 获取处理器的tsc频率单位hz
*
* @return uint64_t
*/
uint64_t cpu_get_tsc_freq()
{
return Cpu_tsc_freq;
}

View File

@ -14,7 +14,7 @@ use crate::syscall::SystemError;
/// @brief 保存中断状态到flags中关闭中断并对自旋锁加锁
#[inline]
pub fn spin_lock_irqsave(lock: *mut spinlock_t, flags: &mut u64) {
local_irq_save(flags);
*flags = local_irq_save() as u64;
unsafe {
spin_lock(lock);
}
@ -27,7 +27,7 @@ pub fn spin_unlock_irqrestore(lock: *mut spinlock_t, flags: &u64) {
spin_unlock(lock);
}
// kdebug!("123");
local_irq_restore(flags);
local_irq_restore(*flags as usize);
}
/// 判断一个自旋锁是否已经被加锁
@ -130,14 +130,14 @@ impl RawSpinlock {
/// @brief 保存中断状态到flags中关闭中断并对自旋锁加锁
pub fn lock_irqsave(&self, flags: &mut u64) {
local_irq_save(flags);
*flags = local_irq_save() as u64;
self.lock();
}
/// @brief 恢复rflags以及中断状态并解锁自旋锁
pub fn unlock_irqrestore(&self, flags: &u64) {
self.unlock();
local_irq_restore(flags);
local_irq_restore(*flags as usize);
}
/// @brief 尝试保存中断状态到flags中关闭中断并对自旋锁加锁
@ -145,11 +145,11 @@ impl RawSpinlock {
/// 加锁失败->false
#[inline(always)]
pub fn try_lock_irqsave(&self, flags: &mut u64) -> bool {
local_irq_save(flags);
*flags = local_irq_save() as u64;
if self.try_lock() {
return true;
}
local_irq_restore(flags);
local_irq_restore(*flags as usize);
return false;
}
}

View File

@ -51,7 +51,8 @@ void reload_gdt()
gdtp.size = bsp_gdt_size - 1;
gdtp.gdt_vaddr = (ul)phys_2_virt((ul)&GDT_Table);
asm volatile("lgdt (%0) \n\t" ::"r"(&gdtp) : "memory");
asm volatile("lgdt (%0) \n\t" ::"r"(&gdtp)
: "memory");
}
void reload_idt()
@ -62,7 +63,8 @@ void reload_idt()
// kdebug("gdtvaddr=%#018lx", p.gdt_vaddr);
// kdebug("gdt size=%d", p.size);
asm volatile("lidt (%0) \n\t" ::"r"(&idtp) : "memory");
asm volatile("lidt (%0) \n\t" ::"r"(&idtp)
: "memory");
}
// 初始化系统各模块
@ -124,15 +126,21 @@ void system_initialize()
current_pcb->cpu_id = 0;
current_pcb->preempt_count = 0;
// 先初始化系统调用模块
syscall_init();
io_mfence();
// 再初始化进程模块。顺序不能调转
// sched_init();
rs_timekeeping_init();
io_mfence();
rs_timer_init();
io_mfence();
rs_jiffies_init();
io_mfence();
rs_clocksource_boot_finish();
// 这里必须加内存屏障,否则会出错
io_mfence();
smp_init();
@ -140,7 +148,7 @@ void system_initialize()
vfs_init();
rs_tty_init();
cpu_init();
ps2_keyboard_init();
// tty_init();
@ -160,7 +168,7 @@ void system_initialize()
io_mfence();
// current_pcb->preempt_count = 0;
// kdebug("cpu_get_core_crysral_freq()=%ld", cpu_get_core_crysral_freq());
process_init();
// 启用double buffer
// scm_enable_double_buffer(); // 因为时序问题, 该函数调用被移到 initial_kernel_thread
@ -173,7 +181,7 @@ void system_initialize()
apic_timer_init();
io_mfence();
// 这里不能删除否则在O1会报错
// while (1)
// pause();

View File

@ -15,13 +15,16 @@ use super::socket::{SOCKET_SET, SOCKET_WAITQUEUE};
/// The network poll function, which will be called by timer.
///
/// The main purpose of this function is to poll all network interfaces.
struct NetWorkPollFunc();
#[derive(Debug)]
struct NetWorkPollFunc;
impl TimerFunction for NetWorkPollFunc {
fn run(&mut self) {
fn run(&mut self) -> Result<(), SystemError> {
poll_ifaces_try_lock(10).ok();
let next_time = next_n_ms_timer_jiffies(10);
let timer = Timer::new(Box::new(NetWorkPollFunc()), next_time);
let timer = Timer::new(Box::new(NetWorkPollFunc), next_time);
timer.activate();
return Ok(());
}
}
@ -29,7 +32,7 @@ pub fn net_init() -> Result<(), SystemError> {
dhcp_query()?;
// Init poll timer function
let next_time = next_n_ms_timer_jiffies(5);
let timer = Timer::new(Box::new(NetWorkPollFunc()), next_time);
let timer = Timer::new(Box::new(NetWorkPollFunc), next_time);
timer.activate();
return Ok(());
}

View File

@ -859,7 +859,8 @@ void process_exit_thread(struct process_control_block *pcb)
int process_release_pcb(struct process_control_block *pcb)
{
// 释放子进程的页表
process_exit_mm(pcb);
// BUG 暂时注释process_exit_mm
// process_exit_mm(pcb);
if ((pcb->flags & PF_KTHREAD)) // 释放内核线程的worker private结构体
free_kthread_struct(pcb);

View File

@ -16,7 +16,10 @@ use crate::{
io::SeekFrom,
kinfo,
net::syscall::SockAddr,
time::TimeSpec,
time::{
syscall::{PosixTimeZone, PosixTimeval, SYS_TIMEZONE},
TimeSpec,
},
};
#[repr(i32)]
@ -354,6 +357,7 @@ pub const SYS_ACCEPT: usize = 40;
pub const SYS_GETSOCKNAME: usize = 41;
pub const SYS_GETPEERNAME: usize = 42;
pub const SYS_GETTIMEOFDAY: usize = 43;
#[derive(Debug)]
pub struct Syscall;
@ -867,6 +871,43 @@ impl Syscall {
SYS_GETPEERNAME => {
Self::getpeername(args[0], args[1] as *mut SockAddr, args[2] as *mut u32)
}
SYS_GETTIMEOFDAY => {
let timeval = args[0] as *mut PosixTimeval;
let timezone_ptr = args[1] as *const PosixTimeZone;
let security_check = || {
if unsafe {
verify_area(timeval as u64, core::mem::size_of::<PosixTimeval>() as u64)
} == false
{
return Err(SystemError::EFAULT);
}
if unsafe {
verify_area(
timezone_ptr as u64,
core::mem::size_of::<PosixTimeZone>() as u64,
)
} == false
{
return Err(SystemError::EFAULT);
}
return Ok(());
};
let r = security_check();
if r.is_err() {
Err(r.unwrap_err())
} else {
let timezone = if !timezone_ptr.is_null() {
&SYS_TIMEZONE
} else {
unsafe { timezone_ptr.as_ref().unwrap() }
};
if !timeval.is_null() {
Self::gettimeofday(timeval, timezone)
} else {
Err(SystemError::EFAULT)
}
}
}
_ => panic!("Unsupported syscall ID: {}", syscall_num),
};

View File

@ -53,3 +53,6 @@
#define SYS_ACCEPT 40 // 接受一个socket连接
#define SYS_GETSOCKNAME 41 // 获取socket的名字
#define SYS_GETPEERNAME 42 // 获取socket的对端名字
#define SYS_GETTIMEOFDAY 43 // 获取当前时间
#define SYS_AHCI_END_REQ 255 // AHCI DMA请求结束end_request的系统调用

8
kernel/src/time/Makefile Normal file
View File

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

View File

@ -0,0 +1,8 @@
#include "clocksource.h"
#include <common/kthread.h>
void run_watchdog_kthread()
{
kdebug("run_watchdog_kthread");
kthread_run(rs_clocksource_watchdog_kthread, NULL, "clocksource_watchdog");
}

View File

@ -0,0 +1,8 @@
#pragma once
#include <common/kthread.h>
extern int rs_clocksource_watchdog_kthread(void *_data);
extern void rs_clocksource_boot_finish();
void run_watchdog_kthread();

View File

@ -0,0 +1,850 @@
use core::{
ffi::c_void,
fmt::Debug,
sync::atomic::{AtomicBool, Ordering},
};
use alloc::{boxed::Box, collections::LinkedList, string::String, sync::Arc, vec::Vec};
use lazy_static::__Deref;
use crate::{
include::bindings::bindings::run_watchdog_kthread, kdebug, kinfo, libs::spinlock::SpinLock,
syscall::SystemError,
};
use super::{
jiffies::clocksource_default_clock,
timer::{clock, Timer, TimerFunction},
NSEC_PER_SEC,
};
lazy_static! {
/// linked list with the registered clocksources
pub static ref CLOCKSOURCE_LIST: SpinLock<LinkedList<Arc<dyn Clocksource>>> =
SpinLock::new(LinkedList::new());
/// 被监视中的时钟源
pub static ref WATCHDOG_LIST: SpinLock<LinkedList<Arc<dyn Clocksource>>> =
SpinLock::new(LinkedList::new());
pub static ref CLOCKSOUCE_WATCHDOG:SpinLock<ClocksouceWatchdog> = SpinLock::new(ClocksouceWatchdog::new());
pub static ref OVERRIDE_NAME: SpinLock<String> = SpinLock::new(String::from(""));
}
/// 正在被使用时钟源
pub static CUR_CLOCKSOURCE: SpinLock<Option<Arc<dyn Clocksource>>> = SpinLock::new(None);
/// 是否完成加载
pub static mut FINISHED_BOOTING: AtomicBool = AtomicBool::new(false);
/// Interval: 0.5sec Threshold: 0.0625s
/// 系统节拍率
pub const HZ: u64 = 1000;
/// watchdog检查间隔
pub const WATCHDOG_INTERVAL: u64 = HZ >> 1;
/// 最大能接受的误差大小
pub const WATCHDOG_THRESHOLD: u32 = NSEC_PER_SEC >> 4;
// 时钟周期数
#[derive(Debug, Clone, Copy)]
#[repr(transparent)]
pub struct CycleNum(pub u64);
#[allow(dead_code)]
impl CycleNum {
#[inline(always)]
pub fn new(cycle: u64) -> Self {
Self(cycle)
}
#[inline(always)]
pub fn data(&self) -> u64 {
self.0
}
#[inline(always)]
#[allow(dead_code)]
pub fn add(&self, other: CycleNum) -> CycleNum {
CycleNum(self.data() + other.data())
}
#[inline(always)]
pub fn div(&self, other: CycleNum) -> CycleNum {
CycleNum(self.data() - other.data())
}
}
bitflags! {
#[derive(Default)]
pub struct ClocksourceMask: u64 {
}
/// 时钟状态标记
#[derive(Default)]
pub struct ClocksourceFlags: u64 {
/// 表示时钟设备是连续的
const CLOCK_SOURCE_IS_CONTINUOUS = 0x01;
/// 表示该时钟源需要经过watchdog检查
const CLOCK_SOURCE_MUST_VERIFY = 0x02;
/// 表示该时钟源是watchdog
const CLOCK_SOURCE_WATCHDOG = 0x10;
/// 表示该时钟源是高分辨率的
const CLOCK_SOURCE_VALID_FOR_HRES = 0x20;
/// 表示该时钟源误差过大
const CLOCK_SOURCE_UNSTABLE = 0x40;
}
}
impl From<u64> for ClocksourceMask {
fn from(value: u64) -> Self {
if value < 64 {
return Self::from_bits_truncate((1 << value) - 1);
}
return Self::from_bits_truncate(u64::MAX);
}
}
impl ClocksourceMask {
pub fn new(b: u64) -> Self {
Self { bits: b }
}
}
impl ClocksourceFlags {
pub fn new(b: u64) -> Self {
Self { bits: b }
}
}
#[derive(Debug)]
pub struct ClocksouceWatchdog {
/// 监视器
watchdog: Option<Arc<dyn Clocksource>>,
/// 检查器是否在工作的标志
is_running: bool,
/// 上一次检查的时刻
last_check: CycleNum,
/// 定时监视器的过期时间
timer_expires: u64,
}
impl ClocksouceWatchdog {
pub fn new() -> Self {
Self {
watchdog: None,
is_running: false,
last_check: CycleNum(0),
timer_expires: 0,
}
}
/// 获取watchdog
fn get_watchdog(&mut self) -> &mut Option<Arc<dyn Clocksource>> {
&mut self.watchdog
}
/// 启用检查器
pub fn clocksource_start_watchdog(&mut self) {
// 如果watchdog未被设置或者已经启用了就退出
let watchdog_list = &WATCHDOG_LIST.lock();
if self.is_running || self.watchdog.is_none() || watchdog_list.is_empty() {
return;
}
// 生成一个定时器
let wd_timer_func: Box<WatchdogTimerFunc> = Box::new(WatchdogTimerFunc {});
self.timer_expires += clock() + WATCHDOG_INTERVAL;
self.last_check = self.watchdog.as_ref().unwrap().clone().read();
let wd_timer = Timer::new(wd_timer_func, self.timer_expires);
wd_timer.activate();
self.is_running = true;
}
/// 停止检查器
/// list_len WATCHDOG_LIST长度
pub fn clocksource_stop_watchdog(&mut self, list_len: usize) {
if !self.is_running || (self.watchdog.is_some() && list_len != 0) {
return;
}
// TODO 当实现了周期性的定时器后 需要将监视用的定时器删除
self.is_running = false;
}
}
/// 定时检查器
#[derive(Debug)]
pub struct WatchdogTimerFunc;
impl TimerFunction for WatchdogTimerFunc {
fn run(&mut self) -> Result<(), SystemError> {
return clocksource_watchdog();
}
}
/// 时钟源的特性
pub trait Clocksource: Send + Sync + Debug {
// TODO 返回值类型可能需要改变
/// returns a cycle value, passes clocksource as argument
fn read(&self) -> CycleNum;
/// optional function to enable the clocksource
fn enable(&self) -> Result<i32, SystemError> {
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
/// optional function to disable the clocksource
fn disable(&self) -> Result<(), SystemError> {
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
/// vsyscall based read
fn vread(&self) -> Result<CycleNum, SystemError> {
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
/// suspend function for the clocksource, if necessary
fn suspend(&self) -> Result<(), SystemError> {
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
/// resume function for the clocksource, if necessary
fn resume(&self) -> Result<(), SystemError> {
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
// 获取时钟源数据
fn clocksource_data(&self) -> ClocksourceData;
fn update_clocksource_data(&self, _data: ClocksourceData) -> Result<(), SystemError> {
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
// 获取时钟源
fn clocksource(&self) -> Arc<dyn Clocksource>;
}
/// # 实现整数log2的运算
///
/// ## 参数
///
/// * `x` - 要计算的数字
///
/// ## 返回值
///
/// * `u32` - 返回\log_2(x)的值
fn log2(x: u32) -> u32 {
let mut result = 0;
let mut x = x;
if x >= 1 << 16 {
x >>= 16;
result |= 16;
}
if x >= 1 << 8 {
x >>= 8;
result |= 8;
}
if x >= 1 << 4 {
x >>= 4;
result |= 4;
}
if x >= 1 << 2 {
x >>= 2;
result |= 2;
}
if x >= 1 << 1 {
result |= 1;
}
result
}
impl dyn Clocksource {
/// # 计算时钟源能记录的最大时间跨度
pub fn clocksource_max_deferment(&self) -> u64 {
let cs_data_guard = self.clocksource_data();
let max_nsecs: u64;
let mut max_cycles: u64;
max_cycles = (1 << (63 - (log2(cs_data_guard.mult) + 1))) as u64;
max_cycles = max_cycles.min(cs_data_guard.mask.bits);
max_nsecs = clocksource_cyc2ns(
CycleNum(max_cycles),
cs_data_guard.mult,
cs_data_guard.shift,
);
return max_nsecs - (max_nsecs >> 5);
}
/// # 注册时钟源
///
/// ## 返回值
///
/// * `Ok(0)` - 时钟源注册成功。
/// * `Err(SystemError)` - 时钟源注册失败。
pub fn register(&self) -> Result<i32, SystemError> {
let ns = self.clocksource_max_deferment();
let mut cs_data = self.clocksource_data();
cs_data.max_idle_ns = ns as u32;
self.update_clocksource_data(cs_data)?;
// 将时钟源加入到时钟源队列中
self.clocksource_enqueue();
// 将时钟源加入到监视队列中
self.clocksource_enqueue_watchdog()
.expect("register: failed to enqueue watchdog list");
// 选择一个最好的时钟源
clocksource_select();
kdebug!("clocksource_register successfully");
return Ok(0);
}
/// # 将时钟源插入时钟源队列
pub fn clocksource_enqueue(&self) {
// 根据rating由大到小排序
let cs_data = self.clocksource_data();
let list_guard = &mut 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 {
spilt_pos = pos;
break;
}
}
let mut temp_list = list_guard.split_off(spilt_pos);
let cs = self.clocksource();
list_guard.push_back(cs);
list_guard.append(&mut temp_list);
// kdebug!(
// "CLOCKSOURCE_LIST len = {:?},clocksource_enqueue sccessfully",
// list_guard.len()
// );
}
/// # 将时间源插入监控队列
///
/// ## 返回值
///
/// * `Ok(0)` - 时间源插入监控队列成功
/// * `Err(SystemError)` - 时间源插入监控队列失败
pub fn clocksource_enqueue_watchdog(&self) -> Result<i32, SystemError> {
// BUG 可能需要lock irq
let mut cs_data = self.clocksource_data();
let cs = self.clocksource();
if cs_data
.flags
.contains(ClocksourceFlags::CLOCK_SOURCE_MUST_VERIFY)
{
let mut list_guard = WATCHDOG_LIST.lock_irqsave();
// cs是被监视的
cs_data
.flags
.remove(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG);
cs.update_clocksource_data(cs_data)?;
list_guard.push_back(cs);
} else {
// cs是监视器
if cs_data
.flags
.contains(ClocksourceFlags::CLOCK_SOURCE_IS_CONTINUOUS)
{
// 如果时钟设备是连续的
cs_data
.flags
.insert(ClocksourceFlags::CLOCK_SOURCE_VALID_FOR_HRES);
cs.update_clocksource_data(cs_data.clone())?;
}
// 将时钟源加入到监控队列中
let mut list_guard = WATCHDOG_LIST.lock();
list_guard.push_back(cs.clone());
drop(list_guard);
// 对比当前注册的时间源的精度和监视器的精度
let cs_watchdog = &mut CLOCKSOUCE_WATCHDOG.lock();
if cs_watchdog.watchdog.is_none()
|| cs_data.rating
> cs_watchdog
.watchdog
.clone()
.unwrap()
.clocksource_data()
.rating
{
// 当前注册的时间源的精度更高或者没有监视器,替换监视器
cs_watchdog.watchdog.replace(cs);
clocksource_reset_watchdog();
}
// 启动监视器
cs_watchdog.clocksource_start_watchdog();
}
return Ok(0);
}
/// # 将时钟源标记为unstable
///
/// ## 参数
/// * `delta` - 时钟源误差
pub fn set_unstable(&self, delta: i64) -> Result<i32, SystemError> {
let mut cs_data = self.clocksource_data();
// 打印出unstable的时钟源信息
kdebug!(
"clocksource :{:?} is unstable, its delta is {:?}",
cs_data.name,
delta
);
cs_data.flags.remove(
ClocksourceFlags::CLOCK_SOURCE_VALID_FOR_HRES | ClocksourceFlags::CLOCK_SOURCE_WATCHDOG,
);
cs_data
.flags
.insert(ClocksourceFlags::CLOCK_SOURCE_UNSTABLE);
self.update_clocksource_data(cs_data)?;
// 启动watchdog线程 进行后续处理
if unsafe { FINISHED_BOOTING.load(Ordering::Relaxed) } {
// TODO 在实现了工作队列后将启动线程换成schedule work
unsafe { run_watchdog_kthread() }
}
return Ok(0);
}
/// # 将时间源从监视链表中弹出
fn clocksource_dequeue_watchdog(&self) {
let data = self.clocksource_data();
let mut locked_watchdog = CLOCKSOUCE_WATCHDOG.lock();
let watchdog = locked_watchdog
.get_watchdog()
.clone()
.unwrap()
.clocksource_data();
let mut list = WATCHDOG_LIST.lock();
let mut size = list.len();
let mut del_pos: usize = size;
for (pos, ele) in list.iter().enumerate() {
let ele_data = ele.clocksource_data();
if ele_data.name.eq(&data.name) && ele_data.rating.eq(&data.rating) {
// 记录要删除的时钟源在监视链表中的下标
del_pos = pos;
}
}
if data
.flags
.contains(ClocksourceFlags::CLOCK_SOURCE_MUST_VERIFY)
{
// 如果时钟源是需要被检查的,直接删除时钟源
if del_pos != size {
let mut temp_list = list.split_off(del_pos);
temp_list.pop_front();
list.append(&mut temp_list);
}
} else if watchdog.name.eq(&data.name) && watchdog.rating.eq(&data.rating) {
// 如果要删除的时钟源是监视器,则需要找到一个新的监视器
// TODO 重新设置时钟源
// 将链表解锁防止reset中双重加锁 并释放保存的旧的watchdog的数据
// 代替了clocksource_reset_watchdog()的功能将所有时钟源的watchdog标记清除
for ele in list.iter() {
ele.clocksource_data()
.flags
.remove(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG);
}
// 遍历所有时间源,寻找新的监视器
let mut clocksource_list = CLOCKSOURCE_LIST.lock();
let mut replace_pos: usize = clocksource_list.len();
for (pos, ele) in clocksource_list.iter().enumerate() {
let ele_data = ele.clocksource_data();
if ele_data.name.eq(&data.name) && ele_data.rating.eq(&data.rating)
|| ele_data
.flags
.contains(ClocksourceFlags::CLOCK_SOURCE_MUST_VERIFY)
{
// 当前时钟源是要被删除的时钟源或没被检查过的时钟源
// 不适合成为监视器
continue;
}
let watchdog = locked_watchdog.get_watchdog().clone();
if watchdog.is_none()
|| ele_data.rating > watchdog.unwrap().clocksource_data().rating
{
// 如果watchdog不存在或者当前时钟源的精度高于watchdog的精度则记录当前时钟源的下标
replace_pos = pos;
}
}
// 使用刚刚找到的更好的时钟源替换旧的watchdog
if replace_pos < clocksource_list.len() {
let mut temp_list = clocksource_list.split_off(replace_pos);
let new_wd = temp_list.front().unwrap().clone();
clocksource_list.append(&mut temp_list);
// 替换watchdog
locked_watchdog.watchdog.replace(new_wd);
// drop(locked_watchdog);
}
// 删除时钟源
if del_pos != size {
let mut temp_list = list.split_off(del_pos);
temp_list.pop_front();
list.append(&mut temp_list);
}
}
// 清除watchdog标记
let mut cs_data = self.clocksource_data();
cs_data
.flags
.remove(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG);
self.update_clocksource_data(cs_data)
.expect("clocksource_dequeue_watchdog: failed to update clocksource data");
size = list.len();
// 停止当前的watchdog
locked_watchdog.clocksource_stop_watchdog(size - 1);
}
/// # 将时钟源从时钟源链表中弹出
fn clocksource_dequeue(&self) {
let mut list = CLOCKSOURCE_LIST.lock();
let data = self.clocksource_data();
let mut del_pos: usize = list.len();
for (pos, ele) in list.iter().enumerate() {
let ele_data = ele.clocksource_data();
if ele_data.name.eq(&data.name) && ele_data.rating.eq(&data.rating) {
// 记录时钟源在链表中的下标
del_pos = pos;
}
}
// 删除时钟源
if del_pos != list.len() {
let mut temp_list = list.split_off(del_pos);
temp_list.pop_front();
list.append(&mut temp_list);
}
}
/// # 注销时钟源
#[allow(dead_code)]
pub fn unregister(&self) {
// 将时钟源从监视链表中弹出
self.clocksource_dequeue_watchdog();
// 将时钟源从时钟源链表中弹出
self.clocksource_dequeue();
// 检查是否有更好的时钟源
clocksource_select();
}
/// # 修改时钟源的精度
///
/// ## 参数
///
/// * `rating` - 指定的时钟精度
fn clocksource_change_rating(&self, rating: i32) {
// 将时钟源从链表中弹出
self.clocksource_dequeue();
let mut data = self.clocksource_data();
// 修改时钟源的精度
data.set_rating(rating);
self.update_clocksource_data(data)
.expect("clocksource_change_rating:updata clocksource failed");
// 插入时钟源到时钟源链表中
self.clocksource_enqueue();
// 检查是否有更好的时钟源
clocksource_select();
}
}
#[derive(Debug, Clone)]
pub struct ClocksourceData {
/// 时钟源名字
pub name: String,
/// 时钟精度
pub rating: i32,
pub mask: ClocksourceMask,
pub mult: u32,
pub shift: u32,
pub max_idle_ns: u32,
pub flags: ClocksourceFlags,
pub watchdog_last: CycleNum,
}
impl ClocksourceData {
#[allow(dead_code)]
pub fn new(
name: String,
rating: i32,
mask: ClocksourceMask,
mult: u32,
shift: u32,
max_idle_ns: u32,
flags: ClocksourceFlags,
) -> Self {
let csd = ClocksourceData {
name,
rating,
mask,
mult,
shift,
max_idle_ns,
flags,
watchdog_last: CycleNum(0),
};
return csd;
}
pub fn set_name(&mut self, name: String) {
self.name = name;
}
pub fn set_rating(&mut self, rating: i32) {
self.rating = rating;
}
pub fn set_mask(&mut self, mask: ClocksourceMask) {
self.mask = mask;
}
pub fn set_mult(&mut self, mult: u32) {
self.mult = mult;
}
pub fn set_shift(&mut self, shift: u32) {
self.shift = shift;
}
pub fn set_max_idle_ns(&mut self, max_idle_ns: u32) {
self.max_idle_ns = max_idle_ns;
}
pub fn set_flags(&mut self, flags: ClocksourceFlags) {
self.flags = flags;
}
#[allow(dead_code)]
pub fn remove_flags(&mut self, flags: ClocksourceFlags) {
self.flags.remove(flags)
}
#[allow(dead_code)]
pub fn insert_flags(&mut self, flags: ClocksourceFlags) {
self.flags.insert(flags)
}
}
/// converts clocksource cycles to nanoseconds
///
pub fn clocksource_cyc2ns(cycles: CycleNum, mult: u32, shift: u32) -> u64 {
return (cycles.data() * mult as u64) >> shift;
}
/// # 重启所有的时间源
#[allow(dead_code)]
pub fn clocksource_resume() {
let list = CLOCKSOURCE_LIST.lock();
for ele in list.iter() {
let data = ele.clocksource_data();
match ele.resume() {
Ok(_) => continue,
Err(_) => {
kdebug!("clocksource {:?} resume failed", data.name)
}
}
}
clocksource_resume_watchdog();
}
/// # 暂停所有的时间源
#[allow(dead_code)]
pub fn clocksource_suspend() {
let list = CLOCKSOURCE_LIST.lock();
for ele in list.iter() {
let data = ele.clocksource_data();
match ele.suspend() {
Ok(_) => continue,
Err(_) => {
kdebug!("clocksource {:?} suspend failed", data.name)
}
}
}
}
/// # 根据watchdog的精度来检查被监视的时钟源的误差
///
/// ## 返回值
///
/// * `Ok()` - 检查完成
/// * `Err(SystemError)` - 错误码
pub fn clocksource_watchdog() -> Result<(), SystemError> {
let mut cs_watchdog = CLOCKSOUCE_WATCHDOG.lock();
// watchdog没有在运行的话直接退出
if !cs_watchdog.is_running || cs_watchdog.watchdog.is_none() {
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);
let watchdog_list = &mut WATCHDOG_LIST.lock();
for cs in watchdog_list.iter() {
let mut cs_data = cs.clocksource_data();
// 判断时钟源是否已经被标记为不稳定
if cs_data
.flags
.contains(ClocksourceFlags::CLOCK_SOURCE_UNSTABLE)
{
// 启动watchdog_kthread
unsafe { run_watchdog_kthread() };
continue;
}
// 读取时钟源现在的时间
let cs_now_clock = cs.read();
// 如果时钟源没有被监视,则开始监视他
if !cs_data
.flags
.contains(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG)
{
cs_data
.flags
.insert(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG);
// 记录此次检查的时刻
cs_data.watchdog_last = cs_now_clock;
cs.update_clocksource_data(cs_data.clone())?;
continue;
}
// 计算时钟源的误差
let cs_dev_nsec = clocksource_cyc2ns(
CycleNum(cs_now_clock.div(cs_data.watchdog_last).data() & cs_data.mask.bits),
cs_data.mult,
cs_data.shift,
);
// 记录此次检查的时刻
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() {
// 误差过大标记为unstable
cs.set_unstable((cs_dev_nsec - wd_dev_nsec).try_into().unwrap())?;
continue;
}
// 判断是否要切换为高精度模式
if !cs_data
.flags
.contains(ClocksourceFlags::CLOCK_SOURCE_VALID_FOR_HRES)
&& cs_data
.flags
.contains(ClocksourceFlags::CLOCK_SOURCE_IS_CONTINUOUS)
&& cur_wd_data
.flags
.contains(ClocksourceFlags::CLOCK_SOURCE_IS_CONTINUOUS)
{
cs_data
.flags
.insert(ClocksourceFlags::CLOCK_SOURCE_VALID_FOR_HRES);
cs.update_clocksource_data(cs_data)?;
// TODO 通知tick机制 切换为高精度模式
}
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();
}
return Ok(());
}
/// # watchdog线程的逻辑执行unstable的后续操作
pub 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();
// 将不稳定的时钟源弹出监视链表
for (pos, ele) in wd_list.iter().enumerate() {
let data = ele.clocksource_data();
if data.flags.contains(ClocksourceFlags::CLOCK_SOURCE_UNSTABLE) {
del_vec.push(pos);
del_clocks.push(ele.clone());
}
}
for pos in del_vec {
let mut temp_list = wd_list.split_off(pos);
temp_list.pop_front();
wd_list.append(&mut temp_list);
}
// 检查是否需要停止watchdog
CLOCKSOUCE_WATCHDOG
.lock()
.clocksource_stop_watchdog(wd_list.len());
// 将不稳定的时钟源精度都设置为最低
for clock in del_clocks.iter() {
clock.clocksource_change_rating(0);
}
}
/// # 清空所有时钟源的watchdog标志位
pub fn clocksource_reset_watchdog() {
let list_guard = WATCHDOG_LIST.lock();
for ele in list_guard.iter() {
ele.clocksource_data()
.flags
.remove(ClocksourceFlags::CLOCK_SOURCE_WATCHDOG);
}
}
/// # 重启检查器
pub fn clocksource_resume_watchdog() {
clocksource_reset_watchdog();
}
/// # 根据精度选择最优的时钟源,或者接受用户指定的时间源
pub fn clocksource_select() {
let list_guard = CLOCKSOURCE_LIST.lock();
if unsafe { FINISHED_BOOTING.load(Ordering::Relaxed) } || list_guard.is_empty() {
return;
}
let mut best = list_guard.front().unwrap().clone();
let override_name = OVERRIDE_NAME.lock();
// 判断是否有用户空间指定的时间源
for ele in list_guard.iter() {
if ele.clocksource_data().name.eq(override_name.deref()) {
// TODO 判断是否是高精度模式
// 暂时不支持高精度模式
// 如果是高精度模式,但是时钟源不支持高精度模式的话,就要退出循环
best = ele.clone();
break;
}
}
// 对比当前的时钟源和记录到最好的时钟源的精度
if CUR_CLOCKSOURCE.lock().as_ref().is_some() {
// 当前时钟源不为空
let cur_clocksource = CUR_CLOCKSOURCE.lock().as_ref().unwrap().clone();
let best_name = &best.clocksource_data().name;
if cur_clocksource.clocksource_data().name.ne(best_name) {
kinfo!("Switching to the clocksource {:?}\n", best_name);
drop(cur_clocksource);
CUR_CLOCKSOURCE.lock().replace(best);
// TODO 通知timerkeeping 切换了时间源
}
} else {
// 当前时钟源为空
CUR_CLOCKSOURCE.lock().replace(best);
}
kdebug!(" clocksource_select finish");
}
/// # clocksource模块加载完成
pub fn clocksource_boot_finish() {
let mut cur_clocksource = CUR_CLOCKSOURCE.lock();
cur_clocksource.replace(clocksource_default_clock());
unsafe { FINISHED_BOOTING.store(true, Ordering::Relaxed) };
// 清除不稳定的时钟源
clocksource_watchdog_kthread();
kdebug!("clocksource_boot_finish");
}
// ======== 以下为对C的接口 ========
/// # 完成对clocksource模块的加载
#[no_mangle]
pub extern "C" fn rs_clocksource_boot_finish() {
clocksource_boot_finish();
}
/// # 启动watchdog线程的辅助函数
#[no_mangle]
pub extern "C" fn rs_clocksource_watchdog_kthread(_data: c_void) -> i32 {
clocksource_watchdog_kthread();
return 0;
}

View File

@ -0,0 +1,3 @@
#pragma once
extern void rs_jiffies_init();

100
kernel/src/time/jiffies.rs Normal file
View File

@ -0,0 +1,100 @@
use alloc::{
string::ToString,
sync::{Arc, Weak},
};
use crate::{kdebug, libs::spinlock::SpinLock, syscall::SystemError};
use super::{
clocksource::{Clocksource, ClocksourceData, ClocksourceFlags, ClocksourceMask, CycleNum, HZ},
timer::clock,
NSEC_PER_SEC,
};
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) as u32;
pub const ACTHZ: u32 = sh_div(CLOCK_TICK_RATE, LATCH, 8);
pub const NSEC_PER_JIFFY: u32 = ((NSEC_PER_SEC << 8) / ACTHZ) as u32;
pub const fn sh_div(nom: u32, den: u32, lsh: u32) -> u32 {
(((nom) / (den)) << (lsh)) + ((((nom) % (den)) << (lsh)) + (den) / 2) / (den)
}
#[derive(Debug)]
pub struct ClocksourceJiffies(SpinLock<InnerJiffies>);
#[derive(Debug)]
pub struct InnerJiffies {
data: ClocksourceData,
self_ref: Weak<ClocksourceJiffies>,
}
impl Clocksource for ClocksourceJiffies {
fn read(&self) -> CycleNum {
CycleNum(clock())
}
fn clocksource_data(&self) -> ClocksourceData {
let inner = self.0.lock();
return inner.data.clone();
}
fn clocksource(&self) -> Arc<dyn Clocksource> {
self.0.lock().self_ref.upgrade().unwrap()
}
fn update_clocksource_data(&self, _data: ClocksourceData) -> Result<(), SystemError> {
let d = &mut self.0.lock().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_rating(_data.rating);
d.set_shift(_data.shift);
return Ok(());
}
fn enable(&self) -> Result<i32, SystemError> {
return Ok(0);
}
}
impl ClocksourceJiffies {
pub fn new() -> Arc<Self> {
let data = ClocksourceData {
name: "jiffies".to_string(),
rating: 1,
mask: ClocksourceMask::new(0xffffffff),
mult: NSEC_PER_JIFFY << JIFFIES_SHIFT,
shift: JIFFIES_SHIFT,
max_idle_ns: Default::default(),
flags: ClocksourceFlags::new(0),
watchdog_last: CycleNum(0),
};
let jieffies = Arc::new(ClocksourceJiffies(SpinLock::new(InnerJiffies {
data,
self_ref: Default::default(),
})));
jieffies.0.lock().self_ref = Arc::downgrade(&jieffies);
return jieffies;
}
}
pub fn clocksource_default_clock() -> Arc<ClocksourceJiffies> {
DEFAULT_CLOCK.clone()
}
pub fn jiffies_init() {
//注册jiffies
let jiffies = clocksource_default_clock() as Arc<dyn Clocksource>;
match jiffies.register() {
Ok(_) => kdebug!("jiffies_init sccessfully"),
Err(_) => kdebug!("jiffies_init failed, no default clock running"),
}
}
#[no_mangle]
pub extern "C" fn rs_jiffies_init() {
jiffies_init();
}

View File

@ -2,11 +2,14 @@ use core::{fmt, ops};
use self::timekeep::ktime_get_real_ns;
pub mod clocksource;
pub mod jiffies;
pub mod sleep;
pub mod syscall;
pub mod timeconv;
pub mod timekeep;
pub mod timekeeping;
pub mod timer;
/* Time structures. (Partitially taken from smoltcp)
The `time` module contains structures used to represent both
@ -18,6 +21,20 @@ absolute and relative time.
[Instant]: struct.Instant.html
[Duration]: struct.Duration.html
*/
#[allow(dead_code)]
pub const MSEC_PER_SEC: u32 = 1000;
#[allow(dead_code)]
pub const USEC_PER_MSEC: u32 = 1000;
#[allow(dead_code)]
pub const NSEC_PER_USEC: u32 = 1000;
#[allow(dead_code)]
pub const NSEC_PER_MSEC: u32 = 1000000;
#[allow(dead_code)]
pub const USEC_PER_SEC: u32 = 1000000;
#[allow(dead_code)]
pub const NSEC_PER_SEC: u32 = 1000000000;
#[allow(dead_code)]
pub const FSEC_PER_SEC: u64 = 1000000000000000;
/// 表示时间的结构体符合POSIX标准。
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]

View File

@ -1,10 +1,42 @@
use core::ptr::null_mut;
use core::{
ffi::{c_int, c_longlong},
ptr::null_mut,
};
use crate::{
kdebug,
syscall::{Syscall, SystemError},
time::{sleep::nanosleep, TimeSpec},
};
use super::timekeeping::do_gettimeofday;
pub type PosixTimeT = c_longlong;
pub type PosixSusecondsT = c_int;
#[repr(C)]
#[derive(Default, Debug)]
pub struct PosixTimeval {
pub tv_sec: PosixTimeT,
pub tv_usec: PosixSusecondsT,
}
#[repr(C)]
#[derive(Default, Debug)]
/// 当前时区信息
pub struct PosixTimeZone {
/// 格林尼治相对于当前时区相差的分钟数
pub tz_minuteswest: c_int,
/// DST矫正时差
pub tz_dsttime: c_int,
}
/// 系统时区 暂时写定为东八区
pub const SYS_TIMEZONE: PosixTimeZone = PosixTimeZone {
tz_minuteswest: -480,
tz_dsttime: 0,
};
impl Syscall {
/// @brief 休眠指定时间单位纳秒提供给C的接口
///
@ -44,4 +76,22 @@ impl Syscall {
pub fn clock() -> Result<usize, SystemError> {
return Ok(super::timer::clock() as usize);
}
pub fn gettimeofday(
tv: *mut PosixTimeval,
_timezone: &PosixTimeZone,
) -> Result<usize, SystemError> {
// TODO; 处理时区信息
kdebug!("enter sys_do_gettimeofday");
if tv == null_mut() {
return Err(SystemError::EFAULT);
}
let posix_time = do_gettimeofday();
unsafe {
(*tv).tv_sec = posix_time.tv_sec;
(*tv).tv_usec = posix_time.tv_usec;
}
kdebug!("exit sys_do_gettimeofday");
return Ok(0);
}
}

143
kernel/src/time/timeconv.rs Normal file
View File

@ -0,0 +1,143 @@
use super::syscall::PosixTimeT;
/// 一小时所包含的秒数
const SECS_PER_HOUR: i64 = 60 * 60;
/// 一天所包含的秒数
const SECS_PER_DAY: i64 = SECS_PER_HOUR * 24;
/// 每年中每个月最后一天所对应天数
const MON_OF_YDAY: [[i64; 13]; 2] = [
// 普通年
[0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365],
// 闰年
[0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366],
];
#[derive(Debug)]
#[allow(dead_code)]
pub struct CalendarTime {
tm_sec: i32,
tm_min: i32,
tm_hour: i32,
tm_mday: i32,
tm_mon: i32,
tm_wday: i32,
tm_yday: i32,
tm_year: i32,
}
impl CalendarTime {
pub fn new() -> Self {
CalendarTime {
tm_year: Default::default(),
tm_sec: Default::default(),
tm_min: Default::default(),
tm_hour: Default::default(),
tm_mday: Default::default(),
tm_mon: Default::default(),
tm_wday: Default::default(),
tm_yday: Default::default(),
}
}
}
/// # 判断是否是闰年
///
/// ## 参数
///
/// * 'year' - 年份
fn is_leap(year: u32) -> bool {
let mut flag = false;
if (year % 4 == 0 && year % 100 != 0) || year % 400 == 0 {
flag = true;
}
return flag;
}
/// # 计算除法
///
/// # 参数
///
/// * 'left' - 被除数
/// * 'right' - 除数
fn math_div(left: u32, right: u32) -> u32 {
return left / right;
}
/// # 计算两年之间的闰年数目
///
/// ## 参数
///
/// * 'y1' - 起始年份
/// * 'y2' - 结束年份
fn leaps_between(y1: u32, y2: u32) -> u32 {
// 算出y1之前的闰年数量
let y1_leaps = math_div(y1 - 1, 4) - math_div(y1 - 1, 100) + math_div(y1 - 1, 400);
// 算出y2之前的闰年数量
let y2_leaps = math_div(y2 - 1, 4) - math_div(y2 - 1, 100) + math_div(y2 - 1, 400);
y2_leaps - y1_leaps
}
/// # 将秒数转换成日期
///
/// ## 参数
///
/// * 'totalsecs' - 1970年1月1日 00:00:00 UTC到现在的秒数
/// * 'offset' - 指定的秒数对应的时间段(含)的偏移量(以秒为单位)
#[allow(dead_code)]
pub fn time_to_calendar(totalsecs: PosixTimeT, offset: i32) -> CalendarTime {
let mut result = CalendarTime::new();
// 计算对应的天数
let mut days = totalsecs / SECS_PER_DAY;
// 一天中剩余的秒数
let mut rem = totalsecs % SECS_PER_DAY;
// 加入偏移量
rem += offset as i64;
while rem < 0 {
rem += SECS_PER_DAY;
days -= 1;
}
while rem >= SECS_PER_DAY {
rem -= SECS_PER_DAY;
days += 1;
}
// 计算对应的小时数
result.tm_hour = (rem / SECS_PER_HOUR) as i32;
rem = rem % SECS_PER_HOUR;
// 计算对应的分钟数
result.tm_min = (rem / 60) as i32;
rem = rem % 60;
// 秒数
result.tm_sec = rem as i32;
// totalsec是从1970年1月1日 00:00:00 UTC到现在的秒数
// 当时是星期四
result.tm_wday = ((4 + days) % 7) as i32;
let mut year = 1970;
while days < 0 || (is_leap(year) && days >= 366) || (!is_leap(year) && days >= 365) {
// 假设每一年都是365天计算出大概的年份
let guess_year = year + math_div(days.try_into().unwrap(), 365);
// 将已经计算过的天数去掉
days -= ((guess_year - year) * 365 + leaps_between(year, guess_year)) as i64;
year = guess_year;
}
result.tm_year = (year - 1900) as i32;
result.tm_yday = days as i32;
let mut il = 0;
if is_leap(year) {
il = 1
};
let mut mon = 0;
for i in MON_OF_YDAY[il] {
if days < i {
break;
}
mon += 1;
}
days -= MON_OF_YDAY[il][mon - 1];
result.tm_mon = (mon - 1) as i32;
result.tm_mday = (days + 1) as i32;
result
}

View File

@ -0,0 +1,3 @@
#pragma once
extern void rs_timekeeping_init();

View File

@ -0,0 +1,312 @@
use alloc::sync::Arc;
use core::sync::atomic::{compiler_fence, AtomicBool, AtomicI64, Ordering};
use x86_64::align_up;
use crate::{
arch::CurrentIrqArch,
exception::InterruptArch,
kdebug,
libs::rwlock::RwLock,
time::{jiffies::clocksource_default_clock, timekeep::ktime_get_real_ns, TimeSpec},
};
use super::{
clocksource::{clocksource_cyc2ns, Clocksource, CycleNum, HZ},
syscall::PosixTimeval,
NSEC_PER_SEC, USEC_PER_SEC,
};
/// NTP周期频率
pub const NTP_INTERVAL_FREQ: u64 = HZ;
/// NTP周期长度
pub const NTP_INTERVAL_LENGTH: u64 = NSEC_PER_SEC as u64 / NTP_INTERVAL_FREQ;
/// NTP转换比例
pub const NTP_SCALE_SHIFT: u32 = 32;
/// timekeeping休眠标志false为未休眠
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>);
#[allow(dead_code)]
#[derive(Debug)]
pub struct TimekeeperData {
/// 用于计时的当前时钟源。
clock: Option<Arc<dyn Clocksource>>,
/// 当前时钟源的移位值。
shift: i32,
/// 一个NTP间隔中的时钟周期数。
cycle_interval: CycleNum,
/// 一个NTP间隔中时钟移位的纳秒数。
xtime_interval: u64,
///
xtime_remainder: i64,
/// 每个NTP间隔累积的原始纳米秒
raw_interval: i64,
/// 时钟移位纳米秒余数
xtime_nsec: u64,
/// 积累时间和ntp时间在ntp位移纳秒量上的差距
ntp_error: i64,
/// 用于转换时钟偏移纳秒和ntp偏移纳秒的偏移量
ntp_error_shift: i32,
/// NTP调整时钟乘法器
mult: u32,
raw_time: TimeSpec,
wall_to_monotonic: TimeSpec,
total_sleep_time: TimeSpec,
xtime: TimeSpec,
}
impl TimekeeperData {
pub fn new() -> Self {
Self {
clock: None,
shift: Default::default(),
cycle_interval: CycleNum(0),
xtime_interval: Default::default(),
xtime_remainder: Default::default(),
raw_interval: Default::default(),
xtime_nsec: Default::default(),
ntp_error: Default::default(),
ntp_error_shift: Default::default(),
mult: Default::default(),
xtime: TimeSpec {
tv_nsec: 0,
tv_sec: 0,
},
wall_to_monotonic: TimeSpec {
tv_nsec: 0,
tv_sec: 0,
},
total_sleep_time: TimeSpec {
tv_nsec: 0,
tv_sec: 0,
},
raw_time: TimeSpec {
tv_nsec: 0,
tv_sec: 0,
},
}
}
}
impl Timekeeper {
/// # 设置timekeeper的参数
///
/// ## 参数
///
/// * 'clock' - 指定的时钟实际类型。初始为ClocksourceJiffies
pub fn timekeeper_setup_internals(&self, clock: Arc<dyn Clocksource>) {
let mut timekeeper = self.0.write();
// 更新clock
let mut clock_data = clock.clocksource_data();
clock_data.watchdog_last = clock.read();
if clock.update_clocksource_data(clock_data).is_err() {
kdebug!("timekeeper_setup_internals:update_clocksource_data run failed");
}
timekeeper.clock.replace(clock.clone());
let clock_data = clock.clocksource_data();
let mut temp = NTP_INTERVAL_LENGTH << clock_data.shift;
let ntpinterval = temp;
temp += (clock_data.mult / 2) as u64;
// do div
timekeeper.cycle_interval = CycleNum(temp);
timekeeper.xtime_interval = temp * clock_data.mult as u64;
timekeeper.xtime_remainder = (ntpinterval - timekeeper.xtime_interval) as i64;
timekeeper.raw_interval = (timekeeper.xtime_interval >> clock_data.shift) as i64;
timekeeper.xtime_nsec = 0;
timekeeper.shift = clock_data.shift as i32;
timekeeper.ntp_error = 0;
timekeeper.ntp_error_shift = (NTP_SCALE_SHIFT - clock_data.shift) as i32;
timekeeper.mult = clock_data.mult;
}
/// # 获取当前时钟源距离上次检测走过的纳秒数
#[allow(dead_code)]
pub fn tk_get_ns(&self) -> u64 {
let timekeeper = self.0.read();
let clock = timekeeper.clock.clone().unwrap();
let clock_now = clock.read();
let clcok_data = clock.clocksource_data();
let clock_delta = clock_now.div(clcok_data.watchdog_last).data() & clcok_data.mask.bits();
return clocksource_cyc2ns(CycleNum(clock_delta), clcok_data.mult, clcok_data.shift);
}
}
pub fn timekeeper() -> &'static Timekeeper {
return unsafe { __TIMEKEEPER.as_ref().unwrap() };
}
pub fn timekeeper_init() {
unsafe { __TIMEKEEPER = Some(Timekeeper(RwLock::new(TimekeeperData::new()))) };
}
/// # 获取1970.1.1至今的UTC时间戳(最小单位:nsec)
///
/// ## 返回值
///
/// * 'TimeSpec' - 时间戳
pub fn getnstimeofday() -> TimeSpec {
kdebug!("enter getnstimeofday");
// let mut nsecs: u64 = 0;0
let mut _xtime = TimeSpec {
tv_nsec: 0,
tv_sec: 0,
};
loop {
match timekeeper().0.try_read() {
None => continue,
Some(tk) => {
_xtime = tk.xtime;
drop(tk);
// nsecs = timekeeper().tk_get_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;
}
// TODO 将xtime和当前时间源的时间相加
return _xtime;
}
/// # 获取1970.1.1至今的UTC时间戳(最小单位:usec)
///
/// ## 返回值
///
/// * 'PosixTimeval' - 时间戳
pub fn do_gettimeofday() -> PosixTimeval {
let tp = getnstimeofday();
return PosixTimeval {
tv_sec: tp.tv_sec,
tv_usec: (tp.tv_nsec / 1000) as i32,
};
}
/// # 初始化timekeeping模块
pub fn timekeeping_init() {
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
timekeeper_init();
// TODO 有ntp模块后 在此初始化ntp模块
let clock = clocksource_default_clock();
clock
.enable()
.expect("clocksource_default_clock enable failed");
timekeeper().timekeeper_setup_internals(clock);
// 暂时不支持其他架构平台对时间的设置 所以使用x86平台对应值初始化
let mut timekeeper = timekeeper().0.write();
timekeeper.xtime.tv_nsec = ktime_get_real_ns();
// 初始化wall time到monotonic的时间
let mut nsec = -timekeeper.xtime.tv_nsec;
let mut sec = -timekeeper.xtime.tv_sec;
// FIXME: 这里有个奇怪的奇怪的bug
let num = nsec % NSEC_PER_SEC as i64;
nsec += num * NSEC_PER_SEC as i64;
sec -= num;
timekeeper.wall_to_monotonic.tv_nsec = nsec;
timekeeper.wall_to_monotonic.tv_sec = sec;
__ADDED_USEC.store(0, Ordering::SeqCst);
__ADDED_SEC.store(0, Ordering::SeqCst);
drop(irq_guard);
kdebug!("timekeeping_init successfully");
}
/// # 使用当前时钟源增加wall time
pub fn update_wall_time() {
let rsp = unsafe { crate::include::bindings::bindings::get_rsp() } as usize;
let _stack_use = align_up(rsp as u64, 32768) - rsp as u64;
// kdebug!("enter update_wall_time, stack_use = {:}",stack_use);
compiler_fence(Ordering::SeqCst);
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
// 如果在休眠那就不更新
if TIMEKEEPING_SUSPENDED.load(Ordering::SeqCst) {
return;
}
// ===== 请不要删除这些注释 =====
// let clock = timekeeper.clock.clone().unwrap();
// let clock_data = clock.clocksource_data();
// let offset = (clock.read().div(clock_data.watchdog_last).data()) & clock_data.mask.bits();
// timekeeper.xtime_nsec = (timekeeper.xtime.tv_nsec as u64) << timekeeper.shift;
// // TODO 当有ntp模块之后 需要将timekeep与ntp进行同步并检查
// 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;
// while unlikely(timekeeper.xtime.tv_nsec >= NSEC_PER_SEC.into()) {
// timekeeper.xtime.tv_nsec -= NSEC_PER_SEC as i64;
// timekeeper.xtime.tv_sec += 1;
// // TODO 需要处理闰秒
// }
// ================
compiler_fence(Ordering::SeqCst);
// 一分钟同步一次
__ADDED_USEC.fetch_add(500, Ordering::SeqCst);
compiler_fence(Ordering::SeqCst);
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 {
if __ADDED_USEC
.compare_exchange(usec, 0, Ordering::SeqCst, Ordering::SeqCst)
.is_ok()
|| retry == 0
{
// 同步时间
// 我感觉这里会出问题:多个读者不退出的话,写者就无法写入
// 然后这里会超时,导致在中断返回之后,会不断的进入这个中断,最终爆栈。
let mut timekeeper = timekeeper().0.write();
timekeeper.xtime.tv_nsec = ktime_get_real_ns();
timekeeper.xtime.tv_sec = 0;
__ADDED_SEC.store(0, Ordering::SeqCst);
drop(timekeeper);
break;
}
retry -= 1;
} else {
break;
}
}
// TODO 需要检查是否更新时间源
compiler_fence(Ordering::SeqCst);
drop(irq_guard);
compiler_fence(Ordering::SeqCst);
}
// TODO timekeeping_adjust
// TODO wall_to_monotic
// ========= 以下为对C的接口 =========
#[no_mangle]
pub extern "C" fn rs_timekeeping_init() {
timekeeping_init();
}

View File

@ -2,6 +2,7 @@
#include <common/glib.h>
#include <driver/timers/HPET/HPET.h>
#include <common/kthread.h>
// 定义LONG_MAX为最大超时时间 - 允许负数
#define MAX_TIMEOUT (int64_t)((1ul << 63) - 1)

View File

@ -1,4 +1,8 @@
use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
use core::{
fmt::Debug,
intrinsics::unlikely,
sync::atomic::{compiler_fence, AtomicBool, AtomicU64, Ordering},
};
use alloc::{
boxed::Box,
@ -7,31 +11,33 @@ use alloc::{
};
use crate::{
arch::{
asm::current::current_pcb,
interrupt::{cli, sti},
sched::sched,
arch::{asm::current::current_pcb, sched::sched, CurrentIrqArch},
exception::{
softirq::{softirq_vectors, SoftirqNumber, SoftirqVec},
InterruptArch,
},
exception::softirq::{softirq_vectors, SoftirqNumber, SoftirqVec},
include::bindings::bindings::{process_control_block, process_wakeup, pt_regs, PROC_RUNNING},
include::bindings::bindings::{process_control_block, process_wakeup, PROC_RUNNING},
kdebug, kerror,
libs::spinlock::SpinLock,
syscall::SystemError,
};
use super::timekeeping::update_wall_time;
const MAX_TIMEOUT: i64 = i64::MAX;
const TIMER_RUN_CYCLE_THRESHOLD: usize = 20;
static mut TIMER_JIFFIES: u64 = 0;
static TIMER_JIFFIES: AtomicU64 = AtomicU64::new(0);
lazy_static! {
pub static ref TIMER_LIST: SpinLock<LinkedList<Arc<Timer>>> = SpinLock::new(LinkedList::new());
}
/// 定时器要执行的函数的特征
pub trait TimerFunction: Send + Sync {
fn run(&mut self);
pub trait TimerFunction: Send + Sync + Debug {
fn run(&mut self) -> Result<(), SystemError>;
}
#[derive(Debug)]
/// WakeUpHelper函数对应的结构体
pub struct WakeUpHelper {
pcb: &'static mut process_control_block,
@ -44,13 +50,15 @@ impl WakeUpHelper {
}
impl TimerFunction for WakeUpHelper {
fn run(&mut self) {
fn run(&mut self) -> Result<(), SystemError> {
unsafe {
process_wakeup(self.pcb);
}
return Ok(());
}
}
#[derive(Debug)]
pub struct Timer(SpinLock<InnerTimer>);
impl Timer {
@ -97,6 +105,7 @@ impl Timer {
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);
@ -106,11 +115,18 @@ impl Timer {
#[inline]
fn run(&self) {
self.0.lock().timer_func.run();
let r = self.0.lock().timer_func.run();
if unlikely(r.is_err()) {
kerror!(
"Failed to run timer function: {self:?} {:?}",
r.err().unwrap()
);
}
}
}
/// 定时器类型
#[derive(Debug)]
pub struct InnerTimer {
/// 定时器结束时刻
pub expire_jiffies: u64,
@ -179,7 +195,7 @@ impl SoftirqVec for DoTimerSoftirq {
continue;
}
let timer_list_front_guard = timer_list_front_guard.unwrap();
if timer_list_front_guard.expire_jiffies > unsafe { TIMER_JIFFIES as u64 } {
if timer_list_front_guard.expire_jiffies > TIMER_JIFFIES.load(Ordering::SeqCst) {
drop(timer_list_front_guard);
timer_list.push_front(timer_list_front);
break;
@ -205,11 +221,11 @@ pub fn timer_init() {
/// 计算接下来n毫秒对应的定时器时间片
pub fn next_n_ms_timer_jiffies(expire_ms: u64) -> u64 {
return unsafe { TIMER_JIFFIES as u64 } + 1000 * (expire_ms);
return TIMER_JIFFIES.load(Ordering::SeqCst) + 1000 * (expire_ms);
}
/// 计算接下来n微秒对应的定时器时间片
pub fn next_n_us_timer_jiffies(expire_us: u64) -> u64 {
return unsafe { TIMER_JIFFIES as u64 } + (expire_us);
return TIMER_JIFFIES.load(Ordering::SeqCst) + (expire_us);
}
/// @brief 让pcb休眠timeout个jiffies
@ -229,15 +245,17 @@ pub fn schedule_timeout(mut timeout: i64) -> Result<i64, SystemError> {
return Err(SystemError::EINVAL);
} else {
// 禁用中断,防止在这段期间发生调度,造成死锁
cli();
timeout += unsafe { TIMER_JIFFIES } as i64;
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
timeout += TIMER_JIFFIES.load(Ordering::SeqCst) as i64;
let timer = Timer::new(WakeUpHelper::new(current_pcb()), timeout as u64);
timer.activate();
current_pcb().state &= (!PROC_RUNNING) as u64;
sti();
drop(irq_guard);
sched();
let time_remaining: i64 = timeout - unsafe { TIMER_JIFFIES } as i64;
let time_remaining: i64 = timeout - TIMER_JIFFIES.load(Ordering::SeqCst) as i64;
if time_remaining >= 0 {
// 被提前唤醒,返回剩余时间
return Ok(time_remaining);
@ -270,21 +288,22 @@ pub fn timer_get_first_expire() -> Result<u64, SystemError> {
}
pub fn update_timer_jiffies(add_jiffies: u64) -> u64 {
unsafe { TIMER_JIFFIES += add_jiffies };
return unsafe { TIMER_JIFFIES };
let prev = TIMER_JIFFIES.fetch_add(add_jiffies, Ordering::SeqCst);
compiler_fence(Ordering::SeqCst);
update_wall_time();
compiler_fence(Ordering::SeqCst);
return prev + add_jiffies;
}
pub fn clock() -> u64 {
return unsafe { TIMER_JIFFIES };
return TIMER_JIFFIES.load(Ordering::SeqCst);
}
// ====== 重构完成后请删掉extern C ======
#[no_mangle]
pub extern "C" fn rs_clock() -> u64 {
clock()
}
#[no_mangle]
pub extern "C" fn sys_clock(_regs: *const pt_regs) -> u64 {
clock()
}
// ====== 以下为给C提供的接口 ======
#[no_mangle]