Add support for clock_nanosleep

Also replace nanosleep implementation with clock_nanosleep
This commit is contained in:
Hui, Chunyang 2022-02-22 05:58:11 +00:00 committed by Zongmin.Gu
parent 63db3e340c
commit ffaccedf95
4 changed files with 73 additions and 16 deletions

@ -141,7 +141,8 @@ enclave {
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(
int occlum_ocall_clock_nanosleep(
clockid_t clockid, int flags,
[in] const struct timespec* req,
[out] struct timespec* rem
) propagate_errno;

@ -318,7 +318,7 @@ macro_rules! process_syscall_table_with_callback {
(ClockSettime = 227) => handle_unsupported(),
(ClockGettime = 228) => do_clock_gettime(clockid: clockid_t, ts_u: *mut timespec_t),
(ClockGetres = 229) => do_clock_getres(clockid: clockid_t, res_u: *mut timespec_t),
(ClockNanosleep = 230) => handle_unsupported(),
(ClockNanosleep = 230) => do_clock_nanosleep(clockid: clockid_t, flags: i32, request: *const timespec_t, remain: *mut timespec_t),
(ExitGroup = 231) => do_exit_group(exit_status: i32, user_context: *mut CpuContext),
(EpollWait = 232) => do_epoll_wait(epfd: c_int, events: *mut libc::epoll_event, maxevents: c_int, timeout: c_int),
(EpollCtl = 233) => do_epoll_ctl(epfd: c_int, op: c_int, fd: c_int, event: *const libc::epoll_event),
@ -885,6 +885,27 @@ fn do_clock_getres(clockid: clockid_t, res_u: *mut timespec_t) -> Result<isize>
Ok(0)
}
fn do_clock_nanosleep(
clockid: clockid_t,
flags: i32,
req_u: *const timespec_t,
rem_u: *mut timespec_t,
) -> Result<isize> {
let req = {
check_ptr(req_u)?;
timespec_t::from_raw_ptr(req_u)?
};
let rem = if !rem_u.is_null() {
check_mut_ptr(rem_u)?;
Some(unsafe { &mut *rem_u })
} else {
None
};
let clockid = time::ClockID::from_raw(clockid)?;
time::do_clock_nanosleep(clockid, flags, &req, rem)?;
Ok(0)
}
// TODO: handle remainder
fn do_nanosleep(req_u: *const timespec_t, rem_u: *mut timespec_t) -> Result<isize> {
let req = {

@ -188,29 +188,63 @@ pub fn do_clock_getres(clockid: ClockID) -> Result<timespec_t> {
Ok(res)
}
pub fn do_nanosleep(req: &timespec_t, rem: Option<&mut timespec_t>) -> Result<()> {
const TIMER_ABSTIME: i32 = 0x01;
pub fn do_clock_nanosleep(
clockid: ClockID,
flags: i32,
req: &timespec_t,
rem: Option<&mut timespec_t>,
) -> Result<()> {
extern "C" {
fn occlum_ocall_nanosleep(
fn occlum_ocall_clock_nanosleep(
ret: *mut i32,
clockid: clockid_t,
flags: i32,
req: *const timespec_t,
rem: *mut timespec_t,
) -> sgx_status_t;
}
unsafe {
let mut ret = 0;
let mut u_rem: timespec_t = timespec_t { sec: 0, nsec: 0 };
let sgx_status = occlum_ocall_nanosleep(&mut ret, req, &mut u_rem);
match clockid {
ClockID::CLOCK_REALTIME
| ClockID::CLOCK_MONOTONIC
| ClockID::CLOCK_BOOTTIME
| ClockID::CLOCK_PROCESS_CPUTIME_ID => {}
ClockID::CLOCK_THREAD_CPUTIME_ID => {
return_errno!(EINVAL, "CLOCK_THREAD_CPUTIME_ID is not a permitted value");
}
_ => {
return_errno!(EOPNOTSUPP, "does not support sleeping against this clockid");
}
}
let sgx_status = unsafe {
occlum_ocall_clock_nanosleep(&mut ret, clockid as clockid_t, flags, req, &mut u_rem)
};
assert!(sgx_status == sgx_status_t::SGX_SUCCESS);
assert!(ret == 0 || libc::errno() == Errno::EINTR as i32);
assert!(ret == 0 || ret == Errno::EINTR as i32);
if ret != 0 {
assert!(u_rem.as_duration() <= req.as_duration() + (*TIMERSLACK).to_duration());
// rem is only valid if TIMER_ABSTIME flag is not set
if flags != TIMER_ABSTIME {
if let Some(rem) = rem {
*rem = u_rem;
}
}
return_errno!(EINTR, "sleep interrupted");
}
}
Ok(())
return Ok(());
}
pub fn do_nanosleep(req: &timespec_t, rem: Option<&mut timespec_t>) -> Result<()> {
// POSIX.1 specifies that nanosleep() should measure time against
// the CLOCK_REALTIME clock. However, Linux measures the time using
// the CLOCK_MONOTONIC clock.
// Here we follow the POSIX.1
let clock_id = ClockID::CLOCK_REALTIME;
return do_clock_nanosleep(clock_id, 0, req, rem);
}
pub fn do_thread_getcpuclock() -> Result<timespec_t> {

@ -16,8 +16,9 @@ void occlum_ocall_clock_getres(int clockid, struct timespec *res) {
clock_getres(clockid, res);
}
int occlum_ocall_nanosleep(const struct timespec *req, struct timespec *rem) {
return nanosleep(req, rem);
int occlum_ocall_clock_nanosleep(clockid_t clockid, int flags, const struct timespec *req,
struct timespec *rem) {
return clock_nanosleep(clockid, flags, req, rem);
}
int occlum_ocall_thread_getcpuclock(struct timespec *tp) {