summaryrefslogtreecommitdiffstats
path: root/vendor/rustix/src/backend/libc/thread/syscalls.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rustix/src/backend/libc/thread/syscalls.rs')
-rw-r--r--vendor/rustix/src/backend/libc/thread/syscalls.rs122
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)
+}