time.c (1841B)
1 #include <u.h> 2 #include <libc.h> 3 #include <draw.h> 4 #include <thread.h> 5 #include <cursor.h> 6 #include <mouse.h> 7 #include <keyboard.h> 8 #include <frame.h> 9 #include <fcall.h> 10 #include "dat.h" 11 #include "fns.h" 12 13 static Channel* ctimer; /* chan(Timer*)[100] */ 14 static Timer *timer; 15 16 static 17 uint 18 msec(void) 19 { 20 return nsec()/1000000; 21 } 22 23 void 24 timerstop(Timer *t) 25 { 26 t->next = timer; 27 timer = t; 28 } 29 30 void 31 timercancel(Timer *t) 32 { 33 t->cancel = TRUE; 34 } 35 36 static 37 void 38 timerproc(void *a) 39 { 40 int i, nt, na, dt, del; 41 Timer **t, *x; 42 uint old, new; 43 44 USED(a); 45 rfork(RFFDG); 46 threadsetname("TIMERPROC"); 47 t = nil; 48 na = 0; 49 nt = 0; 50 old = msec(); 51 for(;;){ 52 sleep(1); /* will sleep minimum incr */ 53 new = msec(); 54 dt = new-old; 55 old = new; 56 if(dt < 0) /* timer wrapped; go around, losing a tick */ 57 continue; 58 for(i=0; i<nt; i++){ 59 x = t[i]; 60 x->dt -= dt; 61 del = 0; 62 if(x->cancel){ 63 timerstop(x); 64 del = 1; 65 }else if(x->dt <= 0){ 66 /* 67 * avoid possible deadlock if client is 68 * now sending on ctimer 69 */ 70 if(nbsendul(x->c, 0) > 0) 71 del = 1; 72 } 73 if(del){ 74 memmove(&t[i], &t[i+1], (nt-i-1)*sizeof t[0]); 75 --nt; 76 --i; 77 } 78 } 79 if(nt == 0){ 80 x = recvp(ctimer); 81 gotit: 82 if(nt == na){ 83 na += 10; 84 t = realloc(t, na*sizeof(Timer*)); 85 if(t == nil) 86 abort(); 87 } 88 t[nt++] = x; 89 old = msec(); 90 } 91 if(nbrecv(ctimer, &x) > 0) 92 goto gotit; 93 } 94 } 95 96 void 97 timerinit(void) 98 { 99 ctimer = chancreate(sizeof(Timer*), 100); 100 proccreate(timerproc, nil, STACK); 101 } 102 103 /* 104 * timeralloc() and timerfree() don't lock, so can only be 105 * called from the main proc. 106 */ 107 108 Timer* 109 timerstart(int dt) 110 { 111 Timer *t; 112 113 t = timer; 114 if(t) 115 timer = timer->next; 116 else{ 117 t = emalloc(sizeof(Timer)); 118 t->c = chancreate(sizeof(int), 0); 119 } 120 t->next = nil; 121 t->dt = dt; 122 t->cancel = FALSE; 123 sendp(ctimer, t); 124 return t; 125 }