/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* Portions of this file are Copyright (C) 2015-2018 Giacomo Tesio * See /doc/license/gpl-2.0.txt for details about the licensing. */ /* Portions of this file are Copyright (C) 9front's team. * See /doc/license/9front-mit for details about the licensing. * See http://git.9front.org/plan9front/plan9front/HEAD/info.html for a list of authors. */ #include #include #include #include #include #include #include #include #include <9P2000.h> #include "dat.h" #include "fns.h" static Channel* ctimer; /* chan(Timer*)[100] */ static Timer *timer; static uint32_t msec(void) { return nsec()/1000000; } void timerstop(Timer *t) { t->next = timer; timer = t; } void timercancel(Timer *t) { t->cancel = TRUE; } static void timerproc(void* _) { int i, nt, na, dt, del; Timer **t, *x; uint32_t old, new; sys_rfork(RFFDG); threadsetname("TIMERPROC"); t = nil; na = 0; nt = 0; old = msec(); for(;;){ sleep(1); /* will sleep minimum incr */ new = msec(); dt = new-old; old = new; if(dt < 0) /* timer wrapped; go around, losing a tick */ continue; for(i=0; idt -= dt; del = 0; if(x->cancel){ timerstop(x); del = 1; }else if(x->dt <= 0){ /* * avoid possible deadlock if client is * now sending on ctimer */ if(nbsendul(x->c, 0) > 0) del = 1; } if(del){ memmove(&t[i], &t[i+1], (nt-i-1)*sizeof t[0]); --nt; --i; } } if(nt == 0){ x = recvp(ctimer); gotit: if(nt == na){ na += 10; t = realloc(t, na*sizeof(Timer*)); if(t == nil) abort(); } t[nt++] = x; old = msec(); } if(nbrecv(ctimer, &x) > 0) goto gotit; } } void timerinit(void) { ctimer = chancreate(sizeof(Timer*), 100); proccreate(timerproc, nil, STACK); } /* * timeralloc() and timerfree() don't lock, so can only be * called from the main proc. */ Timer* timerstart(int dt) { Timer *t; t = timer; if(t) timer = timer->next; else{ t = emalloc(sizeof(Timer)); t->c = chancreate(sizeof(int), 0); } t->next = nil; t->dt = dt; t->cancel = FALSE; sendp(ctimer, t); return t; }