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 { 75e96a66cSDavid du Colombier VtLock *lk; 8*7fd2696aSDavid du Colombier int die; /* flag: quit if set */ 9*7fd2696aSDavid du Colombier void (*f)(void*); /* call this each period */ 10*7fd2696aSDavid du Colombier void *a; /* argument to f */ 11*7fd2696aSDavid 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 215e96a66cSDavid du Colombier p = vtMemAllocZ(sizeof(Periodic)); 225e96a66cSDavid du Colombier p->lk = vtLockAlloc(); 235e96a66cSDavid du Colombier p->f = f; 245e96a66cSDavid du Colombier p->a = a; 255e96a66cSDavid du Colombier p->msec = msec; 265e96a66cSDavid du Colombier if(p->msec < 10) 275e96a66cSDavid du Colombier p->msec = 10; 285e96a66cSDavid du Colombier 295e96a66cSDavid du Colombier vtThread(periodicThread, p); 305e96a66cSDavid du Colombier return p; 315e96a66cSDavid du Colombier } 325e96a66cSDavid du Colombier 335e96a66cSDavid du Colombier void periodicKill(Periodic * p)345e96a66cSDavid du ColombierperiodicKill(Periodic *p) 355e96a66cSDavid du Colombier { 365e96a66cSDavid du Colombier if(p == nil) 375e96a66cSDavid du Colombier return; 385e96a66cSDavid du Colombier vtLock(p->lk); 395e96a66cSDavid du Colombier p->die = 1; 405e96a66cSDavid du Colombier vtUnlock(p->lk); 415e96a66cSDavid du Colombier } 425e96a66cSDavid du Colombier 435e96a66cSDavid du Colombier static void periodicFree(Periodic * p)445e96a66cSDavid du ColombierperiodicFree(Periodic *p) 455e96a66cSDavid du Colombier { 465e96a66cSDavid du Colombier vtLockFree(p->lk); 475e96a66cSDavid du Colombier vtMemFree(p); 485e96a66cSDavid du Colombier } 495e96a66cSDavid du Colombier 505e96a66cSDavid du Colombier static void periodicThread(void * a)515e96a66cSDavid du ColombierperiodicThread(void *a) 525e96a66cSDavid du Colombier { 535e96a66cSDavid du Colombier Periodic *p = a; 54*7fd2696aSDavid du Colombier vlong t, ct, ts; /* times in ms. */ 555e96a66cSDavid du Colombier 565e96a66cSDavid du Colombier vtThreadSetName("periodic"); 575e96a66cSDavid du Colombier 58*7fd2696aSDavid du Colombier ct = nsec() / 1000000; 59*7fd2696aSDavid du Colombier t = ct + p->msec; /* call p->f at or after this time */ 605e96a66cSDavid du Colombier 615e96a66cSDavid du Colombier for(;;){ 62*7fd2696aSDavid du Colombier ts = t - ct; /* ms. to next cycle's start */ 635e96a66cSDavid du Colombier if(ts > 1000) 64*7fd2696aSDavid du Colombier ts = 1000; /* bound sleep duration */ 65*7fd2696aSDavid du Colombier if(ts > 0) 66*7fd2696aSDavid du Colombier sleep(ts); /* wait for cycle's start */ 67*7fd2696aSDavid du Colombier 685e96a66cSDavid du Colombier vtLock(p->lk); 695e96a66cSDavid du Colombier if(p->die){ 705e96a66cSDavid du Colombier vtUnlock(p->lk); 715e96a66cSDavid du Colombier break; 725e96a66cSDavid du Colombier } 73*7fd2696aSDavid du Colombier ct = nsec() / 1000000; 74*7fd2696aSDavid du Colombier if(t <= ct){ /* due to call p->f? */ 755e96a66cSDavid du Colombier p->f(p->a); 76*7fd2696aSDavid du Colombier ct = nsec() / 1000000; 77*7fd2696aSDavid du Colombier while(t <= ct) /* advance t to future cycle start */ 785e96a66cSDavid du Colombier t += p->msec; 795e96a66cSDavid du Colombier } 805e96a66cSDavid du Colombier vtUnlock(p->lk); 815e96a66cSDavid du Colombier } 825e96a66cSDavid du Colombier periodicFree(p); 835e96a66cSDavid du Colombier } 845e96a66cSDavid du Colombier 85