Add clock_getres syscall

This commit is contained in:
LI Qing 2020-06-02 07:28:03 +00:00 committed by Tate, Hongliang Tian
parent 70d3991ff5
commit c8e3e0ffc6
5 changed files with 63 additions and 1 deletions

@ -97,6 +97,7 @@ enclave {
void occlum_ocall_gettimeofday([out] struct timeval* tv);
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_nanosleep([in] const struct timespec* req);

@ -306,7 +306,7 @@ macro_rules! process_syscall_table_with_callback {
(TimerDelete = 226) => handle_unsupported(),
(ClockSettime = 227) => handle_unsupported(),
(ClockGettime = 228) => do_clock_gettime(clockid: clockid_t, ts_u: *mut timespec_t),
(ClockGetres = 229) => handle_unsupported(),
(ClockGetres = 229) => do_clock_getres(clockid: clockid_t, res_u: *mut timespec_t),
(ClockNanosleep = 230) => handle_unsupported(),
(ExitGroup = 231) => do_exit_group(exit_status: i32),
(EpollWait = 232) => do_epoll_wait(epfd: c_int, events: *mut libc::epoll_event, maxevents: c_int, timeout: c_int),
@ -775,6 +775,19 @@ fn do_clock_gettime(clockid: clockid_t, ts_u: *mut timespec_t) -> Result<isize>
Ok(0)
}
fn do_clock_getres(clockid: clockid_t, res_u: *mut timespec_t) -> Result<isize> {
if res_u.is_null() {
return Ok(0);
}
check_mut_ptr(res_u)?;
let clockid = time::ClockID::from_raw(clockid)?;
let res = time::do_clock_getres(clockid)?;
unsafe {
*res_u = res;
}
Ok(0)
}
// TODO: handle remainder
fn do_nanosleep(req_u: *const timespec_t, rem_u: *mut timespec_t) -> Result<isize> {
check_ptr(req_u)?;

@ -137,6 +137,28 @@ pub fn do_clock_gettime(clockid: ClockID) -> Result<timespec_t> {
Ok(tv)
}
pub fn do_clock_getres(clockid: ClockID) -> Result<timespec_t> {
extern "C" {
fn occlum_ocall_clock_getres(clockid: clockid_t, res: *mut timespec_t) -> sgx_status_t;
}
let mut res: timespec_t = Default::default();
unsafe {
occlum_ocall_clock_getres(clockid as clockid_t, &mut res as *mut timespec_t);
}
let validate_resolution = |res: &timespec_t| -> Result<()> {
// The resolution can be ranged from 1 nanosecond to a few milliseconds
if res.sec == 0 && res.nsec > 0 && res.nsec < 1_000_000_000 {
Ok(())
} else {
return_errno!(EINVAL, "invalid value for resolution");
}
};
// do sanity check
validate_resolution(&res).expect("ocall returned invalid resolution");
Ok(res)
}
pub fn do_nanosleep(req: &timespec_t) -> Result<()> {
extern "C" {
fn occlum_ocall_nanosleep(req: *const timespec_t) -> sgx_status_t;

@ -10,6 +10,10 @@ void occlum_ocall_clock_gettime(int clockid, struct timespec *tp) {
clock_gettime(clockid, tp);
}
void occlum_ocall_clock_getres(int clockid, struct timespec *res) {
clock_getres(clockid, res);
}
void occlum_ocall_nanosleep(const struct timespec *req) {
nanosleep(req, NULL);
}

@ -29,6 +29,27 @@ int test_clock_gettime() {
return 0;
}
// ============================================================================
// Test cases for clock_getres
// ============================================================================
int test_clock_getres() {
struct timespec res;
if (clock_getres(CLOCK_REALTIME, &res)) {
THROW_ERROR("clock_getres(CLOCK_REALTIME, ...) failed");
}
if (clock_getres(CLOCK_MONOTONIC, &res)) {
THROW_ERROR("clock_getres(CLOCK_MONOTONIC, ...) failed");
}
if (clock_getres(CLOCK_MONOTONIC_COARSE, &res)) {
THROW_ERROR("clock_getres(CLOCK_MONOTONIC_COARSE, ...) failed");
}
if (clock_getres(CLOCK_REALTIME, NULL)) {
THROW_ERROR("clock_getres(CLOCK_REALTIME, NULL) failed");
}
return 0;
}
// ============================================================================
// Test suite
// ============================================================================
@ -36,6 +57,7 @@ int test_clock_gettime() {
static test_case_t test_cases[] = {
TEST_CASE(test_gettimeofday),
TEST_CASE(test_clock_gettime),
TEST_CASE(test_clock_getres),
};
int main() {