tools/memory-model/Documentation/control-dependencies.txt

Source file repositories/reference/linux-study-clean/tools/memory-model/Documentation/control-dependencies.txt

File Facts

System
Linux kernel
Corpus path
tools/memory-model/Documentation/control-dependencies.txt
Extension
.txt
Size
9524 bytes
Lines
259
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: documentation
Status
atlas-only

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

CONTROL DEPENDENCIES
====================

A major difficulty with control dependencies is that current compilers
do not support them.  One purpose of this document is therefore to
help you prevent your compiler from breaking your code.  However,
control dependencies also pose other challenges, which leads to the
second purpose of this document, namely to help you to avoid breaking
your own code, even in the absence of help from your compiler.

One such challenge is that control dependencies order only later stores.
Therefore, a load-load control dependency will not preserve ordering
unless a read memory barrier is provided.  Consider the following code:

	q = READ_ONCE(a);
	if (q)
		p = READ_ONCE(b);

This is not guaranteed to provide any ordering because some types of CPUs
are permitted to predict the result of the load from "b".  This prediction
can cause other CPUs to see this load as having happened before the load
from "a".  This means that an explicit read barrier is required, for example
as follows:

	q = READ_ONCE(a);
	if (q) {
		smp_rmb();
		p = READ_ONCE(b);
	}

However, stores are not speculated.  This means that ordering is
(usually) guaranteed for load-store control dependencies, as in the
following example:

	q = READ_ONCE(a);
	if (q)
		WRITE_ONCE(b, 1);

Control dependencies can pair with each other and with other types
of ordering.  But please note that neither the READ_ONCE() nor the
WRITE_ONCE() are optional.  Without the READ_ONCE(), the compiler might
fuse the load from "a" with other loads.  Without the WRITE_ONCE(),
the compiler might fuse the store to "b" with other stores.  Worse yet,
the compiler might convert the store into a load and a check followed
by a store, and this compiler-generated load would not be ordered by
the control dependency.

Furthermore, if the compiler is able to prove that the value of variable
"a" is always non-zero, it would be well within its rights to optimize
the original example by eliminating the "if" statement as follows:

	q = a;
	b = 1;  /* BUG: Compiler and CPU can both reorder!!! */

So don't leave out either the READ_ONCE() or the WRITE_ONCE().
In particular, although READ_ONCE() does force the compiler to emit a
load, it does *not* force the compiler to actually use the loaded value.

It is tempting to try use control dependencies to enforce ordering on
identical stores on both branches of the "if" statement as follows:

	q = READ_ONCE(a);
	if (q) {
		barrier();
		WRITE_ONCE(b, 1);
		do_something();
	} else {
		barrier();
		WRITE_ONCE(b, 1);
		do_something_else();

Annotation

Implementation Notes