17 #ifdef USE_FREEBSD_KQUEUE
18 # include <sys/event.h>
19 # include <sys/time.h>
21 static void fdevent_freebsd_kqueue_free(fdevents
*ev
) {
26 static int fdevent_freebsd_kqueue_event_del(fdevents
*ev
, int fde_ndx
, int fd
) {
32 if (fde_ndx
< 0) return -1;
34 oevents
= ev
->fdarray
[fd
]->events
;
36 if (oevents
& FDEVENT_IN
) {
37 EV_SET(&kev
[n
], fd
, EVFILT_READ
, EV_DELETE
, 0, 0, NULL
);
40 if (oevents
& FDEVENT_OUT
) {
41 EV_SET(&kev
[n
], fd
, EVFILT_WRITE
, EV_DELETE
, 0, 0, NULL
);
45 if (0 == n
) return -1;
50 ret
= kevent(ev
->kq_fd
,
56 log_error_write(ev
->srv
, __FILE__
, __LINE__
, "SS",
57 "kqueue event delete failed: ", strerror(errno
));
65 static int fdevent_freebsd_kqueue_event_set(fdevents
*ev
, int fde_ndx
, int fd
, int events
) {
69 int oevents
= ev
->fdarray
[fd
]->events
;
70 int addevents
= events
& ~oevents
;
71 int delevents
= ~events
& oevents
;
75 if (events
== oevents
) return fd
;
77 if (addevents
& FDEVENT_IN
) {
78 EV_SET(&kev
[n
], fd
, EVFILT_READ
, EV_ADD
|EV_CLEAR
, 0, 0, NULL
);
80 } else if (delevents
& FDEVENT_IN
) {
81 EV_SET(&kev
[n
], fd
, EVFILT_READ
, EV_DELETE
, 0, 0, NULL
);
84 if (addevents
& FDEVENT_OUT
) {
85 EV_SET(&kev
[n
], fd
, EVFILT_WRITE
, EV_ADD
|EV_CLEAR
, 0, 0, NULL
);
87 } else if (delevents
& FDEVENT_OUT
) {
88 EV_SET(&kev
[n
], fd
, EVFILT_WRITE
, EV_DELETE
, 0, 0, NULL
);
92 if (0 == n
) return fd
;
97 ret
= kevent(ev
->kq_fd
,
103 log_error_write(ev
->srv
, __FILE__
, __LINE__
, "SS",
104 "kqueue event set failed: ", strerror(errno
));
112 static int fdevent_freebsd_kqueue_poll(fdevents
*ev
, int timeout_ms
) {
116 ts
.tv_sec
= timeout_ms
/ 1000;
117 ts
.tv_nsec
= (timeout_ms
% 1000) * 1000000;
119 ret
= kevent(ev
->kq_fd
,
121 ev
->kq_results
, ev
->maxfds
,
127 /* we got interrupted, perhaps just a SIGCHLD of a CGI script */
130 log_error_write(ev
->srv
, __FILE__
, __LINE__
, "SS",
131 "kqueue failed polling: ", strerror(errno
));
139 static int fdevent_freebsd_kqueue_event_get_revent(fdevents
*ev
, size_t ndx
) {
142 e
= ev
->kq_results
[ndx
].filter
;
144 if (e
== EVFILT_READ
) {
145 events
|= FDEVENT_IN
;
146 } else if (e
== EVFILT_WRITE
) {
147 events
|= FDEVENT_OUT
;
150 e
= ev
->kq_results
[ndx
].flags
;
153 events
|= FDEVENT_HUP
;
157 events
|= FDEVENT_ERR
;
163 static int fdevent_freebsd_kqueue_event_get_fd(fdevents
*ev
, size_t ndx
) {
164 return ev
->kq_results
[ndx
].ident
;
167 static int fdevent_freebsd_kqueue_event_next_fdndx(fdevents
*ev
, int ndx
) {
170 return (ndx
< 0) ? 0 : ndx
+ 1;
173 static int fdevent_freebsd_kqueue_reset(fdevents
*ev
) {
174 if (-1 == (ev
->kq_fd
= kqueue())) {
175 log_error_write(ev
->srv
, __FILE__
, __LINE__
, "SSS",
176 "kqueue failed (", strerror(errno
), "), try to set server.event-handler = \"poll\" or \"select\"");
185 int fdevent_freebsd_kqueue_init(fdevents
*ev
) {
186 ev
->type
= FDEVENT_HANDLER_FREEBSD_KQUEUE
;
188 ev->x = fdevent_freebsd_kqueue_##x;
197 SET(event_next_fdndx
);
199 SET(event_get_revent
);
203 ev
->kq_results
= calloc(ev
->maxfds
, sizeof(*ev
->kq_results
));
204 force_assert(NULL
!= ev
->kq_results
);
206 /* check that kqueue works */
208 if (-1 == (ev
->kq_fd
= kqueue())) {
209 log_error_write(ev
->srv
, __FILE__
, __LINE__
, "SSS",
210 "kqueue failed (", strerror(errno
), "), try to set server.event-handler = \"poll\" or \"select\"");
221 int fdevent_freebsd_kqueue_init(fdevents
*ev
) {
224 log_error_write(ev
->srv
, __FILE__
, __LINE__
, "S",
225 "kqueue not available, try to set server.event-handler = \"poll\" or \"select\"");