Пример #1
0
static int
canflush(Proc *p, Segment *s)
{
	int i, x;

	lock(s);
	if(s->ref == 1) {		/* Easy if we are the only user */
		s->ref++;
		unlock(s);
		return canpage(p);
	}
	s->ref++;
	unlock(s);

	/* Now we must do hardwork to ensure all processes which have tlb
	 * entries for this segment will be flushed if we succeed in paging it out
	 */
	for(x = 0; (p = psincref(x)) != nil; x++){
		if(p->state != Dead) {
			for(i = 0; i < NSEG; i++){
				if(p->seg[i] == s && !canpage(p)){
					psdecref(p);
					return 0;
				}
			}
		}
		psdecref(p);
	}
	return 1;
}
Пример #2
0
void
pgrpnote(ulong noteid, char *a, long n, int flag)
{
	int i;
	Proc *p;
	char buf[ERRMAX];

	if(n >= ERRMAX-1)
		error(Etoobig);

	memmove(buf, a, n);
	buf[n] = 0;
	for(i = 0; (p = psincref(i)) != nil; i++){
		if(p == up || p->state == Dead || p->noteid != noteid || p->kp){
			psdecref(p);
			continue;
		}
		qlock(&p->debug);
		if(p->pid == 0 || p->noteid != noteid){
			qunlock(&p->debug);
			psdecref(p);
			continue;
		}
		if(!waserror()) {
			postnote(p, 0, buf, flag);
			poperror();
		}
		qunlock(&p->debug);
		psdecref(p);
	}
}
Пример #3
0
Файл: proc.c Проект: npe9/harvey
/*
 *  wait till all processes have flushed their mmu
 *  state about segement s
 */
void
procflushseg(Segment *s)
{
	Mach *m = machp();
	int i, ns, nm, nwait;
	Proc *p;
	Mach *mp;

	/*
	 *  tell all processes with this
	 *  segment to flush their mmu's
	 */
	nwait = 0;
	for(i=0; (p = psincref(i)) != nil; i++) {
		if(p->state == Dead){
			psdecref(p);
			continue;
		}
		for(ns = 0; ns < NSEG; ns++){
			if(p->seg[ns] == s){
				p->newtlb = 1;
				for(nm = 0; nm < MACHMAX; nm++)
					if((mp = sys->machptr[nm]) != nil && mp->online)
						if(mp->proc == p){
							mp->mmuflush = 1;
							nwait++;
						}
				break;
			}
		}
		psdecref(p);
	}

	if(nwait == 0)
		return;

	/*
	 *  wait for all processors to take a clock interrupt
	 *  and flush their mmu's.
	 *  NIX BUG: this won't work if another core is in AC mode.
	 *  In that case we must IPI it, but only if that core is
	 *  using this segment.
	 */
	for(i = 0; i < MACHMAX; i++)
		if((mp = sys->machptr[i]) != nil && mp->online)
			if(mp != m)
				while(mp->mmuflush)
					sched();
}
Пример #4
0
void
killbig(char *why)
{
	int i, x;
	Segment *s;
	uintptr_t l, max;
	Proc *p, *kp;

	max = 0;
	kp = nil;
	for(x = 0; (p = psincref(x)) != nil; x++) {
		if(p->state == Dead || p->kp){
			psdecref(p);
			continue;
		}
		l = 0;
		for(i=1; i<NSEG; i++) {
			s = p->seg[i];
			if(s != 0)
				l += s->top - s->base;
		}
		if(l > max && ((p->procmode&0222) || strcmp(eve, p->user)!=0)) {
			if(kp != nil)
				psdecref(kp);
			kp = p;
			max = l;
		}
		else
			psdecref(p);
	}
	if(kp == nil)
		return;

	print("%d: %s killed: %s\n", kp->pid, kp->text, why);
	for(x = 0; (p = psincref(x)) != nil; x++) {
		if(p->state == Dead || p->kp){
			psdecref(p);
			continue;
		}
		/* TODO(aki): figure out what this was for. the oom killer is broken anyway though?
		if(p != kp && p->seg[BSEG] && p->seg[BSEG] == kp->seg[BSEG])
			p->procctl = Proc_exitbig;
		*/
		psdecref(p);
	}

	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)/BIGPGSZ);
			qunlock(&s->lk);
		}
	}
	psdecref(kp);
}
Пример #5
0
void
procdump(void)
{
	int i;
	Proc *p;

	if(up)
		print("up %d\n", up->pid);
	else
		print("no current process\n");
	for(i=0; (p = psincref(i)) != nil; i++) {
		if(p->state != Dead)
			dumpaproc(p);
		psdecref(p);
	}
}
Пример #6
0
static void
pageouttext(int pgszi, int color)
{

	Proc *p;
	Pgsza *pa;
	int i, n, np, x;
	Segment *s;
	int prepaged;

	USED(color);
	pa = &pga.pgsza[pgszi];
	n = x = 0;
	prepaged = 0;

	/*
	 * Try first to steal text pages from non-prepaged processes,
	 * then from anyone.
	 */
Again:
	do{
		if((p = psincref(x)) == nil)
			break;
		np = 0;
		if(p->prepagemem == 0 || prepaged != 0)
		if(p->state != Dead && p->noswap == 0 && canqlock(&p->seglock)){
			for(i = 0; i < NSEG; i++){
				if((s = p->seg[i]) == nil)
					continue;
				if((s->type&SG_TYPE) == SG_TEXT)
					np = pageout(p, s);
			}
			qunlock(&p->seglock);
		}
		/*
		 * else process dead or locked or changing its segments
		 */
		psdecref(p);
		n += np;
		if(np > 0)
			DBG("pager: %d from proc #%d %#p\n", np, x, p);
		x++;
	}while(pa->freecount < Minpages);

	if(pa->freecount < Minpages && prepaged++ == 0)
		goto Again;
}
Пример #7
0
Файл: proc.c Проект: npe9/harvey
/*
 * wire this proc to a machine
 */
void
procwired(Proc *p, int bm)
{
	Mach *m = machp();
	Proc *pp;
	int i;
	char nwired[MACHMAX];
	Mach *wm;

	if(bm < 0){
		/* pick a machine to wire to */
		memset(nwired, 0, sizeof(nwired));
		p->wired = 0;
		for(i=0; (pp = psincref(i)) != nil; i++){
			wm = pp->wired;
			if(wm && pp->pid)
				nwired[wm->machno]++;
			psdecref(pp);
		}
		bm = 0;
		for(i=0; i<sys->nmach; i++)
			if(nwired[i] < nwired[bm])
				bm = i;
	} else {
		/* use the virtual machine requested */
		bm = bm % sys->nmach;
	}

	p->wired = sys->machptr[bm];
	p->mp = p->wired;

	/*
	 * adjust our color to the new domain.
	 */
	if(m->externup == nil || p != m->externup)
		return;
	m->externup->color = corecolor(m->externup->mp->machno);
	qlock(&m->externup->seglock);
	for(i = 0; i < NSEG; i++)
		if(m->externup->seg[i])
			m->externup->seg[i]->color = m->externup->color;
	qunlock(&m->externup->seglock);
}
Пример #8
0
static char *
testschedulability(Proc *theproc)
{
	Proc *p;
	int32_t H, G, Cb, ticks;
	int steps, i;

	/* initialize */
	DPRINT("schedulability test %d\n", theproc->pid);
	qschedulability = nil;
	for(i=0; (p = psincref(i)) != nil; i++) {
		if(p->state == Dead){
			psdecref(p);
			continue;
		}
		if ((p->edf == nil || (p->edf->flags & Admitted) == 0) && p != theproc){
			psdecref(p);
			continue;
		}
		p->edf->testtype = Rl;
		p->edf->testtime = 0;
		DPRINT("\tInit: edfenqueue %d\n", p->pid);
		testenq(p);
		psdecref(p);
	}
	H=0;
	G=0;
	for(steps = 0; steps < Maxsteps; steps++){
		p = qschedulability;
		qschedulability = p->edf->testnext;
		ticks = p->edf->testtime;
		switch (p->edf->testtype){
		case Dl:
			H += p->edf->C;
			Cb = 0;
			DPRINT("\tStep %3d, Ticks %lu, pid %d, deadline, H += %lu → %lu, Cb = %lu\n",
				steps, ticks, p->pid, p->edf->C, H, Cb);
			if (H+Cb>ticks){
				DPRINT("not schedulable\n");
				return "not schedulable";
			}
			p->edf->testtime += p->edf->T - p->edf->D;
			p->edf->testtype = Rl;
			testenq(p);
			break;
		case Rl:
			DPRINT("\tStep %3d, Ticks %lu, pid %d, release, G  %lu, C%lu\n",
				steps, ticks, p->pid, p->edf->C, G);
			if(ticks && G <= ticks){
				DPRINT("schedulable\n");
				return nil;
			}
			G += p->edf->C;
			p->edf->testtime += p->edf->D;
			p->edf->testtype = Dl;
			testenq(p);
			break;
		default:
			assert(0);
		}
	}
	DPRINT("probably not schedulable\n");
	return "probably not schedulable";
}
Пример #9
0
char *
edfadmit(Proc *p)
{
	Proc *up = externup();
	char *err;
	Edf *e;
	int i;
	Proc *r;
	int32_t tns;

	e = p->edf;
	if (e->flags & Admitted)
		return "task state";	/* should never happen */

	/* simple sanity checks */
	if (e->T == 0)
		return "T not set";
	if (e->C == 0)
		return "C not set";
	if (e->D > e->T)
		return "D > T";
	if (e->D == 0)	/* if D is not set, set it to T */
		e->D = e->T;
	if (e->C > e->D)
		return "C > D";

	qlock(&edfschedlock);
	if (err = testschedulability(p)){
		qunlock(&edfschedlock);
		return err;
	}
	e->flags |= Admitted;

	edflock(p);

	if(p->trace)
		proctrace(p, SAdmit, 0);

	/* Look for another proc with the same period to synchronize to */
	for(i=0; (r = psincref(i)) != nil; i++) {
		if(r->state == Dead || r == p){
			psdecref(r);
			continue;
		}
		if (r->edf == nil || (r->edf->flags & Admitted) == 0){
			psdecref(r);
			continue;
		}
		if (r->edf->T == e->T)
			break;
	}
	if (r == nil){
		/* Can't synchronize to another proc, release now */
		e->t = now;
		e->d = 0;
		release(p);
		if (p == up){
			DPRINT("%lu edfadmit self %d[%s], release now: r=%lu d=%lu t=%lu\n",
				now, p->pid, statename[p->state], e->r, e->d, e->t);
			/* We're already running */
			edfrun(p, 1);
		}else{
			/* We're releasing another proc */
			DPRINT("%lu edfadmit other %d[%s], release now: r=%lu d=%lu t=%lu\n",
				now, p->pid, statename[p->state], e->r, e->d, e->t);
			p->Timer.ta = p;
			edfunlock();
			qunlock(&edfschedlock);
			releaseintr(nil, &p->Timer);
			return nil;
		}
	}else{
		/* Release in synch to something else */
		e->t = r->edf->t;
		psdecref(r);
		if (p == up){
			DPRINT("%lu edfadmit self %d[%s], release at %lu\n",
				now, p->pid, statename[p->state], e->t);
		}else{
			DPRINT("%lu edfadmit other %d[%s], release at %lu\n",
				now, p->pid, statename[p->state], e->t);
			if(e->Timer.tt == nil){
				e->Timer.tf = releaseintr;
				e->Timer.ta = p;
				tns = e->t - now;
				if(tns < 20)
					tns = 20;
				e->Timer.tns = 1000LL * tns;
				e->Timer.tmode = Trelative;
				timeradd(&e->Timer);
			}
		}
	}
	edfunlock();
	qunlock(&edfschedlock);
	return nil;
}
Пример #10
0
static int
procgen(Chan *c, char *name, Dirtab *tab, int, int s, Dir *dp)
{
	Qid qid;
	Proc *p;
	char *ename;
	Segment *q;
	int pid;
	ulong path, perm, len;

	if(s == DEVDOTDOT){
		mkqid(&qid, Qdir, 0, QTDIR);
		devdir(c, qid, "#p", 0, eve, 0555, dp);
		return 1;
	}

	if(c->qid.path == Qdir){
		if(s == 0){
			strcpy(up->genbuf, "trace");
			mkqid(&qid, Qtrace, -1, QTFILE);
			devdir(c, qid, up->genbuf, 0, eve, 0444, dp);
			return 1;
		}

		if(name != nil){
			/* ignore s and use name to find pid */
			pid = strtol(name, &ename, 10);
			if(pid<=0 || ename[0]!='\0')
				return -1;
			s = psindex(pid);
			if(s < 0)
				return -1;
		}
		else if(--s >= procalloc.nproc)
			return -1;

		if((p = psincref(s)) == nil || (pid = p->pid) == 0)
			return 0;
		sprint(up->genbuf, "%d", pid);
		/*
		 * String comparison is done in devwalk so
		 * name must match its formatted pid.
		 */
		if(name != nil && strcmp(name, up->genbuf) != 0)
			return -1;
		mkqid(&qid, (s+1)<<QSHIFT, pid, QTDIR);
		devdir(c, qid, up->genbuf, 0, p->user, DMDIR|0555, dp);
		psdecref(p);
		return 1;
	}
	if(c->qid.path == Qtrace){
		strcpy(up->genbuf, "trace");
		mkqid(&qid, Qtrace, -1, QTFILE);
		devdir(c, qid, up->genbuf, 0, eve, 0444, dp);
		return 1;
	}
	if(s >= nelem(procdir))
		return -1;
	if(tab)
		panic("procgen");

	tab = &procdir[s];
	path = c->qid.path&~(((1<<QSHIFT)-1));	/* slot component */

	if((p = psincref(SLOT(c->qid))) == nil)
		return -1;
	perm = tab->perm;
	if(perm == 0)
		perm = p->procmode;
	else	/* just copy read bits */
		perm |= p->procmode & 0444;

	len = tab->length;
	switch(QID(c->qid)) {
	case Qwait:
		len = p->nwait;	/* incorrect size, but >0 means there's something to read */
		break;
	case Qprofile:
		q = p->seg[TSEG];
		if(q && q->profile) {
			len = (q->top-q->base)>>LRESPROF;
			len *= sizeof(*q->profile);
		}
		break;
	}
Пример #11
0
static int
procgen(Chan *c, char *name, Dirtab *tab, int j, int s, Dir *dp)
{
	Proc *up = externup();
	Qid qid;
	Proc *p;
	char *ename;
	int pid, sno;
	uint32_t path, perm, len;

	if(s == DEVDOTDOT){
		mkqid(&qid, Qdir, 0, QTDIR);
		devdir(c, qid, "#p", 0, eve, 0555, dp);
		return 1;
	}

	if(c->qid.path == Qdir){
		if(s == 0){
			strcpy(up->genbuf, "trace");
			mkqid(&qid, Qtrace, -1, QTFILE);
			devdir(c, qid, up->genbuf, 0, eve, 0444, dp);
			return 1;
		}
		if(s == 1){
			strcpy(up->genbuf, "tracepids");
			mkqid(&qid, Qtracepids, -1, QTFILE);
			devdir(c, qid, up->genbuf, 0, eve, 0444, dp);
			return 1;
		}
		s -= 2;
		if(name != nil){
			/* ignore s and use name to find pid */
			pid = strtol(name, &ename, 10);
			if(pid<=0 || ename[0]!='\0')
				return -1;
			s = psindex(pid);
			if(s < 0)
				return -1;
		}
		else if(s >= conf.nproc)
			return -1;

		if((p = psincref(s)) == nil || (pid = p->pid) == 0)
			return 0;
		snprint(up->genbuf, sizeof up->genbuf, "%u", pid);
		/*
		 * String comparison is done in devwalk so
		 * name must match its formatted pid.
		 */
		if(name != nil && strcmp(name, up->genbuf) != 0)
			return -1;
		mkqid(&qid, (s+1)<<QSHIFT, pid, QTDIR);
		devdir(c, qid, up->genbuf, 0, p->user, DMDIR|0555, dp);
		psdecref(p);
		return 1;
	}
	if(c->qid.path == Qtrace){
		strcpy(up->genbuf, "trace");
		mkqid(&qid, Qtrace, -1, QTFILE);
		devdir(c, qid, up->genbuf, 0, eve, 0444, dp);
		return 1;
	}
	if(c->qid.path == Qtracepids){
		strcpy(up->genbuf, "tracepids");
		mkqid(&qid, Qtrace, -1, QTFILE);
		devdir(c, qid, up->genbuf, 0, eve, 0444, dp);
		return 1;
	}
	if(s >= nelem(procdir))
		return -1;
	if(tab)
		panic("procgen");

	tab = &procdir[s];
	path = c->qid.path&~(((1<<QSHIFT)-1));	/* slot component */

	if((p = psincref(SLOT(c->qid))) == nil)
		return -1;
	perm = tab->perm;
	if(perm == 0)
		perm = p->procmode;
	else	/* just copy read bits */
		perm |= p->procmode & 0444;

	len = tab->length;
	switch(QID(c->qid)) {
	case Qwait:
		len = p->nwait;	/* incorrect size, but >0 means there's something to read */
		break;
	case Qprofile: /* TODO(aki): test this */
		len = 0;
		for(sno = 0; sno < NSEG; sno++){
			if(p->seg[sno] != nil && (p->seg[sno]->type & SG_EXEC) != 0){
				Segment *s;
				s = p->seg[sno];
				if(s->profile)
					len += ((s->top-s->base)>>LRESPROF) * sizeof s->profile[0];
			}
		}
		break;
	}