plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }