diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
commit | 698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch) | |
tree | 173a775858bd501c378080a10dca74132f05bc50 /vendor/rustix/src/imp/linux_raw/time | |
parent | Initial commit. (diff) | |
download | rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip |
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/rustix/src/imp/linux_raw/time')
-rw-r--r-- | vendor/rustix/src/imp/linux_raw/time/mod.rs | 3 | ||||
-rw-r--r-- | vendor/rustix/src/imp/linux_raw/time/syscalls.rs | 229 | ||||
-rw-r--r-- | vendor/rustix/src/imp/linux_raw/time/types.rs | 154 |
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, +} |