17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <thread.h>
5*9a747e4fSDavid du Colombier #include <cursor.h>
67dd7cddfSDavid du Colombier #include <mouse.h>
77dd7cddfSDavid du Colombier #include <keyboard.h>
87dd7cddfSDavid du Colombier #include <frame.h>
97dd7cddfSDavid du Colombier #include <fcall.h>
107dd7cddfSDavid du Colombier #include <plumb.h>
117dd7cddfSDavid du Colombier #include "dat.h"
127dd7cddfSDavid du Colombier #include "fns.h"
137dd7cddfSDavid du Colombier
147dd7cddfSDavid du Colombier static Channel* ctimer; /* chan(Timer*)[100] */
157dd7cddfSDavid du Colombier static Timer *timer;
167dd7cddfSDavid du Colombier
177dd7cddfSDavid du Colombier static
187dd7cddfSDavid du Colombier uint
msec(void)197dd7cddfSDavid du Colombier msec(void)
207dd7cddfSDavid du Colombier {
217dd7cddfSDavid du Colombier return nsec()/1000000;
227dd7cddfSDavid du Colombier }
237dd7cddfSDavid du Colombier
247dd7cddfSDavid du Colombier void
timerstop(Timer * t)257dd7cddfSDavid du Colombier timerstop(Timer *t)
267dd7cddfSDavid du Colombier {
277dd7cddfSDavid du Colombier t->next = timer;
287dd7cddfSDavid du Colombier timer = t;
297dd7cddfSDavid du Colombier }
307dd7cddfSDavid du Colombier
317dd7cddfSDavid du Colombier void
timercancel(Timer * t)327dd7cddfSDavid du Colombier timercancel(Timer *t)
337dd7cddfSDavid du Colombier {
347dd7cddfSDavid du Colombier t->cancel = TRUE;
357dd7cddfSDavid du Colombier }
367dd7cddfSDavid du Colombier
377dd7cddfSDavid du Colombier static
387dd7cddfSDavid du Colombier void
timerproc(void *)397dd7cddfSDavid du Colombier timerproc(void*)
407dd7cddfSDavid du Colombier {
417dd7cddfSDavid du Colombier int i, nt, na, dt, del;
427dd7cddfSDavid du Colombier Timer **t, *x;
437dd7cddfSDavid du Colombier uint old, new;
447dd7cddfSDavid du Colombier
457dd7cddfSDavid du Colombier threadsetname("timerproc");
467dd7cddfSDavid du Colombier rfork(RFFDG);
477dd7cddfSDavid du Colombier t = nil;
487dd7cddfSDavid du Colombier na = 0;
497dd7cddfSDavid du Colombier nt = 0;
507dd7cddfSDavid du Colombier old = msec();
517dd7cddfSDavid du Colombier for(;;){
527dd7cddfSDavid du Colombier sleep(1); /* will sleep minimum incr */
537dd7cddfSDavid du Colombier new = msec();
547dd7cddfSDavid du Colombier dt = new-old;
557dd7cddfSDavid du Colombier old = new;
567dd7cddfSDavid du Colombier if(dt < 0) /* timer wrapped; go around, losing a tick */
577dd7cddfSDavid du Colombier continue;
587dd7cddfSDavid du Colombier for(i=0; i<nt; i++){
597dd7cddfSDavid du Colombier x = t[i];
607dd7cddfSDavid du Colombier x->dt -= dt;
617dd7cddfSDavid du Colombier del = FALSE;
627dd7cddfSDavid du Colombier if(x->cancel){
637dd7cddfSDavid du Colombier timerstop(x);
647dd7cddfSDavid du Colombier del = TRUE;
657dd7cddfSDavid du Colombier }else if(x->dt <= 0){
667dd7cddfSDavid du Colombier /*
677dd7cddfSDavid du Colombier * avoid possible deadlock if client is
687dd7cddfSDavid du Colombier * now sending on ctimer
697dd7cddfSDavid du Colombier */
707dd7cddfSDavid du Colombier if(nbsendul(x->c, 0) > 0)
717dd7cddfSDavid du Colombier del = TRUE;
727dd7cddfSDavid du Colombier }
737dd7cddfSDavid du Colombier if(del){
747dd7cddfSDavid du Colombier memmove(&t[i], &t[i+1], (nt-i-1)*sizeof t[0]);
757dd7cddfSDavid du Colombier --nt;
767dd7cddfSDavid du Colombier --i;
777dd7cddfSDavid du Colombier }
787dd7cddfSDavid du Colombier }
797dd7cddfSDavid du Colombier if(nt == 0){
807dd7cddfSDavid du Colombier x = recvp(ctimer);
817dd7cddfSDavid du Colombier gotit:
827dd7cddfSDavid du Colombier if(nt == na){
837dd7cddfSDavid du Colombier na += 10;
847dd7cddfSDavid du Colombier t = realloc(t, na*sizeof(Timer*));
857dd7cddfSDavid du Colombier if(t == nil)
867dd7cddfSDavid du Colombier error("timer realloc failed");
877dd7cddfSDavid du Colombier }
887dd7cddfSDavid du Colombier t[nt++] = x;
897dd7cddfSDavid du Colombier old = msec();
907dd7cddfSDavid du Colombier }
917dd7cddfSDavid du Colombier if(nbrecv(ctimer, &x) > 0)
927dd7cddfSDavid du Colombier goto gotit;
937dd7cddfSDavid du Colombier }
947dd7cddfSDavid du Colombier }
957dd7cddfSDavid du Colombier
967dd7cddfSDavid du Colombier void
timerinit(void)977dd7cddfSDavid du Colombier timerinit(void)
987dd7cddfSDavid du Colombier {
997dd7cddfSDavid du Colombier ctimer = chancreate(sizeof(Timer*), 100);
1007dd7cddfSDavid du Colombier proccreate(timerproc, nil, STACK);
1017dd7cddfSDavid du Colombier }
1027dd7cddfSDavid du Colombier
1037dd7cddfSDavid du Colombier Timer*
timerstart(int dt)1047dd7cddfSDavid du Colombier timerstart(int dt)
1057dd7cddfSDavid du Colombier {
1067dd7cddfSDavid du Colombier Timer *t;
1077dd7cddfSDavid du Colombier
1087dd7cddfSDavid du Colombier t = timer;
1097dd7cddfSDavid du Colombier if(t)
1107dd7cddfSDavid du Colombier timer = timer->next;
1117dd7cddfSDavid du Colombier else{
1127dd7cddfSDavid du Colombier t = emalloc(sizeof(Timer));
1137dd7cddfSDavid du Colombier t->c = chancreate(sizeof(int), 0);
1147dd7cddfSDavid du Colombier }
1157dd7cddfSDavid du Colombier t->next = nil;
1167dd7cddfSDavid du Colombier t->dt = dt;
1177dd7cddfSDavid du Colombier t->cancel = FALSE;
1187dd7cddfSDavid du Colombier sendp(ctimer, t);
1197dd7cddfSDavid du Colombier return t;
1207dd7cddfSDavid du Colombier }
121