diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-09-25 14:48:42 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-09-25 14:48:42 +0000 |
commit | 6fb883b02c6fca762dcbe31450c868e4b854952c (patch) | |
tree | 1749dbbe1ac1a00635fa9e508fa16d0829ba2e9d /sys/src/9/port | |
parent | 6abe569ec8f47ba14c3dcd5d5214e7b7a020bf7a (diff) |
9/port: revert timer wheel change, breaks pi4 boot, needs more time investigating
Diffstat (limited to 'sys/src/9/port')
-rw-r--r-- | sys/src/9/port/alarm.c | 150 | ||||
-rw-r--r-- | sys/src/9/port/portclock.c | 284 | ||||
-rw-r--r-- | sys/src/9/port/portdat.h | 12 | ||||
-rw-r--r-- | sys/src/9/port/portfns.h | 2 | ||||
-rw-r--r-- | sys/src/9/port/proc.c | 2 |
5 files changed, 189 insertions, 261 deletions
diff --git a/sys/src/9/port/alarm.c b/sys/src/9/port/alarm.c index 95516222f..49dec2ccb 100644 --- a/sys/src/9/port/alarm.c +++ b/sys/src/9/port/alarm.c @@ -3,91 +3,109 @@ #include "mem.h" #include "dat.h" #include "fns.h" -#include "error.h" -static Proc *tripped; +static Alarms alarms; static Rendez alarmr; -static Lock triplk; - -static int -tfn(void *) -{ - int t; - - ilock(&triplk); - t = (tripped != nil); - iunlock(&triplk); - return t; -} - -/* - * called every clock tick on cpu0 - */ -static void -tripalarm(Ureg*, Timer *t) -{ - ilock(&triplk); - t->p->palarm = tripped; - tripped = t->p; - iunlock(&triplk); - - wakeup(&alarmr); -} void alarmkproc(void*) { - static Note alarmnote = { - "alarm", - NUser, - 1, - }; - Proc *p, *n; - Timer *a; + Proc *rp; + ulong now, when; while(waserror()) ; - while(1){ - ilock(&triplk); - p = tripped; - tripped = nil; - iunlock(&triplk); - - for(; p != nil; p = n){ - n = p->palarm; - a = &p->alarm; - if(!canqlock(&p->debug)){ - a->tns = MS2NS(10); - timeradd(a); + for(;;){ + now = MACHP(0)->ticks; + qlock(&alarms); + for(rp = alarms.head; rp != nil; rp = rp->palarm){ + if((when = rp->alarm) == 0) continue; + if((long)(now - when) < 0) + break; + if(!canqlock(&rp->debug)) + break; + if(rp->alarm != 0){ + static Note alarm = { + "alarm", + NUser, + 1, + }; + incref(&alarm); + pushnote(rp, &alarm); + rp->alarm = 0; } - incref(&alarmnote); - pushnote(p, &alarmnote); - qunlock(&p->debug); + qunlock(&rp->debug); } - sleep(&alarmr, tfn, nil); + alarms.head = rp; + qunlock(&alarms); + + sleep(&alarmr, return0, 0); + } +} + +/* + * called every clock tick on cpu0 + */ +void +checkalarms(void) +{ + Proc *p; + ulong now, when; + + p = alarms.head; + if(p != nil){ + now = MACHP(0)->ticks; + when = p->alarm; + if(when == 0 || (long)(now - when) >= 0) + wakeup(&alarmr); } } ulong procalarm(ulong time) { - uvlong old; - Timer *a; + Proc **l, *f; + ulong when, old; + + when = MACHP(0)->ticks; + old = up->alarm; + if(old) { + old -= when; + if((long)old > 0) + old = tk2ms(old); + else + old = 0; + } + if(time == 0) { + up->alarm = 0; + return old; + } + when += ms2tk(time); + if(when == 0) + when = 1; - a = &up->alarm; - old = a->tns; - timerdel(a); + qlock(&alarms); + l = &alarms.head; + for(f = *l; f; f = f->palarm) { + if(up == f){ + *l = f->palarm; + break; + } + l = &f->palarm; + } + l = &alarms.head; + for(f = *l; f; f = f->palarm) { + time = f->alarm; + if(time != 0 && (long)(time - when) >= 0) + break; + l = &f->palarm; + } + up->palarm = f; + *l = up; + up->alarm = when; + qunlock(&alarms); - lock(a); - a->tns = MS2NS(time); - a->tf = tripalarm; - a->tmode = Trelative; - a->p = up; - a->ta = nil; - unlock(a); - if(time != 0) - timeradd(a); - return NS2MS(old); + return old; } diff --git a/sys/src/9/port/portclock.c b/sys/src/9/port/portclock.c index 5f7a498e9..e12938bc3 100644 --- a/sys/src/9/port/portclock.c +++ b/sys/src/9/port/portclock.c @@ -7,27 +7,10 @@ #include "ureg.h" #include "tos.h" -typedef struct Timers Timers; -typedef struct Wheel Wheel; - -enum { - WSHIFT = 5, - NWHEEL = 6, - NSLOT = 1<<WSHIFT, - SMASK = NSLOT-1, - TMAX = 1<<(WSHIFT*(NWHEEL-1)), -}; - -struct Wheel { - Timer *slots[NSLOT]; - int idx; -}; - -struct Timers { +struct Timers +{ Lock; - uvlong tnow; - uvlong tsched; - Wheel wheels[NWHEEL]; + Timer *head; }; static Timers timers[MAXMACH]; @@ -35,102 +18,13 @@ static Timers timers[MAXMACH]; ulong intrcount[MAXMACH]; ulong fcallcount[MAXMACH]; -#define slot(tt, i, j) ((tt)->wheels[(i)].slots[(j) & SMASK]) -#define slotp(tt, i, j) (&(tt)->wheels[(i)].slots[(j) & SMASK]) - -static void -tins(Timers *tt, Timer *t) -{ - Timer *n, **p; - uvlong dt; - int i; - - dt = t->twhen - tt->tnow; - assert((vlong)dt >= 0); - for(i = 0; dt >= NSLOT && i < NWHEEL-1; i++) - dt = (dt + tt->wheels[i].idx) >> WSHIFT; - dt = (dt + tt->wheels[i].idx) & SMASK; - - p = &tt->wheels[i].slots[dt]; - n = *p; - t->tt = tt; - t->tnext = n; - t->tlink = p; - if(n != nil) - n->tlink = &t->tnext; - *p = t; -} - -static void -tdel(Timer *dt) -{ - if(dt->tt == nil) - return; - if(dt->tnext != nil) - dt->tnext->tlink = dt->tlink; - *dt->tlink = dt->tnext; - dt->tlink = nil; - dt->tnext = nil; - dt->tt = nil; -} - -/* look for another timer at same frequency for combining */ -static uvlong -tcombine(Timers *tt, Timer *nt, uvlong now) -{ - int i, j, s; - Timer *t; - - for(i = 0; i < NWHEEL; i++){ - s = tt->wheels[i].idx; - for(j = s; j < s+NSLOT; j++) - for(t = slot(tt, i, j); t != nil && t->tns < nt->tns; t = t->tnext) - if(t->tmode == Tperiodic && t->twhen > now && t->tns == nt->tns) - return t->twhen; - } - return fastticks(nil); -} - -/* approximate time of the next timer to schedule, or 0 if there's already one scheduled */ -static uvlong -tnext(Timers *tt, uvlong when) -{ - uvlong tk, dt; - int i, j, s; - Wheel *w; - - if(when > tt->tsched) - return 0; - - dt = 1; - for(i = 0; i < NWHEEL; i++){ - w = &tt->wheels[i]; - s = w->idx+1; - tk = tt->tnow; - /* the current slot should always already be processed, and thus empty */ - assert(slot(tt, i, w->idx) == nil); - for(j = s; j < s+NSLOT-1; j++){ - tk += dt; - if(tk >= when || slot(tt, i, j) != nil) - break; - } - if(tk < when) - when = tk; - dt <<= WSHIFT; - } - tt->tsched = when; - return when; - -} - -/* Called with tt locked */ -static void +static vlong tadd(Timers *tt, Timer *nt) { + Timer *t, **last; + + /* Called with tt locked */ assert(nt->tt == nil); - nt->tt = tt; - nt->tnext = nil; - nt->tlink = nil; switch(nt->tmode){ default: panic("timer"); @@ -142,14 +36,54 @@ tadd(Timers *tt, Timer *nt) break; case Tperiodic: assert(nt->tns >= 100000); /* At least 100 µs period */ - if(0 && nt->twhen == 0) - nt->twhen = tcombine(tt, nt, tt->tnow); - else - nt->twhen = fastticks(nil); + if(nt->twhen == 0){ + /* look for another timer at same frequency for combining */ + for(t = tt->head; t; t = t->tnext){ + if(t->tmode == Tperiodic && t->tns == nt->tns) + break; + } + if (t) + nt->twhen = t->twhen; + else + nt->twhen = fastticks(nil); + } nt->twhen += ns2fastticks(nt->tns); break; } - tins(tt, nt); + + for(last = &tt->head; t = *last; last = &t->tnext){ + if(t->twhen > nt->twhen) + break; + } + nt->tnext = *last; + *last = nt; + nt->tt = tt; + if(last == &tt->head) + return nt->twhen; + return 0; +} + +static uvlong +tdel(Timer *dt) +{ + + Timer *t, **last; + Timers *tt; + + tt = dt->tt; + if (tt == nil) + return 0; + for(last = &tt->head; t = *last; last = &t->tnext){ + if(t == dt){ + assert(dt->tt); + dt->tt = nil; + *last = t->tnext; + break; + } + } + if(last == &tt->head && tt->head) + return tt->head->twhen; + return 0; } /* add or modify a timer */ @@ -157,20 +91,18 @@ void timeradd(Timer *nt) { Timers *tt; - uvlong when; + vlong when; /* Must lock Timer struct before Timers struct */ ilock(nt); - tt = nt->tt; - if(tt != nil){ + if(tt = nt->tt){ ilock(tt); tdel(nt); iunlock(tt); } tt = &timers[m->machno]; ilock(tt); - tadd(tt, nt); - when = tnext(tt, nt->twhen); + when = tadd(tt, nt); if(when) timerset(when); iunlock(tt); @@ -191,10 +123,9 @@ timerdel(Timer *dt) ilock(dt); if(tt = dt->tt){ ilock(tt); - tdel(dt); - when = tnext(tt, dt->twhen); + when = tdel(dt); if(when && tt == &timers[m->machno]) - timerset(when); + timerset(tt->head->twhen); iunlock(tt); } if((mp = dt->tactive) == nil || mp->machno == m->machno){ @@ -202,6 +133,7 @@ timerdel(Timer *dt) return; } iunlock(dt); + /* rare, but tf can still be active on another cpu */ while(dt->tactive == mp && dt->tt == nil) if(up->nlocks == 0 && islo()) @@ -234,6 +166,9 @@ hzclock(Ureg *ur) if(active.exiting) exit(0); + if(m->machno == 0) + checkalarms(); + if(up && up->state == Running){ if(userureg(ur)){ /* user profiling clock */ @@ -249,77 +184,47 @@ hzclock(Ureg *ur) void timerintr(Ureg *u, Tval) { - uvlong dt, when, now; - int i, j, s, hz; - Timer *t, *n; + Timer *t; Timers *tt; - Wheel *w; + uvlong when, now; + int callhzclock; intrcount[m->machno]++; + callhzclock = 0; tt = &timers[m->machno]; now = fastticks(nil); - ilock(tt); - hz = 0; - dt = now - tt->tnow; - tt->tnow = now; - /* - * We need to look at all the wheels. - */ - for(i = 0; i < NWHEEL; i++){ - w = &tt->wheels[i]; - s = w->idx; - w->idx = (s+dt)&SMASK; - for(j = s; j <= s+dt && j < s+NSLOT; j++){ - for(t = slot(tt, i, j); t != nil; t = n){ - assert(t->tt == tt); - n = t->tnext; - /* - * The last wheel can contain timers that are - * expiring both before and after now. - * Cascade the future ones, and expire the current - * ones. - */ - if(t->twhen > now+TMAX) - continue; - /* - * Otherwise, we cascade this timer into a new slot - * in a closer wheel. - */ - tdel(t); - if(t->twhen > now){ - tins(tt, t); - continue; - } - /* - * No need to ilock t here: any manipulation of t - * requires tdel(t) and this must be done with a - * lock to tt held. We have tt, so the tdel will - * wait until we're done - */ - t->tactive = MACHP(m->machno); - fcallcount[m->machno]++; - iunlock(tt); - if(t->tf) - t->tf(u, t); - else - hz = 1; - t->tactive = nil; - ilock(tt); - if(t->tmode == Tperiodic) - tadd(tt, t); - } + while(t = tt->head){ + /* + * No need to ilock t here: any manipulation of t + * requires tdel(t) and this must be done with a + * lock to tt held. We have tt, so the tdel will + * wait until we're done + */ + when = t->twhen; + if(when > now){ + timerset(when); + iunlock(tt); + if(callhzclock) + hzclock(u); + return; } - dt += s; - dt >>= WSHIFT; + tt->head = t->tnext; + assert(t->tt == tt); + t->tt = nil; + t->tactive = MACHP(m->machno); + fcallcount[m->machno]++; + iunlock(tt); + if(t->tf) + (*t->tf)(u, t); + else + callhzclock++; + t->tactive = nil; + ilock(tt); + if(t->tmode == Tperiodic) + tadd(tt, t); } - when = tnext(tt, ~0); - - if(when != 0) - timerset(when); iunlock(tt); - if(hz) - hzclock(u); } void @@ -359,8 +264,7 @@ addclock0link(void (*f)(void), int ms) nt->tf = (void (*)(Ureg*, Timer*))f; ilock(&timers[0]); - tadd(&timers[0], nt); - when = tnext(&timers[0], nt->twhen); + when = tadd(&timers[0], nt); if(when) timerset(when); iunlock(&timers[0]); diff --git a/sys/src/9/port/portdat.h b/sys/src/9/port/portdat.h index 2a674b3bb..45a39be8e 100644 --- a/sys/src/9/port/portdat.h +++ b/sys/src/9/port/portdat.h @@ -1,3 +1,4 @@ +typedef struct Alarms Alarms; typedef struct Block Block; typedef struct Chan Chan; typedef struct Cmdbuf Cmdbuf; @@ -97,6 +98,12 @@ struct RWlock int writer; /* number of writers */ }; +struct Alarms +{ + QLock; + Proc *head; +}; + struct Sargs { uchar args[MAXSYSARG*BY2WD]; @@ -568,7 +575,6 @@ struct Timer Tval tticks; /* tns converted to ticks */ Tval twhen; /* ns represented in fastticks */ Timer *tnext; - Timer **tlink; /* a pointer to the prev nodes's next */ }; enum @@ -714,8 +720,8 @@ struct Proc Rendez sleep; /* place for syssleep/debug */ int notepending; /* note issued but not acted on */ int kp; /* true if a kernel process */ - Proc *palarm; /* triggered alarm chain */ - Timer alarm; /* alarm context */ + Proc *palarm; /* Next alarm time */ + ulong alarm; /* Time of call */ int newtlb; /* Pager has changed my pte's, I must flush */ uintptr rendtag; /* Tag for rendezvous */ diff --git a/sys/src/9/port/portfns.h b/sys/src/9/port/portfns.h index 5c78e24ee..c6877690d 100644 --- a/sys/src/9/port/portfns.h +++ b/sys/src/9/port/portfns.h @@ -26,6 +26,7 @@ void chandevinit(void); void chandevreset(void); void chandevshutdown(void); void chanfree(Chan*); +void checkalarms(void); void checkb(Block*, char*); void cinit(void); Chan* cclone(Chan*); @@ -175,7 +176,6 @@ void log(Log*, int, char*, ...); Cmdtab* lookupcmd(Cmdbuf*, Cmdtab*, int); Page* lookpage(Image*, uintptr); #define MS2NS(n) (((vlong)(n))*1000000LL) -#define NS2MS(n) (((vlong)(n)+500000LL)/100000LL) void machinit(void); void* mallocz(ulong, int); void* malloc(ulong); diff --git a/sys/src/9/port/proc.c b/sys/src/9/port/proc.c index 77e212402..3cf0cea9d 100644 --- a/sys/src/9/port/proc.c +++ b/sys/src/9/port/proc.c @@ -1203,7 +1203,7 @@ pexit(char *exitstr, int freemem) void (*pt)(Proc*, int, vlong); up->fpstate &= ~FPillegal; - procalarm(0); + up->alarm = 0; timerdel(up); pt = proctrace; if(pt != nil) |