From 29752835c219c60658c3ac6383f801ec6fb7db80 Mon Sep 17 00:00:00 2001 From: vasilito Date: Fri, 31 Jul 2026 18:37:19 +0300 Subject: [PATCH] sync: export C futex_wake/futex_wait for portable futex users (Mesa) Mesa's util/futex declares int futex_wake(uint32_t*, int32_t) / int futex_wait(uint32_t*, int32_t, const struct timespec*) and its drivers (ANV) call them. relibc already has the correct Redox futex internally; expose it under these C symbols so Mesa's Redox branch links against a working futex. --- src/sync/mod.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/sync/mod.rs b/src/sync/mod.rs index 630922b55c..22abbf60f2 100644 --- a/src/sync/mod.rs +++ b/src/sync/mod.rs @@ -128,6 +128,39 @@ pub fn futex_wait( unsafe { futex_wait_ptr(atomic.ptr(), value, deadline_opt) } } +/// C-ABI futex primitives for consumers such as Mesa's `util/futex`, which +/// expects `int futex_wake(uint32_t *addr, int32_t count)` and +/// `int futex_wait(uint32_t *addr, int32_t value, const struct timespec *)`. +/// Backed by relibc's own futex (the correct primitive for Redox), so these +/// give portable code a working futex without reimplementing the Redox ABI. +/// +/// # Safety +/// `addr` must point to a valid, properly-aligned `u32`; `timeout` is null or a +/// valid `timespec`. +#[unsafe(export_name = "futex_wake")] +pub unsafe extern "C" fn c_futex_wake(addr: *mut u32, count: c_int) -> c_int { + unsafe { futex_wake_ptr(addr, count) as c_int } +} + +/// See [`c_futex_wake`]. +/// +/// # Safety +/// As for [`c_futex_wake`]. +#[unsafe(export_name = "futex_wait")] +pub unsafe extern "C" fn c_futex_wait( + addr: *mut u32, + value: c_int, + timeout: *const timespec, +) -> c_int { + let deadline = if timeout.is_null() { + None + } else { + Some(unsafe { &*timeout }) + }; + let _ = unsafe { futex_wait_ptr(addr, value as u32, deadline) }; + 0 +} + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum FutexWaitResult { Waited, // possibly spurious