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