Commit 55bccf1f authored by Peter Zijlstra's avatar Peter Zijlstra

Documentation/atomic_t: Document forward progress expectations

Add a few words on forward progress; there's been quite a bit of
confusion on the subject.
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: default avatarWill Deacon <will@kernel.org>
Acked-by: default avatarBoqun Feng <boqun.feng@gmail.com>
Link: https://lkml.kernel.org/r/YQK9ziyogxTH0m9H@hirez.programming.kicks-ass.net
parent 9248e52f
......@@ -312,3 +312,56 @@ Usage:
NB. try_cmpxchg() also generates better code on some platforms (notably x86)
where the function more closely matches the hardware instruction.
FORWARD PROGRESS
----------------
In general strong forward progress is expected of all unconditional atomic
operations -- those in the Arithmetic and Bitwise classes and xchg(). However
a fair amount of code also requires forward progress from the conditional
atomic operations.
Specifically 'simple' cmpxchg() loops are expected to not starve one another
indefinitely. However, this is not evident on LL/SC architectures, because
while an LL/SC architecure 'can/should/must' provide forward progress
guarantees between competing LL/SC sections, such a guarantee does not
transfer to cmpxchg() implemented using LL/SC. Consider:
old = atomic_read(&v);
do {
new = func(old);
} while (!atomic_try_cmpxchg(&v, &old, new));
which on LL/SC becomes something like:
old = atomic_read(&v);
do {
new = func(old);
} while (!({
volatile asm ("1: LL %[oldval], %[v]\n"
" CMP %[oldval], %[old]\n"
" BNE 2f\n"
" SC %[new], %[v]\n"
" BNE 1b\n"
"2:\n"
: [oldval] "=&r" (oldval), [v] "m" (v)
: [old] "r" (old), [new] "r" (new)
: "memory");
success = (oldval == old);
if (!success)
old = oldval;
success; }));
However, even the forward branch from the failed compare can cause the LL/SC
to fail on some architectures, let alone whatever the compiler makes of the C
loop body. As a result there is no guarantee what so ever the cacheline
containing @v will stay on the local CPU and progress is made.
Even native CAS architectures can fail to provide forward progress for their
primitive (See Sparc64 for an example).
Such implementations are strongly encouraged to add exponential backoff loops
to a failed CAS in order to ensure some progress. Affected architectures are
also strongly encouraged to inspect/audit the atomic fallbacks, refcount_t and
their locking primitives.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment