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