Example #1
0
void zmq::select_t::loop ()
{
    while (!stopping) {

        //  Execute any due timers.
        int timeout = (int) execute_timers ();

        //  Intialise the pollsets.
        memcpy (&readfds, &source_set_in, sizeof source_set_in);
        memcpy (&writefds, &source_set_out, sizeof source_set_out);
        memcpy (&exceptfds, &source_set_err, sizeof source_set_err);

        //  Wait for events.
        struct timeval tv = {(long) (timeout / 1000),
            (long) (timeout % 1000 * 1000)};
#ifdef ZMQ_HAVE_WINDOWS
        int rc = select (0, &readfds, &writefds, &exceptfds,
            timeout ? &tv : NULL);
        wsa_assert (rc != SOCKET_ERROR);
#else
        int rc = select (maxfd + 1, &readfds, &writefds, &exceptfds,
            timeout ? &tv : NULL);
        if (rc == -1) {
            errno_assert (errno == EINTR);
            continue;
        }
#endif

        //  If there are no events (i.e. it's a timeout) there's no point
        //  in checking the pollset.
        if (rc == 0)
            continue;

        for (fd_set_t::size_type i = 0; i < fds.size (); i ++) {
            if (fds [i].fd == retired_fd)
                continue;
            if (FD_ISSET (fds [i].fd, &exceptfds))
                fds [i].events->in_event ();
            if (fds [i].fd == retired_fd)
                continue;
            if (FD_ISSET (fds [i].fd, &writefds))
                fds [i].events->out_event ();
            if (fds [i].fd == retired_fd)
                continue;
            if (FD_ISSET (fds [i].fd, &readfds))
                fds [i].events->in_event ();
        }

        //  Destroy retired event sources.
        if (retired) {
            fds.erase (std::remove_if (fds.begin (), fds.end (),
                zmq::select_t::is_retired_fd), fds.end ());
            retired = false;
        }
    }
}
Example #2
0
void zmq::poll_t::loop ()
{
    while (true) {
        //  Execute any due timers.
        int timeout = (int) execute_timers ();

        cleanup_retired ();

        if (pollset.empty ()) {
            zmq_assert (get_load () == 0);

            if (timeout == 0)
                break;

            // TODO sleep for timeout
            continue;
        }

        //  Wait for events.
        int rc = poll (&pollset[0], static_cast<nfds_t> (pollset.size ()),
                       timeout ? timeout : -1);
#ifdef ZMQ_HAVE_WINDOWS
        wsa_assert (rc != SOCKET_ERROR);
#else
        if (rc == -1) {
            errno_assert (errno == EINTR);
            continue;
        }
#endif

        //  If there are no events (i.e. it's a timeout) there's no point
        //  in checking the pollset.
        if (rc == 0)
            continue;

        for (pollset_t::size_type i = 0; i != pollset.size (); i++) {
            zmq_assert (!(pollset[i].revents & POLLNVAL));
            if (pollset[i].fd == retired_fd)
                continue;
            if (pollset[i].revents & (POLLERR | POLLHUP))
                fd_table[pollset[i].fd].events->in_event ();
            if (pollset[i].fd == retired_fd)
                continue;
            if (pollset[i].revents & POLLOUT)
                fd_table[pollset[i].fd].events->out_event ();
            if (pollset[i].fd == retired_fd)
                continue;
            if (pollset[i].revents & POLLIN)
                fd_table[pollset[i].fd].events->in_event ();
        }
    }
}
Example #3
0
void zmq::poll_t::loop ()
{
    while (!stopping) {

        //  Execute any due timers.
        int timeout = (int) execute_timers ();

        //  Wait for events.
        int rc = poll (&pollset [0], pollset.size (), timeout ? timeout : -1);
        if (rc == -1 && errno == EINTR)
            continue;
        errno_assert (rc != -1);


        //  If there are no events (i.e. it's a timeout) there's no point
        //  in checking the pollset.
        if (rc == 0)
            continue;

        for (pollset_t::size_type i = 0; i != pollset.size (); i++) {

            zmq_assert (!(pollset [i].revents & POLLNVAL));
            if (pollset [i].fd == retired_fd)
               continue;
            if (pollset [i].revents & (POLLERR | POLLHUP))
                fd_table [pollset [i].fd].events->in_event ();
            if (pollset [i].fd == retired_fd)
               continue;
            if (pollset [i].revents & POLLOUT)
                fd_table [pollset [i].fd].events->out_event ();
            if (pollset [i].fd == retired_fd)
               continue;
            if (pollset [i].revents & POLLIN)
                fd_table [pollset [i].fd].events->in_event ();
        }

        //  Clean up the pollset and update the fd_table accordingly.
        if (retired) {
            pollset_t::size_type i = 0;
            while (i < pollset.size ()) {
                if (pollset [i].fd == retired_fd)
                    pollset.erase (pollset.begin () + i);
                else {
                    fd_table [pollset [i].fd].index = i;
                    i ++;
                }
            }
            retired = false;
        }
    }
}
Example #4
0
void zmq::kqueue_t::loop ()
{
    while (!stopping) {

        //  Execute any due timers.
        int timeout = (int) execute_timers ();

        //  Wait for events.
        struct kevent ev_buf [max_io_events];
        timespec ts = {timeout / 1000, (timeout % 1000) * 1000000};
        int n = kevent (kqueue_fd, NULL, 0, &ev_buf [0], max_io_events,
            timeout ? &ts: NULL);
#ifdef HAVE_FORK
        if (unlikely(pid != getpid())) {
            //printf("zmq::kqueue_t::loop aborting on forked child %d\n", (int)getpid());
            // simply exit the loop in a forked process.
            return;
        }
#endif
        if (n == -1) {
            errno_assert (errno == EINTR);
            continue;
        }

        for (int i = 0; i < n; i ++) {
            poll_entry_t *pe = (poll_entry_t*) ev_buf [i].udata;

            if (pe->fd == retired_fd)
                continue;
            if (ev_buf [i].flags & EV_EOF)
                pe->reactor->in_event ();
            if (pe->fd == retired_fd)
                continue;
            if (ev_buf [i].filter == EVFILT_WRITE)
                pe->reactor->out_event ();
            if (pe->fd == retired_fd)
                continue;
            if (ev_buf [i].filter == EVFILT_READ)
                pe->reactor->in_event ();
        }

        //  Destroy retired event sources.
        for (retired_t::iterator it = retired.begin (); it != retired.end ();
              ++it)
            delete *it;
        retired.clear ();
    }
}
Example #5
0
void zmq::devpoll_t::loop ()
{
    while (!stopping) {

        struct pollfd ev_buf [max_io_events];
        struct dvpoll poll_req;

        for (pending_list_t::size_type i = 0; i < pending_list.size (); i ++)
            fd_table [pending_list [i]].accepted = true;
        pending_list.clear ();

        //  Execute any due timers.
        int timeout = (int) execute_timers ();

        //  Wait for events.
        //  On Solaris, we can retrieve no more then (OPEN_MAX - 1) events.
        poll_req.dp_fds = &ev_buf [0];
#if defined ZMQ_HAVE_SOLARIS
        poll_req.dp_nfds = std::min ((int) max_io_events, OPEN_MAX - 1);
#else
        poll_req.dp_nfds = max_io_events;
#endif
        poll_req.dp_timeout = timeout ? timeout : -1;
        int n = ioctl (devpoll_fd, DP_POLL, &poll_req);
        if (n == -1 && errno == EINTR)
            continue;
        errno_assert (n != -1);

        for (int i = 0; i < n; i ++) {

            fd_entry_t *fd_ptr = &fd_table [ev_buf [i].fd];
            if (!fd_ptr->valid || !fd_ptr->accepted)
                continue;
            if (ev_buf [i].revents & (POLLERR | POLLHUP))
                fd_ptr->reactor->in_event ();
            if (!fd_ptr->valid || !fd_ptr->accepted)
                continue;
            if (ev_buf [i].revents & POLLOUT)
                fd_ptr->reactor->out_event ();
            if (!fd_ptr->valid || !fd_ptr->accepted)
                continue;
            if (ev_buf [i].revents & POLLIN)
                fd_ptr->reactor->in_event ();
        }
    }
}
Example #6
0
void zmq::pollset_t::loop ()
{
    struct pollfd polldata_array[max_io_events];

    while (!stopping) {

        //  Execute any due timers.
        int timeout = (int) execute_timers ();

        //  Wait for events.
        int n = pollset_poll(pollset_fd, polldata_array, max_io_events, 
            timeout ? timeout : -1);
        if (n == -1) {
            errno_assert (errno == EINTR);
            continue;
        }

        for (int i = 0; i < n; i ++) {
            poll_entry_t *pe = fd_table [polldata_array [i].fd];
            if (!pe)
                continue;

            if (pe->fd == retired_fd)
                continue;
            if (polldata_array [i].revents & (POLLERR | POLLHUP))
                pe->events->in_event ();
            if (pe->fd == retired_fd)
               continue;
            if (polldata_array [i].revents & POLLOUT)
                pe->events->out_event ();
            if (pe->fd == retired_fd)
                continue;
            if (polldata_array [i].revents & POLLIN)
                pe->events->in_event ();
        }

        //  Destroy retired event sources.
        for (retired_t::iterator it = retired.begin (); it != retired.end ();
              ++it)
            LIBZMQ_DELETE(*it);
        retired.clear ();
    }
}
Example #7
0
void zmq::epoll_t::loop ()
{
    epoll_event ev_buf [max_io_events];

    while (!stopping) {

        //  Execute any due timers.
        int timeout = (int) execute_timers ();

        //  Wait for events.
        int n = epoll_wait (epoll_fd, &ev_buf [0], max_io_events,
            timeout ? timeout : -1);
        if (n == -1) {
            errno_assert (errno == EINTR);
            continue;
        }

        for (int i = 0; i < n; i ++) {
            poll_entry_t *pe = ((poll_entry_t*) ev_buf [i].data.ptr);

            if (pe->fd == retired_fd)
                continue;
            if (ev_buf [i].events & (EPOLLERR | EPOLLHUP))
                pe->events->in_event ();
            if (pe->fd == retired_fd)
               continue;
            if (ev_buf [i].events & EPOLLOUT)
                pe->events->out_event ();
            if (pe->fd == retired_fd)
                continue;
            if (ev_buf [i].events & EPOLLIN)
                pe->events->in_event ();
        }

        //  Destroy retired event sources.
        retired_sync.lock ();
        for (retired_t::iterator it = retired.begin (); it != retired.end (); ++it) {
            LIBZMQ_DELETE(*it);
        }
        retired.clear ();
        retired_sync.unlock ();
    }
}
Example #8
0
void zmq::kqueue_t::loop ()
{
    while (!stopping) {

        //  Execute any due timers.
        int timeout = (int) execute_timers ();

        //  Wait for events.
        struct kevent ev_buf [max_io_events];
        timespec ts = {timeout / 1000, (timeout % 1000) * 1000000};
        int n = kevent (kqueue_fd, NULL, 0, &ev_buf [0], max_io_events,
            timeout ? &ts: NULL);
        if (n == -1) {
            errno_assert (errno == EINTR);
            continue;
        }

        for (int i = 0; i < n; i ++) {
            poll_entry_t *pe = (poll_entry_t*) ev_buf [i].udata;

            if (pe->fd == retired_fd)
                continue;
            if (ev_buf [i].flags & EV_EOF)
                pe->reactor->in_event ();
            if (pe->fd == retired_fd)
                continue;
            if (ev_buf [i].filter == EVFILT_WRITE)
                pe->reactor->out_event ();
            if (pe->fd == retired_fd)
                continue;
            if (ev_buf [i].filter == EVFILT_READ)
                pe->reactor->in_event ();
        }

        //  Destroy retired event sources.
        for (retired_t::iterator it = retired.begin (); it != retired.end ();
              ++it)
            delete *it;
        retired.clear ();
    }
}
Example #9
0
void device_scheduler::timeslice()
{
	bool call_debugger = ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0);

	// build the execution list if we don't have one yet
	if (m_execute_list == NULL)
		rebuild_execute_list();

	// execute timers
	execute_timers();

	// loop until we hit the next timer
	while (m_basetime < m_timer_list->m_expire)
	{
		// by default, assume our target is the end of the next quantum
		attotime target = m_basetime + attotime(0, m_quantum_list.first()->m_actual);

		// however, if the next timer is going to fire before then, override
		if (m_timer_list->m_expire < target)
			target = m_timer_list->m_expire;

		LOG(("------------------\n"));
		LOG(("cpu_timeslice: target = %s\n", target.as_string()));

		// do we have pending suspension changes?
		if (m_suspend_changes_pending)
			apply_suspend_changes();

		// loop over non-suspended CPUs
		for (device_execute_interface *exec = m_execute_list; exec != NULL; exec = exec->m_nextexec)
		{
			// only process if our target is later than the CPU's current time (coarse check)
			if (target.seconds >= exec->m_localtime.seconds)
			{
				// compute how many attoseconds to execute this CPU
				attoseconds_t delta = target.attoseconds - exec->m_localtime.attoseconds;
				if (delta < 0 && target.seconds > exec->m_localtime.seconds)
					delta += ATTOSECONDS_PER_SECOND;
				assert(delta == (target - exec->m_localtime).as_attoseconds());

				// if we have enough for at least 1 cycle, do the math
				if (delta >= exec->m_attoseconds_per_cycle)
				{
					// compute how many cycles we want to execute
					int ran = exec->m_cycles_running = divu_64x32((UINT64)delta >> exec->m_divshift, exec->m_divisor);
					LOG(("  cpu '%s': %d cycles\n", exec->device().tag(), exec->m_cycles_running));

					// if we're not suspended, actually execute
					if (exec->m_suspend == 0)
					{
						g_profiler.start(exec->m_profiler);

						// note that this global variable cycles_stolen can be modified
						// via the call to cpu_execute
						exec->m_cycles_stolen = 0;
						m_executing_device = exec;
						*exec->m_icountptr = exec->m_cycles_running;
						if (!call_debugger)
							exec->run();
						else
						{
							debugger_start_cpu_hook(&exec->device(), target);
							exec->run();
							debugger_stop_cpu_hook(&exec->device());
						}

						// adjust for any cycles we took back
						assert(ran >= *exec->m_icountptr);
						ran -= *exec->m_icountptr;
						assert(ran >= exec->m_cycles_stolen);
						ran -= exec->m_cycles_stolen;
						g_profiler.stop();
					}

					// account for these cycles
					exec->m_totalcycles += ran;

					// update the local time for this CPU
					attotime delta = attotime(0, exec->m_attoseconds_per_cycle * ran);
					assert(delta >= attotime::zero);
					exec->m_localtime += delta;
					LOG(("         %d ran, %d total, time = %s\n", ran, (INT32)exec->m_totalcycles, exec->m_localtime.as_string()));

					// if the new local CPU time is less than our target, move the target up, but not before the base
					if (exec->m_localtime < target)
					{
						assert(exec->m_localtime < target);
						target = max(exec->m_localtime, m_basetime);
						LOG(("         (new target)\n"));
					}
				}
			}
		}
Example #10
0
void zmq::select_t::loop ()
{
    while (!stopping) {
        //  Execute any due timers.
        int timeout = (int) execute_timers ();

#if defined ZMQ_HAVE_OSX
        struct timeval tv = { (long) (timeout / 1000), timeout % 1000 * 1000 };
#else
        struct timeval tv = { (long) (timeout / 1000), (long) (timeout % 1000 * 1000) };
#endif

        int rc = 0;

#if defined ZMQ_HAVE_WINDOWS
        /*
            On Windows select does not allow to mix descriptors from different
            service providers. It seems to work for AF_INET and AF_INET6,
            but fails for AF_INET and VMCI. The workaround is to use
            WSAEventSelect and WSAWaitForMultipleEvents to wait, then use
            select to find out what actually changed. WSAWaitForMultipleEvents
            cannot be used alone, because it does not support more than 64 events
            which is not enough.

            To reduce unncessary overhead, WSA is only used when there are more
            than one family. Moreover, AF_INET and AF_INET6 are considered the same
            family because Windows seems to handle them properly.
            See get_fd_family for details.
        */
        wsa_events_t wsa_events;

        //  If there is just one family, there is no reason to use WSA events.
        if (family_entries.size () > 1) {
            for (family_entries_t::iterator family_entry_it = family_entries.begin ();
                  family_entry_it != family_entries.end (); ++family_entry_it) {
                family_entry_t& family_entry = family_entry_it->second;

                for (fd_entries_t::iterator fd_entry_it = family_entry.fd_entries.begin ();
                      fd_entry_it != family_entry.fd_entries.end (); ++fd_entry_it) {
                    fd_t fd = fd_entry_it->fd;

                    //  http://stackoverflow.com/q/35043420/188530
                    if (FD_ISSET (fd, &family_entry.fds_set.read) &&
                          FD_ISSET (fd, &family_entry.fds_set.write))
                        rc = WSAEventSelect (fd, wsa_events.events [3],
                            FD_READ | FD_ACCEPT | FD_CLOSE | FD_WRITE | FD_CONNECT | FD_OOB);
                    else if (FD_ISSET (fd, &family_entry.fds_set.read))
                        rc = WSAEventSelect (fd, wsa_events.events [0],
                            FD_READ | FD_ACCEPT | FD_CLOSE | FD_OOB);
                    else if (FD_ISSET (fd, &family_entry.fds_set.write))
                        rc = WSAEventSelect (fd, wsa_events.events [1],
                            FD_WRITE | FD_CONNECT | FD_OOB);
                    else if (FD_ISSET (fd, &family_entry.fds_set.error))
                        rc = WSAEventSelect (fd, wsa_events.events [2],
                            FD_OOB);
                    else
                        rc = 0;

                    wsa_assert (rc != SOCKET_ERROR);
                }
            }
        }
#endif

#if defined ZMQ_HAVE_WINDOWS
        if (family_entries.size () > 1) {
            rc = WSAWaitForMultipleEvents (4, wsa_events.events, FALSE,
                timeout ? timeout : INFINITE, FALSE);
            wsa_assert (rc != (int)WSA_WAIT_FAILED);
            zmq_assert (rc != WSA_WAIT_IO_COMPLETION);

            if (rc == WSA_WAIT_TIMEOUT)
                continue;
        }

        for (current_family_entry_it = family_entries.begin ();
              current_family_entry_it != family_entries.end (); ++current_family_entry_it) {
            family_entry_t& family_entry = current_family_entry_it->second;

            //  select will fail when run with empty sets.
            if (family_entry.fd_entries.empty ())
                continue;

            fds_set_t local_fds_set = family_entry.fds_set;

            if (family_entries.size () > 1) {
                //  There is no reason to wait again after WSAWaitForMultipleEvents.
                //  Simply collect what is ready.
                struct timeval tv_nodelay = { 0, 0 };
                rc = select (0, &local_fds_set.read, &local_fds_set.write, &local_fds_set.error,
                    &tv_nodelay);
            }
            else
                rc = select (0, &local_fds_set.read, &local_fds_set.write,
                    &local_fds_set.error, timeout > 0 ? &tv : NULL);

            wsa_assert (rc != SOCKET_ERROR);

            //  Size is cached to avoid iteration through recently added descriptors.
            for (fd_entries_t::size_type i = 0, size = family_entry.fd_entries.size (); i < size && rc > 0; ++i) {
                fd_entry_t fd_entry = family_entry.fd_entries [i];

                if (fd_entry.fd == retired_fd)
                    continue;

                if (FD_ISSET (fd_entry.fd, &local_fds_set.read)) {
                    fd_entry.events->in_event ();
                    --rc;
                }

                if (fd_entry.fd == retired_fd || rc == 0)
                    continue;

                if (FD_ISSET (fd_entry.fd, &local_fds_set.write)) {
                    fd_entry.events->out_event ();
                    --rc;
                }

                if (fd_entry.fd == retired_fd || rc == 0)
                    continue;

                if (FD_ISSET (fd_entry.fd, &local_fds_set.error)) {
                    fd_entry.events->in_event ();
                    --rc;
                }
            }

            if (family_entry.retired) {
                family_entry.retired = false;
                family_entry.fd_entries.erase (std::remove_if (family_entry.fd_entries.begin (),
                    family_entry.fd_entries.end (), is_retired_fd), family_entry.fd_entries.end ());
            }
        }
#else
        fds_set_t local_fds_set = fds_set;
        rc = select (maxfd + 1, &local_fds_set.read, &local_fds_set.write,
            &local_fds_set.error, timeout ? &tv : NULL);

        if (rc == -1) {
            errno_assert (errno == EINTR);
            continue;
        }

        //  Size is cached to avoid iteration through just added descriptors.
        for (fd_entries_t::size_type i = 0, size = fd_entries.size (); i < size && rc > 0; ++i) {
            fd_entry_t& fd_entry = fd_entries [i];

            if (fd_entry.fd == retired_fd)
                continue;

            if (FD_ISSET (fd_entry.fd, &local_fds_set.read)) {
                fd_entry.events->in_event ();
                --rc;
            }

            if (fd_entry.fd == retired_fd || rc == 0)
                continue;

            if (FD_ISSET (fd_entry.fd, &local_fds_set.write)) {
                fd_entry.events->out_event ();
                --rc;
            }

            if (fd_entry.fd == retired_fd || rc == 0)
                continue;

            if (FD_ISSET (fd_entry.fd, &local_fds_set.error)) {
                fd_entry.events->in_event ();
                --rc;
            }
        }

        if (retired) {
            retired = false;
            fd_entries.erase (std::remove_if (fd_entries.begin (), fd_entries.end (),
                is_retired_fd), fd_entries.end ());
        }
#endif
    }
}