forked from rcore-os/zCore
171 lines
5.1 KiB
Rust
171 lines
5.1 KiB
Rust
//! Syscalls for time
|
||
//! - clock_gettime
|
||
//!
|
||
use crate::Syscall;
|
||
use kernel_hal::{user::UserInPtr, user::UserOutPtr};
|
||
use linux_object::error::LxError;
|
||
use linux_object::error::SysResult;
|
||
use linux_object::time::*;
|
||
|
||
const USEC_PER_TICK: usize = 10000;
|
||
|
||
impl Syscall<'_> {
|
||
/// finds the resolution (precision) of the specified clock clockid, and,
|
||
/// if buffer is non-NULL, stores it in the struct timespec pointed to by buffer
|
||
pub fn sys_clock_gettime(&self, clock: usize, mut buf: UserOutPtr<TimeSpec>) -> SysResult {
|
||
info!("clock_gettime: id={:?} buf={:?}", clock, buf);
|
||
// TODO: handle clock_settime
|
||
let ts = TimeSpec::now();
|
||
buf.write(ts)?;
|
||
|
||
info!("TimeSpec: {:?}", ts);
|
||
|
||
Ok(0)
|
||
}
|
||
|
||
/// get the time with second and microseconds
|
||
pub fn sys_gettimeofday(
|
||
&mut self,
|
||
mut tv: UserOutPtr<TimeVal>,
|
||
tz: UserInPtr<u8>,
|
||
) -> SysResult {
|
||
info!("gettimeofday: tv: {:?}, tz: {:?}", tv, tz);
|
||
// don't support tz
|
||
if !tz.is_null() {
|
||
return Err(LxError::EINVAL);
|
||
}
|
||
|
||
let timeval = TimeVal::now();
|
||
tv.write(timeval)?;
|
||
|
||
info!("TimeVal: {:?}", timeval);
|
||
|
||
Ok(0)
|
||
}
|
||
|
||
/// get time in seconds
|
||
#[cfg(target_arch = "x86_64")]
|
||
pub fn sys_time(&mut self, mut time: UserOutPtr<u64>) -> SysResult {
|
||
info!("time: time: {:?}", time);
|
||
let sec = TimeSpec::now().sec;
|
||
time.write(sec as u64)?;
|
||
Ok(sec)
|
||
}
|
||
|
||
/// JUST FOR TEST, DO NOT USE IT
|
||
pub fn sys_block_in_kernel(&self) -> SysResult {
|
||
// DEAD LOOP
|
||
error!("loop in kernel");
|
||
let mut old = TimeSpec::now().sec;
|
||
loop {
|
||
let sec = TimeSpec::now().sec;
|
||
if sec == old {
|
||
core::hint::spin_loop();
|
||
continue;
|
||
}
|
||
old = sec;
|
||
warn!("1 seconds past");
|
||
}
|
||
}
|
||
|
||
/// get resource usage
|
||
/// currently only support ru_utime and ru_stime:
|
||
/// - `ru_utime`: user CPU time used
|
||
/// - `ru_stime`: system CPU time used
|
||
pub fn sys_getrusage(&mut self, who: usize, mut rusage: UserOutPtr<RUsage>) -> SysResult {
|
||
info!("getrusage: who: {}, rusage: {:?}", who, rusage);
|
||
|
||
let new_rusage = RUsage {
|
||
utime: TimeVal::now(),
|
||
stime: TimeVal::now(),
|
||
};
|
||
rusage.write(new_rusage)?;
|
||
Ok(0)
|
||
}
|
||
|
||
/// stores the current process times in the struct tms that buf points to
|
||
pub fn sys_times(&mut self, mut buf: UserOutPtr<Tms>) -> SysResult {
|
||
info!("times: buf: {:?}", buf);
|
||
|
||
let tv = TimeVal::now();
|
||
|
||
let tick = (tv.sec * 1_000_000 + tv.usec) / USEC_PER_TICK;
|
||
|
||
let new_buf = Tms {
|
||
tms_utime: 0,
|
||
tms_stime: 0,
|
||
tms_cutime: 0,
|
||
tms_cstime: 0,
|
||
};
|
||
|
||
buf.write(new_buf)?;
|
||
|
||
info!("tick: {:?}", tick);
|
||
Ok(tick as usize)
|
||
}
|
||
|
||
/// Allows the calling thread to sleep for
|
||
/// an interval specified with nanosecond precision
|
||
pub async fn sys_nanosleep(&self, req: UserInPtr<TimeSpec>) -> SysResult {
|
||
info!("nanosleep: deadline={:?}", req);
|
||
let duration = req.read()?.into();
|
||
nanosleep(duration).await;
|
||
Ok(0)
|
||
}
|
||
|
||
/// clock nanosleep
|
||
pub async fn sys_clock_nanosleep(
|
||
&self,
|
||
clockid: usize,
|
||
flags: usize,
|
||
req: UserInPtr<TimeSpec>,
|
||
rem: UserOutPtr<TimeSpec>,
|
||
) -> SysResult {
|
||
warn!(
|
||
"clock_nanosleep: clockid={:?},flags={:?},req={:?},,rem={:?}",
|
||
clockid,
|
||
flags,
|
||
req.read()?,
|
||
rem
|
||
);
|
||
use core::time::Duration;
|
||
let duration: Duration = req.read()?.into();
|
||
let clockid = ClockId::from(clockid);
|
||
let flags = ClockFlags::from(flags);
|
||
warn!("clockid={:?},flags={:?}", clockid, flags,);
|
||
match clockid {
|
||
ClockId::ClockRealTime => {
|
||
match flags {
|
||
ClockFlags::ZeroFlag => {
|
||
nanosleep(duration).await;
|
||
}
|
||
ClockFlags::TimerAbsTime => {
|
||
// 目前统一由nanosleep代替了、之后再修改
|
||
nanosleep(duration).await;
|
||
}
|
||
}
|
||
}
|
||
ClockId::ClockMonotonic => {
|
||
match flags {
|
||
ClockFlags::ZeroFlag => {
|
||
nanosleep(duration).await;
|
||
}
|
||
ClockFlags::TimerAbsTime => {
|
||
// 目前统一由nanosleep代替了、之后再修改
|
||
nanosleep(duration).await;
|
||
}
|
||
}
|
||
}
|
||
ClockId::ClockProcessCpuTimeId => {}
|
||
ClockId::ClockThreadCpuTimeId => {}
|
||
ClockId::ClockMonotonicRaw => {}
|
||
ClockId::ClockRealTimeCoarse => {}
|
||
ClockId::ClockMonotonicCoarse => {}
|
||
ClockId::ClockBootTime => {}
|
||
ClockId::ClockRealTimeAlarm => {}
|
||
ClockId::ClockBootTimeAlarm => {}
|
||
}
|
||
Ok(0)
|
||
}
|
||
}
|