; mos5 all functions are in S2 ; Happy Sonkran Day ! ; 13 Apr 2016 ; semaphore 14 Apr 2016 ; update 18 Feb 2017 ; 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 r0 #di ; ... initialise mov r1 #tswitch st r1 1000 ; set int vec mov sp #1700 ; sp = &1700 st r0 nump st r0 currentp mov r1 #Q ; Q at &2000 st r1 qend ; pointer to Qend st r0 @0 r1 ; Q[end] = 0 st r0 qindex ; qindex = 0 mov r1 #2100 st r1 pcbptr ; pcbptr = &2100 mov r1 #2316 ; offset +16, for first resr st r1 stackptr ; stackptr = &2316 st r0 cnt ; cnt = 0 trap r0 #newsem st retval sem ; sem = newsem() mov r1 #process1 ; create process1 jal link createp mov 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 r0 #ei int #0 ; start by switch p trap r0 #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 r0 #di ld r6 qindex mov r7 #Q mov r5 #1 st r5 +r6 r7 ; Q[qindex] = 1 ld r5 nump sub r5 r5 #1 st r5 nump ; nump-- trap r0 #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 mov retval r0 ret link :skip ld r5 qindex mov 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 ? mov r5 r0 ; qindex = 0 ld r7 +r5 r6 :exit2 mov retval r7 ; ret Q[qindex] st r5 qindex ret link :process1 ; count 1..n :loop1 ld r1 sem trap r1 #wait ; wait(sem) ld r5 cnt add r5 r5 #1 st r5 cnt trap r1 #signal ; signal(sem) mov r1 r5 trap r1 print3 gt r6 r5 #20 jf r6 loop1 jal link terminate int #0 ; force task switch trap r0 #stop :tswitch ; use r20,21 trap r0 #di ld r21 currentp xch r20 ; get RetAds st r20 @0 r21 ; p.PC = RetAds pushm sp ; save current context + link st sp @1 r21 ; p.SP = sp jal link nextp mov r21 retval jf r21 exit ; no process in the queue st r21 currentp ; update currentp ld sp @1 r21 ; get p.SP popm sp ; restore context ld r20 @0 r21 ; get p.PC xch r20 ; RetAds = p.PC trap r0 #ei reti :exit trap r0 #stop .data 200 .end