git: 9front

Download patch

ref: 3700154c4e1d9c6eaa4f3443fbf461834ad0a846
parent: 74b9943b9cfb060b95ea607117c89f2fef2c734c
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Sat Jun 22 05:50:34 EDT 2013

apic: eleminate splhi and apictimerlock, per cpu apictimer structure

the splhi() and apictimerlock in the Mach isnt neccesary, as
portclock always holds the ilock of the per mach timer queue
when calling timerset().

as fastticks() and the portclock timers are all handled on a
per processor basis, i think it should be theoretically possible
for the lapics to run at different frequencies. so we measure
the lapic frequency for each individual lapic and keep them in
a per processor Apictimer structure instead of assuming them
to be the same.

--- a/sys/src/9/pc/apic.c
+++ b/sys/src/9/pc/apic.c
@@ -89,7 +89,8 @@
 
 static ulong* lapicbase;
 
-struct
+typedef struct Apictimer Apictimer;
+struct Apictimer
 {
 	uvlong	hz;
 	ulong	max;
@@ -96,8 +97,10 @@
 	ulong	min;
 	ulong	div;
 	int	tdx;
-} lapictimer;
+};
 
+static Apictimer lapictimer[MAXMACH];
+
 static ulong
 lapicr(int r)
 {
@@ -115,6 +118,10 @@
 void
 lapiconline(void)
 {
+	Apictimer *a;
+
+	a = &lapictimer[m->machno];
+
 	/*
 	 * Reload the timer to de-synchronise the processors,
 	 * then lower the task priority to allow interrupts to be
@@ -121,7 +128,7 @@
 	 * accepted by the APIC.
 	 */
 	microdelay((TK2MS(1)*1000/conf.nmach) * m->machno);
-	lapicw(LapicTICR, lapictimer.max);
+	lapicw(LapicTICR, a->max);
 	lapicw(LapicTIMER, LapicCLKIN|LapicPERIODIC|(VectorPIC+IrqTIMER));
 
 	/*
@@ -128,7 +135,7 @@
 	 * not strickly neccesary, but reported (osdev.org) to be
 	 * required for some machines.
 	 */
-	lapicw(LapicTDCR, lapictdxtab[lapictimer.tdx]);
+	lapicw(LapicTDCR, lapictdxtab[a->tdx]);
 
 	lapicw(LapicTPR, 0);
 }
@@ -139,35 +146,44 @@
 static void
 lapictimerinit(void)
 {
+	uvlong x, v, hz;
+	Apictimer *a;
+	int s;
+
+	s = splhi();
+	a = &lapictimer[m->machno];
+	a->tdx = 0;
 Retry:
 	lapicw(LapicTIMER, ApicIMASK|LapicCLKIN|LapicONESHOT|(VectorPIC+IrqTIMER));
-	lapicw(LapicTDCR, lapictdxtab[lapictimer.tdx]);
+	lapicw(LapicTDCR, lapictdxtab[a->tdx]);
 
-	if(lapictimer.hz == 0ULL){
-		uvlong x, v, hz;
+	x = fastticks(&hz);
+	x += hz/10;
+	lapicw(LapicTICR, 0xffffffff);
+	do{
+		v = fastticks(nil);
+	}while(v < x);
 
-		x = fastticks(&hz);
-		x += hz/10;
-		lapicw(LapicTICR, 0xffffffff);
-		do{
-			v = fastticks(nil);
-		}while(v < x);
-
-		v = (0xffffffffUL-lapicr(LapicTCCR))*10;
-		if(v > hz-(hz/10)){
-			if(v > hz+(hz/10) && lapictimer.tdx < nelem(lapictdxtab)-1){
-				lapictimer.tdx++;
-				goto Retry;
-			}
-			v = hz;
+	v = (0xffffffffUL-lapicr(LapicTCCR))*10;
+	if(v > hz-(hz/10)){
+		if(v > hz+(hz/10) && a->tdx < nelem(lapictdxtab)-1){
+			a->tdx++;
+			goto Retry;
 		}
-		assert(v != 0);
-
-		lapictimer.hz = v;
-		lapictimer.div = hz/lapictimer.hz;
-		lapictimer.max = lapictimer.hz/HZ;
-		lapictimer.min = lapictimer.hz/(100*HZ);
+		v = hz;
 	}
+
+	assert(v >= (100*HZ));
+
+	a->hz = v;
+	a->div = hz/a->hz;
+	a->max = a->hz/HZ;
+	a->min = a->hz/(100*HZ);
+
+	splx(s);
+
+	v = (v+500000LL)/1000000LL;
+	print("cpu%d: lapic clock at %lludMHz\n", m->machno, v);
 }
 
 void
@@ -377,25 +393,19 @@
 lapictimerset(uvlong next)
 {
 	vlong period;
-	int x;
+	Apictimer *a;
 
-	x = splhi();
-	lock(&m->apictimerlock);
-
-	period = lapictimer.max;
+	a = &lapictimer[m->machno];
+	period = a->max;
 	if(next != 0){
 		period = next - fastticks(nil);
-		period /= lapictimer.div;
-
-		if(period < lapictimer.min)
-			period = lapictimer.min;
-		else if(period > lapictimer.max - lapictimer.min)
-			period = lapictimer.max;
+		period /= a->div;
+		if(period < a->min)
+			period = a->min;
+		else if(period > a->max - a->min)
+			period = a->max;
 	}
 	lapicw(LapicTICR, period);
-
-	unlock(&m->apictimerlock);
-	splx(x);
 }
 
 void
--- a/sys/src/9/pc/dat.h
+++ b/sys/src/9/pc/dat.h
@@ -242,7 +242,6 @@
 
 	int	loopconst;
 
-	Lock	apictimerlock;
 	int	cpumhz;
 	uvlong	cyclefreq;		/* Frequency of user readable cycle counter */
 	uvlong	cpuhz;
--