示例#1
0
void io_loop_handler_run_internal(struct ioloop *ioloop)
{
	struct ioloop_handler_context *ctx = ioloop->handler_context;
	struct epoll_event *events;
	const struct epoll_event *event;
	struct io_list *list;
	struct io_file *io;
	struct timeval tv;
	unsigned int events_count;
	int msecs, ret, i, j;
	bool call;

        /* get the time left for next timeout task */
	msecs = io_loop_get_wait_time(ioloop, &tv);

	events = array_get_modifiable(&ctx->events, &events_count);
	if (ioloop->io_files != NULL && events_count > ctx->deleted_count) {
		ret = epoll_wait(ctx->epfd, events, events_count, msecs);
		if (ret < 0 && errno != EINTR)
			i_fatal("epoll_wait(): %m");
	} else {
		/* no I/Os, but we should have some timeouts.
		   just wait for them. */
		i_assert(msecs >= 0);
		usleep(msecs*1000);
		ret = 0;
	}

	/* execute timeout handlers */
        io_loop_handle_timeouts(ioloop);

	if (!ioloop->running)
		return;

	for (i = 0; i < ret; i++) {
		/* io_loop_handle_add() may cause events array reallocation,
		   so we have use array_idx() */
		event = array_idx(&ctx->events, i);
		list = event->data.ptr;

		for (j = 0; j < IOLOOP_IOLIST_IOS_PER_FD; j++) {
			io = list->ios[j];
			if (io == NULL)
				continue;

			call = FALSE;
			if ((event->events & (EPOLLHUP | EPOLLERR)) != 0)
				call = TRUE;
			else if ((io->io.condition & IO_READ) != 0)
				call = (event->events & EPOLLIN) != 0;
			else if ((io->io.condition & IO_WRITE) != 0)
				call = (event->events & EPOLLOUT) != 0;
			else if ((io->io.condition & IO_ERROR) != 0)
				call = (event->events & IO_EPOLL_ERROR) != 0;

			if (call)
				io_loop_call_io(&io->io);
		}
	}
}
示例#2
0
void io_loop_handler_run_internal(struct ioloop *ioloop)
{
	struct ioloop_handler_context *ctx = ioloop->handler_context;
	struct kevent *events;
	const struct kevent *event;
	struct timeval tv;
	struct timespec ts;
	struct io_file *io;
	unsigned int events_count;
	int ret, i, msecs;

	/* get the time left for next timeout task */
	msecs = io_loop_get_wait_time(ioloop, &tv);
	ts.tv_sec = tv.tv_sec;
	ts.tv_nsec = tv.tv_usec * 1000;

	/* wait for events */
	events = array_get_modifiable(&ctx->events, &events_count);

	if (events_count > 0) {
		ret = kevent (ctx->kq, NULL, 0, events, events_count, &ts);
		if (ret < 0 && errno != EINTR)
			i_panic("kevent() failed: %m");
	} else {
		if (msecs < 0)
			i_panic("BUG: No IOs or timeouts set. Not waiting for infinity.");
		usleep(msecs * 1000);
		ret = 0;
	}

	/* reference all IOs */
	for (i = 0; i < ret; i++) {
		io = (void *)events[i].udata;
		i_assert(io->refcount > 0);
		io->refcount++;
	}

	/* execute timeout handlers */
	io_loop_handle_timeouts(ioloop);

	for (i = 0; i < ret; i++) {
		/* io_loop_handle_add() may cause events array reallocation,
		   so we have use array_idx() */
		event = array_idx(&ctx->events, i);
		io = (void *)event->udata;

		/* callback is NULL if io_remove() was already called */
		if (io->io.callback != NULL)
			io_loop_call_io(&io->io);

		i_assert(io->refcount > 0);
		if (--io->refcount == 0)
			i_free(io);
	}
}
void io_loop_handler_run(struct ioloop *ioloop)
{
	struct ioloop_handler_context *ctx = ioloop->handler_context;
	struct timeval tv;
	struct io_file *io;
	int ret;

	/* get the time left for next timeout task */
	io_loop_get_wait_time(ioloop, &tv);

	memcpy(&ctx->tmp_read_fds, &ctx->read_fds, sizeof(fd_set));
	memcpy(&ctx->tmp_write_fds, &ctx->write_fds, sizeof(fd_set));
	memcpy(&ctx->tmp_except_fds, &ctx->except_fds, sizeof(fd_set));

	ret = select(ctx->highest_fd + 1, &ctx->tmp_read_fds,
		     &ctx->tmp_write_fds, &ctx->tmp_except_fds, &tv);
	if (ret < 0 && errno != EINTR)
		i_warning("select() : %m");

	/* execute timeout handlers */
        io_loop_handle_timeouts(ioloop);

	if (ret <= 0 || !ioloop->running) {
                /* no I/O events */
		return;
	}

	io = ioloop->io_files;
	for (; io != NULL && ret > 0; io = ioloop->next_io_file) {
                ioloop->next_io_file = io->next;

		if (io_check_condition(ctx, io->fd, io->io.condition)) {
			ret--;
			io_loop_call_io(&io->io);
		}
	}
}