; Lecture 20 (include-book "irun") (in-package "M5") (defun shift-to-odd (n) (if (zp n) n (if (evenp n) (shift-to-odd (floor n 2)) n))) (defun init-job-2 (n) (if (zp n) nil (if (evenp n) (append (repeat 2 8) (init-job-2 (floor n 2))) nil))) (defun schedule1 (n) (if (zp n) nil (if (evenp n) (append (repeat 2 8) (schedule1 (floor n 2))) (append (repeat 2 8) (append (repeat 1 8) (schedule1 (floor n 2))))))) (defun schedule (n) (if (zp n) nil (append (repeat 0 19) (append (repeat 1 3) (append (repeat 2 9) (append (init-job-2 n) (append (repeat 1 4) (append (schedule1 (floor (shift-to-odd n) 2)) (repeat 0 3))))))))) (i-am-here) (defconst *multi-threaded-state* (make state :tt (list (make thread :id 0 :cs (push (make frame :pc 0 :locs nil :stk nil :mloc '("Top" "main" 0)) nil) :stat 'active :ref nil)) :hp nil :ct (make-ct (list (make class :name "Container" :supers '("Object") :fields '("counter") :methods nil) (make class :name "Job" :supers '("Thread" "Object") :fields '("C") :methods (list (make method :name "run" :formals () :sync nil :code ;;; ("Job" "run" 0) '((load 0) ;;; 0 (getfield ("Job" "C")) ;;; 1 (store 1) ;;; 2 (load 1) ;;; 3 loop: (load 1) ;;; 4 (getfield ("Container" "counter")) ;;; 5 (load 1) ;;; 6 (getfield ("Container" "counter")) ;;; 7 (add) ;;; 8 (putfield ("Container" "counter")) ;;; 9 C.counter = C.counter+C.counter; (goto -7)) ;;; 10 goto loop :xtbl nil))) (make class :name "Top" :supers '("Object") :fields nil :methods (list (make method :name "main" :formals () :sync nil :code ;;; ("Top" "main" 0) '((new "Container") ;;; 0 \ (dup) ;;; 1 | Build Container C (const 1) ;;; 2 | C.counter = 1; (putfield ("Container" "counter"));;; 3 | (store 0) ;;; 4 / (new "Job") ;;; 5 \ (store 1) ;;; 6 | (load 1) ;;; 7 | build and start (load 0) ;;; 8 | thread 1 running (putfield ("Job" "C")) ;;; 9 | Job with C (load 1) ;;; 10 | (invokevirtual ("Thread" "start" 0));;11 / (new "Job") ;;; 12 \ (store 1) ;;; 13 | (load 1) ;;; 14 | build and start (load 0) ;;; 15 | thread 2 running (putfield ("Job" "C")) ;;; 16 | Job with C (load 1) ;;; 17 | (invokevirtual ("Thread" "start" 0));;18 / (load 0) ;;; 19 \ (getfield ("Container" "counter"));;; 20 | return C.counter (halt)) ;;; 21 / :xtbl nil))))))) (irun *multi-threaded-state*) ; :stepn 19 ; :set-thread 1 ; :stepn 3 ; :set-thread 2 ; :stepn 3 ; :set-thread 1 ; :stepn 8 => C.counter = 2 ; :stepn 8 => C.counter = 4 ; :stepn 8 => C.counter = 8 ; :set-thread 2 ; :stepn 8 => C.counter = 16 ; :q ; Challenge: Can you make a 3? ; Yes! (irun *multi-threaded-state*) ; :stepn 19 ; :set-thread 1 ; :stepn 3 ; :set-thread 2 ; :stepn 3 ; :set-thread 1 ; :stepn 4 ; :set-thread 2 ; :stepn 7 ; :set-thread 1 ; :stepn 3 ; :set-thread 0 ; :stepn 3 (defun test-sched (n sched) (equal n (top (stk (top-frame 0 (run sched *multi-threaded-state*)))))) (defun test (n) (test-sched n (schedule n))) (test 3) (test 5) (test 17) (test 123456789)