about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2014-11-23 07:19:14 -0800
committerKartik K. Agaram <vc@akkartik.com>2014-11-23 07:19:14 -0800
commitb437f7aee100475533add418632833e9eaebc7bc (patch)
treeaa696ac10c84f26b1f2095faf2b46c584e4c09e2
parent88e1f0eba0be324a74f10b9632ffbfc391b4a6fa (diff)
downloadmu-b437f7aee100475533add418632833e9eaebc7bc.tar.gz
304 - a unit test for a race condition
Still failing, but worth memorializing for posterity.

Race condition tests are still experimental, even more tied to a very
specific implementation. If I make changes to 'write' the very
'wipe-read' label will go away.

But then you just delete all tests relying on stale labels and try to
think up new race conditions.
-rw-r--r--mu.arc6
-rw-r--r--mu.arc.t26
2 files changed, 32 insertions, 0 deletions
diff --git a/mu.arc b/mu.arc
index 1dc43b62..d3cf5946 100644
--- a/mu.arc
+++ b/mu.arc
@@ -198,6 +198,7 @@
   (= abort-routine* (parameter nil))
   (= curr-cycle* 0)
   (= scheduling-interval* 500)
+  (= scheduler-switch-table* nil)  ; hook into scheduler for tests
   )
 
 ; like arc's 'point' but you can also call ((abort-routine*)) in nested calls
@@ -443,6 +444,11 @@
       (trace "run" curr-cycle* " " top.routine*!fn-name " " pc.routine* ": " (body.routine* pc.routine*))
 ;?       (trace "run" routine*)
       (when (atom (body.routine* pc.routine*))  ; label
+        (when (aand scheduler-switch-table*
+                    (alref it (body.routine* pc.routine*)))
+          (++ pc.routine*)
+          (trace "run" "context-switch forced " abort-routine*)
+          ((abort-routine*)))
         (++ pc.routine*)
         (continue))
       (let (oarg op arg)  (parse-instr (body.routine* pc.routine*))
diff --git a/mu.arc.t b/mu.arc.t
index d010e415..66d2f3ee 100644
--- a/mu.arc.t
+++ b/mu.arc.t
@@ -2434,6 +2434,32 @@
   (prn "F - channels are meant to be shared between routines"))
 ;? (quit)
 
+(reset)
+(new-trace "channel-race")
+(add-fns
+  '((main
+      ; create a channel with capacity 1
+      ((1 channel-address) <- new-channel (1 literal))
+      ((2 integer-address) <- new (integer literal))
+      ((2 integer-address deref) <- copy (34 literal))
+      ((3 tagged-value-address) <- new-tagged-value (integer-address literal) (2 integer-address))
+      ; write a value
+      ((1 channel-address deref) <- write (1 channel-address) (3 tagged-value-address deref))
+      ; write a second value
+      ((1 channel-address deref) <- write (1 channel-address) (3 tagged-value-address deref)))
+    (reader
+      (_ (1 channel-address deref) <- read (1 channel-address)))))
+; switch context at just the wrong time
+(= scheduler-switch-table*
+   '((wipe-read  reader)))
+;? (= dump-trace* (obj whitelist '("schedule" "run")))
+(run 'main 'reader)
+; second write should not cause deadlock
+(each routine completed-routines*
+  (when (posmatch "deadlock" rep.routine!error)
+    (prn "F - 'write' race condition 1")))
+;? (quit)
+
 ;; Separating concerns
 ;
 ; Lightweight tools can also operate on quoted lists of statements surrounded