plan 9 kernel history: overview | file list | diff list

1996/0426/port/proc.c (diff list | history)

port/proc.c on 1990/0227
1990/0227    
#include	"u.h" 
1992/0321    
#include	"../port/lib.h" 
1990/0227    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
1992/0111    
#include	"../port/error.h" 
1990/0227    
 
1992/0309    
Ref	pidalloc; 
1992/0428    
Ref	noteidalloc; 
1990/0227    
 
struct 
{ 
	Lock; 
	Proc	*arena; 
	Proc	*free; 
}procalloc; 
 
1991/0926    
struct 
{ 
	Lock; 
	Waitq	*free; 
}waitqalloc; 
 
1994/0914    
typedef struct 
{ 
	Lock; 
	Proc	*head; 
	Proc	*tail; 
	int	n; 
} Schedq; 
1994/0728    
 
1995/0110    
int	nrdy; 
int	lastreadied; 
Schedq	runq[Nrq]; 
1991/0420    
 
1992/0309    
char *statename[] = 
{			/* BUG: generate automatically */ 
1990/0227    
	"Dead", 
	"Moribund", 
	"Ready", 
	"Scheding", 
	"Running", 
	"Queueing", 
	"Wakeme", 
	"Broken", 
1991/0705    
	"Stopped", 
1991/0806    
	"Rendez", 
1990/0227    
}; 
 
/* 
 * Always splhi()'ed. 
 */ 
void 
schedinit(void)		/* never returns */ 
{ 
	setlabel(&m->sched); 
1993/0501    
	if(up) { 
1990/0227    
		m->proc = 0; 
1993/0501    
		switch(up->state) { 
		case Running: 
			ready(up); 
			break; 
		case Moribund: 
			up->state = Dead; 
1991/0705    
			/*  
1991/0717    
			 * Holding locks from pexit: 
1995/0112    
			 * 	procalloc 
1991/0705    
			 */ 
1993/0501    
			mmurelease(up); 
1991/0705    
 
1993/0501    
			up->qnext = procalloc.free; 
			procalloc.free = up; 
1995/1230    
 
			unlock(&palloc); 
1990/0227    
			unlock(&procalloc); 
1993/0501    
			break; 
1990/0227    
		} 
1993/0501    
		up->mach = 0; 
		up = 0; 
1990/0227    
	} 
	sched(); 
} 
 
void 
sched(void) 
{ 
1993/0501    
	if(up) { 
1990/0227    
		splhi(); 
1993/1212    
 
		/* statistics */ 
1991/0425    
		m->cs++; 
1993/1212    
 
1993/0501    
		procsave(up); 
		if(setlabel(&up->sched)) { 
			procrestore(up); 
1990/0227    
			spllo(); 
			return; 
		} 
		gotolabel(&m->sched); 
	} 
1993/0501    
	up = runproc(); 
	up->state = Running; 
1995/0811    
	up->mach = MACHP(m->machno); 
1993/0501    
	m->proc = up; 
	mmuswitch(up); 
	gotolabel(&up->sched); 
1994/0311    
} 
 
1994/0321    
int 
anyready(void) 
{ 
1995/0110    
	return nrdy; 
1990/1227    
} 
 
1994/0809    
int 
1994/0817    
anyhigher(void) 
1994/0809    
{ 
1995/0110    
	int x; 
1994/0817    
 
1995/0110    
	x = lastreadied; 
	lastreadied = 0; 
	return nrdy && x >= up->priority; 
1994/0809    
} 
 
1995/0110    
enum 
{ 
	Squantum = (HZ+Nrq-1)/Nrq, 
}; 
 
1990/0227    
void 
ready(Proc *p) 
{ 
1995/0110    
	int s, pri; 
	Schedq *rq; 
1990/0227    
 
	s = splhi(); 
1991/0501    
 
1995/0110    
	/* 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); 
1990/0227    
	p->rnext = 0; 
1995/0110    
	if(rq->tail) 
		rq->tail->rnext = p; 
1990/0227    
	else 
1995/0110    
		rq->head = p; 
	rq->tail = p; 
	rq->n++; 
	nrdy++; 
	p->readytime = m->ticks; 
1990/0227    
	p->state = Ready; 
1995/0110    
	if(p->priority > lastreadied) 
		lastreadied = p->priority; 
	unlock(runq); 
1990/0227    
	splx(s); 
} 
 
Proc* 
runproc(void) 
{ 
1995/0110    
	int i; 
	Schedq *rq; 
	Proc *p, *l; 
1990/0227    
 
loop: 
1995/0110    
 
	/* 
	 *  find a process that last ran on this processor (affinity), 
	 *  or one that hasn't moved in a while (load balancing). 
	 */ 
1992/0603    
	spllo(); 
1995/0912    
	for(;;){ 
1995/0110    
		/* 
1996/0315    
		 *  get lowest priority process that this 
		 *  processor can run given affinity constraints 
		 *  and that hasn't run in a while 
1995/0110    
		 */ 
1996/0315    
		if((m->ticks & 3) == 0){ 
1995/0110    
			for(rq = runq; rq < &runq[Nrq]; rq++){ 
				p = rq->head; 
1996/0315    
				if(p == 0) 
1995/0110    
					continue; 
1996/0315    
				for(; p; p = p->rnext){ 
					if(p->mp != MACHP(m->machno)) 
					if(p->movetime >= m->ticks) 
						continue; 
					i = m->ticks - p->readytime; 
					if(i >= 2*nrdy*p->art) 
						goto found; 
				} 
1995/0110    
			} 
		} 
 
1994/0918    
		/* 
1995/0110    
		 *  get highest priority process that this 
		 *  processor can run given affinity constraints 
1994/0918    
		 */ 
1995/0110    
		for(rq = &runq[Nrq-1]; rq >= runq; rq--){ 
			p = rq->head; 
			if(p == 0) 
				continue; 
			for(; p; p = p->rnext){ 
1996/0315    
				if(p->mp == MACHP(m->machno) 
				|| p->movetime < m->ticks) 
1995/0110    
					goto found; 
			} 
		} 
1994/0729    
	} 
1995/0110    
 
found: 
1994/0729    
	splhi(); 
1995/0110    
	lock(runq); 
1991/0420    
 
1995/0110    
	l = 0; 
	for(p = rq->head; p; p = p->rnext){ 
1995/0811    
		if(p->mp == MACHP(m->machno) || p->movetime < m->ticks) 
1995/0110    
			break; 
		l = p; 
1994/0728    
	} 
1995/0110    
 
	/* 
	 *  p->mach==0 only when process state is saved 
	 */ 
	if(p == 0 || p->mach){	 
		unlock(runq); 
1990/0227    
		goto loop; 
	} 
1995/0110    
	if(p->rnext == 0) 
		rq->tail = l; 
	if(l) 
		l->rnext = p->rnext; 
1994/0728    
	else 
1995/0110    
		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); 
1995/0102    
 
1995/0110    
	p->state = Scheding; 
1995/0811    
	if(p->mp != MACHP(m->machno)) 
1995/0110    
		p->movetime = m->ticks + HZ/2; 
1995/0811    
	p->mp = MACHP(m->machno); 
1995/0110    
	return p; 
1990/0227    
} 
 
1991/0705    
int 
canpage(Proc *p) 
{ 
	int ok = 0; 
 
	splhi(); 
1995/0110    
	lock(runq); 
1991/0906    
	/* Only reliable way to see if we are Running */ 
	if(p->mach == 0) { 
1991/0705    
		p->newtlb = 1; 
		ok = 1; 
	} 
1995/0110    
	unlock(runq); 
1991/0705    
	spllo(); 
 
	return ok; 
} 
 
1990/0227    
Proc* 
newproc(void) 
{ 
	Proc *p; 
 
1993/0501    
	lock(&procalloc); 
1991/1110    
	for(;;) { 
1993/0501    
		if(p = procalloc.free) 
			break; 
 
1990/0227    
		unlock(&procalloc); 
1991/1110    
		resrcwait("no procs"); 
1993/0501    
		lock(&procalloc); 
1990/0227    
	} 
1993/0501    
	procalloc.free = p->qnext; 
	unlock(&procalloc); 
 
	p->state = Scheding; 
	p->psstate = "New"; 
	p->mach = 0; 
	p->qnext = 0; 
	p->nchild = 0; 
	p->nwait = 0; 
	p->waitq = 0; 
	p->pgrp = 0; 
	p->egrp = 0; 
	p->fgrp = 0; 
1994/0812    
	p->rgrp = 0; 
1993/0501    
	p->pdbg = 0; 
	p->fpstate = FPinit; 
	p->kp = 0; 
	p->procctl = 0; 
	p->notepending = 0; 
1995/0110    
	p->mp = 0; 
	p->movetime = 0; 
1995/0102    
	p->wired = 0; 
1995/0115    
	p->ureg = 0; 
1996/0426    
	p->error[0] = '\0'; 
1993/0501    
	memset(p->seg, 0, sizeof p->seg); 
	p->pid = incref(&pidalloc); 
	p->noteid = incref(¬eidalloc); 
	if(p->pid==0 || p->noteid==0) 
		panic("pidalloc"); 
	if(p->kstack == 0) 
		p->kstack = smalloc(KSTACK); 
 
	return p; 
1990/0227    
} 
 
1995/0102    
/* 
 * wire this proc to a machine 
 */ 
1990/0227    
void 
1995/0102    
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); 
1995/0110    
	p->movetime = 0xffffffff; 
	p->mp = p->wired; 
1995/0102    
} 
 
void 
1990/0227    
procinit0(void)		/* bad planning - clashes with devproc.c */ 
{ 
	Proc *p; 
	int i; 
 
1992/0619    
	procalloc.free = xalloc(conf.nproc*sizeof(Proc)); 
1990/0227    
	procalloc.arena = procalloc.free; 
 
	p = procalloc.free; 
1994/0612    
	for(i=0; i<conf.nproc-1; i++,p++) 
1990/0227    
		p->qnext = p+1; 
	p->qnext = 0; 
} 
 
void 
sleep1(Rendez *r, int (*f)(void*), void *arg) 
{ 
	int s; 
 
	/* 
	 * spl is to allow lock to be called 
	 * at interrupt time. lock is mutual exclusion 
	 */ 
	s = splhi(); 
1993/0501    
	up->r = r;	/* early so postnote knows */ 
1990/0227    
	lock(r); 
 
	/* 
	 * if condition happened, never mind 
	 */ 
1991/0727    
	if((*f)(arg)){ 
1993/0501    
		up->r = 0; 
1990/0227    
		unlock(r); 
		splx(s); 
		return; 
	} 
 
	/* 
	 * now we are committed to 
	 * change state and call scheduler 
	 */ 
1991/0807    
	if(r->p){ 
1993/0501    
		print("double sleep %d %d\n", r->p->pid, up->pid); 
1991/0807    
		dumpstack(); 
	} 
1993/0501    
	up->state = Wakeme; 
	r->p = up; 
1990/0227    
	unlock(r); 
} 
 
void 
sleep(Rendez *r, int (*f)(void*), void *arg) 
{ 
1992/0519    
	int s; 
1991/0727    
 
1990/0227    
	sleep1(r, f, arg); 
1995/0110    
	if(up->notepending == 0) 
1991/0727    
		sched();	/* notepending may go true while asleep */ 
1993/0501    
 
	if(up->notepending) { 
		up->notepending = 0; 
1992/0519    
		s = splhi(); 
1991/0805    
		lock(r); 
1993/0501    
		if(r->p == up) 
1991/0805    
			r->p = 0; 
		unlock(r); 
1992/0519    
		splx(s); 
1990/11211    
		error(Eintr); 
1990/0227    
	} 
} 
 
1992/0617    
int 
tfn(void *arg) 
{ 
1993/0501    
	return MACHP(0)->ticks >= up->twhen || (*up->tfn)(arg); 
1992/0617    
} 
 
1990/0227    
void 
1992/0602    
tsleep(Rendez *r, int (*fn)(void*), void *arg, int ms) 
1990/0227    
{ 
1994/0812    
	ulong when; 
1993/0501    
	Proc *f, **l; 
1990/0227    
 
1992/0602    
	when = MS2TK(ms)+MACHP(0)->ticks; 
 
	lock(&talarm); 
1992/0701    
	/* take out of list if checkalarm didn't */ 
1993/0501    
	if(up->trend) { 
1992/0701    
		l = &talarm.list; 
		for(f = *l; f; f = f->tlink) { 
1993/0501    
			if(f == up) { 
				*l = up->tlink; 
1992/0701    
				break; 
			} 
			l = &f->tlink; 
		} 
	} 
	/* insert in increasing time order */ 
1992/0602    
	l = &talarm.list; 
1992/0701    
	for(f = *l; f; f = f->tlink) { 
		if(f->twhen >= when) 
			break; 
1992/0602    
		l = &f->tlink; 
1991/0727    
	} 
1993/0501    
	up->trend = r; 
	up->twhen = when; 
	up->tfn = fn; 
	up->tlink = *l; 
	*l = up; 
1992/0602    
	unlock(&talarm); 
 
1992/0617    
	sleep(r, tfn, arg); 
1993/0501    
	up->twhen = 0; 
1990/0227    
} 
 
1992/0909    
/* 
 * Expects that only one process can call wakeup for any given Rendez 
 */ 
1990/0227    
void 
wakeup(Rendez *r) 
{ 
	Proc *p; 
	int s; 
 
	s = splhi(); 
	lock(r); 
	p = r->p; 
	if(p){ 
		r->p = 0; 
1991/0705    
		if(p->state != Wakeme)  
			panic("wakeup: state"); 
1990/0227    
		p->r = 0; 
		ready(p); 
	} 
	unlock(r); 
	splx(s); 
1990/03091    
} 
 
1990/0227    
int 
postnote(Proc *p, int dolock, char *n, int flag) 
{ 
1991/1120    
	int s, ret; 
1990/0227    
	Rendez *r; 
1991/0806    
	Proc *d, **l; 
1990/0227    
 
	if(dolock) 
1991/1216    
		qlock(&p->debug); 
1991/0430    
 
1993/0112    
	if(p->kp) 
		print("sending %s to kproc %d %s\n", n, p->pid, p->text); 
 
1993/0501    
	if(flag != NUser && (p->notify == 0 || p->notified)) 
		p->nnote = 0; 
1991/0425    
 
1991/1120    
	ret = 0; 
1993/0501    
	if(p->nnote < NNOTE) { 
		strcpy(p->note[up->nnote].msg, n); 
		p->note[p->nnote++].flag = flag; 
1991/1120    
		ret = 1; 
1990/0617    
	} 
1991/0727    
	p->notepending = 1; 
1990/0227    
	if(dolock) 
1991/1216    
		qunlock(&p->debug); 
1991/0705    
 
1995/0104    
	r = p->r; 
	if(r != 0) { 
1992/0909    
		for(;;) { 
			s = splhi(); 
			if(canlock(r)) 
				break; 
			splx(s); 
		} 
1993/0501    
		/* check we won the race */ 
		if(p->r == r && r->p == p && p->state==Wakeme) { 
1992/0909    
			r->p = 0; 
			p->r = 0; 
			ready(p); 
1990/0227    
		} 
		unlock(r); 
		splx(s); 
	} 
1991/0807    
 
1992/1206    
	if(p->state != Rendezvous) 
		return ret; 
 
	/* Try and pull out of a rendezvous */ 
1994/0812    
	lock(p->rgrp); 
1991/0806    
	if(p->state == Rendezvous) { 
1992/1206    
		p->rendval = ~0; 
1994/0812    
		l = &REND(p->rgrp, p->rendtag); 
1992/1206    
		for(d = *l; d; d = d->rendhash) { 
			if(d == p) { 
				*l = p->rendhash; 
				break; 
1991/0806    
			} 
1992/1206    
			l = &d->rendhash; 
1991/0806    
		} 
1993/0501    
		ready(p); 
1991/0806    
	} 
1994/0812    
	unlock(p->rgrp); 
1991/1120    
	return ret; 
1990/0227    
} 
 
1990/1101    
/* 
 * weird thing: keep at most NBROKEN around 
 */ 
#define	NBROKEN 4 
1992/1206    
struct 
{ 
	QLock; 
1990/1101    
	int	n; 
	Proc	*p[NBROKEN]; 
}broken; 
 
1990/0227    
void 
1992/1206    
addbroken(Proc *p) 
1990/1101    
{ 
1992/1206    
	qlock(&broken); 
	if(broken.n == NBROKEN) { 
1990/1101    
		ready(broken.p[0]); 
1991/0318    
		memmove(&broken.p[0], &broken.p[1], sizeof(Proc*)*(NBROKEN-1)); 
1990/1101    
		--broken.n; 
	} 
1992/1206    
	broken.p[broken.n++] = p; 
	qunlock(&broken); 
 
	p->state = Broken; 
	p->psstate = 0; 
	sched(); 
1990/1101    
} 
 
1992/1206    
void 
unbreak(Proc *p) 
{ 
	int b; 
 
	qlock(&broken); 
1992/1208    
	for(b=0; b < broken.n; b++) 
1992/1225    
		if(broken.p[b] == p) { 
1992/1208    
			broken.n--; 
			memmove(&broken.p[b], &broken.p[b+1], 
					sizeof(Proc*)*(NBROKEN-(b+1))); 
			ready(p); 
			break; 
		} 
1992/1206    
	qunlock(&broken); 
} 
 
1990/1101    
int 
freebroken(void) 
{ 
1991/0109    
	int i, n; 
1990/1101    
 
1992/1206    
	qlock(&broken); 
1990/1101    
	n = broken.n; 
1992/1206    
	for(i=0; i<n; i++) { 
1991/0109    
		ready(broken.p[i]); 
1992/1206    
		broken.p[i] = 0; 
	} 
1991/0109    
	broken.n = 0; 
1992/1206    
	qunlock(&broken); 
1990/1101    
	return n; 
} 
 
void 
1991/0717    
pexit(char *exitstr, int freemem) 
1990/0227    
{ 
1991/1218    
	int n; 
1993/0501    
	Proc *p; 
1992/1206    
	Segment **s, **es; 
1993/0501    
	long utime, stime; 
1991/0926    
	Waitq *wq, *f, *next; 
1990/0227    
 
1993/0501    
	up->alarm = 0; 
1991/0517    
 
1993/0501    
	if(up->fgrp) 
		closefgrp(up->fgrp); 
	if(up->egrp) 
		closeegrp(up->egrp); 
1994/0812    
	if(up->rgrp) 
		closergrp(up->rgrp); 
1991/0517    
 
1993/0501    
	close(up->dot); 
	closepgrp(up->pgrp); 
 
1992/0115    
	/* 
	 * if not a kernel process and have a parent, 
	 * do some housekeeping. 
	 */ 
1993/0501    
	if(up->kp == 0) { 
		p = up->parent; 
1992/1206    
		if(p == 0) { 
1992/0902    
			if(exitstr == 0) 
				exitstr = "unknown"; 
			panic("boot process died: %s", exitstr); 
		} 
1992/0805    
 
		while(waserror()) 
1993/0501    
			; 
	 
1992/0620    
		wq = smalloc(sizeof(Waitq)); 
1992/0805    
		poperror(); 
 
1993/0501    
		readnum(0, wq->w.pid, NUMSIZE, up->pid, NUMSIZE); 
		utime = up->time[TUser] + up->time[TCUser]; 
		stime = up->time[TSys] + up->time[TCSys]; 
1992/0309    
		readnum(0, &wq->w.time[TUser*12], NUMSIZE, 
			TK2MS(utime), NUMSIZE); 
		readnum(0, &wq->w.time[TSys*12], NUMSIZE, 
			TK2MS(stime), NUMSIZE); 
		readnum(0, &wq->w.time[TReal*12], NUMSIZE, 
1993/0501    
			TK2MS(MACHP(0)->ticks - up->time[TReal]), NUMSIZE); 
1991/1218    
		if(exitstr && exitstr[0]){ 
1993/0501    
			n = sprint(wq->w.msg, "%s %d:", up->text, up->pid); 
1991/1218    
			strncpy(wq->w.msg+n, exitstr, ERRLEN-n); 
1995/0329    
			wq->w.msg[ERRLEN-1] = 0; 
1992/1206    
		} 
		else 
1991/1006    
			wq->w.msg[0] = '\0'; 
 
1991/1005    
		lock(&p->exl); 
1993/0501    
		/* My parent still alive, processes are limited to 128 
		 * Zombies to prevent a badly written daemon lots of wait 
		 * records 
1992/0620    
		 */ 
1993/0501    
		if(p->pid == up->parentpid && p->state != Broken && p->nwait < 128) {	 
1991/1005    
			p->nchild--; 
1992/0205    
			p->time[TCUser] += utime; 
			p->time[TCSys] += stime; 
1991/1005    
	 
			wq->next = p->waitq; 
			p->waitq = wq; 
			p->nwait++; 
			unlock(&p->exl); 
1993/0501    
	 
1991/1005    
			wakeup(&p->waitr); 
		} 
		else { 
			unlock(&p->exl); 
1992/0620    
			free(wq); 
1991/1005    
		} 
1990/0227    
	} 
1990/03081    
 
1991/0926    
	if(!freemem) 
1993/0501    
		addbroken(up); 
1990/03081    
 
1993/0501    
	es = &up->seg[NSEG]; 
1995/0104    
	for(s = up->seg; s < es; s++) { 
		if(*s) { 
1992/1206    
			putseg(*s); 
1995/0104    
			*s = 0; 
		} 
	} 
1991/0926    
 
1993/0501    
	lock(&up->exl);		/* Prevent my children from leaving waits */ 
	up->pid = 0; 
1996/0121    
	wakeup(&up->waitr); 
1993/0501    
	unlock(&up->exl); 
1991/0926    
 
1993/0501    
	for(f = up->waitq; f; f = next) { 
1991/0926    
		next = f->next; 
1992/0620    
		free(f); 
1991/0926    
	} 
 
1991/1110    
	/* release debuggers */ 
1995/0104    
	qlock(&up->debug); 
1993/0501    
	if(up->pdbg) { 
		wakeup(&up->pdbg->sleep); 
		up->pdbg = 0; 
1991/1110    
	} 
1995/0104    
	qunlock(&up->debug); 
1991/1110    
 
1995/0104    
	/* Sched must not loop for this lock */ 
1991/1110    
	lock(&procalloc); 
1995/1230    
	lock(&palloc); 
1991/0705    
 
1993/0501    
	up->state = Moribund; 
1991/0705    
	sched(); 
	panic("pexit"); 
1990/0227    
} 
 
1991/0926    
int 
haswaitq(void *x) 
{ 
	Proc *p; 
 
	p = (Proc *)x; 
	return p->waitq != 0; 
} 
 
1990/0227    
ulong 
pwait(Waitmsg *w) 
{ 
	ulong cpid; 
1991/0926    
	Waitq *wq; 
1990/0227    
 
1993/0501    
	if(!canqlock(&up->qwaitr)) 
1993/0309    
		error(Einuse); 
 
	if(waserror()) { 
1993/0501    
		qunlock(&up->qwaitr); 
1993/0309    
		nexterror(); 
	} 
 
1993/0501    
	lock(&up->exl); 
	if(up->nchild == 0 && up->waitq == 0) { 
		unlock(&up->exl); 
1991/0926    
		error(Enochild); 
1990/0227    
	} 
1993/0501    
	unlock(&up->exl); 
1991/0926    
 
1993/0501    
	sleep(&up->waitr, haswaitq, up); 
1991/0926    
 
1993/0501    
	lock(&up->exl); 
	wq = up->waitq; 
	up->waitq = wq->next; 
	up->nwait--; 
	unlock(&up->exl); 
1993/0309    
 
1993/0501    
	qunlock(&up->qwaitr); 
1993/0309    
	poperror(); 
1991/0926    
 
1990/0227    
	if(w) 
1991/0926    
		memmove(w, &wq->w, sizeof(Waitmsg)); 
1992/0309    
	cpid = atoi(wq->w.pid); 
1992/0620    
	free(wq); 
1990/0227    
	return cpid; 
} 
 
Proc* 
proctab(int i) 
{ 
	return &procalloc.arena[i]; 
} 
 
1990/1220    
void 
1995/1030    
dumpaproc(Proc *p) 
{ 
	ulong bss; 
	char *s; 
 
	if(p == 0) 
		return; 
 
	bss = 0; 
	if(p->seg[BSEG]) 
		bss = p->seg[BSEG]->top; 
 
	s = p->psstate; 
	if(s == 0) 
		s = "kproc"; 
	print("%3d:%10s pc %8lux dbgpc %8lux  %8s (%s) ut %ld st %ld bss %lux\n", 
		p->pid, p->text, p->pc, dbgpc(p),  s, statename[p->state], 
		p->time[0], p->time[1], bss, p->priority); 
} 
 
void 
1991/0608    
procdump(void) 
1990/0227    
{ 
1990/0330    
	int i; 
1990/0227    
	Proc *p; 
 
1995/1009    
	if(up) 
		print("up %d\n", up->pid); 
	else 
		print("no current process\n"); 
1993/0501    
	for(i=0; i<conf.nproc; i++) { 
		p = &procalloc.arena[i]; 
		if(p->state == Dead) 
			continue; 
1992/0805    
 
1995/1030    
		dumpaproc(p); 
		delay(150); 
1994/0728    
	} 
1995/1030    
} 
 
void 
scheddump(void) 
{ 
	Proc *p; 
	Schedq *rq; 
 
1995/0110    
	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) 
1995/1009    
			print(" %d(%d, %d)", p->pid, m->ticks - p->readytime, 
				m->ticks - p->movetime); 
1994/0728    
		print("\n"); 
1995/1030    
		delay(150); 
1990/0227    
	} 
1995/0110    
	print("nrdy %d\n", nrdy); 
1990/0227    
} 
 
void 
kproc(char *name, void (*func)(void *), void *arg) 
{ 
	Proc *p; 
1990/0722    
	static Pgrp *kpgrp; 
1990/0227    
 
	p = newproc(); 
1991/0926    
	p->psstate = 0; 
1991/1112    
	p->procmode = 0644; 
1990/1212    
	p->kp = 1; 
1990/0227    
 
1993/0501    
	p->fpsave = up->fpsave; 
	p->scallnr = up->scallnr; 
	p->s = up->s; 
	p->nerrlab = 0; 
	p->slash = up->slash; 
	p->dot = up->dot; 
	incref(p->dot); 
1990/0227    
 
1993/0501    
	memmove(p->note, up->note, sizeof(p->note)); 
	p->nnote = up->nnote; 
	p->notified = 0; 
	p->lastnote = up->lastnote; 
	p->notify = up->notify; 
	p->ureg = 0; 
	p->dbgreg = 0; 
1994/0920    
 
1995/0110    
	p->basepri = PriKproc; 
	p->priority = p->basepri; 
1990/0227    
 
1993/0501    
	kprocchild(p, func, arg); 
1991/0705    
 
1993/0501    
	strcpy(p->user, eve); 
	if(kpgrp == 0) 
1990/0722    
		kpgrp = newpgrp(); 
	p->pgrp = kpgrp; 
	incref(kpgrp); 
1991/0705    
 
1992/0703    
	strcpy(p->text, name); 
1991/0705    
 
1990/0227    
	p->nchild = 0; 
	p->parent = 0; 
	memset(p->time, 0, sizeof(p->time)); 
	p->time[TReal] = MACHP(0)->ticks; 
1991/0926    
	ready(p); 
1991/0529    
	/* 
	 *  since the bss/data segments are now shareable, 
	 *  any mmu info about this process is now stale 
	 *  and has to be discarded. 
	 */ 
1990/0227    
	flushmmu(); 
1991/0705    
} 
 
1992/0609    
/* 
 *  called splhi() by notify().  See comment in notify for the 
 *  reasoning. 
 */ 
1991/0705    
void 
procctl(Proc *p) 
{ 
1991/1108    
	char *state; 
1995/0112    
	ulong s; 
1991/1108    
 
1991/0705    
	switch(p->procctl) { 
1995/0215    
	case Proc_exitbig: 
		spllo(); 
		pexit("Killed: Insufficient physical memory", 1); 
 
1991/0705    
	case Proc_exitme: 
1993/0501    
		spllo();		/* pexit has locks in it */ 
1991/0705    
		pexit("Killed", 1); 
1992/0620    
 
1991/1110    
	case Proc_traceme: 
1993/0501    
		if(p->nnote == 0) 
1991/1110    
			return; 
		/* No break */ 
1992/0620    
 
1991/0705    
	case Proc_stopme: 
		p->procctl = 0; 
1991/1108    
		state = p->psstate; 
		p->psstate = "Stopped"; 
1991/1110    
		/* free a waiting debugger */ 
1995/0112    
		s = spllo(); 
1991/1216    
		qlock(&p->debug); 
1991/1110    
		if(p->pdbg) { 
			wakeup(&p->pdbg->sleep); 
			p->pdbg = 0; 
		} 
1991/1216    
		qunlock(&p->debug); 
1995/0105    
		splhi(); 
1991/0705    
		p->state = Stopped; 
1995/0112    
		sched(); 
1991/1108    
		p->psstate = state; 
1995/0112    
		splx(s); 
1991/0705    
		return; 
	} 
1990/0227    
} 
1991/0710    
 
#include "errstr.h" 
 
void 
1992/0604    
error(char *err) 
1991/0710    
{ 
1995/0110    
	spllo(); 
1993/0501    
	strncpy(up->error, err, ERRLEN); 
1991/0710    
	nexterror(); 
} 
 
void 
1992/0114    
nexterror(void) 
1991/0710    
{ 
1993/0501    
	gotolabel(&up->errlab[--up->nerrlab]); 
1991/0710    
} 
 
void 
1992/0114    
exhausted(char *resource) 
1991/0710    
{ 
1992/0114    
	char buf[ERRLEN]; 
 
	sprint(buf, "no free %s", resource); 
	error(buf); 
1991/0926    
} 
1993/1123    
 
void 
killbig(void) 
{ 
	int i; 
	Segment *s; 
	ulong l, max; 
	Proc *p, *ep, *kp; 
 
	max = 0; 
	kp = 0; 
	ep = procalloc.arena+conf.nproc; 
	for(p = procalloc.arena; p < ep; p++) { 
		if(p->state == Dead || p->kp) 
			continue; 
		l = 0; 
1994/0325    
		for(i=1; i<NSEG; i++) { 
1993/1123    
			s = p->seg[i]; 
1995/0104    
			if(s != 0) 
1993/1123    
				l += s->top - s->base; 
		} 
		if(l > max) { 
			kp = p; 
			max = l; 
		} 
	} 
1995/0215    
	kp->procctl = Proc_exitbig; 
1995/0104    
	for(i = 0; i < NSEG; i++) { 
		s = kp->seg[i]; 
		if(s != 0 && canqlock(&s->lk)) { 
			mfreeseg(s, s->base, (s->top - s->base)/BY2PG); 
			qunlock(&s->lk); 
		} 
	} 
	print("%d: %s killed because no swap configured\n", kp->pid, kp->text); 
1993/1123    
} 
1994/1027    
 
/* 
 *  change ownership to 'new' of all processes owned by 'old'.  Used when 
 *  eve changes. 
 */ 
void 
renameuser(char *old, char *new) 
{ 
	Proc *p, *ep; 
 
	ep = procalloc.arena+conf.nproc; 
	for(p = procalloc.arena; p < ep; p++) 
		if(strcmp(old, p->user) == 0) 
			memmove(p->user, new, NAMELEN); 
1995/0104    
} 
 
/* 
 *  time accounting called by clock() splhi'd 
 */ 
void 
accounttime(void) 
{ 
	Proc *p; 
1995/0110    
	int n; 
	static int nrun; 
1995/0104    
 
	p = m->proc; 
	if(p) { 
		nrun++; 
		p->time[p->insyscall]++; 
	} 
 
	/* only one processor gets to compute system load averages */ 
	if(m->machno != 0) 
		return; 
 
	/* calculate decaying load average */ 
1995/0110    
	n = nrun; 
1995/0104    
	nrun = 0; 
 
1995/0110    
	n = (nrdy+n)*1000; 
	m->load = (m->load*19+n)/20; 
1994/1027    
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)