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 static
18 uint
19 msec(void)
20 {
21 return nsec()/1000000;
22 }
24 void
25 timerstop(Timer *t)
26 {
27 t->next = timer;
28 timer = t;
29 }
31 void
32 timercancel(Timer *t)
33 {
34 t->cancel = TRUE;
35 }
37 static
38 void
39 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 is
69 * now sending on ctimer
70 */
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 void
98 timerinit(void)
99 {
100 ctimer = chancreate(sizeof(Timer*), 100);
101 chansetname(ctimer, "ctimer");
102 proccreate(timerproc, nil, STACK);
105 Timer*
106 timerstart(int dt)
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);
118 t->next = nil;
119 t->dt = dt;
120 t->cancel = FALSE;
121 sendp(ctimer, t);
122 return t;