about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-10-29 17:06:48 -0700
committerKartik K. Agaram <vc@akkartik.com>2016-10-29 17:06:48 -0700
commitef69c56c82e85e83014605f501110697d81bcdc1 (patch)
tree7d1794a21701db7ecac84f747d165470daba7fc2
parent358aa35d306571511a4a8027d7033ffe37e8812d (diff)
downloadmu-ef69c56c82e85e83014605f501110697d81bcdc1.tar.gz
3608 - concurrent writes to fake file system
-rw-r--r--075channel.mu4
-rw-r--r--088file.mu6
-rw-r--r--089scenario_filesystem.cc2
3 files changed, 10 insertions, 2 deletions
diff --git a/075channel.mu b/075channel.mu
index a023b294..985292a3 100644
--- a/075channel.mu
+++ b/075channel.mu
@@ -9,6 +9,10 @@
 #   b) Writing to a channel implicitly performs a deep copy. This prevents
 #   addresses from being shared between routines, and therefore eliminates all
 #   possibility of race conditions.
+#
+# There's still a narrow window for race conditions: the ingredients passed in
+# to 'start-running'. Pass only channels into routines and you should be fine.
+# Any other mutable ingredients will require locks.
 
 scenario channel [
   run [
diff --git a/088file.mu b/088file.mu
index 3c31e66f..de374f1f 100644
--- a/088file.mu
+++ b/088file.mu
@@ -2,6 +2,7 @@
 # are thus easier to test.
 
 container resources [
+  lock:bool
   data:&:@:resource
 ]
 
@@ -84,7 +85,6 @@ def start-writing resources:&:resources, filename:text -> sink:&:sink:char, rout
   {
     break-unless resources
     # fake file system
-    # beware: doesn't support multiple concurrent writes yet
     routine-id <- start-running transmit-to-fake-file resources, filename, source
     reply
   }
@@ -109,6 +109,8 @@ def transmit-to-file file:num, source:&:source:char -> source:&:source:char [
 def transmit-to-fake-file resources:&:resources, filename:text, source:&:source:char -> resources:&:resources, source:&:source:char [
   local-scope
   load-ingredients
+  lock:location <- get-location *resources, lock:offset
+  wait-for-reset-then-set lock
   # compute new file contents
   buf:&:buffer <- new-buffer 30
   {
@@ -133,6 +135,7 @@ def transmit-to-fake-file resources:&:resources, filename:text, source:&:source:
     found?:bool <- equal filename, curr-filename
     loop-unless found?
     put-index *data, i, new-resource
+    reset lock
     reply
   }
   # if file didn't already exist, make room for it
@@ -149,4 +152,5 @@ def transmit-to-fake-file resources:&:resources, filename:text, source:&:source:
   }
   # write new file
   put-index *new-data, len, new-resource
+  reset lock
 ]
diff --git a/089scenario_filesystem.cc b/089scenario_filesystem.cc
index 6af3166b..dfbc245d 100644
--- a/089scenario_filesystem.cc
+++ b/089scenario_filesystem.cc
@@ -224,7 +224,7 @@ void construct_resources_object(const map<string, string>& contents) {
   trace(9999, "mem") << "storing refcount 1 in location " << resources_data_address << end();
   // wrap the resources data in a 'resources' object
   int resources_address = allocate(size_of_resources());
-  curr = resources_address+/*skip refcount*/1;
+  curr = resources_address+/*skip refcount*/1+/*offset of 'data' element*/1;
   put(Memory, curr, resources_data_address);
   trace(9999, "mem") << "storing resources data address " << resources_data_address << " in location " << curr << end();
   put(Memory, resources_address, 1);  // initialize refcount