mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-23 17:33:23 +00:00
Support more clock ids
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
c84efe7a90
commit
e952a16954
@ -96,7 +96,7 @@ impl DirOps for RootDirOps {
|
||||
SelfSymOps::new_inode(this_ptr.clone())
|
||||
} else if let Ok(pid) = name.parse::<Pid>() {
|
||||
let process_ref =
|
||||
process_table::get_process(&pid).ok_or_else(|| Error::new(Errno::ENOENT))?;
|
||||
process_table::get_process(pid).ok_or_else(|| Error::new(Errno::ENOENT))?;
|
||||
PidDirOps::new_inode(process_ref, this_ptr.clone())
|
||||
} else {
|
||||
return_errno!(Errno::ENOENT);
|
||||
|
@ -63,7 +63,7 @@ const INIT_PROCESS_PID: Pid = 1;
|
||||
|
||||
/// Get the init process
|
||||
fn get_init_process() -> Option<Arc<Process>> {
|
||||
process_table::get_process(&INIT_PROCESS_PID)
|
||||
process_table::get_process(INIT_PROCESS_PID)
|
||||
}
|
||||
|
||||
fn is_init_process(process: &Process) -> bool {
|
||||
|
@ -20,7 +20,7 @@ use crate::{
|
||||
/// If `signal` is `None`, this method will only check permission without sending
|
||||
/// any signal.
|
||||
pub fn kill(pid: Pid, signal: Option<UserSignal>) -> Result<()> {
|
||||
let process = process_table::get_process(&pid)
|
||||
let process = process_table::get_process(pid)
|
||||
.ok_or_else(|| Error::with_message(Errno::ESRCH, "the target process does not exist"))?;
|
||||
|
||||
kill_process(&process, signal)
|
||||
|
@ -20,8 +20,8 @@ static SESSION_TABLE: Mutex<BTreeMap<Sid, Arc<Session>>> = Mutex::new(BTreeMap::
|
||||
// ************ Process *************
|
||||
|
||||
/// Gets a process with pid
|
||||
pub fn get_process(pid: &Pid) -> Option<Arc<Process>> {
|
||||
PROCESS_TABLE.lock().get(pid).cloned()
|
||||
pub fn get_process(pid: Pid) -> Option<Arc<Process>> {
|
||||
PROCESS_TABLE.lock().get(&pid).cloned()
|
||||
}
|
||||
|
||||
pub(super) fn process_table_mut() -> MutexGuard<'static, BTreeMap<Pid, Arc<Process>>> {
|
||||
|
@ -8,6 +8,8 @@ use int_to_c_enum::TryFromInt;
|
||||
use super::SyscallReturn;
|
||||
use crate::{
|
||||
prelude::*,
|
||||
process::{posix_thread::PosixThreadExt, process_table},
|
||||
thread::{thread_table, Thread},
|
||||
time::{
|
||||
clockid_t,
|
||||
clocks::{
|
||||
@ -20,10 +22,9 @@ use crate::{
|
||||
};
|
||||
|
||||
pub fn sys_clock_gettime(clockid: clockid_t, timespec_addr: Vaddr) -> Result<SyscallReturn> {
|
||||
let clock_id = ClockID::try_from(clockid)?;
|
||||
debug!("clockid = {:?}", clock_id);
|
||||
debug!("clockid = {:?}", clockid);
|
||||
|
||||
let time_duration = read_clock(&clock_id)?;
|
||||
let time_duration = read_clock(clockid)?;
|
||||
|
||||
let timespec = timespec_t::from(time_duration);
|
||||
write_val_to_user(timespec_addr, ×pec)?;
|
||||
@ -31,9 +32,10 @@ pub fn sys_clock_gettime(clockid: clockid_t, timespec_addr: Vaddr) -> Result<Sys
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
||||
// The hard-coded clock IDs.
|
||||
#[derive(Debug, Copy, Clone, TryFromInt, PartialEq)]
|
||||
#[repr(i32)]
|
||||
pub enum ClockID {
|
||||
pub enum ClockId {
|
||||
CLOCK_REALTIME = 0,
|
||||
CLOCK_MONOTONIC = 1,
|
||||
CLOCK_PROCESS_CPUTIME_ID = 2,
|
||||
@ -44,19 +46,110 @@ pub enum ClockID {
|
||||
CLOCK_BOOTTIME = 7,
|
||||
}
|
||||
|
||||
/// Read the time of a clock specified by the input `ClockID`.
|
||||
/// The information decoded from a dynamic clock ID.
|
||||
///
|
||||
/// If the `ClockID` does not support, this function will return `Err`.
|
||||
pub fn read_clock(clock_id: &ClockID) -> Result<Duration> {
|
||||
match clock_id {
|
||||
ClockID::CLOCK_REALTIME => Ok(RealTimeClock::get().read_time()),
|
||||
ClockID::CLOCK_MONOTONIC => Ok(MonotonicClock::get().read_time()),
|
||||
ClockID::CLOCK_MONOTONIC_RAW => Ok(MonotonicRawClock::get().read_time()),
|
||||
ClockID::CLOCK_REALTIME_COARSE => Ok(RealTimeCoarseClock::get().read_time()),
|
||||
ClockID::CLOCK_MONOTONIC_COARSE => Ok(MonotonicCoarseClock::get().read_time()),
|
||||
ClockID::CLOCK_BOOTTIME => Ok(BootTimeClock::get().read_time()),
|
||||
_ => {
|
||||
return_errno_with_message!(Errno::EINVAL, "unsupported clock_id");
|
||||
/// Dynamic clocks are the clocks operates on certain
|
||||
/// character devices, processes or threads. Their IDs will
|
||||
/// be generated by encoding the file descriptor, PID or TID.
|
||||
/// Here we follow the rules in Linux:
|
||||
///
|
||||
/// The dynamic clock ID is a 32 bit integer.
|
||||
/// - The most significant 29 bits hold either a PID or a file descriptor.
|
||||
/// - Bit 2 indicates whether a cpu clock refers to a thread or a process.
|
||||
/// - Bits 1 and 0 give the type: PROF=0, VIRT=1, SCHED=2, or FD=3.
|
||||
/// - A clock ID is invalid if bits 2, 1, and 0 are all set.
|
||||
///
|
||||
/// Ref: https://github.com/torvalds/linux/blob/master/include/linux/posix-timers_types.h
|
||||
pub enum DynamicClockIdInfo {
|
||||
Pid(u32, DynamicClockType),
|
||||
Tid(u32, DynamicClockType),
|
||||
Fd(u32),
|
||||
}
|
||||
|
||||
impl TryFrom<clockid_t> for DynamicClockIdInfo {
|
||||
type Error = crate::Error;
|
||||
|
||||
fn try_from(value: clockid_t) -> core::prelude::v1::Result<Self, Self::Error> {
|
||||
const CPU_CLOCK_TYPE_MASK: i32 = 0b11;
|
||||
const ID_TYPE_MASK: i32 = 0b100;
|
||||
const INVALID_MASK: i32 = CPU_CLOCK_TYPE_MASK | ID_TYPE_MASK;
|
||||
|
||||
if (value & INVALID_MASK) == INVALID_MASK {
|
||||
return_errno_with_message!(Errno::EINVAL, "invalid clock ID");
|
||||
}
|
||||
|
||||
let id = !(value >> 3);
|
||||
let cpu_clock_type = DynamicClockType::try_from(CPU_CLOCK_TYPE_MASK & value)?;
|
||||
|
||||
if let DynamicClockType::FD = cpu_clock_type {
|
||||
return Ok(DynamicClockIdInfo::Fd(id as u32));
|
||||
}
|
||||
|
||||
if ID_TYPE_MASK & value > 0 {
|
||||
Ok(DynamicClockIdInfo::Tid(id as u32, cpu_clock_type))
|
||||
} else {
|
||||
Ok(DynamicClockIdInfo::Pid(id as u32, cpu_clock_type))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, TryFromInt, PartialEq)]
|
||||
#[repr(i32)]
|
||||
pub enum DynamicClockType {
|
||||
Profiling = 0,
|
||||
Virtual = 1,
|
||||
Scheduling = 2,
|
||||
FD = 3,
|
||||
}
|
||||
|
||||
/// Reads the time of a clock specified by the input clock ID.
|
||||
///
|
||||
/// If the clock ID does not support, this function will return `Err`.
|
||||
pub fn read_clock(clockid: clockid_t) -> Result<Duration> {
|
||||
if clockid >= 0 {
|
||||
let clock_id = ClockId::try_from(clockid)?;
|
||||
match clock_id {
|
||||
ClockId::CLOCK_REALTIME => Ok(RealTimeClock::get().read_time()),
|
||||
ClockId::CLOCK_MONOTONIC => Ok(MonotonicClock::get().read_time()),
|
||||
ClockId::CLOCK_MONOTONIC_RAW => Ok(MonotonicRawClock::get().read_time()),
|
||||
ClockId::CLOCK_REALTIME_COARSE => Ok(RealTimeCoarseClock::get().read_time()),
|
||||
ClockId::CLOCK_MONOTONIC_COARSE => Ok(MonotonicCoarseClock::get().read_time()),
|
||||
ClockId::CLOCK_BOOTTIME => Ok(BootTimeClock::get().read_time()),
|
||||
ClockId::CLOCK_PROCESS_CPUTIME_ID => {
|
||||
let process = current!();
|
||||
Ok(process.prof_clock().read_time())
|
||||
}
|
||||
ClockId::CLOCK_THREAD_CPUTIME_ID => {
|
||||
let thread = Thread::current();
|
||||
Ok(thread.as_posix_thread().unwrap().prof_clock().read_time())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let dynamic_clockid_info = DynamicClockIdInfo::try_from(clockid)?;
|
||||
match dynamic_clockid_info {
|
||||
DynamicClockIdInfo::Pid(pid, clock_type) => {
|
||||
let process = process_table::get_process(pid)
|
||||
.ok_or_else(|| crate::Error::with_message(Errno::EINVAL, "invalid clock ID"))?;
|
||||
match clock_type {
|
||||
DynamicClockType::Profiling => Ok(process.prof_clock().read_time()),
|
||||
DynamicClockType::Virtual => Ok(process.prof_clock().user_clock().read_time()),
|
||||
// TODO: support scheduling clock and fd clock.
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
DynamicClockIdInfo::Tid(tid, clock_type) => {
|
||||
let thread = thread_table::get_thread(tid)
|
||||
.ok_or_else(|| Error::with_message(Errno::EINVAL, "invalid clock ID"))?;
|
||||
let posix_thread = thread.as_posix_thread().unwrap();
|
||||
match clock_type {
|
||||
DynamicClockType::Profiling => Ok(posix_thread.prof_clock().read_time()),
|
||||
DynamicClockType::Virtual => {
|
||||
Ok(posix_thread.prof_clock().user_clock().read_time())
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
DynamicClockIdInfo::Fd(_) => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ pub fn sys_getsid(pid: Pid) -> Result<SyscallReturn> {
|
||||
return Ok(SyscallReturn::Return(sid as _));
|
||||
}
|
||||
|
||||
let Some(process) = process_table::get_process(&pid) else {
|
||||
let Some(process) = process_table::get_process(pid) else {
|
||||
return_errno_with_message!(Errno::ESRCH, "the process does not exist")
|
||||
};
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use core::time::Duration;
|
||||
|
||||
use super::{clock_gettime::read_clock, ClockID, SyscallReturn};
|
||||
use super::{clock_gettime::read_clock, ClockId, SyscallReturn};
|
||||
use crate::{
|
||||
prelude::*,
|
||||
process::signal::Pauser,
|
||||
@ -14,9 +14,14 @@ pub fn sys_nanosleep(
|
||||
request_timespec_addr: Vaddr,
|
||||
remain_timespec_addr: Vaddr,
|
||||
) -> Result<SyscallReturn> {
|
||||
let clock_id = ClockID::CLOCK_MONOTONIC;
|
||||
let clockid = ClockId::CLOCK_MONOTONIC;
|
||||
|
||||
do_clock_nanosleep(clock_id, false, request_timespec_addr, remain_timespec_addr)
|
||||
do_clock_nanosleep(
|
||||
clockid as clockid_t,
|
||||
false,
|
||||
request_timespec_addr,
|
||||
remain_timespec_addr,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn sys_clock_nanosleep(
|
||||
@ -25,7 +30,6 @@ pub fn sys_clock_nanosleep(
|
||||
request_timespec_addr: Vaddr,
|
||||
remain_timespec_addr: Vaddr,
|
||||
) -> Result<SyscallReturn> {
|
||||
let clock_id = ClockID::try_from(clockid)?;
|
||||
let is_abs_time = if flags == 0 {
|
||||
false
|
||||
} else if flags == TIMER_ABSTIME {
|
||||
@ -35,7 +39,7 @@ pub fn sys_clock_nanosleep(
|
||||
};
|
||||
|
||||
do_clock_nanosleep(
|
||||
clock_id,
|
||||
clockid,
|
||||
is_abs_time,
|
||||
request_timespec_addr,
|
||||
remain_timespec_addr,
|
||||
@ -43,7 +47,7 @@ pub fn sys_clock_nanosleep(
|
||||
}
|
||||
|
||||
fn do_clock_nanosleep(
|
||||
clock_id: ClockID,
|
||||
clockid: clockid_t,
|
||||
is_abs_time: bool,
|
||||
request_timespec_addr: Vaddr,
|
||||
remain_timespec_addr: Vaddr,
|
||||
@ -55,10 +59,10 @@ fn do_clock_nanosleep(
|
||||
|
||||
debug!(
|
||||
"clockid = {:?}, is_abs_time = {}, request_time = {:?}, remain_timespec_addr = 0x{:x}",
|
||||
clock_id, is_abs_time, request_time, remain_timespec_addr
|
||||
clockid, is_abs_time, request_time, remain_timespec_addr
|
||||
);
|
||||
|
||||
let start_time = read_clock(&clock_id)?;
|
||||
let start_time = read_clock(clockid)?;
|
||||
let timeout = if is_abs_time {
|
||||
if request_time < start_time {
|
||||
return Ok(SyscallReturn::Return(0));
|
||||
@ -77,7 +81,7 @@ fn do_clock_nanosleep(
|
||||
match res {
|
||||
Err(e) if e.error() == Errno::ETIME => Ok(SyscallReturn::Return(0)),
|
||||
Err(e) if e.error() == Errno::EINTR => {
|
||||
let end_time = read_clock(&clock_id)?;
|
||||
let end_time = read_clock(clockid)?;
|
||||
|
||||
if end_time >= start_time + timeout {
|
||||
return Ok(SyscallReturn::Return(0));
|
||||
|
@ -61,7 +61,7 @@ pub fn sys_get_priority(which: i32, who: u32) -> Result<SyscallReturn> {
|
||||
fn get_processes(prio_target: PriorityTarget) -> Result<Vec<Arc<Process>>> {
|
||||
Ok(match prio_target {
|
||||
PriorityTarget::Process(pid) => {
|
||||
let process = process_table::get_process(&pid).ok_or(Error::new(Errno::ESRCH))?;
|
||||
let process = process_table::get_process(pid).ok_or(Error::new(Errno::ESRCH))?;
|
||||
vec![process]
|
||||
}
|
||||
PriorityTarget::ProcessGroup(pgid) => {
|
||||
|
@ -28,7 +28,7 @@ pub fn sys_setpgid(pid: Pid, pgid: Pgid) -> Result<SyscallReturn> {
|
||||
return_errno_with_message!(Errno::EPERM, "process group must exist");
|
||||
}
|
||||
|
||||
let process = process_table::get_process(&pid)
|
||||
let process = process_table::get_process(pid)
|
||||
.ok_or(Error::with_message(Errno::ESRCH, "process does not exist"))?;
|
||||
|
||||
process.to_other_group(pgid)?;
|
||||
|
Reference in New Issue
Block a user