diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2014-11-06 16:08:16 -0800 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2014-11-06 16:08:16 -0800 |
commit | 40544ff87cf82d84c051659c971093ffb534b0d6 (patch) | |
tree | d4497a34975a3277295aae7800b7abfe5019e140 | |
parent | 64579cf7c812e4ffe659fc6f1b1614bfc5848f22 (diff) | |
download | mu-40544ff87cf82d84c051659c971093ffb534b0d6.tar.gz |
238 - avoid deadlock if all jobs are sleeping
-rw-r--r-- | mu.arc | 11 | ||||
-rw-r--r-- | mu.arc.t | 24 |
2 files changed, 33 insertions, 2 deletions
diff --git a/mu.arc b/mu.arc index 5779ac47..0aed2f73 100644 --- a/mu.arc +++ b/mu.arc @@ -190,7 +190,9 @@ (each it fn-names (enq make-routine.it running-routines*)) ; simple round-robin scheduler - (while (~empty running-routines*) + (while (or (~empty running-routines*) + (~empty sleeping-routines*)) + (point continue (each (routine _) sleeping-routines* (awhen (> curr-cycle* rep.routine!sleep.1) (trace "schedule" "waking up " top.routine!fn-name) @@ -198,6 +200,11 @@ (wipe rep.routine!sleep) (++ pc.routine) ; complete the sleep instruction (enq routine running-routines*))) + (when (empty running-routines*) + ; ensure forward progress + (trace "schedule" "skipping cycle " curr-cycle*) + (++ curr-cycle*) + (continue)) (= routine* deq.running-routines*) (trace "schedule" top.routine*!fn-name) (routine-mark:run-for-time-slice scheduling-interval*) @@ -207,7 +214,7 @@ (~empty routine*) (enq routine* running-routines*) :else - (enq-limit routine* completed-routines*)))) + (enq-limit routine* completed-routines*))))) (def die (msg) (= rep.routine*!error msg) diff --git a/mu.arc.t b/mu.arc.t index 41561520..4050a6aa 100644 --- a/mu.arc.t +++ b/mu.arc.t @@ -1698,6 +1698,30 @@ ("run" "f1 2") )) +(reset) +(new-trace "sleep-long") +(add-fns + '((f1 + (sleep (20 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 progresses sleeping routines when there are no routines left to run" + '(("run" "f1 0") + ("run" "sleeping until 21") + ("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. |