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 11:28:40 +0200
committerMara Bos <m-ou.se@m-ou.se>2022-04-29 16:30:54 +0200
commit69f0bcb26def1bccdf3774fc487201258b746fca (patch)
treebe4309b7295a8f2f31ccb446f0f86bd0e726f2f3 /library/std/src/sys/unix/futex.rs
parent2dfad1e3f81d649124bba15f96fd8e96431cd4fc (diff)
downloadrust-69f0bcb26def1bccdf3774fc487201258b746fca.tar.gz
rust-69f0bcb26def1bccdf3774fc487201258b746fca.zip
Use futex-based locks and thread parker on DragonFlyBSD.
Diffstat (limited to 'library/std/src/sys/unix/futex.rs')
-rw-r--r--library/std/src/sys/unix/futex.rs30
1 files changed, 30 insertions, 0 deletions
diff --git a/library/std/src/sys/unix/futex.rs b/library/std/src/sys/unix/futex.rs
index 64ed146b036..cfb2d1f07de 100644
--- a/library/std/src/sys/unix/futex.rs
+++ b/library/std/src/sys/unix/futex.rs
@@ -4,6 +4,7 @@
     all(target_os = "emscripten", target_feature = "atomics"),
     target_os = "openbsd",
     target_os = "netbsd",
+    target_os = "dragonfly",
 ))]
 
 use crate::sync::atomic::AtomicU32;
@@ -158,6 +159,35 @@ pub fn futex_wake_all(futex: &AtomicU32) {
     }
 }
 
+#[cfg(target_os = "dragonfly")]
+pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool {
+    use crate::convert::TryFrom;
+    let r = unsafe {
+        libc::umtx_sleep(
+            futex as *const AtomicU32 as *const i32,
+            expected as i32,
+            // A timeout of 0 means infinite, so we round smaller timeouts up to 1 millisecond.
+            // Timeouts larger than i32::MAX milliseconds saturate.
+            timeout.map_or(0, |d| {
+                i32::try_from(d.as_millis()).map_or(i32::MAX, |millis| millis.max(1))
+            }),
+        )
+    };
+
+    r == 0 || super::os::errno() != libc::ETIMEDOUT
+}
+
+// DragonflyBSD doesn't tell us how many threads are woken up, so this doesn't return a bool.
+#[cfg(target_os = "dragonfly")]
+pub fn futex_wake(futex: &AtomicU32) {
+    unsafe { libc::umtx_wakeup(futex as *const AtomicU32 as *const i32, 1) };
+}
+
+#[cfg(target_os = "dragonfly")]
+pub fn futex_wake_all(futex: &AtomicU32) {
+    unsafe { libc::umtx_wakeup(futex as *const AtomicU32 as *const i32, i32::MAX) };
+}
+
 #[cfg(target_os = "emscripten")]
 extern "C" {
     fn emscripten_futex_wake(addr: *const AtomicU32, count: libc::c_int) -> libc::c_int;