epoch's synchronous wait operation tries to bind to CPUs where active
readers are running, so that it can propagate the waiting thread's
priority to preempted readers. This approach has a few problems:
- it can cause the reader to be preempted, which is really the opposite of what we want to do
- the thread might have to wait for a long time if the CPU is monopolized by a high priority thread
- the priority propagation to non-blocked threads does not use the turnstile interface, so it doesn't properly integrate with the existing priority propagation mechanism used by the locking primitives
Try to simplify epoch_block_handler_preempt() by identifying the oldest
active off-CPU reader and making it the owner of a turnstile. Waiting
threads use the turnstile to propagate their scheduling priority; there
is one turnstile per-CPU. Upon exiting the read section, the turnstile
owner takes a slow path to wake up waiters.
This mechanism is not perfect but it is much simpler and avoids the
problems listed above. In some cases priority propagation is not enough
and we'd want a static priority boost to ensure that starved readers can
make progress.