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 ColombierperiodicAlloc(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 ColombierperiodicKill(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 ColombierperiodicFree(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 ColombierperiodicThread(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