Ejemplo n.º 1
0
// Poll epoll and aio and handle any events. If can_sleep is true
// and no aio events are expected, epoll will block.
static void do_poll(bool can_sleep, struct timespec next_wakeup)
{
	struct epoll_event epoll_events[MAX_EVENTS];
#if ENABLE_AIO
	struct io_event aio_events[MAX_EVENTS];

	// We need to be careful to not let either aio or epoll events
	// starve the other. We do this by always doing nonblocking polls
	// of aio and only having epoll block if we aren't expecting aio
	// events. When both types of events are coming in, we switch
	// between processing the two types.
	// Poll for aio events. Don't block.
	int aio_cnt = io_getevents(state.aio_ctx, 0, MAX_EVENTS,
	                           aio_events, NULL);
	if (aio_cnt < 0) { fail2(1, -aio_cnt, "io_getevents"); }
	bool expect_aio = aio_cnt == MAX_EVENTS;
	for (int i = 0; i < aio_cnt; i++) {
		handle_aio_event(&aio_events[i]);
	}
#else
#define expect_aio 0
#endif

	// If we aren't expecting aio, block indefinitely, otherwise
	// just poll.
	int epoll_timeout = expect_aio || !can_sleep ? 0 :
		compute_timeout(next_wakeup);
	int epoll_cnt = epoll_wait(state.epoll_fd, epoll_events,
	                           MAX_EVENTS, epoll_timeout);
	for (int i = 0; i < epoll_cnt; i++) {
#if ENABLE_AIO
		if (epoll_events[i].data.ptr == state.aio_dummy_event) {
			uint64_t eventfd_val;
			if (read(state.aio_eventfd, &eventfd_val,
			         sizeof(eventfd_val)) < 0)
				fail(1, "eventfd read");
		} else
#endif
		{
			handle_epoll_event(&epoll_events[i]);
		}
	}
}
Ejemplo n.º 2
0
int epoll_wait_call::get_current_events()
{
	if (m_epfd_info->m_ready_fds.empty()) {
		return m_n_all_ready_fds;
	}

	vector<socket_fd_api *> socket_fd_vec;
	lock();
	int i,r,w;
	i = r = w = m_n_all_ready_fds;
	socket_fd_api *p_socket_object;
	epoll_fd_rec fd_rec;
	ep_ready_fd_map_t::iterator iter = m_epfd_info->m_ready_fds.begin();
	while (iter != m_epfd_info->m_ready_fds.end() && i < m_maxevents) {
		ep_ready_fd_map_t::iterator iter_cpy = iter; // for protection needs
		++iter;
		p_socket_object = fd_collection_get_sockfd(iter_cpy->first);
		if (p_socket_object)
		{
			if(!m_epfd_info->get_fd_rec_by_fd(iter_cpy->first, fd_rec)) continue;

			m_events[i].events = 0; //initialize

			bool got_event = false;

			//epoll_wait will always wait for EPOLLERR and EPOLLHUP; it is not necessary to set it in events.
			uint32_t mutual_events = iter_cpy->second & (fd_rec.events | EPOLLERR | EPOLLHUP);

			//EPOLLHUP & EPOLLOUT are mutually exclusive. see poll man pages. epoll adapt poll behavior.
			if ((mutual_events & EPOLLHUP) &&  (mutual_events & EPOLLOUT)) {
				mutual_events &= ~EPOLLOUT;
			}

			if (mutual_events & EPOLLIN) {
				if (handle_epoll_event(p_socket_object->is_readable(NULL), EPOLLIN, iter_cpy, fd_rec, i)) {
					r++;
					got_event = true;
				}
				mutual_events &= ~EPOLLIN;
			}

			if (mutual_events & EPOLLOUT) {
				if (handle_epoll_event(p_socket_object->is_writeable(), EPOLLOUT, iter_cpy, fd_rec, i)) {
					w++;
					got_event = true;
				}
				mutual_events &= ~EPOLLOUT;
			}

			if (mutual_events) {
				if (handle_epoll_event(true, mutual_events, iter_cpy, fd_rec, i)) {
					got_event = true;
				}
			}

			if (got_event) {
				socket_fd_vec.push_back(p_socket_object);
				++i;
			}
		}
		else {
			m_epfd_info->m_ready_fds.erase(iter_cpy);
		}
	}

	int ready_rfds = r - m_n_all_ready_fds; //MNY: not only rfds, different counters for read/write ?
	int ready_wfds = w - m_n_all_ready_fds;
	m_n_ready_rfds += ready_rfds;
	m_n_ready_wfds += ready_wfds;
	m_p_stats->n_iomux_rx_ready += ready_rfds;

	unlock();

	/*
	 * for checking ring migration we need a socket context.
	 * in epoll we separate the rings from the sockets, so only here we access the sockets.
	 * therefore, it is most convenient to check it here.
	 * we need to move the ring migration to the epfd, going over the registered sockets,
	 * when polling the rings was not fruitful.
	 * this  will be more similar to the behavior of select/poll.
	 * see RM task 212058
	 */
	for (unsigned int j = 0; j < socket_fd_vec.size(); j++) {
		socket_fd_vec[j]->consider_rings_migration();
	}

	return (i);
}