[PATCH 18/28] Documentation/litmus-tests: Add hazptr drain safety test

From: Kunwu Chan

Date: Wed Nov 04 2026 - 12:07:40 EST


Model the drain engage snapshot race: the engage may read a
slot as empty or wildcard while an in-flight slow-path acquire
still sees the pre-unpublish head. The Sometimes result
confirms the window exists; the engage's wildcard check (see
the engage-wildcard test) closes the gap by deferring
(herd7: Sometimes).

Signed-off-by: Kunwu Chan <kunwu.chan@xxxxxxxxx>
---
Documentation/litmus-tests/README | 4 ++
.../hazptr/hazptr-drain-safety.litmus | 43 +++++++++++++++++++
2 files changed, 47 insertions(+)
create mode 100644 Documentation/litmus-tests/hazptr/hazptr-drain-safety.litmus

diff --git a/Documentation/litmus-tests/README b/Documentation/litmus-tests/README
index 02c26d6bea50..604c2c0025d9 100644
--- a/Documentation/litmus-tests/README
+++ b/Documentation/litmus-tests/README
@@ -119,3 +119,7 @@ hazptr-drain-engage-wildcard.litmus
hazptr-drain-resnapshot-slot-race.litmus
Test the marker consumption race between the resnapshot recovery
path and a reader release: only one path may consume the marker.
+
+hazptr-drain-safety.litmus
+ Test the engage snapshot race: the engage can miss an in-flight
+ slow-path acquire, so completion must defer on wildcards.
diff --git a/Documentation/litmus-tests/hazptr/hazptr-drain-safety.litmus b/Documentation/litmus-tests/hazptr/hazptr-drain-safety.litmus
new file mode 100644
index 000000000000..a0ec1a063642
--- /dev/null
+++ b/Documentation/litmus-tests/hazptr/hazptr-drain-safety.litmus
@@ -0,0 +1,43 @@
+C hazptr-drain-safety
+
+(*
+ * Result: Sometimes
+ *
+ * Models the drain engage snapshot race: the engage (P0)
+ * unpublishes the object (head=0) and reads the slot, while
+ * a slow-path reader (P1) publishes a wildcard (1), then
+ * replaces it with the target address (2).
+ *
+ * The engage may read 0 (empty), 1 (wildcard), or 2 (target).
+ * Reading 0 or 1 while the reader sees head=1 means the
+ * snapshot missed an in-flight acquire — the Sometimes result
+ * confirms this window exists. The engage's wildcard check
+ * (hazptr-drain-engage-wildcard) closes the gap by deferring
+ * when it reads the wildcard value.
+ *)
+
+{
+ head = 1;
+ slot = 0;
+}
+
+P0(int *head, int *slot)
+{
+ int r0;
+
+ WRITE_ONCE(*head, 0);
+ smp_mb();
+ r0 = READ_ONCE(*slot);
+}
+
+P1(int *slot, int *head)
+{
+ int r1;
+
+ WRITE_ONCE(*slot, 1);
+ smp_mb();
+ WRITE_ONCE(*slot, 2);
+ r1 = READ_ONCE(*head);
+}
+
+exists ((0:r0=0 \/ 0:r0=1) /\ 1:r1=1)
--
2.43.0