3 #include "fdevent_impl.h"
12 #ifdef FDEVENT_USE_FREEBSD_KQUEUE
14 # include <sys/event.h>
15 # include <sys/time.h>
18 static void fdevent_freebsd_kqueue_free(fdevents
*ev
) {
23 static int fdevent_freebsd_kqueue_event_del(fdevents
*ev
, fdnode
*fdn
) {
25 struct timespec ts
= {0, 0};
28 int oevents
= fdn
->events
;
30 if (oevents
& FDEVENT_IN
) {
31 EV_SET(&kev
[n
], fd
, EVFILT_READ
, EV_DELETE
, 0, 0, fdn
);
34 if (oevents
& FDEVENT_OUT
) {
35 EV_SET(&kev
[n
], fd
, EVFILT_WRITE
, EV_DELETE
, 0, 0, fdn
);
39 return (0 != n
) ? kevent(ev
->kq_fd
, kev
, n
, NULL
, 0, &ts
) : 0;
40 /*(kevent() changelist still processed on EINTR,
41 * but EINTR should not be received since 0 == nevents)*/
44 static int fdevent_freebsd_kqueue_event_set(fdevents
*ev
, fdnode
*fdn
, int events
) {
46 struct timespec ts
= {0, 0};
47 int fd
= fdn
->fde_ndx
= fdn
->fd
;
49 int oevents
= fdn
->events
;
50 int addevents
= events
& ~oevents
;
51 int delevents
= ~events
& oevents
;
53 if (addevents
& FDEVENT_IN
) {
54 EV_SET(&kev
[n
], fd
, EVFILT_READ
, EV_ADD
, 0, 0, fdn
);
56 } else if (delevents
& FDEVENT_IN
) {
57 EV_SET(&kev
[n
], fd
, EVFILT_READ
, EV_DELETE
, 0, 0, fdn
);
60 if (addevents
& FDEVENT_OUT
) {
61 EV_SET(&kev
[n
], fd
, EVFILT_WRITE
, EV_ADD
, 0, 0, fdn
);
63 } else if (delevents
& FDEVENT_OUT
) {
64 EV_SET(&kev
[n
], fd
, EVFILT_WRITE
, EV_DELETE
, 0, 0, fdn
);
68 return (0 != n
) ? kevent(ev
->kq_fd
, kev
, n
, NULL
, 0, &ts
) : 0;
69 /*(kevent() changelist still processed on EINTR,
70 * but EINTR should not be received since 0 == nevents)*/
73 static int fdevent_freebsd_kqueue_poll(fdevents
* const ev
, int timeout_ms
) {
74 server
* const srv
= ev
->srv
;
78 ts
.tv_sec
= timeout_ms
/ 1000;
79 ts
.tv_nsec
= (timeout_ms
% 1000) * 1000000;
81 n
= kevent(ev
->kq_fd
, NULL
, 0, ev
->kq_results
, ev
->maxfds
, &ts
);
83 for (int i
= 0; i
< n
; ++i
) {
84 fdnode
* const fdn
= (fdnode
*)ev
->kq_results
[i
].udata
;
85 int filt
= ev
->kq_results
[i
].filter
;
86 int e
= ev
->kq_results
[i
].flags
;
87 if ((fdevent_handler
)NULL
!= fdn
->handler
) {
88 int revents
= (filt
== EVFILT_READ
) ? FDEVENT_IN
: FDEVENT_OUT
;
90 revents
|= (filt
== EVFILT_READ
? FDEVENT_RDHUP
: FDEVENT_HUP
);
92 revents
|= FDEVENT_ERR
;
93 (*fdn
->handler
)(srv
, fdn
->ctx
, revents
);
100 static int fdevent_freebsd_kqueue_reset(fdevents
*ev
) {
101 return (-1 != (ev
->kq_fd
= kqueue())) ? 0 : -1;
105 int fdevent_freebsd_kqueue_init(fdevents
*ev
) {
106 ev
->type
= FDEVENT_HANDLER_FREEBSD_KQUEUE
;
107 ev
->event_set
= fdevent_freebsd_kqueue_event_set
;
108 ev
->event_del
= fdevent_freebsd_kqueue_event_del
;
109 ev
->poll
= fdevent_freebsd_kqueue_poll
;
110 ev
->reset
= fdevent_freebsd_kqueue_reset
;
111 ev
->free
= fdevent_freebsd_kqueue_free
;
113 ev
->kq_results
= calloc(ev
->maxfds
, sizeof(*ev
->kq_results
));
114 force_assert(NULL
!= ev
->kq_results
);