130 likes | 262 Views
running. ready. CPU. Kernel as a monitor. signal (sem2). wait (sem2). sem2. wait (sem1). signal (sem1). sem1. suspend. resume. suspend. create. kill. pid qkey qnext qprev. 0. 1. 2 25 33 4. 3. 4 14 2 32.
E N D
running ready CPU Kernel as a monitor signal (sem2) wait (sem2) sem2 wait (sem1) signal (sem1) sem1 suspend resume suspend create kill SSST CS260
pid qkey qnext qprev 0 1 2 25 33 4 3 4 14 2 32 5 NPROC - 1 NPROC Head at 32 MININT 4 ^ Tail at 33 MAXINT ^ 2 Queue as a linked list Head = 32 Tail = 33 4 2 ^ MININT 4 32 14 2 4 25 33 2 MAXINT ^ Kernel Queues /* q.h */ #define NQENT NPROC+NSEM+NSEM+4 struct qent { int qkey; int qnext; int qprev; } extern struct qent q[ ] ; extern int nextqueue; /* inline procedures*/ #define isempty(head) (q[(list)].qnext>=NPROC) #define nonempty(head) (q[(list)].qnext < NPROC) #define firstkey(head) (q[q[(head)].qnext].qkey) #define lastkey(tail) (q[q[(tail)].qprev].qkey)#define firstid(head) (q[(head)].qnext) #define EMPTY -1 q array of qent structures SSST CS260
FIFO queue procedures /* dequeue – removes item from the list */ int dequeue (int item) { struct qent *mptr; mprt = &q[item]; q[mptr->qprev].qnext = mptr->qnext; /*1*/ q[mptr->qnext].qprev = mptr->qprev; /*2*/ return(item); } /* enqueue – insert item at the tail */ int enqueue (int item, int tail) { struct qent *tptr; struct qent *mptr; tptr = &q[tail]; mprt = &q[item]; mptr->qnext = tail; /* 1 */ mptr->qprev = tptr->qprev; /* 2 */ q[tptr->qprev].qnext = item; /* 3 */ tprt->qprev = item; /* 4 */ return(item); } prev item next 2 prev item tail 3 1 1 2 4 SSST CS260
Priority queue procedures /* getfirst returns first process on the list */ int getfirst (int head) { int proc; if ( (proc = q[head].qnext) < NPROC) return(dequeue (proc) ); else return(EMPTY); } /* getlast returns last process from the list */ int getlast (int tail) { int proc; if ( (proc = q[tail].qprev) < NPROC) return(dequeue (proc) ); else return(EMPTY); } /* insert – insert item in priority order */ int insert (int proc, int head, int key) { int next; int prev; next = q[head].qnext; while (q[next].qkey < key) next = qnext[next].qnext; q[proc].qnext = next; /* 1 */ q[proc].qprev = prev = q[next].qprev; /*2*/ q[proc].qkey = key; /* 3 */ q[prev].qnext = proc; /* 4 */ q[next].qprev = proc; /* 5 */ return(OK); /* OK is 1 */ } SSST CS260
Queue initialization /* newqueue intializes new linked list */ int newqueue ( ) { struct qent *hptr; struct qent *tptr; int hindex, tindex; hptr = &q[hindex = nextqueue++] ; /* nextqueue is global variable */ tptr = &q[tindex = nextqueue ++ ] ; hptr->qnext = tindex; hptr->qprev = EMPTY; hptr->qkey = MININT; tptr->qnext = EMPTY; tptr->qprev = hindex; tptr->qkey = MAXINT; return (hindex); } SSST CS260
proc.h extern struct pentry proctab [ ] ; extern int numproc; /* no of currently active proc*/ extern int nextproc; /* next free slot */ extern int currpid; /* pid of running proc */ /* proc.h – isbadpid */ /* process state constants */ #define PRCURR ‘\01’ /* running */ #define PRFREE ‘\02’ /* process slot is free */ #define PRREADY ‘\03’ #define PRRECV ‘\04’ /* waiting for msg */ #define PRSLEEP ‘\05’ #define PRSUSP ‘\06’ /* suspended */ #define PRWAIT ‘\07’ /* waiting in sem que */ #define isbadpid(x) (x<=0 || x>=NPROC) struct pentry { char pstate; int pprio; int psem; /* sem where proc waits */ int pmsg; /* msg sent to this process */ char *pregs; /* saved regs (SP) */ char *pbase; /* base of the run-time stack */ word plen; /* stack length */ char pname[PNMLEN+1]; /* proc name */ int pargs; /* number of arguments */ int (*paddr) ( ); /* code address */ } SSST CS260
resched.c #include <conf.h> #include <kernel.h> #include <proc.h> #include <q.h> int resched ( ) { register struct pentry *optr; register struct pentry *nptr; optr = &proctab[currpid]; if (optr->pstate == PRCURR) { if (lastkey(rdytail) < optr->pprio) return; /* no switch */ optr->pstate = PRREADY; insert(currpid, rdyhead, optr->pprio); } nptr = &proctab[ currpid = getlast(rdytail) ]; nptr->pstate = PRCURR; preempt = QUANTUM; /* no of ticks before preemption */ ctxsw ( &optr->pregs, &nptr->pregs ); /* the old process returns here when resumed */ return; } SSST CS260
SP 100 rn 100 r1 flags bp bp ret addr SP optr 100 nptr 200 9 8 1 10 11 ctxsw.asm _ctxsw proc near • push bp • mov bp, sp • pushf ; push flags • cli ; clear interrupts • push r1 ; save regs on stack • . • push rn • mov bx, [bp + 4] • mov [bx], sp • mov bx, [bp + 6] • mov sp, [bx] • pop rn • . • pop r1 • popf • pop bp • ret SSST CS260
ready – put a process in ready queue • #include <conf.h> • #include <kernel.h> • #include <proc.h> • #include <q.h> • int ready(int pid) { • register struct pentry *ppntr; • if (isbadpid(pid)) return(SYSERR); • ppntr = &proctab[pid]; • ppntr->pstate = PRREADY; • Insert (pid, rdyhead, ppntr->pprio); • return(OK); • } SSST CS260
SYSCALL resume • #include <conf.h> • #include <kernel.h> • #include <proc.h> • SYSCALL resume(int pid) { • int ps; • struct pentry *ppntr; • int prio; • disable(ps); • if (isbadpid(pid) || (ppntr = &proctable[pid])->pstate != PRSUSP) { • restore(ps); • return(SYSERROR); • } • prio = ppntr->pprio; • ready(pid); • resched( ); • restore(ps); • return(prio); • } SSST CS260
SYSCALL suspend • #include <conf.h> • #include <kernel.h> • #include <proc.h> • SYSCALL suspend(int pid) { • int ps; • struct pentry *ppntr; • int prio; • disable(ps); • if (isbadpid(pid) || pid == NULLPROC || ((ppntr = &proctable[pid])->pstate != PRREADY && ppntr->pstate != PRCURR ) { • restore(ps); • return(SYSERROR); • } • if (ppntr->pstate == PRREADY) { • dequeue(pid); • ppntr->pstate = PRSUSP; • } else { • ppntr->pstate = PRSUSP; • resched ( ) ; • } • prio = pptr->pprio; • restore(ps); • return(prio); • } SSST CS260
SYSCALL kill • #include <conf.h> • #include <kernel.h> • #include <proc.h> • #include <mem.h> • #include <sem.h> • SYSCALL kill(int pid) { • int ps; • struct pentry *ppntr; • disable(ps); • if (isbadpid(pid) || (ppntr = • &proctable[pid])->pstate ==PRFREE) { • restore(ps); • return(SYSERROR); • } • if (--numproc == 0) xdone ( ); terminate Xinu • freestk (ppntr->pbase, ppntr->plen); switch (ppntr -> pstate) { case PRCURR: ppntr->pstate = PRFREE; resched ( ) ; case PRWAIT: semaph[pptr->psem].semcnt ++; case PRSLEEP: case PRREADY: dequeue(pid); default: ppntr->pstate = PRFREE; } restore(ps); return(OK); } SSST CS260