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 "dat.h"11 #include "fns.h"13 static Channel* ctimer; /* chan(Timer*)[100] */14 static Timer *timer;16 static17 uint18 msec(void)19 {20 return nsec()/1000000;21 }23 void24 timerstop(Timer *t)25 {26 t->next = timer;27 timer = t;28 }30 void31 timercancel(Timer *t)32 {33 t->cancel = TRUE;34 }36 static37 void38 timerproc(void *a)39 {40 int i, nt, na, dt, del;41 Timer **t, *x;42 uint old, new;44 USED(a);45 rfork(RFFDG);46 threadsetname("TIMERPROC");47 t = nil;48 na = 0;49 nt = 0;50 old = msec();51 for(;;){52 sleep(1); /* will sleep minimum incr */53 new = msec();54 dt = new-old;55 old = new;56 if(dt < 0) /* timer wrapped; go around, losing a tick */57 continue;58 for(i=0; i<nt; i++){59 x = t[i];60 x->dt -= dt;61 del = 0;62 if(x->cancel){63 timerstop(x);64 del = 1;65 }else if(x->dt <= 0){66 /*67 * avoid possible deadlock if client is68 * now sending on ctimer69 */70 if(nbsendul(x->c, 0) > 0)71 del = 1;72 }73 if(del){74 memmove(&t[i], &t[i+1], (nt-i-1)*sizeof t[0]);75 --nt;76 --i;77 }78 }79 if(nt == 0){80 x = recvp(ctimer);81 gotit:82 if(nt == na){83 na += 10;84 t = realloc(t, na*sizeof(Timer*));85 if(t == nil)86 abort();87 }88 t[nt++] = x;89 old = msec();90 }91 if(nbrecv(ctimer, &x) > 0)92 goto gotit;93 }94 }96 void97 timerinit(void)98 {99 ctimer = chancreate(sizeof(Timer*), 100);100 proccreate(timerproc, nil, STACK);101 }103 /*104 * timeralloc() and timerfree() don't lock, so can only be105 * called from the main proc.106 */108 Timer*109 timerstart(int dt)110 {111 Timer *t;113 t = timer;114 if(t)115 timer = timer->next;116 else{117 t = emalloc(sizeof(Timer));118 t->c = chancreate(sizeof(int), 0);119 }120 t->next = nil;121 t->dt = dt;122 t->cancel = FALSE;123 sendp(ctimer, t);124 return t;125 }