|
34 | 34 | #include <sys/time.h>
|
35 | 35 | #include <sys/types.h>
|
36 | 36 |
|
37 |
| -#include "hash.h" |
38 |
| - |
39 | 37 | int epoll_create1(int flags)
|
40 | 38 | {
|
41 | 39 | #if defined(LWAN_HAVE_KQUEUE1)
|
@@ -115,63 +113,60 @@ static struct timespec *to_timespec(struct timespec *t, int ms)
|
115 | 113 | return t;
|
116 | 114 | }
|
117 | 115 |
|
| 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 | + |
118 | 123 | int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
|
119 | 124 | {
|
120 | 125 | struct epoll_event *ev = events;
|
121 | 126 | struct kevent evs[maxevents];
|
122 | 127 | struct timespec tmspec;
|
123 |
| - struct hash *coalesce; |
124 | 128 | int i, r;
|
125 | 129 |
|
126 |
| - coalesce = hash_int_new(NULL, NULL); |
127 |
| - if (UNLIKELY(!coalesce)) |
128 |
| - return -1; |
129 |
| - |
130 | 130 | r = kevent(epfd, NULL, 0, evs, maxevents, to_timespec(&tmspec, timeout));
|
131 | 131 | if (UNLIKELY(r < 0)) {
|
132 |
| - hash_unref(coalesce); |
133 | 132 | return -1;
|
134 | 133 | }
|
135 | 134 |
|
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); |
154 | 136 |
|
| 137 | + int last = -1; |
155 | 138 | 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]; |
161 | 140 |
|
162 |
| - if (kev->udata == &epoll_no_event_marker) |
163 |
| - continue; |
| 141 | + if (kev->udata == &epoll_no_event_marker) { |
| 142 | + continue; |
| 143 | + } |
164 | 144 |
|
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) { |
167 | 148 | 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; |
168 | 162 | }
|
| 163 | + ev->data.ptr = kev->udata; |
| 164 | + |
| 165 | + last = kev->ident; |
169 | 166 | }
|
170 | 167 |
|
171 |
| - hash_unref(coalesce); |
172 | 168 | return (int)(intptr_t)(ev - events);
|
173 | 169 | }
|
174 | 170 | #elif !defined(LWAN_HAVE_EPOLL)
|
175 | 171 | #error epoll() not implemented for this platform
|
176 | 172 | #endif
|
177 |
| - |
0 commit comments