Blame


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