Skip to content

Commit f190897

Browse files
committed
genmc doc edits
1 parent 679cf9f commit f190897

File tree

1 file changed

+17
-19
lines changed

1 file changed

+17
-19
lines changed

doc/genmc.md

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -63,18 +63,14 @@ Note that `cargo miri test` in GenMC mode is currently not supported.
6363

6464
### Eliminating unbounded loops
6565

66-
#### Limiting the number of explored executions
66+
As mentioned above, GenMC requires all loops to be bounded.
67+
Otherwise, it is not possible to exhaustively explore all executions.
68+
Currently, Miri-GenMC has no support for automatically bounding loops, so this needs to be done manually.
6769

68-
The number of explored executions in a concurrent program can increase super-exponentially in the size of the program.
69-
Reducing the number of explored executions is the most impactful way to improve verification times.
70-
Some programs also contain possibly infinite loops, which are not supported by GenMC.
70+
#### Bounding loops without side effects
7171

72-
One way to drastically improve verification performance is by bounding spinloops.
73-
A spinloop may loop a many times before it can finally make progress.
74-
If such a loop doesn't have any visible side effects, meaning it does not matter to the outcome of the program whether the loop ran once or a million time, then the loop can be limited to one iteration.
75-
76-
The following code gives an example for how to replace a loop that waits for a boolean to be true.
77-
Since there are no side effects, replacing the loop with one iteration is safe.
72+
The easiest case is that of a loop that simply spins until it observes a certain condition, without any side effects.
73+
Such loops can be limited to one iteration, as demonstrated by the following example:
7874

7975
```rust
8076
#[cfg(miri)]
@@ -84,21 +80,23 @@ unsafe extern "Rust" {
8480
pub unsafe fn miri_genmc_assume(condition: bool);
8581
}
8682

87-
/// This functions loads an atomic boolean in a loop until it is true.
88-
/// GenMC will explore all executions where this does 1, 2, ..., ∞ loads, which means the verification will never terminate.
83+
// This functions loads an atomic boolean in a loop until it is true.
84+
// GenMC will explore all executions where this does 1, 2, ..., ∞ loads, which means the verification will never terminate.
8985
fn spin_until_true(flag: &AtomicBool) {
90-
while (!flag.load(Relaxed)) {
86+
while !flag.load(Relaxed) {
9187
std::hint::spin_loop();
9288
}
9389
}
9490

95-
/// By replacing this loop with an assume statement, the only executions that will be explored are those with exactly 1 load.
96-
/// Incorrect use of assume statements can lead GenMC to miss important executions, so it is marked `unsafe`.
91+
// By replacing this loop with an assume statement, the only executions that will be explored are those with exactly 1 load that observes the expected value.
92+
// Incorrect use of assume statements can lead GenMC to miss important executions, so it is marked `unsafe`.
9793
fn spin_until_true_genmc(flag: &AtomicBool) {
98-
unsafe { miri_genmc_assume(flag.load(Relaxed)); }
94+
unsafe { miri_genmc_assume(flag.load(Relaxed)) };
9995
}
10096
```
10197

98+
#### Bounding loops with side effects
99+
102100
Some loops do contain side effects, meaning the number of explored iterations affects the rest of the program.
103101
Replacing the loop with one iteration like we did above would mean we miss all those possible executions.
104102

@@ -110,11 +108,11 @@ The choice of iteration limit trades off verification time for possibly missing
110108
/// Instead of replacing the loop entirely (which would miss all executions with `count > 0`), we limit the loop to at most 3 iterations.
111109
fn count_until_true_genmc(flag: &AtomicBool) -> u64 {
112110
let mut count = 0;
113-
while (!flag.load(Relaxed)) {
114-
// Any execution that takes more than 3 iterations will not be explored.
115-
unsafe { miri_genmc_assume(count < 3); }
111+
while !flag.load(Relaxed) {
116112
count += 1;
117113
std::hint::spin_loop();
114+
// Any execution that takes more than 3 iterations will not be explored.
115+
unsafe { miri_genmc_assume(count <= 3) };
118116
}
119117
count
120118
}

0 commit comments

Comments
 (0)