예제 #1
0
파일: edf.c 프로젝트: 8l/inferno
void
edfyield(void)
{
	/* sleep until next release */
	Edf *e;
	void (*pt)(Proc*, int, vlong);

	if((e = edflock(up)) == nil)
		return;
	if(pt = proctrace)
		pt(up, SYield, now);
	while(e->t < now)
		e->t += e->T;
	e->r = e->t;
	e->flags |= Yield;
	e->d = now;
	if (up->tt == nil){
		up->tns = e->t;
		up->tf = releaseintr;
		up->tmode = Tabsolute;
		up->ta = up;
		up->trend = &up->sleep;
		timeradd(up);
	}else if(up->tf != releaseintr)
		print("edfyield: surprise! 0x%lux\n", up->tf);
	edfunlock();
	sleep(&up->sleep, yfn, nil);
}
예제 #2
0
파일: edf.c 프로젝트: Requaos/harvey
void
edfrecord(Proc *p)
{
	int32_t used;
	Edf *e;

	if((e = edflock(p)) == nil)
		return;
	used = now - e->s;
	if(e->d - now <= 0)
		e->edfused += used;
	else
		e->extraused += used;
	if(e->S > 0){
		if(e->S <= used){
			if(p->trace)
				proctrace(p, SSlice, 0);
			DPRINT("%lu edfrecord slice used up\n", now);
			e->d = now;
			e->S = 0;
		}else
			e->S -= used;
	}
	e->s = now;
	edfunlock();
}
예제 #3
0
파일: edf.c 프로젝트: 8l/inferno
void
edfrecord(Proc *p)
{
	vlong used;
	Edf *e;
	void (*pt)(Proc*, int, vlong);

	if((e = edflock(p)) == nil)
		return;
	used = now - e->s;
	if (e->d <= now)
		e->edfused += used;
	else
		e->extraused += used;
	if (e->S > 0){
		if (e->S <= used){
			if(pt = proctrace)
				pt(p, SSlice, now);
			DPRINT("%t edfrecord slice used up\n", now);
			e->d = now;
			e->S = 0;
		}else
			e->S -= used;
	}
	e->s = now;
	edfunlock();
}
예제 #4
0
파일: edf.c 프로젝트: 0intro/enhanced-plan9
static void
releaseintr(Ureg*, Timer *t)
{
	Proc *p;
	extern int panicking;
	Schedq *rq;

	if(panicking || active.exiting)
		return;

	p = t->ta;
	if((edflock(p)) == nil)
		return;
	DPRINT("%lud releaseintr %d[%s]\n", now, p->pid, statename[p->state]);
	switch(p->state){
	default:
		edfunlock();
		return;
	case Ready:
		/* remove proc from current runq */
		rq = &runq[p->priority];
		if(dequeueproc(rq, p) != p){
			DPRINT("releaseintr: can't find proc or lock race\n");
			release(p);	/* It'll start best effort */
			edfunlock();
			return;
		}
		p->state = Waitrelease;
		/* fall through */
	case Waitrelease:
		release(p);
		edfunlock();
		if(p->state == Wakeme){
			iprint("releaseintr: wakeme\n");
		}
		ready(p);
		if(up){
			up->delaysched++;
			delayedscheds++;
		}
		return;
	case Running:
		release(p);
		edfrun(p, 1);
		break;
	case Wakeme:
		release(p);
		edfunlock();
		if(p->trend)
			wakeup(p->trend);
		p->trend = nil;
		if(up){
			up->delaysched++;
			delayedscheds++;
		}
		return;
	}
	edfunlock();
}
예제 #5
0
파일: proc.c 프로젝트: npe9/harvey
/*
 * SMP performs better than AMP with few cores.
 * So, leave this here by now. We should probably
 * write a unified version of runproc good enough for
 * both SMP and AMP.
 */
static Proc*
smprunproc(void)
{
	Mach *m = machp();
	Schedq *rq;
	Proc *p;
	uint32_t start, now;
	int i;

	start = perfticks();
	run.preempts++;

loop:
	/*
	 *  find a process that last ran on this processor (affinity),
	 *  or one that hasn't moved in a while (load balancing).  Every
	 *  time around the loop affinity goes down.
	 */
	spllo();
	for(i = 0;; i++){
		/*
		 *  find the highest priority target process that this
		 *  processor can run given affinity constraints.
		 *
		 */
		for(rq = &run.runq[Nrq-1]; rq >= run.runq; rq--){
			for(p = rq->head; p; p = p->rnext){
				if(p->mp == nil || p->mp == sys->machptr[m->machno]
				|| (!p->wired && i > 0))
					goto found;
			}
		}

		/* waste time or halt the CPU */
		idlehands();
		/* remember how much time we're here */
		now = perfticks();
		m->perf.inidle += now-start;
		start = now;
	}

found:
	splhi();
	p = dequeueproc(&run, rq, p);
	if(p == nil)
		goto loop;

	p->state = Scheding;
	p->mp = sys->machptr[m->machno];

	if(edflock(p)){
		edfrun(p, rq == &run.runq[PriEdf]);	/* start deadline timer and do admin */
		edfunlock();
	}
	if(p->trace)
		proctrace(p, SRun, 0);
	return p;
}
예제 #6
0
파일: edf.c 프로젝트: Requaos/harvey
void
edfstop(Proc *p)
{
	Edf *e;

	if(e = edflock(p)){
		DPRINT("%lu edfstop %d[%s]\n", now, p->pid, statename[p->state]);
		if(p->trace)
			proctrace(p, SExpel, 0);
		e->flags &= ~Admitted;
		if(e->Timer.tt)
			timerdel(&e->Timer);
		edfunlock();
	}
}
예제 #7
0
파일: edf.c 프로젝트: 8l/inferno
void
edfstop(Proc *p)
{
	Edf *e;
	void (*pt)(Proc*, int, vlong);

	if (e = edflock(p)){
		DPRINT("%t edfstop %lud[%s]\n", now, p->pid, statename[p->state]);
		if(pt = proctrace)
			pt(p, SExpel, now);
		e->flags &= ~Admitted;
		if (e->tt)
			timerdel(e);
		edfunlock();
	}
}
예제 #8
0
파일: proc.c 프로젝트: npe9/harvey
Proc*
runproc(void)
{
	Mach *m = machp();
	Schedq *rq;
	Proc *p;
	uint32_t start, now;

	if(nosmp)
		return singlerunproc();

	//NIX modeset cannot work without halt every cpu at boot
	//if(sys->nmach <= AMPmincores)
	else
		return smprunproc();

	start = perfticks();
	run.preempts++;
	rq = nil;
	if(m->machno != 0){
		do{
			spllo();
			while(m->proc == nil)
				idlehands();
			now = perfticks();
			m->perf.inidle += now-start;
			start = now;
			splhi();
			p = m->proc;
		}while(p == nil);
		p->state = Scheding;
		p->mp = sys->machptr[m->machno];
	
		if(edflock(p)){
			edfrun(p, rq == &run.runq[PriEdf]);	/* start deadline timer and do admin */
			edfunlock();
		}
		if(p->trace)
			proctrace(p, SRun, 0);
		return p;
	}

	mach0sched();
	return nil;	/* not reached */
}
예제 #9
0
파일: edf.c 프로젝트: Requaos/harvey
void
edfyield(void)
{
	Proc *up = externup();
	/* sleep until next release */
	Edf *e;
	int32_t n;

	if((e = edflock(up)) == nil)
		return;
	if(up->trace)
		proctrace(up, SYield, 0);
	if((n = now - e->t) > 0){
		if(n < e->T)
			e->t += e->T;
		else
			e->t = now + e->T - (n % e->T);
	}
	e->r = e->t;
	e->flags |= Yield;
	e->d = now;
	if (up->Timer.tt == nil){
		n = e->t - now;
		if(n < 20)
			n = 20;
		up->Timer.tns = 1000LL * n;
		up->Timer.tf = releaseintr;
		up->Timer.tmode = Trelative;
		up->Timer.ta = up;
		up->trend = &up->sleep;
		timeradd(&up->Timer);
	}else if(up->Timer.tf != releaseintr)
		print("edfyield: surprise! %#p\n", up->Timer.tf);
	edfunlock();
	sleep(&up->sleep, yfn, nil);
}
예제 #10
0
파일: edf.c 프로젝트: 0intro/enhanced-plan9
void
edfyield(void)
{
	/* sleep until next release */
	Edf *e;
	void (*pt)(Proc*, int, vlong, vlong);
	long n;

	if((e = edflock(up)) == nil)
		return;
	if(up->trace && (pt = proctrace))
		pt(up, SYield, 0, 0);
	if((n = now - e->t) > 0){
		if(n < e->T)
			e->t += e->T;
		else
			e->t = now + e->T - (n % e->T);
	}
	e->r = e->t;
	e->flags |= Yield;
	e->d = now;
	if (up->tt == nil){
		n = e->t - now;
		if(n < 20)
			n = 20;
		up->tns = 1000LL * n;
		up->tf = releaseintr;
		up->tmode = Trelative;
		up->ta = up;
		up->trend = &up->sleep;
		timeradd(up);
	}else if(up->tf != releaseintr)
		print("edfyield: surprise! %#p\n", up->tf);
	edfunlock();
	sleep(&up->sleep, yfn, nil);
}
예제 #11
0
파일: proc.c 프로젝트: grobe0ba/plan9front
/*
 *  pick a process to run
 */
Proc*
runproc(void)
{
	Schedq *rq;
	Proc *p;
	ulong start, now;
	int i;
	void (*pt)(Proc*, int, vlong);

	start = perfticks();

	/* cooperative scheduling until the clock ticks */
	if((p = m->readied) != nil && p->mach == nil && p->state == Ready
	&& (p->wired == nil || p->wired == MACHP(m->machno))
	&& runq[Nrq-1].head == nil && runq[Nrq-2].head == nil){
		skipscheds++;
		rq = &runq[p->priority];
		goto found;
	}

	preempts++;

loop:
	/*
	 *  find a process that last ran on this processor (affinity),
	 *  or one that hasn't moved in a while (load balancing).  Every
	 *  time around the loop affinity goes down.
	 */
	spllo();
	for(i = 0;; i++){
		/*
		 *  find the highest priority target process that this
		 *  processor can run given affinity constraints.
		 *
		 */
		for(rq = &runq[Nrq-1]; rq >= runq; rq--){
			for(p = rq->head; p != nil; p = p->rnext){
				if(p->mp == nil || p->mp == MACHP(m->machno)
				|| (p->wired == nil && i > 0))
					goto found;
			}
		}

		/* waste time or halt the CPU */
		idlehands();

		/* remember how much time we're here */
		now = perfticks();
		m->perf.inidle += now-start;
		start = now;
	}

found:
	splhi();
	p = dequeueproc(rq, p);
	if(p == nil)
		goto loop;

	p->state = Scheding;
	p->mp = MACHP(m->machno);

	if(edflock(p)){
		edfrun(p, rq == &runq[PriEdf]);	/* start deadline timer and do admin */
		edfunlock();
	}
	pt = proctrace;
	if(pt != nil)
		pt(p, SRun, 0);
	return p;
}
예제 #12
0
파일: edf.c 프로젝트: Requaos/harvey
int
edfready(Proc *p)
{
	Edf *e;
	Sched *sch;
	Schedq *rq;
	Proc *l, *pp;
	int32_t n;

	if((e = edflock(p)) == nil)
		return 0;

	if(p->state == Wakeme && p->r){
		iprint("edfready: wakeme\n");
	}
	if(e->d - now <= 0){
		/* past deadline, arrange for next release */
		if((e->flags & Sporadic) == 0){
			/*
			 * Non sporadic processes stay true to their period;
			 * calculate next release time.
			 */
			if((n = now - e->t) > 0){
				if(n < e->T)
					e->t += e->T;
				else
					e->t = now + e->T - (n % e->T);
			}
		}
		if(now - e->t < 0){
			/* Next release is in the future, schedule it */
			if(e->Timer.tt == nil || e->Timer.tf != releaseintr){
				n = e->t - now;
				if(n < 20)
					n = 20;
				e->Timer.tns = 1000LL * n;
				e->Timer.tmode = Trelative;
				e->Timer.tf = releaseintr;
				e->Timer.ta = p;
				timeradd(&e->Timer);
				DPRINT("%lu edfready %d[%s], release=%lu\n",
					now, p->pid, statename[p->state], e->t);
			}
			if(p->state == Running && (e->flags & (Yield|Yieldonblock)) == 0 && (e->flags & Extratime)){
				/* If we were running, we've overrun our CPU allocation
				 * or missed the deadline, continue running best-effort at low priority
				 * Otherwise we were blocked.  If we don't yield on block, we continue
				 * best effort
				 */
				DPRINT(">");
				p->basepri = PriExtra;
				p->fixedpri = 1;
				edfunlock();
				return 0;	/* Stick on runq[PriExtra] */
			}
			DPRINT("%lu edfready %d[%s] wait release at %lu\n",
				now, p->pid, statename[p->state], e->t);
			p->state = Waitrelease;
			edfunlock();
			return 1;	/* Make runnable later */
		}
		DPRINT("%lu edfready %d %s release now\n", now, p->pid, statename[p->state]);
		/* release now */
		release(p);
	}
	edfunlock();
	DPRINT("^");
	sch = procsched(p);
	rq = &sch->runq[PriEdf];
	/* insert in queue in earliest deadline order */
	lock(&sch->l);
	l = nil;
	for(pp = rq->head; pp; pp = pp->rnext){
		if(pp->edf->d > e->d)
			break;
		l = pp;
	}
	p->rnext = pp;
	if (l == nil)
		rq->head = p;
	else
		l->rnext = p;
	if(pp == nil)
		rq->tail = p;
	rq->n++;
	sch->nrdy++;
	sch->runvec |= 1 << PriEdf;
	p->priority = PriEdf;
	p->readytime = machp()->ticks;
	p->state = Ready;
	unlock(&sch->l);
	if(p->trace)
		proctrace(p, SReady, 0);
	return 1;
}
예제 #13
0
파일: edf.c 프로젝트: Requaos/harvey
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;
}
예제 #14
0
파일: proc.c 프로젝트: npe9/harvey
static Proc*
singlerunproc(void)
{
	Mach *m = machp();
	Schedq *rq;
	Proc *p;
	uint32_t start, now, skipscheds;
	int i;

	start = perfticks();

	/* cooperative scheduling until the clock ticks */
	if((p=m->readied) && p->mach==0 && p->state==Ready
	&& &run.runq[Nrq-1].head == nil && &run.runq[Nrq-2].head == nil){
		skipscheds++;
		rq = &run.runq[p->priority];
		if(0)hi("runproc going to found before loop...\n");
		goto found;
	}

	run.preempts++;

loop:
	/*
	 *  find a process that last ran on this processor (affinity),
	 *  or one that hasn't moved in a while (load balancing).  Every
	 *  time around the loop affinity goes down.
	 */
	spllo();
	for(i = 0;; i++){
		/*
		 *  find the highest priority target process that this
		 *  processor can run given affinity constraints.
		 *
		 */
		for(rq = &run.runq[Nrq-1]; rq >= run.runq; rq--){
			for(p = rq->head; p; p = p->rnext){
				if(p->mp == nil || p->mp == sys->machptr[m->machno]
				|| (!p->wired && i > 0))
				{
					if(0)hi("runproc going to found inside loop...\n");
					goto found;
				}
			}
		}

		/* waste time or halt the CPU */
		idlehands();

		/* remember how much time we're here */
		now = perfticks();
		m->perf.inidle += now-start;
		start = now;
	}

found:
	splhi();
	if(0)hi("runproc into found...\n");
	p = dequeueproc(&run, rq, p);
	if(p == nil)
	{
		if(0)hi("runproc p=nil :(\n");
			goto loop;
	}

	p->state = Scheding;
	if(0)hi("runproc, pm->mp = sys->machptr[m->machno]\n");
	p->mp = sys->machptr[m->machno];
	if(0){hi("runproc, sys->machptr[m->machno] = "); put64((uint64_t)p->mp); hi("\n");}

	if(edflock(p)){
		edfrun(p, rq == &run.runq[PriEdf]);	/* start deadline timer and do admin */
		edfunlock();
	}
	if(p->trace)
		proctrace(p, SRun, 0);
	/* avoiding warnings, this will be removed */
	USED(mach0sched); USED(smprunproc);
	if(0){hi("runproc, returning p ");
	put64((uint64_t)p);
	hi("\n");}

	
	return p;
}
예제 #15
0
파일: edf.c 프로젝트: 8l/inferno
int
edfready(Proc *p)
{
	Edf *e;
	Schedq *rq;
	Proc *l, *pp;
	void (*pt)(Proc*, int, vlong);

	if((e = edflock(p)) == nil)
		return 0;
	if (e->d <= now){
		/* past deadline, arrange for next release */
		if ((e->flags & Sporadic) == 0){
			/* Non sporadic processes stay true to their period, calculate next release time */
			while(e->t < now)
				e->t += e->T;
		}	
		if (now < e->t){
			/* Next release is in the future, schedule it */
			if (e->tt == nil || e->tf != releaseintr){
				e->tns = e->t;
				e->tmode = Tabsolute;
				e->tf = releaseintr;
				e->ta = p;
				timeradd(e);
				DPRINT("%t edfready %lud[%s], release=%t\n",
					now, p->pid, statename[p->state], e->t);
			}
			if(p->state == Running && (e->flags & (Yield|Yieldonblock)) == 0 && (e->flags & Extratime)){
				/* If we were running, we've overrun our CPU allocation
				 * or missed the deadline, continue running best-effort at low priority
				 * Otherwise we were blocked.  If we don't yield on block, we continue
				 * best effort
				 */
				DPRINT(">");
				p->pri = PriExtra;
				edfunlock();
				return 0;	/* Stick on runq[PriExtra] */
			}
			DPRINT("%t edfready %lud[%s] wait release at %t\n",
				now, p->pid, statename[p->state], e->t);
			p->state = Waitrelease;
			edfunlock();
			return 1;	/* Make runnable later */
		}
		DPRINT("%t edfready %lud %s release now\n", now, p->pid, statename[p->state]);
		/* release now */
		release(p);
	}
	edfunlock();
	DPRINT("^");
	rq = &runq[PriEdf];
	/* insert in queue in earliest deadline order */
	lock(runq);
	l = nil;
	for(pp = rq->head; pp; pp = pp->rnext){
		if(pp->edf->d > e->d)
			break;
		l = pp;
	}
	p->rnext = pp;
	if (l == nil)
		rq->head = p;
	else
		l->rnext = p;
	if(pp == nil)
		rq->tail = p;
	rq->n++;
	nrdy++;
	runvec |= 1 << PriEdf;
	p->pri = PriEdf;
	p->readytime = m->ticks;
	p->state = Ready;
	unlock(runq);
	if(pt = proctrace)
		pt(p, SReady, now);
	return 1;
}
예제 #16
0
파일: edf.c 프로젝트: 8l/inferno
char *
edfadmit(Proc *p)
{
	char *err;
	Edf *e;
	int i;
	Proc *r;
	void (*pt)(Proc*, int, vlong);

	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(pt = proctrace)
		pt(p, SAdmit, now);

	/* Look for another proc with the same period to synchronize to */
	SET(r);
	for(i=0; i<conf.nproc; i++) {
		r = proctab(i);
		if(r->state == Dead || r == p)
			continue;
		if (r->edf == nil || (r->edf->flags & Admitted) == 0)
			continue;
		if (r->edf->T == e->T)
				break;
	}
	if (i == conf.nproc){
		/* Can't synchronize to another proc, release now */
		e->t = now;
		e->d = 0;
		release(p);
		if (p == up){
			DPRINT("%t edfadmit self %lud[%s], release now: r=%t d=%t t=%t\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("%t edfadmit other %lud[%s], release now: r=%t d=%t t=%t\n",
				now, p->pid, statename[p->state], e->r, e->d, e->t);
			p->ta = p;
			edfunlock();
			qunlock(&edfschedlock);
			releaseintr(nil, p);
			return nil;
		}
	}else{
		/* Release in synch to something else */
		e->t = r->edf->t;
		if (p == up){
			DPRINT("%t edfadmit self %lud[%s], release at %t\n",
				now, p->pid, statename[p->state], e->t);
			edfunlock();
			qunlock(&edfschedlock);
			return nil;
		}else{
			DPRINT("%t edfadmit other %lud[%s], release at %t\n",
				now, p->pid, statename[p->state], e->t);
			if(e->tt == nil){
				e->tf = releaseintr;
				e->ta = p;
				e->tns = e->t;
				e->tmode = Tabsolute;
				timeradd(e);
			}
		}
	}
	edfunlock();
	qunlock(&edfschedlock);
	return nil;
}