xref: /plan9-contrib/sys/src/9k/port/alarm.c (revision 406c76facc4b13aa2a55454bf4091aab9f03da22)
19ef1f84bSDavid du Colombier #include	"u.h"
29ef1f84bSDavid du Colombier #include	"../port/lib.h"
39ef1f84bSDavid du Colombier #include	"mem.h"
49ef1f84bSDavid du Colombier #include	"dat.h"
59ef1f84bSDavid du Colombier #include	"fns.h"
69ef1f84bSDavid du Colombier 
79ef1f84bSDavid du Colombier static Alarms	alarms;
89ef1f84bSDavid du Colombier static Rendez	alarmr;
99ef1f84bSDavid du Colombier 
109ef1f84bSDavid du Colombier void
alarmkproc(void *)119ef1f84bSDavid du Colombier alarmkproc(void*)
129ef1f84bSDavid du Colombier {
139ef1f84bSDavid du Colombier 	Proc *rp;
149ef1f84bSDavid du Colombier 	ulong now;
159ef1f84bSDavid du Colombier 
169ef1f84bSDavid du Colombier 	for(;;){
179ef1f84bSDavid du Colombier 		now = sys->ticks;
189ef1f84bSDavid du Colombier 		qlock(&alarms);
19*406c76faSDavid du Colombier 		/*
20*406c76faSDavid du Colombier 		 * the odd test of now vs. rp->alarm is to cope with
21*406c76faSDavid du Colombier 		 * now wrapping around.
22*406c76faSDavid du Colombier 		 */
23*406c76faSDavid du Colombier 		while((rp = alarms.head) && (long)(now - rp->alarm) >= 0){
249ef1f84bSDavid du Colombier 			if(rp->alarm != 0L){
259ef1f84bSDavid du Colombier 				if(canqlock(&rp->debug)){
269ef1f84bSDavid du Colombier 					if(!waserror()){
279ef1f84bSDavid du Colombier 						postnote(rp, 0, "alarm", NUser);
289ef1f84bSDavid du Colombier 						poperror();
299ef1f84bSDavid du Colombier 					}
309ef1f84bSDavid du Colombier 					qunlock(&rp->debug);
319ef1f84bSDavid du Colombier 					rp->alarm = 0L;
329ef1f84bSDavid du Colombier 				}else
339ef1f84bSDavid du Colombier 					break;
349ef1f84bSDavid du Colombier 			}
359ef1f84bSDavid du Colombier 			alarms.head = rp->palarm;
369ef1f84bSDavid du Colombier 		}
379ef1f84bSDavid du Colombier 		qunlock(&alarms);
389ef1f84bSDavid du Colombier 
399ef1f84bSDavid du Colombier 		sleep(&alarmr, return0, 0);
409ef1f84bSDavid du Colombier 	}
419ef1f84bSDavid du Colombier }
429ef1f84bSDavid du Colombier 
439ef1f84bSDavid du Colombier /*
449ef1f84bSDavid du Colombier  *  called every clock tick
459ef1f84bSDavid du Colombier  */
469ef1f84bSDavid du Colombier void
checkalarms(void)479ef1f84bSDavid du Colombier checkalarms(void)
489ef1f84bSDavid du Colombier {
499ef1f84bSDavid du Colombier 	Proc *p;
509ef1f84bSDavid du Colombier 	ulong now;
519ef1f84bSDavid du Colombier 
529ef1f84bSDavid du Colombier 	p = alarms.head;
539ef1f84bSDavid du Colombier 	now = sys->ticks;
549ef1f84bSDavid du Colombier 
55*406c76faSDavid du Colombier 	if(p && (long)(now - p->alarm) >= 0)
569ef1f84bSDavid du Colombier 		wakeup(&alarmr);
579ef1f84bSDavid du Colombier }
589ef1f84bSDavid du Colombier 
599ef1f84bSDavid du Colombier ulong
procalarm(ulong time)609ef1f84bSDavid du Colombier procalarm(ulong time)
619ef1f84bSDavid du Colombier {
629ef1f84bSDavid du Colombier 	Proc **l, *f;
639ef1f84bSDavid du Colombier 	ulong when, old;
649ef1f84bSDavid du Colombier 
659ef1f84bSDavid du Colombier 	if(up->alarm)
669ef1f84bSDavid du Colombier 		old = tk2ms(up->alarm - sys->ticks);
679ef1f84bSDavid du Colombier 	else
689ef1f84bSDavid du Colombier 		old = 0;
699ef1f84bSDavid du Colombier 	if(time == 0) {
709ef1f84bSDavid du Colombier 		up->alarm = 0;
719ef1f84bSDavid du Colombier 		return old;
729ef1f84bSDavid du Colombier 	}
739ef1f84bSDavid du Colombier 	when = ms2tk(time)+sys->ticks;
74*406c76faSDavid du Colombier 	if(when == 0)		/* ticks have wrapped to 0? */
75*406c76faSDavid du Colombier 		when = 1;	/* distinguish a wrapped alarm from no alarm */
769ef1f84bSDavid du Colombier 
779ef1f84bSDavid du Colombier 	qlock(&alarms);
789ef1f84bSDavid du Colombier 	l = &alarms.head;
799ef1f84bSDavid du Colombier 	for(f = *l; f; f = f->palarm) {
809ef1f84bSDavid du Colombier 		if(up == f){
819ef1f84bSDavid du Colombier 			*l = f->palarm;
829ef1f84bSDavid du Colombier 			break;
839ef1f84bSDavid du Colombier 		}
849ef1f84bSDavid du Colombier 		l = &f->palarm;
859ef1f84bSDavid du Colombier 	}
869ef1f84bSDavid du Colombier 
879ef1f84bSDavid du Colombier 	up->palarm = 0;
889ef1f84bSDavid du Colombier 	if(alarms.head) {
899ef1f84bSDavid du Colombier 		l = &alarms.head;
909ef1f84bSDavid du Colombier 		for(f = *l; f; f = f->palarm) {
91*406c76faSDavid du Colombier 			if((long)(f->alarm - when) >= 0) {
929ef1f84bSDavid du Colombier 				up->palarm = f;
939ef1f84bSDavid du Colombier 				*l = up;
949ef1f84bSDavid du Colombier 				goto done;
959ef1f84bSDavid du Colombier 			}
969ef1f84bSDavid du Colombier 			l = &f->palarm;
979ef1f84bSDavid du Colombier 		}
989ef1f84bSDavid du Colombier 		*l = up;
999ef1f84bSDavid du Colombier 	}
1009ef1f84bSDavid du Colombier 	else
1019ef1f84bSDavid du Colombier 		alarms.head = up;
1029ef1f84bSDavid du Colombier done:
1039ef1f84bSDavid du Colombier 	up->alarm = when;
1049ef1f84bSDavid du Colombier 	qunlock(&alarms);
1059ef1f84bSDavid du Colombier 
1069ef1f84bSDavid du Colombier 	return old;
1079ef1f84bSDavid du Colombier }
108