~kris/9p

9hist

c935dc90dbbadda92d6cb5eb457ea84f088c6214 — David du Colombier 31 years ago 16c2bd6
Plan 9 from Bell Labs 1995-01-10
M carrera/clock.c => carrera/clock.c +1 -2
@@ 47,7 47,6 @@ clockinit(void)
void
clock(Ureg *ur)
{
	int n;

	wrcompare(rdcount()+(m->speed*1000000)/HZ);



@@ 78,7 77,7 @@ clock(Ureg *ur)
	if(up == 0 || up->state != Running)
		return;

	if(anyready() && !up->inlock)
	if(anyready())
		sched();

	/* user profiling clock */

M carrera/trap.c => carrera/trap.c +1 -1
@@ 397,7 397,7 @@ intr(Ureg *ur)
	}

	/* preemptive scheduling */
	if(up && up->state == Running && anyhigher() && !up->inlock)
	if(up && up->state == Running && anyhigher())
		sched();
}


M pc/clock.c => pc/clock.c +1 -1
@@ 45,7 45,7 @@ clock(Ureg *ur, void *arg)
	uartclock();

	if(up && up->state == Running){
		if(anyready() && !up->inlock)
		if(anyready())
			sched();
	
		/* user profiling clock */

M port/auth.c => port/auth.c +3 -5
@@ 124,10 124,8 @@ sysfsession(ulong *arg)
	unlock(c);

	/* back off if someone else is doing an fsession */
	while(!canlock(&s->send)) {
		up->yield = 1;
	while(!canlock(&s->send))
		sched();
	}

	if(s->valid == 0){
		/*


@@ 575,7 573,7 @@ userwrite(char *a, int n)
		error(Eperm);
	memset(up->user, 0, NAMELEN);
	strcpy(up->user, "none");
	up->nice = NiceNormal;
	up->basepri = PriNormal;
	return n;
}



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


M port/devXXX.c => port/devXXX.c +27 -19
@@ 12,13 12,13 @@
#include	"devtab.h"

enum{
	XXXdirqid,
	XXXdataqid,
	Qdir,
	Qdata,
};
Dirtab XXXtab[]={
	"data",		XXXdataqid,		0,	0600,
	"data",		{Qdata, 0},	0,	0600,
};
#define NXXXtab (sizeof(XXXTab)/sizeof(Dirtab))
#define NXXXtab (sizeof(XXXtab)/sizeof(Dirtab))

void
XXXreset(void)


@@ 45,43 45,39 @@ XXXclone(Chan *c, Chan *nc)
int
XXXwalk(Chan *c, char *name)
{
	return devwalk(c, name, XXXtab, (long)NXXXtab, devgen);
	return devwalk(c, name, XXXtab, NXXXtab, devgen);
}

void
XXXstat(Chan *c, char *db)
{
	devstat(c, db, XXXtab, (long)NXXXtab, devgen);
	devstat(c, db, XXXtab, NXXXtab, devgen);
}

Chan *
XXXopen(Chan *c, int omode)
{
	if(c->qid.path == CHDIR){
		if(omode != OREAD)
			error(Eperm);
	}
	c->mode = openmode(omode);
	c->flag |= COPEN;
	c->offset = 0;
	return c;
	return devopen(c, omode, XXXtab, NXXXtab, devgen);
}

void
XXXcreate(Chan *c, char *name, int omode, ulong perm)
{
	USED(c, name, omode, perm);
	error(Eperm);
}

void
XXXremove(Chan *c)
{
	USED(c);
	error(Eperm);
}

void
XXXwstat(Chan *c, char *dp)
{
	USED(c, dp);
	error(Eperm);
}



@@ 93,10 89,10 @@ XXXclose(Chan *c)
long
XXXread(Chan *c, void *a, long n, ulong offset)
{
	switch((int)(c->qid.path&~CHDIR)){
	case XXXdirqid:
	switch(c->qid.path & ~CHDIR){
	case Qdir:
		return devdirread(c, a, n, XXXtab, NXXXtab, devgen);
	case XXXdataqid:
	case Qdata:
		break;
	default:
		n=0;


@@ 105,14 101,26 @@ XXXread(Chan *c, void *a, long n, ulong offset)
	return n;
}

Block*
XXXbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

long
XXXwrite(Chan *c, char *a, long n, ulong offset)
{
	switch((int)(c->qid.path&~CHDIR)){
	case XXXdataqid:
	switch(c->qid.path & ~CHDIR){
	case Qdata:
		break;
	default:
		error(Ebadusefd);
	}
	return n;
}

long
XXXbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

M port/devproc.c => port/devproc.c +10 -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->nice, NUMSIZE);
		readnum(0, statbuf+j+NUMSIZE*8, NUMSIZE, p->pri, NUMSIZE);
		readnum(0, statbuf+j+NUMSIZE*7, NUMSIZE, p->basepri, NUMSIZE);
		readnum(0, statbuf+j+NUMSIZE*8, NUMSIZE, p->priority, NUMSIZE);
		memmove(a, statbuf+offset, n);
		return n;



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

M port/portdat.h => port/portdat.h +12 -9
@@ 503,10 503,10 @@ enum
	NERR = 15,
	NNOTE = 5,

	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 */
	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 */
};

struct Proc


@@ 586,11 586,14 @@ struct Proc
	Note	lastnote;
	int	(*notify)(void*, char*);

	Mach	*wired;		/* machine this process must run on */
	int	pri;		/* scheduling priority - low is high priority */
	short	nice;		/* time-passing algorithm - low is high priority */
	char	yield;		/* force one lap in the runq */
	char	inlock;		/* temp hi proirity ~= 2*num of locks set */
	Mach	*wired;
	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 */

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

M port/proc.c => port/proc.c +145 -119
@@ 29,8 29,9 @@ typedef struct
	int	n;
} Schedq;

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

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


@@ 106,109 107,155 @@ sched(void)
int
anyready(void)
{
	return runq.n;
	return nrdy;
}

int
anyhigher(void)
{
	Proc *p;
	int pri;
	int x;

	pri = up->pri;
	for(p=runq.head; p; p=p->rnext)
		if(p->pri <= pri)
			if(p->wired == 0 || p->wired == m)
				return 1;
	return 0;
	x = lastreadied;
	lastreadied = 0;
	return nrdy && x >= up->priority;
}

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

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

	s = splhi();

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

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

loop:

	/*
	 *  find a process that last ran on this processor (affinity),
	 *  or one that hasn't moved in a while (load balancing).
	 */
	spllo();
	for(;;){
		/*
		 *  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.
		 */
		if((m->ticks % HZ) == 0){
			for(rq = runq; rq < &runq[Nrq]; rq++){
				p = rq->head;
				if(p == 0 || p->mp != m)
					continue;

				i = m->ticks - p->readytime;
				if(i < HZ)
					break;

				p->art = 0;
				goto found;
			}
		}

	/* look for potential proc while not locked */
	for(p = runq.head; p; p=p->rnext) {
		/*
		 *  state is not saved or wired to another machine
		 *  get highest priority process that this
		 *  processor can run given affinity constraints
		 */
		if(!(p->mach || (p->wired && p->wired != m)))
			break;
		for(rq = &runq[Nrq-1]; rq >= runq; rq--){
			p = rq->head;
			if(p == 0)
				continue;
			for(; p; p = p->rnext){
				if(p->mp == m || p->movetime < m->ticks)
					goto found;
			}
		}
	}
	if(p == 0)
		goto loop;


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

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

found:
	/* unlink found proc from runq */
	op = 0;
	for(p=runq.head; p; p=p->rnext) {
		if(p == bp)
			break;
		op = p;
	/*
	 *  p->mach==0 only when process state is saved
	 */
	if(p == 0 || p->mach){	
		unlock(runq);
		goto loop;
	}
	if(op == 0)
		runq.head = bp->rnext;
	if(p->rnext == 0)
		rq->tail = l;
	if(l)
		l->rnext = p->rnext;
	else
		op->rnext = bp->rnext;
	if(bp == runq.tail)
		runq.tail = op;

	/* clear next so that unlocked runq will not loop */
	bp->rnext = 0;
		rq->head = p->rnext;
	rq->n--;
	nrdy--;
	if(p->state != Ready)
		print("runproc %s %d %s\n", p->text, p->pid, statename[p->state]);
	unlock(runq);

	runq.n--;

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

	bp->state = Scheding;
	return bp;
	p->state = Scheding;
	if(p->mp != m)
		p->movetime = m->ticks + HZ/2;
	p->mp = m;
	return p;
}

int


@@ 217,13 264,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;


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


@@ 298,6 345,8 @@ procwired(Proc *p)
		if(nwired[i] < nwired[bm])
			bm = i;
	p->wired = MACHP(bm);
	p->movetime = 0xffffffff;
	p->mp = p->wired;
}

void


@@ 313,14 362,6 @@ procinit0(void)		/* bad planning - clashes with devproc.c */
	for(i=0; i<conf.nproc-1; i++,p++)
		p->qnext = p+1;
	p->qnext = 0;

	/*
	 * set up priority increments
	 * normal priority sb about 1000/HZ
	 * highest pri (lowest number) sb about 0
	 */
	for(i=0; i<NiceMax; i++)
		priconst[i] = (i*1000)/(NiceNormal*HZ);
}

void


@@ 364,11 405,12 @@ sleep(Rendez *r, int (*f)(void*), void *arg)
{
	int s;

	if((getstatus()&IE) == 0)
		print("sleep hi %lux\n", getcallerpc(r));

	sleep1(r, f, arg);
	if(up->notepending == 0) {
		up->yield = 1;
	if(up->notepending == 0)
		sched();	/* notepending may go true while asleep */
	}

	if(up->notepending) {
		up->notepending = 0;


@@ 394,6 436,9 @@ tsleep(Rendez *r, int (*fn)(void*), void *arg, int ms)
	ulong when;
	Proc *f, **l;

	if((getstatus()&IE) == 0)
		print("tsleep hi %lux\n", getcallerpc(r));

	when = MS2TK(ms)+MACHP(0)->ticks;

	lock(&talarm);


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

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


@@ 766,13 812,15 @@ procdump(void)
			p->pid, p->text, p->pc,  s, statename[p->state],
			p->time[0], p->time[1], bss);
	}
	if(runq.head != 0) {
		print("rq:");
		for(p = runq.head; p; p = p->rnext)
			print(" %d(%d)", p->pid, p->pri);
	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);
		print("\n");
	}
	print("nrdy %d\n", runq.n);
	print("nrdy %d\n", nrdy);
}

void


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

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

	kprocchild(p, func, arg);



@@ 872,6 920,9 @@ procctl(Proc *p)
void
error(char *err)
{
	if((getstatus()&IE) == 0)
		print("error hi %lux\n", getcallerpc(err));
	spllo();
	strncpy(up->error, err, ERRLEN);
	nexterror();
}


@@ 950,21 1001,13 @@ void
accounttime(void)
{
	Proc *p;
	int i, pri;
	static int nrun, m0ticks;
	int n;
	static int nrun;

	p = m->proc;
	if(p) {
		nrun++;
		p->time[p->insyscall]++;
		p->pri += priconst[p->nice];
	}

	if(up) {
		i = up->inlock-1;
		if(i < 0)
			i = 0;
		up->inlock = i;
	}

	/* only one processor gets to compute system load averages */


@@ 972,26 1015,9 @@ accounttime(void)
		return;

	/* calculate decaying load average */
	pri = nrun;
	n = nrun;
	nrun = 0;

	pri = (runq.n+pri)*1000;
	m->load = (m->load*19+pri)/20;

	/*
	 * decay per-process cpu usage
	 *	pri = (3/4)*pri twice per second
	 *	tc = (3/4)^2/(1-(3/4)^2) = 1.286 sec
	 */
	m0ticks--;
	if(m0ticks <= 0) {
		m0ticks = HZ/2;
		p = proctab(0);
		for(i=conf.nproc-1; i!=0; i--,p++)
			if(p->state != Dead) {
				pri = p->pri;
				pri -= pri >> 2;
				p->pri = pri;
			}
	}
	n = (nrdy+n)*1000;
	m->load = (m->load*19+n)/20;
}

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


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



@@ 462,11 462,11 @@ return0(void *a)
long
syssleep(ulong *arg)
{

	int n;

	n = arg[0];
	if(n <= 0) {
		up->yield = 1;
		sched();
		return 0;
	} 

M port/taslock.c => port/taslock.c +21 -48
@@ 8,86 8,59 @@
void
lock(Lock *l)
{
	int n;
	if(tas(&l->key) == 0)
		return;

	if(up) {
		n = up->inlock+2;
		up->inlock = n;
	for(;;){
		while(l->key)
			;
		if(tas(&l->key) == 0)
			return;

		for(;;){
			while(l->key)
				if(conf.nproc == 1) {
					up->yield = 1;
					sched();
				}
			up->inlock = n;
			if(tas(&l->key) == 0)
				return;
		}
	}
}

	if(tas(&l->key) == 0)
void
ilock(Lock *l)
{
	ulong x;

	x = splhi();
	if(tas(&l->key) == 0){
		l->sr = x;
		return;
	}

	for(;;){
		while(l->key)
			;
		if(tas(&l->key) == 0)
		if(tas(&l->key) == 0){
			l->sr = x;
			return;
		}
	}
}

int
canlock(Lock *l)
{
	int n;

	if(up) {
		n = up->inlock;
		up->inlock = n+2;
		if(tas(&l->key)) {
			up->inlock = n;
			return 0;
		}
		return 1;
	}

	if(tas(&l->key))
		return 0;

	return 1;
}

void
unlock(Lock *l)
{
	int n;

	if(up) {
		n = up->inlock-2;
		if(n < 0)
			n = 0;
		up->inlock = n;
	}
	l->key = 0;
}

void
ilock(Lock *l)
{
	ulong sr;

	sr = splhi();
	lock(l);
	l->sr = sr;
}

void
iunlock(Lock *l)
{
	ulong sr;

	sr = l->sr;
	unlock(l);
	l->key = 0;
	splx(sr);
}

M power/clock.c => power/clock.c +1 -1
@@ 103,7 103,7 @@ clock(Ureg *ur)
	if(up == 0 || (ur->status&IEP) == 0 || up->state != Running)
		return;

	if(anyready() && !up->inlock)
	if(anyready())
		sched();

	/* user profiling clock */