ohmu
·
2026-09-21
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
15static Channel* ctimer; /* chan(Timer*)[100] */
16static Timer *timer;
17
18static
19uint
20msec(void)
21{
22 return nsec()/1000000;
23}
24
25void
26timerstop(Timer *t)
27{
28 t->next = timer;
29 timer = t;
30}
31
32void
33timercancel(Timer *t)
34{
35 t->cancel = TRUE;
36}
37
38static
39void
40timerproc(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
98void
99timerinit(void)
100{
101 ctimer = chancreate(sizeof(Timer*), 100);
102 chansetname(ctimer, "ctimer");
103 proccreate(timerproc, nil, STACK);
104}
105
106Timer*
107timerstart(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}