notify() increments it with release ordering. Each handle tracks the last counter value it consumed, starting at zero.
wait(timeout_ms) returns when the counter differs from that handle’s cursor. A notification sent before the wait remains pending. try_wait() checks and consumes a pending change without sleeping, returning true when it finds one.
Timeouts
Timeouts are in milliseconds. Zero checks for a pending change and otherwise returnsTimedOut. u32::MAX is about 49.7 days, not an infinite wait.
zinc_try_wait returns 0 for a pending change, -11 (WouldBlock) if none is pending, and -22 for a null handle.
Multiple readers
Open a separate handle for each reader that needs an independent notification cursor. Linux wakes all threads blocked on the region’s futex. Concurrent waits on the same handle share a cursor and can coalesce observations.Data access
A successful wait acquires the writer’s release notification, publishing writes that happened before it. This does not prevent the writer from modifying data while readers use it. Use atomic data or an application protocol that prevents concurrent writes and reads. For a reusable plain-data buffer, readers need to acknowledge completion before the writer overwrites it.Linux
notify() always calls FUTEX_WAKE, even when no thread is waiting. wait() checks the counter before calling FUTEX_WAIT, then checks it again after waking. Spurious wakes and interrupted syscalls retry within the original timeout. A wake alone does not count as a notification.
See FUTEX_WAIT for the kernel’s wait semantics.
