* Improve the phrasing of some docstrings and comments
* Add warning comments about attempts to validate memory addresses
at reader/writer instantiation time
* Create the `reader_writer` method for ergonomically instantiate
a reader/writer pair covering the same memory region. This method
is also slightly more efficient than calling `reader` and `writer`
separately
* Clean up `check_vaddr` for clarity and rename it to `check_vaddr_lowerbound`
for explicity
* Include the data length check before calling `check_vaddr_lowerbound`
in `atomic_load` and `atomic_fetch_update` for further consistency
with the delayed buffer validation
If the futex wait operation was interrupted by a signal or timed out, the
`FutexItem` must be dequeued and dropped. Otherwise, malicious user programs
could repeatedly issue futex wait operations to exhaust kernel memory.
Due to asynchronicity, this removal can't be done by queue position nor by
futex key match up:
* The position might have changed during the pause as some earlier futex might
have been dequeued
* If two futexes with the same key are enqueued and then one of them times out
or is interrupted, a removal by key would likely dequeue the wrong futex
Therefore, we need to perform a removal by unique global futex ID.
Replace `VmWriter::atomic_update` with `VmWriter::atomic_compare_exchange`,
which takes the old value for comparison and new value instead of a
closure to compute it. This version has one less unsafe call.
Then use `atomic_compare_exchange` to reimplement the looping logic
of `wake_robust_futex` and make it atomic.
This patch pays the price of making the instantiation of `FutexKey`
more expensive to achieve two goals:
* Minor: make `match_up` slightly faster
* Major: make futex bucket allocation balancing more robust
Doing `addr / self.size()` before masking with `(self.size() - 1)`
removes the low bits entirely, which causes adjacent addresses
(modulo `self.size()`) to map to the same bucket, entailing bad
load balance. This patch solves that.
Further, make `FutexBucketVec::new` and `FutexBucketVec::get_bucket`
private, as they only make sense within the scope of `futex.rs`,
where the invariant of `size` being a power of two is guaranteed to
hold via `get_bucket_count` (which is also private).
Use shared references instead of copied objects on some functions
that don't necessarily require ownership of `FutexKey`.
Remove the `Copy` derivation of `FutexKey` to discourage suboptimal
copies.