time.c (1934B)
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 <libsec.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 *v) 41 { 42 int i, nt, na, dt, del; 43 Timer **t, *x; 44 uint old, new; 45 46 USED(v); 47 threadsetname("timerproc"); 48 rfork(RFFDG); 49 t = nil; 50 na = 0; 51 nt = 0; 52 old = msec(); 53 for(;;){ 54 sleep(10); /* longer sleeps here delay recv on ctimer, but 10ms should not be noticeable */ 55 new = msec(); 56 dt = new-old; 57 old = new; 58 if(dt < 0) /* timer wrapped; go around, losing a tick */ 59 continue; 60 for(i=0; i<nt; i++){ 61 x = t[i]; 62 x->dt -= dt; 63 del = FALSE; 64 if(x->cancel){ 65 timerstop(x); 66 del = TRUE; 67 }else if(x->dt <= 0){ 68 /* 69 * avoid possible deadlock if client is 70 * now sending on ctimer 71 */ 72 if(nbsendul(x->c, 0) > 0) 73 del = TRUE; 74 } 75 if(del){ 76 memmove(&t[i], &t[i+1], (nt-i-1)*sizeof t[0]); 77 --nt; 78 --i; 79 } 80 } 81 if(nt == 0){ 82 x = recvp(ctimer); 83 gotit: 84 if(nt == na){ 85 na += 10; 86 t = realloc(t, na*sizeof(Timer*)); 87 if(t == nil) 88 error("timer realloc failed"); 89 } 90 t[nt++] = x; 91 old = msec(); 92 } 93 if(nbrecv(ctimer, &x) > 0) 94 goto gotit; 95 } 96 } 97 98 void 99 timerinit(void) 100 { 101 ctimer = chancreate(sizeof(Timer*), 100); 102 chansetname(ctimer, "ctimer"); 103 proccreate(timerproc, nil, STACK); 104 } 105 106 Timer* 107 timerstart(int dt) 108 { 109 Timer *t; 110 111 t = timer; 112 if(t) 113 timer = timer->next; 114 else{ 115 t = emalloc(sizeof(Timer)); 116 t->c = chancreate(sizeof(int), 0); 117 chansetname(t->c, "tc%p", t->c); 118 } 119 t->next = nil; 120 t->dt = dt; 121 t->cancel = FALSE; 122 sendp(ctimer, t); 123 return t; 124 }