diff options
Diffstat (limited to 'vendor/rustix/src/backend/libc/thread/syscalls.rs')
-rw-r--r-- | vendor/rustix/src/backend/libc/thread/syscalls.rs | 122 |
1 files changed, 120 insertions, 2 deletions
diff --git a/vendor/rustix/src/backend/libc/thread/syscalls.rs b/vendor/rustix/src/backend/libc/thread/syscalls.rs index 5260c39f4..846f0e2a8 100644 --- a/vendor/rustix/src/backend/libc/thread/syscalls.rs +++ b/vendor/rustix/src/backend/libc/thread/syscalls.rs @@ -10,9 +10,10 @@ use crate::timespec::LibcTimespec; use core::mem::MaybeUninit; #[cfg(linux_kernel)] use { - crate::backend::conv::{borrowed_fd, ret_c_int}, + crate::backend::conv::{borrowed_fd, ret_c_int, ret_usize}, crate::fd::BorrowedFd, crate::pid::Pid, + crate::thread::{FutexFlags, FutexOperation}, crate::utils::as_mut_ptr, }; #[cfg(not(any( @@ -279,7 +280,7 @@ pub(crate) fn gettid() -> Pid { #[cfg(linux_kernel)] #[inline] -pub(crate) fn setns(fd: BorrowedFd, nstype: c::c_int) -> io::Result<c::c_int> { +pub(crate) fn setns(fd: BorrowedFd<'_>, nstype: c::c_int) -> io::Result<c::c_int> { // `setns` wasn't supported in glibc until 2.14, and musl until 0.9.5, // so use `syscall`. weak_or_syscall! { @@ -390,3 +391,120 @@ pub(crate) fn setresgid_thread( unsafe { ret(setresgid(rgid.as_raw(), egid.as_raw(), sgid.as_raw())) } } + +// TODO: This could be de-multiplexed. +#[cfg(linux_kernel)] +pub(crate) unsafe fn futex( + uaddr: *mut u32, + op: FutexOperation, + flags: FutexFlags, + val: u32, + utime: *const Timespec, + uaddr2: *mut u32, + val3: u32, +) -> io::Result<usize> { + #[cfg(all( + target_pointer_width = "32", + not(any(target_arch = "aarch64", target_arch = "x86_64")) + ))] + { + // TODO: Upstream this to the libc crate. + #[allow(non_upper_case_globals)] + const SYS_futex_time64: i32 = linux_raw_sys::general::__NR_futex_time64 as i32; + + syscall! { + fn futex_time64( + uaddr: *mut u32, + futex_op: c::c_int, + val: u32, + timeout: *const Timespec, + uaddr2: *mut u32, + val3: u32 + ) via SYS_futex_time64 -> c::ssize_t + } + + ret_usize(futex_time64( + uaddr, + op as i32 | flags.bits() as i32, + val, + utime, + uaddr2, + val3, + )) + .or_else(|err| { + // See the comments in `rustix_clock_gettime_via_syscall` about + // emulation. + if err == io::Errno::NOSYS { + futex_old(uaddr, op, flags, val, utime, uaddr2, val3) + } else { + Err(err) + } + }) + } + + #[cfg(any( + target_pointer_width = "64", + target_arch = "aarch64", + target_arch = "x86_64" + ))] + { + syscall! { + fn futex( + uaddr: *mut u32, + futex_op: c::c_int, + val: u32, + timeout: *const linux_raw_sys::general::__kernel_timespec, + uaddr2: *mut u32, + val3: u32 + ) via SYS_futex -> c::c_long + } + + ret_usize(futex( + uaddr, + op as i32 | flags.bits() as i32, + val, + utime.cast(), + uaddr2, + val3, + ) as isize) + } +} + +#[cfg(linux_kernel)] +#[cfg(all( + target_pointer_width = "32", + not(any(target_arch = "aarch64", target_arch = "x86_64")) +))] +unsafe fn futex_old( + uaddr: *mut u32, + op: FutexOperation, + flags: FutexFlags, + val: u32, + utime: *const Timespec, + uaddr2: *mut u32, + val3: u32, +) -> io::Result<usize> { + syscall! { + fn futex( + uaddr: *mut u32, + futex_op: c::c_int, + val: u32, + timeout: *const linux_raw_sys::general::__kernel_old_timespec, + uaddr2: *mut u32, + val3: u32 + ) via SYS_futex -> c::c_long + } + + let old_utime = linux_raw_sys::general::__kernel_old_timespec { + tv_sec: (*utime).tv_sec.try_into().map_err(|_| io::Errno::INVAL)?, + tv_nsec: (*utime).tv_nsec.try_into().map_err(|_| io::Errno::INVAL)?, + }; + ret_usize(futex( + uaddr, + op as i32 | flags.bits() as i32, + val, + &old_utime, + uaddr2, + val3, + ) as isize) +} |