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"
13
14 static Channel* ctimer; /* chan(Timer*)[100] */
15 static Timer *timer;
16
17 static
18 uint
msec(void)19 msec(void)
20 {
21 return nsec()/1000000;
22 }
23
24 void
timerstop(Timer * t)25 timerstop(Timer *t)
26 {
27 t->next = timer;
28 timer = t;
29 }
30
31 void
timercancel(Timer * t)32 timercancel(Timer *t)
33 {
34 t->cancel = TRUE;
35 }
36
37 static
38 void
timerproc(void *)39 timerproc(void*)
40 {
41 int i, nt, na, dt, del;
42 Timer **t, *x;
43 uint old, new;
44
45 threadsetname("timerproc");
46 rfork(RFFDG);
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 = FALSE;
62 if(x->cancel){
63 timerstop(x);
64 del = TRUE;
65 }else if(x->dt <= 0){
66 /*
67 * avoid possible deadlock if client is
68 * now sending on ctimer
69 */
70 if(nbsendul(x->c, 0) > 0)
71 del = TRUE;
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 error("timer realloc failed");
87 }
88 t[nt++] = x;
89 old = msec();
90 }
91 if(nbrecv(ctimer, &x) > 0)
92 goto gotit;
93 }
94 }
95
96 void
timerinit(void)97 timerinit(void)
98 {
99 ctimer = chancreate(sizeof(Timer*), 100);
100 proccreate(timerproc, nil, STACK);
101 }
102
103 Timer*
timerstart(int dt)104 timerstart(int dt)
105 {
106 Timer *t;
107
108 t = timer;
109 if(t)
110 timer = timer->next;
111 else{
112 t = emalloc(sizeof(Timer));
113 t->c = chancreate(sizeof(int), 0);
114 }
115 t->next = nil;
116 t->dt = dt;
117 t->cancel = FALSE;
118 sendp(ctimer, t);
119 return t;
120 }
121