diff options
| -rw-r--r-- | Changes | 7 | ||||
| -rw-r--r-- | ev.c | 35 | ||||
| -rw-r--r-- | ev_epoll.c | 24 | ||||
| -rw-r--r-- | ev_poll.c | 2 | 
4 files changed, 38 insertions, 30 deletions
| @@ -1,6 +1,13 @@  Revision history for libev, a high-performance and full-featured event loop.  WISH? monotonic clocks times/GetTickCount for coarse corrections? + +	- further optimise away the EPOLL_CTL_ADD/MOD combo in the epoll +          backend by assuming the kernel event mask hasn't changed if +          ADD fails with EEXIST. +        - use memset to initialise most arrays now and do away with the +          init functions. +  3.45 Tue Oct 21 21:59:26 CEST 2008  	- disable inotify usage on linux <2.6.25, as it is broken            (reported by Yoann Vandoorselaere). @@ -451,6 +451,8 @@ typedef struct    WL head;    unsigned char events;    unsigned char reify; +  unsigned char emask; /* the epoll backend stores the actual kernel mask in here */ +  unsigned char unused; /* currently unused padding */  #if EV_SELECT_IS_WINSOCKET    SOCKET handle;  #endif @@ -613,6 +615,9 @@ array_realloc (int elem, void *base, int *cur, int cnt)    return ev_realloc (base, elem * *cur);  } +#define array_init_zero(base,count)	\ +  memset ((void *)(base), 0, sizeof (*(base)) * (count)) +  #define array_needsize(type,base,cur,cnt,init)			\    if (expect_false ((cnt) > (cur)))				\      {								\ @@ -665,19 +670,6 @@ queue_events (EV_P_ W *events, int eventcnt, int type)  /*****************************************************************************/ -void inline_size -anfds_init (ANFD *base, int count) -{ -  while (count--) -    { -      base->head   = 0; -      base->events = EV_NONE; -      base->reify  = 0; - -      ++base; -    } -} -  void inline_speed  fd_event (EV_P_ int fd, int revents)  { @@ -977,18 +969,6 @@ static int signalmax;  static EV_ATOMIC_T gotsig; -void inline_size -signals_init (ANSIG *base, int count) -{ -  while (count--) -    { -      base->head   = 0; -      base->gotsig = 0; - -      ++base; -    } -} -  /*****************************************************************************/  void inline_speed @@ -2141,11 +2121,12 @@ ev_io_start (EV_P_ ev_io *w)      return;    assert (("ev_io_start called with negative fd", fd >= 0)); +  assert (("ev_io start called with illegal event mask", !(w->events & ~(EV_IOFDSET | EV_READ | EV_WRITE))));    EV_FREQUENT_CHECK;    ev_start (EV_A_ (W)w, 1); -  array_needsize (ANFD, anfds, anfdmax, fd + 1, anfds_init); +  array_needsize (ANFD, anfds, anfdmax, fd + 1, array_init_zero);    wlist_add (&anfds[fd].head, (WL)w);    fd_change (EV_A_ fd, w->events & EV_IOFDSET | 1); @@ -2347,7 +2328,7 @@ ev_signal_start (EV_P_ ev_signal *w)      sigprocmask (SIG_SETMASK, &full, &prev);  #endif -    array_needsize (ANSIG, signals, signalmax, w->signum, signals_init); +    array_needsize (ANSIG, signals, signalmax, w->signum, array_init_zero);  #ifndef _WIN32      sigprocmask (SIG_SETMASK, &prev, 0); @@ -57,20 +57,34 @@  #include <sys/epoll.h> +void inline_size +unsigned_char_init (unsigned char *base, int count) +{ +  /* memset might be overkill */ +  while (count--) +    *base++ = 0; +} +  static void  epoll_modify (EV_P_ int fd, int oev, int nev)  {    struct epoll_event ev; +  unsigned char oldmask;    /*     * we handle EPOLL_CTL_DEL by ignoring it here     * on the assumption that the fd is gone anyways     * if that is wrong, we have to handle the spurious     * event in epoll_poll. +   * the fd is later added, we try to ADD it, and, if that +   * fails, we assume it still has the same eventmask.     */    if (!nev)      return; +  oldmask = anfds [fd].emask; +  anfds [fd].emask = nev; +    ev.data.u64 = fd; /* use u64 to fully initialise the struct, for nicer strace etc. */    ev.events   = (nev & EV_READ  ? EPOLLIN  : 0)                | (nev & EV_WRITE ? EPOLLOUT : 0); @@ -80,7 +94,7 @@ epoll_modify (EV_P_ int fd, int oev, int nev)    if (expect_true (errno == ENOENT))      { -      /* on ENOENT the fd went away, so try to do the right thing */ +      /* if ENOENT then the fd went away, so try to do the right thing */        if (!nev)          return; @@ -89,8 +103,9 @@ epoll_modify (EV_P_ int fd, int oev, int nev)      }    else if (expect_true (errno == EEXIST))      { -      /* on EEXIST we ignored a previous DEL */ -      if (!epoll_ctl (backend_fd, EPOLL_CTL_MOD, fd, &ev)) +      /* EEXIST means we ignored a previous DEL, but the fd is still active */ +      /* if the kernel mask is the same as the new mask, we assume it hasn't changed */ +      if (oldmask == nev || !epoll_ctl (backend_fd, EPOLL_CTL_MOD, fd, &ev))          return;      } @@ -122,7 +137,10 @@ epoll_poll (EV_P_ ev_tstamp timeout)        if (expect_false (got & ~want))          { +          anfds [fd].emask = want; +            /* we received an event but are not interested in it, try mod or del */ +          /* I don't think we ever need MOD, but let's handle it anyways */            ev->events = (want & EV_READ  ? EPOLLIN  : 0)                       | (want & EV_WRITE ? EPOLLOUT : 0); @@ -42,6 +42,8 @@  void inline_size  pollidx_init (int *base, int count)  { +  /* consider using memset (.., -1, ...), which is pratically guarenteed +   * to work on all systems implementing poll */    while (count--)      *base++ = -1;  } | 
