xref: /plan9/sys/src/9/port/alarm.c (revision 6bbfed0d85c6d7248503ef0614d0f1e40438b735)
1 #include	"u.h"
2 #include	"../port/lib.h"
3 #include	"mem.h"
4 #include	"dat.h"
5 #include	"fns.h"
6 
7 static Alarms	alarms;
8 static Rendez	alarmr;
9 
10 void
alarmkproc(void *)11 alarmkproc(void*)
12 {
13 	Proc *rp;
14 	ulong now;
15 
16 	for(;;){
17 		now = MACHP(0)->ticks;
18 		qlock(&alarms);
19 		/*
20 		 * the odd test of now vs. rp->alarm is to cope with
21 		 * now wrapping around.
22 		 */
23 		while((rp = alarms.head) && (long)(now - rp->alarm) >= 0){
24 			if(rp->alarm != 0L){
25 				if(canqlock(&rp->debug)){
26 					if(!waserror()){
27 						postnote(rp, 0, "alarm", NUser);
28 						poperror();
29 					}
30 					qunlock(&rp->debug);
31 					rp->alarm = 0L;
32 				}else
33 					break;
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
checkalarms(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 && (long)(now - p->alarm) >= 0)
56 		wakeup(&alarmr);
57 }
58 
59 ulong
procalarm(ulong time)60 procalarm(ulong time)
61 {
62 	Proc **l, *f;
63 	ulong when, old;
64 
65 	if(up->alarm)
66 		old = tk2ms(up->alarm - MACHP(0)->ticks);
67 	else
68 		old = 0;
69 	if(time == 0) {
70 		up->alarm = 0;
71 		return old;
72 	}
73 	when = ms2tk(time)+MACHP(0)->ticks;
74 	if(when == 0)		/* ticks have wrapped to 0? */
75 		when = 1;	/* distinguish a wrapped alarm from no alarm */
76 
77 	qlock(&alarms);
78 	l = &alarms.head;
79 	for(f = *l; f; f = f->palarm) {
80 		if(up == f){
81 			*l = f->palarm;
82 			break;
83 		}
84 		l = &f->palarm;
85 	}
86 
87 	up->palarm = 0;
88 	if(alarms.head) {
89 		l = &alarms.head;
90 		for(f = *l; f; f = f->palarm) {
91 			if((long)(f->alarm - when) >= 0) {
92 				up->palarm = f;
93 				*l = up;
94 				goto done;
95 			}
96 			l = &f->palarm;
97 		}
98 		*l = up;
99 	}
100 	else
101 		alarms.head = up;
102 done:
103 	up->alarm = when;
104 	qunlock(&alarms);
105 
106 	return old;
107 }
108