2019-11-14 23:15:48 +00:00
|
|
|
#include <u.h>
|
|
|
|
#include <libc.h>
|
|
|
|
#include <draw.h>
|
|
|
|
#include <thread.h>
|
|
|
|
#include <cursor.h>
|
|
|
|
#include <mouse.h>
|
|
|
|
#include <keyboard.h>
|
2022-02-22 05:52:56 +00:00
|
|
|
#include "libframe/frame.h"
|
2019-11-14 23:15:48 +00:00
|
|
|
#include <fcall.h>
|
|
|
|
#include <plumb.h>
|
|
|
|
#include <libsec.h>
|
|
|
|
#include "dat.h"
|
|
|
|
#include "fns.h"
|
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
static Channel* ctimer; /* chan(Timer*)[100] */
|
|
|
|
static Timer* timer;
|
2019-11-14 23:15:48 +00:00
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
static uint msec(void) { return nsec() / 1000000; }
|
2019-11-14 23:15:48 +00:00
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
void timerstop(Timer* t) {
|
|
|
|
t->next = timer;
|
|
|
|
timer = t;
|
2019-11-14 23:15:48 +00:00
|
|
|
}
|
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
void timercancel(Timer* t) { t->cancel = TRUE; }
|
2019-11-14 23:15:48 +00:00
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
static void timerproc(void* v) {
|
|
|
|
int i, nt, na, dt, del;
|
|
|
|
Timer **t, *x;
|
|
|
|
uint old, new;
|
2019-11-14 23:15:48 +00:00
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
USED(v);
|
|
|
|
threadsetname("timerproc");
|
|
|
|
rfork(RFFDG);
|
|
|
|
t = nil;
|
|
|
|
na = 0;
|
|
|
|
nt = 0;
|
|
|
|
old = msec();
|
|
|
|
for (;;) {
|
|
|
|
sleep(10); /* longer sleeps here delay recv on ctimer, but 10ms should not
|
|
|
|
be noticeable */
|
|
|
|
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 = FALSE;
|
|
|
|
if (x->cancel) {
|
|
|
|
timerstop(x);
|
|
|
|
del = TRUE;
|
|
|
|
} else if (x->dt <= 0) {
|
|
|
|
/*
|
|
|
|
* avoid possible deadlock if client is
|
|
|
|
* now sending on ctimer
|
|
|
|
*/
|
|
|
|
if (nbsendul(x->c, 0) > 0)
|
|
|
|
del = TRUE;
|
|
|
|
}
|
|
|
|
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)
|
|
|
|
error("timer realloc failed");
|
|
|
|
}
|
|
|
|
t[nt++] = x;
|
|
|
|
old = msec();
|
|
|
|
}
|
|
|
|
if (nbrecv(ctimer, &x) > 0)
|
|
|
|
goto gotit;
|
|
|
|
}
|
2019-11-14 23:15:48 +00:00
|
|
|
}
|
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
void timerinit(void) {
|
|
|
|
ctimer = chancreate(sizeof(Timer*), 100);
|
|
|
|
chansetname(ctimer, "ctimer");
|
|
|
|
proccreate(timerproc, nil, STACK);
|
2019-11-14 23:15:48 +00:00
|
|
|
}
|
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
Timer* timerstart(int dt) {
|
|
|
|
Timer* t;
|
2019-11-14 23:15:48 +00:00
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
t = timer;
|
|
|
|
if (t)
|
|
|
|
timer = timer->next;
|
|
|
|
else {
|
|
|
|
t = emalloc(sizeof(Timer));
|
|
|
|
t->c = chancreate(sizeof(int), 0);
|
|
|
|
chansetname(t->c, "tc%p", t->c);
|
|
|
|
}
|
|
|
|
t->next = nil;
|
|
|
|
t->dt = dt;
|
|
|
|
t->cancel = FALSE;
|
|
|
|
sendp(ctimer, t);
|
|
|
|
return t;
|
2019-11-14 23:15:48 +00:00
|
|
|
}
|