plan 9 kernel history: overview | file list | diff list

2002/0327/port/edf.c (diff list | history)

2002/0322/sys/src/9/port/edf.c:26,322002/0327/sys/src/9/port/edf.c:26,34 (short | long | prev | next)
2002/0315    
	[EdfDeadline] =		"Deadline", 
}; 
 
static Cycintr	schedpoint;		/* First scheduling point */ 
2002/0327    
static Cycintr	cycdeadline;		/* Time of next deadline */ 
static Cycintr	cycrelease;		/* Time of next release */ 
 
2002/0315    
static Ticks	utilization;		/* Current utilization */ 
static int		initialized; 
static uvlong	fasthz;	 
2002/0322/sys/src/9/port/edf.c:66,772002/0327/sys/src/9/port/edf.c:68,79
2002/0315    
 
2002/0316    
void (*devrt)(Task*, Ticks, int); 
2002/0315    
 
static void		edf_intr(Ureg*, Cycintr*); 
2002/0327    
static void		edfdeadlineintr(Ureg*, Cycintr*); 
2002/0315    
static void		edf_resched(Task *t); 
2002/0320    
static void		setdelta(void); 
static void		testdelta(Task *thetask); 
2002/0315    
static char *	edf_testschedulability(Task *thetask); 
static void		edf_setclock(void); 
2002/0327    
static void		edfreleaseintr(void); 
2002/0315    
 
void 
edf_init(void) 
2002/0322/sys/src/9/port/edf.c:84,922002/0327/sys/src/9/port/edf.c:86,97
2002/0315    
		return; 
	} 
	fastticks(&fasthz); 
	schedpoint.f = edf_intr; 
	schedpoint.a = &schedpoint; 
	schedpoint.when = 0; 
2002/0327    
	cycdeadline.f = edfdeadlineintr; 
	cycdeadline.a = &cycdeadline; 
	cycdeadline.when = 0; 
	cycrelease.f = edfreleaseintr; 
	cycrelease.a = &cycrelease; 
	cycrelease.when = 0; 
2002/0315    
	initialized = 1; 
	iunlock(&edflock); 
} 
2002/0322/sys/src/9/port/edf.c:190,1962002/0327/sys/src/9/port/edf.c:195,201
2002/0315    
	return t; 
} 
 
static void 
2002/0327    
static Task* 
2002/0315    
edfqremove(Taskq *q, Task *t) 
{ 
	Task **tp; 
2002/0322/sys/src/9/port/edf.c:200,2132002/0327/sys/src/9/port/edf.c:205,256
2002/0315    
	for (tp = &q->head; *tp; tp = &(*tp)->rnext){ 
		if (*tp == t){ 
			*tp = t->rnext; 
2002/0327    
			t = (tp == &q->head) ? q->head : nil; 
2002/0315    
			iunlock(q); 
			return; 
2002/0327    
			return t; 
2002/0315    
		} 
	} 
	iunlock(q); 
} 
 
2002/0327    
			 
2002/0315    
void 
2002/0327    
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 
2002/0315    
edf_block(Proc *p) 
{ 
	Task *t, *pt; 
2002/0322/sys/src/9/port/edf.c:255,2612002/0327/sys/src/9/port/edf.c:298,308
2002/0315    
		iunlock(&edflock); 
		assert(0 && p == nil || nt == t); 
	} 
                 
2002/0327    
	if (cycdeadline.when){ 
		cycintrdel(&cycdeadline); 
		cycdeadline.when = 0; 
		clockintrsched(); 
	} 
2002/0315    
	t->d = now; 
	t->state = EdfDeadline; 
2002/0316    
	if(devrt) devrt(t, now, why); 
2002/0322/sys/src/9/port/edf.c:318,3242002/0327/sys/src/9/port/edf.c:365,370
2002/0320    
		setdelta(); 
2002/0315    
		assert(t->runq.n > 0 || (up && up->task == t)); 
		edfpush(t); 
		edf_setclock(); 
	}else{ 
		if (t->runq.n){ 
			if (edfstack[m->machno].head == nil){ 
2002/0322/sys/src/9/port/edf.c:358,3642002/0327/sys/src/9/port/edf.c:404,411
2002/0315    
		/* Just reset state */ 
		break; 
	case EdfAwaitrelease: 
		edfqremove(&qwaitrelease, t); 
2002/0327    
		if (edfqremove(&qwaitrelease, t)) 
			edfreleasetimer(); 
2002/0315    
		break; 
	case EdfReleased: 
		edfqremove(&qreleased, t); 
2002/0322/sys/src/9/port/edf.c:387,3972002/0327/sys/src/9/port/edf.c:434,474
2002/0315    
} 
 
static void 
edf_timer(void) 
2002/0327    
edfreleaseintr(void) 
2002/0315    
{ 
2002/0327    
	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) 
{ 
2002/0315    
	Ticks used; 
	Task *t; 
 
2002/0327    
	DPRINT("%d edfdeadlineintr\n", m->machno); 
	/* Task reached deadline 
	 */ 
	now = fastticks(nil); 
 
	if(active.exiting) 
		return; 
 
	ilock(&edflock); 
2002/0315    
	// If up is not set, we're running inside the scheduler 
	// for non-real-time processes.  
	if (up && isedf(up)) { 
2002/0322/sys/src/9/port/edf.c:418,4882002/0327/sys/src/9/port/edf.c:495,500
2002/0315    
			} 
		} 
	} 
                 
	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; 
                 
2002/0322    
	DPRINT("%d edf_setclock\n", m->machno); 
2002/0315    
	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){ 
2002/0322    
		DPRINT("%d cycintrdel %T\n", m->machno, ticks2time(schedpoint.when)); 
2002/0315    
		cycintrdel(&schedpoint); 
		schedpoint.when = 0; 
	} 
	if (ticks <= now){ 
2002/0322    
		DPRINT("%d edf_timer: %T too late\n", m->machno, ticks2time(now-ticks)); 
2002/0315    
		ticks = now; 
	} 
	if (ticks != ~0ULL) { 
2002/0322    
		DPRINT("%d program timer in %T\n", m->machno, ticks2time(ticks-now)); 
2002/0315    
		schedpoint.when = ticks; 
		cycintradd(&schedpoint); 
2002/0322    
		DPRINT("%d cycintradd %T\n", m->machno, ticks2time(schedpoint.when-now)); 
2002/0315    
	} 
	clockintrsched(); 
} 
	                 
static void 
edf_intr(Ureg *, Cycintr *cy) 
{ 
                 
2002/0322    
	DPRINT("%d edf_intr\n", m->machno); 
2002/0315    
	/* 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(); 
2002/0322/sys/src/9/port/edf.c:630,6412002/0327/sys/src/9/port/edf.c:642,650
2002/0315    
			/* Released, but deadline is past, release at t->t */ 
			t->r = t->t; 
		} 
2002/0322    
		DPRINT("%d edf_resched, schedule release\n", m->machno); 
2002/0315    
		xt = edfpop(); 
		assert(xt == t); 
		edfenqueue(&qwaitrelease, t); 
		t->state = EdfAwaitrelease; 
		edf_setclock(); 
2002/0327    
		schedrelease(t); 
2002/0315    
		break; 
	case EdfBlocked: 
	case EdfDeadline: 
2002/0322/sys/src/9/port/edf.c:661,6702002/0327/sys/src/9/port/edf.c:670,676
2002/0315    
			/* Released, but deadline is past, release at t->t */ 
			t->r = t->t; 
		} 
2002/0322    
		DPRINT("%d edf_resched, schedule release\n", m->machno); 
2002/0315    
		edfenqueue(&qwaitrelease, t); 
		t->state = EdfAwaitrelease; 
		edf_setclock(); 
2002/0327    
		schedrelease(t); 
2002/0315    
		break; 
	} 
} 
2002/0322/sys/src/9/port/edf.c:681,6872002/0327/sys/src/9/port/edf.c:687,692
2002/0315    
	t->state = EdfReleased; 
	edfenqueue(&qreleased, t); 
2002/0316    
	if(devrt) devrt(t, now, SRelease); 
2002/0315    
	edf_setclock(); 
} 
 
Proc * 
2002/0322/sys/src/9/port/edf.c:691,6972002/0327/sys/src/9/port/edf.c:696,702
2002/0315    
	 
	Task *t, *nt; 
	Proc *p; 
//	Ticks when; 
2002/0327    
	Ticks when; 
2002/0315    
	static ulong nilcount; 
 
	/* Figure out if the current proc should be preempted*/ 
2002/0322/sys/src/9/port/edf.c:737,7432002/0327/sys/src/9/port/edf.c:742,769
2002/0315    
	if(p->mp != MACHP(m->machno)) 
		p->movetime = MACHP(0)->ticks + HZ/10; 
	p->mp = MACHP(m->machno); 
	edf_setclock(); 
2002/0327    
 
	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(); 
2002/0315    
	iunlock(&edflock); 
	return p; 
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)