summaryrefslogtreecommitdiffstats
path: root/vendor/rustix/src/imp/linux_raw/time
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rustix/src/imp/linux_raw/time')
-rw-r--r--vendor/rustix/src/imp/linux_raw/time/mod.rs3
-rw-r--r--vendor/rustix/src/imp/linux_raw/time/syscalls.rs229
-rw-r--r--vendor/rustix/src/imp/linux_raw/time/types.rs154
3 files changed, 386 insertions, 0 deletions
diff --git a/vendor/rustix/src/imp/linux_raw/time/mod.rs b/vendor/rustix/src/imp/linux_raw/time/mod.rs
new file mode 100644
index 000000000..c42592c4f
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/time/mod.rs
@@ -0,0 +1,3 @@
+#[cfg(any(feature = "time", target_arch = "x86"))]
+pub(crate) mod syscalls;
+pub(crate) mod types;
diff --git a/vendor/rustix/src/imp/linux_raw/time/syscalls.rs b/vendor/rustix/src/imp/linux_raw/time/syscalls.rs
new file mode 100644
index 000000000..93651e499
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/time/syscalls.rs
@@ -0,0 +1,229 @@
+//! linux_raw syscalls supporting `rustix::time`.
+//!
+//! # Safety
+//!
+//! See the `rustix::imp` module documentation for details.
+#![allow(unsafe_code)]
+#![allow(clippy::undocumented_unsafe_blocks)]
+
+#[cfg(feature = "time")]
+use super::super::conv::{by_ref, ret_owned_fd};
+use super::super::conv::{ret, ret_infallible};
+use super::types::ClockId;
+#[cfg(feature = "time")]
+use crate::fd::BorrowedFd;
+use crate::io;
+#[cfg(feature = "time")]
+use crate::io::OwnedFd;
+#[cfg(feature = "time")]
+use crate::time::{Itimerspec, TimerfdClockId, TimerfdFlags, TimerfdTimerFlags};
+use core::mem::MaybeUninit;
+use linux_raw_sys::general::__kernel_timespec;
+#[cfg(feature = "time")]
+#[cfg(target_pointer_width = "32")]
+use {core::convert::TryInto, linux_raw_sys::general::itimerspec as __kernel_old_itimerspec};
+#[cfg(target_pointer_width = "32")]
+use {core::ptr, linux_raw_sys::general::timespec as __kernel_old_timespec};
+
+// `clock_gettime` has special optimizations via the vDSO.
+#[cfg(feature = "time")]
+pub(crate) use super::super::vdso_wrappers::{clock_gettime, clock_gettime_dynamic};
+
+#[inline]
+pub(crate) fn clock_getres(which_clock: ClockId) -> __kernel_timespec {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ let mut result = MaybeUninit::<__kernel_timespec>::uninit();
+ if let Err(err) = ret(syscall!(__NR_clock_getres_time64, which_clock, &mut result)) {
+ // See the comments in `rustix_clock_gettime_via_syscall` about
+ // emulation.
+ debug_assert_eq!(err, io::Errno::NOSYS);
+ clock_getres_old(which_clock, &mut result);
+ }
+ result.assume_init()
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ let mut result = MaybeUninit::<__kernel_timespec>::uninit();
+ ret_infallible(syscall!(__NR_clock_getres, which_clock, &mut result));
+ result.assume_init()
+ }
+}
+
+#[cfg(target_pointer_width = "32")]
+unsafe fn clock_getres_old(which_clock: ClockId, result: &mut MaybeUninit<__kernel_timespec>) {
+ let mut old_result = MaybeUninit::<__kernel_old_timespec>::uninit();
+ ret_infallible(syscall!(__NR_clock_getres, which_clock, &mut old_result));
+ let old_result = old_result.assume_init();
+ // TODO: With Rust 1.55, we can use MaybeUninit::write here.
+ ptr::write(
+ result.as_mut_ptr(),
+ __kernel_timespec {
+ tv_sec: old_result.tv_sec.into(),
+ tv_nsec: old_result.tv_nsec.into(),
+ },
+ );
+}
+
+#[cfg(feature = "time")]
+#[inline]
+pub(crate) fn timerfd_create(clockid: TimerfdClockId, flags: TimerfdFlags) -> io::Result<OwnedFd> {
+ unsafe { ret_owned_fd(syscall!(__NR_timerfd_create, clockid, flags)) }
+}
+
+#[cfg(feature = "time")]
+#[inline]
+pub(crate) fn timerfd_settime(
+ fd: BorrowedFd<'_>,
+ flags: TimerfdTimerFlags,
+ new_value: &Itimerspec,
+) -> io::Result<Itimerspec> {
+ let mut result = MaybeUninit::<Itimerspec>::uninit();
+
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret(syscall!(
+ __NR_timerfd_settime,
+ fd,
+ flags,
+ by_ref(new_value),
+ &mut result
+ ))
+ .map(|()| result.assume_init())
+ }
+
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret(syscall!(
+ __NR_timerfd_settime64,
+ fd,
+ flags,
+ by_ref(new_value),
+ &mut result
+ ))
+ .or_else(|err| {
+ // See the comments in `rustix_clock_gettime_via_syscall` about
+ // emulation.
+ if err == io::Errno::NOSYS {
+ timerfd_settime_old(fd, flags, new_value, &mut result)
+ } else {
+ Err(err)
+ }
+ })
+ .map(|()| result.assume_init())
+ }
+}
+
+#[cfg(feature = "time")]
+#[cfg(target_pointer_width = "32")]
+unsafe fn timerfd_settime_old(
+ fd: BorrowedFd<'_>,
+ flags: TimerfdTimerFlags,
+ new_value: &Itimerspec,
+ result: &mut MaybeUninit<Itimerspec>,
+) -> io::Result<()> {
+ let mut old_result = MaybeUninit::<__kernel_old_itimerspec>::uninit();
+
+ // Convert `new_value` to the old `__kernel_old_itimerspec` format.
+ let old_new_value = __kernel_old_itimerspec {
+ it_interval: __kernel_old_timespec {
+ tv_sec: new_value
+ .it_interval
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ tv_nsec: new_value
+ .it_interval
+ .tv_nsec
+ .try_into()
+ .map_err(|_| io::Errno::INVAL)?,
+ },
+ it_value: __kernel_old_timespec {
+ tv_sec: new_value
+ .it_value
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ tv_nsec: new_value
+ .it_value
+ .tv_nsec
+ .try_into()
+ .map_err(|_| io::Errno::INVAL)?,
+ },
+ };
+ ret(syscall!(
+ __NR_timerfd_settime,
+ fd,
+ flags,
+ by_ref(&old_new_value),
+ &mut old_result
+ ))?;
+ let old_result = old_result.assume_init();
+ // TODO: With Rust 1.55, we can use MaybeUninit::write here.
+ ptr::write(
+ result.as_mut_ptr(),
+ Itimerspec {
+ it_interval: __kernel_timespec {
+ tv_sec: old_result.it_interval.tv_sec.into(),
+ tv_nsec: old_result.it_interval.tv_nsec.into(),
+ },
+ it_value: __kernel_timespec {
+ tv_sec: old_result.it_value.tv_sec.into(),
+ tv_nsec: old_result.it_value.tv_nsec.into(),
+ },
+ },
+ );
+ Ok(())
+}
+
+#[cfg(feature = "time")]
+#[inline]
+pub(crate) fn timerfd_gettime(fd: BorrowedFd<'_>) -> io::Result<Itimerspec> {
+ let mut result = MaybeUninit::<Itimerspec>::uninit();
+
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret(syscall!(__NR_timerfd_gettime, fd, &mut result)).map(|()| result.assume_init())
+ }
+
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret(syscall!(__NR_timerfd_gettime64, fd, &mut result))
+ .or_else(|err| {
+ // See the comments in `rustix_clock_gettime_via_syscall` about
+ // emulation.
+ if err == io::Errno::NOSYS {
+ timerfd_gettime_old(fd, &mut result)
+ } else {
+ Err(err)
+ }
+ })
+ .map(|()| result.assume_init())
+ }
+}
+
+#[cfg(feature = "time")]
+#[cfg(target_pointer_width = "32")]
+unsafe fn timerfd_gettime_old(
+ fd: BorrowedFd<'_>,
+ result: &mut MaybeUninit<Itimerspec>,
+) -> io::Result<()> {
+ let mut old_result = MaybeUninit::<__kernel_old_itimerspec>::uninit();
+ ret(syscall!(__NR_timerfd_gettime, fd, &mut old_result))?;
+ let old_result = old_result.assume_init();
+ // TODO: With Rust 1.55, we can use MaybeUninit::write here.
+ ptr::write(
+ result.as_mut_ptr(),
+ Itimerspec {
+ it_interval: __kernel_timespec {
+ tv_sec: old_result.it_interval.tv_sec.into(),
+ tv_nsec: old_result.it_interval.tv_nsec.into(),
+ },
+ it_value: __kernel_timespec {
+ tv_sec: old_result.it_value.tv_sec.into(),
+ tv_nsec: old_result.it_value.tv_nsec.into(),
+ },
+ },
+ );
+ Ok(())
+}
diff --git a/vendor/rustix/src/imp/linux_raw/time/types.rs b/vendor/rustix/src/imp/linux_raw/time/types.rs
new file mode 100644
index 000000000..5a0fcc6f5
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/time/types.rs
@@ -0,0 +1,154 @@
+use super::super::c;
+use crate::fd::BorrowedFd;
+use bitflags::bitflags;
+
+/// `struct timespec`
+pub type Timespec = linux_raw_sys::general::__kernel_timespec;
+
+/// A type for the `tv_sec` field of [`Timespec`].
+pub type Secs = linux_raw_sys::general::__kernel_time64_t;
+
+/// A type for the `tv_nsec` field of [`Timespec`].
+pub type Nsecs = i64;
+
+/// `struct itimerspec` for use with [`timerfd_gettime`] and
+/// [`timerfd_settime`].
+///
+/// [`timerfd_gettime`]: crate::time::timerfd_gettime
+/// [`timerfd_settime`]: crate::time::timerfd_settime
+pub type Itimerspec = linux_raw_sys::general::__kernel_itimerspec;
+
+/// `CLOCK_*` constants for use with [`clock_gettime`].
+///
+/// These constants are always supported at runtime, so `clock_gettime` never
+/// has to fail with `INVAL` due to an unsupported clock. See
+/// [`DynamicClockId`] for a greater set of clocks, with the caveat that not
+/// all of them are always supported.
+///
+/// [`clock_gettime`]: crate::time::clock_gettime
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+#[repr(u32)]
+#[non_exhaustive]
+pub enum ClockId {
+ /// `CLOCK_REALTIME`
+ Realtime = linux_raw_sys::general::CLOCK_REALTIME,
+
+ /// `CLOCK_MONOTONIC`
+ Monotonic = linux_raw_sys::general::CLOCK_MONOTONIC,
+
+ /// `CLOCK_PROCESS_CPUTIME_ID`
+ ProcessCPUTime = linux_raw_sys::general::CLOCK_PROCESS_CPUTIME_ID,
+
+ /// `CLOCK_THREAD_CPUTIME_ID`
+ ThreadCPUTime = linux_raw_sys::general::CLOCK_THREAD_CPUTIME_ID,
+
+ /// `CLOCK_REALTIME_COARSE`
+ RealtimeCoarse = linux_raw_sys::general::CLOCK_REALTIME_COARSE,
+
+ /// `CLOCK_MONOTONIC_COARSE`
+ MonotonicCoarse = linux_raw_sys::general::CLOCK_MONOTONIC_COARSE,
+
+ /// `CLOCK_MONOTONIC_RAW`
+ MonotonicRaw = linux_raw_sys::general::CLOCK_MONOTONIC_RAW,
+}
+
+/// `CLOCK_*` constants for use with [`clock_gettime_dynamic`].
+///
+/// These constants may be unsupported at runtime, depending on the OS version,
+/// and `clock_gettime_dynamic` may fail with `INVAL`. See [`ClockId`] for
+/// clocks which are always supported at runtime.
+///
+/// [`clock_gettime_dynamic`]: crate::time::clock_gettime_dynamic
+#[derive(Debug, Copy, Clone)]
+#[non_exhaustive]
+pub enum DynamicClockId<'a> {
+ /// `ClockId` values that are always supported at runtime.
+ Known(ClockId),
+
+ /// Linux dynamic clocks.
+ Dynamic(BorrowedFd<'a>),
+
+ /// `CLOCK_REALTIME_ALARM`, available on Linux >= 3.0
+ RealtimeAlarm,
+
+ /// `CLOCK_TAI`, available on Linux >= 3.10
+ Tai,
+
+ /// `CLOCK_BOOTTIME`, available on Linux >= 2.6.39
+ Boottime,
+
+ /// `CLOCK_BOOTTIME_ALARM`, available on Linux >= 2.6.39
+ BoottimeAlarm,
+}
+
+bitflags! {
+ /// `TFD_*` flags for use with [`timerfd_create`].
+ ///
+ /// [`timerfd_create`]: crate::time::timerfd_create
+ pub struct TimerfdFlags: c::c_uint {
+ /// `TFD_NONBLOCK`
+ const NONBLOCK = linux_raw_sys::general::TFD_NONBLOCK;
+
+ /// `TFD_CLOEXEC`
+ const CLOEXEC = linux_raw_sys::general::TFD_CLOEXEC;
+ }
+}
+
+bitflags! {
+ /// `TFD_TIMER_*` flags for use with [`timerfd_settime`].
+ ///
+ /// [`timerfd_settime`]: crate::time::timerfd_settime
+ pub struct TimerfdTimerFlags: c::c_uint {
+ /// `TFD_TIMER_ABSTIME`
+ const ABSTIME = linux_raw_sys::general::TFD_TIMER_ABSTIME;
+
+ /// `TFD_TIMER_CANCEL_ON_SET`
+ const CANCEL_ON_SET = linux_raw_sys::general::TFD_TIMER_CANCEL_ON_SET;
+ }
+}
+
+/// `CLOCK_*` constants for use with [`timerfd_create`].
+///
+/// [`timerfd_create`]: crate::time::timerfd_create
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+#[repr(u32)]
+#[non_exhaustive]
+pub enum TimerfdClockId {
+ /// `CLOCK_REALTIME`—A clock that tells the "real" time.
+ ///
+ /// This is a clock that tells the amount of time elapsed since the
+ /// Unix epoch, 1970-01-01T00:00:00Z. The clock is externally settable, so
+ /// it is not monotonic. Successive reads may see decreasing times, so it
+ /// isn't reliable for measuring durations.
+ Realtime = linux_raw_sys::general::CLOCK_REALTIME,
+
+ /// `CLOCK_MONOTONIC`—A clock that tells an abstract time.
+ ///
+ /// Unlike `Realtime`, this clock is not based on a fixed known epoch, so
+ /// individual times aren't meaningful. However, since it isn't settable,
+ /// it is reliable for measuring durations.
+ ///
+ /// This clock does not advance while the system is suspended; see
+ /// `Boottime` for a clock that does.
+ Monotonic = linux_raw_sys::general::CLOCK_MONOTONIC,
+
+ /// `CLOCK_BOOTTIME`—Like `Monotonic`, but advances while suspended.
+ ///
+ /// This clock is similar to `Monotonic`, but does advance while the system
+ /// is suspended.
+ Boottime = linux_raw_sys::general::CLOCK_BOOTTIME,
+
+ /// `CLOCK_REALTIME_ALARM`—Like `Realtime`, but wakes a suspended system.
+ ///
+ /// This clock is like `Realtime`, but can wake up a suspended system.
+ ///
+ /// Use of this clock requires the `CAP_WAKE_ALARM` Linux capability.
+ RealtimeAlarm = linux_raw_sys::general::CLOCK_REALTIME_ALARM,
+
+ /// `CLOCK_BOOTTIME_ALARM`—Like `Boottime`, but wakes a suspended system.
+ ///
+ /// This clock is like `Boottime`, but can wake up a suspended system.
+ ///
+ /// Use of this clock requires the `CAP_WAKE_ALARM` Linux capability.
+ BoottimeAlarm = linux_raw_sys::general::CLOCK_BOOTTIME_ALARM,
+}