Blob
1 #include <u.h>2 #include <libc.h>3 #include <draw.h>4 #include <thread.h>5 #include <cursor.h>6 #include <mouse.h>7 #include <keyboard.h>8 #include <frame.h>9 #include <fcall.h>10 #include <plumb.h>11 #include "dat.h"12 #include "fns.h"14 static Channel* ctimer; /* chan(Timer*)[100] */15 static Timer *timer;17 static18 uint19 msec(void)20 {21 return nsec()/1000000;22 }24 void25 timerstop(Timer *t)26 {27 t->next = timer;28 timer = t;29 }31 void32 timercancel(Timer *t)33 {34 t->cancel = TRUE;35 }37 static38 void39 timerproc(void *v)40 {41 int i, nt, na, dt, del;42 Timer **t, *x;43 uint old, new;45 USED(v);46 threadsetname("timerproc");47 rfork(RFFDG);48 t = nil;49 na = 0;50 nt = 0;51 old = msec();52 for(;;){53 sleep(1); /* will sleep minimum incr */54 new = msec();55 dt = new-old;56 old = new;57 if(dt < 0) /* timer wrapped; go around, losing a tick */58 continue;59 for(i=0; i<nt; i++){60 x = t[i];61 x->dt -= dt;62 del = FALSE;63 if(x->cancel){64 timerstop(x);65 del = TRUE;66 }else if(x->dt <= 0){67 /*68 * avoid possible deadlock if client is69 * now sending on ctimer70 */71 if(nbsendul(x->c, 0) > 0)72 del = TRUE;73 }74 if(del){75 memmove(&t[i], &t[i+1], (nt-i-1)*sizeof t[0]);76 --nt;77 --i;78 }79 }80 if(nt == 0){81 x = recvp(ctimer);82 gotit:83 if(nt == na){84 na += 10;85 t = realloc(t, na*sizeof(Timer*));86 if(t == nil)87 error("timer realloc failed");88 }89 t[nt++] = x;90 old = msec();91 }92 if(nbrecv(ctimer, &x) > 0)93 goto gotit;94 }95 }97 void98 timerinit(void)99 {100 ctimer = chancreate(sizeof(Timer*), 100);101 chansetname(ctimer, "ctimer");102 proccreate(timerproc, nil, STACK);103 }105 Timer*106 timerstart(int dt)107 {108 Timer *t;110 t = timer;111 if(t)112 timer = timer->next;113 else{114 t = emalloc(sizeof(Timer));115 t->c = chancreate(sizeof(int), 0);116 chansetname(t->c, "tc%p", t->c);117 }118 t->next = nil;119 t->dt = dt;120 t->cancel = FALSE;121 sendp(ctimer, t);122 return t;123 }