From 6caad3a53814e00b4147b3dbae5af8e83745cf1a Mon Sep 17 00:00:00 2001 From: vasilito Date: Thu, 2 Jul 2026 06:23:13 +0300 Subject: [PATCH] relibc: fix pthread_cond_signal POSIX semantics bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit src/sync/cond.rs:signal() was calling self.broadcast() (which wakes ALL waiters via futex_wake(INT32_MAX)) instead of self.wake(1) (which wakes exactly one). This violated POSIX: pthread_cond_signal must wake at least one waiter but must not wake all waiters (that is pthread_cond_broadcast semantics). The pre-existing code also had a commented-out self.wake(1), suggesting this was an unfinished fix that got left in the wrong state. Real-world impact: every pthread_cond_signal() in relibc (Qt's event loop, Mesa worker threads, KWin compositor, glib main loop, libwayland protocol dispatch) was triggering a thundering herd. On a multi-CPU system, this defeats the purpose of signal vs broadcast and degrades all conditional-variable-using code to broadcast-equivalent cost. After this commit: pthread_cond_signal() wakes exactly one waiter (the first one that the kernel's futex wakes), matching POSIX semantics. Verified: pre-existing host cargo check has 85 unrelated errors (relibc contains Redox-specific code that doesn't compile on Linux). The change in cond.rs introduces zero new errors. Full cross-compile validation requires 'touch relibc && make prefix' on a target build host. This is the first commit of the multi-threading plan Phase 0a — the 'one-line correctness fix' that the plan's audit identified as the single highest-ROI standalone action. --- src/sync/cond.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/sync/cond.rs b/src/sync/cond.rs index 19f9868a19..171a35dc3a 100644 --- a/src/sync/cond.rs +++ b/src/sync/cond.rs @@ -61,8 +61,14 @@ impl Cond { self.wake(i32::MAX) } pub fn signal(&self) -> Result<(), Errno> { - self.broadcast() - //self.wake(1) + // POSIX requires pthread_cond_signal to wake AT LEAST ONE waiter that + // is currently waiting on the condition variable, but it must not + // wake all waiters (that is pthread_cond_broadcast semantics). + // Wake exactly one via FUTEX_WAKE with count=1. Using broadcast() here + // was a thundering-herd bug: every cond_signal woke every waiter on + // every CPU. Fixed 2026-07-02 (Red Bear OS multi-threading plan, + // Phase 0a). + self.wake(1) } pub fn clockwait( &self,