Skip to content

Commit 25e6eac

Browse files
committed
Get rid of the hash table in the kqueue epoll implementation
This will get rid of a malloc()/free() every time epoll_wait() is called on a BSD system, but still coalesce the filters/and flags as before. Untested/uncompiled.
1 parent 5520530 commit 25e6eac

File tree

1 file changed

+32
-37
lines changed

1 file changed

+32
-37
lines changed

src/lib/missing-epoll.c

+32-37
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@
3434
#include <sys/time.h>
3535
#include <sys/types.h>
3636

37-
#include "hash.h"
38-
3937
int epoll_create1(int flags)
4038
{
4139
#if defined(LWAN_HAVE_KQUEUE1)
@@ -115,63 +113,60 @@ static struct timespec *to_timespec(struct timespec *t, int ms)
115113
return t;
116114
}
117115

116+
static int kevent_ident_cmp(const void *ptr0, const void *ptr1)
117+
{
118+
struct kevent *ev0 = ptr0;
119+
struct kevent *ev1 = ptr1;
120+
return (ev0->ident > ev1->ident) - (ev0->ident < ev1->ident);
121+
}
122+
118123
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
119124
{
120125
struct epoll_event *ev = events;
121126
struct kevent evs[maxevents];
122127
struct timespec tmspec;
123-
struct hash *coalesce;
124128
int i, r;
125129

126-
coalesce = hash_int_new(NULL, NULL);
127-
if (UNLIKELY(!coalesce))
128-
return -1;
129-
130130
r = kevent(epfd, NULL, 0, evs, maxevents, to_timespec(&tmspec, timeout));
131131
if (UNLIKELY(r < 0)) {
132-
hash_unref(coalesce);
133132
return -1;
134133
}
135134

136-
for (i = 0; i < r; i++) {
137-
struct kevent *kev = &evs[i];
138-
uint32_t mask = (uint32_t)(uintptr_t)hash_find(
139-
coalesce, (void *)(intptr_t)evs[i].ident);
140-
141-
if (kev->flags & EV_ERROR)
142-
mask |= EPOLLERR;
143-
if (kev->flags & EV_EOF)
144-
mask |= EPOLLRDHUP;
145-
146-
if (kev->filter == EVFILT_READ)
147-
mask |= EPOLLIN;
148-
else if (kev->filter == EVFILT_WRITE && evs[i].udata != &epoll_no_event_marker)
149-
mask |= EPOLLOUT;
150-
151-
hash_add(coalesce, (void *)(intptr_t)evs[i].ident,
152-
(void *)(uintptr_t)mask);
153-
}
135+
qsort(evs, (size_t)r, sizeof(struct kevent), kevent_ident_cmp);
154136

137+
int last = -1;
155138
for (i = 0; i < r; i++) {
156-
void *maskptr;
157-
158-
maskptr = hash_find(coalesce, (void *)(intptr_t)evs[i].ident);
159-
if (maskptr) {
160-
struct kevent *kev = &evs[i];
139+
struct kevent *kev = &evs[i];
161140

162-
if (kev->udata == &epoll_no_event_marker)
163-
continue;
141+
if (kev->udata == &epoll_no_event_marker) {
142+
continue;
143+
}
164144

165-
ev->data.ptr = kev->udata;
166-
ev->events = (uint32_t)(uintptr_t)maskptr;
145+
if (last < 0) {
146+
ev->mask = 0;
147+
} else if (kev->ident != last) {
167148
ev++;
149+
ev->mask = 0;
150+
}
151+
152+
if (kev->flags & EV_ERROR) {
153+
ev->events |= EPOLLERR;
154+
}
155+
if (kev->flags & EV_EOF) {
156+
ev->events |= EPOLLRDHUP;
157+
}
158+
if (kev->filter == EVFILT_READ) {
159+
ev->events |= EPOLLIN;
160+
} else if (kev->filter == EVFILT_WRITE) {
161+
ev->events |= EPOLLOUT;
168162
}
163+
ev->data.ptr = kev->udata;
164+
165+
last = kev->ident;
169166
}
170167

171-
hash_unref(coalesce);
172168
return (int)(intptr_t)(ev - events);
173169
}
174170
#elif !defined(LWAN_HAVE_EPOLL)
175171
#error epoll() not implemented for this platform
176172
#endif
177-

0 commit comments

Comments
 (0)