Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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 <plumb.h>
11
#include "dat.h"
12
#include "fns.h"
13
 
14
static Channel*	ctimer;	/* chan(Timer*)[100] */
15
static Timer *timer;
16
 
17
static
18
uint
19
msec(void)
20
{
21
	return nsec()/1000000;
22
}
23
 
24
void
25
timerstop(Timer *t)
26
{
27
	t->next = timer;
28
	timer = t;
29
}
30
 
31
void
32
timercancel(Timer *t)
33
{
34
	t->cancel = TRUE;
35
}
36
 
37
static
38
void
39
timerproc(void*)
40
{
41
	int i, nt, na, dt, del;
42
	Timer **t, *x;
43
	uint old, new;
44
 
45
	threadsetname("timerproc");
46
	rfork(RFFDG);
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 = FALSE;
62
			if(x->cancel){
63
				timerstop(x);
64
				del = TRUE;
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 = TRUE;
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
					error("timer realloc failed");
87
			}
88
			t[nt++] = x;
89
			old = msec();
90
		}
91
		if(nbrecv(ctimer, &x) > 0)
92
			goto gotit;
93
	}
94
}
95
 
96
void
97
timerinit(void)
98
{
99
	ctimer = chancreate(sizeof(Timer*), 100);
100
	proccreate(timerproc, nil, STACK);
101
}
102
 
103
Timer*
104
timerstart(int dt)
105
{
106
	Timer *t;
107
 
108
	t = timer;
109
	if(t)
110
		timer = timer->next;
111
	else{
112
		t = emalloc(sizeof(Timer));
113
		t->c = chancreate(sizeof(int), 0);
114
	}
115
	t->next = nil;
116
	t->dt = dt;
117
	t->cancel = FALSE;
118
	sendp(ctimer, t);
119
	return t;
120
}