⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 proc.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
📖 第 1 页 / 共 2 页
字号:
		qlock(&p->debug);//	if(p->kp)//		print("sending %s to kproc %lud %s\n", n, p->pid, p->text);	if(flag != NUser && (p->notify == 0 || p->notified))		p->nnote = 0;	ret = 0;	if(p->nnote < NNOTE) {		strcpy(p->note[p->nnote].msg, n);		p->note[p->nnote++].flag = flag;		ret = 1;	}	p->notepending = 1;	if(dolock)		qunlock(&p->debug);	s = splhi();	lock(&p->rlock);	r = p->r;	if(r){		if(r->p != p || p->r != r || p->state != Wakeme)			panic("postnote: state %d %d %d", r->p != p, p->r != r, p->state);		r->p = 0;		p->r = 0;		ready(p);	}	unlock(&p->rlock);	splx(s);	if(p->state != Rendezvous)		return ret;	/* Try and pull out of a rendezvous */	lock(p->rgrp);	if(p->state == Rendezvous) {		p->rendval = ~0;		l = &REND(p->rgrp, p->rendtag);		for(d = *l; d; d = d->rendhash) {			if(d == p) {				*l = p->rendhash;				break;			}			l = &d->rendhash;		}		ready(p);	}	unlock(p->rgrp);	return ret;}/* * weird thing: keep at most NBROKEN around */#define	NBROKEN 4struct{	QLock;	int	n;	Proc	*p[NBROKEN];}broken;voidaddbroken(Proc *p){	qlock(&broken);	if(broken.n == NBROKEN) {		ready(broken.p[0]);		memmove(&broken.p[0], &broken.p[1], sizeof(Proc*)*(NBROKEN-1));		--broken.n;	}	broken.p[broken.n++] = p;	qunlock(&broken);	p->state = Broken;	p->psstate = 0;	sched();}voidunbreak(Proc *p){	int b;	qlock(&broken);	for(b=0; b < broken.n; b++)		if(broken.p[b] == p) {			broken.n--;			memmove(&broken.p[b], &broken.p[b+1],					sizeof(Proc*)*(NBROKEN-(b+1)));			ready(p);			break;		}	qunlock(&broken);}intfreebroken(void){	int i, n;	qlock(&broken);	n = broken.n;	for(i=0; i<n; i++) {		ready(broken.p[i]);		broken.p[i] = 0;	}	broken.n = 0;	qunlock(&broken);	return n;}voidpexit(char *exitstr, int freemem){	int n;	Proc *p;	Segment **s, **es;	long utime, stime;	Waitq *wq, *f, *next;	Fgrp *fgrp;	Egrp *egrp;	Rgrp *rgrp;	Pgrp *pgrp;	Chan *dot;	up->alarm = 0;	/* nil out all the resources under lock (free later) */	qlock(&up->debug);	fgrp = up->fgrp;	up->fgrp = nil;	egrp = up->egrp;	up->egrp = nil;	rgrp = up->rgrp;	up->rgrp = nil;	pgrp = up->pgrp;	up->pgrp = nil;	dot = up->dot;	up->dot = nil;	qunlock(&up->debug);	if(fgrp)		closefgrp(fgrp);	if(egrp)		closeegrp(egrp);	if(rgrp)		closergrp(rgrp);	if(dot)		cclose(dot);	if(pgrp)		closepgrp(pgrp);	/*	 * if not a kernel process and have a parent,	 * do some housekeeping.	 */	if(up->kp == 0) {		p = up->parent;		if(p == 0) {			if(exitstr == 0)				exitstr = "unknown";			panic("boot process died: %s", exitstr);		}		while(waserror())			;		wq = smalloc(sizeof(Waitq));		poperror();		readnum(0, wq->w.pid, NUMSIZE, up->pid, NUMSIZE);		utime = up->time[TUser] + up->time[TCUser];		stime = up->time[TSys] + up->time[TCSys];		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,			TK2MS(MACHP(0)->ticks - up->time[TReal]), NUMSIZE);		if(exitstr && exitstr[0]){			n = sprint(wq->w.msg, "%s %lud:", up->text, up->pid);			strncpy(wq->w.msg+n, exitstr, ERRLEN-n);			wq->w.msg[ERRLEN-1] = 0;		}		else			wq->w.msg[0] = '\0';		lock(&p->exl);		/*		 *  If my parent is no longer alive, or if there would be more		 *  than 128 zombie child processes for my parent, then don't		 *  leave a wait record behind.  This helps prevent badly		 *  written daemon processes from accumulating lots of wait		 *  records.		 */		if(p->pid == up->parentpid && p->state != Broken && p->nwait < 128) {			p->nchild--;			p->time[TCUser] += utime;			p->time[TCSys] += stime;			wq->next = p->waitq;			p->waitq = wq;			p->nwait++;			wakeup(&p->waitr);			unlock(&p->exl);		}		else {			unlock(&p->exl);			free(wq);		}	}	if(!freemem)		addbroken(up);	qlock(&up->seglock);	es = &up->seg[NSEG];	for(s = up->seg; s < es; s++) {		if(*s) {			putseg(*s);			*s = 0;		}	}	qunlock(&up->seglock);	lock(&up->exl);		/* Prevent my children from leaving waits */	up->pid = 0;	wakeup(&up->waitr);	unlock(&up->exl);	for(f = up->waitq; f; f = next) {		next = f->next;		free(f);	}	/* release debuggers */	qlock(&up->debug);	if(up->pdbg) {		wakeup(&up->pdbg->sleep);		up->pdbg = 0;	}	qunlock(&up->debug);	/* Sched must not loop for these locks */	lock(&procalloc);	lock(&palloc);	up->state = Moribund;	sched();	panic("pexit");}inthaswaitq(void *x){	Proc *p;	p = (Proc *)x;	return p->waitq != 0;}ulongpwait(Waitmsg *w){	ulong cpid;	Waitq *wq;	if(!canqlock(&up->qwaitr))		error(Einuse);	if(waserror()) {		qunlock(&up->qwaitr);		nexterror();	}	lock(&up->exl);	if(up->nchild == 0 && up->waitq == 0) {		unlock(&up->exl);		error(Enochild);	}	unlock(&up->exl);	sleep(&up->waitr, haswaitq, up);	lock(&up->exl);	wq = up->waitq;	up->waitq = wq->next;	up->nwait--;	unlock(&up->exl);	qunlock(&up->qwaitr);	poperror();	if(w)		memmove(w, &wq->w, sizeof(Waitmsg));	cpid = atoi(wq->w.pid);	free(wq);	return cpid;}Proc*proctab(int i){	return &procalloc.arena[i];}voiddumpaproc(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("%3lud:%10s pc %8lux dbgpc %8lux  %8s (%s) ut %ld st %ld bss %lux qpc %lux\n",		p->pid, p->text, p->pc, dbgpc(p),  s, statename[p->state],		p->time[0], p->time[1], bss, p->qpc);}voidprocdump(void){	int i;	Proc *p;	if(up)		print("up %lud\n", up->pid);	else		print("no current process\n");	for(i=0; i<conf.nproc; i++) {		p = &procalloc.arena[i];		if(p->state == Dead)			continue;		dumpaproc(p);		delay(150);	}}/* *  wait till all processes have flushed their mmu *  state about segement s */voidprocflushseg(Segment *s){	int i, ns, nm, nwait;	Proc *p;	/*	 *  tell all processes with this	 *  segment to flush their mmu's	 */	nwait = 0;	for(i=0; i<conf.nproc; i++) {		p = &procalloc.arena[i];		if(p->state == Dead)			continue;		for(ns = 0; ns < NSEG; ns++)			if(p->seg[ns] == s){				p->newtlb = 1;				for(nm = 0; nm < conf.nmach; nm++){					if(MACHP(nm)->proc == p){						MACHP(nm)->flushmmu = 1;						nwait++;					}				}				break;			}	}	if(nwait == 0)		return;	/*	 *  wait for all processors to take a clock interrupt	 *  and flush their mmu's	 */	for(nm = 0; nm < conf.nmach; nm++)		if(MACHP(nm) != m)			while(MACHP(nm)->flushmmu)				sched();}voidscheddump(void){	Proc *p;	Schedq *rq;	for(rq = &runq[Nrq-1]; rq >= runq; rq--){		if(rq->head == 0)			continue;		print("rq%ld:", rq-runq);		for(p = rq->head; p; p = p->rnext)			print(" %lud(%lud, %lud)", p->pid, m->ticks - p->readytime,				MACHP(0)->ticks - p->movetime);		print("\n");		delay(150);	}	print("nrdy %d\n", nrdy);}voidkproc(char *name, void (*func)(void *), void *arg){	Proc *p;	static Pgrp *kpgrp;	p = newproc();	p->psstate = 0;	p->procmode = 0644;	p->kp = 1;	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);	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;	p->basepri = PriKproc;	p->priority = p->basepri;	kprocchild(p, func, arg);	strcpy(p->user, eve);	if(kpgrp == 0)		kpgrp = newpgrp();	p->pgrp = kpgrp;	incref(kpgrp);	strcpy(p->text, name);	p->nchild = 0;	p->parent = 0;	memset(p->time, 0, sizeof(p->time));	p->time[TReal] = MACHP(0)->ticks;	ready(p);	/*	 *  since the bss/data segments are now shareable,	 *  any mmu info about this process is now stale	 *  and has to be discarded.	 */	flushmmu();}/* *  called splhi() by notify().  See comment in notify for the *  reasoning. */voidprocctl(Proc *p){	char *state;	ulong s;	switch(p->procctl) {	case Proc_exitbig:		spllo();		pexit("Killed: Insufficient physical memory", 1);	case Proc_exitme:		spllo();		/* pexit has locks in it */		pexit("Killed", 1);	case Proc_traceme:		if(p->nnote == 0)			return;		/* No break */	case Proc_stopme:		p->procctl = 0;		state = p->psstate;		p->psstate = "Stopped";		/* free a waiting debugger */		s = spllo();		qlock(&p->debug);		if(p->pdbg) {			wakeup(&p->pdbg->sleep);			p->pdbg = 0;		}		qunlock(&p->debug);		splhi();		p->state = Stopped;		sched();		p->psstate = state;		splx(s);		return;	}}#include "errstr.h"voiderror(char *err){	spllo();	strncpy(up->error, err, ERRLEN);	nexterror();}voidnexterror(void){	gotolabel(&up->errlab[--up->nerrlab]);}voidexhausted(char *resource){	char buf[ERRLEN];	sprint(buf, "no free %s", resource);	iprint("%s\n", buf);	error(buf);}voidkillbig(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;		for(i=1; i<NSEG; i++) {			s = p->seg[i];			if(s != 0)				l += s->top - s->base;		}		if(l > max) {			kp = p;			max = l;		}	}	kp->procctl = Proc_exitbig;	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("%lud: %s killed because no swap configured\n", kp->pid, kp->text);}/* *  change ownership to 'new' of all processes owned by 'old'.  Used when *  eve changes. */voidrenameuser(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);}/* *  time accounting called by clock() splhi'd */voidaccounttime(void){	Proc *p;	int n;	static int nrun;	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 */	n = nrun;	nrun = 0;	n = (nrdy+n)*1000;	m->load = (m->load*19+n)/20;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -