|
5 | 5 | target_os = "freebsd",
|
6 | 6 | target_os = "openbsd",
|
7 | 7 | target_os = "dragonfly",
|
| 8 | + target_os = "fuchsia", |
8 | 9 | ))]
|
9 | 10 |
|
10 | 11 | use crate::sync::atomic::AtomicU32;
|
@@ -237,3 +238,52 @@ pub fn futex_wake(futex: &AtomicU32) -> bool {
|
237 | 238 | pub fn futex_wake_all(futex: &AtomicU32) {
|
238 | 239 | unsafe { emscripten_futex_wake(futex, i32::MAX) };
|
239 | 240 | }
|
| 241 | + |
| 242 | +#[cfg(target_os = "fuchsia")] |
| 243 | +mod zircon { |
| 244 | + type zx_time_t = i64; |
| 245 | + type zx_futex_t = crate::sync::atomic::AtomicU32; |
| 246 | + type zx_handle_t = u32; |
| 247 | + type zx_status_t = i32; |
| 248 | + |
| 249 | + pub const ZX_HANDLE_INVALID: zx_handle_t = 0; |
| 250 | + pub const ZX_ERR_TIMED_OUT: zx_status_t = -21; |
| 251 | + pub const ZX_TIME_INFINITE: zx_time_t = zx_time_t::MAX; |
| 252 | + |
| 253 | + extern "C" { |
| 254 | + pub fn zx_futex_wait( |
| 255 | + value_ptr: *const zx_futex_t, |
| 256 | + current_value: zx_futex_t, |
| 257 | + new_futex_owner: zx_handle_t, |
| 258 | + deadline: zx_time_t, |
| 259 | + ) -> zx_status_t; |
| 260 | + pub fn zx_futex_wake(value_ptr: *const zx_futex_t, wake_count: u32) -> zx_status_t; |
| 261 | + pub fn zx_clock_get_monotonic() -> zx_time_t; |
| 262 | + } |
| 263 | +} |
| 264 | + |
| 265 | +#[cfg(target_os = "fuchsia")] |
| 266 | +pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool { |
| 267 | + use crate::convert::TryFrom; |
| 268 | + |
| 269 | + // Sleep forever if the timeout is longer than fits in a i64. |
| 270 | + let deadline = timeout |
| 271 | + .and_then(|d| { |
| 272 | + i64::try_from(d.as_nanos()) |
| 273 | + .ok()? |
| 274 | + .checked_add(unsafe { zircon::zx_clock_get_monotonic() }) |
| 275 | + }) |
| 276 | + .unwrap_or(zircon::ZX_TIME_INFINITE); |
| 277 | + |
| 278 | + unsafe { |
| 279 | + zircon::zx_futex_wait(futex, AtomicU32::new(expected), zircon::ZX_HANDLE_INVALID, deadline) |
| 280 | + != zircon::ZX_ERR_TIMED_OUT |
| 281 | + } |
| 282 | +} |
| 283 | + |
| 284 | +// Fuchsia doesn't tell us how many threads are woken up, so this always returns false. |
| 285 | +#[cfg(target_os = "fuchsia")] |
| 286 | +pub fn futex_wake(futex: &AtomicU32) -> bool { |
| 287 | + unsafe { zircon::zx_futex_wake(futex, 1) }; |
| 288 | + false |
| 289 | +} |
0 commit comments