Skip to content

Commit 0b16e15

Browse files
committed
implement clock_gettime, clock_getres, clock_settime
1 parent 38de042 commit 0b16e15

File tree

6 files changed

+160
-0
lines changed

6 files changed

+160
-0
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
2121
([#1058](https://github.com/nix-rust/nix/pull/1058))
2222
- Add `renameat`.
2323
([#1097](https://github.com/nix-rust/nix/pull/1097))
24+
- Add `clock_gettime`, `clock_settime`, `clock_getres`
25+
([#1100](https://github.com/nix-rust/nix/pull/1100))
2426

2527
### Changed
2628
- Support for `ifaddrs` now present when building for Android.

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ pub mod poll;
6666
pub mod pty;
6767
pub mod sched;
6868
pub mod sys;
69+
pub mod time;
6970
// This can be implemented for other platforms as soon as libc
7071
// provides bindings for them.
7172
#[cfg(all(target_os = "linux",

src/sys/time.rs

+6
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ impl AsRef<timespec> for TimeSpec {
6767
}
6868
}
6969

70+
impl From<timespec> for TimeSpec {
71+
fn from(ts: timespec) -> Self {
72+
TimeSpec(ts)
73+
}
74+
}
75+
7076
impl Ord for TimeSpec {
7177
// The implementation of cmp is simplified by assuming that the struct is
7278
// normalized. That is, tv_nsec must always be within [0, 1_000_000_000)

src/time.rs

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
use sys::time::TimeSpec;
2+
use {Result, Errno};
3+
use libc;
4+
5+
libc_enum! {
6+
#[repr(i32)]
7+
pub enum ClockId {
8+
#[cfg(any(target_os = "fuchsia",
9+
target_os = "linux",
10+
target_os = "android",
11+
target_os = "emscripten"))]
12+
CLOCK_BOOTTIME,
13+
#[cfg(any(target_os = "fuchsia",
14+
target_os = "linux",
15+
target_os = "android",
16+
target_os = "emscripten"))]
17+
CLOCK_BOOTTIME_ALARM,
18+
CLOCK_MONOTONIC,
19+
#[cfg(any(target_os = "fuchsia",
20+
target_os = "linux",
21+
target_os = "android",
22+
target_os = "emscripten"))]
23+
CLOCK_MONOTONIC_COARSE,
24+
#[cfg(any(target_os = "freebsd",
25+
target_os = "dragonfly"))]
26+
CLOCK_MONOTONIC_FAST,
27+
#[cfg(any(target_os = "freebsd",
28+
target_os = "dragonfly"))]
29+
CLOCK_MONOTONIC_PRECISE,
30+
#[cfg(any(target_os = "fuchsia",
31+
target_os = "linux",
32+
target_os = "android",
33+
target_os = "emscripten"))]
34+
CLOCK_MONOTONIC_RAW,
35+
#[cfg(any(target_os = "fuchsia",
36+
target_env = "uclibc",
37+
target_os = "macos",
38+
target_os = "ios",
39+
target_os = "freebsd",
40+
target_os = "dragonfly",
41+
target_os = "linux",
42+
target_os = "android",
43+
target_os = "emscripten"))]
44+
CLOCK_PROCESS_CPUTIME_ID,
45+
#[cfg(any(target_os = "freebsd",
46+
target_os = "dragonfly"))]
47+
CLOCK_PROF,
48+
CLOCK_REALTIME,
49+
#[cfg(any(target_os = "fuchsia",
50+
target_os = "linux",
51+
target_os = "android",
52+
target_os = "emscripten"))]
53+
CLOCK_REALTIME_ALARM,
54+
#[cfg(any(target_os = "fuchsia",
55+
target_os = "linux",
56+
target_os = "android",
57+
target_os = "emscripten"))]
58+
CLOCK_REALTIME_COARSE,
59+
#[cfg(any(target_os = "freebsd",
60+
target_os = "dragonfly"))]
61+
CLOCK_REALTIME_FAST,
62+
#[cfg(any(target_os = "freebsd",
63+
target_os = "dragonfly"))]
64+
CLOCK_REALTIME_PRECISE,
65+
#[cfg(any(target_os = "freebsd",
66+
target_os = "dragonfly"))]
67+
CLOCK_SECOND,
68+
#[cfg(any(target_os = "fuchsia",
69+
target_os = "emscripten",
70+
all(target_os = "linux", target_env = "musl")))]
71+
CLOCK_SGI_CYCLE,
72+
#[cfg(any(target_os = "fuchsia",
73+
target_os = "emscripten",
74+
all(target_os = "linux", target_env = "musl")))]
75+
CLOCK_TAI,
76+
#[cfg(any(target_os = "fuchsia",
77+
target_os = "ios",
78+
target_os = "macos",
79+
target_os = "freebsd",
80+
target_os = "dragonfly",
81+
target_os = "linux",
82+
target_os = "android",
83+
target_os = "emscripten",
84+
target_env = "uclibc"))]
85+
CLOCK_THREAD_CPUTIME_ID,
86+
#[cfg(any(target_os = "freebsd",
87+
target_os = "dragonfly"))]
88+
CLOCK_UPTIME,
89+
#[cfg(any(target_os = "freebsd",
90+
target_os = "dragonfly"))]
91+
CLOCK_UPTIME_FAST,
92+
#[cfg(any(target_os = "freebsd",
93+
target_os = "dragonfly"))]
94+
CLOCK_UPTIME_PRECISE,
95+
#[cfg(any(target_os = "freebsd",
96+
target_os = "dragonfly"))]
97+
CLOCK_VIRTUAL,
98+
}
99+
}
100+
101+
pub fn clock_getres(clk_id: ClockId) -> Result<TimeSpec> {
102+
let mut c_time = libc::timespec {tv_sec: 0, tv_nsec: 0};
103+
let res = unsafe { libc::clock_getres(clk_id as libc::c_int, &mut c_time) };
104+
Errno::result(res)?;
105+
Ok(TimeSpec::from(c_time))
106+
}
107+
108+
pub fn clock_gettime(clk_id: ClockId) -> Result<TimeSpec> {
109+
let mut c_time = libc::timespec {tv_sec: 0, tv_nsec: 0};
110+
let res = unsafe { libc::clock_gettime(clk_id as libc::c_int, &mut c_time) };
111+
Errno::result(res)?;
112+
Ok(TimeSpec::from(c_time))
113+
}
114+
115+
pub fn clock_settime(clk_id: ClockId, timespec: TimeSpec) -> Result<()> {
116+
let res = unsafe { libc::clock_settime(clk_id as libc::c_int, timespec.as_ref()) };
117+
Errno::result(res).map(drop)
118+
}

test/test.rs

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ mod test_pty;
8686
target_os = "macos"))]
8787
mod test_sendfile;
8888
mod test_stat;
89+
mod test_time;
8990
mod test_unistd;
9091

9192
use std::os::unix::io::RawFd;

test/test_time.rs

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
use nix::time::{clock_getres, clock_gettime, clock_settime, ClockId};
2+
use nix::Error;
3+
use nix::errno::Errno;
4+
use nix::sys::time::TimeSpec;
5+
use libc::timespec;
6+
7+
#[test]
8+
pub fn test_clock_getres() {
9+
clock_getres(ClockId::CLOCK_REALTIME).unwrap();
10+
}
11+
12+
#[test]
13+
pub fn test_clock_gettime() {
14+
let res1 = clock_gettime(ClockId::CLOCK_REALTIME).unwrap();
15+
let res2 = clock_gettime(ClockId::CLOCK_REALTIME).unwrap();
16+
assert!(res1 < res2);
17+
}
18+
19+
#[test]
20+
pub fn test_clock_settime() {
21+
require_capability!(CAP_SYS_TIME);
22+
let ts = TimeSpec::from(timespec{tv_sec: 10000000, tv_nsec: 100});
23+
let res = clock_settime(ClockId::CLOCK_REALTIME, ts).unwrap();
24+
}
25+
26+
#[test]
27+
pub fn test_clock_settime_err() {
28+
require_capability!(CAP_SYS_TIME);
29+
let ts = TimeSpec::from(timespec{tv_sec: 10000000, tv_nsec: 100});
30+
let err = clock_settime(ClockId::CLOCK_MONOTONIC, ts).unwrap_err();
31+
assert_eq!(err, Error::Sys(Errno::EINVAL));
32+
}

0 commit comments

Comments
 (0)