xref: /plan9/sys/src/cmd/acme/time.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <thread.h>
5*9a747e4fSDavid du Colombier #include <cursor.h>
67dd7cddfSDavid du Colombier #include <mouse.h>
77dd7cddfSDavid du Colombier #include <keyboard.h>
87dd7cddfSDavid du Colombier #include <frame.h>
97dd7cddfSDavid du Colombier #include <fcall.h>
107dd7cddfSDavid du Colombier #include <plumb.h>
117dd7cddfSDavid du Colombier #include "dat.h"
127dd7cddfSDavid du Colombier #include "fns.h"
137dd7cddfSDavid du Colombier 
147dd7cddfSDavid du Colombier static Channel*	ctimer;	/* chan(Timer*)[100] */
157dd7cddfSDavid du Colombier static Timer *timer;
167dd7cddfSDavid du Colombier 
177dd7cddfSDavid du Colombier static
187dd7cddfSDavid du Colombier uint
msec(void)197dd7cddfSDavid du Colombier msec(void)
207dd7cddfSDavid du Colombier {
217dd7cddfSDavid du Colombier 	return nsec()/1000000;
227dd7cddfSDavid du Colombier }
237dd7cddfSDavid du Colombier 
247dd7cddfSDavid du Colombier void
timerstop(Timer * t)257dd7cddfSDavid du Colombier timerstop(Timer *t)
267dd7cddfSDavid du Colombier {
277dd7cddfSDavid du Colombier 	t->next = timer;
287dd7cddfSDavid du Colombier 	timer = t;
297dd7cddfSDavid du Colombier }
307dd7cddfSDavid du Colombier 
317dd7cddfSDavid du Colombier void
timercancel(Timer * t)327dd7cddfSDavid du Colombier timercancel(Timer *t)
337dd7cddfSDavid du Colombier {
347dd7cddfSDavid du Colombier 	t->cancel = TRUE;
357dd7cddfSDavid du Colombier }
367dd7cddfSDavid du Colombier 
377dd7cddfSDavid du Colombier static
387dd7cddfSDavid du Colombier void
timerproc(void *)397dd7cddfSDavid du Colombier timerproc(void*)
407dd7cddfSDavid du Colombier {
417dd7cddfSDavid du Colombier 	int i, nt, na, dt, del;
427dd7cddfSDavid du Colombier 	Timer **t, *x;
437dd7cddfSDavid du Colombier 	uint old, new;
447dd7cddfSDavid du Colombier 
457dd7cddfSDavid du Colombier 	threadsetname("timerproc");
467dd7cddfSDavid du Colombier 	rfork(RFFDG);
477dd7cddfSDavid du Colombier 	t = nil;
487dd7cddfSDavid du Colombier 	na = 0;
497dd7cddfSDavid du Colombier 	nt = 0;
507dd7cddfSDavid du Colombier 	old = msec();
517dd7cddfSDavid du Colombier 	for(;;){
527dd7cddfSDavid du Colombier 		sleep(1);	/* will sleep minimum incr */
537dd7cddfSDavid du Colombier 		new = msec();
547dd7cddfSDavid du Colombier 		dt = new-old;
557dd7cddfSDavid du Colombier 		old = new;
567dd7cddfSDavid du Colombier 		if(dt < 0)	/* timer wrapped; go around, losing a tick */
577dd7cddfSDavid du Colombier 			continue;
587dd7cddfSDavid du Colombier 		for(i=0; i<nt; i++){
597dd7cddfSDavid du Colombier 			x = t[i];
607dd7cddfSDavid du Colombier 			x->dt -= dt;
617dd7cddfSDavid du Colombier 			del = FALSE;
627dd7cddfSDavid du Colombier 			if(x->cancel){
637dd7cddfSDavid du Colombier 				timerstop(x);
647dd7cddfSDavid du Colombier 				del = TRUE;
657dd7cddfSDavid du Colombier 			}else if(x->dt <= 0){
667dd7cddfSDavid du Colombier 				/*
677dd7cddfSDavid du Colombier 				 * avoid possible deadlock if client is
687dd7cddfSDavid du Colombier 				 * now sending on ctimer
697dd7cddfSDavid du Colombier 				 */
707dd7cddfSDavid du Colombier 				if(nbsendul(x->c, 0) > 0)
717dd7cddfSDavid du Colombier 					del = TRUE;
727dd7cddfSDavid du Colombier 			}
737dd7cddfSDavid du Colombier 			if(del){
747dd7cddfSDavid du Colombier 				memmove(&t[i], &t[i+1], (nt-i-1)*sizeof t[0]);
757dd7cddfSDavid du Colombier 				--nt;
767dd7cddfSDavid du Colombier 				--i;
777dd7cddfSDavid du Colombier 			}
787dd7cddfSDavid du Colombier 		}
797dd7cddfSDavid du Colombier 		if(nt == 0){
807dd7cddfSDavid du Colombier 			x = recvp(ctimer);
817dd7cddfSDavid du Colombier 	gotit:
827dd7cddfSDavid du Colombier 			if(nt == na){
837dd7cddfSDavid du Colombier 				na += 10;
847dd7cddfSDavid du Colombier 				t = realloc(t, na*sizeof(Timer*));
857dd7cddfSDavid du Colombier 				if(t == nil)
867dd7cddfSDavid du Colombier 					error("timer realloc failed");
877dd7cddfSDavid du Colombier 			}
887dd7cddfSDavid du Colombier 			t[nt++] = x;
897dd7cddfSDavid du Colombier 			old = msec();
907dd7cddfSDavid du Colombier 		}
917dd7cddfSDavid du Colombier 		if(nbrecv(ctimer, &x) > 0)
927dd7cddfSDavid du Colombier 			goto gotit;
937dd7cddfSDavid du Colombier 	}
947dd7cddfSDavid du Colombier }
957dd7cddfSDavid du Colombier 
967dd7cddfSDavid du Colombier void
timerinit(void)977dd7cddfSDavid du Colombier timerinit(void)
987dd7cddfSDavid du Colombier {
997dd7cddfSDavid du Colombier 	ctimer = chancreate(sizeof(Timer*), 100);
1007dd7cddfSDavid du Colombier 	proccreate(timerproc, nil, STACK);
1017dd7cddfSDavid du Colombier }
1027dd7cddfSDavid du Colombier 
1037dd7cddfSDavid du Colombier Timer*
timerstart(int dt)1047dd7cddfSDavid du Colombier timerstart(int dt)
1057dd7cddfSDavid du Colombier {
1067dd7cddfSDavid du Colombier 	Timer *t;
1077dd7cddfSDavid du Colombier 
1087dd7cddfSDavid du Colombier 	t = timer;
1097dd7cddfSDavid du Colombier 	if(t)
1107dd7cddfSDavid du Colombier 		timer = timer->next;
1117dd7cddfSDavid du Colombier 	else{
1127dd7cddfSDavid du Colombier 		t = emalloc(sizeof(Timer));
1137dd7cddfSDavid du Colombier 		t->c = chancreate(sizeof(int), 0);
1147dd7cddfSDavid du Colombier 	}
1157dd7cddfSDavid du Colombier 	t->next = nil;
1167dd7cddfSDavid du Colombier 	t->dt = dt;
1177dd7cddfSDavid du Colombier 	t->cancel = FALSE;
1187dd7cddfSDavid du Colombier 	sendp(ctimer, t);
1197dd7cddfSDavid du Colombier 	return t;
1207dd7cddfSDavid du Colombier }
121