[ltt-dev] [PATCH v2 1/3] new futex model
Paolo Bonzini
pbonzini at redhat.com
Wed Aug 17 04:28:12 EDT 2011
Rewrite the model to include the futex primitives and the list
move algorithm used by urcu. The model implements a full-blown
parity-flipping RCU where grace period waits are driven exclusively
by futexes. It runs the waker and waiter infinitely, asserting
that progress states (parity flips) are reached infinite times.
---
futex-wakeup/DEFINES | 2 +-
futex-wakeup/futex.ltl | 2 +-
futex-wakeup/futex.spin | 134 +++++++++++++++++++++++++----------------------
3 files changed, 73 insertions(+), 65 deletions(-)
diff --git a/futex-wakeup/DEFINES b/futex-wakeup/DEFINES
index e328b55..3e0a545 100644
--- a/futex-wakeup/DEFINES
+++ b/futex-wakeup/DEFINES
@@ -1 +1 @@
-#define queue_has_entry (queue[0] == 1 || queue[1] == 1)
+/* no defines needed yet */
diff --git a/futex-wakeup/futex.ltl b/futex-wakeup/futex.ltl
index 3d6842e..8718641 100644
--- a/futex-wakeup/futex.ltl
+++ b/futex-wakeup/futex.ltl
@@ -1 +1 @@
-([] <> ((!np_) || (!queue_has_entry)))
+([] <> !np_)
diff --git a/futex-wakeup/futex.spin b/futex-wakeup/futex.spin
index 5459a53..ab41a0a 100644
--- a/futex-wakeup/futex.spin
+++ b/futex-wakeup/futex.spin
@@ -4,30 +4,39 @@
* Algorithm verified :
*
* queue = 0;
- * fut = 0;
- * runvar = 0;
+ * waiting = 0;
+ * gp_futex = 0;
+ * gp = 1;
*
- * Waker
- * queue = 1;
- * if (fut == -1) {
- * fut = 0;
+ * Waker
+ * while (1) {
+ * this.queue = gp;
+ * if (gp_futex == -1) {
+ * gp_futex = 0;
+ * futex_wake = 1;
* }
+ * }
*
* Waiter
+ * in_registry = 1;
* while (1) {
- * progress:
- * fut = fut - 1;
- * if (queue == 1) {
- * fut = 0;
+ * gp_futex = -1;
+ * in_registry &= (queue != gp);
+ * if (all in_registry == 0) {
+ * progress:
+ * gp_futex = 0;
+ * gp = !gp;
+ * restart;
* } else {
- * if (fut == -1) {
- * while (fut == -1) { }
- * }
+ * futex_wake = (gp_futex == -1 ? 0 : 1);
+ * while (futex_wake == 0) { }
* }
* queue = 0;
* }
*
- * if queue = 1, then !_np
+ * By testing progress, i.e. [] <> !np_, we check that an infinite sequence
+ * of update_counter_and_wait (and consequently of synchronize_rcu) will
+ * not block.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -49,76 +56,77 @@
#define get_pid() (_pid)
int queue[2] = 0;
-int fut = 0;
+int futex_wake = 0;
+int gp_futex = 0;
+int gp = 1;
+int in_registry[2] = 0;
active [2] proctype waker()
{
assert(get_pid() < 2);
- queue[get_pid()] = 1;
-
- if
- :: (fut == -1) ->
- fut = 0;
- :: else ->
- skip;
- fi;
-
- queue[get_pid()] = 1;
-
- if
- :: (fut == -1) ->
- fut = 0;
- :: else ->
- skip;
- fi;
-
-#ifdef INJ_QUEUE_NO_WAKE
- queue[get_pid()] = 1;
+ do
+ :: 1 ->
+ queue[get_pid()] = gp;
+
+ if
+ :: (gp_futex == -1) ->
+ gp_futex = 0;
+#ifndef INJ_QUEUE_NO_WAKE
+ futex_wake = 1;
#endif
+ :: else ->
+ skip;
+ fi;
+ od;
}
active proctype waiter()
{
+restart:
+ in_registry[0] = 1;
+ in_registry[1] = 1;
do
:: 1 ->
#ifndef INJ_LATE_DEC
- fut = fut - 1;
+ gp_futex = -1;
#endif
+
if
- :: (queue[0] == 1 || queue[1] == 1) ->
-#ifndef INJ_LATE_DEC
- fut = 0;
-#endif
- skip;
+ :: (in_registry[0] == 1 && queue[0] == gp) ->
+ in_registry[0] = 0;
:: else ->
-#ifdef INJ_LATE_DEC
- fut = fut - 1;
-#endif
- if
- :: (fut == -1) ->
- do
- :: 1 ->
- if
- :: (fut == -1) ->
- skip;
- :: else ->
- break;
- fi;
- od;
- :: else ->
- skip;
- fi;
+ skip;
fi;
-progress:
if
- :: queue[0] == 1 ->
- queue[0] = 0;
+ :: (in_registry[1] == 1 && queue[1] == gp) ->
+ in_registry[1] = 0;
+ :: else ->
+ skip;
fi;
if
- :: queue[1] == 1 ->
- queue[1] = 0;
+ :: (in_registry[0] == 0 && in_registry[1] == 0) ->
+progress:
+#ifndef INJ_LATE_DEC
+ gp_futex = 0;
+#endif
+ gp = !gp;
+ goto restart;
+ :: else ->
+#ifdef INJ_LATE_DEC
+ gp_futex = -1;
+#endif
+ futex_wake = gp_futex + 1;
+ do
+ :: 1 ->
+ if
+ :: (futex_wake == 0) ->
+ skip;
+ :: else ->
+ break;
+ fi;
+ od;
fi;
od;
}
--
1.7.6
More information about the lttng-dev
mailing list