From 0e8efe94f7be45b19b5808cd4eeeb42a31d921a5 Mon Sep 17 00:00:00 2001 From: SteveLauC Date: Sun, 7 Jan 2024 10:12:06 +0800 Subject: [PATCH] feat: clock_nanosleep() (#2277) --- changelog/2277.added.md | 1 + src/time.rs | 52 +++++++++++++++++++++++++++++++++++++++++ test/test_time.rs | 25 ++++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 changelog/2277.added.md diff --git a/changelog/2277.added.md b/changelog/2277.added.md new file mode 100644 index 0000000000..0b6e8611c4 --- /dev/null +++ b/changelog/2277.added.md @@ -0,0 +1 @@ +Add `clock_nanosleep()` diff --git a/src/time.rs b/src/time.rs index 96e84900dd..72915c25df 100644 --- a/src/time.rs +++ b/src/time.rs @@ -199,3 +199,55 @@ pub fn clock_getcpuclockid(pid: Pid) -> Result { Err(Errno::from_i32(ret)) } } + +#[cfg(any( + linux_android, + solarish, + freebsdlike, + target_os = "netbsd", + target_os = "hurd", + target_os = "aix" +))] +libc_bitflags! { + /// Flags that are used for arming the timer. + pub struct ClockNanosleepFlags: libc::c_int { + TIMER_ABSTIME; + } +} + +/// Suspend execution of this thread for the amount of time specified by `request` +/// and measured against the clock speficied by `clock_id`. If `flags` is +/// `TIMER_ABSTIME`, this function will suspend execution until the time value of +/// clock_id reaches the absolute time specified by `request`. If a signal is caught +/// by a signal-catching function, or a signal causes the process to terminate, +/// this sleep is interrrupted. +/// +/// see also [man 3 clock_nanosleep](https://pubs.opengroup.org/onlinepubs/009695399/functions/clock_nanosleep.html) +#[cfg(any( + linux_android, + solarish, + freebsdlike, + target_os = "netbsd", + target_os = "hurd", + target_os = "aix" +))] +pub fn clock_nanosleep( + clock_id: ClockId, + flags: ClockNanosleepFlags, + request: &TimeSpec, +) -> Result { + let mut remain = TimeSpec::new(0, 0); + let ret = unsafe { + libc::clock_nanosleep( + clock_id.as_raw(), + flags.bits(), + request.as_ref() as *const _, + remain.as_mut() as *mut _, + ) + }; + if ret == 0 { + Ok(remain) + } else { + Err(Errno::from_i32(ret)) + } +} diff --git a/test/test_time.rs b/test/test_time.rs index 6d7dfbedc0..64c8161dbf 100644 --- a/test/test_time.rs +++ b/test/test_time.rs @@ -39,3 +39,28 @@ pub fn test_clock_id_pid_cpu_clock_id() { .unwrap() .unwrap(); } + +#[cfg(any( + linux_android, + solarish, + freebsdlike, + target_os = "netbsd", + target_os = "hurd", + target_os = "aix" +))] +#[test] +pub fn test_clock_nanosleep() { + use nix::{ + sys::time::{TimeSpec, TimeValLike}, + time::{clock_nanosleep, ClockNanosleepFlags}, + }; + + let sleep_time = TimeSpec::microseconds(1); + let res = clock_nanosleep( + ClockId::CLOCK_MONOTONIC, + ClockNanosleepFlags::empty(), + &sleep_time, + ); + let expected = TimeSpec::microseconds(0); + assert_eq!(res, Ok(expected)); +}