Commit 72b40807 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull kernel memory model updates from Paul McKenney:
 "Add more atomic operations, rework tags, and update documentation:

   - Add additional atomic operations (Puranjay Mohan)

   - Make better use of herd7 tags (Jonas Oberhauser)

   - Update documentation (Akira Yokosawa)

  These changes require v7.58 of the herd7 and klitmus tools, up from
  v7.52"

* tag 'lkmm.2025.03.21a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu:
  tools/memory-model: glossary.txt: Fix indents
  tools/memory-model/README: Fix typo
  tools/memory-model: Distinguish between syntactic and semantic tags
  tools/memory-model: Switch to softcoded herd7 tags
  tools/memory-model: Define effect of Mb tags on RMWs in tools/...
  tools/memory-model: Define applicable tags on operation in tools/...
  tools/memory-model: Legitimize current use of tags in LKMM macros
  tools/memory-model: Add atomic_andnot() with its variants
  tools/memory-model: Add atomic_and()/or()/xor() and add_negative
parents 418becac a2bfbf84
Loading
Loading
Loading
Loading
+26 −23
Original line number Diff line number Diff line
@@ -18,6 +18,11 @@
#
# By convention, a blank line in a cell means "same as the preceding line".
#
# Note that the syntactic representation does not always match the sets and
# relations in linux-kernel.cat, due to redefinitions in linux-kernel.bell and
# lock.cat. For example, the po link between LKR and LKW is upgraded to an rmw
# link, and W[ACQUIRE] are not included in the Acquire set.
#
# Disclaimer.  The table includes representations of "add" and "and" operations;
# corresponding/identical representations of "sub", "inc", "dec" and "or", "xor",
# "andnot" operations are omitted.
@@ -27,16 +32,16 @@
    ------------------------------------------------------------------------------
    |                    Non-RMW ops |                                           |
    ------------------------------------------------------------------------------
    |                      READ_ONCE | R[once]                                   |
    |                      READ_ONCE | R[ONCE]                                   |
    |                    atomic_read |                                           |
    |                     WRITE_ONCE | W[once]                                   |
    |                     WRITE_ONCE | W[ONCE]                                   |
    |                     atomic_set |                                           |
    |               smp_load_acquire | R[acquire]                                |
    |               smp_load_acquire | R[ACQUIRE]                                |
    |            atomic_read_acquire |                                           |
    |              smp_store_release | W[release]                                |
    |              smp_store_release | W[RELEASE]                                |
    |             atomic_set_release |                                           |
    |                   smp_store_mb | W[once] ->po F[mb]                        |
    |                         smp_mb | F[mb]                                     |
    |                   smp_store_mb | W[ONCE] ->po F[MB]                        |
    |                         smp_mb | F[MB]                                     |
    |                        smp_rmb | F[rmb]                                    |
    |                        smp_wmb | F[wmb]                                    |
    |          smp_mb__before_atomic | F[before-atomic]                          |
@@ -49,8 +54,8 @@
    |                  rcu_read_lock | F[rcu-lock]                               |
    |                rcu_read_unlock | F[rcu-unlock]                             |
    |                synchronize_rcu | F[sync-rcu]                               |
    |                rcu_dereference | R[once]                                   |
    |             rcu_assign_pointer | W[release]                                |
    |                rcu_dereference | R[ONCE]                                   |
    |             rcu_assign_pointer | W[RELEASE]                                |
    |                 srcu_read_lock | R[srcu-lock]                              |
    |                 srcu_down_read |                                           |
    |               srcu_read_unlock | W[srcu-unlock]                            |
@@ -60,32 +65,31 @@
    ------------------------------------------------------------------------------
    |       RMW ops w/o return value |                                           |
    ------------------------------------------------------------------------------
    |                     atomic_add | R*[noreturn] ->rmw W*[once]               |
    |                     atomic_add | R*[NORETURN] ->rmw W*[NORETURN]           |
    |                     atomic_and |                                           |
    |                      spin_lock | LKR ->po LKW                              |
    ------------------------------------------------------------------------------
    |        RMW ops w/ return value |                                           |
    ------------------------------------------------------------------------------
    |              atomic_add_return | F[mb] ->po R*[once]                       |
    |                                |     ->rmw W*[once] ->po F[mb]             |
    |              atomic_add_return | R*[MB] ->rmw W*[MB]                       |
    |               atomic_fetch_add |                                           |
    |               atomic_fetch_and |                                           |
    |                    atomic_xchg |                                           |
    |                           xchg |                                           |
    |            atomic_add_negative |                                           |
    |      atomic_add_return_relaxed | R*[once] ->rmw W*[once]                   |
    |      atomic_add_return_relaxed | R*[ONCE] ->rmw W*[ONCE]                   |
    |       atomic_fetch_add_relaxed |                                           |
    |       atomic_fetch_and_relaxed |                                           |
    |            atomic_xchg_relaxed |                                           |
    |                   xchg_relaxed |                                           |
    |    atomic_add_negative_relaxed |                                           |
    |      atomic_add_return_acquire | R*[acquire] ->rmw W*[once]                |
    |      atomic_add_return_acquire | R*[ACQUIRE] ->rmw W*[ACQUIRE]             |
    |       atomic_fetch_add_acquire |                                           |
    |       atomic_fetch_and_acquire |                                           |
    |            atomic_xchg_acquire |                                           |
    |                   xchg_acquire |                                           |
    |    atomic_add_negative_acquire |                                           |
    |      atomic_add_return_release | R*[once] ->rmw W*[release]                |
    |      atomic_add_return_release | R*[RELEASE] ->rmw W*[RELEASE]             |
    |       atomic_fetch_add_release |                                           |
    |       atomic_fetch_and_release |                                           |
    |            atomic_xchg_release |                                           |
@@ -94,17 +98,16 @@
    ------------------------------------------------------------------------------
    |            Conditional RMW ops |                                           |
    ------------------------------------------------------------------------------
    |                 atomic_cmpxchg | On success: F[mb] ->po R*[once]           |
    |                                |                 ->rmw W*[once] ->po F[mb] |
    |                                | On failure: R*[once]                      |
    |                 atomic_cmpxchg | On success: R*[MB] ->rmw W*[MB]           |
    |                                | On failure: R*[MB]                        |
    |                        cmpxchg |                                           |
    |              atomic_add_unless |                                           |
    |         atomic_cmpxchg_relaxed | On success: R*[once] ->rmw W*[once]       |
    |                                | On failure: R*[once]                      |
    |         atomic_cmpxchg_acquire | On success: R*[acquire] ->rmw W*[once]    |
    |                                | On failure: R*[once]                      |
    |         atomic_cmpxchg_release | On success: R*[once] ->rmw W*[release]    |
    |                                | On failure: R*[once]                      |
    |         atomic_cmpxchg_relaxed | On success: R*[ONCE] ->rmw W*[ONCE]       |
    |                                | On failure: R*[ONCE]                      |
    |         atomic_cmpxchg_acquire | On success: R*[ACQUIRE] ->rmw W*[ACQUIRE] |
    |                                | On failure: R*[ACQUIRE]                   |
    |         atomic_cmpxchg_release | On success: R*[RELEASE] ->rmw W*[RELEASE] |
    |                                | On failure: R*[RELEASE]                   |
    |                   spin_trylock | On success: LKR ->po LKW                  |
    |                                | On failure: LF                            |
    ------------------------------------------------------------------------------
+2 −2
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ that litmus test to be exercised within the Linux kernel.
REQUIREMENTS
============

Version 7.52 or higher of the "herd7" and "klitmus7" tools must be
Version 7.58 or higher of the "herd7" and "klitmus7" tools must be
downloaded separately:

  https://github.com/herd/herdtools7
@@ -79,7 +79,7 @@ Several thousand more example litmus tests are available here:
	https://git.kernel.org/pub/scm/linux/kernel/git/paulmck/perfbook.git/tree/CodeSamples/formal/herd
	https://git.kernel.org/pub/scm/linux/kernel/git/paulmck/perfbook.git/tree/CodeSamples/formal/litmus

Documentation describing litmus tests and now to use them may be found
Documentation describing litmus tests and how to use them may be found
here:

	tools/memory-model/Documentation/litmus-tests.txt
+24 −9
Original line number Diff line number Diff line
@@ -13,17 +13,18 @@

"Linux-kernel memory consistency model"

enum Accesses = 'once (*READ_ONCE,WRITE_ONCE*) ||
		'release (*smp_store_release*) ||
		'acquire (*smp_load_acquire*) ||
		'noreturn (* R of non-return RMW *)
instructions R[{'once,'acquire,'noreturn}]
instructions W[{'once,'release}]
instructions RMW[{'once,'acquire,'release}]
enum Accesses = 'ONCE (*READ_ONCE,WRITE_ONCE*) ||
		'RELEASE (*smp_store_release*) ||
		'ACQUIRE (*smp_load_acquire*) ||
		'NORETURN (* R of non-return RMW *) ||
		'MB (*xchg(),cmpxchg(),...*)
instructions R[Accesses]
instructions W[Accesses]
instructions RMW[Accesses]

enum Barriers = 'wmb (*smp_wmb*) ||
		'rmb (*smp_rmb*) ||
		'mb (*smp_mb*) ||
		'MB (*smp_mb*) ||
		'barrier (*barrier*) ||
		'rcu-lock (*rcu_read_lock*)  ||
		'rcu-unlock (*rcu_read_unlock*) ||
@@ -35,6 +36,17 @@ enum Barriers = 'wmb (*smp_wmb*) ||
		'after-srcu-read-unlock (*smp_mb__after_srcu_read_unlock*)
instructions F[Barriers]


(*
 * Filter out syntactic annotations that do not provide the corresponding
 * semantic ordering, such as Acquire on a store or Mb on a failed RMW.
 *)
let FailedRMW = RMW \ (domain(rmw) | range(rmw))
let Acquire = ACQUIRE \ W \ FailedRMW
let Release = RELEASE \ R \ FailedRMW
let Mb = MB \ FailedRMW
let Noreturn = NORETURN \ W

(* SRCU *)
enum SRCU = 'srcu-lock || 'srcu-unlock || 'sync-srcu
instructions SRCU[SRCU]
@@ -73,7 +85,7 @@ flag ~empty rcu-rscs & (po ; [Sync-srcu] ; po) as invalid-sleep
flag ~empty different-values(srcu-rscs) as srcu-bad-value-match

(* Compute marked and plain memory accesses *)
let Marked = (~M) | IW | Once | Release | Acquire | domain(rmw) | range(rmw) |
let Marked = (~M) | IW | ONCE | RELEASE | ACQUIRE | MB | RMW |
		LKR | LKW | UL | LF | RL | RU | Srcu-lock | Srcu-unlock
let Plain = M \ Marked

@@ -82,3 +94,6 @@ let carry-dep = (data ; [~ Srcu-unlock] ; rfi)*
let addr = carry-dep ; addr
let ctrl = carry-dep ; ctrl
let data = carry-dep ; data

flag ~empty (if "lkmmv2" then 0 else _)
  as this-model-requires-variant-higher-than-lkmmv1
+10 −0
Original line number Diff line number Diff line
@@ -34,6 +34,16 @@ let R4rmb = R \ Noreturn (* Reads for which rmb works *)
let rmb = [R4rmb] ; fencerel(Rmb) ; [R4rmb]
let wmb = [W] ; fencerel(Wmb) ; [W]
let mb = ([M] ; fencerel(Mb) ; [M]) |
	(*
	 * full-barrier RMWs (successful cmpxchg(), xchg(), etc.) act as
	 * though there were enclosed by smp_mb().
	 * The effect of these virtual smp_mb() is formalized by adding
	 * Mb tags to the read and write of the operation, and providing
	 * the same ordering as though there were additional po edges
	 * between the Mb tag and the read resp. write.
	 *)
	([M] ; po ; [Mb & R]) |
	([Mb & W] ; po ; [M]) |
	([M] ; fencerel(Before-atomic) ; [RMW] ; po? ; [M]) |
	([M] ; po? ; [RMW] ; fencerel(After-atomic) ; [M]) |
	([M] ; po? ; [LKW] ; fencerel(After-spinlock) ; [M]) |
+1 −0
Original line number Diff line number Diff line
macros linux-kernel.def
bell linux-kernel.bell
model linux-kernel.cat
variant lkmmv2
graph columns
squished true
showevents noregs
Loading