~kris/9p

9hist

e6f6e843ac2051282dd30af3b55fe5b75b26c26f — David du Colombier 24 years ago 010b688
Plan 9 from Bell Labs 2002-03-28
4 files changed, 36 insertions(+), 96 deletions(-)

M port/edf.c
M port/portdat.h
M port/proc.c
M port/taslock.c
M port/edf.c => port/edf.c +31 -83
@@ 33,8 33,7 @@ static Ticks	utilization;		/* Current utilization */
static int		initialized;
static uvlong	fasthz;	
static Ticks	now;
QLock		edfschedlock;		/* schedulability, held for
							 */
QLock		edfschedlock;
Lock			edflock;

Task			tasks[Maxtasks];


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

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

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		edfreleaseintr(void);
static void		edfreleaseintr(Ureg *, Cycintr *cy);
static void		edfdeadlineintr(Ureg*, Cycintr*);

void
edf_init(void)


@@ 211,6 210,7 @@ edfqremove(Taskq *q, Task *t)
		}
	}
	iunlock(q);
	return nil;
}

			


@@ 219,38 219,19 @@ edfreleasetimer(void)
{
	Task *t;

	t = qwaitrelease.head;
	DPRINT("edf_schedrelease clock\n");
	if (cycrelease.when == t->r)
	if ((t = qwaitrelease.head) == nil)
		return;
	if (cycrelease.when){
		DPRINT("%d cycintrdel %T\n", m->machno, ticks2time(cycrelease.when));
	DPRINT("edfreleasetimer clock\n");
	if (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));
	if (cycrelease.when <= now)
		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)
{
	Task *t, *pt;


@@ 434,19 415,23 @@ edf_expel(Task *t)
}

static void
edfreleaseintr(void)
edfreleaseintr(Ureg*, Cycintr*)
{
	Task *t;

	now = fastticks(nil);
	DPRINT("%d edfreleaseintr\n", m->machno);

	cycrelease.when = 0;

	if(active.exiting)
		return;

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


@@ 455,15 440,16 @@ edfreleaseintr(void)
}

static void
edfdeadlineintr(Ureg *, Cycintr *cy)
edfdeadlineintr(Ureg*, Cycintr*)
{
	/* Task reached deadline */

	Ticks used;
	Task *t;

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

	cycdeadline.when = 0;

	if(active.exiting)
		return;


@@ 472,6 458,8 @@ edfdeadlineintr(Ureg *, Cycintr *cy)
	// If up is not set, we're running inside the scheduler
	// for non-real-time processes. 
	if (up && isedf(up)) {
		now = fastticks(nil);

		t = up->task;
		assert(t->scheduled > 0);
	


@@ 644,7 632,9 @@ edf_resched(Task *t)
		}
		xt = edfpop();
		assert(xt == t);
		schedrelease(t);
		t->state = EdfAwaitrelease;
		if (edfenqueue(&qwaitrelease, t))
			edfreleasetimer();
		break;
	case EdfBlocked:
	case EdfDeadline:


@@ 670,7 660,9 @@ edf_resched(Task *t)
			/* Released, but deadline is past, release at t->t */
			t->r = t->t;
		}
		schedrelease(t);
		t->state = EdfAwaitrelease;
		if (edfenqueue(&qwaitrelease, t))
			edfreleasetimer();
		break;
	}
}


@@ 747,68 739,24 @@ edf_runproc(void)
	if (t->d < when)
		when = t->d;

	if (when < now){
		DPRINT("%d edf_timer: %T too late\n", m->machno, ticks2time(now-when));
		when = now;
	}
	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;
}

static Lock	waitlock;

int
edf_waitlock(Lock *l)
{
	ilock(&waitlock);	/* can't afford normal locks here */
	if (l->key == 0){
		/* race on lock, don't block, just return */
		iunlock(&waitlock);
		return 0;
	}
	edf_block(up);
	up->rnext = l->edfwaiting;	/* enqueue on lock */
	l->edfwaiting = up;
	up->state = Scheding;
	up->lockwait = l;
	iunlock(&waitlock);
	return 1;
}

void
edf_releaselock(Lock *l)
{
	Proc *p;

	ilock(&waitlock);	/* can't afford normal locks here */
	if(l->edfwaiting == nil){
		iunlock(&waitlock);
		return;
	}
	p = l->edfwaiting;
	l->edfwaiting = p->rnext;
	assert(p->lockwait == l);
	if(p->state != Scheding)
		print("edf_releaselock: %s %lud %s\n", p->text, p->pid, statename[p->state]);
	p->lockwait = nil;
	iunlock(&waitlock);
	edf_ready(p);
}


/* Schedulability testing and its supporting routines */

static void

M port/portdat.h => port/portdat.h +2 -1
@@ 635,10 635,11 @@ struct Proc
	Note	lastnote;
	int	(*notify)(void*, char*);

	Lock		*lockwait;	/* waiting for lock to be released */
	Lock		*lockwait;

	Mach	*wired;
	Mach	*mp;		/* machine this process last ran on */
	ulong	nlocks;	/* number of locks held by proc */
	ulong	priority;	/* priority level */
	ulong	basepri;	/* base priority level */
	uchar	fixedpri;	/* priority level deson't change */

M port/proc.c => port/proc.c +1 -0
@@ 347,6 347,7 @@ newproc(void)
	p->wired = 0;
	p->ureg = 0;
	p->privatemem = 0;
	p->lockwait = nil;
	p->errstr = p->errbuf0;
	p->syserrstr = p->errbuf1;
	p->errbuf0[0] = '\0';

M port/taslock.c => port/taslock.c +2 -12
@@ 72,16 72,8 @@ lock(Lock *l)
		lockstats.inglare++;
		i = 0;
		while(l->key){
			if (isedf(up)){
				/* Edf process waiting for a lock; process holding lock will not
				 * be scheduled unless we give up the processor.  We give up
				 * the processor, but make sure we get awoken when the lock
				 * is released
				 */
				if (edf_waitlock(l))
					sched();
			} else if(conf.nmach < 2 && cansched){
				if (i++ > 5000){
			if(conf.nmach < 2 && cansched){
				if (i++ > 1000){
					i = 0;
					lockloop(l, pc);
				}


@@ 181,8 173,6 @@ unlock(Lock *l)
	l->pc = 0;
	l->key = 0;
	coherence();
	if (l->edfwaiting)
		edf_releaselock(l);
}

void