]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/rio/time.c
rio: /dev/kbd cleanup
[plan9front.git] / sys / src / cmd / rio / time.c
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"
12
13 static Channel* ctimer; /* chan(Timer*)[100] */
14 static Timer *timer;
15
16 static
17 uint
18 msec(void)
19 {
20         return nsec()/1000000;
21 }
22
23 void
24 timerstop(Timer *t)
25 {
26         t->next = timer;
27         timer = t;
28 }
29
30 void
31 timercancel(Timer *t)
32 {
33         t->cancel = TRUE;
34 }
35
36 static
37 void
38 timerproc(void*)
39 {
40         int i, nt, na, dt, del;
41         Timer **t, *x;
42         uint old, new;
43
44         rfork(RFFDG);
45         threadsetname("TIMERPROC");
46         t = nil;
47         na = 0;
48         nt = 0;
49         old = msec();
50         for(;;){
51                 sleep(1);       /* will sleep minimum incr */
52                 new = msec();
53                 dt = new-old;
54                 old = new;
55                 if(dt < 0)      /* timer wrapped; go around, losing a tick */
56                         continue;
57                 for(i=0; i<nt; i++){
58                         x = t[i];
59                         x->dt -= dt;
60                         del = 0;
61                         if(x->cancel){
62                                 timerstop(x);
63                                 del = 1;
64                         }else if(x->dt <= 0){
65                                 /*
66                                  * avoid possible deadlock if client is
67                                  * now sending on ctimer
68                                  */
69                                 if(nbsendul(x->c, 0) > 0)
70                                         del = 1;
71                         }
72                         if(del){
73                                 memmove(&t[i], &t[i+1], (nt-i-1)*sizeof t[0]);
74                                 --nt;
75                                 --i;
76                         }
77                 }
78                 if(nt == 0){
79                         x = recvp(ctimer);
80         gotit:
81                         if(nt == na){
82                                 na += 10;
83                                 t = realloc(t, na*sizeof(Timer*));
84                                 if(t == nil)
85                                         abort();
86                         }
87                         t[nt++] = x;
88                         old = msec();
89                 }
90                 if(nbrecv(ctimer, &x) > 0)
91                         goto gotit;
92         }
93 }
94
95 void
96 timerinit(void)
97 {
98         ctimer = chancreate(sizeof(Timer*), 100);
99         proccreate(timerproc, nil, STACK);
100 }
101
102 /*
103  * timeralloc() and timerfree() don't lock, so can only be
104  * called from the main proc.
105  */
106
107 Timer*
108 timerstart(int dt)
109 {
110         Timer *t;
111
112         t = timer;
113         if(t)
114                 timer = timer->next;
115         else{
116                 t = emalloc(sizeof(Timer));
117                 t->c = chancreate(sizeof(int), 0);
118         }
119         t->next = nil;
120         t->dt = dt;
121         t->cancel = FALSE;
122         sendp(ctimer, t);
123         return t;
124 }