2 #include "../port/lib.h"
16 static Timers timers[MAXMACH];
18 ulong intrcount[MAXMACH];
19 ulong fcallcount[MAXMACH];
22 tadd(Timers *tt, Timer *nt)
26 /* Called with tt locked */
27 assert(nt->tt == nil);
35 nt->twhen = fastticks(nil) + ns2fastticks(nt->tns);
38 assert(nt->tns >= 100000); /* At least 100 µs period */
40 /* look for another timer at same frequency for combining */
41 for(t = tt->head; t; t = t->tnext){
42 if(t->tmode == Tperiodic && t->tns == nt->tns)
48 nt->twhen = fastticks(nil);
50 nt->twhen += ns2fastticks(nt->tns);
54 for(last = &tt->head; t = *last; last = &t->tnext){
55 if(t->twhen > nt->twhen)
76 for(last = &tt->head; t = *last; last = &t->tnext){
84 if(last == &tt->head && tt->head)
85 return tt->head->twhen;
89 /* add or modify a timer */
96 /* Must lock Timer struct before Timers struct */
103 tt = &timers[m->machno];
120 /* avoid Tperiodic getting re-added */
121 dt->tmode = Trelative;
127 if(when && tt == &timers[m->machno])
128 timerset(tt->head->twhen);
131 if((mp = dt->tactive) == nil || mp->machno == m->machno){
137 /* rare, but tf can still be active on another cpu */
138 while(dt->tactive == mp && dt->tt == nil)
139 if(up->nlocks == 0 && islo())
148 m->proc->pc = ur->pc;
159 if(kproftimer != nil)
162 if(active.machs[m->machno] == 0)
171 if(up && up->state == Running){
173 /* user profiling clock */
174 Tos *tos = (Tos*)(USTKTOP-sizeof(Tos));
175 tos->clock += TK2MS(1);
179 hzsched(); /* in proc.c */
184 timerintr(Ureg *u, Tval)
191 intrcount[m->machno]++;
193 tt = &timers[m->machno];
194 now = fastticks(nil);
198 * No need to ilock t here: any manipulation of t
199 * requires tdel(t) and this must be done with a
200 * lock to tt held. We have tt, so the tdel will
201 * wait until we're done
214 t->tactive = MACHP(m->machno);
215 fcallcount[m->machno]++;
223 if(t->tmode == Tperiodic)
235 * T->tf == nil means the HZ clock for this processor.
238 t = malloc(sizeof(*t));
240 panic("timersinit: no memory for Timer");
241 t->tmode = Tperiodic;
243 t->tns = 1000000000/HZ;
249 addclock0link(void (*f)(void), int ms)
254 /* Synchronize to hztimer if ms is 0 */
255 nt = malloc(sizeof(Timer));
257 panic("addclock0link: no memory for Timer");
260 nt->tns = (vlong)ms*1000000LL;
261 nt->tmode = Tperiodic;
263 nt->tf = (void (*)(Ureg*, Timer*))f;
266 when = tadd(&timers[0], nt);
274 * This tk2ms avoids overflows that the macro version is prone to.
275 * It is a LOT slower so shouldn't be used if you're just converting
294 /* avoid overflows at the cost of precision */
295 if(ms >= 1000000000/HZ)
297 return (ms*HZ+500)/1000;