;; mos4 all functions are in S2 ;; Happy Sonkran Day ! ;; 13 Apr 2016 ;; semaphore 14 Apr 2016 ;; two processes share a variable ;; memory map ;; 0..900 code ;; 1000 int vec ;; 1500 global var ;; 1700 system stack ;; 2000 process queue ;; 2100 PCB ;; 2300 process stack ;; 3000 semaphore area ;; trap 19 print3 show which process ;; trap 20 sem = newsem() ;; trap 21 wait(sem) ;; trap 22 signal(sem) .symbol stop 0 di 15 ei 16 print1 17 print2 18 print3 19 newsem 20 wait 21 signal 22 cnt 1600 sem 1601 ;; global registers sp 28 ;; system stack pointer retval 27 link 15 ;; must be r1..r15 ;; OS variables qend 1510 qindex 1511 nump 1500 ;; number of process currentp 1501 ;; pointer to current proc pcbptr 1502 ;; PCB block pointer stackptr 1503 ;; process stack pointer ;; OS constant Q 2000 ;; Q at &2000 .code 0 trap di ;; ... initialise mv r1 #tswitch st r1 1000 ;; set int vec mv sp #1700 ;; sp = &1700 st r0 nump st r0 currentp mv r1 #Q ;; Q at &2000 st r1 qend ;; pointer to Qend st r0 @0 r1 ;; Q[end] = 0 st r0 qindex ;; qindex = 0 mv r1 #2100 st r1 pcbptr ;; pcbptr = &2100 mv r1 #2316 ;; offset +16, for first resr st r1 stackptr ;; stackptr = &2316 st r0 cnt ;; cnt = 0 trap newsem st retval sem ;; sem = newsem() mv r1 #process1 ;; create process1 jal link createp mv r1 #process1 ;; create process2 jal link createp ;; boot make zeroth process not in Q ;; then switch to process in Q jal link newp st sp @1 retval st retval currentp ;; zeroth p trap ei int 0 ;; start by switch p trap stop ;; creat new PCB, enqueue it ;; input: &program in r1 ;; return: process :createp push sp link ;; save ret jal link newp ;; newp() st r1 @0 retval ;; p.PC = &program mv r1 retval ;; keep process jal link newStack ;; newStack() st retval @1 r1 ;; p.SP = newStack jal link enqueue ;; enqueue() mv retval r1 ;; return process pop sp link ;; restore ret ret link ;; newp() ;; a = pcbptr ;; pcbptr += 16 ;; return a :newp ld r5 pcbptr mv retval r5 add r5 r5 #16 st r5 pcbptr ret link :newStack ld r5 stackptr mv retval r5 add r5 r5 #64 st r5 stackptr ret link ;; enqueue(p) ;; Q[end] = p ;; Q[end+1] = 0 ;; end++ ;; nump++ :enqueue ;; input in r1 ld r6 qend st r1 @0 r6 ;; Q[end] = p add r6 r6 #1 st r0 @0 r6 ;; Q[end+1] = 0 st r6 qend ;; end++ ld r6 nump add r6 r6 #1 st r6 nump ;; nump++ ret link ;; terminate() ;; Q[qindex] = 1 ;; nump-- :terminate ;; critical section trap di ld r6 qindex mv r7 #Q mv r5 #1 st r5 +r6 r7 ;; Q[qindex] = 1 ld r5 nump sub r5 r5 #1 st r5 nump ;; nump-- trap ei ret link ;; include compact Q (delete "1") ;; nextp() ;; if( nump == 0 ) return 0 ;; if( Q[qindex] == 1 ) ;; compact Q from qindex to qend ;; qend-- ;; else ;; qindex++ ;; if( Q[qindex] == 0 ) qindex = 0 ;; return Q[qindex] :nextp ld r5 nump jt r5 skip mv retval r0 ret link :skip ld r5 qindex mv r6 #Q ld r7 +r5 r6 ;; Q[qindex] eq r8 r7 #1 ;; Q[qindex] == 1 jf r8 skip2 ;; compact from qindex to qend add r8 r5 r6 ;; r8 &Q[qindex] ld r9 qend sub r9 r9 #1 st r9 qend ;; qend-- :loop le r10 r8 r9 ;; ptr <= qend? jf r10 skip2 ld r10 @1 r8 ;; st r10 @0 r8 ;; *prt = *(ptr+1) add r8 r8 #1 jmp loop :skip2 add r5 r5 #1 ld r7 +r5 r6 jt r7 exit2 ;; Q[qindex] == 0 ? mv r5 r0 ;; qindex = 0 ld r7 +r5 r6 :exit2 mv retval r7 ;; ret Q[qindex] st r5 qindex ret link :process1 ;; count 1..n :loop1 ld r1 sem trap wait ;; wait(sem) ld r5 cnt add r5 r5 #1 st r5 cnt trap signal ;; signal(sem) mv r1 r5 trap print3 gt r6 r5 #20 jf r6 loop1 jal link terminate int 0 ;; force task switch trap stop :tswitch ;; use r20,21 trap di ld r21 currentp savt r20 ;; get RetAds st r20 @0 r21 ;; p.PC = RetAds savr sp ;; save current context + link st sp @1 r21 ;; p.SP = sp jal link nextp mv r21 retval jf r21 exit ;; no process in the queue st r21 currentp ;; update currentp ld sp @1 r21 ;; get p.SP resr sp ;; restore context ld r20 @0 r21 ;; get p.PC rest r20 ;; RetAds = p.PC trap ei reti :exit trap stop .end