documentation: Record limitations of bitfields and small variables
This commit documents the fact that it is not safe to use bitfields as shared variables in synchronization algorithms. It also documents that CPUs must be able to concurrently load from and store to adjacent one-byte and two-byte variables, which is in fact required by the C11 standard (Section 3.14). Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
This commit is contained in:
parent
84596ccbf1
commit
432fbf3c6a
|
@ -269,6 +269,50 @@ And there are a number of things that _must_ or _must_not_ be assumed:
|
|||
STORE *(A + 4) = Y; STORE *A = X;
|
||||
STORE {*A, *(A + 4) } = {X, Y};
|
||||
|
||||
And there are anti-guarantees:
|
||||
|
||||
(*) These guarantees do not apply to bitfields, because compilers often
|
||||
generate code to modify these using non-atomic read-modify-write
|
||||
sequences. Do not attempt to use bitfields to synchronize parallel
|
||||
algorithms.
|
||||
|
||||
(*) Even in cases where bitfields are protected by locks, all fields
|
||||
in a given bitfield must be protected by one lock. If two fields
|
||||
in a given bitfield are protected by different locks, the compiler's
|
||||
non-atomic read-modify-write sequences can cause an update to one
|
||||
field to corrupt the value of an adjacent field.
|
||||
|
||||
(*) These guarantees apply only to properly aligned and sized scalar
|
||||
variables. "Properly sized" currently means variables that are
|
||||
the same size as "char", "short", "int" and "long". "Properly
|
||||
aligned" means the natural alignment, thus no constraints for
|
||||
"char", two-byte alignment for "short", four-byte alignment for
|
||||
"int", and either four-byte or eight-byte alignment for "long",
|
||||
on 32-bit and 64-bit systems, respectively. Note that these
|
||||
guarantees were introduced into the C11 standard, so beware when
|
||||
using older pre-C11 compilers (for example, gcc 4.6). The portion
|
||||
of the standard containing this guarantee is Section 3.14, which
|
||||
defines "memory location" as follows:
|
||||
|
||||
memory location
|
||||
either an object of scalar type, or a maximal sequence
|
||||
of adjacent bit-fields all having nonzero width
|
||||
|
||||
NOTE 1: Two threads of execution can update and access
|
||||
separate memory locations without interfering with
|
||||
each other.
|
||||
|
||||
NOTE 2: A bit-field and an adjacent non-bit-field member
|
||||
are in separate memory locations. The same applies
|
||||
to two bit-fields, if one is declared inside a nested
|
||||
structure declaration and the other is not, or if the two
|
||||
are separated by a zero-length bit-field declaration,
|
||||
or if they are separated by a non-bit-field member
|
||||
declaration. It is not safe to concurrently update two
|
||||
bit-fields in the same structure if all members declared
|
||||
between them are also bit-fields, no matter what the
|
||||
sizes of those intervening bit-fields happen to be.
|
||||
|
||||
|
||||
=========================
|
||||
WHAT ARE MEMORY BARRIERS?
|
||||
|
|
Loading…
Reference in New Issue