# Busy Waiting

> ForkUnion for C

Here's what "busy waiting" looks like in C++:

```cpp
while (!has_work_to_do())
    std::this_thread::yield();
```

On Linux, the `std::this_thread::yield()` translates into a `sched_yield` system call, which means context switching to the kernel and back.
Instead, you can replace the `standard_yield_t` wrapper with a platform-specific micro-wait instruction, which is much cheaper.
Those instructions, like [`WFET` on Arm](https://developer.arm.com/documentation/ddi0602/2025-03/Base-Instructions/WFET--Wait-for-event-with-timeout-), generally hint the CPU to transition to a low-power state.

| Wrapper           | ISA          | Instruction         | Privileges |
| :---------------- | :----------- | :------------------ | :--------- |
| `x86_pause_t`     | x86          | `PAUSE`             | R3         |
| `x86_tpause_t`    | x86+WAITPKG  | `UMONITOR`+`UMWAIT` | R3         |
| `arm64_yield_t`   | AArch64      | `YIELD`             | EL0        |
| `arm64_wfe_t`     | AArch64      | `LDAXR`+`WFE`       | EL0        |
| `arm64_wfet_t`    | AArch64+WFXT | `WFET`              | EL0        |
| `riscv64_pause_t` | RISC-V       | `PAUSE`             | U          |
| `riscv64_wrs_t`   | RISC-V+Zawrs | `WRS.STO`/`WRS.NTO` | U          |

No kernel calls.
No futexes.
Works in tight loops.

The `UMWAIT`, `WFE`, `WFET`, and `WRS` wrappers go a step further than a spin hint: they sleep the core until a store to the watched line, capped by a timeout only where the loop guards more than one word, so the pool parks a worker in a low-power state rather than burning the core.
`spin_mutex<fu::preferred_yield_t>` takes the same wrappers, while the default `spin_mutex_t` yields to the scheduler and Rust's `SpinMutex` spins on `core::hint::spin_loop` - a futex-free `std::mutex` alternative, and the lock used in the NUMA example above.
On WebAssembly threads the waiter is `wasm_wait_t`: a 32- or 64-bit watch sleeps in `memory.atomic.wait` until a `wasm_atomic_ref` releasing write notifies or 1 µs passes, so pair the two; uncapped waits and 1- or 2-byte watches spin.

