From c4c69143a996a9065a040e7d99c31da7b1ad7a81 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 29 Apr 2022 16:44:28 +0200 Subject: [PATCH] Always return false in futex_wake on {Free,DragonFly}BSD. --- library/std/src/sys/unix/futex.rs | 12 ++++++++---- library/std/src/sys/unix/locks/futex_rwlock.rs | 17 +++++------------ 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/library/std/src/sys/unix/futex.rs b/library/std/src/sys/unix/futex.rs index 4f91d48f2f0..fd046bdf19d 100644 --- a/library/std/src/sys/unix/futex.rs +++ b/library/std/src/sys/unix/futex.rs @@ -104,6 +104,8 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option) - /// /// Returns true if this actually woke up such a thread, /// or false if no thread was waiting on this futex. +/// +/// On some platforms, this always returns false. #[cfg(any(target_os = "linux", target_os = "android", target_os = "netbsd"))] pub fn futex_wake(futex: &AtomicU32) -> bool { let ptr = futex as *const AtomicU32; @@ -135,9 +137,9 @@ 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. +// FreeBSD doesn't tell us how many threads are woken up, so this always returns false. #[cfg(target_os = "freebsd")] -pub fn futex_wake(futex: &AtomicU32) { +pub fn futex_wake(futex: &AtomicU32) -> bool { use crate::ptr::null_mut; unsafe { libc::_umtx_op( @@ -148,6 +150,7 @@ pub fn futex_wake(futex: &AtomicU32) { null_mut(), ) }; + false } #[cfg(target_os = "freebsd")] @@ -231,10 +234,11 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option) - 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. +// DragonflyBSD doesn't tell us how many threads are woken up, so this always returns false. #[cfg(target_os = "dragonfly")] -pub fn futex_wake(futex: &AtomicU32) { +pub fn futex_wake(futex: &AtomicU32) -> bool { unsafe { libc::umtx_wakeup(futex as *const AtomicU32 as *const i32, 1) }; + false } #[cfg(target_os = "dragonfly")] diff --git a/library/std/src/sys/unix/locks/futex_rwlock.rs b/library/std/src/sys/unix/locks/futex_rwlock.rs index 9c698f89b0d..57f6d58840d 100644 --- a/library/std/src/sys/unix/locks/futex_rwlock.rs +++ b/library/std/src/sys/unix/locks/futex_rwlock.rs @@ -283,18 +283,11 @@ impl RwLock { /// writer that was about to go to sleep. fn wake_writer(&self) -> bool { self.writer_notify.fetch_add(1, Release); - cfg_if::cfg_if! { - 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. - futex_wake(&self.writer_notify); - false - } else { - futex_wake(&self.writer_notify) - } - } + futex_wake(&self.writer_notify) + // Note that FreeBSD and DragonFlyBSD don't tell us whether they woke + // up any threads or not, and always return `false` here. That still + // results in correct behaviour: it just means readers get woken up as + // well in case both readers and writers were waiting. } /// Spin for a while, but stop directly at the given condition.