Exemplo n.º 1
0
/*
 * Update events with the current events object.
 */
static int update_current_events(struct lttng_poll_event *events)
{
	int ret;
	struct compat_poll_event_array *current, *wait;

	assert(events);

	current = &events->current;
	wait = &events->wait;

	wait->nb_fd = current->nb_fd;
	if (current->alloc_size != wait->alloc_size) {
		ret = resize_poll_event(wait, current->alloc_size);
		if (ret < 0) {
			goto error;
		}
	}
	memcpy(wait->events, current->events,
			current->nb_fd * sizeof(*current->events));

	/* Update is done. */
	events->need_update = 0;

	return 0;

error:
	return -1;
}
Exemplo n.º 2
0
/*
 * Wait on epoll set. This is a blocking call of timeout value.
 */
int compat_epoll_wait(struct lttng_poll_event *events, int timeout)
{
	int ret;
	uint32_t new_size;

	if (events == NULL || events->events == NULL) {
		ERR("Wrong arguments in compat_epoll_wait");
		goto error;
	}

	if (events->nb_fd == 0) {
		errno = EINVAL;
		return -1;
	}

	/*
	 * Resize if needed before waiting. We could either expand the array or
	 * shrink it down. It's important to note that after this step, we are
	 * ensured that the events argument of the epoll_wait call will be large
	 * enough to hold every possible returned events.
	 */
	new_size = 1U << utils_get_count_order_u32(events->nb_fd);
	if (new_size != events->alloc_size && new_size >= events->init_size) {
		ret = resize_poll_event(events, new_size);
		if (ret < 0) {
			/* ENOMEM problem at this point. */
			goto error;
		}
	}

	do {
		ret = epoll_wait(events->epfd, events->events, events->nb_fd, timeout);
	} while (ret == -1 && errno == EINTR);
	if (ret < 0) {
		/* At this point, every error is fatal */
		PERROR("epoll_wait");
		goto error;
	}

	/*
	 * Since the returned events are set sequentially in the "events" structure
	 * we only need to return the epoll_wait value and iterate over it.
	 */
	return ret;

error:
	return -1;
}
Exemplo n.º 3
0
/*
 * Add fd to pollfd data structure with requested events.
 */
int compat_poll_add(struct lttng_poll_event *events, int fd,
		uint32_t req_events)
{
	int new_size, ret, i;
	struct compat_poll_event_array *current;

	if (events == NULL || events->current.events == NULL || fd < 0) {
		ERR("Bad compat poll add arguments");
		goto error;
	}

	current = &events->current;

	/* Check if fd we are trying to add is already there. */
	for (i = 0; i < current->nb_fd; i++) {
		if (current->events[i].fd == fd) {
			errno = EEXIST;
			goto error;
		}
	}

	/* Resize array if needed. */
	new_size = 1U << utils_get_count_order_u32(current->nb_fd + 1);
	if (new_size != current->alloc_size && new_size >= current->init_size) {
		ret = resize_poll_event(current, new_size);
		if (ret < 0) {
			goto error;
		}
	}

	current->events[current->nb_fd].fd = fd;
	current->events[current->nb_fd].events = req_events;
	current->nb_fd++;
	events->need_update = 1;

	DBG("fd %d of %d added to pollfd", fd, current->nb_fd);

	return 0;

error:
	return -1;
}
Exemplo n.º 4
0
/*
 * Remove a fd from the pollfd structure.
 */
int compat_poll_del(struct lttng_poll_event *events, int fd)
{
	int new_size, i, count = 0, ret;
	struct compat_poll_event_array *current;

	if (events == NULL || events->current.events == NULL || fd < 0) {
		ERR("Wrong arguments for poll del");
		goto error;
	}

	/* Ease our life a bit. */
	current = &events->current;

	for (i = 0; i < current->nb_fd; i++) {
		/* Don't put back the fd we want to delete */
		if (current->events[i].fd != fd) {
			current->events[count].fd = current->events[i].fd;
			current->events[count].events = current->events[i].events;
			count++;
		}
	}
	/* No fd duplicate should be ever added into array. */
	assert(current->nb_fd - 1 == count);
	current->nb_fd = count;

	/* Resize array if needed. */
	new_size = 1U << utils_get_count_order_u32(current->nb_fd);
	if (new_size != current->alloc_size && new_size >= current->init_size) {
		ret = resize_poll_event(current, new_size);
		if (ret < 0) {
			goto error;
		}
	}

	events->need_update = 1;

	return 0;

error:
	return -1;
}