~kris/9p

9hist

d75610b71a40a3a99b6fc39ed02eb0b1afe8f101 — David du Colombier 31 years ago 73aa6a9
Plan 9 from Bell Labs 1995-01-02
6 files changed, 128 insertions(+), 151 deletions(-)

M port/auth.c
M port/devproc.c
M port/portdat.h
M port/portfns.h
M port/proc.c
M port/sysproc.c
M port/auth.c => port/auth.c +2 -2
@@ 573,7 573,7 @@ userwrite(char *a, int n)
		error(Eperm);
	memset(up->user, 0, NAMELEN);
	strcpy(up->user, "none");
	up->basepri = PriNormal;
	up->nice = NiceNormal;
	return n;
}



@@ 598,7 598,7 @@ hostownerwrite(char *a, int n)
	renameuser(eve, buf);
	memmove(eve, buf, NAMELEN);
	memmove(up->user, buf, NAMELEN);
	up->basepri = PriNormal;
	up->nice = NiceNormal;
	return n;
}


M port/devproc.c => port/devproc.c +14 -8
@@ 396,8 396,8 @@ procread(Chan *c, void *va, long n, ulong offset)
				l += s->top - s->base;
		}
		readnum(0, statbuf+j+NUMSIZE*6, NUMSIZE, l>>10, NUMSIZE);
		readnum(0, statbuf+j+NUMSIZE*7, NUMSIZE, p->basepri, NUMSIZE);
		readnum(0, statbuf+j+NUMSIZE*8, NUMSIZE, p->priority, NUMSIZE);
		readnum(0, statbuf+j+NUMSIZE*7, NUMSIZE, p->nice, NUMSIZE);
		readnum(0, statbuf+j+NUMSIZE*8, NUMSIZE, p->pri, NUMSIZE);
		memmove(a, statbuf+offset, n);
		return n;



@@ 740,14 740,20 @@ procctlreq(Proc *p, char *va, int n)
	if(strncmp(buf, "pri", 3) == 0){
		if(n < 4)
			error(Ebadctl);
		i = atoi(buf+4);
		i = NiceNormal+atoi(buf+4);
		if(i < 0)
			i = 0;
		if(i >= Nrq)
			i = Nrq - 1;
		if(i < p->basepri && !iseve())
			error(Eperm);
		p->basepri = i;
		if(i >= NiceMax)
			i = NiceMax - 1;
		p->nice = i;
	}
	else
	if(strncmp(buf, "wired", 5) == 0){
		if(n < 6)
			error(Ebadctl);
		i = atoi(buf+6);
		if(i)
			procwired(p);
	}
	else
		error(Ebadctl);

M port/portdat.h => port/portdat.h +7 -11
@@ 501,10 501,10 @@ enum
	NERR = 15,
	NNOTE = 5,

	Nrq		= 20,	/* number of scheduler priority levels */
	PriNormal	= 10,	/* base priority for normal processes */
	PriKproc	= 13,	/* base priority for kernel processes */
	PriRoot		= 13,	/* base priority for root processes */
	NiceMax		= 10,		/* max nice */
	NiceNormal	= 5,		/* base nice for normal processes */
	NiceKproc	= NiceNormal-2,	/* nice for kernel processes */
	NiceRoot	= NiceNormal-2,	/* nice for root processes */
};

struct Proc


@@ 584,13 584,9 @@ struct Proc
	Note	lastnote;
	int	(*notify)(void*, char*);

	Mach	*mp;		/* machine this process last ran on */
	ulong	priority;	/* priority level */
	ulong	basepri;	/* base priority level */
	ulong	rt;		/* # ticks used since last blocked */
	ulong	art;		/* avg # ticks used since last blocked */
	ulong	movetime;	/* last time process switched processors */
	ulong	readytime;	/* time process went ready */
	Mach	*wired;		/* machine this process must run on */
	int	pri;		/* scheduling priority - low is high priority */
	int	nice;		/* time-passing algorithm - low is high priority */

	void	*ureg;		/* User registers for notes */
	void	*dbgreg;	/* User registers for devproc */

M port/portfns.h => port/portfns.h +1 -0
@@ 174,6 174,7 @@ void		procctl(Proc*);
void		procdump(void);
void		procinit0(void);
Proc*		proctab(int);
void		procwired(Proc*);
void		ptclone(Chan*, int, int);
void		ptclose(Pthash*);
Pte*		ptealloc(void);

M port/proc.c => port/proc.c +95 -124
@@ 30,8 30,7 @@ typedef struct
} Schedq;

int	nrdy;
int	lastreadied;
Schedq	runq[Nrq];
Schedq	runq;

char *statename[] =
{			/* BUG: generate automatically */


@@ 117,151 116,101 @@ anyready(void)
int
anyhigher(void)
{
	int x;

	x = lastreadied;
	lastreadied = 0;
	return nrdy && x >= up->priority;
	return nrdy;
}

enum
{
	Squantum = (HZ+Nrq-1)/Nrq,
};

void
ready(Proc *p)
{
	int s, pri;
	Schedq *rq;
	int s;

	s = splhi();

	/* history counts */
	if(p->state == Running){
		p->rt++;
		pri = ((p->art + (p->rt<<1))>>2)/Squantum;
	} else {
		p->art = (p->art + (p->rt<<1))>>2;
		p->rt = 0;
		pri = p->art/Squantum;
	}
	pri = p->basepri - pri;
	if(pri < 0)
		pri = 0;

	/* the only intersection between the classes is at PriNormal */
	if(pri < PriNormal && p->basepri > PriNormal)
		pri = PriNormal;
	p->priority = pri;
	rq = &runq[p->priority];

	lock(runq);
	lock(&runq);
	p->rnext = 0;
	if(rq->tail)
		rq->tail->rnext = p;
	if(runq.tail)
		runq.tail->rnext = p;
	else
		rq->head = p;
	rq->tail = p;
	rq->n++;
		runq.head = p;
	runq.tail = p;
	runq.n++;
	nrdy++;
	p->readytime = m->ticks;
	p->state = Ready;
	if(p->priority > lastreadied)
		lastreadied = p->priority;
	unlock(runq);
	unlock(&runq);
	splx(s);
}

Proc*
runproc(void)
{
	int i;
	Schedq *rq;
	Proc *p, *l;
	static ulong lastfair;
	Proc *p, *bp, *op;

loop:

	/*
	 *  find a process that last ran on this processor (affinity),
	 *  or one that hasn't moved in a while (load balancing).
	 */
	spllo();
	for(;;){

	/* look for potential proc while not locked */
	for(p=runq.head; p; p=p->rnext) {
		/*
		 *  Once a second we look for a long waiting process
		 *  in the lowest priority queue to make sure nothing
		 *  gets starved out by a malfunctioning high priority
		 *  process.
		 *  state is not saved
		 */
		if(m->machno == 0 && m->ticks - lastfair > HZ){
			lastfair = m->ticks;
			for(rq = runq; rq < &runq[Nrq]; rq++){
				p = rq->head;
				if(p){
					i = m->ticks - p->readytime;
					if(i > HZ){
						p->art = 0;
						p->movetime = 0;
						goto found;
					}
					break;
				}
			}
		}

		if(p->mach)
			continue;
		/*
		 *  get highest priority process that this
		 *  processor can run given affinity constraints
		 *  wired to another machine
		 */
		for(rq = &runq[Nrq-1]; rq >= runq; rq--){
			p = rq->head;
			if(p == 0)
				continue;
			for(; p; p = p->rnext){
				if(p->mp == m || m->ticks - p->movetime > HZ/2)
					goto found;
			}
		}
		if(p->wired && p->wired != m)
			continue;
		break;
	}
	if(p == 0)
		goto loop;


found:
	splhi();
	lock(runq);
	lock(&runq);

	l = 0;
	for(p = rq->head; p; p = p->rnext){
		if(p->mp == m || m->ticks - p->movetime > HZ/2)
			break;
		l = p;
	/* find best proc while locked */
	bp = 0;
	for(p=runq.head; p; p=p->rnext) {
		if(p->mach)
			continue;
		if(p->wired && p->wired != m)
			continue;
		if(bp == 0 || p->pri < bp->pri)
			bp = p;
	}

	/*
	 *  p->mach==0 only when process state is saved
	 */
	if(p == 0 || p->mach){	
		unlock(runq);
	if(bp == 0) {
		unlock(&runq);
		goto loop;
	}
	if(p->rnext == 0)
		rq->tail = l;
	if(l)
		l->rnext = p->rnext;

found:
	/* unlink found proc from runq */
	op = 0;
	for(p=runq.head; p; p=p->rnext) {
		if(p == bp)
			break;
		op = p;
	}
	if(op == 0)
		runq.head = bp->rnext;
	else
		rq->head = p->rnext;
	rq->n--;
		op->rnext = bp->rnext;
	if(bp == runq.tail)
		runq.tail = op;

	/* clear next so that unlocked runq will not loop */
	bp->rnext = 0;

	runq.n--;
	nrdy--;
	if(p->state != Ready)
		print("runproc %s %d %s\n", p->text, p->pid, statename[p->state]);
	unlock(runq);

	p->state = Scheding;
	if(p->mp != m)
		p->movetime = m->ticks;
	p->mp = m;
	return p;
	if(bp->state != Ready)
		print("runproc %s %d %s\n", bp->text, bp->pid, statename[bp->state]);
	unlock(&runq);

	bp->state = Scheding;
	return bp;
}

int


@@ 270,13 219,13 @@ canpage(Proc *p)
	int ok = 0;

	splhi();
	lock(runq);
	lock(&runq);
	/* Only reliable way to see if we are Running */
	if(p->mach == 0) {
		p->newtlb = 1;
		ok = 1;
	}
	unlock(runq);
	unlock(&runq);
	spllo();

	return ok;


@@ 316,8 265,9 @@ newproc(void)
	p->kp = 0;
	p->procctl = 0;
	p->notepending = 0;
	p->mp = 0;
	p->movetime = 0;
	p->nice = NiceNormal;
	p->pri = 0;
	p->wired = 0;
	memset(p->seg, 0, sizeof p->seg);
	p->pid = incref(&pidalloc);
	p->noteid = incref(&noteidalloc);


@@ 329,6 279,30 @@ newproc(void)
	return p;
}

/*
 * wire this proc to a machine
 */
void
procwired(Proc *p)
{
	Proc *pp;
	int i, bm;
	char nwired[MAXMACH];

	memset(nwired, 0, sizeof(nwired));
	p->wired = 0;
	pp = proctab(0);
	for(i=0; i<conf.nproc; i++, pp++)
		if(pp->wired && pp->pid)
			nwired[pp->wired->machno]++;
	bm = 0;
	for(i=0; i<conf.nmach; i++)
		if(nwired[i] < nwired[bm])
			bm = i;
	p->wired = MACHP(bm);
print("pid %d wired to machine %d\n", p->pid, p->wired->machno);
}

void
procinit0(void)		/* bad planning - clashes with devproc.c */
{


@@ 767,7 741,6 @@ procdump(void)
	char *s;
	Proc *p;
	ulong bss;
	Schedq *rq;

	for(i=0; i<conf.nproc; i++) {
		p = &procalloc.arena[i];


@@ 784,12 757,10 @@ procdump(void)
			p->pid, p->text, p->pc,  s, statename[p->state],
			p->time[0], p->time[1], bss);
	}
	for(rq = &runq[Nrq-1]; rq >= runq; rq--){
		if(rq->head == 0)
			continue;
		print("rq%d:", rq-runq);
		for(p = rq->head; p; p = p->rnext)
			print(" %d(%d)", p->pid, m->ticks - p->readytime);
	if(runq.head != 0) {
		print("rq:");
		for(p = runq.head; p; p = p->rnext)
			print(" %d(%d)", p->pid, p->pri);
		print("\n");
	}
	print("nrdy %d\n", nrdy);


@@ 822,8 793,8 @@ kproc(char *name, void (*func)(void *), void *arg)
	p->ureg = 0;
	p->dbgreg = 0;

	p->basepri = PriKproc;
	p->priority = p->basepri;
	p->nice = NiceKproc;
	p->pri = 0;

	kprocchild(p, func, arg);


M port/sysproc.c => port/sysproc.c +9 -6
@@ 178,9 178,10 @@ sysrfork(ulong *arg)
	 *  (i.e. has bad properties) and has to be discarded.
	 */
	flushmmu();
	p->priority = up->priority;
	p->basepri = up->basepri;
	p->mp = up->mp;
	p->nice = up->nice;
	p->pri = up->pri;
	if(up->wired)
		procwired(p);
	ready(p);
	return pid;
}


@@ 396,9 397,11 @@ sysexec(ulong *arg)
	/*
	 *  '/' processes are higher priority (hack to make /ip more responsive).
	 */
	if(devchar[tc->type] == L'/')
		up->basepri = PriRoot;
	up->priority = up->basepri;
	up->nice = NiceNormal;
	if(devchar[tc->type] == L'/') {
		up->nice = NiceRoot;
		up->pri = 0;
	}
	poperror();
	close(tc);