You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: doc/genmc.md
+17-19Lines changed: 17 additions & 19 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -63,18 +63,14 @@ Note that `cargo miri test` in GenMC mode is currently not supported.
63
63
64
64
### Eliminating unbounded loops
65
65
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.
67
69
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
71
71
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:
78
74
79
75
```rust
80
76
#[cfg(miri)]
@@ -84,21 +80,23 @@ unsafe extern "Rust" {
84
80
pubunsafefnmiri_genmc_assume(condition:bool);
85
81
}
86
82
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.
89
85
fnspin_until_true(flag:&AtomicBool) {
90
-
while(!flag.load(Relaxed)) {
86
+
while!flag.load(Relaxed) {
91
87
std::hint::spin_loop();
92
88
}
93
89
}
94
90
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`.
97
93
fnspin_until_true_genmc(flag:&AtomicBool) {
98
-
unsafe { miri_genmc_assume(flag.load(Relaxed)); }
94
+
unsafe { miri_genmc_assume(flag.load(Relaxed)) };
99
95
}
100
96
```
101
97
98
+
#### Bounding loops with side effects
99
+
102
100
Some loops do contain side effects, meaning the number of explored iterations affects the rest of the program.
103
101
Replacing the loop with one iteration like we did above would mean we miss all those possible executions.
104
102
@@ -110,11 +108,11 @@ The choice of iteration limit trades off verification time for possibly missing
110
108
/// Instead of replacing the loop entirely (which would miss all executions with `count > 0`), we limit the loop to at most 3 iterations.
0 commit comments