1 #include "stdinc.h" 2 #include "dat.h" 3 #include "fns.h" 4 #include "error.h" 5 6 struct Periodic { 7 QLock lk; 8 int die; /* flag: quit if set */ 9 void (*f)(void*); /* call this each period */ 10 void *a; /* argument to f */ 11 int msec; /* period */ 12 }; 13 14 static void periodicThread(void *a); 15 16 Periodic * periodicAlloc(void (* f)(void *),void * a,int msec)17periodicAlloc(void (*f)(void*), void *a, int msec) 18 { 19 Periodic *p; 20 21 p = vtmallocz(sizeof(Periodic)); 22 p->f = f; 23 p->a = a; 24 p->msec = msec; 25 if(p->msec < 10) 26 p->msec = 10; 27 28 proccreate(periodicThread, p, STACK); 29 return p; 30 } 31 32 void periodicKill(Periodic * p)33periodicKill(Periodic *p) 34 { 35 if(p == nil) 36 return; 37 qlock(&p->lk); 38 p->die = 1; 39 qunlock(&p->lk); 40 } 41 42 static void periodicFree(Periodic * p)43periodicFree(Periodic *p) 44 { 45 vtfree(p); 46 } 47 48 static void periodicThread(void * a)49periodicThread(void *a) 50 { 51 Periodic *p = a; 52 vlong t, ct, ts; /* times in ms. */ 53 54 threadsetname("periodic"); 55 56 ct = nsec() / 1000000; 57 t = ct + p->msec; /* call p->f at or after this time */ 58 59 for(;;){ 60 if(t - ct > p->msec) /* time went backwards? */ 61 t = ct + p->msec; 62 ts = t - ct; /* ms. to next cycle's start */ 63 if(ts > 1000) 64 ts = 1000; /* bound sleep duration */ 65 if(ts > 0) 66 sleep(ts); /* wait for cycle's start */ 67 68 qlock(&p->lk); 69 if(p->die){ 70 qunlock(&p->lk); 71 break; 72 } 73 ct = nsec() / 1000000; 74 if(t <= ct){ /* due to call p->f? */ 75 p->f(p->a); 76 ct = nsec() / 1000000; 77 while(t <= ct) /* advance t to future cycle start */ 78 t += p->msec; 79 } 80 qunlock(&p->lk); 81 } 82 periodicFree(p); 83 } 84 85