5 #if defined(HAVE_KQUEUE)
11 #if defined(HOST_WIN32)
12 /* We assume that kqueue is not available on windows */
16 #define KQUEUE_NEVENTS 128
18 static gint kqueue_fd
;
19 static struct kevent
*kqueue_events
;
22 KQUEUE_INIT_FD (gint fd
, gint events
, gint flags
)
25 EV_SET (&event
, fd
, events
, flags
, 0, 0, 0);
26 return kevent (kqueue_fd
, &event
, 1, NULL
, 0, NULL
);
30 kqueue_init (gint wakeup_pipe_fd
)
32 kqueue_fd
= kqueue ();
33 if (kqueue_fd
== -1) {
34 g_error ("kqueue_init: kqueue () failed, error (%d) %s", errno
, g_strerror (errno
));
38 if (KQUEUE_INIT_FD (wakeup_pipe_fd
, EVFILT_READ
, EV_ADD
| EV_ENABLE
) == -1) {
39 g_error ("kqueue_init: kevent () failed, error (%d) %s", errno
, g_strerror (errno
));
44 kqueue_events
= g_new0 (struct kevent
, KQUEUE_NEVENTS
);
50 kqueue_can_register_fd (int fd
)
56 kqueue_register_fd (gint fd
, gint events
, gboolean is_new
)
58 if (events
& EVENT_IN
) {
59 if (KQUEUE_INIT_FD (fd
, EVFILT_READ
, EV_ADD
| EV_ENABLE
) == -1)
60 g_error ("kqueue_register_fd: kevent(read,enable) failed, error (%d) %s", errno
, g_strerror (errno
));
62 if (KQUEUE_INIT_FD (fd
, EVFILT_READ
, EV_ADD
| EV_DISABLE
) == -1)
63 g_error ("kqueue_register_fd: kevent(read,disable) failed, error (%d) %s", errno
, g_strerror (errno
));
65 if (events
& EVENT_OUT
) {
66 if (KQUEUE_INIT_FD (fd
, EVFILT_WRITE
, EV_ADD
| EV_ENABLE
) == -1)
67 g_error ("kqueue_register_fd: kevent(write,enable) failed, error (%d) %s", errno
, g_strerror (errno
));
69 if (KQUEUE_INIT_FD (fd
, EVFILT_WRITE
, EV_ADD
| EV_DISABLE
) == -1)
70 g_error ("kqueue_register_fd: kevent(write,disable) failed, error (%d) %s", errno
, g_strerror (errno
));
76 kqueue_remove_fd (gint fd
)
78 /* FIXME: a race between closing and adding operation in the Socket managed code trigger a ENOENT error */
79 if (KQUEUE_INIT_FD (fd
, EVFILT_READ
, EV_DELETE
) == -1)
80 g_error ("kqueue_register_fd: kevent(read,delete) failed, error (%d) %s", errno
, g_strerror (errno
));
81 if (KQUEUE_INIT_FD (fd
, EVFILT_WRITE
, EV_DELETE
) == -1)
82 g_error ("kqueue_register_fd: kevent(write,delete) failed, error (%d) %s", errno
, g_strerror (errno
));
86 kqueue_event_wait (void (*callback
) (gint fd
, gint events
, gpointer user_data
), gpointer user_data
)
90 memset (kqueue_events
, 0, sizeof (struct kevent
) * KQUEUE_NEVENTS
);
92 mono_thread_info_set_flags (MONO_THREAD_INFO_FLAGS_NO_GC
);
95 ready
= kevent (kqueue_fd
, NULL
, 0, kqueue_events
, KQUEUE_NEVENTS
, NULL
);
98 mono_thread_info_set_flags (MONO_THREAD_INFO_FLAGS_NONE
);
106 g_error ("kqueue_event_wait: kevent () failed, error (%d) %s", errno
, g_strerror (errno
));
114 for (i
= 0; i
< ready
; ++i
) {
117 fd
= kqueue_events
[i
].ident
;
118 if (kqueue_events
[i
].filter
== EVFILT_READ
|| (kqueue_events
[i
].flags
& EV_ERROR
) != 0)
120 if (kqueue_events
[i
].filter
== EVFILT_WRITE
|| (kqueue_events
[i
].flags
& EV_ERROR
) != 0)
123 callback (fd
, events
, user_data
);
129 static ThreadPoolIOBackend backend_kqueue
= {
131 .can_register_fd
= kqueue_can_register_fd
,
132 .register_fd
= kqueue_register_fd
,
133 .remove_fd
= kqueue_remove_fd
,
134 .event_wait
= kqueue_event_wait
,