about summary refs log tree commit diff
path: root/library/std/src/sys/unix/futex.rs
diff options
context:
space:
mode:
authorMara Bos <m-ou.se@m-ou.se>2022-04-28 10:32:11 +0200
committerMara Bos <m-ou.se@m-ou.se>2022-04-29 16:30:54 +0200
commitafe1a256ce6612c8c98b5f8a15f797dced1cf696 (patch)
tree358b01537f80d04e3be16067348df5da42bf91e2 /library/std/src/sys/unix/futex.rs
parent87937d3b6c302dfedfa5c4b94d0a30985d46298d (diff)
downloadrust-afe1a256ce6612c8c98b5f8a15f797dced1cf696.tar.gz
rust-afe1a256ce6612c8c98b5f8a15f797dced1cf696.zip
Use futex-based locks and thread parker on OpenBSD.
Diffstat (limited to 'library/std/src/sys/unix/futex.rs')
-rw-r--r--library/std/src/sys/unix/futex.rs52
1 files changed, 51 insertions, 1 deletions
diff --git a/library/std/src/sys/unix/futex.rs b/library/std/src/sys/unix/futex.rs
index c12ee169e79..f86dd560d63 100644
--- a/library/std/src/sys/unix/futex.rs
+++ b/library/std/src/sys/unix/futex.rs
@@ -1,7 +1,8 @@
 #![cfg(any(
     target_os = "linux",
     target_os = "android",
-    all(target_os = "emscripten", target_feature = "atomics")
+    all(target_os = "emscripten", target_feature = "atomics"),
+    target_os = "openbsd",
 ))]
 
 use crate::sync::atomic::AtomicU32;
@@ -81,6 +82,55 @@ pub fn futex_wake_all(futex: &AtomicU32) {
     }
 }
 
+#[cfg(target_os = "openbsd")]
+pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool {
+    use crate::convert::TryInto;
+    use crate::ptr::{null, null_mut};
+    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 _,
+        })
+    });
+
+    let r = unsafe {
+        libc::futex(
+            futex as *const AtomicU32 as *mut u32,
+            libc::FUTEX_WAIT,
+            expected as i32,
+            timespec.as_ref().map_or(null(), |t| t as *const libc::timespec),
+            null_mut(),
+        )
+    };
+
+    r == 0 || super::os::errno() != libc::ETIMEDOUT
+}
+
+#[cfg(target_os = "openbsd")]
+pub fn futex_wake(futex: &AtomicU32) -> bool {
+    use crate::ptr::{null, null_mut};
+    unsafe {
+        libc::futex(futex as *const AtomicU32 as *mut u32, libc::FUTEX_WAKE, 1, null(), null_mut())
+            > 0
+    }
+}
+
+#[cfg(target_os = "openbsd")]
+pub fn futex_wake_all(futex: &AtomicU32) {
+    use crate::ptr::{null, null_mut};
+    unsafe {
+        libc::futex(
+            futex as *const AtomicU32 as *mut u32,
+            libc::FUTEX_WAKE,
+            i32::MAX,
+            null(),
+            null_mut(),
+        );
+    }
+}
+
 #[cfg(target_os = "emscripten")]
 extern "C" {
     fn emscripten_futex_wake(addr: *const AtomicU32, count: libc::c_int) -> libc::c_int;