Example #1
0
static int
evport_del(struct event_base *base, int fd, short old, short events, void *p)
{
	struct evport_data *evpd = base->evbase;
	struct fd_info *fdi;
	int i;
	int associated = 1;
	(void)p;

	check_evportop(evpd);

	if (evpd->ed_nevents < fd) {
		return (-1);
	}

	for (i = 0; i < EVENTS_PER_GETN; ++i) {
		if (evpd->ed_pending[i] == fd) {
			associated = 0;
			break;
		}
	}

	fdi = &evpd->ed_fds[fd];
	if (events & EV_READ)
		fdi->fdi_what &= ~EV_READ;
	if (events & EV_WRITE)
		fdi->fdi_what &= ~EV_WRITE;

	if (associated) {
		if (!FDI_HAS_EVENTS(fdi) &&
		    port_dissociate(evpd->ed_port, PORT_SOURCE_FD, fd) == -1) {
			/*
			 * Ignore EBADFD error the fd could have been closed
			 * before event_del() was called.
			 */
			if (errno != EBADFD) {
				event_warn("port_dissociate");
				return (-1);
			}
		} else {
			if (FDI_HAS_EVENTS(fdi)) {
				return (reassociate(evpd, fdi, fd));
			}
		}
	} else {
		if ((fdi->fdi_what & (EV_READ|EV_WRITE)) == 0) {
			evpd->ed_pending[i] = -1;
		}
	}
	return 0;
}
Example #2
0
static int
evport_del(struct event_base *base, int fd, short old, short events, void *p)
{
	struct evport_data *evpd = base->evbase;
	struct fd_info *fdi = p;
	int associated = ! fdi->pending_idx_plus_1;

	check_evportop(evpd);

	fdi->fdi_what &= ~(events &(EV_READ|EV_WRITE));

	if (associated) {
		if (!FDI_HAS_EVENTS(fdi) &&
		    port_dissociate(evpd->ed_port, PORT_SOURCE_FD, fd) == -1) {
			/*
			 * Ignore EBADFD error the fd could have been closed
			 * before event_del() was called.
			 */
			if (errno != EBADFD) {
				event_warn("port_dissociate");
				return (-1);
			}
		} else {
			if (FDI_HAS_EVENTS(fdi)) {
				return (reassociate(evpd, fdi, fd));
			}
		}
	} else {
		if ((fdi->fdi_what & (EV_READ|EV_WRITE)) == 0) {
			const int i = fdi->pending_idx_plus_1 - 1;
			EVUTIL_ASSERT(evpd->ed_pending[i] == fd);
			evpd->ed_pending[i] = -1;
			fdi->pending_idx_plus_1 = 0;
		}
	}
	return 0;
}
Example #3
0
static int
evport_dispatch(struct event_base *base, struct timeval *tv)
{
	int i, res;
	struct evport_data *epdp = base->evbase;
	port_event_t pevtlist[EVENTS_PER_GETN];

	/*
	 * port_getn will block until it has at least nevents events. It will
	 * also return how many it's given us (which may be more than we asked
	 * for, as long as it's less than our maximum (EVENTS_PER_GETN)) in
	 * nevents.
	 */
	int nevents = 1;

	/*
	 * We have to convert a struct timeval to a struct timespec
	 * (only difference is nanoseconds vs. microseconds). If no time-based
	 * events are active, we should wait for I/O (and tv == NULL).
	 */
	struct timespec ts;
	struct timespec *ts_p = NULL;
	if (tv != NULL) {
		ts.tv_sec = tv->tv_sec;
		ts.tv_nsec = tv->tv_usec * 1000;
		ts_p = &ts;
	}

	/*
	 * Before doing anything else, we need to reassociate the events we hit
	 * last time which need reassociation. See comment at the end of the
	 * loop below.
	 */
	for (i = 0; i < EVENTS_PER_GETN; ++i) {
		struct fd_info *fdi = NULL;
		if (epdp->ed_pending[i] != -1) {
			fdi = &(epdp->ed_fds[epdp->ed_pending[i]]);
		}

		if (fdi != NULL && FDI_HAS_EVENTS(fdi)) {
			int fd = epdp->ed_pending[i];
			reassociate(epdp, fdi, fd);
			epdp->ed_pending[i] = -1;
		}
	}

	EVBASE_RELEASE_LOCK(base, th_base_lock);

	res = port_getn(epdp->ed_port, pevtlist, EVENTS_PER_GETN,
	    (unsigned int *) &nevents, ts_p);

	EVBASE_ACQUIRE_LOCK(base, th_base_lock);

	if (res == -1) {
		if (errno == EINTR || errno == EAGAIN) {
			return (0);
		} else if (errno == ETIME) {
			if (nevents == 0)
				return (0);
		} else {
			event_warn("port_getn");
			return (-1);
		}
	}

	event_debug(("%s: port_getn reports %d events", __func__, nevents));

	for (i = 0; i < nevents; ++i) {
		struct fd_info *fdi;
		port_event_t *pevt = &pevtlist[i];
		int fd = (int) pevt->portev_object;

		check_evportop(epdp);
		check_event(pevt);
		epdp->ed_pending[i] = fd;

		/*
		 * Figure out what kind of event it was
		 * (because we have to pass this to the callback)
		 */
		res = 0;
		if (pevt->portev_events & (POLLERR|POLLHUP)) {
			res = EV_READ | EV_WRITE;
		} else {
			if (pevt->portev_events & POLLIN)
				res |= EV_READ;
			if (pevt->portev_events & POLLOUT)
				res |= EV_WRITE;
		}

		/*
		 * Check for the error situations or a hangup situation
		 */
		if (pevt->portev_events & (POLLERR|POLLHUP|POLLNVAL))
			res |= EV_READ|EV_WRITE;

		EVUTIL_ASSERT(epdp->ed_nevents > fd);
		fdi = &(epdp->ed_fds[fd]);

		evmap_io_active(base, fd, res);
	} /* end of all events gotten */

	check_evportop(epdp);

	return (0);
}
Example #4
0
static int
evport_del (void *arg, struct event *ev)
{

  struct evport_data *evpd = arg;

  struct fd_info *fdi;
  int i;
  int associated = 1;

  check_evportop (evpd);

  /*
   * Delegate, if it's not ours to handle
   */

  if (ev->ev_events & EV_SIGNAL)
    {
      return (evsignal_del (ev) );
    }

  if (evpd->ed_nevents < ev->ev_fd)
    {
      return (-1);
    }

  for (i = 0; i < EVENTS_PER_GETN; ++i)
    {
      if (evpd->ed_pending[i] == ev->ev_fd)
        {
          associated = 0;
          break;
        }
    }

  fdi = &evpd->ed_fds[ev->ev_fd];

  if (ev->ev_events & EV_READ)
    fdi->fdi_revt = NULL;

  if (ev->ev_events & EV_WRITE)
    fdi->fdi_wevt = NULL;

  if (associated)
    {
      if (!FDI_HAS_EVENTS (fdi) &&
              port_dissociate (evpd->ed_port, PORT_SOURCE_FD,
                               ev->ev_fd) == -1)
        {
          /*
           * Ignre EBADFD error the fd could have been closed
           * before event_del() was called.
           */
          if (errno != EBADFD)
            {
              event_warn ("port_dissociate");
              return (-1);
            }
        }

      else
        {
          if (FDI_HAS_EVENTS (fdi) )
            {
              return (reassociate (evpd, fdi, ev->ev_fd) );
            }
        }
    }

  else
    {
      if (fdi->fdi_revt == NULL && fdi->fdi_wevt == NULL)
        {
          evpd->ed_pending[i] = -1;
        }
    }

  return 0;
}
Example #5
0
static int
evport_dispatch (struct event_base *base, void *arg, struct timeval *tv)
{
  int i, res;

  struct evport_data *epdp = arg;
  port_event_t pevtlist[EVENTS_PER_GETN];

  /*
   * port_getn will block until it has at least nevents events. It will
   * also return how many it's given us (which may be more than we asked
   * for, as long as it's less than our maximum (EVENTS_PER_GETN)) in
   * nevents.
   */
  int nevents = 1;

  /*
   * We have to convert a struct timeval to a struct timespec
   * (only difference is nanoseconds vs. microseconds). If no time-based
   * events are active, we should wait for I/O (and tv == NULL).
   */

  struct timespec ts;

  struct timespec *ts_p = NULL;

  if (tv != NULL)
    {
      ts.tv_sec = tv->tv_sec;
      ts.tv_nsec = tv->tv_usec * 1000;
      ts_p = &ts;
    }

  /*
   * Before doing anything else, we need to reassociate the events we hit
   * last time which need reassociation. See comment at the end of the
   * loop below.
   */

  for (i = 0; i < EVENTS_PER_GETN; ++i)
    {

      struct fd_info *fdi = NULL;

      if (epdp->ed_pending[i] != -1)
        {
          fdi = & (epdp->ed_fds[epdp->ed_pending[i]]);
        }

      if (fdi != NULL && FDI_HAS_EVENTS (fdi) )
        {
          int fd = FDI_HAS_READ (fdi) ? fdi->fdi_revt->ev_fd :
                   fdi->fdi_wevt->ev_fd;
          reassociate (epdp, fdi, fd);
          epdp->ed_pending[i] = -1;
        }
    }

  if ( (res = port_getn (epdp->ed_port, pevtlist, EVENTS_PER_GETN,
                         (unsigned int *) & nevents, ts_p) ) == -1)
    {
      if (errno == EINTR || errno == EAGAIN)
        {
          evsignal_process (base);
          return (0);
        }

      else if (errno == ETIME)
        {
          if (nevents == 0)
            return (0);
        }

      else
        {
          event_warn ("port_getn");
          return (-1);
        }
    }

  else if (base->sig.evsignal_caught)
    {
      evsignal_process (base);
    }

  event_debug ( ("%s: port_getn reports %d events", __func__, nevents) );

  for (i = 0; i < nevents; ++i)
    {

      struct event *ev;

      struct fd_info *fdi;
      port_event_t *pevt = &pevtlist[i];
      int fd = (int) pevt->portev_object;

      check_evportop (epdp);
      check_event (pevt);
      epdp->ed_pending[i] = fd;

      /*
       * Figure out what kind of event it was
       * (because we have to pass this to the callback)
       */
      res = 0;

      if (pevt->portev_events & POLLIN)
        res |= EV_READ;

      if (pevt->portev_events & POLLOUT)
        res |= EV_WRITE;

      assert (epdp->ed_nevents > fd);

      fdi = & (epdp->ed_fds[fd]);

      /*
       * We now check for each of the possible events (READ
       * or WRITE).  Then, we activate the event (which will
       * cause its callback to be executed).
       */

      if ( (res & EV_READ) && ( (ev = fdi->fdi_revt) != NULL) )
        {
          event_active (ev, res, 1);
        }

      if ( (res & EV_WRITE) && ( (ev = fdi->fdi_wevt) != NULL) )
        {
          event_active (ev, res, 1);
        }
    } /* end of all events gotten */

  check_evportop (epdp);

  return (0);
}