plan9port

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

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 }