Skip to content

Commit 4c830ee

Browse files
AlanSternpaulmckrcu
authored andcommitted
tools/memory-model: Fix bug in lock.cat
Andrea reported that the following innocuous litmus test: C T {} P0(spinlock_t *x) { int r0; spin_lock(x); spin_unlock(x); r0 = spin_is_locked(x); } gives rise to a nonsensical empty result with no executions: $ herd7 -conf linux-kernel.cfg T.litmus Test T Required States 0 Ok Witnesses Positive: 0 Negative: 0 Condition forall (true) Observation T Never 0 0 Time T 0.00 Hash=6fa204e139ddddf2cb6fa963bad117c0 The problem is caused by a bug in the lock.cat part of the LKMM. Its computation of the rf relation for RU (read-unlocked) events is faulty; it implicitly assumes that every RU event must read from either a UL (unlock) event in another thread or from the lock's initial state. Neither is true in the litmus test above, so the computation yields no possible executions. The lock.cat code tries to make up for this deficiency by allowing RU events outside of critical sections to read from the last po-previous UL event. But it does this incorrectly, trying to keep these rfi links separate from the rfe links that might also be needed, and passing only the latter to herd7's cross() macro. The problem is fixed by merging the two sets of possible rf links for RU events and using them all in the call to cross(). Signed-off-by: Alan Stern <[email protected]> Reported-by: Andrea Parri <[email protected]> Closes: https://lore.kernel.org/linux-arch/ZlC0IkzpQdeGj+a3@andrea/ Tested-by: Andrea Parri <[email protected]> Acked-by: Andrea Parri <[email protected]> Fixes: 15553dc ("tools/memory-model: Add model support for spin_is_locked()") CC: <[email protected]> Signed-off-by: Paul E. McKenney <[email protected]>
1 parent 520c637 commit 4c830ee

File tree

1 file changed

+10
-10
lines changed

1 file changed

+10
-10
lines changed

tools/memory-model/lock.cat

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -102,19 +102,19 @@ let rf-lf = rfe-lf | rfi-lf
102102
* within one of the lock's critical sections returns False.
103103
*)
104104

105-
(* rfi for RU events: an RU may read from the last po-previous UL *)
106-
let rfi-ru = ([UL] ; po-loc ; [RU]) \ ([UL] ; po-loc ; [LKW] ; po-loc)
107-
108-
(* rfe for RU events: an RU may read from an external UL or the initial write *)
109-
let all-possible-rfe-ru =
110-
let possible-rfe-ru r =
105+
(*
106+
* rf for RU events: an RU may read from an external UL or the initial write,
107+
* or from the last po-previous UL
108+
*)
109+
let all-possible-rf-ru =
110+
let possible-rf-ru r =
111111
let pair-to-relation p = p ++ 0
112-
in map pair-to-relation (((UL | IW) * {r}) & loc & ext)
113-
in map possible-rfe-ru RU
112+
in map pair-to-relation ((((UL | IW) * {r}) & loc & ext) |
113+
(((UL * {r}) & po-loc) \ ([UL] ; po-loc ; [LKW] ; po-loc)))
114+
in map possible-rf-ru RU
114115

115116
(* Generate all rf relations for RU events *)
116-
with rfe-ru from cross(all-possible-rfe-ru)
117-
let rf-ru = rfe-ru | rfi-ru
117+
with rf-ru from cross(all-possible-rf-ru)
118118

119119
(* Final rf relation *)
120120
let rf = rf | rf-lf | rf-ru

0 commit comments

Comments
 (0)