xref: /plan9-contrib/sys/src/9/port/alarm.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include	"u.h"
2 #include	"../port/lib.h"
3 #include	"mem.h"
4 #include	"dat.h"
5 #include	"fns.h"
6 #include	"io.h"
7 
8 Alarms	alarms;
9 Rendez	alarmr;
10 Talarm	talarm;
11 
12 void
13 alarmkproc(void *arg)
14 {
15 	Proc *rp;
16 	ulong now;
17 
18 	USED(arg);
19 
20 	for(;;){
21 		now = MACHP(0)->ticks;
22 		qlock(&alarms);
23 		while((rp = alarms.head) && rp->alarm <= now) {
24 			if(rp->alarm != 0L) {
25 				if(!canqlock(&rp->debug))
26 					break;
27 
28 				if(!waserror()) {
29 					postnote(rp, 0, "alarm", NUser);
30 					poperror();
31 				}
32 				qunlock(&rp->debug);
33 				rp->alarm = 0L;
34 			}
35 			alarms.head = rp->palarm;
36 		}
37 		qunlock(&alarms);
38 
39 		sleep(&alarmr, return0, 0);
40 	}
41 }
42 
43 /*
44  *  called every clock tick
45  */
46 void
47 checkalarms(void)
48 {
49 	Proc *p;
50 	ulong now;
51 
52 	p = alarms.head;
53 	now = MACHP(0)->ticks;
54 
55 	if(p && p->alarm <= now)
56 		wakeup(&alarmr);
57 
58 	if(talarm.list == 0 || canlock(&talarm) == 0)
59 		return;
60 
61 	for(;;) {
62 		p = talarm.list;
63 		if(p == 0)
64 			break;
65 
66 		if(p->twhen == 0) {
67 			talarm.list = p->tlink;
68 			p->trend = 0;
69 			continue;
70 		}
71 		if(now < p->twhen)
72 			break;
73 		wakeup(p->trend);
74 		talarm.list = p->tlink;
75 		p->trend = 0;
76 	}
77 
78 	unlock(&talarm);
79 }
80 
81 ulong
82 procalarm(ulong time)
83 {
84 	Proc **l, *f, *p;
85 	ulong when, old;
86 
87 	p = u->p;
88 	if(p->alarm)
89 		old = TK2MS(p->alarm - MACHP(0)->ticks);
90 	else
91 		old = 0;
92 	if(time == 0) {
93 		p->alarm = 0;
94 		return old;
95 	}
96 	when = MS2TK(time)+MACHP(0)->ticks;
97 
98 	qlock(&alarms);
99 	l = &alarms.head;
100 	for(f = *l; f; f = f->palarm) {
101 		if(p == f){
102 			*l = f->palarm;
103 			break;
104 		}
105 		l = &f->palarm;
106 	}
107 
108 	p->palarm = 0;
109 	if(alarms.head) {
110 		l = &alarms.head;
111 		for(f = *l; f; f = f->palarm) {
112 			if(f->alarm > when) {
113 				p->palarm = f;
114 				*l = p;
115 				goto done;
116 			}
117 			l = &f->palarm;
118 		}
119 		*l = p;
120 	}
121 	else
122 		alarms.head = p;
123 done:
124 	p->alarm = when;
125 	qunlock(&alarms);
126 
127 	return old;
128 }
129