documentation: Clarify memory-barrier semantics of atomic operations
All value-returning atomic read-modify-write operations must provide full memory-barrier semantics on both sides of the operation. This commit clarifies the documentation to make it clear that these memory-barrier semantics are provided by the operations themselves, not by their callers. Reported-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
This commit is contained in:
parent
f1360570f4
commit
daf1aab9ac
1 changed files with 23 additions and 22 deletions
|
@ -201,11 +201,11 @@ These routines add 1 and subtract 1, respectively, from the given
|
||||||
atomic_t and return the new counter value after the operation is
|
atomic_t and return the new counter value after the operation is
|
||||||
performed.
|
performed.
|
||||||
|
|
||||||
Unlike the above routines, it is required that explicit memory
|
Unlike the above routines, it is required that these primitives
|
||||||
barriers are performed before and after the operation. It must be
|
include explicit memory barriers that are performed before and after
|
||||||
done such that all memory operations before and after the atomic
|
the operation. It must be done such that all memory operations before
|
||||||
operation calls are strongly ordered with respect to the atomic
|
and after the atomic operation calls are strongly ordered with respect
|
||||||
operation itself.
|
to the atomic operation itself.
|
||||||
|
|
||||||
For example, it should behave as if a smp_mb() call existed both
|
For example, it should behave as if a smp_mb() call existed both
|
||||||
before and after the atomic operation.
|
before and after the atomic operation.
|
||||||
|
@ -233,21 +233,21 @@ These two routines increment and decrement by 1, respectively, the
|
||||||
given atomic counter. They return a boolean indicating whether the
|
given atomic counter. They return a boolean indicating whether the
|
||||||
resulting counter value was zero or not.
|
resulting counter value was zero or not.
|
||||||
|
|
||||||
It requires explicit memory barrier semantics around the operation as
|
Again, these primitives provide explicit memory barrier semantics around
|
||||||
above.
|
the atomic operation.
|
||||||
|
|
||||||
int atomic_sub_and_test(int i, atomic_t *v);
|
int atomic_sub_and_test(int i, atomic_t *v);
|
||||||
|
|
||||||
This is identical to atomic_dec_and_test() except that an explicit
|
This is identical to atomic_dec_and_test() except that an explicit
|
||||||
decrement is given instead of the implicit "1". It requires explicit
|
decrement is given instead of the implicit "1". This primitive must
|
||||||
memory barrier semantics around the operation.
|
provide explicit memory barrier semantics around the operation.
|
||||||
|
|
||||||
int atomic_add_negative(int i, atomic_t *v);
|
int atomic_add_negative(int i, atomic_t *v);
|
||||||
|
|
||||||
The given increment is added to the given atomic counter value. A
|
The given increment is added to the given atomic counter value. A boolean
|
||||||
boolean is return which indicates whether the resulting counter value
|
is return which indicates whether the resulting counter value is negative.
|
||||||
is negative. It requires explicit memory barrier semantics around the
|
This primitive must provide explicit memory barrier semantics around
|
||||||
operation.
|
the operation.
|
||||||
|
|
||||||
Then:
|
Then:
|
||||||
|
|
||||||
|
@ -257,7 +257,7 @@ This performs an atomic exchange operation on the atomic variable v, setting
|
||||||
the given new value. It returns the old value that the atomic variable v had
|
the given new value. It returns the old value that the atomic variable v had
|
||||||
just before the operation.
|
just before the operation.
|
||||||
|
|
||||||
atomic_xchg requires explicit memory barriers around the operation.
|
atomic_xchg must provide explicit memory barriers around the operation.
|
||||||
|
|
||||||
int atomic_cmpxchg(atomic_t *v, int old, int new);
|
int atomic_cmpxchg(atomic_t *v, int old, int new);
|
||||||
|
|
||||||
|
@ -266,7 +266,7 @@ with the given old and new values. Like all atomic_xxx operations,
|
||||||
atomic_cmpxchg will only satisfy its atomicity semantics as long as all
|
atomic_cmpxchg will only satisfy its atomicity semantics as long as all
|
||||||
other accesses of *v are performed through atomic_xxx operations.
|
other accesses of *v are performed through atomic_xxx operations.
|
||||||
|
|
||||||
atomic_cmpxchg requires explicit memory barriers around the operation.
|
atomic_cmpxchg must provide explicit memory barriers around the operation.
|
||||||
|
|
||||||
The semantics for atomic_cmpxchg are the same as those defined for 'cas'
|
The semantics for atomic_cmpxchg are the same as those defined for 'cas'
|
||||||
below.
|
below.
|
||||||
|
@ -279,8 +279,8 @@ If the atomic value v is not equal to u, this function adds a to v, and
|
||||||
returns non zero. If v is equal to u then it returns zero. This is done as
|
returns non zero. If v is equal to u then it returns zero. This is done as
|
||||||
an atomic operation.
|
an atomic operation.
|
||||||
|
|
||||||
atomic_add_unless requires explicit memory barriers around the operation
|
atomic_add_unless must provide explicit memory barriers around the
|
||||||
unless it fails (returns 0).
|
operation unless it fails (returns 0).
|
||||||
|
|
||||||
atomic_inc_not_zero, equivalent to atomic_add_unless(v, 1, 0)
|
atomic_inc_not_zero, equivalent to atomic_add_unless(v, 1, 0)
|
||||||
|
|
||||||
|
@ -460,9 +460,9 @@ the return value into an int. There are other places where things
|
||||||
like this occur as well.
|
like this occur as well.
|
||||||
|
|
||||||
These routines, like the atomic_t counter operations returning values,
|
These routines, like the atomic_t counter operations returning values,
|
||||||
require explicit memory barrier semantics around their execution. All
|
must provide explicit memory barrier semantics around their execution.
|
||||||
memory operations before the atomic bit operation call must be made
|
All memory operations before the atomic bit operation call must be
|
||||||
visible globally before the atomic bit operation is made visible.
|
made visible globally before the atomic bit operation is made visible.
|
||||||
Likewise, the atomic bit operation must be visible globally before any
|
Likewise, the atomic bit operation must be visible globally before any
|
||||||
subsequent memory operation is made visible. For example:
|
subsequent memory operation is made visible. For example:
|
||||||
|
|
||||||
|
@ -536,8 +536,9 @@ except that two underscores are prefixed to the interface name.
|
||||||
These non-atomic variants also do not require any special memory
|
These non-atomic variants also do not require any special memory
|
||||||
barrier semantics.
|
barrier semantics.
|
||||||
|
|
||||||
The routines xchg() and cmpxchg() need the same exact memory barriers
|
The routines xchg() and cmpxchg() must provide the same exact
|
||||||
as the atomic and bit operations returning values.
|
memory-barrier semantics as the atomic and bit operations returning
|
||||||
|
values.
|
||||||
|
|
||||||
Spinlocks and rwlocks have memory barrier expectations as well.
|
Spinlocks and rwlocks have memory barrier expectations as well.
|
||||||
The rule to follow is simple:
|
The rule to follow is simple:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue