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*) 39 { 40 int i, nt, na, dt, del; 41 Timer **t, *x; 42 uint old, new; 43 44 rfork(RFFDG); 45 threadsetname("TIMERPROC"); 46 t = nil; 47 na = 0; 48 nt = 0; 49 old = msec(); 50 for(;;){ 51 sleep(1); /* will sleep minimum incr */ 52 new = msec(); 53 dt = new-old; 54 old = new; 55 if(dt < 0) /* timer wrapped; go around, losing a tick */ 56 continue; 57 for(i=0; i<nt; i++){ 58 x = t[i]; 59 x->dt -= dt; 60 del = 0; 61 if(x->cancel){ 62 timerstop(x); 63 del = 1; 64 }else if(x->dt <= 0){ 65 /* 66 * avoid possible deadlock if client is 67 * now sending on ctimer 68 */ 69 if(nbsendul(x->c, 0) > 0) 70 del = 1; 71 } 72 if(del){ 73 memmove(&t[i], &t[i+1], (nt-i-1)*sizeof t[0]); 74 --nt; 75 --i; 76 } 77 } 78 if(nt == 0){ 79 x = recvp(ctimer); 80 gotit: 81 if(nt == na){ 82 na += 10; 83 t = realloc(t, na*sizeof(Timer*)); 84 if(t == nil) 85 abort(); 86 } 87 t[nt++] = x; 88 old = msec(); 89 } 90 if(nbrecv(ctimer, &x) > 0) 91 goto gotit; 92 } 93 } 94 95 void 96 timerinit(void) 97 { 98 ctimer = chancreate(sizeof(Timer*), 100); 99 proccreate(timerproc, nil, STACK); 100 } 101 102 /* 103 * timeralloc() and timerfree() don't lock, so can only be 104 * called from the main proc. 105 */ 106 107 Timer* 108 timerstart(int dt) 109 { 110 Timer *t; 111 112 t = timer; 113 if(t) 114 timer = timer->next; 115 else{ 116 t = emalloc(sizeof(Timer)); 117 t->c = chancreate(sizeof(int), 0); 118 } 119 t->next = nil; 120 t->dt = dt; 121 t->cancel = FALSE; 122 sendp(ctimer, t); 123 return t; 124 } 125