about summary refs log tree commit diff
path: root/library/std/src/sys/unix/futex.rs
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-10-01 13:21:34 +0000
committerbors <bors@rust-lang.org>2020-10-01 13:21:34 +0000
commit782013564efc06ef02614ba35a4e67dee4fcb8e7 (patch)
tree2e905ff25153425fe0389ea1db074a72edcd7934 /library/std/src/sys/unix/futex.rs
parent9cba260df0f1c67ea3690035cd5611a7465a1560 (diff)
parent0b73fd7105db81a994a81b775a43bbdb1be3c76a (diff)
downloadrust-782013564efc06ef02614ba35a4e67dee4fcb8e7.tar.gz
rust-782013564efc06ef02614ba35a4e67dee4fcb8e7.zip
Auto merge of #76919 - fusion-engineering-forks:thread-parker, r=dtolnay
Use futex-based thread::park/unpark on Linux.

This moves the parking/unparking logic out of `thread/mod.rs` into a module named `thread_parker` in `sys_common`. The current implementation is moved to `sys_common/thread_parker/generic.rs` and the new implementation using futexes is added in `sys_common/thread_parker/futex.rs`.
Diffstat (limited to 'library/std/src/sys/unix/futex.rs')
-rw-r--r--library/std/src/sys/unix/futex.rs37
1 files changed, 37 insertions, 0 deletions
diff --git a/library/std/src/sys/unix/futex.rs b/library/std/src/sys/unix/futex.rs
new file mode 100644
index 00000000000..e6f0c48c59b
--- /dev/null
+++ b/library/std/src/sys/unix/futex.rs
@@ -0,0 +1,37 @@
+#![cfg(any(target_os = "linux", target_os = "android"))]
+
+use crate::convert::TryInto;
+use crate::ptr::null;
+use crate::sync::atomic::AtomicI32;
+use crate::time::Duration;
+
+pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option<Duration>) {
+    let timespec = timeout.and_then(|d| {
+        Some(libc::timespec {
+            // Sleep forever if the timeout is longer than fits in a timespec.
+            tv_sec: d.as_secs().try_into().ok()?,
+            // This conversion never truncates, as subsec_nanos is always <1e9.
+            tv_nsec: d.subsec_nanos() as _,
+        })
+    });
+    unsafe {
+        libc::syscall(
+            libc::SYS_futex,
+            futex as *const AtomicI32,
+            libc::FUTEX_WAIT | libc::FUTEX_PRIVATE_FLAG,
+            expected,
+            timespec.as_ref().map_or(null(), |d| d as *const libc::timespec),
+        );
+    }
+}
+
+pub fn futex_wake(futex: &AtomicI32) {
+    unsafe {
+        libc::syscall(
+            libc::SYS_futex,
+            futex as *const AtomicI32,
+            libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG,
+            1,
+        );
+    }
+}