Tom Kelliher, CS42
Feb. 23, 1998
The following is from the Xinu system, designed by Douglas Comer.
/* declarations */
#define QUANTUM 10 /* clock ticks until preemption */
#define SP 6 /* reg. 6 is stack pointer */
#define PC 7 /* reg. 7 is program counter */
#define PS 8 /* proc. status stored in 8th loc. */
#define NPROC 10 /* max number of processes */
#define PRCURR 0x01 /* process is running */
#define PRFREE 0x02 /* table entry is free */
#define PRREADY 0x03 /* process is on ready queue */
#define PRRECV 0x04 /* process is waiting for message */
#define PRSLEEP 0x05 /* process is sleeping */
#define PRSUSP 0x06 /* process is suspended */
#define PRWAIT 0x07 /* process is on semaphore queue */
#define PNREGS 9 /* number of CPU registers */
#define PNMLEN 8 /* process name length */
/* process table entry */
struct pentry \{
char pstate; /* state of process */
short pprio; /* process priority */
short pregs[PNREGS]; /* saved registers: R0-R5, SP, PC, PS */
short psem; /* semaphore process waiting on */
short pmsg; /* message sent to process */
short phasmsg; /* nonzero iff pmsg is valid */
short pbase; /* base of runtime stack */
short pstklen; /* stack length */
short plimit; /* lowest extent of stack */
char name[PNMLEN]; /* process name */
short pargs; /* number of arguments */
short paddr; /* initial code address */
\};
extern struct pentry proctab[NPROC];
extern int currpid; /* currently executing process */
extern int rdyhead, rdytail;
extern int preempt;
/*-----------------------------------------------------------------------------
* resched -- reschedule processor to highest priority ready process
*
* Notes: Upon entry, currpid gives current process id.
* Proctab[currpid].pstate gives correct NEXT state for current
* process if other than PRCURR.
*-----------------------------------------------------------------------------
*/
int resched() \{
register struct pentry *optr; /* pointer to old process entry */
register struct pentry *nptr; /* pointer to new process entry */
/* no switch needed if current process priority HIGHER than next */
if ( ( (optr = &proctab[currpid])->pstate == PRCURR) &&
(lastkey(rdytail) < optr->pprio) )
return(OK);
/* force context switch */
if (optr->pstate == PRCURR) \{
optr->pstate = PREADY;
insert(currpid, rdyhead, optr->pprio);
\}
/* remove highest priority process at end of ready list */
nptr = &proctab[ (currpid = getlast(rdytail) ) ];
nptr->pstate = PRCURR;
preempt = QUANTUM; /* reset preemption counter */
ctxsw(optr->pregs, nptr->pregs); /* do context switch */
/* the OLD process returns here when resumed */
return(OK);
\}
/*-----------------------------------------------------------------------------
* ctxsw -- assembler routine for performing context switch,
* saving/loading registers
*
* The stack contains three items upon entry to this routine:
*
* SP+4 => address of 9 word save area with new registers + PS
* SP+2 => address of 9 word save area for old registers + PS
* SP => return address
*
* The saved state consists of: the values of R0-R5 upon entry, SP+2, PC
* equal to the return address, and the PS (i.e., the PC and SP are saved
* as if the calling process had returned to its caller.
*-----------------------------------------------------------------------------
*/
.globl _ctxsw /* declare name global */
_ctxsw: /* entry point to proc. */
mov r0,*2(sp) /* save old R0 in old register area */
mov 2(sp),r0 /* get address of old register area in R0 */
add $2,r0 /* increment to saved pos. of R1 */
mov r1,(r0)+ /* save R1-R5 in successive locations of old
mov r2,(r0)+ /* process register save are */
mov r3,(r0)+
mov r4,(r0)+
mov r5,(r0)+
add $2,sp /* move SP beyond the return address, as if a */
/* return had occurred */
mov sp,(r0)+ /* save stack pointer */
mov -(sp),(r0)+ /* save caller's return address as PC */
mfps (r0) /* save processor status beyond registers */
mov 4(sp),r0 /* get address of start of new register area */
/* ready to load registers for the new process */
/* and abandon the old stack */
mov 2(r0),r1 /* load R1-R5 and SP from the new area */
mov 4(r0),r2
mov 6(r0),r3
mov 8.(r0),r4 /* dot following a number makes it decimal; */
mov 10.(r0),r5 /* otherwise it is octal */
mov 12.(r0),sp /* have switched stacks now */
mov 16.(r0),-(sp) /* push new process PS on new process stack */
mov 14.(r0),-(sp) /* push new process PC on new process stack */
mov (r0),r0 /* load R0 from new area */
rtt /* load PC, PS, and reset SP all at once */