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