📄 portclock.c
字号:
#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "ureg.h"struct Timers{ Lock; Timer *head;};static Timers timers[MAXMACH];ulong intrcount[MAXMACH];ulong fcallcount[MAXMACH];static vlongtadd(Timers *tt, Timer *nt){ Timer *t, **last; /* Called with tt locked */ assert(nt->tt == nil); switch(nt->tmode){ default: panic("timer"); break; case Trelative: if(nt->tns <= 0) nt->tns = 1; nt->twhen = fastticks(nil) + ns2fastticks(nt->tns); break; case Tperiodic: assert(nt->tns >= 100000); /* At least 100 µs period */ 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; } 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 uvlongtdel(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 */voidtimeradd(Timer *nt){ Timers *tt; vlong when; /* Must lock Timer struct before Timers struct */ ilock(nt); if(tt = nt->tt){ ilock(tt); tdel(nt); iunlock(tt); } tt = &timers[m->machno]; ilock(tt); when = tadd(tt, nt); if(when) timerset(when); iunlock(tt); iunlock(nt);}voidtimerdel(Timer *dt){ Timers *tt; uvlong when; ilock(dt); if(tt = dt->tt){ ilock(tt); when = tdel(dt); if(when && tt == &timers[m->machno]) timerset(tt->head->twhen); iunlock(tt); } iunlock(dt);}voidhzclock(Ureg *ur){ m->ticks++; if(m->proc) m->proc->pc = ur->pc; if(m->flushmmu){ if(up) flushmmu(); m->flushmmu = 0; } accounttime(); kmapinval(); if(kproftimer != nil) kproftimer(ur->pc); if((active.machs&(1<<m->machno)) == 0) return; if(active.exiting) { print("someone's exiting\n"); exit(0); } checkalarms(); if(up && up->state == Running) hzsched(); /* in proc.c */}voidtimerintr(Ureg *u, uvlong){ Timer *t; Timers *tt; uvlong when, now; int callhzclock; static int sofar; intrcount[m->machno]++; callhzclock = 0; tt = &timers[m->machno]; now = fastticks(nil); ilock(tt); 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; } tt->head = t->tnext; assert(t->tt == tt); t->tt = nil; fcallcount[m->machno]++; iunlock(tt); if(t->tf) (*t->tf)(u, t); else callhzclock++; ilock(tt); if(t->tmode == Tperiodic) tadd(tt, t); } iunlock(tt);}voidtimersinit(void){ Timer *t; /* * T->tf == nil means the HZ clock for this processor. */ todinit(); t = malloc(sizeof(*t)); t->tmode = Tperiodic; t->tt = nil; t->tns = 1000000000/HZ; t->tf = nil; timeradd(t);}Timer*addclock0link(void (*f)(void), int ms){ Timer *nt; uvlong when; /* Synchronize to hztimer if ms is 0 */ nt = malloc(sizeof(Timer)); if(ms == 0) ms = 1000/HZ; nt->tns = (vlong)ms*1000000LL; nt->tmode = Tperiodic; nt->tt = nil; nt->tf = (void (*)(Ureg*, Timer*))f; ilock(&timers[0]); when = tadd(&timers[0], nt); if(when) timerset(when); iunlock(&timers[0]); return nt;}/* * 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. */ulongtk2ms(ulong ticks){ uvlong t, hz; t = ticks; hz = HZ; t *= 1000L; t = t/hz; ticks = t; return ticks;}ulongms2tk(ulong ms){ /* avoid overflows at the cost of precision */ if(ms >= 1000000000/HZ) return (ms/1000)*HZ; return (ms*HZ+500)/1000;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -