Beispiel #1
0
static void iv_fd_kqueue_poll(struct iv_state *st,
			      struct iv_list_head *active,
			      const struct timespec *abs)
{
	struct kevent kev[UPLOAD_BATCH];
	int num;
	struct kevent batch[st->numfds ? 2 * st->numfds : 1];
	struct timespec rel;
	int ret;
	int run_events;
	int i;

	iv_fd_kqueue_upload(st, kev, UPLOAD_BATCH, &num);

	ret = kevent(st->u.kqueue.kqueue_fd, kev, num,
		     batch, ARRAY_SIZE(batch), to_relative(st, &rel, abs));

	__iv_invalidate_now(st);

	if (ret < 0) {
		if (errno == EINTR)
			return;

		iv_fatal("iv_fd_kqueue_poll: got error %d[%s]", errno,
			 strerror(errno));
	}

	run_events = 0;
	for (i = 0; i < ret; i++) {
		struct iv_fd_ *fd;

		if (batch[i].filter == EVFILT_USER) {
			run_events = 1;
			continue;
		}

		if (batch[i].flags & EV_ERROR) {
			int err = batch[i].data;
			int fd = batch[i].ident;

			iv_fatal("iv_fd_kqueue_poll: got error %d[%s] "
				 "polling fd %d", err, strerror(err), fd);
		}

		fd = (void *)batch[i].udata;
		if (batch[i].filter == EVFILT_READ) {
			iv_fd_make_ready(active, fd, MASKIN);
		} else if (batch[i].filter == EVFILT_WRITE) {
			iv_fd_make_ready(active, fd, MASKOUT);
		} else {
			iv_fatal("iv_fd_kqueue_poll: got message from "
				 "filter %d", batch[i].filter);
		}
	}

	if (run_events)
		iv_event_run_pending_events();
}
Beispiel #2
0
static int iv_fd_port_poll(struct iv_state *st,
                           struct iv_list_head *active,
                           const struct timespec *abs)
{
    struct timespec _rel;
    struct timespec *rel;
    int run_timers;
    int run_events;
    unsigned int nget;
    port_event_t pe[PORTEV_NUM];
    int ret;
    int i;

    iv_fd_port_upload(st);

    rel = to_relative(st, &_rel, abs);

    run_timers = 0;
    if (rel != NULL && rel->tv_sec == 0 && rel->tv_nsec == 0)
        run_timers = 1;

    run_events = 0;

poll_more:
    nget = 1;

    /*
     * If we get EINTR from port_getn(), no events are returned
     * and nget will not have been updated, but if we get ETIME,
     * events may be returned, and nget will be set to the number
     * of events in the array, and we need to process those
     * events as usual.
     */
    ret = port_getn(st->u.port.port_fd, pe, PORTEV_NUM, &nget, rel);

    __iv_invalidate_now(st);

    if (ret < 0 && errno != ETIME) {
        if (errno == EINTR)
            return run_timers;

        iv_fatal("iv_fd_port_poll: got error %d[%s]", errno,
                 strerror(errno));
    }

    if (ret < 0 && errno == ETIME)
        run_timers = 1;

    for (i = 0; i < nget; i++) {
        int source;

        source = pe[i].portev_source;
        if (source == PORT_SOURCE_FD) {
            int revents;
            struct iv_fd_ *fd;

            revents = pe[i].portev_events;
            fd = pe[i].portev_user;

            if (revents & (POLLIN | POLLERR | POLLHUP))
                iv_fd_make_ready(active, fd, MASKIN);

            if (revents & (POLLOUT | POLLERR | POLLHUP))
                iv_fd_make_ready(active, fd, MASKOUT);

            if (revents & (POLLERR | POLLHUP))
                iv_fd_make_ready(active, fd, MASKERR);

            fd->registered_bands = 0;

            iv_list_del_init(&fd->list_notify);
            if (fd->wanted_bands) {
                iv_list_add_tail(&fd->list_notify,
                                 &st->u.port.notify);
            }
        } else if (source == PORT_SOURCE_TIMER) {
            run_timers = 1;
        } else if (source == PORT_SOURCE_USER) {
            run_events = 1;
        } else {
            iv_fatal("iv_fd_port_poll: received event "
                     "from unknown source %d", source);
        }
    }

    if (nget == PORTEV_NUM) {
        run_timers = 1;
        rel = &_rel;
        rel->tv_sec = 0;
        rel->tv_nsec = 0;
        goto poll_more;
    }

    if (run_events)
        iv_event_run_pending_events();

    return run_timers;
}