Skip to content

Commit be3fd20

Browse files
committed
eloop: Simplify kqueue implementation
Easier to read, reduces binary size at a small cost of more kevents when forking and keeping fd's which is acceptable.
1 parent 2059c20 commit be3fd20

File tree

1 file changed

+106
-142
lines changed

1 file changed

+106
-142
lines changed

src/eloop.c

Lines changed: 106 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
#ifdef BSD
4040
#include <sys/event.h>
4141
#define USE_KQUEUE
42-
#define NFD 2
4342
#if defined(__NetBSD__) || defined(__OpenBSD__)
4443
#define HAVE_KQUEUE1
4544
#endif
@@ -91,10 +90,6 @@
9190
#define UTIME_MAX (TIME_MAX * 2) + 1
9291
#endif
9392

94-
#ifndef NFD
95-
#define NFD 1
96-
#endif
97-
9893
#ifndef UNUSED
9994
#define UNUSED(a) (void)(a)
10095
#endif
@@ -178,17 +173,15 @@ eloop_event_setup_fds(struct eloop *eloop)
178173
struct eloop_event *e, *ne;
179174
#ifdef USE_PPOLL
180175
struct pollfd *pfd;
181-
size_t nfds = 0;
182176

183-
nfds += eloop->nevents;
184-
if (nfds > eloop->nfds) {
185-
pfd = eloop_realloca(eloop->fds, nfds, sizeof(*pfd));
177+
if (eloop->nevents > eloop->nfds) {
178+
pfd = eloop_realloca(eloop->fds, eloop->nevents, sizeof(*pfd));
186179
if (pfd == NULL)
187180
return -1;
188181
eloop->fds = pfd;
189-
eloop->nfds = nfds;
190-
}
191-
pfd = eloop->fds;
182+
eloop->nfds = eloop->nevents;
183+
} else
184+
pfd = eloop->fds;
192185
#endif
193186

194187
TAILQ_FOREACH_SAFE(e, &eloop->events, next, ne) {
@@ -240,25 +233,93 @@ eloop_event_count(const struct eloop *eloop)
240233
return eloop->nevents;
241234
}
242235

243-
int
244-
eloop_event_add(struct eloop *eloop, int fd, unsigned short events,
245-
void (*cb)(void *, unsigned short), void *cb_arg)
246-
{
247-
struct eloop_event *e;
248-
bool added;
249236
#if defined(USE_KQUEUE)
237+
238+
static int
239+
eloop_signal_kqueue(struct eloop *eloop, const int *signals, size_t nsignals)
240+
{
241+
size_t n = nsignals == 0 ? eloop->nsignals : nsignals;
242+
struct kevent ke[n], *kep = ke;
243+
size_t i;
244+
245+
if (eloop->signal_cb == NULL || n == 0)
246+
return 0;
247+
248+
if (signals == NULL)
249+
signals = eloop->signals;
250+
for (i = 0; i < n; i++)
251+
EV_SET(kep++, (uintptr_t)signals[i],
252+
EVFILT_SIGNAL, nsignals == 0 ? EV_DELETE : EV_ADD, 0, 0, NULL);
253+
254+
return _kevent(eloop->fd, ke, n, NULL, 0, NULL);
255+
}
256+
257+
static int
258+
eloop_event_kqueue(struct eloop *eloop, struct eloop_event *e,
259+
unsigned short events)
260+
{
250261
#ifdef EVFILT_PROCDESC
251262
#define NKE 3
252263
#else
253264
#define NKE 2
254265
#endif
255-
struct kevent ke[NKE], *kep = &ke[0];
256-
size_t n = NKE;
266+
struct kevent ke[NKE], *kep = ke;
267+
int fd = e->fd;
268+
269+
if (events & ELE_READ && !(e->events & ELE_READ))
270+
EV_SET(kep++, (uintptr_t)fd, EVFILT_READ, EV_ADD, 0, 0, e);
271+
else if (!(events & ELE_READ) && e->events & ELE_READ)
272+
EV_SET(kep++, (uintptr_t)fd, EVFILT_READ, EV_DELETE, 0, 0, e);
273+
if (events & ELE_WRITE && !(e->events & ELE_WRITE))
274+
EV_SET(kep++, (uintptr_t)fd, EVFILT_WRITE, EV_ADD, 0, 0, e);
275+
else if (!(events & ELE_WRITE) && e->events & ELE_WRITE)
276+
EV_SET(kep++, (uintptr_t)fd, EVFILT_WRITE, EV_DELETE, 0, 0, e);
277+
#ifdef EVFILT_PROCDESC
278+
if (events & ELE_HANGUP && !(e->events & ELE_HANGUP))
279+
EV_SET(kep++, (uintptr_t)fd, EVFILT_PROCDESC, EV_ADD, NOTE_EXIT,
280+
0, e);
281+
else if (!(events & ELE_HANGUP) && e->events & ELE_HANGUP)
282+
EV_SET(kep++, (uintptr_t)fd, EVFILT_PROCDESC, EV_DELETE, NOTE_EXIT,
283+
0, e);
284+
#endif
285+
if (kep == ke)
286+
return 0;
287+
if (_kevent(eloop->fd, ke, kep - ke, NULL, 0, NULL) == -1)
288+
return -1;
289+
return 1;
290+
}
291+
257292
#elif defined(USE_EPOLL)
293+
294+
static int
295+
eloop_event_epoll(struct eloop *eloop, struct eloop_event *e,
296+
unsigned short events)
297+
{
258298
struct epoll_event epe;
259-
int op;
299+
300+
memset(&epe, 0, sizeof(epe));
301+
epe.data.ptr = e;
302+
if (events & ELE_READ)
303+
epe.events |= EPOLLIN;
304+
if (events & ELE_WRITE)
305+
epe.events |= EPOLLOUT;
306+
op = added ? EPOLL_CTL_ADD : EPOLL_CTL_MOD;
307+
if (eve.events == 0)
308+
return 0;
309+
if (epoll_ctl(eloop->fd, op, fd, &epe) == -1)
310+
return -1;
311+
return 1;
312+
}
260313
#endif
261314

315+
int
316+
eloop_event_add(struct eloop *eloop, int fd, unsigned short events,
317+
void (*cb)(void *, unsigned short), void *cb_arg)
318+
{
319+
struct eloop_event *e;
320+
bool added;
321+
int kadded;
322+
262323
if (fd == -1 || !(events & (ELE_READ | ELE_WRITE | ELE_HANGUP))) {
263324
errno = EINVAL;
264325
return -1;
@@ -291,54 +352,22 @@ eloop_event_add(struct eloop *eloop, int fd, unsigned short events,
291352
e->cb_arg = cb_arg;
292353

293354
#if defined(USE_KQUEUE)
294-
if (events & ELE_READ && !(e->events & ELE_READ))
295-
EV_SET(kep++, (uintptr_t)fd, EVFILT_READ, EV_ADD, 0, 0, e);
296-
else if (!(events & ELE_READ) && e->events & ELE_READ)
297-
EV_SET(kep++, (uintptr_t)fd, EVFILT_READ, EV_DELETE, 0, 0, e);
298-
else
299-
n--;
300-
if (events & ELE_WRITE && !(e->events & ELE_WRITE))
301-
EV_SET(kep++, (uintptr_t)fd, EVFILT_WRITE, EV_ADD, 0, 0, e);
302-
else if (!(events & ELE_WRITE) && e->events & ELE_WRITE)
303-
EV_SET(kep++, (uintptr_t)fd, EVFILT_WRITE, EV_DELETE, 0, 0, e);
304-
else
305-
n--;
306-
#ifdef EVFILT_PROCDESC
307-
if (events & ELE_HANGUP)
308-
EV_SET(kep++, (uintptr_t)fd, EVFILT_PROCDESC, EV_ADD, NOTE_EXIT,
309-
0, e);
310-
else
311-
n--;
312-
#endif
313-
if (n != 0 && _kevent(eloop->fd, ke, n, NULL, 0, NULL) == -1) {
314-
if (added) {
315-
TAILQ_REMOVE(&eloop->events, e, next);
316-
TAILQ_INSERT_TAIL(&eloop->free_events, e, next);
317-
}
318-
return -1;
319-
}
355+
kadded = eloop_event_kqueue(eloop, e, events);
320356
#elif defined(USE_EPOLL)
321-
memset(&epe, 0, sizeof(epe));
322-
epe.data.ptr = e;
323-
if (events & ELE_READ)
324-
epe.events |= EPOLLIN;
325-
if (events & ELE_WRITE)
326-
epe.events |= EPOLLOUT;
327-
op = added ? EPOLL_CTL_ADD : EPOLL_CTL_MOD;
328-
if (epe.events != 0 && epoll_ctl(eloop->fd, op, fd, &epe) == -1) {
329-
if (added) {
330-
TAILQ_REMOVE(&eloop->events, e, next);
331-
TAILQ_INSERT_TAIL(&eloop->free_events, e, next);
332-
}
333-
return -1;
334-
}
357+
kadded = eloop_event_epoll(eloop, e, events);
335358
#elif defined(USE_PPOLL)
336359
e->pollfd = NULL;
337-
UNUSED(added);
360+
kadded = 1;
338361
#endif
362+
363+
if (kadded != 1 && added) {
364+
TAILQ_REMOVE(&eloop->events, e, next);
365+
TAILQ_INSERT_TAIL(&eloop->free_events, e, next);
366+
}
367+
339368
e->events = events;
340369
eloop->events_need_setup = true;
341-
return 0;
370+
return kadded;
342371
}
343372

344373
int
@@ -666,76 +695,37 @@ eloop_forked(struct eloop *eloop, unsigned short flags)
666695
{
667696
#if defined(USE_KQUEUE) || defined(USE_EPOLL)
668697
struct eloop_event *e;
669-
#if defined(USE_KQUEUE)
670-
struct kevent *pfds, *pfd;
671-
size_t i;
698+
unsigned short events;
672699
int err;
673-
#elif defined(USE_EPOLL)
674-
struct epoll_event epe = { .events = 0 };
675-
#endif
676700

677-
#if defined(USE_KQUEUE) || defined(USE_EPOLL)
678701
/* The fd is invalid after a fork, no need to close it. */
679702
eloop->fd = -1;
680703
if (flags && eloop_open(eloop) == -1)
681704
return -1;
682-
#endif
705+
683706
eloop_clear(eloop, flags);
684707
if (!flags)
685708
return 0;
686709

687710
#ifdef USE_KQUEUE
688-
pfds = malloc(
689-
(eloop->nsignals + (eloop->nevents * NFD)) * sizeof(*pfds));
690-
if (pfds == NULL)
711+
if (eloop_signal_kqueue(eloop, eloop->signals, eloop->nsignals) == -1)
691712
return -1;
692-
pfd = pfds;
693-
694-
if (eloop->signal_cb != NULL) {
695-
for (i = 0; i < eloop->nsignals; i++) {
696-
EV_SET(pfd++, (uintptr_t)eloop->signals[i],
697-
EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
698-
}
699-
} else
700-
i = 0;
701713
#endif
702714

703715
TAILQ_FOREACH(e, &eloop->events, next) {
704716
if (e->fd == -1)
705717
continue;
718+
events = e->events;
719+
e->events = 0;
706720
#if defined(USE_KQUEUE)
707-
if (e->events & ELE_READ) {
708-
EV_SET(pfd++, (uintptr_t)e->fd, EVFILT_READ, EV_ADD, 0,
709-
0, e);
710-
i++;
711-
}
712-
if (e->events & ELE_WRITE) {
713-
EV_SET(pfd++, (uintptr_t)e->fd, EVFILT_WRITE, EV_ADD, 0,
714-
0, e);
715-
i++;
716-
}
721+
err = eloop_event_kqueue(eloop, e, events);
717722
#elif defined(USE_EPOLL)
718-
memset(&epe, 0, sizeof(epe));
719-
epe.data.ptr = e;
720-
if (e->events & ELE_READ)
721-
epe.events |= EPOLLIN;
722-
if (e->events & ELE_WRITE)
723-
epe.events |= EPOLLOUT;
724-
if (epoll_ctl(eloop->fd, EPOLL_CTL_ADD, e->fd, &epe) == -1)
725-
return -1;
723+
err = eloop_event_epoll(eloop, e, events);
726724
#endif
725+
if (err == -1)
726+
return -1;
727727
}
728-
729-
#if defined(USE_KQUEUE)
730-
if (i == 0)
731-
err = 0;
732-
else
733-
err = _kevent(eloop->fd, pfds, i, NULL, 0, NULL);
734-
free(pfds);
735-
return err;
736-
#else
737728
return 0;
738-
#endif
739729
#else
740730
eloop_clear(eloop, flags);
741731
return 0;
@@ -746,24 +736,10 @@ int
746736
eloop_signal_set_cb(struct eloop *eloop, const int *signals, size_t nsignals,
747737
void (*signal_cb)(int, void *), void *signal_cb_ctx)
748738
{
749-
#ifdef USE_KQUEUE
750-
size_t i;
751-
struct kevent *ke, *kes;
752-
#endif
753-
int error = 0;
754739

755740
#ifdef USE_KQUEUE
756-
ke = kes = malloc(MAX(eloop->nsignals, nsignals) * sizeof(*kes));
757-
if (kes == NULL)
741+
if (eloop_signal_kqueue(eloop, NULL, 0) == -1)
758742
return -1;
759-
for (i = 0; i < eloop->nsignals; i++) {
760-
EV_SET(ke++, (uintptr_t)eloop->signals[i], EVFILT_SIGNAL,
761-
EV_DELETE, 0, 0, NULL);
762-
}
763-
if (i != 0 && _kevent(eloop->fd, kes, i, NULL, 0, NULL) == -1) {
764-
error = -1;
765-
goto out;
766-
}
767743
#endif
768744

769745
eloop->signals = signals;
@@ -772,23 +748,11 @@ eloop_signal_set_cb(struct eloop *eloop, const int *signals, size_t nsignals,
772748
eloop->signal_cb_ctx = signal_cb_ctx;
773749

774750
#ifdef USE_KQUEUE
775-
if (signal_cb == NULL)
776-
goto out;
777-
ke = kes;
778-
for (i = 0; i < eloop->nsignals; i++) {
779-
EV_SET(ke++, (uintptr_t)eloop->signals[i], EVFILT_SIGNAL,
780-
EV_ADD, 0, 0, NULL);
781-
}
782-
if (i != 0) {
783-
if (_kevent(eloop->fd, kes, i, NULL, 0, NULL) == -1)
784-
error = -1;
785-
eloop->events_need_setup = true;
786-
}
787-
out:
788-
free(kes);
751+
if (eloop_signal_kqueue(eloop, signals, nsignals) == -1)
752+
return -1;
789753
#endif
790754

791-
return error;
755+
return 0;
792756
}
793757

794758
#ifndef USE_KQUEUE
@@ -1016,7 +980,7 @@ eloop_run_ppoll(struct eloop *eloop, const struct timespec *ts)
1016980
struct pollfd *pfd;
1017981
unsigned short events;
1018982

1019-
n = ppoll(eloop->fds, (nfds_t)eloop->nfds, ts, &eloop->sigset);
983+
n = ppoll(eloop->fds, (nfds_t)eloop->nevents, ts, &eloop->sigset);
1020984
if (n == -1 || n == 0)
1021985
return n;
1022986

0 commit comments

Comments
 (0)