Esempio n. 1
0
/* Iterate through all the event lists (such as connect_events, read_events,
 * timer_events, etc) and take action for those that have completed (due to
 * timeout, i/o, etc) */
void iterate_through_event_lists(mspool *nsp, int evcount) {
  int n;
  struct kqueue_engine_info *kinfo = (struct kqueue_engine_info *)nsp->engine_data;
  gh_list_elem *current, *next, *last, *timer_last;
  msevent *nse;
  msiod *nsi;

  /* Clear it -- We will find the next event as we go through the list */
  nsp->next_ev.tv_sec = 0;

  last = GH_LIST_LAST_ELEM(&nsp->active_iods);
  timer_last = GH_LIST_LAST_ELEM(&nsp->timer_events);

  for (n = 0; n < evcount; n++) {
    struct kevent *kev = &kinfo->events[n];

    nsi = (msiod *)kev->udata;

    /* process all the pending events for this IOD */
    process_iod_events(nsp, nsi, get_evmask(nsi, kev));

    IOD_PROPSET(nsi, IOD_PROCESSED);
  }

  current = GH_LIST_FIRST_ELEM(&nsp->active_iods);

  /* cull timeouts amongst the non active IODs */
  while (current != NULL && GH_LIST_ELEM_PREV(current) != last) {
    msiod *nsi = (msiod *)GH_LIST_ELEM_DATA(current);

    if (IOD_PROPGET(nsi, IOD_PROCESSED))
      IOD_PROPCLR(nsi, IOD_PROCESSED);
    else if (nsi->state != NSIOD_STATE_DELETED && nsi->events_pending)
      process_iod_events(nsp, nsi, EV_NONE);

    next = GH_LIST_ELEM_NEXT(current);
    if (nsi->state == NSIOD_STATE_DELETED) {
      gh_list_remove_elem(&nsp->active_iods, current);
      gh_list_prepend(&nsp->free_iods, nsi);
    }
    current = next;
  }

  /* iterate through timers */
  for (current = GH_LIST_FIRST_ELEM(&nsp->timer_events);
       current != NULL && GH_LIST_ELEM_PREV(current) != timer_last; current = next) {

    nse = (msevent *)GH_LIST_ELEM_DATA(current);

    process_event(nsp, &nsp->timer_events, nse, EV_NONE);

    next = GH_LIST_ELEM_NEXT(current);
    if (nse->event_done)
      gh_list_remove_elem(&nsp->timer_events, current);
  }
}
Esempio n. 2
0
/* Iterate through all the event lists (such as connect_events, read_events,
 * timer_events, etc) and take action for those that have completed (due to
 * timeout, i/o, etc) */
void iterate_through_event_lists(mspool *nsp) {
  gh_list_elem *current, *next, *last, *timer_last;

  /* Clear it -- We will find the next event as we go through the list */
  nsp->next_ev.tv_sec = 0;

  last = GH_LIST_LAST_ELEM(&nsp->active_iods);
  timer_last = GH_LIST_LAST_ELEM(&nsp->timer_events);

  for (current = GH_LIST_FIRST_ELEM(&nsp->active_iods);
       current != NULL && GH_LIST_ELEM_PREV(current) != last; current = next) {
    msiod *nsi = (msiod *)GH_LIST_ELEM_DATA(current);
    
    if (nsi->state != NSIOD_STATE_DELETED && nsi->events_pending)
      process_iod_events(nsp, nsi, get_evmask(nsp, nsi));

    next = GH_LIST_ELEM_NEXT(current);
    if (nsi->state == NSIOD_STATE_DELETED) {
      gh_list_remove_elem(&nsp->active_iods, current);
      gh_list_prepend(&nsp->free_iods, nsi);
    }
  }

  /* iterate through timers */
  for (current = GH_LIST_FIRST_ELEM(&nsp->timer_events);
       current != NULL && GH_LIST_ELEM_PREV(current) != timer_last; current = next) {

    msevent *nse = (msevent *)GH_LIST_ELEM_DATA(current);

    process_event(nsp, &nsp->timer_events, nse, EV_NONE);

    next = GH_LIST_ELEM_NEXT(current);
    if (nse->event_done)
      gh_list_remove_elem(&nsp->timer_events, current);
  }
}
Esempio n. 3
0
void process_iod_events(mspool *nsp, msiod *nsi, int ev) {
  int i = 0;
  /* store addresses of the pointers to the first elements of each kind instead
   * of storing the values, as a connect can add a read for instance */
  gh_list_elem **start_elems[] = {
    &nsi->first_connect,
    &nsi->first_read,
    &nsi->first_write,
#if HAVE_PCAP
    &nsi->first_pcap_read,
#endif
    NULL
  };
  gh_list *evlists[] = {
    &nsi->nsp->connect_events,
    &nsi->nsp->read_events,
    &nsi->nsp->write_events,
#if HAVE_PCAP
    &nsi->nsp->pcap_read_events,
#endif
    NULL
  };

  /* We keep the events separate because we want to handle them in the
   * order: connect => read => write => timer for several reasons:
   *
   *  1) Makes sure we have gone through all the net i/o events before
   *     a timer expires (would be a shame to timeout after the data was
   *     available but before we delivered the events
   *
   *  2) The connect() results often lead to a read or write that can be
   *     processed in the same cycle.  In the same way, read() often
   *     leads to write().
   */
  for (i = 0; start_elems[i] != NULL; i++) {
    gh_list_elem *current, *next, *last;

    /* for each list, get the last event and don't look past it as an event could
     * add another event in the same list and so on... */
    last = GH_LIST_LAST_ELEM(evlists[i]);

    for (current = *start_elems[i]; current != NULL
        && GH_LIST_ELEM_PREV(current) != last; current = next) {
      msevent *nse = (msevent *)GH_LIST_ELEM_DATA(current);

      /* events are grouped by IOD. Break if we're done with the events for the
       * current IOD */
      if (nse->iod != nsi)
        break;

      process_event(nsp, evlists[i], nse, ev);
      next = GH_LIST_ELEM_NEXT(current);

      if (nse->event_done) {
        /* event is done, remove it from the event list and update IOD pointers
         * to the first events of each kind */
        update_first_events(nse);
        gh_list_remove_elem(evlists[i], current);
      }
    }
  }
}
Esempio n. 4
0
/* Iterate through all the event lists (such as connect_events, read_events,
 * timer_events, etc) and take action for those that have completed (due to
 * timeout, i/o, etc) */
void iterate_through_event_lists(mspool *nsp, int evcount) {
  int n, initial_iod_count;
  struct epoll_engine_info *einfo = (struct epoll_engine_info *)nsp->engine_data;
  gh_list_elem *current, *next, *last, *timer_last, *last_active = NULL;
  msevent *nse;
  msiod *nsi;

  /* Clear it -- We will find the next event as we go through the list */
  nsp->next_ev.tv_sec = 0;

  last = GH_LIST_LAST_ELEM(&nsp->active_iods);
  timer_last = GH_LIST_LAST_ELEM(&nsp->timer_events);

  initial_iod_count = GH_LIST_COUNT(&nsp->active_iods);

  for (n = 0; n < evcount; n++) {
    nsi = (msiod *)einfo->events[n].data.ptr;
    assert(nsi);

    if (nsi->entry_in_nsp_active_iods == last)
      last = GH_LIST_ELEM_PREV(nsi->entry_in_nsp_active_iods);

    /* process all the pending events for this IOD */
    process_iod_events(nsp, nsi, get_evmask(einfo, n));

    if (nsi->state != NSIOD_STATE_DELETED) {
      gh_list_move_front(&nsp->active_iods, nsi->entry_in_nsp_active_iods);
      if (last_active == NULL)
        last_active = nsi->entry_in_nsp_active_iods;
    } else {
      gh_list_remove_elem(&nsp->active_iods, nsi->entry_in_nsp_active_iods);
      gh_list_prepend(&nsp->free_iods, nsi);
    }
  }

  if (evcount < initial_iod_count) {
    /* some IODs had no active events and need to be processed */
    if (!last_active)
      /* either no IOD had events or all IODs were deleted after event processing */
      current = GH_LIST_FIRST_ELEM(&nsp->active_iods);
    else
      /* IODs that had active events were pushed to the beginning of the list, start after them */
      current = GH_LIST_ELEM_NEXT(last_active);
  } else {
    /* all the IODs had events and were therefore processed */
    current = NULL;
  }

  /* cull timeouts amongst the non active IODs */
  while (current != NULL && GH_LIST_ELEM_PREV(current) != last) {
    nsi = (msiod *)GH_LIST_ELEM_DATA(current);

    if (nsi->state != NSIOD_STATE_DELETED && nsi->events_pending)
      process_iod_events(nsp, nsi, EV_NONE);

    next = GH_LIST_ELEM_NEXT(current);
    if (nsi->state == NSIOD_STATE_DELETED) {
      gh_list_remove_elem(&nsp->active_iods, current);
      gh_list_prepend(&nsp->free_iods, nsi);
    }
    current = next;
  }

  /* iterate through timers */
  for (current = GH_LIST_FIRST_ELEM(&nsp->timer_events);
      current != NULL && GH_LIST_ELEM_PREV(current) != timer_last; current = next) {

    nse = (msevent *)GH_LIST_ELEM_DATA(current);

    process_event(nsp, &nsp->timer_events, nse, EV_NONE);

    next = GH_LIST_ELEM_NEXT(current);
    if (nse->event_done)
      gh_list_remove_elem(&nsp->timer_events, current);
  }
}