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 0a53bd62 2023-08-16 op #include <errno.h>
29 0a53bd62 2023-08-16 op #include <fcntl.h>
30 0a53bd62 2023-08-16 op #include <limits.h>
31 0a53bd62 2023-08-16 op #include <poll.h>
32 0a53bd62 2023-08-16 op #include <signal.h>
33 0a53bd62 2023-08-16 op #include <stdlib.h>
34 27bf07a4 2023-08-16 op #include <time.h>
35 0a53bd62 2023-08-16 op #include <unistd.h>
36 0a53bd62 2023-08-16 op
37 0a53bd62 2023-08-16 op #include "ev.h"
38 0a53bd62 2023-08-16 op
39 0a53bd62 2023-08-16 op struct evcb {
40 0a53bd62 2023-08-16 op void (*cb)(int, int, void *);
41 0a53bd62 2023-08-16 op void *udata;
42 0a53bd62 2023-08-16 op };
43 0a53bd62 2023-08-16 op
44 0a53bd62 2023-08-16 op struct evbase {
45 0a53bd62 2023-08-16 op size_t len;
46 0a53bd62 2023-08-16 op
47 0a53bd62 2023-08-16 op struct pollfd *pfds;
48 0a53bd62 2023-08-16 op size_t pfdlen;
49 0a53bd62 2023-08-16 op
50 0a53bd62 2023-08-16 op struct evcb *cbs;
51 0a53bd62 2023-08-16 op size_t cblen;
52 0a53bd62 2023-08-16 op
53 0a53bd62 2023-08-16 op int sigpipe[2];
54 0a53bd62 2023-08-16 op struct evcb sigcb;
55 0a53bd62 2023-08-16 op
56 0a53bd62 2023-08-16 op int timeout;
57 0a53bd62 2023-08-16 op struct evcb toutcb;
58 0a53bd62 2023-08-16 op };
59 0a53bd62 2023-08-16 op
60 0a53bd62 2023-08-16 op static struct evbase *base;
61 0a53bd62 2023-08-16 op static int ev_stop;
62 0a53bd62 2023-08-16 op
63 0a53bd62 2023-08-16 op static int
64 0a53bd62 2023-08-16 op ev_resize(size_t len)
65 0a53bd62 2023-08-16 op {
66 0a53bd62 2023-08-16 op void *t;
67 0a53bd62 2023-08-16 op size_t i;
68 0a53bd62 2023-08-16 op
69 0a53bd62 2023-08-16 op t = recallocarray(base->pfds, base->pfdlen, len, sizeof(*base->pfds));
70 0a53bd62 2023-08-16 op if (t == NULL)
71 0a53bd62 2023-08-16 op return -1;
72 0a53bd62 2023-08-16 op base->pfds = t;
73 0a53bd62 2023-08-16 op base->pfdlen = len;
74 0a53bd62 2023-08-16 op
75 0a53bd62 2023-08-16 op for (i = base->len; i < len; ++i)
76 0a53bd62 2023-08-16 op base->pfds[i].fd = -1;
77 0a53bd62 2023-08-16 op
78 0a53bd62 2023-08-16 op t = recallocarray(base->cbs, base->cblen, len, sizeof(*base->cbs));
79 0a53bd62 2023-08-16 op if (t == NULL)
80 0a53bd62 2023-08-16 op return -1;
81 0a53bd62 2023-08-16 op base->cbs = t;
82 0a53bd62 2023-08-16 op base->cblen = len;
83 0a53bd62 2023-08-16 op
84 0a53bd62 2023-08-16 op base->len = len;
85 0a53bd62 2023-08-16 op return 0;
86 0a53bd62 2023-08-16 op }
87 0a53bd62 2023-08-16 op
88 0a53bd62 2023-08-16 op int
89 0a53bd62 2023-08-16 op ev_init(void)
90 0a53bd62 2023-08-16 op {
91 0a53bd62 2023-08-16 op if (base != NULL) {
92 0a53bd62 2023-08-16 op errno = EINVAL;
93 0a53bd62 2023-08-16 op return -1;
94 0a53bd62 2023-08-16 op }
95 0a53bd62 2023-08-16 op
96 0a53bd62 2023-08-16 op if ((base = calloc(1, sizeof(*base))) == NULL)
97 0a53bd62 2023-08-16 op return -1;
98 0a53bd62 2023-08-16 op
99 0a53bd62 2023-08-16 op base->sigpipe[0] = -1;
100 0a53bd62 2023-08-16 op base->sigpipe[1] = -1;
101 0a53bd62 2023-08-16 op base->timeout = INFTIM;
102 0a53bd62 2023-08-16 op
103 0a53bd62 2023-08-16 op if (ev_resize(16) == -1) {
104 0a53bd62 2023-08-16 op free(base->pfds);
105 0a53bd62 2023-08-16 op free(base->cbs);
106 0a53bd62 2023-08-16 op free(base);
107 0a53bd62 2023-08-16 op base = NULL;
108 0a53bd62 2023-08-16 op return -1;
109 0a53bd62 2023-08-16 op }
110 0a53bd62 2023-08-16 op
111 0a53bd62 2023-08-16 op return 0;
112 0a53bd62 2023-08-16 op }
113 0a53bd62 2023-08-16 op
114 0a53bd62 2023-08-16 op int
115 0a53bd62 2023-08-16 op ev_add(int fd, int ev, void (*cb)(int, int, void *), void *udata)
116 0a53bd62 2023-08-16 op {
117 0a53bd62 2023-08-16 op if (fd >= base->len) {
118 0a53bd62 2023-08-16 op if (ev_resize(fd + 1) == -1)
119 0a53bd62 2023-08-16 op return -1;
120 0a53bd62 2023-08-16 op }
121 0a53bd62 2023-08-16 op
122 0a53bd62 2023-08-16 op base->pfds[fd].fd = fd;
123 0a53bd62 2023-08-16 op base->pfds[fd].events = ev;
124 0a53bd62 2023-08-16 op
125 0a53bd62 2023-08-16 op base->cbs[fd].cb = cb;
126 0a53bd62 2023-08-16 op base->cbs[fd].udata = udata;
127 0a53bd62 2023-08-16 op
128 0a53bd62 2023-08-16 op return 0;
129 0a53bd62 2023-08-16 op }
130 0a53bd62 2023-08-16 op
131 0a53bd62 2023-08-16 op static void
132 0a53bd62 2023-08-16 op ev_sigcatch(int signo)
133 0a53bd62 2023-08-16 op {
134 0a53bd62 2023-08-16 op unsigned char s;
135 0a53bd62 2023-08-16 op int err;
136 0a53bd62 2023-08-16 op
137 0a53bd62 2023-08-16 op err = errno;
138 0a53bd62 2023-08-16 op
139 0a53bd62 2023-08-16 op /*
140 0a53bd62 2023-08-16 op * We should be able to write up to PIPE_BUF bytes without
141 0a53bd62 2023-08-16 op * blocking.
142 0a53bd62 2023-08-16 op */
143 0a53bd62 2023-08-16 op s = signo;
144 0a53bd62 2023-08-16 op (void) write(base->sigpipe[1], &s, sizeof(s));
145 0a53bd62 2023-08-16 op
146 0a53bd62 2023-08-16 op errno = err;
147 0a53bd62 2023-08-16 op }
148 0a53bd62 2023-08-16 op
149 0a53bd62 2023-08-16 op static void
150 0a53bd62 2023-08-16 op ev_sigdispatch(int fd, int ev, void *data)
151 0a53bd62 2023-08-16 op {
152 0a53bd62 2023-08-16 op unsigned char signo;
153 0a53bd62 2023-08-16 op
154 0a53bd62 2023-08-16 op if (read(fd, &signo, sizeof(signo)) != sizeof(signo))
155 0a53bd62 2023-08-16 op return;
156 0a53bd62 2023-08-16 op
157 0a53bd62 2023-08-16 op base->sigcb.cb(signo, 0, base->sigcb.udata);
158 0a53bd62 2023-08-16 op }
159 0a53bd62 2023-08-16 op
160 0a53bd62 2023-08-16 op int
161 0a53bd62 2023-08-16 op ev_signal(int sig, void (*cb)(int, int, void *), void *udata)
162 0a53bd62 2023-08-16 op {
163 dc3e25b1 2023-10-07 op int flags;
164 dc3e25b1 2023-10-07 op
165 0a53bd62 2023-08-16 op if (base->sigpipe[0] == -1) {
166 dc3e25b1 2023-10-07 op /* pipe2(2) is not available everywhere... sigh */
167 dc3e25b1 2023-10-07 op if (pipe(base->sigpipe) == -1)
168 dc3e25b1 2023-10-07 op return -1;
169 dc3e25b1 2023-10-07 op
170 dc3e25b1 2023-10-07 op if ((flags = fcntl(base->sigpipe[1], F_GETFL)) == -1 ||
171 dc3e25b1 2023-10-07 op fcntl(base->sigpipe[1], F_SETFL, flags | O_NONBLOCK) == -1)
172 0a53bd62 2023-08-16 op return -1;
173 dc3e25b1 2023-10-07 op
174 0a53bd62 2023-08-16 op if (ev_add(base->sigpipe[0], POLLIN, ev_sigdispatch, NULL)
175 0a53bd62 2023-08-16 op == -1)
176 0a53bd62 2023-08-16 op return -1;
177 0a53bd62 2023-08-16 op }
178 0a53bd62 2023-08-16 op
179 0a53bd62 2023-08-16 op base->sigcb.cb = cb;
180 0a53bd62 2023-08-16 op base->sigcb.udata = udata;
181 0a53bd62 2023-08-16 op
182 0a53bd62 2023-08-16 op signal(sig, ev_sigcatch);
183 0a53bd62 2023-08-16 op return 0;
184 0a53bd62 2023-08-16 op }
185 0a53bd62 2023-08-16 op
186 0a53bd62 2023-08-16 op int
187 0a53bd62 2023-08-16 op ev_timer(const struct timeval *tv, void (*cb)(int, int, void*), void *udata)
188 0a53bd62 2023-08-16 op {
189 0a53bd62 2023-08-16 op base->timeout = INFTIM;
190 0a53bd62 2023-08-16 op if (tv) {
191 0a53bd62 2023-08-16 op base->timeout = tv->tv_sec * 1000;
192 0a53bd62 2023-08-16 op base->timeout += tv->tv_usec / 1000;
193 0a53bd62 2023-08-16 op }
194 0a53bd62 2023-08-16 op
195 0a53bd62 2023-08-16 op base->toutcb.cb = cb;
196 0a53bd62 2023-08-16 op base->toutcb.udata = udata;
197 0a53bd62 2023-08-16 op
198 0a53bd62 2023-08-16 op return 0;
199 0a53bd62 2023-08-16 op }
200 0a53bd62 2023-08-16 op
201 0a53bd62 2023-08-16 op int
202 0a53bd62 2023-08-16 op ev_timer_pending(void)
203 0a53bd62 2023-08-16 op {
204 0a53bd62 2023-08-16 op return base->timeout != INFTIM;
205 0a53bd62 2023-08-16 op }
206 0a53bd62 2023-08-16 op
207 0a53bd62 2023-08-16 op int
208 0a53bd62 2023-08-16 op ev_del(int fd)
209 0a53bd62 2023-08-16 op {
210 0a53bd62 2023-08-16 op if (fd >= base->len) {
211 0a53bd62 2023-08-16 op errno = ERANGE;
212 0a53bd62 2023-08-16 op return -1;
213 0a53bd62 2023-08-16 op }
214 0a53bd62 2023-08-16 op
215 0a53bd62 2023-08-16 op base->pfds[fd].fd = -1;
216 0a53bd62 2023-08-16 op base->pfds[fd].events = 0;
217 0a53bd62 2023-08-16 op
218 0a53bd62 2023-08-16 op base->cbs[fd].cb = NULL;
219 0a53bd62 2023-08-16 op base->cbs[fd].udata = NULL;
220 0a53bd62 2023-08-16 op
221 0a53bd62 2023-08-16 op return 0;
222 0a53bd62 2023-08-16 op }
223 0a53bd62 2023-08-16 op
224 0a53bd62 2023-08-16 op int
225 0a53bd62 2023-08-16 op ev_loop(void)
226 0a53bd62 2023-08-16 op {
227 0a53bd62 2023-08-16 op struct timespec elapsed, beg, end;
228 0a53bd62 2023-08-16 op int n, em;
229 0a53bd62 2023-08-16 op size_t i;
230 0a53bd62 2023-08-16 op
231 0a53bd62 2023-08-16 op while (!ev_stop) {
232 0a53bd62 2023-08-16 op clock_gettime(CLOCK_MONOTONIC, &beg);
233 0a53bd62 2023-08-16 op if ((n = poll(base->pfds, base->len, base->timeout)) == -1) {
234 0a53bd62 2023-08-16 op if (errno != EINTR)
235 0a53bd62 2023-08-16 op return -1;
236 0a53bd62 2023-08-16 op }
237 0a53bd62 2023-08-16 op clock_gettime(CLOCK_MONOTONIC, &end);
238 0a53bd62 2023-08-16 op
239 0a53bd62 2023-08-16 op timespecsub(&end, &beg, &elapsed);
240 0a53bd62 2023-08-16 op em = elapsed.tv_sec * 1000 + elapsed.tv_nsec / 1000000;
241 0a53bd62 2023-08-16 op if (base->timeout != INFTIM) {
242 0a53bd62 2023-08-16 op if (base->timeout - em < 0 || n == 0) {
243 0a53bd62 2023-08-16 op base->timeout = INFTIM;
244 0a53bd62 2023-08-16 op base->toutcb.cb(-1, 0, base->toutcb.udata);
245 0a53bd62 2023-08-16 op } else
246 0a53bd62 2023-08-16 op base->timeout -= em;
247 0a53bd62 2023-08-16 op }
248 0a53bd62 2023-08-16 op
249 0a53bd62 2023-08-16 op for (i = 0; i < base->len && n > 0 && !ev_stop; ++i) {
250 0a53bd62 2023-08-16 op if (base->pfds[i].fd == -1)
251 0a53bd62 2023-08-16 op continue;
252 0a53bd62 2023-08-16 op if (base->pfds[i].revents & (POLLIN|POLLOUT|POLLHUP)) {
253 0a53bd62 2023-08-16 op n--;
254 0a53bd62 2023-08-16 op base->cbs[i].cb(base->pfds[i].fd,
255 0a53bd62 2023-08-16 op base->pfds[i].revents,
256 0a53bd62 2023-08-16 op base->cbs[i].udata);
257 0a53bd62 2023-08-16 op }
258 0a53bd62 2023-08-16 op }
259 0a53bd62 2023-08-16 op }
260 0a53bd62 2023-08-16 op
261 0a53bd62 2023-08-16 op return 0;
262 0a53bd62 2023-08-16 op }
263 0a53bd62 2023-08-16 op
264 0a53bd62 2023-08-16 op void
265 0a53bd62 2023-08-16 op ev_break(void)
266 0a53bd62 2023-08-16 op {
267 0a53bd62 2023-08-16 op ev_stop = 1;
268 0a53bd62 2023-08-16 op }