Commit 020e6c22 authored by Paul E. McKenney's avatar Paul E. McKenney
Browse files

kcsan: Add example to data_race() kerneldoc header



Although the data_race() kerneldoc header accurately states what it does,
some of the implications and usage patterns are non-obvious.  Therefore,
add a brief locking example and also state how to have KCSAN ignore
accesses while also preventing the compiler from folding, spindling,
or otherwise mutilating the access.

[ paulmck: Apply Bart Van Assche feedback. ]
[ paulmck: Apply feedback from Marco Elver. ]

Reported-by: default avatarBart Van Assche <bvanassche@acm.org>
Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
Cc: Marco Elver <elver@google.com>
Cc: Breno Leitao <leitao@debian.org>
Cc: Jens Axboe <axboe@kernel.dk>
parent 1613e604
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -194,9 +194,17 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
 * This data_race() macro is useful for situations in which data races
 * should be forgiven.  One example is diagnostic code that accesses
 * shared variables but is not a part of the core synchronization design.
 * For example, if accesses to a given variable are protected by a lock,
 * except for diagnostic code, then the accesses under the lock should
 * be plain C-language accesses and those in the diagnostic code should
 * use data_race().  This way, KCSAN will complain if buggy lockless
 * accesses to that variable are introduced, even if the buggy accesses
 * are protected by READ_ONCE() or WRITE_ONCE().
 *
 * This macro *does not* affect normal code generation, but is a hint
 * to tooling that data races here are to be ignored.
 * to tooling that data races here are to be ignored.  If the access must
 * be atomic *and* KCSAN should ignore the access, use both data_race()
 * and READ_ONCE(), for example, data_race(READ_ONCE(x)).
 */
#define data_race(expr)							\
({									\
+23 −1
Original line number Diff line number Diff line
@@ -24,6 +24,11 @@ The Linux kernel provides the following access-marking options:
4.	WRITE_ONCE(), for example, "WRITE_ONCE(a, b);"
	The various forms of atomic_set() also fit in here.

5.	__data_racy, for example "int __data_racy a;"

6.	KCSAN's negative-marking assertions, ASSERT_EXCLUSIVE_ACCESS()
	and ASSERT_EXCLUSIVE_WRITER(), are described in the
	"ACCESS-DOCUMENTATION OPTIONS" section below.

These may be used in combination, as shown in this admittedly improbable
example:
@@ -205,6 +210,23 @@ because doing otherwise prevents KCSAN from detecting violations of your
code's synchronization rules.


Use of __data_racy
------------------

Adding the __data_racy type qualifier to the declaration of a variable
causes KCSAN to treat all accesses to that variable as if they were
enclosed by data_race().  However, __data_racy does not affect the
compiler, though one could imagine hardened kernel builds treating the
__data_racy type qualifier as if it was the volatile keyword.

Note well that __data_racy is subject to the same pointer-declaration
rules as are other type qualifiers such as const and volatile.
For example:

	int __data_racy *p; // Pointer to data-racy data.
	int *__data_racy p; // Data-racy pointer to non-data-racy data.


ACCESS-DOCUMENTATION OPTIONS
============================

@@ -342,7 +364,7 @@ as follows:

Because foo is read locklessly, all accesses are marked.  The purpose
of the ASSERT_EXCLUSIVE_WRITER() is to allow KCSAN to check for a buggy
concurrent lockless write.
concurrent write, whether marked or not.


Lock-Protected Writes With Heuristic Lockless Reads