xref: /plan9-contrib/sys/src/9/port/alarm.c (revision 6bbfed0d85c6d7248503ef0614d0f1e40438b735)
13e12c5d1SDavid du Colombier #include	"u.h"
23e12c5d1SDavid du Colombier #include	"../port/lib.h"
33e12c5d1SDavid du Colombier #include	"mem.h"
43e12c5d1SDavid du Colombier #include	"dat.h"
53e12c5d1SDavid du Colombier #include	"fns.h"
63e12c5d1SDavid du Colombier 
74b348146SDavid du Colombier static Alarms	alarms;
84b348146SDavid du Colombier static Rendez	alarmr;
93e12c5d1SDavid du Colombier 
103e12c5d1SDavid du Colombier void
alarmkproc(void *)117dd7cddfSDavid du Colombier alarmkproc(void*)
123e12c5d1SDavid du Colombier {
133e12c5d1SDavid du Colombier 	Proc *rp;
143e12c5d1SDavid du Colombier 	ulong now;
153e12c5d1SDavid du Colombier 
163e12c5d1SDavid du Colombier 	for(;;){
173e12c5d1SDavid du Colombier 		now = MACHP(0)->ticks;
183e12c5d1SDavid du Colombier 		qlock(&alarms);
19*6bbfed0dSDavid du Colombier 		/*
20*6bbfed0dSDavid du Colombier 		 * the odd test of now vs. rp->alarm is to cope with
21*6bbfed0dSDavid du Colombier 		 * now wrapping around.
22*6bbfed0dSDavid du Colombier 		 */
23*6bbfed0dSDavid du Colombier 		while((rp = alarms.head) && (long)(now - rp->alarm) >= 0){
243e12c5d1SDavid du Colombier 			if(rp->alarm != 0L){
257dd7cddfSDavid du Colombier 				if(canqlock(&rp->debug)){
263e12c5d1SDavid du Colombier 					if(!waserror()){
273e12c5d1SDavid du Colombier 						postnote(rp, 0, "alarm", NUser);
283e12c5d1SDavid du Colombier 						poperror();
293e12c5d1SDavid du Colombier 					}
303e12c5d1SDavid du Colombier 					qunlock(&rp->debug);
313e12c5d1SDavid du Colombier 					rp->alarm = 0L;
327dd7cddfSDavid du Colombier 				}else
337dd7cddfSDavid du Colombier 					break;
343e12c5d1SDavid du Colombier 			}
353e12c5d1SDavid du Colombier 			alarms.head = rp->palarm;
363e12c5d1SDavid du Colombier 		}
373e12c5d1SDavid du Colombier 		qunlock(&alarms);
383e12c5d1SDavid du Colombier 
393e12c5d1SDavid du Colombier 		sleep(&alarmr, return0, 0);
403e12c5d1SDavid du Colombier 	}
413e12c5d1SDavid du Colombier }
423e12c5d1SDavid du Colombier 
433e12c5d1SDavid du Colombier /*
443e12c5d1SDavid du Colombier  *  called every clock tick
453e12c5d1SDavid du Colombier  */
463e12c5d1SDavid du Colombier void
checkalarms(void)473e12c5d1SDavid du Colombier checkalarms(void)
483e12c5d1SDavid du Colombier {
493e12c5d1SDavid du Colombier 	Proc *p;
503e12c5d1SDavid du Colombier 	ulong now;
513e12c5d1SDavid du Colombier 
523e12c5d1SDavid du Colombier 	p = alarms.head;
533e12c5d1SDavid du Colombier 	now = MACHP(0)->ticks;
543e12c5d1SDavid du Colombier 
55*6bbfed0dSDavid du Colombier 	if(p && (long)(now - p->alarm) >= 0)
563e12c5d1SDavid du Colombier 		wakeup(&alarmr);
573e12c5d1SDavid du Colombier }
583e12c5d1SDavid du Colombier 
593e12c5d1SDavid du Colombier ulong
procalarm(ulong time)603e12c5d1SDavid du Colombier procalarm(ulong time)
613e12c5d1SDavid du Colombier {
627dd7cddfSDavid du Colombier 	Proc **l, *f;
633e12c5d1SDavid du Colombier 	ulong when, old;
643e12c5d1SDavid du Colombier 
657dd7cddfSDavid du Colombier 	if(up->alarm)
663ff48bf5SDavid du Colombier 		old = tk2ms(up->alarm - MACHP(0)->ticks);
67219b2ee8SDavid du Colombier 	else
68219b2ee8SDavid du Colombier 		old = 0;
693e12c5d1SDavid du Colombier 	if(time == 0) {
707dd7cddfSDavid du Colombier 		up->alarm = 0;
713e12c5d1SDavid du Colombier 		return old;
723e12c5d1SDavid du Colombier 	}
739a747e4fSDavid du Colombier 	when = ms2tk(time)+MACHP(0)->ticks;
74*6bbfed0dSDavid du Colombier 	if(when == 0)		/* ticks have wrapped to 0? */
75*6bbfed0dSDavid du Colombier 		when = 1;	/* distinguish a wrapped alarm from no alarm */
763e12c5d1SDavid du Colombier 
773e12c5d1SDavid du Colombier 	qlock(&alarms);
783e12c5d1SDavid du Colombier 	l = &alarms.head;
793e12c5d1SDavid du Colombier 	for(f = *l; f; f = f->palarm) {
807dd7cddfSDavid du Colombier 		if(up == f){
813e12c5d1SDavid du Colombier 			*l = f->palarm;
823e12c5d1SDavid du Colombier 			break;
833e12c5d1SDavid du Colombier 		}
843e12c5d1SDavid du Colombier 		l = &f->palarm;
853e12c5d1SDavid du Colombier 	}
863e12c5d1SDavid du Colombier 
877dd7cddfSDavid du Colombier 	up->palarm = 0;
883e12c5d1SDavid du Colombier 	if(alarms.head) {
893e12c5d1SDavid du Colombier 		l = &alarms.head;
903e12c5d1SDavid du Colombier 		for(f = *l; f; f = f->palarm) {
91*6bbfed0dSDavid du Colombier 			if((long)(f->alarm - when) >= 0) {
927dd7cddfSDavid du Colombier 				up->palarm = f;
937dd7cddfSDavid du Colombier 				*l = up;
943e12c5d1SDavid du Colombier 				goto done;
953e12c5d1SDavid du Colombier 			}
963e12c5d1SDavid du Colombier 			l = &f->palarm;
973e12c5d1SDavid du Colombier 		}
987dd7cddfSDavid du Colombier 		*l = up;
993e12c5d1SDavid du Colombier 	}
1003e12c5d1SDavid du Colombier 	else
1017dd7cddfSDavid du Colombier 		alarms.head = up;
1023e12c5d1SDavid du Colombier done:
1037dd7cddfSDavid du Colombier 	up->alarm = when;
1043e12c5d1SDavid du Colombier 	qunlock(&alarms);
1053e12c5d1SDavid du Colombier 
1063e12c5d1SDavid du Colombier 	return old;
1073e12c5d1SDavid du Colombier }
108