;; mos ;; use semaphore for ;; process synchronization ;; 15 Apr 2016 ;; p1() ;; for i = 0..4 ;; wait(sem1) **** sync ;; signal(sem2) ;; print i ;; p2() ;; for i = 10..14 ;; wait(sem2) **** sync ;; signal(sem1) ;; print i ;; 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 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 sem1 1600 sem2 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 trap newsem st retval sem1 ;; sem1 = newsem() trap newsem st retval sem2 ;; sem2 = newsem() mv r1 #process1 ;; create process1 jal link createp mv r1 #process2 ;; 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 ;; ---- interrupt service routine :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 ;; ------------- user program ----------- ;; p1() ;; i = 0 ;; while i < 5 ;; wait(sem1) ;; signal(sem2) ;; print i ;; i++ :process1 ;; count 1..4 mv r2 r0 ;; r2 : i :loop3 ld r1 sem1 ;; sync trap wait ld r1 sem2 trap signal lt r3 r2 #5 ;; i < 5 ? jf r3 exit3 mv r1 r2 trap print1 add r2 r2 #1 jmp loop3 :exit3 jal link terminate int 0 ;; p2() ;; i = 10 ;; while i < 15 ;; wait(sem2) ;; signal(sem1) ;; print i ;; i++ :process2 ;; count 10..14 mv r2 #10 ;; r2 : i :loop4 ld r1 sem2 ;; sync trap wait ld r1 sem1 trap signal lt r3 r2 #15 ;; i < 15 ? jf r3 exit4 mv r1 r2 trap print2 add r2 r2 #1 jmp loop4 :exit4 jal link terminate int 0 .end