예제 #1
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;
}
예제 #2
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;
}