about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
authorMara Bos <m-ou.se@m-ou.se>2022-04-28 12:22:14 +0200
committerMara Bos <m-ou.se@m-ou.se>2022-04-29 16:45:17 +0200
commit04b0bc97bb84915f2487743b7dde7993ddb34e5d (patch)
tree490ccb048c9dce0eb555e6a4a56ad9bfc075bf05 /library/std/src
parent69f0bcb26def1bccdf3774fc487201258b746fca (diff)
downloadrust-04b0bc97bb84915f2487743b7dde7993ddb34e5d.tar.gz
rust-04b0bc97bb84915f2487743b7dde7993ddb34e5d.zip
Use futex-based locks and thread parker on FreeBSD.
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/sys/unix/futex.rs58
-rw-r--r--library/std/src/sys/unix/locks/futex_rwlock.rs4
-rw-r--r--library/std/src/sys/unix/locks/mod.rs1
-rw-r--r--library/std/src/sys_common/thread_parker/mod.rs1
4 files changed, 60 insertions, 4 deletions
diff --git a/library/std/src/sys/unix/futex.rs b/library/std/src/sys/unix/futex.rs
index cfb2d1f07de..4f91d48f2f0 100644
--- a/library/std/src/sys/unix/futex.rs
+++ b/library/std/src/sys/unix/futex.rs
@@ -2,6 +2,7 @@
     target_os = "linux",
     target_os = "android",
     all(target_os = "emscripten", target_feature = "atomics"),
+    target_os = "freebsd",
     target_os = "openbsd",
     target_os = "netbsd",
     target_os = "dragonfly",
@@ -18,7 +19,12 @@ pub const SYS___futex: i32 = 166;
 /// Returns directly if the futex doesn't hold the expected value.
 ///
 /// Returns false on timeout, and true in all other cases.
-#[cfg(any(target_os = "linux", target_os = "android", target_os = "netbsd"))]
+#[cfg(any(
+    target_os = "linux",
+    target_os = "android",
+    target_os = "freebsd",
+    target_os = "netbsd"
+))]
 pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool {
     use super::time::Timespec;
     use crate::ptr::null;
@@ -40,7 +46,26 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
         // absolute time rather than a relative time.
         let r = unsafe {
             cfg_if::cfg_if! {
-                if #[cfg(target_os = "netbsd")] {
+                if #[cfg(target_os = "freebsd")] {
+                    // FreeBSD doesn't have futex(), but it has
+                    // _umtx_op(UMTX_OP_WAIT_UINT_PRIVATE), which is nearly
+                    // identical. It supports absolute timeouts through a flag
+                    // in the _umtx_time struct.
+                    let umtx_timeout = timespec.map(|t| libc::_umtx_time {
+                        _timeout: t.t,
+                        _flags: libc::UMTX_ABSTIME,
+                        _clockid: libc::CLOCK_MONOTONIC as u32,
+                    });
+                    let umtx_timeout_ptr = umtx_timeout.as_ref().map_or(null(), |t| t as *const _);
+                    let umtx_timeout_size = umtx_timeout.as_ref().map_or(0, |t| crate::mem::size_of_val(t));
+                    libc::_umtx_op(
+                        futex as *const AtomicU32 as *mut _,
+                        libc::UMTX_OP_WAIT_UINT_PRIVATE,
+                        expected as libc::c_ulong,
+                        crate::ptr::invalid_mut(umtx_timeout_size),
+                        umtx_timeout_ptr as *mut _,
+                    )
+                } else if #[cfg(target_os = "netbsd")] {
                     // Netbsd's futex syscall takes addr2 and val2 as separate arguments.
                     // (Both are unused for FUTEX_WAIT[_BITSET].)
                     libc::syscall(
@@ -110,6 +135,35 @@ pub fn futex_wake_all(futex: &AtomicU32) {
     }
 }
 
+// FreeBSD doesn't tell us how many threads are woken up, so this doesn't return a bool.
+#[cfg(target_os = "freebsd")]
+pub fn futex_wake(futex: &AtomicU32) {
+    use crate::ptr::null_mut;
+    unsafe {
+        libc::_umtx_op(
+            futex as *const AtomicU32 as *mut _,
+            libc::UMTX_OP_WAKE_PRIVATE,
+            1,
+            null_mut(),
+            null_mut(),
+        )
+    };
+}
+
+#[cfg(target_os = "freebsd")]
+pub fn futex_wake_all(futex: &AtomicU32) {
+    use crate::ptr::null_mut;
+    unsafe {
+        libc::_umtx_op(
+            futex as *const AtomicU32 as *mut _,
+            libc::UMTX_OP_WAKE_PRIVATE,
+            i32::MAX as libc::c_ulong,
+            null_mut(),
+            null_mut(),
+        )
+    };
+}
+
 #[cfg(target_os = "openbsd")]
 pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool {
     use crate::convert::TryInto;
diff --git a/library/std/src/sys/unix/locks/futex_rwlock.rs b/library/std/src/sys/unix/locks/futex_rwlock.rs
index 8829ed4db25..9c698f89b0d 100644
--- a/library/std/src/sys/unix/locks/futex_rwlock.rs
+++ b/library/std/src/sys/unix/locks/futex_rwlock.rs
@@ -284,8 +284,8 @@ impl RwLock {
     fn wake_writer(&self) -> bool {
         self.writer_notify.fetch_add(1, Release);
         cfg_if::cfg_if! {
-            if #[cfg(target_os = "dragonfly")] {
-                // DragonFlyBSD doesn't tell us whether it woke up any threads or not.
+            if #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] {
+                // FreeBSD and DragonFlyBSD don't tell us whether they woke up any threads or not.
                 // So, we always return `false` here, as that still results in correct behaviour.
                 // The downside is an extra syscall in case both readers and writers were waiting,
                 // and unnecessarily waking up readers when a writer is about to attempt to lock the lock.
diff --git a/library/std/src/sys/unix/locks/mod.rs b/library/std/src/sys/unix/locks/mod.rs
index d39da200dda..27d007a1051 100644
--- a/library/std/src/sys/unix/locks/mod.rs
+++ b/library/std/src/sys/unix/locks/mod.rs
@@ -3,6 +3,7 @@ cfg_if::cfg_if! {
         target_os = "linux",
         target_os = "android",
         all(target_os = "emscripten", target_feature = "atomics"),
+        target_os = "freebsd",
         target_os = "openbsd",
         target_os = "netbsd",
         target_os = "dragonfly",
diff --git a/library/std/src/sys_common/thread_parker/mod.rs b/library/std/src/sys_common/thread_parker/mod.rs
index 7fd4d3610ca..5305f1f2dee 100644
--- a/library/std/src/sys_common/thread_parker/mod.rs
+++ b/library/std/src/sys_common/thread_parker/mod.rs
@@ -3,6 +3,7 @@ cfg_if::cfg_if! {
         target_os = "linux",
         target_os = "android",
         all(target_arch = "wasm32", target_feature = "atomics"),
+        target_os = "freebsd",
         target_os = "openbsd",
         target_os = "netbsd",
         target_os = "dragonfly",