mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-25 18:33:24 +00:00
Enable Timer to set an absolute time
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
e952a16954
commit
13fd173b24
@ -3,13 +3,13 @@
|
|||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
|
|
||||||
use super::SyscallReturn;
|
use super::SyscallReturn;
|
||||||
use crate::prelude::*;
|
use crate::{prelude::*, time::timer::Timeout};
|
||||||
|
|
||||||
pub fn sys_alarm(seconds: u32) -> Result<SyscallReturn> {
|
pub fn sys_alarm(seconds: u32) -> Result<SyscallReturn> {
|
||||||
debug!("seconds = {}", seconds);
|
debug!("seconds = {}", seconds);
|
||||||
|
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let alarm_timer = current.alarm_timer();
|
let alarm_timer = current.timer_manager().alarm_timer();
|
||||||
|
|
||||||
let remaining = alarm_timer.remain();
|
let remaining = alarm_timer.remain();
|
||||||
let mut remaining_secs = remaining.as_secs();
|
let mut remaining_secs = remaining.as_secs();
|
||||||
@ -23,7 +23,7 @@ pub fn sys_alarm(seconds: u32) -> Result<SyscallReturn> {
|
|||||||
return Ok(SyscallReturn::Return(remaining_secs as _));
|
return Ok(SyscallReturn::Return(remaining_secs as _));
|
||||||
}
|
}
|
||||||
|
|
||||||
alarm_timer.set_timeout(Duration::from_secs(seconds as u64));
|
alarm_timer.set_timeout(Timeout::After(Duration::from_secs(seconds as u64)));
|
||||||
|
|
||||||
Ok(SyscallReturn::Return(remaining_secs as _))
|
Ok(SyscallReturn::Return(remaining_secs as _))
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,14 @@ use aster_frame::sync::SpinLock;
|
|||||||
|
|
||||||
use super::Clock;
|
use super::Clock;
|
||||||
|
|
||||||
|
/// A timeout, represented in one of the two ways.
|
||||||
|
pub enum Timeout {
|
||||||
|
/// The timeout is reached _after_ the `Duration` time is elapsed.
|
||||||
|
After(Duration),
|
||||||
|
/// The timeout is reached _when_ the clock's time is equal to `Duration`.
|
||||||
|
When(Duration),
|
||||||
|
}
|
||||||
|
|
||||||
/// A timer with periodic functionality.
|
/// A timer with periodic functionality.
|
||||||
///
|
///
|
||||||
/// Setting the timer will trigger a callback function upon expiration of
|
/// Setting the timer will trigger a callback function upon expiration of
|
||||||
@ -65,9 +73,15 @@ impl Timer {
|
|||||||
/// The registered callback function of this timer will be invoked
|
/// The registered callback function of this timer will be invoked
|
||||||
/// when reaching timeout. If the timer has a valid interval, this timer
|
/// when reaching timeout. If the timer has a valid interval, this timer
|
||||||
/// will be set again with the interval when reaching timeout.
|
/// will be set again with the interval when reaching timeout.
|
||||||
pub fn set_timeout(self: &Arc<Self>, timeout: Duration) {
|
pub fn set_timeout(self: &Arc<Self>, timeout: Timeout) {
|
||||||
|
let expired_time = match timeout {
|
||||||
|
Timeout::After(timeout) => {
|
||||||
let now = self.timer_manager.clock.read_time();
|
let now = self.timer_manager.clock.read_time();
|
||||||
let expired_time = now + timeout;
|
now + timeout
|
||||||
|
}
|
||||||
|
Timeout::When(timeout) => timeout,
|
||||||
|
};
|
||||||
|
|
||||||
let timer_weak = Arc::downgrade(self);
|
let timer_weak = Arc::downgrade(self);
|
||||||
let new_timer_callback = Arc::new(TimerCallback::new(
|
let new_timer_callback = Arc::new(TimerCallback::new(
|
||||||
expired_time,
|
expired_time,
|
||||||
@ -107,6 +121,11 @@ impl Timer {
|
|||||||
pub fn timer_manager(&self) -> &Arc<TimerManager> {
|
pub fn timer_manager(&self) -> &Arc<TimerManager> {
|
||||||
&self.timer_manager
|
&self.timer_manager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the interval time of the current timer.
|
||||||
|
pub fn interval(&self) -> Duration {
|
||||||
|
*self.interval.lock_irq_disabled()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn interval_timer_callback(timer: &Weak<Timer>) {
|
fn interval_timer_callback(timer: &Weak<Timer>) {
|
||||||
@ -117,7 +136,7 @@ fn interval_timer_callback(timer: &Weak<Timer>) {
|
|||||||
(timer.registered_callback)();
|
(timer.registered_callback)();
|
||||||
let interval = timer.interval.lock_irq_disabled();
|
let interval = timer.interval.lock_irq_disabled();
|
||||||
if *interval != Duration::ZERO {
|
if *interval != Duration::ZERO {
|
||||||
timer.set_timeout(*interval);
|
timer.set_timeout(Timeout::After(*interval));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ use core::time::Duration;
|
|||||||
|
|
||||||
use aster_frame::sync::{WaitQueue, Waiter};
|
use aster_frame::sync::{WaitQueue, Waiter};
|
||||||
|
|
||||||
use super::clocks::JIFFIES_TIMER_MANAGER;
|
use super::{clocks::JIFFIES_TIMER_MANAGER, timer::Timeout};
|
||||||
|
|
||||||
/// A trait that provide the timeout related function for [`WaitQueue`]`.
|
/// A trait that provide the timeout related function for [`WaitQueue`]`.
|
||||||
pub trait WaitTimeout {
|
pub trait WaitTimeout {
|
||||||
@ -34,7 +34,7 @@ impl WaitTimeout for WaitQueue {
|
|||||||
let jiffies_timer = JIFFIES_TIMER_MANAGER.get().unwrap().create_timer(move || {
|
let jiffies_timer = JIFFIES_TIMER_MANAGER.get().unwrap().create_timer(move || {
|
||||||
waker.wake_up();
|
waker.wake_up();
|
||||||
});
|
});
|
||||||
jiffies_timer.set_timeout(*timeout);
|
jiffies_timer.set_timeout(Timeout::After(*timeout));
|
||||||
|
|
||||||
let cancel_cond = {
|
let cancel_cond = {
|
||||||
let jiffies_timer = jiffies_timer.clone();
|
let jiffies_timer = jiffies_timer.clone();
|
||||||
|
@ -26,8 +26,8 @@ use spin::Once;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
fs::fs_resolver::{FsPath, FsResolver, AT_FDCWD},
|
fs::fs_resolver::{FsPath, FsResolver, AT_FDCWD},
|
||||||
syscall::ClockID,
|
syscall::ClockId,
|
||||||
time::{clocks::MonotonicClock, SystemTime, START_TIME},
|
time::{clocks::MonotonicClock, timer::Timeout, SystemTime, START_TIME},
|
||||||
vm::vmo::{Vmo, VmoOptions},
|
vm::vmo::{Vmo, VmoOptions},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -49,12 +49,12 @@ enum VdsoClockMode {
|
|||||||
|
|
||||||
/// Instant used in `VdsoData`.
|
/// Instant used in `VdsoData`.
|
||||||
///
|
///
|
||||||
/// Each `VdsoInstant` will store a instant information for a specified `ClockID`.
|
/// Each `VdsoInstant` will store a instant information for a specified `ClockId`.
|
||||||
/// The `secs` field will record the seconds of the instant,
|
/// The `secs` field will record the seconds of the instant,
|
||||||
/// and the `nanos_info` will store the nanoseconds of the instant
|
/// and the `nanos_info` will store the nanoseconds of the instant
|
||||||
/// (for `CLOCK_REALTIME_COARSE` and `CLOCK_MONOTONIC_COARSE`) or
|
/// (for `CLOCK_REALTIME_COARSE` and `CLOCK_MONOTONIC_COARSE`) or
|
||||||
/// the calculation results of left-shift `nanos` with `lshift`
|
/// the calculation results of left-shift `nanos` with `lshift`
|
||||||
/// (for other high-resolution `ClockID`s).
|
/// (for other high-resolution `ClockId`s).
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy, Clone, Pod)]
|
#[derive(Debug, Default, Copy, Clone, Pod)]
|
||||||
struct VdsoInstant {
|
struct VdsoInstant {
|
||||||
@ -100,16 +100,16 @@ struct VdsoData {
|
|||||||
arch_data: ArchVdsoData,
|
arch_data: ArchVdsoData,
|
||||||
}
|
}
|
||||||
|
|
||||||
const HIGH_RES_CLOCK_IDS: [ClockID; 4] = [
|
const HIGH_RES_CLOCK_IDS: [ClockId; 4] = [
|
||||||
ClockID::CLOCK_REALTIME,
|
ClockId::CLOCK_REALTIME,
|
||||||
ClockID::CLOCK_MONOTONIC,
|
ClockId::CLOCK_MONOTONIC,
|
||||||
ClockID::CLOCK_MONOTONIC_RAW,
|
ClockId::CLOCK_MONOTONIC_RAW,
|
||||||
ClockID::CLOCK_BOOTTIME,
|
ClockId::CLOCK_BOOTTIME,
|
||||||
];
|
];
|
||||||
|
|
||||||
const COARSE_RES_CLOCK_IDS: [ClockID; 2] = [
|
const COARSE_RES_CLOCK_IDS: [ClockId; 2] = [
|
||||||
ClockID::CLOCK_REALTIME_COARSE,
|
ClockId::CLOCK_REALTIME_COARSE,
|
||||||
ClockID::CLOCK_MONOTONIC_COARSE,
|
ClockId::CLOCK_MONOTONIC_COARSE,
|
||||||
];
|
];
|
||||||
|
|
||||||
impl VdsoData {
|
impl VdsoData {
|
||||||
@ -159,7 +159,7 @@ impl VdsoData {
|
|||||||
fn update_high_res_instant(&mut self, instant: Instant, instant_cycles: u64) {
|
fn update_high_res_instant(&mut self, instant: Instant, instant_cycles: u64) {
|
||||||
self.last_cycles = instant_cycles;
|
self.last_cycles = instant_cycles;
|
||||||
for clock_id in HIGH_RES_CLOCK_IDS {
|
for clock_id in HIGH_RES_CLOCK_IDS {
|
||||||
let secs = if clock_id == ClockID::CLOCK_REALTIME {
|
let secs = if clock_id == ClockId::CLOCK_REALTIME {
|
||||||
instant.secs() + START_SECS_COUNT.get().unwrap()
|
instant.secs() + START_SECS_COUNT.get().unwrap()
|
||||||
} else {
|
} else {
|
||||||
instant.secs()
|
instant.secs()
|
||||||
@ -175,7 +175,7 @@ impl VdsoData {
|
|||||||
|
|
||||||
fn update_coarse_res_instant(&mut self, instant: Instant) {
|
fn update_coarse_res_instant(&mut self, instant: Instant) {
|
||||||
for clock_id in COARSE_RES_CLOCK_IDS {
|
for clock_id in COARSE_RES_CLOCK_IDS {
|
||||||
let secs = if clock_id == ClockID::CLOCK_REALTIME_COARSE {
|
let secs = if clock_id == ClockId::CLOCK_REALTIME_COARSE {
|
||||||
instant.secs() + START_SECS_COUNT.get().unwrap()
|
instant.secs() + START_SECS_COUNT.get().unwrap()
|
||||||
} else {
|
} else {
|
||||||
instant.secs()
|
instant.secs()
|
||||||
@ -269,7 +269,7 @@ impl Vdso {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Update the requisite fields of the VDSO data in the `data_frame`.
|
/// Update the requisite fields of the VDSO data in the `data_frame`.
|
||||||
fn update_data_frame_instant(&self, clockid: ClockID) {
|
fn update_data_frame_instant(&self, clockid: ClockId) {
|
||||||
let clock_index = clockid as usize;
|
let clock_index = clockid as usize;
|
||||||
let secs_offset = 0xA0 + clock_index * 0x10;
|
let secs_offset = 0xA0 + clock_index * 0x10;
|
||||||
let nanos_info_offset = 0xA8 + clock_index * 0x10;
|
let nanos_info_offset = 0xA8 + clock_index * 0x10;
|
||||||
@ -323,7 +323,7 @@ pub(super) fn init() {
|
|||||||
MonotonicClock::timer_manager().create_timer(update_vdso_coarse_res_instant),
|
MonotonicClock::timer_manager().create_timer(update_vdso_coarse_res_instant),
|
||||||
);
|
);
|
||||||
coarse_instant_timer.set_interval(Duration::from_millis(100));
|
coarse_instant_timer.set_interval(Duration::from_millis(100));
|
||||||
coarse_instant_timer.set_timeout(Duration::from_millis(100));
|
coarse_instant_timer.set_timeout(Timeout::After(Duration::from_millis(100)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the VDSO vmo.
|
/// Return the VDSO vmo.
|
||||||
|
Reference in New Issue
Block a user