2018-01-06 01:08:25 +01:00
|
|
|
/*
|
|
|
|
* 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 <giacomo@tesio.it>
|
|
|
|
* 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://code.9front.org/hg/plan9front/ for a list of authors.
|
|
|
|
*/
|
2016-11-25 17:18:40 +01:00
|
|
|
#include <u.h>
|
2017-04-19 23:33:14 +02:00
|
|
|
#include <lib9.h>
|
2016-11-25 17:18:40 +01:00
|
|
|
#include <draw.h>
|
|
|
|
#include <thread.h>
|
|
|
|
#include <cursor.h>
|
|
|
|
#include <mouse.h>
|
|
|
|
#include <keyboard.h>
|
|
|
|
#include <frame.h>
|
2016-12-01 00:09:42 +01:00
|
|
|
#include <9P2000.h>
|
2016-11-25 17:18:40 +01:00
|
|
|
#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;
|
|
|
|
|
|
|
|
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; i<nt; i++){
|
|
|
|
x = t[i];
|
|
|
|
x->dt -= 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;
|
|
|
|
}
|