xref: /plan9-contrib/sys/src/cmd/fossil/periodic.c (revision 13ab33fbec1dce6058a37685859b28e104de23a6)
15e96a66cSDavid du Colombier #include "stdinc.h"
25e96a66cSDavid du Colombier #include "dat.h"
35e96a66cSDavid du Colombier #include "fns.h"
45e96a66cSDavid du Colombier #include "error.h"
55e96a66cSDavid du Colombier 
65e96a66cSDavid du Colombier struct Periodic {
7d7aba6c3SDavid du Colombier 	QLock lk;
87fd2696aSDavid du Colombier 	int die;		/* flag: quit if set */
97fd2696aSDavid du Colombier 	void (*f)(void*);	/* call this each period */
107fd2696aSDavid du Colombier 	void *a;		/* argument to f */
117fd2696aSDavid du Colombier 	int msec;		/* period */
125e96a66cSDavid du Colombier };
135e96a66cSDavid du Colombier 
145e96a66cSDavid du Colombier static void periodicThread(void *a);
155e96a66cSDavid du Colombier 
165e96a66cSDavid du Colombier Periodic *
periodicAlloc(void (* f)(void *),void * a,int msec)175e96a66cSDavid du Colombier periodicAlloc(void (*f)(void*), void *a, int msec)
185e96a66cSDavid du Colombier {
195e96a66cSDavid du Colombier 	Periodic *p;
205e96a66cSDavid du Colombier 
21d7aba6c3SDavid du Colombier 	p = vtmallocz(sizeof(Periodic));
225e96a66cSDavid du Colombier 	p->f = f;
235e96a66cSDavid du Colombier 	p->a = a;
245e96a66cSDavid du Colombier 	p->msec = msec;
255e96a66cSDavid du Colombier 	if(p->msec < 10)
265e96a66cSDavid du Colombier 		p->msec = 10;
275e96a66cSDavid du Colombier 
28d7aba6c3SDavid du Colombier 	proccreate(periodicThread, p, STACK);
295e96a66cSDavid du Colombier 	return p;
305e96a66cSDavid du Colombier }
315e96a66cSDavid du Colombier 
325e96a66cSDavid du Colombier void
periodicKill(Periodic * p)335e96a66cSDavid du Colombier periodicKill(Periodic *p)
345e96a66cSDavid du Colombier {
355e96a66cSDavid du Colombier 	if(p == nil)
365e96a66cSDavid du Colombier 		return;
37d7aba6c3SDavid du Colombier 	qlock(&p->lk);
385e96a66cSDavid du Colombier 	p->die = 1;
39d7aba6c3SDavid du Colombier 	qunlock(&p->lk);
405e96a66cSDavid du Colombier }
415e96a66cSDavid du Colombier 
425e96a66cSDavid du Colombier static void
periodicFree(Periodic * p)435e96a66cSDavid du Colombier periodicFree(Periodic *p)
445e96a66cSDavid du Colombier {
45d7aba6c3SDavid du Colombier 	vtfree(p);
465e96a66cSDavid du Colombier }
475e96a66cSDavid du Colombier 
485e96a66cSDavid du Colombier static void
periodicThread(void * a)495e96a66cSDavid du Colombier periodicThread(void *a)
505e96a66cSDavid du Colombier {
515e96a66cSDavid du Colombier 	Periodic *p = a;
527fd2696aSDavid du Colombier 	vlong t, ct, ts;		/* times in ms. */
535e96a66cSDavid du Colombier 
54d7aba6c3SDavid du Colombier 	threadsetname("periodic");
555e96a66cSDavid du Colombier 
567fd2696aSDavid du Colombier 	ct = nsec() / 1000000;
577fd2696aSDavid du Colombier 	t = ct + p->msec;		/* call p->f at or after this time */
585e96a66cSDavid du Colombier 
595e96a66cSDavid du Colombier 	for(;;){
60*13ab33fbSDavid du Colombier 		if(t - ct > p->msec)	/* time went backwards? */
61*13ab33fbSDavid du Colombier 			t = ct + p->msec;
627fd2696aSDavid du Colombier 		ts = t - ct;		/* ms. to next cycle's start */
635e96a66cSDavid du Colombier 		if(ts > 1000)
647fd2696aSDavid du Colombier 			ts = 1000;	/* bound sleep duration */
657fd2696aSDavid du Colombier 		if(ts > 0)
667fd2696aSDavid du Colombier 			sleep(ts);	/* wait for cycle's start */
677fd2696aSDavid du Colombier 
68d7aba6c3SDavid du Colombier 		qlock(&p->lk);
695e96a66cSDavid du Colombier 		if(p->die){
70d7aba6c3SDavid du Colombier 			qunlock(&p->lk);
715e96a66cSDavid du Colombier 			break;
725e96a66cSDavid du Colombier 		}
737fd2696aSDavid du Colombier 		ct = nsec() / 1000000;
747fd2696aSDavid du Colombier 		if(t <= ct){		/* due to call p->f? */
755e96a66cSDavid du Colombier 			p->f(p->a);
767fd2696aSDavid du Colombier 			ct = nsec() / 1000000;
777fd2696aSDavid du Colombier 			while(t <= ct)	/* advance t to future cycle start */
785e96a66cSDavid du Colombier 				t += p->msec;
795e96a66cSDavid du Colombier 		}
80d7aba6c3SDavid du Colombier 		qunlock(&p->lk);
815e96a66cSDavid du Colombier 	}
825e96a66cSDavid du Colombier 	periodicFree(p);
835e96a66cSDavid du Colombier }
845e96a66cSDavid du Colombier 
85