~kris/9p

9hist

010b68864226ad43528a22c1a735df920f54c015 — David du Colombier 24 years ago eb058d0
Plan 9 from Bell Labs 2002-03-27
2 files changed, 130 insertions(+), 88 deletions(-)

M pc/trap.c
M port/edf.c
M pc/trap.c => pc/trap.c +16 -0
@@ 303,6 303,22 @@ trap(Ureg* ureg)
		postnote(up, 1, buf, NDebug);
	}
	else if(vno >= VectorPIC && vno != VectorSYSCALL){
		/* call all interrupt routines, just in case */
		for(i = VectorPIC; i <= MaxIrqLAPIC; i++){
			ctl = vctl[i];
			if(ctl == nil)
				continue;
			if(!ctl->isintr)
				continue;
			for(v = ctl; v != nil; v = v->next){
				if(v->f)
					v->f(ureg, v->a);
			}
			/* should we do this? */
			if(ctl->eoi)
				ctl->eoi(i);
		}
			
		/*
		 * An unknown interrupt.
		 * Check for a default IRQ7. This can happen when

M port/edf.c => port/edf.c +114 -88
@@ 26,7 26,9 @@ char *edf_statename[] = {
	[EdfDeadline] =		"Deadline",
};

static Cycintr	schedpoint;		/* First scheduling point */
static Cycintr	cycdeadline;		/* Time of next deadline */
static Cycintr	cycrelease;		/* Time of next release */

static Ticks	utilization;		/* Current utilization */
static int		initialized;
static uvlong	fasthz;	


@@ 66,12 68,12 @@ Taskq		edfstack[MAXMACH];

void (*devrt)(Task*, Ticks, int);

static void		edf_intr(Ureg*, Cycintr*);
static void		edfdeadlineintr(Ureg*, Cycintr*);
static void		edf_resched(Task *t);
static void		setdelta(void);
static void		testdelta(Task *thetask);
static char *	edf_testschedulability(Task *thetask);
static void		edf_setclock(void);
static void		edfreleaseintr(void);

void
edf_init(void)


@@ 84,9 86,12 @@ edf_init(void)
		return;
	}
	fastticks(&fasthz);
	schedpoint.f = edf_intr;
	schedpoint.a = &schedpoint;
	schedpoint.when = 0;
	cycdeadline.f = edfdeadlineintr;
	cycdeadline.a = &cycdeadline;
	cycdeadline.when = 0;
	cycrelease.f = edfreleaseintr;
	cycrelease.a = &cycrelease;
	cycrelease.when = 0;
	initialized = 1;
	iunlock(&edflock);
}


@@ 190,7 195,7 @@ edfdequeue(Taskq *q)
	return t;
}

static void
static Task*
edfqremove(Taskq *q, Task *t)
{
	Task **tp;


@@ 200,13 205,51 @@ edfqremove(Taskq *q, Task *t)
	for (tp = &q->head; *tp; tp = &(*tp)->rnext){
		if (*tp == t){
			*tp = t->rnext;
			t = (tp == &q->head) ? q->head : nil;
			iunlock(q);
			return;
			return t;
		}
	}
	iunlock(q);
}

			
void
edfreleasetimer(void)
{
	Task *t;

	t = qwaitrelease.head;
	DPRINT("edf_schedrelease clock\n");
	if (cycrelease.when == t->r)
		return;
	if (cycrelease.when){
		DPRINT("%d cycintrdel %T\n", m->machno, ticks2time(cycrelease.when));
		cycintrdel(&cycrelease);
	}
	cycrelease.when = t->r;
	if (cycrelease.when <= now){
		DPRINT("%d edf_timer: %T too late\n", m->machno, ticks2time(now-ticks));
		cycrelease.when = now;
	}
	DPRINT("%d program timer in %T\n", m->machno, ticks2time(ticks-now));
	cycintradd(&cycrelease);
	DPRINT("%d cycintradd %T\n", m->machno, ticks2time(cycrelease.when-now));
	clockintrsched();
}

void
edf_schedrelease(Task *t)
{
	Ticks ticks;

	DPRINT("%d edf_schedrelease\n", m->machno);
	/* Schedule a task for release */
	t->state = EdfAwaitrelease;
	if (edfenqueue(&qwaitrelease, t))
		edfreleasetimer();
}

void
edf_block(Proc *p)
{


@@ 255,7 298,11 @@ edfdeadline(Proc *p, SEvent why)
		iunlock(&edflock);
		assert(0 && p == nil || nt == t);
	}

	if (cycdeadline.when){
		cycintrdel(&cycdeadline);
		cycdeadline.when = 0;
		clockintrsched();
	}
	t->d = now;
	t->state = EdfDeadline;
	if(devrt) devrt(t, now, why);


@@ 318,7 365,6 @@ edf_admit(Task *t)
		setdelta();
		assert(t->runq.n > 0 || (up && up->task == t));
		edfpush(t);
		edf_setclock();
	}else{
		if (t->runq.n){
			if (edfstack[m->machno].head == nil){


@@ 358,7 404,8 @@ edf_expel(Task *t)
		/* Just reset state */
		break;
	case EdfAwaitrelease:
		edfqremove(&qwaitrelease, t);
		if (edfqremove(&qwaitrelease, t))
			edfreleasetimer();
		break;
	case EdfReleased:
		edfqremove(&qreleased, t);


@@ 387,11 434,41 @@ edf_expel(Task *t)
}

static void
edf_timer(void)
edfreleaseintr(void)
{
	Task *t;

	now = fastticks(nil);

	if(active.exiting)
		return;

	ilock(&edflock);
	while((t = qwaitrelease.head) && t->r <= now){
		/* There's something waiting to be released and its time has come */
		edfdequeue(&qwaitrelease);
		edf_release(t);
	}
	iunlock(&edflock);
	sched();
	splhi();
}

static void
edfdeadlineintr(Ureg *, Cycintr *cy)
{
	Ticks used;
	Task *t;

	DPRINT("%d edfdeadlineintr\n", m->machno);
	/* Task reached deadline
	 */
	now = fastticks(nil);

	if(active.exiting)
		return;

	ilock(&edflock);
	// If up is not set, we're running inside the scheduler
	// for non-real-time processes. 
	if (up && isedf(up)) {


@@ 418,71 495,6 @@ edf_timer(void)
			}
		}
	}

	while((t = qwaitrelease.head) && t->r <= now){
		/* There's something waiting to be released and its time has come */
		edfdequeue(&qwaitrelease);
		edf_release(t);
	}
}

static void
edf_setclock(void)
{
	Ticks ticks;
	Task *t;

	DPRINT("%d edf_setclock\n", m->machno);
	ticks = ~0ULL;
	if ((t = qwaitrelease.head) && t->r < ticks)
		ticks = t->r;
	if (t = edfstack[m->machno].head){
		if (t->d < ticks)
			ticks = t->d;
		if (now + t->S < ticks)
			ticks = now + t->S;
	}
	if (schedpoint.when > now && schedpoint.when <= ticks){
		return;
	}
	if (schedpoint.when){
		DPRINT("%d cycintrdel %T\n", m->machno, ticks2time(schedpoint.when));
		cycintrdel(&schedpoint);
		schedpoint.when = 0;
	}
	if (ticks <= now){
		DPRINT("%d edf_timer: %T too late\n", m->machno, ticks2time(now-ticks));
		ticks = now;
	}
	if (ticks != ~0ULL) {
		DPRINT("%d program timer in %T\n", m->machno, ticks2time(ticks-now));
		schedpoint.when = ticks;
		cycintradd(&schedpoint);
		DPRINT("%d cycintradd %T\n", m->machno, ticks2time(schedpoint.when-now));
	}
	clockintrsched();
}
	
static void
edf_intr(Ureg *, Cycintr *cy)
{

	DPRINT("%d edf_intr\n", m->machno);
	/* Timer interrupt
	 * Timed events are:
	 * 1. release a task (look in qwaitrelease)
	 * 2. task reaches deadline
	 */
	now = fastticks(nil);

	assert(cy == &schedpoint && schedpoint.when <= now);

	if(active.exiting)
		return;

	ilock(&edflock);
	edf_timer();
	edf_setclock();
	iunlock(&edflock);
	sched();
	splhi();


@@ 630,12 642,9 @@ edf_resched(Task *t)
			/* Released, but deadline is past, release at t->t */
			t->r = t->t;
		}
		DPRINT("%d edf_resched, schedule release\n", m->machno);
		xt = edfpop();
		assert(xt == t);
		edfenqueue(&qwaitrelease, t);
		t->state = EdfAwaitrelease;
		edf_setclock();
		schedrelease(t);
		break;
	case EdfBlocked:
	case EdfDeadline:


@@ 661,10 670,7 @@ edf_resched(Task *t)
			/* Released, but deadline is past, release at t->t */
			t->r = t->t;
		}
		DPRINT("%d edf_resched, schedule release\n", m->machno);
		edfenqueue(&qwaitrelease, t);
		t->state = EdfAwaitrelease;
		edf_setclock();
		schedrelease(t);
		break;
	}
}


@@ 681,7 687,6 @@ edf_release(Task *t)
	t->state = EdfReleased;
	edfenqueue(&qreleased, t);
	if(devrt) devrt(t, now, SRelease);
	edf_setclock();
}

Proc *


@@ 691,7 696,7 @@ edf_runproc(void)
	
	Task *t, *nt;
	Proc *p;
//	Ticks when;
	Ticks when;
	static ulong nilcount;

	/* Figure out if the current proc should be preempted*/


@@ 737,7 742,28 @@ edf_runproc(void)
	if(p->mp != MACHP(m->machno))
		p->movetime = MACHP(0)->ticks + HZ/10;
	p->mp = MACHP(m->machno);
	edf_setclock();

	when = now + t->S;
	if (t->d < when)
		when = t->d;

	if (cycdeadline.when){
		if(cycdeadline.when == when){
			iunlock(&edflock);
			return p;
		}
		DPRINT("%d cycintrdel %T\n", m->machno, ticks2time(cycdeadline.when));
		cycintrdel(&cycdeadline);
	}
	if (when <= now){
		DPRINT("%d edf_timer: %T too late\n", m->machno, ticks2time(now-when));
		when = now;
	}
	DPRINT("%d program timer in %T\n", m->machno, ticks2time(when-now));
	cycdeadline.when = when;
	cycintradd(&cycdeadline);
	DPRINT("%d cycintradd %T\n", m->machno, ticks2time(cycdeadline.when-now));
	clockintrsched();
	iunlock(&edflock);
	return p;
}