Add timerslack concept for libos and enbale prctl PR_GET_TIMERSLACK option
This commit is contained in:
parent
1a11655169
commit
4031216f13
@ -118,6 +118,7 @@ enclave {
|
||||
void occlum_ocall_clock_gettime(clockid_t clockid, [out] struct timespec* ts);
|
||||
void occlum_ocall_clock_getres(clockid_t clockid, [out] struct timespec* res);
|
||||
void occlum_ocall_rdtsc([out] uint32_t* low, [out] uint32_t* high);
|
||||
void occlum_ocall_get_timerslack([out] int *timer_slack);
|
||||
|
||||
int occlum_ocall_nanosleep(
|
||||
[in] const struct timespec* req,
|
||||
|
@ -1,3 +1,4 @@
|
||||
use super::super::time::timer_slack::TIMERSLACK;
|
||||
use super::*;
|
||||
|
||||
pub fn select(
|
||||
@ -63,7 +64,10 @@ pub fn select(
|
||||
if !timeout.is_null() {
|
||||
let time_left = unsafe { *(timeout) };
|
||||
time_left.validate()?;
|
||||
assert!(time_left.as_duration() <= origin_timeout.as_duration());
|
||||
assert!(
|
||||
// Note: TIMERSLACK is a single value use maintained by the libOS and will not vary for different threads.
|
||||
time_left.as_duration() <= origin_timeout.as_duration() + (*TIMERSLACK).to_duration()
|
||||
);
|
||||
}
|
||||
|
||||
debug!("returned pollfds are {:?}", pollfds);
|
||||
|
@ -3,34 +3,31 @@
|
||||
// Implement `PrctlNum` and `PrctlCmd`.
|
||||
#[macro_export]
|
||||
macro_rules! impl_prctl_nums_and_cmds {
|
||||
($( $prctl_name: ident => ( $prctl_num: expr, $($prctl_type_tt: tt)* ) ),+,) => {
|
||||
($( $prctl_name: ident => ( $prctl_num: expr, $($prctl_type_tt: tt),* ) ),+,) => {
|
||||
$(const $prctl_name:i32 = $prctl_num;)*
|
||||
|
||||
impl_prctl_cmds! {
|
||||
$(
|
||||
$prctl_name => ( $($prctl_type_tt)*),
|
||||
$prctl_name => ( $($prctl_type_tt),* ),
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_prctl_cmds {
|
||||
($( $prctl_name: ident => ( $($prctl_type_tt: tt)* ) ),+,) => {
|
||||
($( $prctl_name: ident => ( $($prctl_type_tt: tt),* ) ),+,) => {
|
||||
#[derive(Debug)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum PrctlCmd<'a> {
|
||||
$(
|
||||
$prctl_name( get_arg_type!($($prctl_type_tt)*) ),
|
||||
$prctl_name($(get_arg_type!($prctl_type_tt)),* ),
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! get_arg_type {
|
||||
(()) => {
|
||||
()
|
||||
};
|
||||
($($prctl_type_tt: tt)*) => {
|
||||
$($prctl_type_tt)*
|
||||
($prctl_type_tt: tt) => {
|
||||
$prctl_type_tt
|
||||
};
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ use alloc::vec::Vec;
|
||||
use std::ffi::CString;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
use super::super::time::timer_slack::TIMERSLACK;
|
||||
use super::thread::ThreadName;
|
||||
use crate::prelude::*;
|
||||
use crate::util::mem_util::from_user::{check_array, clone_cstring_safely};
|
||||
@ -16,8 +17,9 @@ impl_prctl_nums_and_cmds! {
|
||||
// Format:
|
||||
// prctl_name => (prctl_num, prctl_type_arg, ...
|
||||
PR_SET_NAME => (15, ThreadName),
|
||||
// Get thread name
|
||||
PR_GET_NAME => (16, &'a mut [u8]),
|
||||
PR_GET_NAME => (16, (&'a mut [u8])),
|
||||
PR_SET_TIMERSLACK => (29, u64),
|
||||
PR_GET_TIMERSLACK => (30, ()),
|
||||
}
|
||||
|
||||
impl<'a> PrctlCmd<'a> {
|
||||
@ -39,6 +41,8 @@ impl<'a> PrctlCmd<'a> {
|
||||
};
|
||||
PrctlCmd::PR_GET_NAME(buf_checked)
|
||||
}
|
||||
PR_SET_TIMERSLACK => PrctlCmd::PR_SET_TIMERSLACK(arg2),
|
||||
PR_GET_TIMERSLACK => PrctlCmd::PR_GET_TIMERSLACK(()),
|
||||
_ => {
|
||||
debug!("prctl cmd num: {}", cmd);
|
||||
return_errno!(EINVAL, "unsupported prctl command");
|
||||
@ -59,7 +63,17 @@ pub fn do_prctl(cmd: PrctlCmd) -> Result<isize> {
|
||||
let name = current.name();
|
||||
c_buf.copy_from_slice(name.as_slice());
|
||||
}
|
||||
_ => warn!("Prctl command not supported"),
|
||||
PrctlCmd::PR_SET_TIMERSLACK(nanoseconds) => {
|
||||
return_errno!(
|
||||
EINVAL,
|
||||
"Setting timer slack for different libos process is not supported"
|
||||
);
|
||||
}
|
||||
PrctlCmd::PR_GET_TIMERSLACK(()) => {
|
||||
let nanoseconds = (*TIMERSLACK).to_u32();
|
||||
return Ok(nanoseconds as isize);
|
||||
}
|
||||
_ => return_errno!(EINVAL, "Prctl command not supported"),
|
||||
}
|
||||
|
||||
Ok(0)
|
||||
|
@ -175,7 +175,7 @@ pub fn do_futex(
|
||||
|
||||
pub fn do_prctl(option: i32, arg2: u64, arg3: u64, arg4: u64, arg5: u64) -> Result<isize> {
|
||||
let prctl_cmd = super::prctl::PrctlCmd::from_raw(option, arg2, arg3, arg4, arg5)?;
|
||||
super::prctl::do_prctl(prctl_cmd).map(|_| 0)
|
||||
super::prctl::do_prctl(prctl_cmd)
|
||||
}
|
||||
|
||||
pub fn do_arch_prctl(code: u32, addr: *mut usize) -> Result<isize> {
|
||||
|
@ -1,3 +1,4 @@
|
||||
use self::timer_slack::*;
|
||||
use super::*;
|
||||
use core::convert::TryFrom;
|
||||
use process::pid_t;
|
||||
@ -8,6 +9,7 @@ use std::{fmt, u64};
|
||||
use syscall::SyscallNum;
|
||||
|
||||
mod profiler;
|
||||
pub mod timer_slack;
|
||||
pub mod up_time;
|
||||
|
||||
pub use profiler::ThreadProfiler;
|
||||
@ -182,7 +184,7 @@ pub fn do_nanosleep(req: ×pec_t, rem: Option<&mut timespec_t>) -> Result<()
|
||||
assert!(sgx_status == sgx_status_t::SGX_SUCCESS);
|
||||
assert!(ret == 0 || libc::errno() == Errno::EINTR as i32);
|
||||
if ret != 0 {
|
||||
assert!(u_rem.as_duration() <= req.as_duration());
|
||||
assert!(u_rem.as_duration() <= req.as_duration() + (*TIMERSLACK).to_duration());
|
||||
if let Some(rem) = rem {
|
||||
*rem = u_rem;
|
||||
}
|
||||
|
47
src/libos/src/time/timer_slack.rs
Normal file
47
src/libos/src/time/timer_slack.rs
Normal file
@ -0,0 +1,47 @@
|
||||
use super::*;
|
||||
use std::time::Duration;
|
||||
|
||||
pub struct TimerSlack {
|
||||
nanoseconds: u32,
|
||||
}
|
||||
|
||||
impl TimerSlack {
|
||||
pub fn new(nanoseconds: u32) -> Result<Self> {
|
||||
let timerslack = Self { nanoseconds };
|
||||
timerslack.validate()?;
|
||||
Ok(timerslack)
|
||||
}
|
||||
|
||||
pub fn validate(&self) -> Result<()> {
|
||||
// Timer slack bigger than 1ms is considered invalid here. The kernel default timer slack is 50us.
|
||||
if self.nanoseconds < 1_000_000 {
|
||||
Ok(())
|
||||
} else {
|
||||
return_errno!(EINVAL, "invalid value for TimerSlack");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_u32(&self) -> u32 {
|
||||
self.nanoseconds
|
||||
}
|
||||
|
||||
pub fn to_duration(&self) -> Duration {
|
||||
Duration::from_nanos(self.to_u32() as u64)
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref TIMERSLACK: TimerSlack =
|
||||
do_get_timerslack().unwrap_or(TimerSlack::new(50_000).unwrap()); // Use kernel default timer slack 50us.
|
||||
}
|
||||
|
||||
fn do_get_timerslack() -> Result<TimerSlack> {
|
||||
extern "C" {
|
||||
fn occlum_ocall_get_timerslack(nanosecond: *mut i32) -> sgx_status_t;
|
||||
}
|
||||
let mut timer_slack: i32 = 0;
|
||||
let sgx_status = unsafe { occlum_ocall_get_timerslack(&mut timer_slack as *mut i32) };
|
||||
assert!(sgx_status == sgx_status_t::SGX_SUCCESS);
|
||||
|
||||
TimerSlack::new(timer_slack as u32)
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/prctl.h>
|
||||
#include "ocalls.h"
|
||||
|
||||
void occlum_ocall_gettimeofday(struct timeval *tv) {
|
||||
@ -35,3 +36,8 @@ void occlum_ocall_rdtsc(uint32_t *low, uint32_t *high) {
|
||||
*low = (uint32_t)rax;
|
||||
*high = (uint32_t)rdx;
|
||||
}
|
||||
|
||||
void occlum_ocall_get_timerslack(int *timer_slack) {
|
||||
int nanoseconds = prctl(PR_GET_TIMERSLACK, 0, 0, 0, 0);
|
||||
*timer_slack = nanoseconds;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <occlum_pal_api.h>
|
||||
#include <sys/prctl.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
// Parse arguments
|
||||
|
@ -126,6 +126,19 @@ static int test_prctl_get_default_thread_name(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_prctl_get_timerslack(void) {
|
||||
int nanoseconds = prctl(PR_GET_TIMERSLACK, 0, 0, 0, 0);
|
||||
if (nanoseconds < 0) {
|
||||
THROW_ERROR("test prctl get timer slack failed");
|
||||
};
|
||||
printf("timer slack = %d ns\n", nanoseconds);
|
||||
// Kernel default timer slack is 50us
|
||||
if (nanoseconds != 50000) {
|
||||
THROW_ERROR("timer slack is not 50us");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Test suite main
|
||||
// ============================================================================
|
||||
@ -133,6 +146,7 @@ static test_case_t test_cases[] = {
|
||||
TEST_CASE(test_prctl_set_get_long_name), // over 16 bytes
|
||||
TEST_CASE(test_prctl_set_get_normal_name),
|
||||
TEST_CASE(test_prctl_get_default_thread_name),
|
||||
TEST_CASE(test_prctl_get_timerslack),
|
||||
};
|
||||
|
||||
int main() {
|
||||
|
Loading…
Reference in New Issue
Block a user