Blame


1 0a53bd62 2023-08-16 op /*
2 0a53bd62 2023-08-16 op * This is free and unencumbered software released into the public domain.
3 0a53bd62 2023-08-16 op *
4 0a53bd62 2023-08-16 op * Anyone is free to copy, modify, publish, use, compile, sell, or
5 0a53bd62 2023-08-16 op * distribute this software, either in source code form or as a compiled
6 0a53bd62 2023-08-16 op * binary, for any purpose, commercial or non-commercial, and by any
7 0a53bd62 2023-08-16 op * means.
8 0a53bd62 2023-08-16 op *
9 0a53bd62 2023-08-16 op * In jurisdictions that recognize copyright laws, the author or authors
10 0a53bd62 2023-08-16 op * of this software dedicate any and all copyright interest in the
11 0a53bd62 2023-08-16 op * software to the public domain. We make this dedication for the benefit
12 0a53bd62 2023-08-16 op * of the public at large and to the detriment of our heirs and
13 0a53bd62 2023-08-16 op * successors. We intend this dedication to be an overt act of
14 0a53bd62 2023-08-16 op * relinquishment in perpetuity of all present and future rights to this
15 0a53bd62 2023-08-16 op * software under copyright law.
16 0a53bd62 2023-08-16 op *
17 0a53bd62 2023-08-16 op * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 0a53bd62 2023-08-16 op * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 0a53bd62 2023-08-16 op * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 0a53bd62 2023-08-16 op * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 0a53bd62 2023-08-16 op * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 0a53bd62 2023-08-16 op * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 0a53bd62 2023-08-16 op * OTHER DEALINGS IN THE SOFTWARE.
24 0a53bd62 2023-08-16 op */
25 0a53bd62 2023-08-16 op
26 0a53bd62 2023-08-16 op #include "config.h"
27 0a53bd62 2023-08-16 op
28 6be81433 2024-04-14 op #include <sys/time.h>
29 6be81433 2024-04-14 op
30 0a53bd62 2023-08-16 op #include <errno.h>
31 0a53bd62 2023-08-16 op #include <fcntl.h>
32 0a53bd62 2023-08-16 op #include <limits.h>
33 0a53bd62 2023-08-16 op #include <poll.h>
34 0a53bd62 2023-08-16 op #include <signal.h>
35 0a53bd62 2023-08-16 op #include <stdlib.h>
36 6be81433 2024-04-14 op #include <string.h>
37 27bf07a4 2023-08-16 op #include <time.h>
38 0a53bd62 2023-08-16 op #include <unistd.h>
39 0a53bd62 2023-08-16 op
40 0a53bd62 2023-08-16 op #include "ev.h"
41 0a53bd62 2023-08-16 op
42 0a53bd62 2023-08-16 op struct evcb {
43 0a53bd62 2023-08-16 op void (*cb)(int, int, void *);
44 0a53bd62 2023-08-16 op void *udata;
45 0a53bd62 2023-08-16 op };
46 0a53bd62 2023-08-16 op
47 6be81433 2024-04-14 op struct evtimer {
48 6be81433 2024-04-14 op unsigned int id;
49 6be81433 2024-04-14 op struct timeval tv;
50 6be81433 2024-04-14 op struct evcb cb;
51 6be81433 2024-04-14 op };
52 6be81433 2024-04-14 op
53 0a53bd62 2023-08-16 op struct evbase {
54 0a53bd62 2023-08-16 op size_t len;
55 0a53bd62 2023-08-16 op
56 0a53bd62 2023-08-16 op struct pollfd *pfds;
57 0a53bd62 2023-08-16 op size_t pfdlen;
58 0a53bd62 2023-08-16 op
59 0a53bd62 2023-08-16 op struct evcb *cbs;
60 0a53bd62 2023-08-16 op size_t cblen;
61 0a53bd62 2023-08-16 op
62 0a53bd62 2023-08-16 op int sigpipe[2];
63 0a53bd62 2023-08-16 op struct evcb sigcb;
64 0a53bd62 2023-08-16 op
65 6be81433 2024-04-14 op unsigned int tid;
66 6be81433 2024-04-14 op
67 6be81433 2024-04-14 op /*
68 6be81433 2024-04-14 op * Binary heap of timers. At runtime, new timers are added in
69 6be81433 2024-04-14 op * the ``reserve'', a space after the caninocal end of the
70 6be81433 2024-04-14 op * array, and at the end of every tick they're added to the
71 6be81433 2024-04-14 op * heap.
72 6be81433 2024-04-14 op */
73 6be81433 2024-04-14 op struct evtimer *timers;
74 6be81433 2024-04-14 op size_t ntimers;
75 6be81433 2024-04-14 op size_t reserve_from;
76 6be81433 2024-04-14 op size_t reserve_till;
77 6be81433 2024-04-14 op size_t timerscap;
78 0a53bd62 2023-08-16 op };
79 0a53bd62 2023-08-16 op
80 0a53bd62 2023-08-16 op static struct evbase *base;
81 0a53bd62 2023-08-16 op static int ev_stop;
82 0a53bd62 2023-08-16 op
83 0a53bd62 2023-08-16 op static int
84 0a53bd62 2023-08-16 op ev_resize(size_t len)
85 0a53bd62 2023-08-16 op {
86 0a53bd62 2023-08-16 op void *t;
87 0a53bd62 2023-08-16 op size_t i;
88 0a53bd62 2023-08-16 op
89 0a53bd62 2023-08-16 op t = recallocarray(base->pfds, base->pfdlen, len, sizeof(*base->pfds));
90 0a53bd62 2023-08-16 op if (t == NULL)
91 0a53bd62 2023-08-16 op return -1;
92 0a53bd62 2023-08-16 op base->pfds = t;
93 0a53bd62 2023-08-16 op base->pfdlen = len;
94 0a53bd62 2023-08-16 op
95 0a53bd62 2023-08-16 op for (i = base->len; i < len; ++i)
96 0a53bd62 2023-08-16 op base->pfds[i].fd = -1;
97 0a53bd62 2023-08-16 op
98 0a53bd62 2023-08-16 op t = recallocarray(base->cbs, base->cblen, len, sizeof(*base->cbs));
99 0a53bd62 2023-08-16 op if (t == NULL)
100 0a53bd62 2023-08-16 op return -1;
101 0a53bd62 2023-08-16 op base->cbs = t;
102 0a53bd62 2023-08-16 op base->cblen = len;
103 0a53bd62 2023-08-16 op
104 0a53bd62 2023-08-16 op base->len = len;
105 0a53bd62 2023-08-16 op return 0;
106 0a53bd62 2023-08-16 op }
107 0a53bd62 2023-08-16 op
108 0a53bd62 2023-08-16 op int
109 0a53bd62 2023-08-16 op ev_init(void)
110 0a53bd62 2023-08-16 op {
111 0a53bd62 2023-08-16 op if (base != NULL) {
112 0a53bd62 2023-08-16 op errno = EINVAL;
113 0a53bd62 2023-08-16 op return -1;
114 0a53bd62 2023-08-16 op }
115 0a53bd62 2023-08-16 op
116 0a53bd62 2023-08-16 op if ((base = calloc(1, sizeof(*base))) == NULL)
117 0a53bd62 2023-08-16 op return -1;
118 0a53bd62 2023-08-16 op
119 0a53bd62 2023-08-16 op base->sigpipe[0] = -1;
120 0a53bd62 2023-08-16 op base->sigpipe[1] = -1;
121 0a53bd62 2023-08-16 op
122 0a53bd62 2023-08-16 op if (ev_resize(16) == -1) {
123 0a53bd62 2023-08-16 op free(base->pfds);
124 0a53bd62 2023-08-16 op free(base->cbs);
125 0a53bd62 2023-08-16 op free(base);
126 0a53bd62 2023-08-16 op base = NULL;
127 0a53bd62 2023-08-16 op return -1;
128 0a53bd62 2023-08-16 op }
129 0a53bd62 2023-08-16 op
130 0a53bd62 2023-08-16 op return 0;
131 0a53bd62 2023-08-16 op }
132 0a53bd62 2023-08-16 op
133 6be81433 2024-04-14 op static inline int
134 6be81433 2024-04-14 op ev2poll(int ev)
135 6be81433 2024-04-14 op {
136 6be81433 2024-04-14 op int ret = 0;
137 6be81433 2024-04-14 op
138 6be81433 2024-04-14 op if (ev & EV_READ)
139 6be81433 2024-04-14 op ret |= POLLIN;
140 6be81433 2024-04-14 op if (ev & EV_WRITE)
141 6be81433 2024-04-14 op ret |= POLLOUT;
142 6be81433 2024-04-14 op
143 6be81433 2024-04-14 op return (ret);
144 6be81433 2024-04-14 op }
145 6be81433 2024-04-14 op
146 0a53bd62 2023-08-16 op int
147 0a53bd62 2023-08-16 op ev_add(int fd, int ev, void (*cb)(int, int, void *), void *udata)
148 0a53bd62 2023-08-16 op {
149 6be81433 2024-04-14 op if (fd < 0) {
150 6be81433 2024-04-14 op errno = EBADF;
151 6be81433 2024-04-14 op return -1;
152 6be81433 2024-04-14 op }
153 6be81433 2024-04-14 op
154 6be81433 2024-04-14 op if ((size_t)fd >= base->len) {
155 0a53bd62 2023-08-16 op if (ev_resize(fd + 1) == -1)
156 0a53bd62 2023-08-16 op return -1;
157 0a53bd62 2023-08-16 op }
158 0a53bd62 2023-08-16 op
159 0a53bd62 2023-08-16 op base->pfds[fd].fd = fd;
160 6be81433 2024-04-14 op base->pfds[fd].events = ev2poll(ev);
161 6be81433 2024-04-14 op base->pfds[fd].revents = 0;
162 0a53bd62 2023-08-16 op
163 0a53bd62 2023-08-16 op base->cbs[fd].cb = cb;
164 0a53bd62 2023-08-16 op base->cbs[fd].udata = udata;
165 0a53bd62 2023-08-16 op
166 0a53bd62 2023-08-16 op return 0;
167 0a53bd62 2023-08-16 op }
168 0a53bd62 2023-08-16 op
169 0a53bd62 2023-08-16 op static void
170 0a53bd62 2023-08-16 op ev_sigcatch(int signo)
171 0a53bd62 2023-08-16 op {
172 0a53bd62 2023-08-16 op unsigned char s;
173 0a53bd62 2023-08-16 op int err;
174 0a53bd62 2023-08-16 op
175 0a53bd62 2023-08-16 op err = errno;
176 0a53bd62 2023-08-16 op
177 0a53bd62 2023-08-16 op /*
178 0a53bd62 2023-08-16 op * We should be able to write up to PIPE_BUF bytes without
179 0a53bd62 2023-08-16 op * blocking.
180 0a53bd62 2023-08-16 op */
181 0a53bd62 2023-08-16 op s = signo;
182 0a53bd62 2023-08-16 op (void) write(base->sigpipe[1], &s, sizeof(s));
183 0a53bd62 2023-08-16 op
184 0a53bd62 2023-08-16 op errno = err;
185 0a53bd62 2023-08-16 op }
186 0a53bd62 2023-08-16 op
187 0a53bd62 2023-08-16 op static void
188 0a53bd62 2023-08-16 op ev_sigdispatch(int fd, int ev, void *data)
189 0a53bd62 2023-08-16 op {
190 0a53bd62 2023-08-16 op unsigned char signo;
191 0a53bd62 2023-08-16 op
192 0a53bd62 2023-08-16 op if (read(fd, &signo, sizeof(signo)) != sizeof(signo))
193 0a53bd62 2023-08-16 op return;
194 0a53bd62 2023-08-16 op
195 6be81433 2024-04-14 op base->sigcb.cb(signo, EV_SIGNAL, base->sigcb.udata);
196 0a53bd62 2023-08-16 op }
197 0a53bd62 2023-08-16 op
198 0a53bd62 2023-08-16 op int
199 0a53bd62 2023-08-16 op ev_signal(int sig, void (*cb)(int, int, void *), void *udata)
200 0a53bd62 2023-08-16 op {
201 dc3e25b1 2023-10-07 op int flags;
202 dc3e25b1 2023-10-07 op
203 0a53bd62 2023-08-16 op if (base->sigpipe[0] == -1) {
204 dc3e25b1 2023-10-07 op /* pipe2(2) is not available everywhere... sigh */
205 dc3e25b1 2023-10-07 op if (pipe(base->sigpipe) == -1)
206 dc3e25b1 2023-10-07 op return -1;
207 dc3e25b1 2023-10-07 op
208 dc3e25b1 2023-10-07 op if ((flags = fcntl(base->sigpipe[1], F_GETFL)) == -1 ||
209 dc3e25b1 2023-10-07 op fcntl(base->sigpipe[1], F_SETFL, flags | O_NONBLOCK) == -1)
210 0a53bd62 2023-08-16 op return -1;
211 dc3e25b1 2023-10-07 op
212 6be81433 2024-04-14 op if (ev_add(base->sigpipe[0], EV_READ, ev_sigdispatch, NULL)
213 0a53bd62 2023-08-16 op == -1)
214 0a53bd62 2023-08-16 op return -1;
215 0a53bd62 2023-08-16 op }
216 0a53bd62 2023-08-16 op
217 0a53bd62 2023-08-16 op base->sigcb.cb = cb;
218 0a53bd62 2023-08-16 op base->sigcb.udata = udata;
219 0a53bd62 2023-08-16 op
220 0a53bd62 2023-08-16 op signal(sig, ev_sigcatch);
221 0a53bd62 2023-08-16 op return 0;
222 0a53bd62 2023-08-16 op }
223 0a53bd62 2023-08-16 op
224 6be81433 2024-04-14 op unsigned int
225 0a53bd62 2023-08-16 op ev_timer(const struct timeval *tv, void (*cb)(int, int, void*), void *udata)
226 0a53bd62 2023-08-16 op {
227 6be81433 2024-04-14 op struct evtimer *evt;
228 6be81433 2024-04-14 op void *t;
229 6be81433 2024-04-14 op size_t newcap;
230 6be81433 2024-04-14 op unsigned int nextid;
231 6be81433 2024-04-14 op
232 6be81433 2024-04-14 op if (tv == NULL) {
233 6be81433 2024-04-14 op errno = EINVAL;
234 6be81433 2024-04-14 op return 0;
235 0a53bd62 2023-08-16 op }
236 0a53bd62 2023-08-16 op
237 6be81433 2024-04-14 op if (base->reserve_till == base->timerscap) {
238 6be81433 2024-04-14 op newcap = base->timerscap + 8;
239 6be81433 2024-04-14 op t = recallocarray(base->timers, base->timerscap, newcap,
240 6be81433 2024-04-14 op sizeof(*base->timers));
241 6be81433 2024-04-14 op if (t == NULL)
242 6be81433 2024-04-14 op return 0;
243 6be81433 2024-04-14 op base->timers = t;
244 6be81433 2024-04-14 op base->timerscap = newcap;
245 6be81433 2024-04-14 op }
246 0a53bd62 2023-08-16 op
247 6be81433 2024-04-14 op if ((nextid = ++base->tid) == 0)
248 6be81433 2024-04-14 op nextid = ++base->tid;
249 0a53bd62 2023-08-16 op
250 6be81433 2024-04-14 op evt = &base->timers[base->reserve_till];
251 6be81433 2024-04-14 op evt->id = nextid;
252 6be81433 2024-04-14 op memcpy(&evt->tv, tv, sizeof(*tv));
253 6be81433 2024-04-14 op evt->cb.cb = cb;
254 6be81433 2024-04-14 op evt->cb.udata = udata;
255 6be81433 2024-04-14 op
256 6be81433 2024-04-14 op base->reserve_till++;
257 6be81433 2024-04-14 op return (nextid);
258 6be81433 2024-04-14 op }
259 6be81433 2024-04-14 op
260 6be81433 2024-04-14 op static int
261 6be81433 2024-04-14 op find_timer(unsigned int id, size_t *pos)
262 0a53bd62 2023-08-16 op {
263 6be81433 2024-04-14 op size_t i;
264 6be81433 2024-04-14 op
265 6be81433 2024-04-14 op if (id == 0)
266 6be81433 2024-04-14 op return (0);
267 6be81433 2024-04-14 op
268 6be81433 2024-04-14 op for (i = 0; i < base->ntimers; ++i) {
269 6be81433 2024-04-14 op if (base->timers[i].id == id) {
270 6be81433 2024-04-14 op *pos = i;
271 6be81433 2024-04-14 op return (1);
272 6be81433 2024-04-14 op }
273 6be81433 2024-04-14 op }
274 6be81433 2024-04-14 op
275 6be81433 2024-04-14 op for (i = base->reserve_from; i < base->reserve_till; ++i) {
276 6be81433 2024-04-14 op if (base->timers[i].id == id) {
277 6be81433 2024-04-14 op *pos = i;
278 6be81433 2024-04-14 op return (1);
279 6be81433 2024-04-14 op }
280 6be81433 2024-04-14 op }
281 6be81433 2024-04-14 op
282 6be81433 2024-04-14 op return (0);
283 0a53bd62 2023-08-16 op }
284 0a53bd62 2023-08-16 op
285 6be81433 2024-04-14 op int
286 6be81433 2024-04-14 op ev_timer_pending(unsigned int id)
287 6be81433 2024-04-14 op {
288 6be81433 2024-04-14 op size_t i;
289 6be81433 2024-04-14 op
290 6be81433 2024-04-14 op return (find_timer(id, &i));
291 6be81433 2024-04-14 op }
292 6be81433 2024-04-14 op
293 6be81433 2024-04-14 op static void
294 6be81433 2024-04-14 op bubbledown(size_t i)
295 6be81433 2024-04-14 op {
296 6be81433 2024-04-14 op struct evtimer tmp;
297 6be81433 2024-04-14 op size_t l, r, s;
298 6be81433 2024-04-14 op
299 6be81433 2024-04-14 op for (;;) {
300 6be81433 2024-04-14 op l = 2 * i + 1;
301 6be81433 2024-04-14 op r = 2 * i + 2;
302 6be81433 2024-04-14 op
303 6be81433 2024-04-14 op /* base case: there are no children */
304 6be81433 2024-04-14 op if (l >= base->ntimers)
305 6be81433 2024-04-14 op return;
306 6be81433 2024-04-14 op
307 6be81433 2024-04-14 op /* find the smaller child */
308 6be81433 2024-04-14 op s = r;
309 6be81433 2024-04-14 op if (r >= base->ntimers ||
310 6be81433 2024-04-14 op timercmp(&base->timers[l].tv, &base->timers[r].tv, <))
311 6be81433 2024-04-14 op s = l;
312 6be81433 2024-04-14 op
313 6be81433 2024-04-14 op /* other base case: it's at the right place */
314 6be81433 2024-04-14 op if (timercmp(&base->timers[i].tv, &base->timers[s].tv, <))
315 6be81433 2024-04-14 op return;
316 6be81433 2024-04-14 op
317 6be81433 2024-04-14 op /* swap */
318 6be81433 2024-04-14 op memcpy(&tmp, &base->timers[s], sizeof(tmp));
319 6be81433 2024-04-14 op memcpy(&base->timers[s], &base->timers[i], sizeof(tmp));
320 6be81433 2024-04-14 op memcpy(&base->timers[i], &tmp, sizeof(tmp));
321 6be81433 2024-04-14 op
322 6be81433 2024-04-14 op i = s;
323 6be81433 2024-04-14 op }
324 6be81433 2024-04-14 op }
325 6be81433 2024-04-14 op
326 6be81433 2024-04-14 op static inline void
327 6be81433 2024-04-14 op cancel_timer(size_t i)
328 6be81433 2024-04-14 op {
329 6be81433 2024-04-14 op base->ntimers--;
330 6be81433 2024-04-14 op if (i != base->ntimers) {
331 6be81433 2024-04-14 op memcpy(&base->timers[i], &base->timers[base->ntimers],
332 6be81433 2024-04-14 op sizeof(*base->timers));
333 6be81433 2024-04-14 op bubbledown(i);
334 6be81433 2024-04-14 op }
335 6be81433 2024-04-14 op }
336 6be81433 2024-04-14 op
337 0a53bd62 2023-08-16 op int
338 6be81433 2024-04-14 op ev_timer_cancel(unsigned int id)
339 6be81433 2024-04-14 op {
340 6be81433 2024-04-14 op size_t i;
341 6be81433 2024-04-14 op
342 6be81433 2024-04-14 op if (!find_timer(id, &i))
343 6be81433 2024-04-14 op return (-1);
344 6be81433 2024-04-14 op
345 6be81433 2024-04-14 op if (i < base->ntimers) {
346 6be81433 2024-04-14 op cancel_timer(i);
347 6be81433 2024-04-14 op return (0);
348 6be81433 2024-04-14 op }
349 6be81433 2024-04-14 op
350 6be81433 2024-04-14 op base->reserve_till--;
351 6be81433 2024-04-14 op if (i != base->reserve_till)
352 6be81433 2024-04-14 op memcpy(&base->timers[i], &base->timers[base->reserve_till],
353 6be81433 2024-04-14 op sizeof(*base->timers));
354 6be81433 2024-04-14 op return (0);
355 6be81433 2024-04-14 op }
356 6be81433 2024-04-14 op
357 6be81433 2024-04-14 op int
358 0a53bd62 2023-08-16 op ev_del(int fd)
359 0a53bd62 2023-08-16 op {
360 6be81433 2024-04-14 op if (fd < 0) {
361 6be81433 2024-04-14 op errno = EBADF;
362 6be81433 2024-04-14 op return -1;
363 6be81433 2024-04-14 op }
364 6be81433 2024-04-14 op
365 6be81433 2024-04-14 op if ((size_t)fd >= base->len) {
366 0a53bd62 2023-08-16 op errno = ERANGE;
367 0a53bd62 2023-08-16 op return -1;
368 0a53bd62 2023-08-16 op }
369 0a53bd62 2023-08-16 op
370 0a53bd62 2023-08-16 op base->pfds[fd].fd = -1;
371 0a53bd62 2023-08-16 op base->pfds[fd].events = 0;
372 0a53bd62 2023-08-16 op
373 0a53bd62 2023-08-16 op base->cbs[fd].cb = NULL;
374 0a53bd62 2023-08-16 op base->cbs[fd].udata = NULL;
375 0a53bd62 2023-08-16 op
376 0a53bd62 2023-08-16 op return 0;
377 0a53bd62 2023-08-16 op }
378 0a53bd62 2023-08-16 op
379 6be81433 2024-04-14 op static void
380 6be81433 2024-04-14 op timerheapify(void)
381 6be81433 2024-04-14 op {
382 6be81433 2024-04-14 op size_t i, reserve, gap;
383 6be81433 2024-04-14 op
384 6be81433 2024-04-14 op reserve = base->reserve_till - base->reserve_from;
385 6be81433 2024-04-14 op if (reserve == 0)
386 6be81433 2024-04-14 op return;
387 6be81433 2024-04-14 op
388 6be81433 2024-04-14 op gap = base->reserve_from - base->ntimers;
389 6be81433 2024-04-14 op if (gap != 0) {
390 6be81433 2024-04-14 op memmove(&base->timers[base->ntimers],
391 6be81433 2024-04-14 op &base->timers[base->reserve_from],
392 6be81433 2024-04-14 op reserve * sizeof(*base->timers));
393 6be81433 2024-04-14 op base->reserve_from -= gap;
394 6be81433 2024-04-14 op base->reserve_till -= gap;
395 6be81433 2024-04-14 op }
396 6be81433 2024-04-14 op
397 6be81433 2024-04-14 op base->ntimers = base->reserve_till;
398 6be81433 2024-04-14 op
399 6be81433 2024-04-14 op if (base->ntimers < 2)
400 6be81433 2024-04-14 op return;
401 6be81433 2024-04-14 op
402 6be81433 2024-04-14 op i = base->ntimers / 2 - 1;
403 6be81433 2024-04-14 op for (;;) {
404 6be81433 2024-04-14 op bubbledown(i);
405 6be81433 2024-04-14 op if (i == 0)
406 6be81433 2024-04-14 op break;
407 6be81433 2024-04-14 op i--;
408 6be81433 2024-04-14 op }
409 6be81433 2024-04-14 op }
410 6be81433 2024-04-14 op
411 6be81433 2024-04-14 op static inline int
412 6be81433 2024-04-14 op poll2ev(int ev)
413 6be81433 2024-04-14 op {
414 6be81433 2024-04-14 op int r = 0;
415 6be81433 2024-04-14 op
416 6be81433 2024-04-14 op if (ev & (POLLIN|POLLHUP))
417 6be81433 2024-04-14 op r |= EV_READ;
418 6be81433 2024-04-14 op if (ev & (POLLOUT|POLLWRNORM|POLLWRBAND))
419 6be81433 2024-04-14 op r |= EV_WRITE;
420 6be81433 2024-04-14 op
421 6be81433 2024-04-14 op return (r);
422 6be81433 2024-04-14 op }
423 6be81433 2024-04-14 op
424 0a53bd62 2023-08-16 op int
425 6be81433 2024-04-14 op ev_step(void)
426 0a53bd62 2023-08-16 op {
427 0a53bd62 2023-08-16 op struct timespec elapsed, beg, end;
428 6be81433 2024-04-14 op struct timeval tv, sub, *min;
429 6be81433 2024-04-14 op struct evcb cb;
430 6be81433 2024-04-14 op int n, msec;
431 0a53bd62 2023-08-16 op size_t i;
432 0a53bd62 2023-08-16 op
433 6be81433 2024-04-14 op timerheapify();
434 6be81433 2024-04-14 op base->reserve_from = base->ntimers;
435 6be81433 2024-04-14 op base->reserve_till = base->ntimers;
436 0a53bd62 2023-08-16 op
437 6be81433 2024-04-14 op min = NULL;
438 6be81433 2024-04-14 op msec = -1;
439 6be81433 2024-04-14 op if (base->ntimers) {
440 6be81433 2024-04-14 op min = &base->timers[0].tv;
441 6be81433 2024-04-14 op msec = min->tv_sec * 1000 + (min->tv_usec + 999) / 1000;
442 6be81433 2024-04-14 op }
443 6be81433 2024-04-14 op
444 6be81433 2024-04-14 op clock_gettime(CLOCK_MONOTONIC, &beg);
445 6be81433 2024-04-14 op if ((n = poll(base->pfds, base->len, msec)) == -1) {
446 6be81433 2024-04-14 op if (errno != EINTR)
447 6be81433 2024-04-14 op return -1;
448 6be81433 2024-04-14 op }
449 6be81433 2024-04-14 op
450 6be81433 2024-04-14 op if (n == 0 && min)
451 6be81433 2024-04-14 op memcpy(&tv, min, sizeof(tv));
452 6be81433 2024-04-14 op else {
453 6be81433 2024-04-14 op clock_gettime(CLOCK_MONOTONIC, &end);
454 0a53bd62 2023-08-16 op timespecsub(&end, &beg, &elapsed);
455 6be81433 2024-04-14 op TIMESPEC_TO_TIMEVAL(&tv, &elapsed);
456 6be81433 2024-04-14 op }
457 6be81433 2024-04-14 op
458 6be81433 2024-04-14 op for (i = 0; i < base->ntimers && !ev_stop; /* nop */) {
459 6be81433 2024-04-14 op timersub(&base->timers[i].tv, &tv, &sub);
460 6be81433 2024-04-14 op if (sub.tv_sec <= 0) {
461 6be81433 2024-04-14 op /*
462 6be81433 2024-04-14 op * delete the timer before calling its
463 6be81433 2024-04-14 op * callback; protects from timer that
464 6be81433 2024-04-14 op * attempt to delete themselves.
465 6be81433 2024-04-14 op */
466 6be81433 2024-04-14 op memcpy(&cb, &base->timers[i].cb, sizeof(cb));
467 6be81433 2024-04-14 op cancel_timer(i);
468 6be81433 2024-04-14 op cb.cb(-1, EV_TIMEOUT, cb.udata);
469 6be81433 2024-04-14 op continue;
470 0a53bd62 2023-08-16 op }
471 0a53bd62 2023-08-16 op
472 6be81433 2024-04-14 op memcpy(&base->timers[i].tv, &sub, sizeof(sub));
473 6be81433 2024-04-14 op i++;
474 6be81433 2024-04-14 op }
475 6be81433 2024-04-14 op
476 6be81433 2024-04-14 op for (i = 0; i < base->len && n > 0 && !ev_stop; ++i) {
477 6be81433 2024-04-14 op if (base->pfds[i].fd == -1)
478 6be81433 2024-04-14 op continue;
479 6be81433 2024-04-14 op if (base->pfds[i].revents & (POLLIN|POLLOUT|POLLHUP)) {
480 6be81433 2024-04-14 op n--;
481 6be81433 2024-04-14 op base->cbs[i].cb(base->pfds[i].fd,
482 6be81433 2024-04-14 op poll2ev(base->pfds[i].revents),
483 6be81433 2024-04-14 op base->cbs[i].udata);
484 0a53bd62 2023-08-16 op }
485 0a53bd62 2023-08-16 op }
486 0a53bd62 2023-08-16 op
487 6be81433 2024-04-14 op return (0);
488 6be81433 2024-04-14 op }
489 6be81433 2024-04-14 op
490 6be81433 2024-04-14 op int
491 6be81433 2024-04-14 op ev_loop(void)
492 6be81433 2024-04-14 op {
493 6be81433 2024-04-14 op while (!ev_stop) {
494 6be81433 2024-04-14 op if (ev_step() == -1)
495 6be81433 2024-04-14 op return (-1);
496 6be81433 2024-04-14 op }
497 6be81433 2024-04-14 op
498 0a53bd62 2023-08-16 op return 0;
499 0a53bd62 2023-08-16 op }
500 0a53bd62 2023-08-16 op
501 0a53bd62 2023-08-16 op void
502 0a53bd62 2023-08-16 op ev_break(void)
503 0a53bd62 2023-08-16 op {
504 0a53bd62 2023-08-16 op ev_stop = 1;
505 0a53bd62 2023-08-16 op }