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 static
17 uint
18 msec(void)
19 {
20 return nsec()/1000000;
21 }
23 void
24 timerstop(Timer *t)
25 {
26 t->next = timer;
27 timer = t;
28 }
30 void
31 timercancel(Timer *t)
32 {
33 t->cancel = TRUE;
34 }
36 static
37 void
38 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 is
68 * now sending on ctimer
69 */
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 void
97 timerinit(void)
98 {
99 ctimer = chancreate(sizeof(Timer*), 100);
100 proccreate(timerproc, nil, STACK);
103 /*
104 * timeralloc() and timerfree() don't lock, so can only be
105 * called from the main proc.
106 */
108 Timer*
109 timerstart(int dt)
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);
120 t->next = nil;
121 t->dt = dt;
122 t->cancel = FALSE;
123 sendp(ctimer, t);
124 return t;