From 0ed7376734c237eeed1c7d91d094c06ebbd2a9cb Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 10 Apr 2002 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2002-04-10 --- alphapc/clock.c | 11 ++- alphapc/dat.h | 12 --- alphapc/main.c | 1 + bitsy/clock.c | 2 +- bitsy/dat.h | 13 --- mtx/clock.c | 13 ++- mtx/dat.h | 11 --- mtx/main.c | 1 + pc/apic.c | 70 +++++++++++++--- pc/archmp.c | 20 ++--- pc/dat.h | 15 +--- pc/devarch.c | 27 ++++++- pc/fns.h | 9 +-- pc/i8253.c | 174 +++++++++++++++++----------------------- pc/main.c | 2 + pc/mem.h | 1 + pc/mp.c | 52 +----------- port/auth.c | 2 +- port/devcons.c | 8 -- port/devloopback.c | 3 - port/devrealtime.c | 30 +++---- port/edf.c | 194 +++++++++++++++++++++++--------------------- port/edf.h | 22 +---- port/nulledf.c | 41 ++++++++++ port/portclock.c | 195 ++++++++++++++++++++++++++++++++++++++------- port/portdat.h | 13 +++ port/portfns.h | 23 +++++- port/proc.c | 51 ++---------- port/qlock.c | 7 +- port/sysproc.c | 3 +- port/tod.c | 15 +++- 31 files changed, 576 insertions(+), 465 deletions(-) create mode 100644 port/nulledf.c diff --git a/alphapc/clock.c b/alphapc/clock.c index 346c703fd41cb00fd2f1938d3ba7b9179c588924..7afef9faa7caad94a1694952ba50d5bc17bdb824 100644 --- a/alphapc/clock.c +++ b/alphapc/clock.c @@ -42,7 +42,7 @@ cycletimer(void) return MACHP(0)->fastclock; } -vlong +uvlong fastticks(uvlong* hz) { uvlong ticks; @@ -55,7 +55,12 @@ fastticks(uvlong* hz) if(hz) *hz = m->cpuhz; - return (vlong)ticks; + return ticks; +} + +void +timerset(uvlong) +{ } void @@ -87,7 +92,7 @@ clock(Ureg *ureg) return; count -= 1024; - portclock(ureg); + timerintr(ureg, 0); } ulong diff --git a/alphapc/dat.h b/alphapc/dat.h index b2ca297649e7ae9ee3b90dad3bd74ebf5de4037e..b694d254c041957fb1e8622db7e210b2c315fdad 100644 --- a/alphapc/dat.h +++ b/alphapc/dat.h @@ -1,5 +1,4 @@ typedef struct Conf Conf; -typedef struct Timer Timer; typedef struct FPsave FPsave; typedef struct ISAConf ISAConf; typedef struct Label Label; @@ -248,14 +247,3 @@ struct DevConf int nports; /* Number of ports */ port_t *ports; /* The ports themselves */ }; - -/* - * fasttick timer interrupts (Dummy for now) - */ -struct Timer -{ - vlong when; /* fastticks when f should be called */ - void (*f)(Ureg*, Timer*); - void *a; - Timer *next; -}; diff --git a/alphapc/main.c b/alphapc/main.c index d90e2584606f7e9fa2213b5188d8848e8a8ac0f1..e459bc233afc5483f755ddcb98b2edb299d79b0d 100644 --- a/alphapc/main.c +++ b/alphapc/main.c @@ -91,6 +91,7 @@ main(void) procinit0(); initseg(); + timersinit(); links(); chandevreset(); pageinit(); diff --git a/bitsy/clock.c b/bitsy/clock.c index c1419f9e819c90404411669cd46affc62a62e3c1..a8893d57607166abbffcc863a6cbe5e7f68bf1ce 100644 --- a/bitsy/clock.c +++ b/bitsy/clock.c @@ -78,7 +78,7 @@ clockinit(void) * us at least once a second and we overflow once every 1165 * seconds, we won't miss an overflow. */ -vlong +uvlong fastticks(uvlong *hz) { static uvlong high; diff --git a/bitsy/dat.h b/bitsy/dat.h index 3bcf2090ad6da0e58e65be6437227e921602f57b..03755258b191feca3451c9790795132087e0184b 100644 --- a/bitsy/dat.h +++ b/bitsy/dat.h @@ -16,7 +16,6 @@ typedef struct PCMconftab PCMconftab; typedef struct PhysUart PhysUart; typedef struct PMMU PMMU; typedef struct Proc Proc; -typedef struct Timer Timer; typedef struct Uart Uart; typedef struct Ureg Ureg; typedef struct Vctl Vctl; @@ -262,15 +261,3 @@ struct DevConf ulong interrupt; /* interrupt number */ char *type; /* card type, mallocated */ }; - -/* - * Timer interrupts - */ -struct Timer -{ - uvlong when; /* fastticks when f should be called */ - ulong period; /* non-zero for recurring periodic timers */ - void (*f)(Ureg*, Timer*); /* function to call */ - void *a; /* User parameter */ - Timer *next; -}; diff --git a/mtx/clock.c b/mtx/clock.c index 7024198369d12ab042410b1c3b511edf576a5d9d..41d2f1f3c4c32d452d3901f95ba33735f61ea08f 100644 --- a/mtx/clock.c +++ b/mtx/clock.c @@ -54,13 +54,12 @@ clockintr(Ureg *ureg) } putdec(clkreload-v); - if(m->flushmmu){ - if(up) - flushmmu(); - m->flushmmu = 0; - } + timerintr(ureg, 0); +} - portclock(ureg); +void +timerset(uvlong) +{ } void @@ -88,7 +87,7 @@ microdelay(int l) ; } -vlong +uvlong fastticks(uvlong *hz) { if(hz) diff --git a/mtx/dat.h b/mtx/dat.h index e0aab824b69ea107eacd2969ab07a6ca1c6d53b5..20566057bd66d4587abab46873b6e31eee3c356c 100644 --- a/mtx/dat.h +++ b/mtx/dat.h @@ -1,5 +1,4 @@ typedef struct Conf Conf; -typedef struct Timer Timer; typedef struct FPsave FPsave; typedef struct ISAConf ISAConf; typedef struct Label Label; @@ -192,16 +191,6 @@ struct ISAConf { int nopt; char *opt[NISAOPT]; }; -/* - * fasttick timer interrupts (Dummy for now) - */ -struct Timer -{ - vlong when; /* fastticks when f should be called */ - void (*f)(Ureg*, Timer*); - void *a; - Timer *next; -}; #define MACHP(n) ((Mach *)((int)&mach0+n*BY2PG)) extern Mach mach0; diff --git a/mtx/main.c b/mtx/main.c index 4d0c04405bdd3c21957278d3af00a9b512fc7e26..a9d3dd6122a397886ca8378a0f317325f3edd70e 100644 --- a/mtx/main.c +++ b/mtx/main.c @@ -32,6 +32,7 @@ main(void) kbdinit(); procinit0(); initseg(); + timersinit(); links(); chandevreset(); pageinit(); diff --git a/pc/apic.c b/pc/apic.c index 0889d5b696ef7e2df6cdb61b145549a65a5558e5..894935f7efa937d62817d72212b006f68bf90e64 100644 --- a/pc/apic.c +++ b/pc/apic.c @@ -88,7 +88,14 @@ enum { /* LapicTDCR */ }; static ulong* lapicbase; -static int clkin; + +struct +{ + uvlong hz; + ulong max; + ulong min; + ulong mult; /* factor to mutiply fast ticks by to get lapicticks<<16 */ +} lapictimer; static int lapicr(int r) @@ -113,32 +120,36 @@ lapiconline(void) * accepted by the APIC. */ microdelay((TK2MS(1)*1000/conf.nmach) * m->machno); - lapicw(LapicTICR, clkin/HZ); + lapicw(LapicTICR, lapictimer.max); lapicw(LapicTIMER, LapicCLKIN|LapicPERIODIC|(VectorPIC+IrqTIMER)); lapicw(LapicTPR, 0); } +/* + * use the i8253 clock to figure out our lapic timer rate. + */ static void lapictimerinit(void) { - ulong lo, v; - vlong tsc; + uvlong x, v, hz; v = m->cpuhz/1000; lapicw(LapicTDCR, LapicX1); lapicw(LapicTIMER, ApicIMASK|LapicCLKIN|LapicONESHOT|(VectorPIC+IrqTIMER)); - if(clkin == 0){ - lapicw(LapicTICR, v); - wrmsr(0x10, 0); - + if(lapictimer.hz == 0ULL){ + x = fastticks(&hz); + x += hz/10; + lapicw(LapicTICR, 0xffffffff); do{ - rdtsc(&tsc); - lo = (ulong)tsc; - }while(lo < v); + v = fastticks(nil); + }while(v < x); - clkin = ((v-lapicr(LapicTCCR)+500)/1000)*1000*1000; + lapictimer.hz = (0xffffffffUL-lapicr(LapicTCCR))*10; + lapictimer.max = lapictimer.hz/HZ; + lapictimer.min = lapictimer.hz/(100*HZ); + lapictimer.mult = (lapictimer.hz<<16)/hz; } } @@ -331,3 +342,38 @@ ioapicinit(Apic* apic, int apicno) for(v = 0; v <= apic->mre; v++) ioapicrdtw(apic, v, hi, lo); } + +ulong lapicperiodset[32]; + +void +lapictimerset(uvlong next) +{ + ulong period; + int x; + + x = splhi(); + lock(&m->apictimerlock); + period = lapictimer.max; + if(next != 0){ + period = next - fastticks(nil); + period *= lapictimer.mult; + period >>= 16; + + if(period < lapictimer.min) + period = lapictimer.min; + else if(period > lapictimer.max - lapictimer.min) + period = lapictimer.max; + } + + lapicw(LapicTICR, period); + lapicperiodset[m->machno]++; + + unlock(&m->apictimerlock); + splx(x); +} + +void +lapicclock(Ureg *u, void*) +{ + timerintr(u, 0); +} diff --git a/pc/archmp.c b/pc/archmp.c index 99d5160a2dec6711f746c2b2cebb0f786acdcf74..1d06f56d42b51e4945d359093331b67b98bc70a8 100644 --- a/pc/archmp.c +++ b/pc/archmp.c @@ -90,17 +90,11 @@ identify(void) } PCArch archmp = { - "_MP_", /* id */ - identify, /* ident */ - mpshutdown, /* reset */ - 0, /* serialpower */ - 0, /* modempower */ - - mpinit, /* intrinit */ - mpintrenable, /* intrenable */ - 0, /* intrvecno */ - 0, /* intrdisable */ - - 0, /* clockenable */ - i8253read, /* fastclock */ +.id= "_MP_", +.ident= identify, +.reset= mpshutdown, +.intrinit= mpinit, +.intrenable= mpintrenable, +.fastclock= i8253read, +.timerset= lapictimerset, }; diff --git a/pc/dat.h b/pc/dat.h index f9905585c31ca44c833fa7d4b9d55cbe19fdb69f..33154eae2afaa4be9232120393e4155265128e64 100644 --- a/pc/dat.h +++ b/pc/dat.h @@ -1,5 +1,4 @@ typedef struct Conf Conf; -typedef struct Timer Timer; typedef struct FPsave FPsave; typedef struct ISAConf ISAConf; typedef struct Label Label; @@ -184,6 +183,7 @@ struct Mach int loopconst; + Lock apictimerlock; int cpumhz; vlong cpuhz; int cpuidax; @@ -191,7 +191,6 @@ struct Mach char cpuidid[16]; char* cpuidtype; int havetsc; - vlong lasttsc; /* last sampled value */ vlong mtrrcap; vlong mtrrdef; @@ -201,17 +200,6 @@ struct Mach int stack[1]; }; -/* - * fasttick timer interrupts - */ -struct Timer -{ - vlong when; /* fastticks when f should be called */ - void (*f)(Ureg*, Timer*); - void *a; - Timer *next; -}; - /* * Fake kmap */ @@ -246,6 +234,7 @@ struct PCArch void (*clockenable)(void); uvlong (*fastclock)(uvlong*); + void (*timerset)(uvlong); }; /* diff --git a/pc/devarch.c b/pc/devarch.c index f652e5293c4fa1b2391f0c30844dabfba61891e4..90c5ae19c0c61bec96b8058ef803abe336ba1c61 100644 --- a/pc/devarch.c +++ b/pc/devarch.c @@ -508,6 +508,7 @@ PCArch archgeneric = { i8253enable, /* clockenable */ i8253read, /* read the standard timer */ + i8253timerset, }; typedef struct { @@ -681,6 +682,12 @@ cpuidentify(void) rdmsr(0x01, &mct); } + if(t->family >= 6){ + cr4 = getcr4(); + cr4 |= 0x80; /* page global enable bit */ + putcr4(cr4); + } + cputype = t; return t->family; } @@ -724,8 +731,6 @@ archinit(void) arch->intrinit = archgeneric.intrinit; if(arch->intrenable == 0) arch->intrenable = archgeneric.intrenable; - if(arch->intrenable == 0) - arch->intrenable = archgeneric.intrenable; } /* @@ -758,3 +763,21 @@ pcmspecialclose(int a) if (_pcmspecialclose != nil) _pcmspecialclose(a); } + +/* + * return value and speed of timer set in arch->clockenable + */ +uvlong +fastticks(uvlong *hz) +{ + return (*arch->fastclock)(hz); +} + +/* + * set next timer interrupt + */ +void +timerset(uvlong x) +{ + (*arch->timerset)(x); +} diff --git a/pc/fns.h b/pc/fns.h index 3b9245d35734b4c9aa8ea9b91cf2fc0b1a440825..e8353a6b80b89007aa7512650a64d48a1140a269 100644 --- a/pc/fns.h +++ b/pc/fns.h @@ -6,7 +6,6 @@ Dirtab* addarchfile(char*, int, long(*)(Chan*,void*,long,vlong), long(*)(Chan*,v void apicclkenable(void); void archinit(void); void bootargs(ulong); -vlong checktimer(Ureg*, void*); int cistrcmp(char*, char*); int cistrncmp(char*, char*, int); #define clearmmucache() /* x86 doesn't have one */ @@ -16,10 +15,6 @@ void (*coherence)(void); void cpuid(char*, int*, int*); int cpuidentify(void); void cpuidprint(void); -void timeradd(Timer*); -void timerdel(Timer*); -void timerset(vlong); -vlong timernext(void); void delay(int); int dmacount(int); int dmadone(int); @@ -40,7 +35,6 @@ ulong getcr4(void); char* getconf(char*); void guesscpuhz(int); void halt(void); -int havetimer(void); int i8042auxcmd(int); void i8042auxenable(void (*)(int, int)); void i8042reset(void); @@ -48,6 +42,7 @@ void i8250console(void); void* i8250alloc(int, int, int); void i8253init(void); void i8253enable(void); +void i8253timerset(uvlong); uvlong i8253read(uvlong*); void i8259init(void); int i8259isr(int); @@ -73,6 +68,8 @@ int iprint(char*, ...); int isaconfig(char*, int, ISAConf*); void kbdinit(void); #define kmapinval() +void lapicclock(Ureg*, void*); +void lapictimerset(uvlong); void lgdt(ushort[3]); void lidt(ushort[3]); void links(void); diff --git a/pc/i8253.c b/pc/i8253.c index bb40090d7e238a81668fb67cc0c6f636fbc6797d..d5182aaef6b9f7b2f414fc27ff71e1087b910d0f 100644 --- a/pc/i8253.c +++ b/pc/i8253.c @@ -46,38 +46,29 @@ enum Trigger=0x0, /* interrupt on terminal count */ Sstrobe=0x8, /* software triggered strobe */ - /* counter 2 controls */ - C2gate= 0x1, - C2speak=0x2, - C2out= 0x10, - /* T2ctl bits */ T2gate= (1<<0), /* enable T2 counting */ T2spkr= (1<<1), /* connect T2 out to speaker */ T2out= (1<<5), /* output of T2 */ Freq= 1193182, /* Real clock frequency */ - Tickshift= 8, /* increase tick wriggle room */ - - Minusec=20, /* minimum cycles for a clock interrupt */ - - FreqMul=16, /* extra accuracy in fastticks/Freq calculation; ok up to ~8ghz */ + Tickshift=8, /* extra accuracy */ + MaxPeriod=Freq/HZ, + MinPeriod=Freq/(100*HZ), }; static struct { Lock; + ulong period; /* current clock period */ int enabled; - int mode; - vlong when; /* next fastticks a clock interrupt should occur */ - vlong timerwhen; /* next fastticks a cycintr happens; 0 == infinity */ - long fastperiod; /* fastticks/hz */ - long fast2freq; /* fastticks*FreqMul/Freq */ + uvlong hz; ushort last; /* last value of clock 1 */ uvlong ticks; /* cumulative ticks of counter 1 */ }i8253; + void i8253init(void) { @@ -87,12 +78,12 @@ i8253init(void) ioalloc(T2ctl, 1, 0, "i8253.cntr2ctl"); /* - * set interrupting clock for 1/HZ seconds + * enable a 1/HZ interrupt for providing scheduling interrupts */ outb(Tmode, Load0|Square); - i8253.mode = Square; outb(T0cntr, (Freq/HZ)); /* low byte */ outb(T0cntr, (Freq/HZ)>>8); /* high byte */ + i8253.period = Freq/HZ; /* * enable a longer period counter to use as a clock @@ -100,10 +91,11 @@ i8253init(void) outb(Tmode, Load2|Square); outb(T2cntr, 0); /* low byte */ outb(T2cntr, 0); /* high byte */ + i8253.period = Freq/HZ; x = inb(T2ctl); x |= T2gate; outb(T2ctl, x); - + /* * Introduce a little delay to make sure the count is * latched and the timer is counting down; with a fast @@ -189,97 +181,58 @@ guesscpuhz(int aalcycles) m->cpumhz = (cpufreq + cpufreq/200)/1000000; m->cpuhz = cpufreq; } -} -/* - * schedule the next interrupt - * timerwhen is the time of the next interrupt - */ -static void -clockintrsched0(vlong next) -{ - vlong now; - long set; - - i8253.timerwhen = next; - if(i8253.mode == Square && next == 0) - return; - - now = fastticks(nil); - if(next || now < i8253.when - i8253.fastperiod || now > i8253.when - ((3*i8253.fastperiod)>>2)){ - if(next > i8253.when) - next = i8253.when; - set = (long)(next - now) * FreqMul / i8253.fast2freq; - set -= 3; /* three cycles for the count to take effect: outb, outb, wait */ - if(i8253.mode != Trigger){ - outb(Tmode, Load0|Trigger); - i8253.mode = Trigger; - set--; - } - if(set < Minusec) - set = Minusec; - outb(T0cntr, set); /* low byte */ - outb(T0cntr, set>>8); /* high byte */ - }else if(i8253.mode != Square){ - i8253.mode = Square; - outb(Tmode, Load0|Square); - outb(T0cntr, (Freq/HZ)); /* low byte */ - outb(T0cntr, (Freq/HZ)>>8); /* high byte */ - } + i8253.hz = Freq<>Tickshift; + now = i8253.ticks; /* assuming whomever called us just did fastticks() */ + + period = MaxPeriod; + if(next != 0){ + period = want - now; + if(period < MinPeriod) + period = MinPeriod; + else if(period > (4*MaxPeriod)/5) /* strong attraction to MaxPeriod */ + period = MaxPeriod; + } - ilock(&i8253); - if(i8253.enabled){ - next = timernext(); - if(next != i8253.timerwhen) - clockintrsched0(next); + /* histeresis */ + if(i8253.period != period){ + ilock(&i8253); + /* load new value */ + outb(Tmode, Load0|Square); + outb(T0cntr, period); /* low byte */ + outb(T0cntr, period>>8); /* high byte */ + + /* remember period */ + i8253.period = period; + i8253periodset++; + iunlock(&i8253); } - iunlock(&i8253); } static void -clockintr0(Ureg* ureg, void *v) +i8253clock(Ureg* ureg, void*) { - vlong now, when; - - /* goes with syncing in squidboy */ - if(m->havetsc) - rdtsc(&m->lasttsc); - - now = fastticks(nil); - when = i8253.when; - - if(now >= i8253.when){ - clockintr(ureg, v); - do - i8253.when += i8253.fastperiod; - while(i8253.when < now); - } - if(i8253.timerwhen || i8253.mode != Square) - clockintrsched0(checktimer(ureg, v)); + timerintr(ureg, 0); } void i8253enable(void) { - uvlong hz; - - i8253.when = fastticks(&hz); - i8253.fastperiod = (hz + HZ/2) / HZ; - i8253.fast2freq = (hz * FreqMul) / Freq; i8253.enabled = 1; - intrenable(IrqCLOCK, clockintr0, 0, BUSUNKNOWN, "clock"); + i8253.period = Freq/HZ; + intrenable(IrqCLOCK, i8253clock, 0, BUSUNKNOWN, "clock"); } /* @@ -294,7 +247,7 @@ i8253read(uvlong *hz) uvlong ticks; if(hz) - *hz = Freq<>1; ticks = i8253.ticks; @@ -313,11 +266,34 @@ i8253read(uvlong *hz) return ticks<clockenable - */ -vlong -fastticks(uvlong *hz) +void +delay(int millisecs) +{ + millisecs *= m->loopconst; + if(millisecs <= 0) + millisecs = 1; + aamloop(millisecs); +} + +void +microdelay(int microsecs) +{ + microsecs *= m->loopconst; + microsecs /= 1000; + if(microsecs <= 0) + microsecs = 1; + aamloop(microsecs); +} + +ulong +TK2MS(ulong ticks) { - return (*arch->fastclock)(hz); + uvlong t, hz; + + t = ticks; + hz = HZ; + t *= 1000L; + t = t/hz; + ticks = t; + return ticks; } diff --git a/pc/main.c b/pc/main.c index 263608116b4245cd986a2deb3ce8c19ecaf871f9..1e700f9d53c083f0bdd438113c6c7b6f2ca73293 100644 --- a/pc/main.c +++ b/pc/main.c @@ -30,6 +30,7 @@ char *confval[MAXCONF]; int nconf; uchar *sp; /* user stack of init proc */ + static void options(void) { @@ -93,6 +94,7 @@ main(void) mmuinit(); if(arch->intrinit) arch->intrinit(); + timersinit(); mathinit(); kbdinit(); if(arch->clockenable) diff --git a/pc/mem.h b/pc/mem.h index 99d97a72f4105dbd81353402fec089df6685824a..0f7ec98bbc2977922c37993751edcab1aa36caaf 100644 --- a/pc/mem.h +++ b/pc/mem.h @@ -125,6 +125,7 @@ #define PTEKERNEL (0<<2) #define PTEUSER (1<<2) #define PTESIZE (1<<7) +#define PTEGLOBAL (1<<8) /* * Macros for calculating offsets within the page directory base diff --git a/pc/mp.c b/pc/mp.c index 0178e8edd8b41db143e0604d6367a1c82e826dd6..561111c340941cb616bc5dec9a891ee35f86e323 100644 --- a/pc/mp.c +++ b/pc/mp.c @@ -19,7 +19,6 @@ static int machno2apicno[MaxAPICNO+1]; /* inverse map: machno -> APIC ID */ static Lock mprdthilock; static int mprdthi; static Ref mpvnoref; /* unique vector assignment */ -static Lock mpclocksynclock; static char* buses[] = { "CBUSI ", @@ -43,41 +42,6 @@ static char* buses[] = { 0, }; -void -apicclkenable(void) -{ - Apic *apic; - - /* Uniprocessor local apic init for apic clock */ - apic = &mpapic[0]; - apic->type = PcmpPROCESSOR; - apic->apicno = 0; - apic->flags = 0; - apic->lintr[0] = ApicIMASK; - apic->lintr[1] = ApicIMASK; - apic->machno = 0; - apic->addr = (ulong*)0xfee00000; - machno2apicno[0] = 0; - - /* - * Map the local APIC. - */ - if(mmukmap((ulong)apic->addr, 0, 1024) == 0) - return; - - /* - * These interrupts are local to the processor - * and do not appear in the I/O APIC so it is OK - * to set them now. - */ - intrenable(IrqTIMER, clockintr, 0, BUSUNKNOWN, "clock"); - intrenable(IrqERROR, lapicerror, 0, BUSUNKNOWN, "lapicerror"); - intrenable(IrqSPURIOUS, lapicspurious, 0, BUSUNKNOWN, "lapicspurious"); - - lapicinit(apic); - lapiconline(); -} - static Apic* mkprocessor(PCMPprocessor* p) { @@ -386,8 +350,6 @@ checkmtrr(void) static void squidboy(Apic* apic) { - ulong x; - // iprint("Hello Squidboy\n"); machinit(); @@ -401,19 +363,9 @@ squidboy(Apic* apic) mprdthi |= (1<apicno)<<24; unlock(&mprdthilock); - if(m->havetsc){ - /* - * Restrain your octopus! Don't let it go out on the sea! - */ - ilock(&mpclocksynclock); - x = MACHP(0)->ticks; - while(MACHP(0)->ticks == x) - ; - wrmsr(0x10, MACHP(0)->lasttsc); /* synchronize fast counters */ - iunlock(&mpclocksynclock); - } lapicinit(apic); lapiconline(); + timersinit(); lock(&active); active.machs |= 1<machno; @@ -587,7 +539,7 @@ mpinit(void) * and do not appear in the I/O APIC so it is OK * to set them now. */ - intrenable(IrqTIMER, clockintr, 0, BUSUNKNOWN, "clock"); + intrenable(IrqTIMER, lapicclock, 0, BUSUNKNOWN, "clock"); intrenable(IrqERROR, lapicerror, 0, BUSUNKNOWN, "lapicerror"); intrenable(IrqSPURIOUS, lapicspurious, 0, BUSUNKNOWN, "lapicspurious"); lapiconline(); diff --git a/port/auth.c b/port/auth.c index 12aef48468e503279ce98526177ed72ea6a5a0fb..bb1cf88d514ff3032ae036629712e31e175cd570 100644 --- a/port/auth.c +++ b/port/auth.c @@ -100,7 +100,7 @@ sysfauth(ulong *arg) long userwrite(char *a, int n) { - if(strcmp(a, "none") != 0) + if(n!=4 || strncmp(a, "none", 4)!=0) error(Eperm); kstrdup(&up->user, "none"); up->basepri = PriNormal; diff --git a/port/devcons.c b/port/devcons.c index 88ed1c6ddc22b81d973a3993379b7b5b82fcb09b..57f169a2afe2df776612ee7553df8e6b0dedf870 100644 --- a/port/devcons.c +++ b/port/devcons.c @@ -384,14 +384,6 @@ echo(char *buf, int n) case 'q': scheddump(); return; -#ifdef RSC -case 'Q': -{ -extern void dumpschedlog(void); -dumpschedlog(); -return; -} -#endif case 'k': if(!cpuserver) killbig(); diff --git a/port/devloopback.c b/port/devloopback.c index b881f78efd5ba88d0027da07d676bbf1295cc9b9..8322e9b6ea399194eb78e09fe12e701dc4ba3fdf 100644 --- a/port/devloopback.c +++ b/port/devloopback.c @@ -129,9 +129,6 @@ loopbackattach(char *spec) int chan; int dev; - if(!havetimer()) - error("can't time packets"); - dev = 0; if(spec != nil){ dev = atoi(spec); diff --git a/port/devrealtime.c b/port/devrealtime.c index ea987715092f66e75fa4e31367c4459d5b8eb852..830955ba694681be0b44372b166e544209dbb740 100644 --- a/port/devrealtime.c +++ b/port/devrealtime.c @@ -76,7 +76,7 @@ dumptask(char *p, char *e, Task *t, Ticks now) char c; p = seprint(p, e, "{%s, D%U, Δ%U,T%U, C%U, S%U", - edf_statename[t->state], t->D, t->Delta, t->T, t->C, t->S); + edfstatename[t->state], t->D, t->Delta, t->T, t->C, t->S); n = t->r - now; if (n >= 0) c = ' '; @@ -224,16 +224,12 @@ devrtinit(void) static Chan * devrtattach(char *param) { - if(havetimer() == 0) - error("no edf on multiprocessors"); return devattach('R', param); } static Walkqid * devrtwalk(Chan *c, Chan *nc, char **name, int nname) { - if (havetimer() == 0) - error("no edf on multiprocessors"); return devwalk(c, nc, name, nname, nil, 0, schedgen); } @@ -267,8 +263,6 @@ devrtopen(Chan *c, int mode) { Task *t; - if (havetimer() == 0) - error("no edf on multiprocessors"); switch ((ulong)c->qid.path){ case Qlog: case Qnblog: @@ -292,7 +286,7 @@ devrtopen(Chan *c, int mode) case Qclone: if (mode == OREAD) error(Eperm); - edf_init(); + edfinit(); /* open a new task */ for (t = tasks; t< tasks + Maxtasks; t++){ qlock(t); @@ -465,7 +459,7 @@ devrtread(Chan *c, void *v, long n, vlong offs) p = buf; e = p + sizeof(buf); p = seprint(p, e, "task=%d", s); - p = seprint(p, e, " state=%s", edf_statename[t->state]); + p = seprint(p, e, " state=%s", edfstatename[t->state]); if (t->T) p = seprint(p, e, " T=%T", ticks2time(t->T)); if (t->D) @@ -634,7 +628,7 @@ removetask(Task *t) Resource *r; qlock(t); - edf_expel(t); + edfexpel(t); for (pp = t->procs; pp < t->procs + nelem(t->procs); pp++) if (p = *pp) p->task = nil; @@ -720,7 +714,7 @@ devrtwrite(Chan *c, void *va, long n, vlong) if (e=parsetime(&time, v)) error(e); ticks = time2ticks(time); - edf_expel(t); + edfexpel(t); switch(add){ case -1: if (ticks > t->T) @@ -739,7 +733,7 @@ devrtwrite(Chan *c, void *va, long n, vlong) if (e=parsetime(&time, v)) error(e); ticks = time2ticks(time); - edf_expel(t); + edfexpel(t); switch(add){ case -1: if (ticks > t->D) @@ -758,7 +752,7 @@ devrtwrite(Chan *c, void *va, long n, vlong) if (e=parsetime(&time, v)) error(e); ticks = time2ticks(time); - edf_expel(t); + edfexpel(t); switch(add){ case -1: if (ticks > t->C) @@ -776,7 +770,7 @@ devrtwrite(Chan *c, void *va, long n, vlong) }else if (strcmp(a, "resources") == 0){ if (v == nil) error("resources: value missing"); - edf_expel(t); + edfexpel(t); if (add == 0){ for (rp = t->res; rp < t->res + nelem(t->res); rp++) if (*rp){ @@ -801,7 +795,7 @@ devrtwrite(Chan *c, void *va, long n, vlong) if (v == nil) error("procs: value missing"); if (add <= 0){ - edf_expel(t); + edfexpel(t); } if (add == 0){ for (pp = t->procs; pp < t->procs + nelem(t->procs); pp++) @@ -828,11 +822,11 @@ devrtwrite(Chan *c, void *va, long n, vlong) } }else if (strcmp(a, "admit") == 0){ /* Do the admission test */ - if (e = edf_admit(t)) + if (e = edfadmit(t)) error(e); }else if (strcmp(a, "expel") == 0){ /* Do the admission test */ - edf_expel(t); + edfexpel(t); }else if (strcmp(a, "remove") == 0){ /* Do the admission test */ removetask(t); @@ -854,7 +848,7 @@ devrtwrite(Chan *c, void *va, long n, vlong) t->flags |= Useblocking; }else if (strcmp(a, "yield") == 0){ if (isedf(up) && up->task == t){ - edf_deadline(up); /* schedule next release */ + edfdeadline(up); /* schedule next release */ sched(); }else error("yield outside task"); diff --git a/port/edf.c b/port/edf.c index bfec571feecbabddfe04e5aef464329b6d300776..dbd603283818be72529ee8cc811b8881b0a48f49 100644 --- a/port/edf.c +++ b/port/edf.c @@ -12,7 +12,7 @@ int edfprint = 0; #define DPRINT if(edfprint)iprint -char *edf_statename[] = { +char *edfstatename[] = { [EdfUnused] = "Unused", [EdfExpelled] = "Expelled", [EdfAdmitted] = "Admitted", @@ -26,8 +26,8 @@ char *edf_statename[] = { [EdfDeadline] = "Deadline", }; -static Timer cycdeadline; /* Time of next deadline */ -static Timer cycrelease; /* Time of next release */ +static Timer deadlinetimer[MAXMACH]; /* Time of next deadline */ +static Timer releasetimer[MAXMACH]; /* Time of next release */ static int initialized; static uvlong fasthz; @@ -39,7 +39,7 @@ Task tasks[Maxtasks]; int ntasks; Resource resources[Maxresources]; int nresources; -int edf_stateupdate; +int edfstateupdate; enum{ Deadline, /* Invariant for schedulability test: Deadline < Release */ @@ -58,24 +58,23 @@ Taskq qreleased = {{0}, nil, earlierdeadline}; /* Exhausted EDF tasks, append at end */ Taskq qextratime; -/* Tasks admitted waiting for first release */ -Taskq qadmit; - /* Running/Preempted EDF tasks, head running, one stack per processor */ Taskq edfstack[MAXMACH]; void (*devrt)(Task*, Ticks, int); -static void edf_resched(Task *t); +static void edfresched(Task *t); static void setdelta(void); static void testdelta(Task *thetask); -static char * edf_testschedulability(Task *thetask); static void edfreleaseintr(Ureg *, Timer *cy); static void edfdeadlineintr(Ureg*, Timer*); +static char * edftestschedulability(Task *thetask); void -edf_init(void) +edfinit(void) { + int i; + if (initialized) return; ilock(&edflock); @@ -84,12 +83,14 @@ edf_init(void) return; } fastticks(&fasthz); - cycdeadline.f = edfdeadlineintr; - cycdeadline.a = &cycdeadline; - cycdeadline.when = 0; - cycrelease.f = edfreleaseintr; - cycrelease.a = &cycrelease; - cycrelease.when = 0; + for (i = 0; i < conf.nmach; i++){ + deadlinetimer[i].f = edfdeadlineintr; + deadlinetimer[i].a = &deadlinetimer[i]; + deadlinetimer[i].when = 0; + releasetimer[i].f = edfreleaseintr; + releasetimer[i].a = &releasetimer[i]; + releasetimer[i].when = 0; + } initialized = 1; iunlock(&edflock); } @@ -101,7 +102,7 @@ isedf(Proc *p) } int -edf_anyready(void) +edfanyready(void) { /* If any edf tasks (with runnable procs in them) are released, * at least one of them must be on the stack @@ -114,7 +115,7 @@ edfpush(Task *t) { Taskq *q; - DPRINT("%d edfpush, %s, %d\n", m->machno, edf_statename[t->state], t->runq.n); + DPRINT("%d edfpush, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n); q = edfstack + m->machno; assert(t->runq.n || (up && up->task == t)); if (q->head){ @@ -153,7 +154,7 @@ edfenqueue(Taskq *q, Task *t) { Task *tt, **ttp; - DPRINT("%d edfenqueue, %s, %d\n", m->machno, edf_statename[t->state], t->runq.n); + DPRINT("%d edfenqueue, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n); t->rnext = nil; if (q->head == nil) { q->head = t; @@ -193,7 +194,7 @@ edfqremove(Taskq *q, Task *t) { Task **tp; - DPRINT("%d edfqremove, %s, %d\n", m->machno, edf_statename[t->state], t->runq.n); + DPRINT("%d edfqremove, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n); for (tp = &q->head; *tp; tp = &(*tp)->rnext){ if (*tp == t){ *tp = t->rnext; @@ -213,17 +214,16 @@ edfreleasetimer(void) if ((t = qwaitrelease.head) == nil) return; DPRINT("edfreleasetimer clock\n"); - if (cycrelease.when) - timerdel(&cycrelease); - cycrelease.when = t->r; - if (cycrelease.when <= now) - cycrelease.when = now; - timeradd(&cycrelease); - clockintrsched(); + if (releasetimer[m->machno].when) + timerdel(&releasetimer[m->machno]); + releasetimer[m->machno].when = t->r; + if (releasetimer[m->machno].when <= now) + releasetimer[m->machno].when = now; + timeradd(&releasetimer[m->machno]); } void -edf_block(Proc *p) +edfblock(Proc *p) { Task *t, *pt; @@ -236,7 +236,7 @@ edf_block(Proc *p) iunlock(&edflock); return; } - DPRINT("%d edf_block, %s, %d\n", m->machno, edf_statename[t->state], t->runq.n); + DPRINT("%d edfblock, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n); if (t->runq.n){ /* There's another runnable proc in the running task, leave task where it is */ @@ -251,12 +251,12 @@ edf_block(Proc *p) } static void -edfdeadline(Proc *p, SEvent why) +deadline(Proc *p, SEvent why) { Task *t, *nt; /* Task has reached its deadline, lock must be held */ - DPRINT("%d edfdeadline, %s, %d\n", m->machno, edf_statename[p->task->state], p->task->runq.n); + DPRINT("%d deadline, %s, %d\n", m->machno, edfstatename[p->task->state], p->task->runq.n); SET(nt); if (p){ nt = p->task; @@ -266,34 +266,33 @@ edfdeadline(Proc *p, SEvent why) t = edfpop(); if(p != nil && nt != t){ - iprint("edfdeadline, %s, %d\n", edf_statename[p->task->state], p->task->runq.n); + iprint("deadline, %s, %d\n", edfstatename[p->task->state], p->task->runq.n); iunlock(&edflock); assert(0 && p == nil || nt == t); } - if (cycdeadline.when){ - timerdel(&cycdeadline); - cycdeadline.when = 0; - clockintrsched(); + if (deadlinetimer[m->machno].when){ + timerdel(&deadlinetimer[m->machno]); + deadlinetimer[m->machno].when = 0; } t->d = now; t->state = EdfDeadline; if(devrt) devrt(t, now, why); - edf_resched(t); + edfresched(t); } void -edf_deadline(Proc *p) +edfdeadline(Proc *p) { - DPRINT("%d edf_deadline\n", m->machno); + DPRINT("%d edfdeadline\n", m->machno); /* Task has reached its deadline */ ilock(&edflock); now = fastticks(nil); - edfdeadline(p, SYield); + deadline(p, SYield); iunlock(&edflock); } char * -edf_admit(Task *t) +edfadmit(Task *t) { char *err; @@ -313,18 +312,18 @@ edf_admit(Task *t) return "C > D"; qlock(&edfschedlock); - if (err = edf_testschedulability(t)){ + if (err = edftestschedulability(t)){ qunlock(&edfschedlock); return err; } ilock(&edflock); - DPRINT("%d edf_admit, %s, %d\n", m->machno, edf_statename[t->state], t->runq.n); + DPRINT("%d edfadmit, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n); now = fastticks(nil); t->state = EdfAdmitted; if(devrt) devrt(t, t->d, SAdmit); if (up->task == t){ - DPRINT("%d edf_admitting self\n", m->machno); + DPRINT("%d edfadmitting self\n", m->machno); /* Admitting self, fake reaching deadline */ t->r = now; t->t = now + t->T; @@ -337,16 +336,18 @@ edf_admit(Task *t) setdelta(); assert(t->runq.n > 0 || (up && up->task == t)); edfpush(t); + if (deadlinetimer[m->machno].when) + timerdel(&deadlinetimer[m->machno]); + deadlinetimer[m->machno].when = t->d; + timeradd(&deadlinetimer[m->machno]); }else{ if (t->runq.n){ if (edfstack[m->machno].head == nil){ t->state = EdfAdmitted; t->r = now; - edf_release(t); + edfrelease(t); setdelta(); - edf_resched(t); - }else{ - edfenqueue(&qadmit, t); + edfresched(t); } } } @@ -356,13 +357,13 @@ edf_admit(Task *t) } void -edf_expel(Task *t) +edfexpel(Task *t) { Task *tt; qlock(&edfschedlock); ilock(&edflock); - DPRINT("%d edf_expel, %s, %d\n", m->machno, edf_statename[t->state], t->runq.n); + DPRINT("%d edfexpel, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n); now = fastticks(nil); switch(t->state){ case EdfUnused: @@ -412,9 +413,8 @@ edfreleaseintr(Ureg*, Timer*) DPRINT("%d edfreleaseintr\n", m->machno); - timerdel(&cycrelease); - cycrelease.when = 0; - clockintrsched(); + timerdel(&releasetimer[m->machno]); + releasetimer[m->machno].when = 0; if(active.exiting) return; @@ -425,7 +425,7 @@ edfreleaseintr(Ureg*, Timer*) /* There's something waiting to be released and its time has come */ edfdequeue(&qwaitrelease); edfreleasetimer(); - edf_release(t); + edfrelease(t); } iunlock(&edflock); sched(); @@ -442,9 +442,8 @@ edfdeadlineintr(Ureg*, Timer*) DPRINT("%d edfdeadlineintr\n", m->machno); - timerdel(&cycdeadline); - cycdeadline.when = 0; - clockintrsched(); + timerdel(&deadlinetimer[m->machno]); + deadlinetimer[m->machno].when = 0; if(active.exiting) return; @@ -469,11 +468,11 @@ edfdeadlineintr(Ureg*, Timer*) if (t->d <= now || t->S == 0LL){ /* Task has reached its deadline/slice, remove from queue */ - edfdeadline(up, SSlice); + deadline(up, SSlice); while (t = edfstack[m->machno].head){ if (now < t->d) break; - edfdeadline(nil, SSlice); + deadline(nil, SSlice); } } } @@ -484,12 +483,12 @@ edfdeadlineintr(Ureg*, Timer*) } void -edf_bury(Proc *p) +edfbury(Proc *p) { Task *t; Proc **pp; - DPRINT("%d edf_bury\n", m->machno); + DPRINT("%d edfbury\n", m->machno); ilock(&edflock); now = fastticks(nil); if ((t = p->task) == nil){ @@ -518,12 +517,12 @@ edf_bury(Proc *p) } void -edf_ready(Proc *p) +edfready(Proc *p) { Task *t; ilock(&edflock); - DPRINT("%d edf_ready, %s, %d\n", m->machno, edf_statename[p->task->state], p->task->runq.n); + DPRINT("%d edfready, %s, %d\n", m->machno, edfstatename[p->task->state], p->task->runq.n); if ((t = p->task) == nil){ /* Must be a race */ iunlock(&edflock); @@ -543,17 +542,17 @@ edf_ready(Proc *p) /* first proc to become runnable in this task */ now = fastticks(nil); - edf_resched(t); + edfresched(t); } iunlock(&edflock); } static void -edf_resched(Task *t) +edfresched(Task *t) { Task *xt; - DPRINT("%d edf_resched, %s, %d\n", m->machno, edf_statename[t->state], t->runq.n); + DPRINT("%d edfresched, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n); if (t->nproc == 0){ /* No member processes */ if (t->state > EdfIdle){ @@ -564,7 +563,7 @@ edf_resched(Task *t) } if (t->runq.n == 0 && (up == nil || up->task != t)){ /* Member processes but none runnable */ - DPRINT("%d edf_resched, nothing runnable\n", m->machno); + DPRINT("%d edfresched, nothing runnable\n", m->machno); if (t->state == EdfRunning) edfpop(); @@ -589,7 +588,7 @@ edf_resched(Task *t) t->t = now + t->T; t->r = t->t; } - edf_release(t); + edfrelease(t); break; case EdfAwaitrelease: case EdfReleased: @@ -606,17 +605,17 @@ edf_resched(Task *t) case EdfRunning: if (t->r <= now){ if (t->t < now){ - DPRINT("%d edf_resched, rerelease\n", m->machno); + DPRINT("%d edfresched, rerelease\n", m->machno); /* Period passed, rerelease */ t->r = now; xt = edfpop(); assert(xt == t); - edf_release(t); + edfrelease(t); return; } if (now < t->d){ if (t->S > 0){ - DPRINT("%d edf_resched, resume\n", m->machno); + DPRINT("%d edfresched, resume\n", m->machno); /* Running, not yet at deadline, leave it */ return; }else @@ -635,15 +634,15 @@ edf_resched(Task *t) case EdfDeadline: if (t->r <= now){ if (t->t < now){ - DPRINT("%d edf_resched, rerelease\n", m->machno); + DPRINT("%d edfresched, rerelease\n", m->machno); /* Period passed, rerelease */ t->r = now; - edf_release(t); + edfrelease(t); return; } if (now < t->d && (t->flags & Useblocking) == 0){ if (t->S > 0){ - DPRINT("%d edf_resched, resume\n", m->machno); + DPRINT("%d edfresched, resume\n", m->machno); /* Released, not yet at deadline, release (again) */ t->state = EdfReleased; edfenqueue(&qreleased, t); @@ -663,9 +662,9 @@ edf_resched(Task *t) } void -edf_release(Task *t) +edfrelease(Task *t) { - DPRINT("%d edf_release, %s, %d\n", m->machno, edf_statename[t->state], t->runq.n); + DPRINT("%d edfrelease, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n); assert(t->runq.n > 0 || (up && up->task == t)); t->t = t->r + t->T; t->d = t->r + t->D; @@ -677,14 +676,15 @@ edf_release(Task *t) } Proc * -edf_runproc(void) +edfrunproc(void) { /* Return an edf proc to run or nil */ - Task *t, *nt; + Task *t, *nt, *xt; Proc *p; Ticks when; static ulong nilcount; + int i; /* Figure out if the current proc should be preempted*/ ilock(&edflock); @@ -701,10 +701,25 @@ edf_runproc(void) iunlock(&edflock); return nil; } - DPRINT("edf_runproc %lud\n", nilcount); + DPRINT("edfrunproc %lud\n", nilcount); if (nt && (t == nil || (nt->d < t->d && nt->D < t->Delta))){ + if (conf.nmach > 1){ + for (i = 0; i < conf.nmach; i++){ + if (i == m->machno) + continue; + xt = edfstack[i].head; + if (xt && xt->Delta <= nt->D){ + DPRINT("%d edfrunproc: interprocessor conflict, run current\n", m->machno); + if (t) + goto runt; + nilcount++; + iunlock(&edflock); + return nil; + } + } + } /* released task is better than current */ - DPRINT("%d edf_runproc: released\n", m->machno); + DPRINT("%d edfrunproc: released\n", m->machno); edfdequeue(&qreleased); assert(nt->runq.n >= 1); edfpush(nt); @@ -712,9 +727,9 @@ edf_runproc(void) t = nt; t->scheduled = now; }else{ - DPRINT("%d edf_runproc: current\n", m->machno); + DPRINT("%d edfrunproc: current\n", m->machno); } - +runt: assert (t->runq.n); /* Get first proc off t's run queue @@ -735,19 +750,18 @@ edf_runproc(void) when = t->d; if (when < now){ - DPRINT("%d edf_timer: %T too late\n", m->machno, ticks2time(now-when)); + DPRINT("%d edftimer: %T too late\n", m->machno, ticks2time(now-when)); when = now; } - if (cycdeadline.when){ - if(cycdeadline.when == when){ + if (deadlinetimer[m->machno].when){ + if(deadlinetimer[m->machno].when == when){ iunlock(&edflock); return p; } - timerdel(&cycdeadline); + timerdel(&deadlinetimer[m->machno]); } - cycdeadline.when = when; - timeradd(&cycdeadline); - clockintrsched(); + deadlinetimer[m->machno].when = when; + timeradd(&deadlinetimer[m->machno]); iunlock(&edflock); return p; } @@ -845,7 +859,7 @@ testenq(Task *t) } static char * -edf_testschedulability(Task *thetask) +edftestschedulability(Task *thetask) { Task *t; Ticks H, G, Cb, ticks; diff --git a/port/edf.h b/port/edf.h index f377f0d22147f93a8f1e8ed9803c6cef5e32d0cd..98b76e51270b1893634af3c82e102a64aef7e961 100644 --- a/port/edf.h +++ b/port/edf.h @@ -97,30 +97,12 @@ extern Taskq qwaitrelease; extern Taskq qreleased; extern Taskq qextratime; extern Taskq edfstack[]; -extern int edf_stateupdate; +extern int edfstateupdate; extern void (*devrt)(Task *, Ticks, int); -extern char * edf_statename[]; +extern char * edfstatename[]; #pragma varargck type "T" Time #pragma varargck type "U" Ticks -/* Interface: */ -void edf_preempt(Task*); /* Stop current task, administrate run time, leave on stack */ -void edf_deadline(Proc*); /* Remove current task from edfstack, schedule its next release */ -void edf_release(Task*); /* Release a task */ -void edf_schedule(Task *); /* Run a released task: remove from qrelease, push onto edfstack */ -char * edf_admit(Task*); -void edf_expel(Task*); -void edf_bury(Proc*); /* Proc dies, update Task membership */ -void edf_sched(Task*); /* Figure out what to do with task (after a state change) */ -int isedf(Proc*); /* Proc must be edf scheduled */ -void edf_stop(Proc*); /* Just event generation; should probably be done differently */ -int edf_anyready(void); -void edf_ready(Proc*); -Proc * edf_runproc(void); -void edf_block(Proc*); /* Edf proc has blocked, do the admin */ -void edf_init(void); -int edf_waitlock(Lock*); -void edf_releaselock(Lock*); Time ticks2time(Ticks); Ticks time2ticks(Time); diff --git a/port/nulledf.c b/port/nulledf.c new file mode 100644 index 0000000000000000000000000000000000000000..ef821c268bd5786fa60909281cf4b2acfe9f7cb7 --- /dev/null +++ b/port/nulledf.c @@ -0,0 +1,41 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" +#include "../port/edf.h" + +int +isedf(Proc*) +{ + return 0; +} + +void +edf_bury(Proc*) +{ +} + +int +edf_anyready(void) +{ + return 0; +} + +void +edf_ready(Proc*) +{ +} + +Proc* +edf_runproc(void) +{ + return nil; +} + +void +edf_block(Proc*) +{ +} + diff --git a/port/portclock.c b/port/portclock.c index 7a8fe5ef20e17e6e58c3b6796512f8548b25d6f1..611bba9fc95b2fe3e6fa6cf310e45e0295b4b324 100644 --- a/port/portclock.c +++ b/port/portclock.c @@ -5,40 +5,93 @@ #include "fns.h" #include "io.h" #include "ureg.h" -#include "../port/edf.h" -void (*kproftimer)(ulong); +typedef struct Timers Timers; -typedef struct Clock0link Clock0link; -typedef struct Clock0link { - void (*clock)(void); - Clock0link* link; -} Clock0link; +struct Timers +{ + Lock; + Timer *head; +}; -static Clock0link *clock0link; -static Lock clock0lock; +static Timers timers[MAXMACH]; -void -addclock0link(void (*clock)(void)) +ulong intrcount[MAXMACH]; +ulong fcallcount[MAXMACH]; + +static uvlong +tadd(Timers *tt, Timer *nt) { - Clock0link *lp; + Timer *t, **last, *pt; + + 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; + } - if((lp = malloc(sizeof(Clock0link))) == 0){ - print("addclock0link: too many links\n"); - return; + 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; } - ilock(&clock0lock); - lp->clock = clock; - lp->link = clock0link; - clock0link = lp; - iunlock(&clock0lock); + + 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; } +/* add of modify a timer */ void -portclock(Ureg *ur) +timeradd(Timer *nt) { - Clock0link *lp; + Timers *tt; + uvlong when; + + 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) +{ m->ticks++; if(m->proc) m->proc->pc = ur->pc; @@ -47,6 +100,12 @@ portclock(Ureg *ur) return; /* interrupted ourself */ m->inclockintr = 1; + if(m->flushmmu){ + if(up) + flushmmu(); + m->flushmmu = 0; + } + accounttime(); kmapinval(); @@ -62,14 +121,6 @@ portclock(Ureg *ur) } checkalarms(); - if(m->machno == 0){ - if(canlock(&clock0lock)) - for(lp = clock0link; lp; lp = lp->link){ - lp->clock(); - splhi(); - } - unlock(&clock0lock); - } m->inclockintr = 0; @@ -77,7 +128,7 @@ portclock(Ureg *ur) return; // i.e. don't schedule an EDF process here! - if(!isedf(up) && anyready()){ + if(anyready() && !isedf(up)){ sched(); splhi(); } @@ -88,3 +139,85 @@ portclock(Ureg *ur) segclock(ur->pc); } } + +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) +{ +} diff --git a/port/portdat.h b/port/portdat.h index 0c9592038ccdb090b390c1b9d03ea3918fff95e2..9d746f3b499217152ee4ee99102d7db59b224b9d 100644 --- a/port/portdat.h +++ b/port/portdat.h @@ -42,6 +42,7 @@ typedef struct Segment Segment; typedef struct Session Session; typedef struct Task Task; typedef struct Talarm Talarm; +typedef struct Timer Timer; typedef struct Uart Uart; typedef struct Waitq Waitq; typedef struct Walkqid Walkqid; @@ -827,6 +828,18 @@ struct Uart Rendez r; }; +/* + * fasttick timer interrupts (Dummy for now) + */ +struct Timer +{ + uvlong when; /* fastticks when f should be called */ + void (*f)(Ureg*, Timer*); + void *a; + Timer *next; + ulong period; +}; + #define DEVDOTDOT -1 #pragma varargck argpos print 1 diff --git a/port/portfns.h b/port/portfns.h index 124ce034366a60319cfb48d076a9a59a3b0b3672..a5275b41a07b7039e866939583a5dd9913c51376 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -7,7 +7,7 @@ void alarmkproc(void*); Block* allocb(int); int anyhigher(void); int anyready(void); -#define assert(x) if(x){}else panic("assert(x) failed") +#define assert(x) if(x){}else _assert("assert(x) failed") void _assert(char*); Image* attachimage(int, Chan*, ulong, ulong); Page* auxpage(void); @@ -87,6 +87,17 @@ void dumpstack(void); Fgrp* dupfgrp(Fgrp*); void duppage(Page*); void dupswap(Page*); +void edfdeadline(Proc*); +void edfrelease(Task*); +char* edfadmit(Task*); +void edfexpel(Task*); +void edfbury(Proc*); +void edfsched(Task*); +int edfanyready(void); +void edfready(Proc*); +Proc* edfrunproc(void); +void edfblock(Proc*); +void edfinit(void); int emptystr(char*); int encrypt(void*, void*, int); void envcpy(Egrp*, Egrp*); @@ -96,7 +107,7 @@ void error(char*); long execregs(ulong, ulong, ulong); void exhausted(char*); void exit(int); -vlong fastticks(uvlong*); +uvlong fastticks(uvlong*); int fault(ulong, int); void fdclose(int, int); Chan* fdtochan(int, int, int, int); @@ -129,6 +140,7 @@ int incref(Ref*); void initseg(void); int iprint(char*, ...); void isdir(Chan*); +int isedf(Proc*); int iseve(void); int islo(void); Segment* isoverlap(Proc*, ulong, int); @@ -175,6 +187,8 @@ long mntversion(Chan*, char*, int, int); void mountfree(Mount*); ulong ms2tk(ulong); ulong msize(void*); +ulong ms2tk(ulong); +uvlong ms2fastticks(ulong); void muxclose(Mnt*); Chan* namec(char*, int, int, ulong); #define nelem(x) (sizeof(x)/sizeof(x[0])) @@ -313,6 +327,11 @@ char* srvname(Chan*); int swapcount(ulong); int swapfull(void); void swapinit(void); +void timeradd(Timer*); +void timerdel(Timer*); +void timersinit(void); +void timerintr(Ureg*, uvlong); +void timerset(uvlong); vlong todget(vlong*); void todfix(void); void todsetfreq(vlong); diff --git a/port/proc.c b/port/proc.c index cae3d30148503ddb932ad7c0f690eb1fc94f9024..04eaa83907ae50010cf836a62f9121cc5e9d8a98 100644 --- a/port/proc.c +++ b/port/proc.c @@ -4,7 +4,6 @@ #include "dat.h" #include "fns.h" #include "../port/error.h" -#include "../port/edf.h" int nrdy; Ref noteidalloc; @@ -43,37 +42,6 @@ char *statename[] = static void pidhash(Proc*); static void pidunhash(Proc*); -/*DEBUGGING: scheduling event log */ -#ifdef RSC -static ulong *lg; -enum {Nlg = 1024*1024}; -static ulong wp, rp; -static void -le(int c, Proc *p) -{ - if(lg==nil) - lg = malloc(Nlg*sizeof(lg[0])); - lg[wp++&(Nlg-1)] = MACHP(0)->ticks; - lg[wp++&(Nlg-1)] = c; - lg[wp++&(Nlg-1)] = (ulong)p; -} -void -dumpschedlog(void) -{ - int i; - - i=0; - iprint("%lux=>%lux\n", rp, wp); - while((rp&(Nlg-1))!=(wp&(Nlg-1))){ - iprint("%lux ", lg[rp++&(Nlg-1)]); - if(++i%8==0) - iprint("\n"); - } - if(i%8) - iprint("\n"); -} -#endif - /* * Always splhi()'ed. */ @@ -90,7 +58,7 @@ schedinit(void) /* never returns */ case Moribund: up->state = Dead; if (isedf(up)) - edf_bury(up); + edfbury(up); /* * Holding locks from pexit: @@ -150,7 +118,7 @@ sched(void) int anyready(void) { - return nrdy || edf_anyready(); + return nrdy || edfanyready(); } int @@ -180,12 +148,9 @@ ready(Proc *p) Schedq *rq; s = splhi(); -#ifdef RSC -le('r',p); -#endif if(isedf(p)){ - edf_ready(p); + edfready(p); splx(s); return; } @@ -239,7 +204,7 @@ runproc(void) Proc *p, *l; ulong rt; - if ((p = edf_runproc()) != nil) + if ((p = edfrunproc()) != nil) return p; loop: @@ -533,7 +498,7 @@ sleep(Rendez *r, int (*f)(void*), void *arg) // Behind unlock, we may call wakeup on ourselves. if (isedf(up)) - edf_block(up); + edfblock(up); gotolabel(&m->sched); } @@ -743,7 +708,7 @@ addbroken(Proc *p) qunlock(&broken); if (isedf(up)) - edf_bury(up); + edfbury(up); p->state = Broken; p->psstate = 0; sched(); @@ -912,7 +877,7 @@ pexit(char *exitstr, int freemem) lock(&palloc); if (isedf(up)) - edf_bury(up); + edfbury(up); up->state = Moribund; sched(); panic("pexit"); @@ -1166,7 +1131,7 @@ procctl(Proc *p) splhi(); p->state = Stopped; if (isedf(up)) - edf_block(up); + edfblock(up); sched(); p->psstate = state; splx(s); diff --git a/port/qlock.c b/port/qlock.c index 1f8dbbeefab5bb4d06ab76cc85f45bcb77a1ca68..f763d46c57fbd0eacb8b9ba2a57aafaf77631506 100644 --- a/port/qlock.c +++ b/port/qlock.c @@ -3,7 +3,6 @@ #include "mem.h" #include "dat.h" #include "fns.h" -#include "../port/edf.h" struct { ulong rlock; @@ -41,7 +40,7 @@ qlock(QLock *q) up->qpc = getcallerpc(&q); unlock(&q->use); if (isedf(mp)) - edf_block(mp); + edfblock(mp); sched(); } @@ -106,7 +105,7 @@ rlock(RWlock *q) mp->state = QueueingR; unlock(&q->use); if (isedf(mp)) - edf_block(mp); + edfblock(mp); sched(); } @@ -164,7 +163,7 @@ wlock(RWlock *q) mp->state = QueueingW; unlock(&q->use); if (isedf(mp)) - edf_block(mp); + edfblock(mp); sched(); } diff --git a/port/sysproc.c b/port/sysproc.c index 4acaacb1ae733b257527768c43ce605ae65b6fc3..151c902a31d5c843bfc456df6b57d16e6358959b 100644 --- a/port/sysproc.c +++ b/port/sysproc.c @@ -4,7 +4,6 @@ #include "dat.h" #include "fns.h" #include "../port/error.h" -#include "../port/edf.h" #include @@ -827,7 +826,7 @@ sysrendezvous(ulong *arg) up->state = Rendezvous; unlock(up->rgrp); if (isedf(up)) - edf_block(up); + edfblock(up); sched(); diff --git a/port/tod.c b/port/tod.c index b7d0d6070ea6f39c62ac061d999a0e6100e9e463..75193d221a92f5ca84985857f419b289bbf9121b 100644 --- a/port/tod.c +++ b/port/tod.c @@ -28,7 +28,7 @@ // frequency of the tod clock -#define TODFREQ 1000000000LL +#define TODFREQ 1000000000ULL struct { ulong cnt; @@ -61,7 +61,10 @@ todsetfreq(vlong f) { ilock(&tod); tod.hz = f; + + /* calculate multiplier for time conversion */ tod.multiplier = (TODFREQ<<31)/f; + iunlock(&tod); } @@ -180,3 +183,13 @@ seconds(void) i = x; return i; } + +// convert milliseconds to fast ticks +// +uvlong +ms2fastticks(ulong ms) +{ + if(tod.hz == 0) + fastticks((uvlong*)&tod.hz); + return (tod.hz*ms)/1000ULL; +}