about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2014-11-06 15:38:00 -0800
committerKartik K. Agaram <vc@akkartik.com>2014-11-06 16:05:57 -0800
commit64579cf7c812e4ffe659fc6f1b1614bfc5848f22 (patch)
treee695c9b2855d863ebf5da681b3e28a15842f6977
parentf462b986b1b2d2dae4f8b6a7416fb1b995a00d85 (diff)
downloadmu-64579cf7c812e4ffe659fc6f1b1614bfc5848f22.tar.gz
237 - rudimentary 'sleep'
-rw-r--r--mu.arc26
-rw-r--r--mu.arc.t24
2 files changed, 47 insertions, 3 deletions
diff --git a/mu.arc b/mu.arc
index 4395bc27..5779ac47 100644
--- a/mu.arc
+++ b/mu.arc
@@ -171,6 +171,8 @@
 (on-init
   (= running-routines* (queue))
   (= completed-routines* (queue))
+  ; set of sleeping routines; don't modify routines while they're in this table
+  (= sleeping-routines* (table))
   (= routine* nil)
   (= abort-routine* (parameter nil))
   (= curr-cycle* 0)
@@ -189,12 +191,23 @@
     (enq make-routine.it running-routines*))
   ; simple round-robin scheduler
   (while (~empty running-routines*)
+    (each (routine _) sleeping-routines*
+      (awhen (> curr-cycle* rep.routine!sleep.1)
+        (trace "schedule" "waking up " top.routine!fn-name)
+        (wipe sleeping-routines*.routine)  ; before modifying routine below
+        (wipe rep.routine!sleep)
+        (++ pc.routine)  ; complete the sleep instruction
+        (enq routine running-routines*)))
     (= routine* deq.running-routines*)
     (trace "schedule" top.routine*!fn-name)
     (routine-mark:run-for-time-slice scheduling-interval*)
-    (if (~empty routine*)
-      (enq routine* running-routines*)
-      (enq-limit routine* completed-routines*))))
+    (if rep.routine*!sleep
+          (do (trace "schedule" "pushing " top.routine*!fn-name " to sleep queue")
+              (set sleeping-routines*.routine*))
+        (~empty routine*)
+          (enq routine* running-routines*)
+        :else
+          (enq-limit routine* completed-routines*))))
 
 (def die (msg)
   (= rep.routine*!error msg)
@@ -202,6 +215,11 @@
   (wipe rep.routine*!call-stack)
   ((abort-routine*)))
 
+(def sleep-for (delay)
+  (trace "run" "sleeping until " (+ curr-cycle* delay))
+  (= rep.routine*!sleep `(literal ,(+ curr-cycle* delay)))
+  ((abort-routine*)))
+
 ;; running a single routine
 (mac v (operand)  ; for value
   `(,operand 0))
@@ -465,6 +483,8 @@
                 ; inspect it
                 assert
                   (assert (m arg.0))
+                sleep
+                  (sleep-for (m arg.0))
 
                 ; text interaction
                 cls
diff --git a/mu.arc.t b/mu.arc.t
index e8257606..41561520 100644
--- a/mu.arc.t
+++ b/mu.arc.t
@@ -1674,6 +1674,30 @@
     ("run" "f2 1")
   ))
 
+(reset)
+(new-trace "sleep")
+(add-fns
+  '((f1
+      (sleep (1 literal))
+      ((1 integer) <- copy (3 literal))
+      ((1 integer) <- copy (3 literal)))
+    (f2
+      ((2 integer) <- copy (4 literal))
+      ((2 integer) <- copy (4 literal)))))
+;? (= dump-trace* (obj whitelist '("run" "schedule")))
+(= scheduling-interval* 1)
+(run 'f1 'f2)
+(check-trace-contents "scheduler handles sleeping routines"
+  '(("run" "f1 0")
+    ("run" "sleeping until 2")
+    ("schedule" "pushing f1 to sleep queue")
+    ("run" "f2 0")
+    ("run" "f2 1")
+    ("schedule" "waking up f1")
+    ("run" "f1 1")
+    ("run" "f1 2")
+  ))
+
 ; The scheduler needs to keep track of the call stack for each routine.
 ; Eventually we'll want to save this information in mu's address space itself,
 ; along with the types array, the magic buffers for args and oargs, and so on.