mirror of
https://github.com/trapexit/mergerfs.git
synced 2026-10-26 02:48:59 -04:00
thread_pool: use acquire ordering in tasks_pending for weak memory
The prior relaxed loads defeated the documented "bias toward zero" invariant on ARM and POWER: the hardware can reorder two relaxed loads against program order, allowing _tasks_completed to be observed before _tasks_enqueued and producing a delta larger than any single atomic snapshot. Upgrade both loads to acquire and put an acquire fence between them so source-order ordering is preserved on weak memory.
This commit is contained in:
parent
17c0ffaddc
commit
fbf69071d2
1 changed files with 10 additions and 7 deletions
|
|
@ -1445,17 +1445,20 @@ ThreadPool::tasks_completed() const
|
|||
return _tasks_completed.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
// Approximate: the two counters are loaded non-atomically.
|
||||
// Loading enqueued first biases the result toward zero (a
|
||||
// completion between the two loads increases c beyond the
|
||||
// snapshot of e, shrinking the delta), which is safer for
|
||||
// scaling heuristics than over-reporting pressure.
|
||||
// Approximate: loads are atomic but the pair is not.
|
||||
// Loading enqueued first is meant to bias the result toward zero (a
|
||||
// completion between the two loads increases c beyond the snapshot
|
||||
// of e, shrinking the delta), which is safer for scaling heuristics
|
||||
// than over-reporting pressure. Acquire ordering on both loads plus
|
||||
// the intervening acquire fence prevents weak-memory hardware (ARM,
|
||||
// POWER) from reordering them and defeating the intended bias.
|
||||
// Suitable for monitoring and heuristics, not for synchronization.
|
||||
inline
|
||||
std::uint64_t
|
||||
ThreadPool::tasks_pending() const
|
||||
{
|
||||
auto e = _tasks_enqueued.load(std::memory_order_relaxed);
|
||||
auto c = _tasks_completed.load(std::memory_order_relaxed);
|
||||
auto e = _tasks_enqueued.load(std::memory_order_acquire);
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
auto c = _tasks_completed.load(std::memory_order_acquire);
|
||||
return (e > c) ? (e - c) : 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue