mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-15 02:31:35 -04:00
Merge tag 'lkmm.2025.05.25a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu
Pull lkmm updates from Paul McKenney: "Update LKMM documentation: - Cross-references, typos, broken URLs (Akira Yokosawa) - Clarify SRCU explanation (Uladzislau Rezki)" * tag 'lkmm.2025.05.25a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu: tools/memory-model/Documentation: Fix SRCU section in explanation.txt tools/memory-model: docs/references: Remove broken link to imgtec.com tools/memory-model: docs/ordering: Fix trivial typos tools/memory-model: docs/simple.txt: Fix trivial typos tools/memory-model: docs/README: Update introduction of locking.txt
This commit is contained in:
@@ -23,8 +23,11 @@ o You are familiar with the Linux-kernel concurrency primitives
|
||||
that you need, and just want to get started with LKMM litmus
|
||||
tests: litmus-tests.txt
|
||||
|
||||
o You would like to access lock-protected shared variables without
|
||||
having their corresponding locks held: locking.txt
|
||||
o You need to locklessly access shared variables that are otherwise
|
||||
protected by a lock: locking.txt
|
||||
|
||||
This locking.txt file expands on the "Locking" section in
|
||||
recipes.txt, but is self-contained.
|
||||
|
||||
o You are familiar with Linux-kernel concurrency, and would
|
||||
like a detailed intuitive understanding of LKMM, including
|
||||
|
||||
@@ -1896,7 +1896,7 @@ following respects:
|
||||
|
||||
3. The srcu_down_read() and srcu_up_read() primitives work
|
||||
exactly like srcu_read_lock() and srcu_read_unlock(), except
|
||||
that matching calls don't have to execute on the same CPU.
|
||||
that matching calls don't have to execute within the same context.
|
||||
(The names are meant to be suggestive of operations on
|
||||
semaphores.) Since the matching is determined by the domain
|
||||
pointer and index value, these primitives make it possible for
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
[!] Note:
|
||||
This file expands on the "Locking" section of recipes.txt,
|
||||
focusing on locklessly accessing shared variables that are
|
||||
otherwise protected by a lock.
|
||||
|
||||
Locking
|
||||
=======
|
||||
|
||||
|
||||
@@ -223,7 +223,7 @@ The Linux kernel's compiler barrier is barrier(). This primitive
|
||||
prohibits compiler code-motion optimizations that might move memory
|
||||
references across the point in the code containing the barrier(), but
|
||||
does not constrain hardware memory ordering. For example, this can be
|
||||
used to prevent to compiler from moving code across an infinite loop:
|
||||
used to prevent the compiler from moving code across an infinite loop:
|
||||
|
||||
WRITE_ONCE(x, 1);
|
||||
while (dontstop)
|
||||
@@ -274,7 +274,7 @@ different pieces of the concurrent algorithm. The variable stored to
|
||||
by the smp_store_release(), in this case "y", will normally be used in
|
||||
an acquire operation in other parts of the concurrent algorithm.
|
||||
|
||||
To see the performance advantages, suppose that the above example read
|
||||
To see the performance advantages, suppose that the above example reads
|
||||
from "x" instead of writing to it. Then an smp_wmb() could not guarantee
|
||||
ordering, and an smp_mb() would be needed instead:
|
||||
|
||||
@@ -394,17 +394,17 @@ from the value returned by the rcu_dereference() or srcu_dereference()
|
||||
to that subsequent memory access.
|
||||
|
||||
A call to rcu_dereference() for a given RCU-protected pointer is
|
||||
usually paired with a call to a call to rcu_assign_pointer() for that
|
||||
same pointer in much the same way that a call to smp_load_acquire() is
|
||||
paired with a call to smp_store_release(). Calls to rcu_dereference()
|
||||
and rcu_assign_pointer are often buried in other APIs, for example,
|
||||
usually paired with a call to rcu_assign_pointer() for that same pointer
|
||||
in much the same way that a call to smp_load_acquire() is paired with
|
||||
a call to smp_store_release(). Calls to rcu_dereference() and
|
||||
rcu_assign_pointer() are often buried in other APIs, for example,
|
||||
the RCU list API members defined in include/linux/rculist.h. For more
|
||||
information, please see the docbook headers in that file, the most
|
||||
recent LWN article on the RCU API (https://lwn.net/Articles/777036/),
|
||||
recent LWN article on the RCU API (https://lwn.net/Articles/988638/),
|
||||
and of course the material in Documentation/RCU.
|
||||
|
||||
If the pointer value is manipulated between the rcu_dereference()
|
||||
that returned it and a later dereference(), please read
|
||||
that returned it and a later rcu_dereference(), please read
|
||||
Documentation/RCU/rcu_dereference.rst. It can also be quite helpful to
|
||||
review uses in the Linux kernel.
|
||||
|
||||
@@ -457,7 +457,7 @@ described earlier in this document.
|
||||
These operations come in three categories:
|
||||
|
||||
o Marked writes, such as WRITE_ONCE() and atomic_set(). These
|
||||
primitives required the compiler to emit the corresponding store
|
||||
primitives require the compiler to emit the corresponding store
|
||||
instructions in the expected execution order, thus suppressing
|
||||
a number of destructive optimizations. However, they provide no
|
||||
hardware ordering guarantees, and in fact many CPUs will happily
|
||||
@@ -465,7 +465,7 @@ o Marked writes, such as WRITE_ONCE() and atomic_set(). These
|
||||
operations, unless these operations are to the same variable.
|
||||
|
||||
o Marked reads, such as READ_ONCE() and atomic_read(). These
|
||||
primitives required the compiler to emit the corresponding load
|
||||
primitives require the compiler to emit the corresponding load
|
||||
instructions in the expected execution order, thus suppressing
|
||||
a number of destructive optimizations. However, they provide no
|
||||
hardware ordering guarantees, and in fact many CPUs will happily
|
||||
@@ -506,7 +506,7 @@ of the old value and the new value.
|
||||
|
||||
Unmarked C-language accesses are unordered, and are also subject to
|
||||
any number of compiler optimizations, many of which can break your
|
||||
concurrent code. It is possible to used unmarked C-language accesses for
|
||||
concurrent code. It is possible to use unmarked C-language accesses for
|
||||
shared variables that are subject to concurrent access, but great care
|
||||
is required on an ongoing basis. The compiler-constraining barrier()
|
||||
primitive can be helpful, as can the various ordering primitives discussed
|
||||
|
||||
@@ -61,6 +61,10 @@ usual) some things to be careful of:
|
||||
Locking
|
||||
-------
|
||||
|
||||
[!] Note:
|
||||
locking.txt expands on this section, providing more detail on
|
||||
locklessly accessing lock-protected shared variables.
|
||||
|
||||
Locking is well-known and straightforward, at least if you don't think
|
||||
about it too hard. And the basic rule is indeed quite simple: Any CPU that
|
||||
has acquired a given lock sees any changes previously seen or made by any
|
||||
|
||||
@@ -46,8 +46,7 @@ o ARM Ltd. (Ed.). 2014. "ARM Architecture Reference Manual (ARMv8,
|
||||
|
||||
o Imagination Technologies, LTD. 2015. "MIPS(R) Architecture
|
||||
For Programmers, Volume II-A: The MIPS64(R) Instruction,
|
||||
Set Reference Manual". Imagination Technologies,
|
||||
LTD. https://imgtec.com/?do-download=4302.
|
||||
Set Reference Manual". Imagination Technologies, LTD.
|
||||
|
||||
o Shaked Flur, Kathryn E. Gray, Christopher Pulte, Susmit
|
||||
Sarkar, Ali Sezgin, Luc Maranget, Will Deacon, and Peter
|
||||
|
||||
@@ -134,7 +134,7 @@ Packaged primitives: Sequence locking
|
||||
Lockless programming is considered by many to be more difficult than
|
||||
lock-based programming, but there are a few lockless design patterns that
|
||||
have been built out into an API. One of these APIs is sequence locking.
|
||||
Although this APIs can be used in extremely complex ways, there are simple
|
||||
Although this API can be used in extremely complex ways, there are simple
|
||||
and effective ways of using it that avoid the need to pay attention to
|
||||
memory ordering.
|
||||
|
||||
@@ -205,7 +205,7 @@ If you want to keep things simple, use the initialization and read-out
|
||||
operations from the previous section only when there are no racing
|
||||
accesses. Otherwise, use only fully ordered operations when accessing
|
||||
or modifying the variable. This approach guarantees that code prior
|
||||
to a given access to that variable will be seen by all CPUs has having
|
||||
to a given access to that variable will be seen by all CPUs as having
|
||||
happened before any code following any later access to that same variable.
|
||||
|
||||
Please note that per-CPU functions are not atomic operations and
|
||||
|
||||
Reference in New Issue
Block a user