ref: 04b78032914d58a33745a1a13e2e3de99a7d94b4
parent: e38938384faa8857471fab0c05ade056b55fb360
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;
--
⑨