Skip to content

Commit

Permalink
Merge #1100
Browse files Browse the repository at this point in the history
1100: implement clock_gettime, clock_getres, clock_settime r=asomers a=kevinwern

See: https://pubs.opengroup.org/onlinepubs/007908799/xsh/clock_settime.html
Again related to: https://github.com/CraneStation/wasi-common/issues/16

Conditional inclusion of clock IDs based on looking through libc.

Co-authored-by: Kevin Wern <[email protected]>
  • Loading branch information
bors[bot] and kevinwern authored Dec 22, 2019
2 parents 1282815 + c9b4a36 commit d2aa08b
Show file tree
Hide file tree
Showing 6 changed files with 206 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased] - ReleaseDate
### Added
- Add `clock_gettime`, `clock_settime`, `clock_getres`
([#1100](https://github.com/nix-rust/nix/pull/1100))

## [0.16.0] - 1 December 2019
### Added
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ pub mod poll;
pub mod pty;
pub mod sched;
pub mod sys;
pub mod time;
// This can be implemented for other platforms as soon as libc
// provides bindings for them.
#[cfg(all(target_os = "linux",
Expand Down
6 changes: 6 additions & 0 deletions src/sys/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ impl AsRef<timespec> for TimeSpec {
}
}

impl From<timespec> for TimeSpec {
fn from(ts: timespec) -> Self {
TimeSpec(ts)
}
}

impl Ord for TimeSpec {
// The implementation of cmp is simplified by assuming that the struct is
// normalized. That is, tv_nsec must always be within [0, 1_000_000_000)
Expand Down
184 changes: 184 additions & 0 deletions src/time.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
use sys::time::TimeSpec;
use std::mem::MaybeUninit;
use {Result, Errno};
use libc;

libc_enum! {
#[cfg_attr(any(
target_env = "uclibc",
target_os = "fuchsia",
target_os = "redox",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "haiku",
all(not(target_env = "newlib"),
any(target_os = "linux",
target_os = "android",
target_os = "emscripten",
target_os = "solaris",
target_os = "illumos")),
), repr(i32))]
#[cfg_attr(any(
all(target_env = "newlib", target_arch = "arm"),
target_os = "macos",
target_os = "ios",
), repr(u32))]
#[cfg_attr(any(
all(target_env = "newlib", target_arch = "aarch64"),
all(not(any(target_env = "newlib", target_env = "uclibc")), target_os = "hermit"),
target_os = "dragonfly",
), repr(u64))]
pub enum ClockId {
#[cfg(any(target_os = "fuchsia",
all(not(any(target_env = "uclibc",
target_env = "newlib")),
any(target_os = "linux",
target_os = "android",
target_os = "emscripten"),
)
))]
CLOCK_BOOTTIME,
#[cfg(any(target_os = "fuchsia",
all(not(any(target_env = "uclibc",
target_env = "newlib")),
any(target_os = "linux",
target_os = "android",
target_os = "emscripten"))))]
CLOCK_BOOTTIME_ALARM,
CLOCK_MONOTONIC,
#[cfg(any(target_os = "fuchsia",
all(not(any(target_env = "uclibc",
target_env = "newlib")),
any(target_os = "linux",
target_os = "android",
target_os = "emscripten"))))]
CLOCK_MONOTONIC_COARSE,
#[cfg(any(target_os = "freebsd",
target_os = "dragonfly"))]
CLOCK_MONOTONIC_FAST,
#[cfg(any(target_os = "freebsd",
target_os = "dragonfly"))]
CLOCK_MONOTONIC_PRECISE,
#[cfg(any(target_os = "fuchsia",
all(not(any(target_env = "uclibc",
target_env = "newlib")),
any(target_os = "linux",
target_os = "android",
target_os = "emscripten"))))]
CLOCK_MONOTONIC_RAW,
#[cfg(any(target_os = "fuchsia",
target_env = "uclibc",
target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly",
all(not(target_env = "newlib"),
any(target_os = "linux",
target_os = "android",
target_os = "emscripten"))))]
CLOCK_PROCESS_CPUTIME_ID,
#[cfg(any(target_os = "freebsd",
target_os = "dragonfly"))]
CLOCK_PROF,
CLOCK_REALTIME,
#[cfg(any(target_os = "fuchsia",
all(not(any(target_env = "uclibc",
target_env = "newlib")),
any(target_os = "linux",
target_os = "android",
target_os = "emscripten"))))]
CLOCK_REALTIME_ALARM,
#[cfg(any(target_os = "fuchsia",
all(not(any(target_env = "uclibc",
target_env = "newlib")),
any(target_os = "linux",
target_os = "android",
target_os = "emscripten"))))]
CLOCK_REALTIME_COARSE,
#[cfg(any(target_os = "freebsd",
target_os = "dragonfly"))]
CLOCK_REALTIME_FAST,
#[cfg(any(target_os = "freebsd",
target_os = "dragonfly"))]
CLOCK_REALTIME_PRECISE,
#[cfg(any(target_os = "freebsd",
target_os = "dragonfly"))]
CLOCK_SECOND,
#[cfg(any(target_os = "fuchsia",
all(not(any(target_env = "uclibc", target_env = "newlib")),
any(target_os = "emscripten",
all(target_os = "linux", target_env = "musl")))))]
CLOCK_SGI_CYCLE,
#[cfg(any(target_os = "fuchsia",
all(not(any(target_env = "uclibc", target_env = "newlib")),
any(target_os = "emscripten",
all(target_os = "linux", target_env = "musl")))))]
CLOCK_TAI,
#[cfg(any(
target_env = "uclibc",
target_os = "fuchsia",
target_os = "ios",
target_os = "macos",
target_os = "freebsd",
target_os = "dragonfly",
all(
not(target_env = "newlib"),
any(
target_os = "linux",
target_os = "android",
target_os = "emscripten",
),
),
)
)]
CLOCK_THREAD_CPUTIME_ID,
#[cfg(any(target_os = "freebsd",
target_os = "dragonfly"))]
CLOCK_UPTIME,
#[cfg(any(target_os = "freebsd",
target_os = "dragonfly"))]
CLOCK_UPTIME_FAST,
#[cfg(any(target_os = "freebsd",
target_os = "dragonfly"))]
CLOCK_UPTIME_PRECISE,
#[cfg(any(target_os = "freebsd",
target_os = "dragonfly"))]
CLOCK_VIRTUAL,
}
}

pub fn clock_getres(clk_id: ClockId) -> Result<TimeSpec> {
let mut c_time: MaybeUninit<libc::timespec> = MaybeUninit::uninit();
let errno = unsafe { libc::clock_getres(clk_id as libc::clockid_t, c_time.as_mut_ptr()) };
Errno::result(errno)?;
let res = unsafe { c_time.assume_init() };
Ok(TimeSpec::from(res))
}

pub fn clock_gettime(clk_id: ClockId) -> Result<TimeSpec> {
let mut c_time: MaybeUninit<libc::timespec> = MaybeUninit::uninit();
let errno = unsafe { libc::clock_gettime(clk_id as libc::clockid_t, c_time.as_mut_ptr()) };
Errno::result(errno)?;
let res = unsafe { c_time.assume_init() };
Ok(TimeSpec::from(res))
}

#[cfg(not(
any(
target_os = "macos",
target_os = "ios",
all(
not(any(target_env = "uclibc", target_env = "newlibc")),
any(
target_os = "redox",
target_os = "hermit",
),
),
)
)
)]
pub fn clock_settime(clk_id: ClockId, timespec: TimeSpec) -> Result<()> {
let res = unsafe { libc::clock_settime(clk_id as libc::clockid_t, timespec.as_ref()) };
Errno::result(res).map(drop)
}
1 change: 1 addition & 0 deletions test/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ mod test_sched;
target_os = "macos"))]
mod test_sendfile;
mod test_stat;
mod test_time;
mod test_unistd;

use std::os::unix::io::RawFd;
Expand Down
11 changes: 11 additions & 0 deletions test/test_time.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use nix::time::{clock_getres, clock_gettime, ClockId};

#[test]
pub fn test_clock_getres() {
assert!(clock_getres(ClockId::CLOCK_REALTIME).is_ok());
}

#[test]
pub fn test_clock_gettime() {
assert!(clock_gettime(ClockId::CLOCK_REALTIME).is_ok());
}

0 comments on commit d2aa08b

Please sign in to comment.