Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/port/portclock.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname port/portclock.c 2000/1106
## diff -e /dev/null /n/emeliedump/2000/1106/sys/src/9/port/portclock.c
0a
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "ureg.h"

void (*kproftimer)(ulong);

typedef struct Clock0link Clock0link;
typedef struct Clock0link {
	void		(*clock)(void);
	Clock0link*	link;
} Clock0link;

static Clock0link *clock0link;
static Lock clock0lock;

void
addclock0link(void (*clock)(void))
{
	Clock0link *lp;

	if((lp = malloc(sizeof(Clock0link))) == 0){
		print("addclock0link: too many links\n");
		return;
	}
	ilock(&clock0lock);
	lp->clock = clock;
	lp->link = clock0link;
	clock0link = lp;
	iunlock(&clock0lock);
}

void
portclock(Ureg *ur)
{
	Clock0link *lp;

	m->ticks++;
	if(m->proc)
		m->proc->pc = ur->pc;

	if(m->inclockintr)
		return;		/* interrupted ourself */
	m->inclockintr = 1;

	accounttime();

	if(kproftimer != nil)
		kproftimer(ur->pc);

	if((active.machs&(1<<m->machno)) == 0)
		return;

	if(active.exiting && (active.machs & (1<<m->machno))) {
		print("someone's exiting\n");
		exit(0);
	}

	checkalarms();
	if(m->machno == 0){
		ilock(&clock0lock);
		for(lp = clock0link; lp; lp = lp->link){
			lp->clock();
			splhi();
		}
		iunlock(&clock0lock);
	}

	m->inclockintr = 0;

	if(up == 0 || up->state != Running)
		return;

	if(anyready())
		sched();

	/* user profiling clock */
	if(userureg(ur)) {
		(*(ulong*)(USTKTOP-BY2WD)) += TK2MS(1);
		segclock(ur->pc);
	}
}
.
## diffname port/portclock.c 2000/1206
## diff -e /n/emeliedump/2000/1106/sys/src/9/port/portclock.c /n/emeliedump/2000/1206/sys/src/9/port/portclock.c
64,69c
		if(canlock(&clock0lock))
			for(lp = clock0link; lp; lp = lp->link){
				lp->clock();
				splhi();
			}
		unlock(&clock0lock);
.
## diffname port/portclock.c 2001/0328
## diff -e /n/emeliedump/2000/1206/sys/src/9/port/portclock.c /n/emeliedump/2001/0328/sys/src/9/port/portclock.c
84a
	m->inclockintr = 0;
.
75a
	}
.
72,74c
	if(up == 0 || up->state != Running){
		m->inclockintr = 0;
.
## diffname port/portclock.c 2001/0331
## diff -e /n/emeliedump/2001/0328/sys/src/9/port/portclock.c /n/emeliedump/2001/0331/sys/src/9/port/portclock.c
85d
78a
		splhi();
	}
.
77c
	if(anyready()){
.
75d
72,73c
	m->inclockintr = 0;
	if(up == 0 || up->state != Running)
.
## diffname port/portclock.c 2001/0527
## diff -e /n/emeliedump/2001/0331/sys/src/9/port/portclock.c /n/emeliedump/2001/0527/sys/src/9/port/portclock.c
72a

.
49a
	kmapinval();
.
## diffname port/portclock.c 2001/0711
## diff -e /n/emeliedump/2001/0527/sys/src/9/port/portclock.c /n/emeliedump/2001/0711/sys/src/9/port/portclock.c
88a

ulong
TK2MS(ulong ticks)
{
	uvlong t, hz;

	t = ticks;
	hz = HZ;
	t *= 1000L;
	t = t/hz;
	ticks = t;
	return ticks;
}
.
## diffname port/portclock.c 2001/0905
## diff -e /n/emeliedump/2001/0711/sys/src/9/port/portclock.c /n/emeliedump/2001/0905/sys/src/9/port/portclock.c
89,101d
## diffname port/portclock.c 2002/0315
## diff -e /n/emeliedump/2001/0905/sys/src/9/port/portclock.c /n/emeliedump/2002/0315/sys/src/9/port/portclock.c
78c
	// i.e. don't schedule an EDF process here!
	if(!isedf(up) && anyready()){
.
7a
#include "../port/edf.h"
.
## diffname port/portclock.c 2002/0402
## diff -e /n/emeliedump/2002/0315/sys/src/9/port/portclock.c /n/emeliedump/2002/0402/sys/src/9/port/portclock.c
78,83d
8d
## diffname port/portclock.c 2002/0404
## diff -e /n/emeliedump/2002/0402/sys/src/9/port/portclock.c /n/emeliedump/2002/0404/sys/src/9/port/portclock.c
76a

	// i.e. don't schedule an EDF process here!
	if(!isedf(up) && anyready()){
		sched();
		splhi();
	}
.
7a
#include "../port/edf.h"
.
## diffname port/portclock.c 2002/0410
## diff -e /n/emeliedump/2002/0404/sys/src/9/port/portclock.c /n/emeliedump/2002/0410/sys/src/9/port/portclock.c
89a
}

void
timerintr(Ureg *u, uvlong)
{
	Timer *t;
	Timers *tt;
	uvlong when, now;
	int callhzclock;

	intrcount[m->machno]++;
	callhzclock = 0;
	tt = &timers[m->machno];
	now = (uvlong)fastticks(nil);
	ilock(tt);
	while(t = tt->head){
		when = t->when;
		if(when > now){
			iunlock(tt);
			timerset(when);
			if(callhzclock)
				hzclock(u);
			return;
		}
		tt->head = t->next;
		fcallcount[m->machno]++;
		iunlock(tt);
		if (t->f){
			(*t->f)(u, t);
			splhi();
		} else
			callhzclock++;
		ilock(tt);
		if(t->period){
			t->when += t->period;
			if (t->when <= now)
				t->when = now + t->period;
			tadd(tt, t);
		}
	}
	iunlock(tt);
}

uvlong hzperiod;

void
timersinit(void)
{
	Timer *t;

	hzperiod = ms2fastticks(1000/HZ);

	t = smalloc(sizeof(*t));
	t->period = hzperiod;
	t->f = nil;
	timeradd(t);
}

void
addclock0link(void (*f)(void))
{
	Timer *nt;

	/* Synchronize this to hztimer: reduces # of interrupts */
	nt = malloc(sizeof(Timer));
	nt->when = 0;
	if (hzperiod == 0)
		hzperiod = ms2fastticks(1000/HZ);
	nt->period = hzperiod;
	nt->f = (void (*)(Ureg*, Timer*))f;

	ilock(&timers[0]);
	tadd(&timers[0], nt);
	/* no need to restart timer:
	 * this one's synchronized with hztimer which is already running
	 */
	iunlock(&timers[0]);
}

void
clockintrsched(void)
{
.
80c
	if(anyready() && !isedf(up)){
.
65,72d
49a
	if(m->flushmmu){
		if(up)
			flushmmu();
		m->flushmmu = 0;
	}

.
41a
	tt = &timers[m->machno];
	ilock(tt);
	when = tadd(tt, nt);
	if (when)
		timerset(when);
	iunlock(tt);
}

void
timerdel(Timer *dt)
{
	Timer *t, **last;
	Timers *tt;

	tt = &timers[m->machno];
	ilock(tt);
	for(last = &tt->head; t = *last; last = &t->next){
		if(t == dt){
			*last = t->next;
			break;
		}
	}
	if (last == &tt->head && tt->head)
		timerset(tt->head->when);
	iunlock(tt);
}

void
hzclock(Ureg *ur)
{
.
40c
	Timers *tt;
	uvlong when;
.
38c
timeradd(Timer *nt)
.
36a
/* add of modify a timer */
.
30,34c

	if(nt->when == 0){
		/* Try to synchronize periods to reduce # of interrupts */
		assert(nt->period);
		if(pt)
			nt->when = pt->when;
		else
			nt->when = (uvlong)fastticks(nil) + nt->period;
	}
	
	for(last = &tt->head; t = *last; last = &t->next){
		if(t->when > nt->when)
			break;
	}
	nt->next = *last;
	*last = nt;
	if (last == &tt->head)
		return nt->when;
	else
		return 0;
.
26,28c
	pt = nil;
	for(last = &tt->head; t = *last; last = &t->next){
		if(t == nt){
			*last = t->next;
			break;
		}
		if (t->period == nt->period)
			pt = t;
.
24c
	Timer *t, **last, *pt;
.
21,22c
ulong intrcount[MAXMACH];
ulong fcallcount[MAXMACH];

static uvlong
tadd(Timers *tt, Timer *nt)
.
18,19c
static Timers timers[MAXMACH];
.
12,16c
struct Timers
{
	Lock;
	Timer	*head;
};
.
10c
typedef struct Timers Timers;
.
8d
## diffname port/portclock.c 2002/0412
## diff -e /n/emeliedump/2002/0410/sys/src/9/port/portclock.c /n/emeliedump/2002/0412/sys/src/9/port/portclock.c
130c
	/* i.e. don't deschedule an EDF process here! */
.
## diffname port/portclock.c 2002/0413
## diff -e /n/emeliedump/2002/0412/sys/src/9/port/portclock.c /n/emeliedump/2002/0413/sys/src/9/port/portclock.c
218,222d
193c
	t = malloc(sizeof(*t));
	t->when = 0;
.
181a
	m->inclockintr = 0;
.
162a
			m->inclockintr = 0;
.
154c
	now = fastticks(nil);
.
150a
	if(m->inclockintr)
		return;
	m->inclockintr = 1;

.
99,102d
## diffname port/portclock.c 2002/0414
## diff -e /n/emeliedump/2002/0413/sys/src/9/port/portclock.c /n/emeliedump/2002/0414/sys/src/9/port/portclock.c
177,178d
## diffname port/portclock.c 2002/0416
## diff -e /n/emeliedump/2002/0414/sys/src/9/port/portclock.c /n/emeliedump/2002/0416/sys/src/9/port/portclock.c
181d
163d
147,150d
121,122d
## diffname port/portclock.c 2002/0704
## diff -e /n/emeliedump/2002/0416/sys/src/9/port/portclock.c /n/emeliedump/2002/0704/sys/src/9/port/portclock.c
125c
	if(anyready() && !edf->isedf(up)){
.
## diffname port/portclock.c 2002/0710
## diff -e /n/emeliedump/2002/0704/sys/src/9/port/portclock.c /n/emeliedump/2002/0710/sys/src/9/port/portclock.c
210a
}

/*
 *  This tk2ms avoids overflows that the macro version is prone to.
 *  It is a LOT slower so shouldn't be used if you're just converting
 *  a delta.
 */
ulong
tk2ms(ulong ticks)
{
	uvlong t, hz;

	t = ticks;
	hz = HZ;
	t *= 1000L;
	t = t/hz;
	ticks = t;
	return ticks;
}

ulong
ms2tk(ulong ms)
{
	/* avoid overflows at the cost of precision */
	if(ms >= 1000000000/HZ)
		return (ms/1000)*HZ;
	return (ms*HZ+500)/1000;
.
173a
	intimer = 0;
.
156a
			intimer = 0;
.
144a
	if(intimer){
		print("!");
		return;
	}
	intimer = 1;

.
143a
	static int intimer;
.
## diffname port/portclock.c 2002/0711
## diff -e /n/emeliedump/2002/0710/sys/src/9/port/portclock.c /n/emeliedump/2002/0711/sys/src/9/port/portclock.c
182d
164d
161a
			m->splpc = pc;	/* for kernel profiling */
.
146,150c
	pc = m->splpc;	/* remember last splhi pc for kernel profiling */
.
144c
	ulong pc;
	static int sofar;
.
## diffname port/portclock.c 2002/0928
## diff -e /n/emeliedump/2002/0711/sys/src/9/port/portclock.c /n/emeliedump/2002/0928/sys/src/9/port/portclock.c
205,207c
	if (ms == 0)
		ms = 1000/HZ;
	nt->period = ms2fastticks(ms);
.
198c
addclock0link(void (*f)(void), int ms)
.
34a
		}
.
33c
		if (t->period == nt->period){
			/* look for another timer at same frequency for combining */
.
29a
			/* timer's changing, remove it before putting it back on */
.
## diffname port/portclock.c 2003/0122
## diff -e /n/emeliedump/2002/0928/sys/src/9/port/portclock.c /n/emeliedump/2003/0122/sys/src/9/port/portclock.c
161a
			iunlock(tt);
.
160d
## diffname port/portclock.c 2003/0226
## diff -e /n/emeliedump/2003/0122/sys/src/9/port/portclock.c /n/emeliedump/2003/0226/sys/src/9/port/portclock.c
127,128c
	if(up->fixedpri){
		/*  fixed priority processes are only preempted by
		 *  higher piority processes.
		 */
		if(anyhigher())
			callsched = 1;
	} else {
		/*  floating priority processes are are preempted
		 *  by all sorts of things.
		 */
		if(anyready() && !edf->isedf(up))
			callsched = 1;
	}
	if(callsched){
.
97a
	int callsched;

.
## diffname port/portclock.c 2003/0228
## diff -e /n/emeliedump/2003/0226/sys/src/9/port/portclock.c /n/emeliedump/2003/0228/sys/src/9/port/portclock.c
151a

	hzsched();	/* in proc.c */
.
148c
	if(userureg(ur)){
.
129,146d
98,99d
## diffname port/portclock.c 2003/0406
## diff -e /n/emeliedump/2003/0228/sys/src/9/port/portclock.c /n/emeliedump/2003/0406/sys/src/9/port/portclock.c
204c
	if(ms == 0)
.
166c
		if(t->f){
.
90c
	if(last == &tt->head && tt->head)
.
71c
	if(when)
.
55c
	if(last == &tt->head)
.
34c
		if(t->period == nt->period){
.
## diffname port/portclock.c 2003/0409
## diff -e /n/emeliedump/2003/0406/sys/src/9/port/portclock.c /n/emeliedump/2003/0409/sys/src/9/port/portclock.c
98a
if((m->ticks % 10000) == 0){
	extern int allints[];
	int i;
	for(i=0; i < 32; i++)
		print("[%d] %d\n", i, allints[i]);
}
.
## diffname port/portclock.c 2003/0410
## diff -e /n/emeliedump/2003/0409/sys/src/9/port/portclock.c /n/emeliedump/2003/0410/sys/src/9/port/portclock.c
99,104d

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].