Skip to content

Commit

Permalink
implement clock_gettime, clock_getres, clock_settime
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinwern committed Jul 24, 2019
1 parent 38de042 commit 0b16e15
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
([#1058](https://github.com/nix-rust/nix/pull/1058))
- Add `renameat`.
([#1097](https://github.com/nix-rust/nix/pull/1097))
- Add `clock_gettime`, `clock_settime`, `clock_getres`
([#1100](https://github.com/nix-rust/nix/pull/1100))

### Changed
- Support for `ifaddrs` now present when building for Android.
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,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
118 changes: 118 additions & 0 deletions src/time.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
use sys::time::TimeSpec;
use {Result, Errno};
use libc;

libc_enum! {
#[repr(i32)]
pub enum ClockId {
#[cfg(any(target_os = "fuchsia",
target_os = "linux",
target_os = "android",
target_os = "emscripten"))]
CLOCK_BOOTTIME,
#[cfg(any(target_os = "fuchsia",
target_os = "linux",
target_os = "android",
target_os = "emscripten"))]
CLOCK_BOOTTIME_ALARM,
CLOCK_MONOTONIC,
#[cfg(any(target_os = "fuchsia",
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",
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",
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",
target_os = "linux",
target_os = "android",
target_os = "emscripten"))]
CLOCK_REALTIME_ALARM,
#[cfg(any(target_os = "fuchsia",
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",
target_os = "emscripten",
all(target_os = "linux", target_env = "musl")))]
CLOCK_SGI_CYCLE,
#[cfg(any(target_os = "fuchsia",
target_os = "emscripten",
all(target_os = "linux", target_env = "musl")))]
CLOCK_TAI,
#[cfg(any(target_os = "fuchsia",
target_os = "ios",
target_os = "macos",
target_os = "freebsd",
target_os = "dragonfly",
target_os = "linux",
target_os = "android",
target_os = "emscripten",
target_env = "uclibc"))]
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 = libc::timespec {tv_sec: 0, tv_nsec: 0};
let res = unsafe { libc::clock_getres(clk_id as libc::c_int, &mut c_time) };
Errno::result(res)?;
Ok(TimeSpec::from(c_time))
}

pub fn clock_gettime(clk_id: ClockId) -> Result<TimeSpec> {
let mut c_time = libc::timespec {tv_sec: 0, tv_nsec: 0};
let res = unsafe { libc::clock_gettime(clk_id as libc::c_int, &mut c_time) };
Errno::result(res)?;
Ok(TimeSpec::from(c_time))
}

pub fn clock_settime(clk_id: ClockId, timespec: TimeSpec) -> Result<()> {
let res = unsafe { libc::clock_settime(clk_id as libc::c_int, 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 @@ -86,6 +86,7 @@ mod test_pty;
target_os = "macos"))]
mod test_sendfile;
mod test_stat;
mod test_time;
mod test_unistd;

use std::os::unix::io::RawFd;
Expand Down
32 changes: 32 additions & 0 deletions test/test_time.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use nix::time::{clock_getres, clock_gettime, clock_settime, ClockId};
use nix::Error;
use nix::errno::Errno;
use nix::sys::time::TimeSpec;
use libc::timespec;

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

#[test]
pub fn test_clock_gettime() {
let res1 = clock_gettime(ClockId::CLOCK_REALTIME).unwrap();
let res2 = clock_gettime(ClockId::CLOCK_REALTIME).unwrap();
assert!(res1 < res2);
}

#[test]
pub fn test_clock_settime() {
require_capability!(CAP_SYS_TIME);
let ts = TimeSpec::from(timespec{tv_sec: 10000000, tv_nsec: 100});
let res = clock_settime(ClockId::CLOCK_REALTIME, ts).unwrap();
}

#[test]
pub fn test_clock_settime_err() {
require_capability!(CAP_SYS_TIME);
let ts = TimeSpec::from(timespec{tv_sec: 10000000, tv_nsec: 100});
let err = clock_settime(ClockId::CLOCK_MONOTONIC, ts).unwrap_err();
assert_eq!(err, Error::Sys(Errno::EINVAL));
}

0 comments on commit 0b16e15

Please sign in to comment.