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 <plumb.h> 11 #include "dat.h" 12 #include "fns.h" 13 14 static Channel* ctimer; /* chan(Timer*)[100] */ 15 static Timer *timer; 16 17 static 18 uint 19 msec(void) 20 { 21 return nsec()/1000000; 22 } 23 24 void 25 timerstop(Timer *t) 26 { 27 t->next = timer; 28 timer = t; 29 } 30 31 void 32 timercancel(Timer *t) 33 { 34 t->cancel = TRUE; 35 } 36 37 static 38 void 39 timerproc(void*) 40 { 41 int i, nt, na, dt, del; 42 Timer **t, *x; 43 uint old, new; 44 45 threadsetname("timerproc"); 46 rfork(RFFDG); 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 = FALSE; 62 if(x->cancel){ 63 timerstop(x); 64 del = TRUE; 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 = TRUE; 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 error("timer realloc failed"); 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 Timer* 104 timerstart(int dt) 105 { 106 Timer *t; 107 108 t = timer; 109 if(t) 110 timer = timer->next; 111 else{ 112 t = emalloc(sizeof(Timer)); 113 t->c = chancreate(sizeof(int), 0); 114 } 115 t->next = nil; 116 t->dt = dt; 117 t->cancel = FALSE; 118 sendp(ctimer, t); 119 return t; 120 } 121