Charles.Forsyth20060303644188019 years agoHistory
788 lines · 11.3 KB · C
RawDownload
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"../port/error.h"#include	<interp.h> Ref	pidalloc; struct{	Lock;	Proc*	arena;	Proc*	free;}procalloc; typedef struct{	Lock;	Proc*	head;	Proc*	tail;}Schedq; static Schedq	runq[Nrq];static ulong	occupied;int	nrdy; char *statename[] ={			/* BUG: generate automatically */	"Dead",	"Moribund",	"Ready",	"Scheding",	"Running",	"Queueing",	"Wakeme",	"Broken",	"Stopped",	"Rendez",}; /* * Always splhi()'ed. */voidschedinit(void)		/* never returns */{	setlabel(&m->sched);	if(up) {/*		if((e = up->edf) && (e->flags & Admitted))			edfrecord(up);*/		m->proc = nil;		switch(up->state) {		case Running:			ready(up);			break;		case Moribund:			up->state = Dead;/*			edfstop(up);			if(up->edf){				free(up->edf);				up->edf = nil;			}*/			/*			 * Holding locks from pexit:			 * 	procalloc			 */			up->qnext = procalloc.free;			procalloc.free = up;			unlock(&procalloc);			break;		}		up->mach = nil;		up = nil;	}	sched();} voidsched(void){	if(up) {		splhi();		procsave(up);		if(setlabel(&up->sched)) {			/* procrestore(up); */			spllo();			return;		}		gotolabel(&m->sched);	}	up = runproc();	up->state = Running;	up->mach = MACHP(m->machno);	/* m might be a fixed address; use MACHP */	m->proc = up;	gotolabel(&up->sched);} voidready(Proc *p){	int s;	Schedq *rq; 	s = splhi();/*	if(edfready(p)){		splx(s);		return;	}*/	rq = &runq[p->pri];	lock(runq);	p->rnext = 0;	if(rq->tail)		rq->tail->rnext = p;	else		rq->head = p;	rq->tail = p; 	nrdy++;	occupied |= 1<<p->pri;	p->state = Ready;	unlock(runq);	splx(s);} intanyready(void){	/* same priority only */	return occupied & (1<<up->pri);} intanyhigher(void){	return occupied & ((1<<up->pri)-1);} intpreemption(int tick){	if(up != nil && up->state == Running && !up->preempted &&	   (anyhigher() || tick && anyready())){		up->preempted = 1;		sched();		splhi();		up->preempted = 0;		return 1;	}	return 0;}		Proc*runproc(void){	Proc *p, *l;	Schedq *rq, *erq; 	erq = runq + Nrq - 1;loop:	splhi();	for(rq = runq; rq->head == 0; rq++)		if(rq >= erq) {			idlehands();			spllo();			goto loop;		} 	if(!canlock(runq))		goto loop;	/* choose first one we last ran on this processor at this level or hasn't moved recently */	l = nil;	for(p = rq->head; p != nil; p = p->rnext)		if(p->mp == nil || p->mp == MACHP(m->machno) || p->movetime < MACHP(0)->ticks)			break;	if(p == nil)		p = rq->head;	/* p->mach==0 only when process state is saved */	if(p == 0 || p->mach) {		unlock(runq);		goto loop;	}	if(p->rnext == nil)		rq->tail = l;	if(l)		l->rnext = p->rnext;	else		rq->head = p->rnext;	if(rq->head == nil){		rq->tail = nil;		occupied &= ~(1<<p->pri);	}	nrdy--;	if(p->dbgstop){		p->state = Stopped;		unlock(runq);		goto loop;	}	if(p->state != Ready)		print("runproc %s %lud %s\n", p->text, p->pid, statename[p->state]);	unlock(runq);	p->state = Scheding;	if(p->mp != MACHP(m->machno))		p->movetime = MACHP(0)->ticks + HZ/10;	p->mp = MACHP(m->machno); /*	if(edflock(p)){		edfrun(p, rq == &runq[PriEdf]);	// start deadline timer and do admin		edfunlock();	}*/	return p;} intsetpri(int pri){	int p; 	/* called by up so not on run queue */	p = up->pri;	up->pri = pri;	if(up->state == Running && anyhigher())		sched();	return p;} Proc*newproc(void){	Proc *p; 	lock(&procalloc);	for(;;) {		if(p = procalloc.free)			break; 		unlock(&procalloc);		resrcwait("no procs");		lock(&procalloc);	}	procalloc.free = p->qnext;	unlock(&procalloc); 	p->type = Unknown;	p->state = Scheding;	p->pri = PriNormal;	p->psstate = "New";	p->mach = 0;	p->qnext = 0;	p->fpstate = FPINIT;	p->kp = 0;	p->killed = 0;	p->swipend = 0;	p->mp = 0;	p->movetime = 0;	p->delaysched = 0;	p->edf = nil;	memset(&p->defenv, 0, sizeof(p->defenv));	p->env = &p->defenv;	p->dbgreg = 0;	kstrdup(&p->env->user, "*nouser");	p->env->errstr = p->env->errbuf0;	p->env->syserrstr = p->env->errbuf1; 	p->pid = incref(&pidalloc);	if(p->pid == 0)		panic("pidalloc");	if(p->kstack == 0)		p->kstack = smalloc(KSTACK);	addprog(p); 	return p;} voidprocinit(void){	Proc *p;	int i; 	procalloc.free = xalloc(conf.nproc*sizeof(Proc));	procalloc.arena = procalloc.free; 	p = procalloc.free;	for(i=0; i<conf.nproc-1; i++,p++)		p->qnext = p+1;	p->qnext = 0; 	debugkey('p', "processes", procdump, 0);} voidsleep(Rendez *r, int (*f)(void*), void *arg){	int s; 	if(up == nil)		panic("sleep() not in process (%lux)", getcallerpc(&r));	/*	 * spl is to allow lock to be called	 * at interrupt time. lock is mutual exclusion	 */	s = splhi(); 	lock(&up->rlock);	lock(r); 	/*	 * if killed or condition happened, never mind	 */	if(up->killed || f(arg)){		unlock(r);	}else{ 		/*		 * now we are committed to		 * change state and call scheduler		 */		if(r->p != nil) {			print("double sleep pc=0x%lux %lud %lud r=0x%lux\n", getcallerpc(&r), r->p->pid, up->pid, r);			dumpstack();			panic("sleep");		}		up->state = Wakeme;		r->p = up;		unlock(r);		up->swipend = 0;		up->r = r;	/* for swiproc */		unlock(&up->rlock); 		sched();		splhi();	/* sched does spllo */ 		lock(&up->rlock);		up->r = nil;	} 	if(up->killed || up->swipend) {		up->killed = 0;		up->swipend = 0;		unlock(&up->rlock);		splx(s);		error(Eintr);	}	unlock(&up->rlock);	splx(s);} inttfn(void *arg){	return MACHP(0)->ticks >= up->twhen || (*up->tfn)(arg);} voidtsleep(Rendez *r, int (*fn)(void*), void *arg, int ms){	ulong when;	Proc *f, **l; 	if(up == nil)		panic("tsleep() not in process (0x%lux)", getcallerpc(&r)); 	when = MS2TK(ms)+MACHP(0)->ticks;	lock(&talarm);	/* take out of list if checkalarm didn't */	if(up->trend) {		l = &talarm.list;		for(f = *l; f; f = f->tlink) {			if(f == up) {				*l = up->tlink;				break;			}			l = &f->tlink;		}	}	/* insert in increasing time order */	l = &talarm.list;	for(f = *l; f; f = f->tlink) {		if(f->twhen >= when)			break;		l = &f->tlink;	}	up->trend = r;	up->twhen = when;	up->tfn = fn;	up->tlink = *l;	*l = up;	unlock(&talarm); 	if(waserror()){		up->twhen = 0;		nexterror();	}	sleep(r, tfn, arg);	up->twhen = 0;	poperror();} intwakeup(Rendez *r){	Proc *p;	int s; 	s = splhi();	lock(r);	p = r->p;	if(p){		r->p = nil;		if(p->state != Wakeme)			panic("wakeup: state");		ready(p);	}	unlock(r);	splx(s);	return p != nil;} voidswiproc(Proc *p, int interp){	ulong s;	Rendez *r; 	if(p == nil)		return; 	s = splhi();	lock(&p->rlock);	if(!interp)		p->killed = 1;	r = p->r;	if(r != nil) {		lock(r);		if(r->p == p){			p->swipend = 1;			r->p = nil;			ready(p);		}		unlock(r);	}	unlock(&p->rlock);	splx(s);} voidnotkilled(void){	lock(&up->rlock);	up->killed = 0;	unlock(&up->rlock);} voidpexit(char*, int){	Osenv *o; 	up->alarm = 0; 	o = up->env;	if(o != nil){		closefgrp(o->fgrp);		closepgrp(o->pgrp);		closeegrp(o->egrp);		closesigs(o->sigs);	} 	/* Sched must not loop for this lock */	lock(&procalloc); /*	edfstop(up);*/	up->state = Moribund;	sched();	panic("pexit");} Proc*proctab(int i){	return &procalloc.arena[i];} voidprocdump(void){	int i;	char *s;

Lines 1–500 of 788.