* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*
- * $Id: kqueue.c 25038 2008-01-23 16:03:08Z androsyn $
+ * $Id: kqueue.c 26092 2008-09-19 15:13:52Z androsyn $
*/
#include <libratbox_config.h>
#include <sys/event.h>
-#define KE_LENGTH 128
-
/* jlemon goofed up and didn't add EV_SET until fbsd 4.3 */
#ifndef EV_SET
static struct timespec zero_timespec;
static struct kevent *kqlst; /* kevent buffer */
+static struct kevent *kqout; /* kevent output buffer */
static int kqmax; /* max structs to buffer */
static int kqoff; /* offset into the buffer */
int
-rb_setup_fd_kqueue(rb_fde_t * F)
+rb_setup_fd_kqueue(rb_fde_t *F)
{
return 0;
}
static void
-kq_update_events(rb_fde_t * F, short filter, PF * handler)
+kq_update_events(rb_fde_t *F, short filter, PF * handler)
{
PF *cur_handler;
int kep_flags;
kep_flags = EV_DELETE;
}
- EV_SET(kep, (uintptr_t) F->fd, filter, kep_flags, 0, 0, (void *) F);
+ EV_SET(kep, (uintptr_t)F->fd, filter, kep_flags, 0, 0, (void *)F);
if(++kqoff == kqmax)
{
- int ret;
-
- ret = kevent(kq, kqlst, kqoff, NULL, 0, &zero_timespec);
- /* jdc -- someone needs to do error checking... */
- if(ret == -1)
+ int ret, i;
+
+ /* Add them one at a time, because there may be
+ * already closed fds in it. The kernel will try
+ * to report invalid fds in the output; if there
+ * is no space, it silently stops processing the
+ * array at that point. We cannot give output space
+ * because that would also return events we cannot
+ * process at this point.
+ */
+ for(i = 0; i < kqoff; i++)
{
- rb_lib_log("kq_update_events(): kevent(): %s", strerror(errno));
- return;
+ ret = kevent(kq, kqlst + i, 1, NULL, 0, &zero_timespec);
+ /* jdc -- someone needs to do error checking... */
+ /* EBADF is normal here -- jilles */
+ if(ret == -1 && errno != EBADF)
+ rb_lib_log("kq_update_events(): kevent(): %s",
+ strerror(errno));
}
kqoff = 0;
}
}
kqmax = getdtablesize();
kqlst = rb_malloc(sizeof(struct kevent) * kqmax);
+ kqout = rb_malloc(sizeof(struct kevent) * kqmax);
rb_open(kq, RB_FD_UNKNOWN, "kqueue fd");
zero_timespec.tv_sec = 0;
zero_timespec.tv_nsec = 0;
* and deregister interest in a pending IO state for a given FD.
*/
void
-rb_setselect_kqueue(rb_fde_t * F, unsigned int type, PF * handler, void *client_data)
+rb_setselect_kqueue(rb_fde_t *F, unsigned int type, PF * handler, void *client_data)
{
lrb_assert(IsFDOpen(F));
rb_select_kqueue(long delay)
{
int num, i;
- static struct kevent ke[KE_LENGTH];
struct timespec poll_time;
struct timespec *pt;
rb_fde_t *F;
- if(delay < 0) {
+ if(delay < 0)
+ {
pt = NULL;
}
- else {
+ else
+ {
pt = &poll_time;
poll_time.tv_sec = delay / 1000;
poll_time.tv_nsec = (delay % 1000) * 1000000;
}
- for (;;)
+ for(;;)
{
- num = kevent(kq, kqlst, kqoff, ke, KE_LENGTH, pt);
+ num = kevent(kq, kqlst, kqoff, kqout, kqmax, pt);
kqoff = 0;
if(num >= 0)
if(num == 0)
return RB_OK; /* No error.. */
- for (i = 0; i < num; i++)
+ for(i = 0; i < num; i++)
{
PF *hdl = NULL;
- if(ke[i].flags & EV_ERROR)
+ if(kqout[i].flags & EV_ERROR)
{
- errno = ke[i].data;
+ errno = kqout[i].data;
/* XXX error == bad! -- adrian */
continue; /* XXX! */
}
- switch (ke[i].filter)
+ switch (kqout[i].filter)
{
case EVFILT_READ:
- F = ke[i].udata;
+ F = kqout[i].udata;
if((hdl = F->read_handler) != NULL)
{
F->read_handler = NULL;
break;
case EVFILT_WRITE:
- F = ke[i].udata;
+ F = kqout[i].udata;
if((hdl = F->write_handler) != NULL)
{
F->write_handler = NULL;
break;
#if defined(EVFILT_TIMER)
case EVFILT_TIMER:
- rb_run_event(ke[i].udata);
+ rb_run_event(kqout[i].udata);
break;
#endif
default:
}
return RB_OK;
}
+
+#if defined(KQUEUE_SCHED_EVENT)
static int can_do_event = 0;
int
rb_kqueue_supports_event(void)
ts.tv_nsec = 1000;
- EV_SET(&kv, (uintptr_t) 0x0, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 1, 0);
+ EV_SET(&kv, (uintptr_t)0x0, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 1, 0);
if(kevent(xkq, &kv, 1, NULL, 0, NULL) < 0)
{
can_do_event = -1;
kep_flags = EV_ADD;
if(event->frequency == 0)
kep_flags |= EV_ONESHOT;
- EV_SET(&kev, (uintptr_t) event, EVFILT_TIMER, kep_flags, 0, when * 1000, event);
+ EV_SET(&kev, (uintptr_t)event, EVFILT_TIMER, kep_flags, 0, when * 1000, event);
if(kevent(kq, &kev, 1, NULL, 0, NULL) < 0)
- return 0;
+ return 0;
return 1;
}
rb_kqueue_unsched_event(struct ev_entry *event)
{
struct kevent kev;
- EV_SET(&kev, (uintptr_t) event, EVFILT_TIMER, EV_DELETE, 0, 0, event);
+ EV_SET(&kev, (uintptr_t)event, EVFILT_TIMER, EV_DELETE, 0, 0, event);
kevent(kq, &kev, 1, NULL, 0, NULL);
}
{
return;
}
+#endif /* KQUEUE_SCHED_EVENT */
#else /* kqueue not supported */
int
}
void
-rb_setselect_kqueue(rb_fde_t * F, unsigned int type, PF * handler, void *client_data)
+rb_setselect_kqueue(rb_fde_t *F, unsigned int type, PF * handler, void *client_data)
{
errno = ENOSYS;
return;
}
int
-rb_setup_fd_kqueue(rb_fde_t * F)
+rb_setup_fd_kqueue(rb_fde_t *F)
{
errno = ENOSYS;
return -1;