// nos4 nut operating system in Rz // model after nos2 in ecse\src 22 Aug 2011 // for s23 embed sys demo 20 Jan 2013 // mailbox 10 Feb 2013 // s23 trap for nos // 20 enable interrupt // 21 disable interrupt // 22 block // 23 get event // 24 stop simulation asm(x) // dummy for compiler use new(n) // alloc n asm("trap r1 #14") blockp() asm("trap r0 #22") wakeup() asm("trap r0 #25") getEvent() asm("trap r0 #23") ei() asm("trap r0 #20") di() asm("trap r0 #21") // global activep // current active process sseg // stack segment pid // unique process id // process descriptor // 0 next, 1 prev // 2 id, 3 value // 4 fp, 5 sp, 6 pc, // 7 inbox, 8 awaitbox, 9 msg, 10 timer // process state // READY, RUNNING, WAIT, DEAD, SEND, RECEIVE // process descriptor access function getNext(a) return a[0] getPrev(a) return a[1] setNext(a,v) a[0] = v setPrev(a,v) a[1] = v getId(p) return p[2] getValue(p) return p[3] setId(p,id) p[2] = id setValue(p, v) p[3] = v // ---- process list functions -------- // append a2 to the end of a1 appendDL(a1,a2) if(a1 == 0) setNext(a2,a2) // only one item setPrev(a2,a2) return a2 else b = getPrev(a1) setNext(a2,a1) setPrev(a1,a2) setNext(b,a2) setPrev(a2,b) return a1 deleteDL(b) if(getNext(b) == b) return 0 // delete singleton else a = getPrev(b) c = getNext(b) setNext(a,c) setPrev(c,a) setNext(b,b) // make b singleton return c newp() // new process p = new(11) // new pdes setNext(p,0) setPrev(p,0) p[4] = sseg p[5] = sseg + 500 p[6] = 0 sseg = sseg + 1000 p[7] = 0 p[8] = 0 return p // -------nos functions -------- init() pid = 1 sseg = 4000 activep = 0 run(ads) // return p p = newp() setId(p,pid) pid = pid + 1 p[6] = ads activep = appendDL(activep, p) return p bootnos() // setup interrupt asm("mov r1 #interrupt") asm("st r1 1000") asm("mov r1 #10") asm("trap r1 #10 ; set timer1 = 10") asm("mov r1 #100") asm("trap r1 #11 ; set div = 100") asm("trap r0 #20 ; enable int") // boot nos // restore fp,sp,pc from activep asm("ld r1 activep") asm("ld fp @4 r1") asm("ld sp @5 r1") asm("ld r2 @6 r1") asm("ret r2") interrupt() // switchp() asm("trap r0 #21") // di asm("ld r21 activep") // save activep asm("st fp @4 r21") asm("st sp @5 r21") asm("st r31 @6 r21") print("*") event = getEvent() if(event == 11 || event == 13) // 11 TIMEOUT, 13 WAKEUP activep = getNext(activep) // switch next else // 10 STOP, 12 BLOCK activep = deleteDL(activep) if(activep == 0) asm("trap r0 #24") // stop simulation asm("ld r21 activep") asm("ld fp @4 r21") asm("ld sp @5 r21") asm("ld r31 @6 r21") asm("trap r0 #20") // ei // --------- message passing -------- getMbox(p) return p[7] getAwait(p) return p[8] getMsg(p) return p[9] setMbox(p,m) p[7] = m setAwait(p,m) p[8] = m setMsg(p,m) p[9] = m // search mail p in the box // return mail if found else 0 findmail(p,box) y = 0 // return value x = box while( x != 0 ) if( x == p ) y = x x = 0 // exit else x = getNext(x) if( x == box ) x = 0 // not found return y // p is pointer to process send(p,mess) di() box = getAwait(activep) s = findmail(p,box) if( s == 0 ) s = activep // self setMsg(s,mess) activep = deleteDL(activep) setMbox(p,appendDL(getMbox(p),s)) blockp() else // p is waiting setMsg(p,mess) s = deleteDL(p) if( box == p ) setAwait(activep,s) wakeup(p) ei() receive(p) di() box = getMbox(activep) r = findmail(p,box) if( r == 0 ) // put to await p r = activep // self activep = deleteDL(activep) setAwait(p,appendDL(getAwait(p),r)) blockp() m = getMsg(r) // retrieve from self else // already in mbox r = deleteDL(p) if( box == p ) setMbox(activep,r) m = getMsg(p) // retrieve mbox wakeup(p) ei() return m // --- producer, consumer ---- // send 2..n to p2 ended with -1 produce() n = 10 i = 2 while( i < n ) send(p2,i) i = i + 1 send(p2,-1) // receive 2..n from p1 ended with -1 consume() m = 1 while( m > 0 ) m = receive(p1) print(m," ") // ------------------------------ p1, p2 // user process main() init() p1 = run(produce()) p2 = run(consume()) bootnos() // end