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 <libsec.h>
12 #include "dat.h"
13 #include "fns.h"
15 static Channel* ctimer; /* chan(Timer*)[100] */
16 static Timer *timer;
18 static
19 uint
20 msec(void)
21 {
22 return nsec()/1000000;
23 }
25 void
26 timerstop(Timer *t)
27 {
28 t->next = timer;
29 timer = t;
30 }
32 void
33 timercancel(Timer *t)
34 {
35 t->cancel = TRUE;
36 }
38 static
39 void
40 timerproc(void *v)
41 {
42 int i, nt, na, dt, del;
43 Timer **t, *x;
44 uint old, new;
46 USED(v);
47 threadsetname("timerproc");
48 rfork(RFFDG);
49 t = nil;
50 na = 0;
51 nt = 0;
52 old = msec();
53 for(;;){
54 sleep(10); /* longer sleeps here delay recv on ctimer, but 10ms should not be noticeable */
55 new = msec();
56 dt = new-old;
57 old = new;
58 if(dt < 0) /* timer wrapped; go around, losing a tick */
59 continue;
60 for(i=0; i<nt; i++){
61 x = t[i];
62 x->dt -= dt;
63 del = FALSE;
64 if(x->cancel){
65 timerstop(x);
66 del = TRUE;
67 }else if(x->dt <= 0){
68 /*
69 * avoid possible deadlock if client is
70 * now sending on ctimer
71 */
72 if(nbsendul(x->c, 0) > 0)
73 del = TRUE;
74 }
75 if(del){
76 memmove(&t[i], &t[i+1], (nt-i-1)*sizeof t[0]);
77 --nt;
78 --i;
79 }
80 }
81 if(nt == 0){
82 x = recvp(ctimer);
83 gotit:
84 if(nt == na){
85 na += 10;
86 t = realloc(t, na*sizeof(Timer*));
87 if(t == nil)
88 error("timer realloc failed");
89 }
90 t[nt++] = x;
91 old = msec();
92 }
93 if(nbrecv(ctimer, &x) > 0)
94 goto gotit;
95 }
96 }
98 void
99 timerinit(void)
101 ctimer = chancreate(sizeof(Timer*), 100);
102 chansetname(ctimer, "ctimer");
103 proccreate(timerproc, nil, STACK);
106 Timer*
107 timerstart(int dt)
109 Timer *t;
111 t = timer;
112 if(t)
113 timer = timer->next;
114 else{
115 t = emalloc(sizeof(Timer));
116 t->c = chancreate(sizeof(int), 0);
117 chansetname(t->c, "tc%p", t->c);
119 t->next = nil;
120 t->dt = dt;
121 t->cancel = FALSE;
122 sendp(ctimer, t);
123 return t;