2019-02-22 10:10:24 +04:00
|
|
|
//! Syscalls for time
|
|
|
|
|
|
|
|
use super::*;
|
2019-03-12 07:49:17 +04:00
|
|
|
use crate::consts::USEC_PER_TICK;
|
2019-03-09 10:08:56 +04:00
|
|
|
use core::time::Duration;
|
2019-03-09 21:20:50 +04:00
|
|
|
use lazy_static::lazy_static;
|
2019-02-22 10:10:24 +04:00
|
|
|
|
2019-03-10 04:53:29 +04:00
|
|
|
/// should be initialized together
|
2019-03-04 19:52:19 +04:00
|
|
|
lazy_static! {
|
2019-03-12 07:49:17 +04:00
|
|
|
pub static ref EPOCH_BASE: u64 = crate::arch::timer::read_epoch();
|
2019-03-04 19:52:19 +04:00
|
|
|
pub static ref TICK_BASE: u64 = unsafe { crate::trap::TICK as u64 };
|
|
|
|
}
|
|
|
|
|
2019-03-10 04:53:29 +04:00
|
|
|
// 1ms msec
|
|
|
|
// 1us usec
|
|
|
|
// 1ns nsec
|
|
|
|
|
|
|
|
const USEC_PER_SEC: u64 = 1_000_000;
|
|
|
|
const MSEC_PER_SEC: u64 = 1_000;
|
|
|
|
const USEC_PER_MSEC: u64 = 1_000;
|
|
|
|
const NSEC_PER_USEC: u64 = 1_000;
|
2019-04-16 21:16:27 +04:00
|
|
|
const NSEC_PER_MSEC: u64 = 1_000_000;
|
2019-03-10 04:53:29 +04:00
|
|
|
|
|
|
|
/// Get time since epoch in usec
|
|
|
|
fn get_epoch_usec() -> u64 {
|
|
|
|
let tick_base = *TICK_BASE;
|
|
|
|
let epoch_base = *EPOCH_BASE;
|
|
|
|
let tick = unsafe { crate::trap::TICK as u64 };
|
|
|
|
|
|
|
|
(tick - tick_base) * USEC_PER_TICK as u64 + epoch_base * USEC_PER_SEC
|
|
|
|
}
|
|
|
|
|
2019-03-04 19:52:19 +04:00
|
|
|
#[repr(C)]
|
2019-03-09 10:08:56 +04:00
|
|
|
#[derive(Debug, Copy, Clone)]
|
2019-03-04 19:52:19 +04:00
|
|
|
pub struct TimeVal {
|
2019-04-21 10:58:43 +04:00
|
|
|
sec: usize,
|
|
|
|
usec: usize,
|
2019-03-04 19:52:19 +04:00
|
|
|
}
|
|
|
|
|
2019-03-07 05:47:36 +04:00
|
|
|
impl TimeVal {
|
|
|
|
pub fn to_msec(&self) -> u64 {
|
2019-04-21 10:58:43 +04:00
|
|
|
(self.sec as u64) * MSEC_PER_SEC + (self.usec as u64) / USEC_PER_MSEC
|
2019-03-07 05:47:36 +04:00
|
|
|
}
|
|
|
|
|
2019-03-10 04:53:29 +04:00
|
|
|
pub fn get_epoch() -> Self {
|
|
|
|
let usec = get_epoch_usec();
|
|
|
|
TimeVal {
|
2019-04-21 10:58:43 +04:00
|
|
|
sec: (usec / USEC_PER_SEC) as usize,
|
|
|
|
usec: (usec % USEC_PER_SEC) as usize,
|
2019-03-10 04:53:29 +04:00
|
|
|
}
|
2019-03-07 05:47:36 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-08 11:35:18 +04:00
|
|
|
#[repr(C)]
|
2019-03-09 10:08:56 +04:00
|
|
|
#[derive(Debug, Copy, Clone)]
|
2019-03-08 11:35:18 +04:00
|
|
|
pub struct TimeSpec {
|
2019-04-21 10:30:02 +04:00
|
|
|
sec: usize,
|
|
|
|
nsec: usize,
|
2019-03-08 11:35:18 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl TimeSpec {
|
2019-04-16 21:16:27 +04:00
|
|
|
pub fn to_msec(&self) -> u64 {
|
2019-04-21 10:58:43 +04:00
|
|
|
(self.sec as u64) * MSEC_PER_SEC + (self.nsec as u64) / NSEC_PER_MSEC
|
2019-04-16 21:16:27 +04:00
|
|
|
}
|
|
|
|
|
2019-03-09 10:08:56 +04:00
|
|
|
pub fn to_duration(&self) -> Duration {
|
2019-04-21 10:30:02 +04:00
|
|
|
Duration::new(self.sec as u64, self.nsec as u32)
|
2019-03-08 11:35:18 +04:00
|
|
|
}
|
2019-03-10 04:53:29 +04:00
|
|
|
|
|
|
|
pub fn get_epoch() -> Self {
|
|
|
|
let usec = get_epoch_usec();
|
|
|
|
TimeSpec {
|
2019-04-21 10:30:02 +04:00
|
|
|
sec: (usec / USEC_PER_SEC) as usize,
|
|
|
|
nsec: (usec % USEC_PER_SEC * NSEC_PER_USEC) as usize,
|
2019-03-10 04:53:29 +04:00
|
|
|
}
|
|
|
|
}
|
2019-03-08 11:35:18 +04:00
|
|
|
}
|
|
|
|
|
2019-03-04 19:52:19 +04:00
|
|
|
pub fn sys_gettimeofday(tv: *mut TimeVal, tz: *const u8) -> SysResult {
|
2019-03-08 11:35:18 +04:00
|
|
|
info!("gettimeofday: tv: {:?}, tz: {:?}", tv, tz);
|
2019-03-04 12:25:57 +04:00
|
|
|
if tz as usize != 0 {
|
|
|
|
return Err(SysError::EINVAL);
|
|
|
|
}
|
|
|
|
|
2019-03-10 04:39:22 +04:00
|
|
|
let proc = process();
|
2019-04-28 11:55:45 +04:00
|
|
|
let tv = unsafe { proc.vm.check_write_ptr(tv)? };
|
2019-03-04 12:25:57 +04:00
|
|
|
|
2019-03-10 04:53:29 +04:00
|
|
|
let timeval = TimeVal::get_epoch();
|
2019-04-28 11:55:45 +04:00
|
|
|
*tv = timeval;
|
2019-03-04 12:25:57 +04:00
|
|
|
Ok(0)
|
2019-03-02 16:15:55 +04:00
|
|
|
}
|
|
|
|
|
2019-03-08 11:35:18 +04:00
|
|
|
pub fn sys_clock_gettime(clock: usize, ts: *mut TimeSpec) -> SysResult {
|
|
|
|
info!("clock_gettime: clock: {:?}, ts: {:?}", clock, ts);
|
|
|
|
|
2019-03-10 04:39:22 +04:00
|
|
|
let proc = process();
|
2019-04-28 11:55:45 +04:00
|
|
|
let ts = unsafe { proc.vm.check_write_ptr(ts)? };
|
2019-03-08 11:35:18 +04:00
|
|
|
|
2019-03-10 04:53:29 +04:00
|
|
|
let timespec = TimeSpec::get_epoch();
|
2019-04-28 11:55:45 +04:00
|
|
|
*ts = timespec;
|
2019-03-08 11:35:18 +04:00
|
|
|
Ok(0)
|
|
|
|
}
|
|
|
|
|
2019-03-02 16:15:55 +04:00
|
|
|
pub fn sys_time(time: *mut u64) -> SysResult {
|
2019-03-10 04:53:29 +04:00
|
|
|
let sec = get_epoch_usec() / USEC_PER_SEC;
|
2019-03-02 16:15:55 +04:00
|
|
|
if time as usize != 0 {
|
2019-03-10 04:39:22 +04:00
|
|
|
let proc = process();
|
2019-04-28 11:55:45 +04:00
|
|
|
let time = unsafe { proc.vm.check_write_ptr(time)? };
|
|
|
|
*time = sec as u64;
|
2019-03-02 16:15:55 +04:00
|
|
|
}
|
2019-03-08 15:04:39 +04:00
|
|
|
Ok(sec as usize)
|
2019-03-02 16:15:55 +04:00
|
|
|
}
|
2019-03-12 05:54:07 +04:00
|
|
|
|
|
|
|
// ignore other fields for now
|
|
|
|
#[repr(C)]
|
|
|
|
pub struct RUsage {
|
|
|
|
utime: TimeVal,
|
2019-03-27 14:35:08 +04:00
|
|
|
stime: TimeVal,
|
2019-03-12 05:54:07 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn sys_getrusage(who: usize, rusage: *mut RUsage) -> SysResult {
|
|
|
|
info!("getrusage: who: {}, rusage: {:?}", who, rusage);
|
|
|
|
let proc = process();
|
2019-04-28 11:55:45 +04:00
|
|
|
let rusage = unsafe { proc.vm.check_write_ptr(rusage)? };
|
2019-03-12 05:54:07 +04:00
|
|
|
|
|
|
|
let tick_base = *TICK_BASE;
|
|
|
|
let tick = unsafe { crate::trap::TICK as u64 };
|
|
|
|
|
|
|
|
let usec = (tick - tick_base) * USEC_PER_TICK as u64;
|
|
|
|
let new_rusage = RUsage {
|
|
|
|
utime: TimeVal {
|
2019-04-21 10:58:43 +04:00
|
|
|
sec: (usec / USEC_PER_SEC) as usize,
|
|
|
|
usec: (usec % USEC_PER_SEC) as usize,
|
2019-03-12 05:54:07 +04:00
|
|
|
},
|
|
|
|
stime: TimeVal {
|
2019-04-21 10:58:43 +04:00
|
|
|
sec: (usec / USEC_PER_SEC) as usize,
|
|
|
|
usec: (usec % USEC_PER_SEC) as usize,
|
2019-03-27 14:35:08 +04:00
|
|
|
},
|
2019-03-12 05:54:07 +04:00
|
|
|
};
|
2019-04-28 11:55:45 +04:00
|
|
|
*rusage = new_rusage;
|
2019-03-12 05:54:07 +04:00
|
|
|
Ok(0)
|
|
|
|
}
|
2019-04-21 13:07:40 +04:00
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
#[derive(Debug, Copy, Clone)]
|
|
|
|
pub struct Tms {
|
2019-04-25 21:14:40 +04:00
|
|
|
tms_utime: u64, /* user time */
|
2019-04-21 13:07:40 +04:00
|
|
|
tms_stime: u64, /* system time */
|
|
|
|
tms_cutime: u64, /* user time of children */
|
|
|
|
tms_cstime: u64, /* system time of children */
|
|
|
|
}
|
|
|
|
|
2019-04-25 21:14:40 +04:00
|
|
|
pub fn sys_times(buf: *mut Tms) -> SysResult {
|
2019-04-21 13:07:40 +04:00
|
|
|
info!("times: buf: {:?}", buf);
|
|
|
|
let proc = process();
|
2019-04-28 11:55:45 +04:00
|
|
|
let buf = unsafe { proc.vm.check_write_ptr(buf)? };
|
2019-04-21 13:07:40 +04:00
|
|
|
|
|
|
|
let tick_base = *TICK_BASE;
|
|
|
|
let tick = unsafe { crate::trap::TICK as u64 };
|
|
|
|
|
|
|
|
let new_buf = Tms {
|
|
|
|
tms_utime: 0,
|
|
|
|
tms_stime: 0,
|
|
|
|
tms_cutime: 0,
|
|
|
|
tms_cstime: 0,
|
|
|
|
};
|
|
|
|
|
2019-04-28 11:55:45 +04:00
|
|
|
*buf = new_buf;
|
2019-04-21 13:07:40 +04:00
|
|
|
Ok(tick as usize)
|
2019-04-25 21:14:40 +04:00
|
|
|
}
|