about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2014-11-08 10:31:37 -0800
committerKartik K. Agaram <vc@akkartik.com>2014-11-08 10:35:25 -0800
commitfc46ebddf0c802e3942d80446dcd6c8fc339c4fd (patch)
tree54cb92b6544dd71ed46a93f55f5f6951f99be509
parent3bec25ce266aef848fb2a87b9a9ee33ab80566b0 (diff)
downloadmu-fc46ebddf0c802e3942d80446dcd6c8fc339c4fd.tar.gz
263
I'm trying to think about how to write a test for the race condition,
and how to fix it. One thing that's been hard is even remembering where
it lies. It's not between wiping the watch and sleeping on it; that's
innocuous because the sleep would just immediately wake up. No, the race
condition lies between the empty check and the wipe.

For the innocuous race we could just create an atomic wipe-and-sleep.
But the more serious race requires a lock.

If we need a lock anyway, is there any reason to have two watch
variables?

I'm going to preserve these alternative functions in the code.
Alternatives will only ever be called from other alteratives or tests.
-rw-r--r--mu.arc7
1 files changed, 4 insertions, 3 deletions
diff --git a/mu.arc b/mu.arc
index d9d6321b..3bffa39f 100644
--- a/mu.arc
+++ b/mu.arc
@@ -868,6 +868,7 @@
   ((chan channel) <- arg)
   ((val tagged-value) <- arg)
   { begin
+    ; block if chan is full
     ((full boolean) <- full? (chan channel))
     ; race condition: might unnecessarily sleep if consumer routine reads from
     ; channel between previous check and the set to watch below
@@ -895,6 +896,7 @@
   ((default-scope scope-address) <- new (scope literal) (30 literal))
   ((chan channel) <- arg)
   { begin
+    ; block if chan is empty
     ((empty boolean) <- empty? (chan channel))
     ; race condition: might unnecessarily sleep if consumer routine writes to
     ; channel between previous check and the set to watch below
@@ -918,9 +920,6 @@
   (reply (result tagged-value) (chan channel)))
 
 ; An empty channel has first-empty and first-full both at the same value.
-; A full channel has first-empty just before first-full, wasting one slot.
-; (Other alternatives: https://en.wikipedia.org/wiki/Circular_buffer#Full_.2F_Empty_Buffer_Distinction)
-
 (init-fn empty?
   ((default-scope scope-address) <- new (scope literal) (30 literal))
   ((chan channel) <- arg)
@@ -929,6 +928,8 @@
   ((result boolean) <- eq (full integer) (free integer))
   (reply (result boolean)))
 
+; A full channel has first-empty just before first-full, wasting one slot.
+; (Other alternatives: https://en.wikipedia.org/wiki/Circular_buffer#Full_.2F_Empty_Buffer_Distinction)
 (init-fn full?
   ((default-scope scope-address) <- new (scope literal) (30 literal))
   ((chan channel) <- arg)