1 #include <u.h> 2 #include <libc.h> 3 #include <draw.h> 4 #include <memdraw.h> 5 #include <thread.h> 6 #include <cursor.h> 7 #include <mouse.h> 8 #include <keyboard.h> 9 #include <frame.h> 10 #include <plumb.h> 11 #include <html.h> 12 #include "dat.h" 13 #include "fns.h" 14 15 static Channel* ctimer; /* chan(Timer*)[100] */ 16 static Timer *timer; 17 18 static 19 uint 20 msec(void) 21 { 22 return nsec()/1000000; 23 } 24 25 void 26 timerstop(Timer *t) 27 { 28 t->next = timer; 29 timer = t; 30 } 31 32 void 33 timercancel(Timer *t) 34 { 35 t->cancel = TRUE; 36 } 37 38 static 39 void 40 timerproc(void*) 41 { 42 int i, nt, na, dt, del; 43 Timer **t, *x; 44 uint old, new; 45 46 threadsetname("timerproc"); 47 rfork(RFFDG); 48 t = nil; 49 na = 0; 50 nt = 0; 51 old = msec(); 52 for(;;){ 53 sleep(1); /* will sleep minimum incr */ 54 new = msec(); 55 dt = new-old; 56 old = new; 57 if(dt < 0) /* timer wrapped; go around, losing a tick */ 58 continue; 59 for(i=0; i<nt; i++){ 60 x = t[i]; 61 x->dt -= dt; 62 del = FALSE; 63 if(x->cancel){ 64 timerstop(x); 65 del = TRUE; 66 }else if(x->dt <= 0){ 67 /* 68 * avoid possible deadlock if client is 69 * now sending on ctimer 70 */ 71 if(nbsendul(x->c, 0) > 0) 72 del = TRUE; 73 } 74 if(del){ 75 memmove(&t[i], &t[i+1], (nt-i-1)*sizeof t[0]); 76 --nt; 77 --i; 78 } 79 } 80 if(nt == 0){ 81 x = recvp(ctimer); 82 gotit: 83 if(nt == na){ 84 na += 10; 85 t = erealloc(t, na*sizeof(Timer*)); 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 Timer* 103 timerstart(int dt) 104 { 105 Timer *t; 106 107 t = timer; 108 if(t) 109 timer = timer->next; 110 else{ 111 t = emalloc(sizeof(Timer)); 112 t->c = chancreate(sizeof(int), 0); 113 } 114 t->next = nil; 115 t->dt = dt; 116 t->cancel = FALSE; 117 sendp(ctimer, t); 118 return t; 119 } 120