Skip to content

[herd] Consequences of splitting exclusive effects from the X events set (PR #1889)#1908

Merged
maranget merged 3 commits into
masterfrom
herd-is-exclusive-again
Jul 13, 2026
Merged

[herd] Consequences of splitting exclusive effects from the X events set (PR #1889)#1908
maranget merged 3 commits into
masterfrom
herd-is-exclusive-again

Conversation

@maranget

@maranget maranget commented Jul 9, 2026

Copy link
Copy Markdown
Member

This PR groups three commits

  1. Fixing the RISCV model (and the collect_atomics function from memUtils.ml)
  2. Add some RISCV tests that check the problem fixed in 1.
  3. Fix the computation of "atomic pairs" in OCaml, this computation was wrong before PR [herd] Split exclusive accesses from the X event set #1889: the cases of AMO's and exclusive accessed were not separated as they should be.

As to 3., notice that, since PR #1889, there is no need to compute atomic pairs in OCaml for AArch64 and possibly for all Cat model (perhaps at the price of a small optimisation of -optace iico). Implementation of limiting the usage of the OCaml code for atomic pairs not being that straightforward, we leave that to a further PR.

@maranget maranget force-pushed the herd-is-exclusive-again branch from 9be33ad to 07f8f11 Compare July 9, 2026 10:58
@maranget maranget changed the title [herd] Consequences of splitting exclusives effects from the X events set (PR #1889) [herd] Consequences of splitting exclusive effects from the X events set (PR #1889) Jul 9, 2026
Comment thread herd/mem.ml
* closest generalised po successor exclusive store,
* by using a set of stores ordered by po.
* We additionally check that no exclusive read exists
* between the read and the write.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe good to add that this would not work for AArch64 because it only constructs pairs at the same location? And that it constructs pairs that have an interleaving read at a different location?

Suggested change
* between the read and the write.
* between the read and the write. Notice that the pairs generated here
* have the same location. Notice that the pairs generated do not check
* for the presence of an interleaving read at another location.

I do not know if the riscv semantics in herd prevent those cases from happening, or if those cases are not a problem for riscv, but I thought it would be important to flag this.
If this is a problem for riscv, it can be left as a subsequent PR, or an open issue, as this behaviour was present before this PR.

@maranget maranget Jul 9, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not understand "This would not work for AArch64 [...]".

As for the presence of an interleaving (exclusive) read at another location, we should at least add a test. At the moment, the current code pairs LDXR [x] abd STXR [x] in LDXR [x]; LDXR [y]; STXR [x] (The STXR [x] can succeed and generate a write effect in spite of the reservation being to y). This contradicts the Cat definition of lxsx:

let lxsx = [R&EX]; po \ (p; [M&EX]; po); [W&EX]

Namely, the Cat definition does not pair LDXR [x] and STXR [X], due to the interleaving exclusive read on y (po; [M&EX]; po above).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is the test:

AArch64 LXSX0C
{
0:X0=x;
0:X2=y;
0:X1=1;
1:X0=x;
1:X1=2;
}
  P0             | P1          ;
 LDXR W3,[X0]    | STR W1,[X0] ;
 LDXR W5,[X2]    |             ;
 STXR W7,W1,[X0] |             ;
exists 0:X3=0 /\ [x]=1
A Diagram made with PR #1896.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is observed on a variety of machines with option -mode presi.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This contradicts the Cat definition of lxsx

My comment was exactly this: we should document that what this ocaml code computes is not in sync with the cat definition of lxsx, and would roughly correspond to the following definition:

let lxsx' =
  let poloc = po & loc in
  [R&EX]; poloc \ (poloc; [M&EX]; poloc); [W&EX]

As far as I understand, this does not have any consequences for AArch64, because the results of this algorithm are overridden by the cat definition. However, maybe it has a consequence for riscv because the results of this algorithm are used to compute ppo?


This test is observed on a variety of machines with option -mode presi.

I'm not familiar with the -mode presi, could you explain what this means?


we should at least add a test

Agreed. Please do add it!

@maranget maranget Jul 10, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My idea would rather be to have OCaml and Cat to compute the same lxsx. Stay tuned.

I suspect that the test succeeds when x and y are in the same cache line or, less precisely, when their addresses are close. In mode -mode presi x and y are either in the same cache line or in successive cache lines. In standard mode, x and y are close with small size parameter (e.g. -s 4). This "x and y are close" assumption is compatible with experiments.

This test is for PR #1896, it would fail here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My idea would rather be to have OCaml and Cat to compute the same lxsx. Stay tuned.

I haven't had a look at the code yet, but is this about lxsx only or about the whole of rmw?

What is the benefit in having this ability? The Ocaml code is relatively complex and evidently hard to get right.

Also is the idea that both calculations would be enabled at the same time?

@maranget maranget Jul 10, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @relokin. You are right, this PR lacks motivation. At the moment the OCaml code for computing lxsx, amo and rmw as lxsx|amo is still useful

  1. For the few, legacy, non-cat models
  2. For optimisations (as far as I have checked, for -optace iico|true)
  3. For computing dependencies in OCaml, which applies to all models except aarch64.cat

We have to keep the code for 1. alone, we can probably get rid of 2. and 3. is still unclear to me. I plan to look at this when I am back at the end of July. But before, I'd like to have the OCaml code to match the Cat definitions.

Comment thread herd/libdir/riscv-tso-defs.cat Outdated
@maranget maranget force-pushed the herd-is-exclusive-again branch from 07f8f11 to 73325b8 Compare July 9, 2026 17:44
@maranget maranget marked this pull request as draft July 10, 2026 13:50
@maranget maranget force-pushed the herd-is-exclusive-again branch from 73325b8 to 67cb82e Compare July 10, 2026 15:53
Comment thread herd/mem.ml Outdated
Comment on lines +1995 to +2007
let po =
let rec do_rec k = function
| [] -> E.EventRel.of_list k
| e0::es ->
let k =
List.fold_left
(fun k e ->
if E.po_strict e0 e then (e0,e)::k
else if E.po_strict e e0 then (e,e0)::k
else k)
k es in
do_rec k es in
do_rec [] evts in

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this just EventRel.of_pred es es E.po_strict?

Suggested change
let po =
let rec do_rec k = function
| [] -> E.EventRel.of_list k
| e0::es ->
let k =
List.fold_left
(fun k e ->
if E.po_strict e0 e then (e0,e)::k
else if E.po_strict e e0 then (e,e0)::k
else k)
k es in
do_rec k es in
do_rec [] evts in
let po = E.EventRel.of_pred es es E.po_strict in

@maranget maranget Jul 10, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because es is a list and not a set....

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Admittedly, I could have written a function fold_pairs_once in misc.ml.

@maranget maranget marked this pull request as ready for review July 11, 2026 06:36
@maranget maranget force-pushed the herd-is-exclusive-again branch from 67cb82e to 9077f97 Compare July 12, 2026 07:06
maranget added 2 commits July 13, 2026 11:52
This commit regroups three changes related to
the new organisation of "atomic" accesses performed
by PR #1889: such effects are now partitioned into the sets 'X'
(emited by access-modify instructions, OCaml function `is_atomic`)
and 'EX' (emited by exclusive access instructions, _i.e._
load reserve and store conditional, OCaml function `is_exclusive`).
Notice that before the OCaml function `is_atomic` and the
Cat set `X` were gathering all such effects. Also
notice that `is_exclusive` was absent and that
there existed a set `AMO` gathering the memory
write effects emited by access-modify instructions.

  1. Noticing that `is_atomic` no longer holds on
  effects generated by exclusive load and store,
  change `collect_atomics` (from memUtils.ml)
  names and code  into `collect_atomics_and_exclusives`.
  2. Modify the RISCV Cat models to account
  for the new semantics of the sets 'X'
  and `EX`.
  3. Remove the Cat set `AMO` and
  the code that computed it.
The new tests are sensitive to the sets AMO and EX being correct.
@maranget maranget force-pushed the herd-is-exclusive-again branch from 9077f97 to 4d36cb0 Compare July 13, 2026 09:54
We compute non-explicit atomic pairs as the restriction
of `iico_data` from non-explicit atomic reads to non-explicit
atomic writes. We here rely on the assumption that *all* atomic pairs of
non-explicit accesses result from page table updates.

As for explicit accesses, we compute AMO's and exclusives differently.
 + AMO -> The read and the write are generated by the same instruction
 + Exclusives -> No exclusive in-between.

Code for exclusives closely follows the Cat definition
```
let lxsx = [R&EX]; po/(po;[M&EX];po); [W&EX]
```
This proved to be the most robust solution...
@maranget maranget force-pushed the herd-is-exclusive-again branch from 4d36cb0 to 2d6247f Compare July 13, 2026 10:02
@maranget

Copy link
Copy Markdown
Member Author

Thanks @HadrienRenaud and @relokin, merging.

@maranget maranget merged commit 43666f0 into master Jul 13, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants