diff --git a/framework/aster-frame/src/arch/x86/kernel/tsc.rs b/framework/aster-frame/src/arch/x86/kernel/tsc.rs index 41acea582..cb139b354 100644 --- a/framework/aster-frame/src/arch/x86/kernel/tsc.rs +++ b/framework/aster-frame/src/arch/x86/kernel/tsc.rs @@ -1,17 +1,28 @@ // SPDX-License-Identifier: MPL-2.0 -use core::sync::atomic::AtomicU64; +use core::{ + arch::x86_64::_rdtsc, + sync::atomic::{AtomicBool, AtomicU64, Ordering}, +}; +use log::info; +use trapframe::TrapFrame; use x86::cpuid::cpuid; -/// The frequency of tsc. The unit is Hz. +use crate::{ + arch::timer::{ + pit::{self, OperatingMode}, + TIMER_FREQ, TIMER_IRQ_NUM, + }, + trap::IrqLine, +}; + +/// The frequency of TSC(Hz) pub(crate) static TSC_FREQ: AtomicU64 = AtomicU64::new(0); -const TSC_DEADLINE_MODE_SUPPORT: u32 = 1 << 24; - -/// Determine if the current system supports tsc_deadline mode. -pub fn is_tsc_deadline_mode_supported() -> bool { - let cpuid = cpuid!(1); - (cpuid.ecx & TSC_DEADLINE_MODE_SUPPORT) > 0 +pub fn init_tsc_freq() { + let tsc_freq = determine_tsc_freq_via_cpuid().map_or(determine_tsc_freq_via_pit(), |freq| freq); + TSC_FREQ.store(tsc_freq, Ordering::Relaxed); + info!("TSC frequency:{:?} Hz", tsc_freq); } /// Determine TSC frequency via CPUID. If the CPU does not support calculating TSC frequency by @@ -19,7 +30,7 @@ pub fn is_tsc_deadline_mode_supported() -> bool { /// /// Ref: function `native_calibrate_tsc` in linux `arch/x86/kernel/tsc.c` /// -pub fn determine_tsc_freq_via_cpuid() -> Option { +pub fn determine_tsc_freq_via_cpuid() -> Option { // Check the max cpuid supported let cpuid = cpuid!(0); let max_cpuid = cpuid.eax; @@ -49,6 +60,53 @@ pub fn determine_tsc_freq_via_cpuid() -> Option { if crystal_khz == 0 { None } else { - Some(crystal_khz * ebx_numerator / eax_denominator) + let crystal_hz = crystal_khz as u64 * 1000; + Some(crystal_hz * ebx_numerator as u64 / eax_denominator as u64) + } +} + +/// When kernel cannot get the TSC frequency from CPUID, it can leverage +/// the PIT to calculate this frequency. +pub fn determine_tsc_freq_via_pit() -> u64 { + // Allocate IRQ + let mut irq = IrqLine::alloc_specific(TIMER_IRQ_NUM.load(Ordering::Relaxed)).unwrap(); + irq.on_active(pit_callback); + + // Enable PIT + pit::init(OperatingMode::RateGenerator); + pit::enable_ioapic_line(irq.clone()); + + static IS_FINISH: AtomicBool = AtomicBool::new(false); + static FREQUENCY: AtomicU64 = AtomicU64::new(0); + x86_64::instructions::interrupts::enable(); + while !IS_FINISH.load(Ordering::Acquire) { + x86_64::instructions::hlt(); + } + x86_64::instructions::interrupts::disable(); + drop(irq); + return FREQUENCY.load(Ordering::Acquire); + + fn pit_callback(trap_frame: &TrapFrame) { + static IN_TIME: AtomicU64 = AtomicU64::new(0); + static TSC_FIRST_COUNT: AtomicU64 = AtomicU64::new(0); + // Set a certain times of callbacks to calculate the frequency + const CALLBACK_TIMES: u64 = TIMER_FREQ / 10; + + if IN_TIME.load(Ordering::Relaxed) < CALLBACK_TIMES || IS_FINISH.load(Ordering::Acquire) { + if IN_TIME.load(Ordering::Relaxed) == 0 { + unsafe { + TSC_FIRST_COUNT.store(_rdtsc(), Ordering::Relaxed); + } + } + IN_TIME.fetch_add(1, Ordering::Relaxed); + return; + } + + pit::disable_ioapic_line(); + let tsc_count = unsafe { _rdtsc() }; + let freq = + (tsc_count - TSC_FIRST_COUNT.load(Ordering::Relaxed)) * (TIMER_FREQ / CALLBACK_TIMES); + FREQUENCY.store(freq, Ordering::Release); + IS_FINISH.store(true, Ordering::Release); } } diff --git a/framework/aster-frame/src/arch/x86/timer/apic.rs b/framework/aster-frame/src/arch/x86/timer/apic.rs index 437e21e89..ccb1f1e35 100644 --- a/framework/aster-frame/src/arch/x86/timer/apic.rs +++ b/framework/aster-frame/src/arch/x86/timer/apic.rs @@ -3,19 +3,21 @@ use alloc::sync::Arc; use core::arch::x86_64::_rdtsc; use core::sync::atomic::{AtomicBool, AtomicU64, Ordering}; +use x86::cpuid::cpuid; use log::info; use spin::Once; use trapframe::TrapFrame; use x86::msr::{wrmsr, IA32_TSC_DEADLINE}; -use crate::arch::kernel::apic::ioapic::IO_APIC; -use crate::arch::kernel::tsc::is_tsc_deadline_mode_supported; +use crate::arch::kernel::tsc::init_tsc_freq; +use crate::arch::timer::pit::OperatingMode; use crate::arch::x86::kernel::apic::{DivideConfig, APIC_INSTANCE}; -use crate::arch::x86::kernel::tsc::{determine_tsc_freq_via_cpuid, TSC_FREQ}; -use crate::config::TIMER_FREQ; +use crate::arch::x86::kernel::tsc::TSC_FREQ; use crate::trap::IrqLine; +use super::TIMER_FREQ; + pub fn init() { init_tsc_freq(); if is_tsc_deadline_mode_supported() { @@ -29,16 +31,16 @@ pub fn init() { pub(super) static APIC_TIMER_CALLBACK: Once> = Once::new(); -fn init_tsc_freq() { - let tsc_freq = determine_tsc_freq_via_cpuid() - .map_or(determine_tsc_freq_via_pit(), |freq| freq as u64 * 1000); - TSC_FREQ.store(tsc_freq, Ordering::Relaxed); - info!("TSC frequency:{:?} Hz", tsc_freq); +/// Determine if the current system supports tsc_deadline mode APIC timer +fn is_tsc_deadline_mode_supported() -> bool { + const TSC_DEADLINE_MODE_SUPPORT: u32 = 1 << 24; + let cpuid = cpuid!(1); + (cpuid.ecx & TSC_DEADLINE_MODE_SUPPORT) > 0 } fn init_tsc_mode() { let mut apic_lock = APIC_INSTANCE.get().unwrap().lock(); - // Enable tsc deadline mode. + // Enable tsc deadline mode apic_lock.set_lvt_timer(super::TIMER_IRQ_NUM.load(Ordering::Relaxed) as u64 | (1 << 18)); drop(apic_lock); let tsc_step = TSC_FREQ.load(Ordering::Relaxed) / TIMER_FREQ; @@ -53,97 +55,54 @@ fn init_tsc_mode() { APIC_TIMER_CALLBACK.call_once(|| Arc::new(callback)); } -/// When kernel cannot get the TSC frequency from CPUID, it can leverage -/// the PIT to calculate this frequency. -fn determine_tsc_freq_via_pit() -> u64 { +fn init_periodic_mode() { + // Allocate IRQ let mut irq = IrqLine::alloc_specific(super::TIMER_IRQ_NUM.load(Ordering::Relaxed)).unwrap(); irq.on_active(pit_callback); - let mut io_apic = IO_APIC.get().unwrap().first().unwrap().lock(); - debug_assert_eq!(io_apic.interrupt_base(), 0); - io_apic.enable(2, irq.clone()).unwrap(); - drop(io_apic); - super::pit::init(); + // Enable PIT + super::pit::init(OperatingMode::RateGenerator); + super::pit::enable_ioapic_line(irq.clone()); - x86_64::instructions::interrupts::enable(); - static IS_FINISH: AtomicBool = AtomicBool::new(false); - static FREQUENCY: AtomicU64 = AtomicU64::new(0); - while !IS_FINISH.load(Ordering::Acquire) { - x86_64::instructions::hlt(); - } - x86_64::instructions::interrupts::disable(); - drop(irq); - return FREQUENCY.load(Ordering::Acquire); - - fn pit_callback(trap_frame: &TrapFrame) { - static mut IN_TIME: u64 = 0; - static mut TSC_FIRST_COUNT: u64 = 0; - // Set a certain times of callbacks to calculate the frequency. - const CALLBACK_TIMES: u64 = TIMER_FREQ / 10; - unsafe { - if IN_TIME < CALLBACK_TIMES || IS_FINISH.load(Ordering::Acquire) { - // drop the first entry, since it may not be the time we want - if IN_TIME == 0 { - TSC_FIRST_COUNT = _rdtsc(); - } - IN_TIME += 1; - return; - } - let mut io_apic = IO_APIC.get().unwrap().first().unwrap().lock(); - io_apic.disable(2).unwrap(); - drop(io_apic); - let tsc_count = _rdtsc(); - let freq = (tsc_count - TSC_FIRST_COUNT) * (TIMER_FREQ / CALLBACK_TIMES); - FREQUENCY.store(freq, Ordering::Release); - } - IS_FINISH.store(true, Ordering::Release); - } -} - -fn init_periodic_mode() { + // Set APIC timer count let mut apic_lock = APIC_INSTANCE.get().unwrap().lock(); - let mut irq = IrqLine::alloc_specific(super::TIMER_IRQ_NUM.load(Ordering::Relaxed)).unwrap(); - irq.on_active(init_function); - let mut io_apic = IO_APIC.get().unwrap().first().unwrap().lock(); - debug_assert_eq!(io_apic.interrupt_base(), 0); - io_apic.enable(2, irq.clone()).unwrap(); - drop(io_apic); - // divide by 64 apic_lock.set_timer_div_config(DivideConfig::Divide64); apic_lock.set_timer_init_count(0xFFFF_FFFF); drop(apic_lock); - super::pit::init(); - // wait until it is finish - x86_64::instructions::interrupts::enable(); + static IS_FINISH: AtomicBool = AtomicBool::new(false); + x86_64::instructions::interrupts::enable(); while !IS_FINISH.load(Ordering::Acquire) { x86_64::instructions::hlt(); } x86_64::instructions::interrupts::disable(); drop(irq); - fn init_function(trap_frame: &TrapFrame) { - static mut IN_TIME: u8 = 0; - static mut FIRST_TIME_COUNT: u64 = 0; - unsafe { - if IS_FINISH.load(Ordering::Acquire) || IN_TIME == 0 { - // drop the first entry, since it may not be the time we want - IN_TIME += 1; + fn pit_callback(trap_frame: &TrapFrame) { + static IN_TIME: AtomicU64 = AtomicU64::new(0); + static APIC_FIRST_COUNT: AtomicU64 = AtomicU64::new(0); + // Set a certain times of callbacks to calculate the frequency + const CALLBACK_TIMES: u64 = TIMER_FREQ / 10; + + if IN_TIME.load(Ordering::Relaxed) < CALLBACK_TIMES || IS_FINISH.load(Ordering::Acquire) { + if IN_TIME.load(Ordering::Relaxed) == 0 { let apic_lock = APIC_INSTANCE.get().unwrap().lock(); let remain_ticks = apic_lock.timer_current_count(); - FIRST_TIME_COUNT = 0xFFFF_FFFF - remain_ticks; - return; + APIC_FIRST_COUNT.store(0xFFFF_FFFF - remain_ticks, Ordering::Relaxed); } + IN_TIME.fetch_add(1, Ordering::Relaxed); + return; } - let mut io_apic = IO_APIC.get().unwrap().first().unwrap().lock(); - io_apic.disable(2).unwrap(); - drop(io_apic); - // stop APIC Timer, get the number of tick we need + + // Stop PIT and APIC Timer + super::pit::disable_ioapic_line(); let mut apic_lock = APIC_INSTANCE.get().unwrap().lock(); let remain_ticks = apic_lock.timer_current_count(); apic_lock.set_timer_init_count(0); - let ticks = unsafe { 0xFFFF_FFFF - remain_ticks - FIRST_TIME_COUNT }; - // periodic mode, divide 64, freq: TIMER_FREQ Hz + + // Init APIC Timer + let ticks = (0xFFFF_FFFF - remain_ticks - APIC_FIRST_COUNT.load(Ordering::Relaxed)) + / CALLBACK_TIMES; apic_lock.set_timer_init_count(ticks); apic_lock.set_lvt_timer(super::TIMER_IRQ_NUM.load(Ordering::Relaxed) as u64 | (1 << 17)); apic_lock.set_timer_div_config(DivideConfig::Divide64); diff --git a/framework/aster-frame/src/arch/x86/timer/mod.rs b/framework/aster-frame/src/arch/x86/timer/mod.rs index 4f3bccc9e..15a791081 100644 --- a/framework/aster-frame/src/arch/x86/timer/mod.rs +++ b/framework/aster-frame/src/arch/x86/timer/mod.rs @@ -12,19 +12,28 @@ use spin::Once; use trapframe::TrapFrame; use crate::arch::x86::kernel; -use crate::config::TIMER_FREQ; use crate::sync::SpinLock; use crate::trap::IrqLine; use self::apic::APIC_TIMER_CALLBACK; +/// The timer frequency (Hz). Here we choose 1000Hz since 1000Hz is easier for unit conversion and +/// convenient for timer. What's more, the frequency cannot be set too high or too low, 1000Hz is +/// a modest choice. +/// +/// For system performance reasons, this rate cannot be set too high, otherwise most of the time +/// is spent executing timer code. +/// +/// Due to hardware limitations, this value cannot be set too low; for example, PIT cannot accept +/// frequencies lower than 19Hz = 1193182 / 65536 (Timer rate / Divider) +pub const TIMER_FREQ: u64 = 1000; + pub static TIMER_IRQ_NUM: AtomicU8 = AtomicU8::new(32); pub static TICK: AtomicU64 = AtomicU64::new(0); static TIMER_IRQ: Once = Once::new(); pub fn init() { - TIMEOUT_LIST.call_once(|| SpinLock::new(BinaryHeap::new())); if kernel::apic::APIC_INSTANCE.is_completed() { // Get the free irq number first. Use `allocate_target_irq` to get the Irq handle after dropping it. // Because the function inside `apic::init` will allocate this irq. @@ -33,8 +42,9 @@ pub fn init() { drop(irq); apic::init(); } else { - pit::init(); + pit::init(pit::OperatingMode::SquareWaveGenerator); }; + TIMEOUT_LIST.call_once(|| SpinLock::new(BinaryHeap::new())); let mut timer_irq = IrqLine::alloc_specific(TIMER_IRQ_NUM.load(Ordering::Relaxed)).unwrap(); timer_irq.on_active(timer_callback); TIMER_IRQ.call_once(|| timer_irq); diff --git a/framework/aster-frame/src/arch/x86/timer/pit.rs b/framework/aster-frame/src/arch/x86/timer/pit.rs index 2f830ee54..c8151d5de 100644 --- a/framework/aster-frame/src/arch/x86/timer/pit.rs +++ b/framework/aster-frame/src/arch/x86/timer/pit.rs @@ -1,21 +1,191 @@ // SPDX-License-Identifier: MPL-2.0 -//! used for PIT Timer +//! The Programmable Interval Timer (PIT) chip (Intel 8253/8254) basically consists of an oscillator, +//! a prescaler and 3 independent frequency dividers. Each frequency divider has an output, which is +//! used to allow the timer to control external circuitry (for example, IRQ 0). +//! +//! Reference: https://wiki.osdev.org/Programmable_Interval_Timer +//! -use crate::config::TIMER_FREQ; +use crate::{ + arch::{ + kernel::IO_APIC, + timer::TIMER_FREQ, + x86::device::io_port::{IoPort, WriteOnlyAccess}, + }, + trap::IrqLine, +}; -use crate::arch::x86::device::io_port::{IoPort, WriteOnlyAccess}; +/// PIT Operating Mode. +/// +/// Usually, only the rate generator, which is used to determine the base frequency of other timers +/// (e.g. APIC Timer), and the Square wave generator, which is used to generate interrupts directly, are used. +/// +/// Note that if IOAPIC is used to manage interrupts and square wave mode is enabled, the frequency at which +/// clock interrupts are generated is `Frequency/2`. +#[repr(u8)] +pub enum OperatingMode { + /// Triggers an interrupt (only on channel 0) when the counter is terminated (1 -> 0). + /// The data port needs to be reset before the next interrupt. + /// ```text,ignore + /// software reload counter + /// ⬇ + /// +------+ +---- + /// | | | + /// --------------+ +-------------+ + /// ⬆ ⬆ ⬆ + /// init() counter 1 -> 0 counter 1 -> 0 + /// ``` + InterruptOnTerminalCount = 0b000, + /// This mode is similar to `InterruptOnTerminalCount` mode, however counting doesn't start until + /// a rising edge of the gate input is detected. For this reason it is not usable for PIT channels + /// 0 or 1(where the gate input can't be changed). + OneShotHardwareRetriggerable = 0b001, + /// Rate generator, which produces a pulse at a fixed frequency. + /// ```text,ignore + /// init() counter 2 -> 1 counter 2 -> 1 + /// ⬇ ⬇ ⬇ + /// --------------+ +-------------+ + /// | | | + /// +--+ +-- + /// ⬆ + /// counter 1 -> 0, auto reload counter + /// ``` + RateGenerator = 0b010, + /// In this mode, the current count is **decremented twice** on each falling edge of the input signal. + /// The output will change state and then set to reload value. + /// ```text,ignore + /// init() auto reload counter + /// ⬇ ⬇ + /// --------------+ +-------------- + /// | | + /// +--------------+ + /// ⬆ + /// auto reload counter + /// ``` + SquareWaveGenerator = 0b011, + /// Similar to a Rate generator, but requires a software reset to start counting. + /// ```text,ignore + /// init() counter: 1 software reload counter + /// ⬇ ⬇ ⬇ + /// --------------+ +---------------------------+ +-- + /// | | | | + /// +-+ +-+ + /// ⬆ + /// counter: 0 + /// ``` + SoftwareTriggeredStrobe = 0b100, + /// This mode is similar to `SoftwareTriggeredStrobe` mode, except that it waits for the rising + /// edge of the gate input to trigger (or re-trigger) the delay period (like `OneShotHardwareRetriggerable` + /// mode). + HardwareTriggeredStrobe = 0b101, + // 0b110 -> Rate Generator + // 0b111 -> Square Wave Generator +} +/// This bits tell the PIT what access mode is used for the selected channel. +#[repr(u8)] +enum AccessMode { + /// When this command is sent, the current count is copied into latch register which can be read + /// through the data port corresponding to the selected channel (I/O ports 0x40 to 0x42). + LatchCountValueCommand = 0b00, + /// Only the lowest 8 bits of the count value are used in this mode. + LowByteOnly = 0b01, + /// Only the highest 8 bits of the count value are used in this mode. + HighByteOnly = 0b10, + /// 16 bits are used in this mode. User should sent the lowest 8 bits followed by the highest 8 bits + /// to the same data port. + LowAndHighByte = 0b11, +} + +/// Used to select the configured channel in the `MODE_COMMAND_PORT` of the PIT. +#[repr(u8)] +enum Channel { + /// Channel 0. For more details, check `CHANNEL0_PORT` static variable + Channel0 = 0b00, + /// Channel 1. For more details, check `CHANNEL1_PORT` static variable + Channel1 = 0b01, + /// Channel 2. For more details, check `CHANNEL2_PORT` static variable + Channel2 = 0b10, + /// The read back command is a special command sent to the mode/command register. + /// The register uses the following format if set to read back command: + /// ```text + /// Bits Usage + /// 7 and 6 Must be set for the read back command + /// 5 Latch count flag (0 = latch count, 1 = don't latch count) + /// 4 Latch status flag (0 = latch status, 1 = don't latch status) + /// 3 Read back timer channel 2 (1 = yes, 0 = no) + /// 2 Read back timer channel 1 (1 = yes, 0 = no) + /// 1 Read back timer channel 0 (1 = yes, 0 = no) + /// 0 Reserved + /// ``` + /// Bits 1 to 3 of the read back command select which PIT channels are affected, + /// and allow multiple channels to be selected at the same time. + /// + /// If bit 5 is clear, then any/all PIT channels selected with bits 1 to 3 will + /// have their current count copied into their latch register. + /// + /// If bit 4 is clear, then for any/all PIT channels selected with bits 1 to 3, + /// the next read of the corresponding data port will return a status byte. + /// + /// Ref: https://wiki.osdev.org/Programmable_Interval_Timer#Read_Back_Command + ReadBackCommand = 0b11, +} + +/// The output from PIT channel 0 is connected to the PIC chip and generate "IRQ 0". +/// If connected to PIC, the IRQ0 will generate by the **rising edge** of the output voltage. +static CHANNEL0_PORT: IoPort = unsafe { IoPort::new(0x40) }; + +/// The output from PIT channel 1 was once used for refreshing the DRAM or RAM so that +/// the capacitors don't forget their state. +/// +/// On later machines, the DRAM refresh is done with dedicated hardware and this channel +/// is no longer used. +#[allow(unused)] +static CHANNEL1_PORT: IoPort = unsafe { IoPort::new(0x41) }; + +/// The output from PIT channel 2 is connected to the PC speaker, so the frequency of the +/// output determines the frequency of the sound produced by the speaker. For more information, +/// check https://wiki.osdev.org/PC_Speaker. +#[allow(unused)] +static CHANNEL2_PORT: IoPort = unsafe { IoPort::new(0x42) }; + +/// PIT command port. +/// ```text +/// Bits Usage +/// 6 and 7 channel +/// 4 and 5 Access mode +/// 1 to 3 Operating mode +/// 0 BCD/Binary mode: 0 = 16-bit binary, 1 = four-digit BCD +/// ``` +static MODE_COMMAND_PORT: IoPort = unsafe { IoPort::new(0x43) }; const TIMER_RATE: u32 = 1193182; -static TIMER_PERIOD: IoPort = unsafe { IoPort::new(0x40) }; -static TIMER_MOD: IoPort = unsafe { IoPort::new(0x43) }; -static TIMER_SQUARE_WAVE: u8 = 0x34; +pub(crate) fn init(operating_mode: OperatingMode) { + // Set PIT mode + // Bit 0 is BCD/binary mode, which is always set to binary mode(value: 0) + MODE_COMMAND_PORT.write( + ((operating_mode as u8) << 1) + | (AccessMode::LowAndHighByte as u8) << 4 + | (Channel::Channel0 as u8) << 6, + ); -pub(crate) fn init() { - // Initialize timer. - let cycle = TIMER_RATE / TIMER_FREQ as u32; - TIMER_MOD.write(TIMER_SQUARE_WAVE); - TIMER_PERIOD.write((cycle & 0xFF) as _); - TIMER_PERIOD.write((cycle >> 8) as _); + // Set timer frequency + const CYCLE: u32 = TIMER_RATE / TIMER_FREQ as u32; + CHANNEL0_PORT.write((CYCLE & 0xFF) as _); + CHANNEL0_PORT.write((CYCLE >> 8) as _); +} + +/// Enable the IOAPIC line that connected to PIC +pub(crate) fn enable_ioapic_line(irq: IrqLine) { + let mut io_apic = IO_APIC.get().unwrap().first().unwrap().lock(); + debug_assert_eq!(io_apic.interrupt_base(), 0); + io_apic.enable(2, irq.clone()).unwrap(); +} + +/// Disable the IOAPIC line that connected to PIC +pub(crate) fn disable_ioapic_line() { + let mut io_apic = IO_APIC.get().unwrap().first().unwrap().lock(); + debug_assert_eq!(io_apic.interrupt_base(), 0); + io_apic.disable(2).unwrap(); } diff --git a/framework/aster-frame/src/config.rs b/framework/aster-frame/src/config.rs index 145e2c156..f3abeb463 100644 --- a/framework/aster-frame/src/config.rs +++ b/framework/aster-frame/src/config.rs @@ -19,7 +19,5 @@ pub const PAGE_SIZE_BITS: usize = 0xc; pub const KVA_START: usize = (usize::MAX) << PAGE_SIZE_BITS; pub const DEFAULT_LOG_LEVEL: Level = Level::Error; -/// This value represent the base timer frequency in Hz -pub const TIMER_FREQ: u64 = 500; pub const REAL_TIME_TASK_PRI: u16 = 100; diff --git a/framework/aster-frame/src/sync/wait.rs b/framework/aster-frame/src/sync/wait.rs index 596f6c2d1..b099a566f 100644 --- a/framework/aster-frame/src/sync/wait.rs +++ b/framework/aster-frame/src/sync/wait.rs @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 use super::SpinLock; -use crate::arch::timer::add_timeout_list; -use crate::config::TIMER_FREQ; +use crate::arch::timer::{add_timeout_list, TIMER_FREQ}; use alloc::{collections::VecDeque, sync::Arc}; use bitflags::bitflags; use core::sync::atomic::{AtomicBool, Ordering}; diff --git a/framework/aster-frame/src/timer.rs b/framework/aster-frame/src/timer.rs index dcccd0a7d..bab9eef00 100644 --- a/framework/aster-frame/src/timer.rs +++ b/framework/aster-frame/src/timer.rs @@ -2,14 +2,12 @@ //! Timer. -#[cfg(target_arch = "x86_64")] -use crate::arch::x86::timer::{add_timeout_list, TimerCallback, TICK}; -use crate::sync::SpinLock; -use crate::{config::TIMER_FREQ, prelude::*}; +use crate::arch::timer::{add_timeout_list, TimerCallback, TICK}; +use crate::prelude::*; +use crate::{arch::timer::TIMER_FREQ, sync::SpinLock}; use core::{sync::atomic::Ordering, time::Duration}; -#[cfg(target_arch = "x86_64")] -pub use crate::arch::x86::timer::read_monotonic_milli_seconds; +pub use crate::arch::timer::read_monotonic_milli_seconds; /// A timer invokes a callback function after a specified span of time elapsed. ///