]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - scheduler/select.c
Import CUPS trunk (1.4svn) r7116.
[thirdparty/cups.git] / scheduler / select.c
index c6f278e3674a6cf45d00dbaa6cde4da05a3c33b2..a2e1925d141b7b394375a75dfd6232721ea8e6cf 100644 (file)
@@ -33,6 +33,7 @@
 
 #ifdef HAVE_EPOLL
 #  include <sys/epoll.h>
+#  include <sys/poll.h>
 #elif defined(HAVE_KQUEUE)
 #  include <sys/event.h>
 #  include <sys/time.h>
  *
  *   In tests using the "make test" target with option 0 (keep cupsd
  *   running) and the "testspeed" program with "-c 50 -r 1000", epoll()
- *   performed 5.5% slower select(), followed by kqueue() at 16% slower
- *   than select() and poll() at 18% slower than select().  Similar
+ *   performed 5.5% slower than select(), followed by kqueue() at 16%
+ *   slower than select() and poll() at 18% slower than select().  Similar
  *   results were seen with twice the number of client connections.
  *
  *   The epoll() and kqueue() performance is likely limited by the
@@ -214,10 +215,7 @@ static cups_array_t        *cupsd_inactive_fds = NULL;
 static int             cupsd_in_select = 0;
 #endif /* HAVE_EPOLL || HAVE_KQUEUE */
 
-#ifdef HAVE_EPOLL
-static int             cupsd_epoll_fd = -1;
-static struct epoll_event *cupsd_epoll_events = NULL;
-#elif defined(HAVE_KQUEUE)
+#ifdef HAVE_KQUEUE
 static int             cupsd_kqueue_fd = -1,
                        cupsd_kqueue_changes = 0;
 static struct kevent   *cupsd_kqueue_events = NULL;
@@ -225,12 +223,16 @@ static struct kevent      *cupsd_kqueue_events = NULL;
 static int             cupsd_alloc_pollfds = 0,
                        cupsd_update_pollfds = 0;
 static struct pollfd   *cupsd_pollfds = NULL;
+#  ifdef HAVE_EPOLL
+static int             cupsd_epoll_fd = -1;
+static struct epoll_event *cupsd_epoll_events = NULL;
+#  endif /* HAVE_EPOLL */
 #else /* select() */
 static fd_set          cupsd_global_input,
                        cupsd_global_output,
                        cupsd_current_input,
                        cupsd_current_output;
-#endif /* HAVE_EPOLL */
+#endif /* HAVE_KQUEUE */
 
 
 /*
@@ -299,26 +301,7 @@ cupsdAddSelect(int             fd, /* I - File descriptor */
   else
     added = 0;
 
-#ifdef HAVE_EPOLL
-  {
-    struct epoll_event event;          /* Event data */
-
-
-    event.events = 0;
-
-    if (read_cb)
-      event.events |= EPOLLIN;
-
-    if (write_cb)
-      event.events |= EPOLLOUT;
-
-    event.data.ptr = fdptr;
-
-    epoll_ctl(cupsd_epoll_fd, added ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd,
-              &event);
-  }
-
-#elif defined(HAVE_KQUEUE)
+#ifdef HAVE_KQUEUE
   {
     struct kevent      event;          /* Event data */
     struct timespec    timeout;        /* Timeout value */
@@ -361,6 +344,33 @@ cupsdAddSelect(int             fd, /* I - File descriptor */
   }
 
 #elif defined(HAVE_POLL)
+#  ifdef HAVE_EPOLL
+  if (cupsd_epoll_fd >= 0)
+  {
+    struct epoll_event event;          /* Event data */
+
+
+    event.events = 0;
+
+    if (read_cb)
+      event.events |= EPOLLIN;
+
+    if (write_cb)
+      event.events |= EPOLLOUT;
+
+    event.data.ptr = fdptr;
+
+    if (epoll_ctl(cupsd_epoll_fd, added ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd,
+                  &event))
+    {
+      close(cupsd_epoll_fd);
+      cupsd_epoll_fd       = -1;
+      cupsd_update_pollfds = 1;
+    }
+  }
+  else
+#  endif /* HAVE_EPOLL */
+
   cupsd_update_pollfds = 1;
 
 #else /* select() */
@@ -396,7 +406,7 @@ cupsdAddSelect(int             fd,  /* I - File descriptor */
     FD_CLR(fd, &cupsd_global_output);
     FD_CLR(fd, &cupsd_current_output);
   }
-#endif /* HAVE_EPOLL */
+#endif /* HAVE_KQUEUE */
 
  /*
   * Save the (new) read and write callbacks...
@@ -419,53 +429,7 @@ cupsdDoSelect(long timeout)                /* I - Timeout in seconds */
 {
   int                  nfds;           /* Number of file descriptors */
   _cupsd_fd_t          *fdptr;         /* Current file descriptor */
-#ifdef HAVE_EPOLL
-  int                  i;              /* Looping var */
-  struct epoll_event   *event;         /* Current event */
-
-
-  cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                  "cupsdDoSelect: polling %d fds for %ld seconds...",
-                 cupsArrayCount(cupsd_fds), timeout);
-
-  cupsd_in_select = 1;
-
-  if (timeout >= 0 && timeout < 86400)
-    nfds = epoll_wait(cupsd_epoll_fd, cupsd_epoll_events, MaxFDs,
-                      timeout * 1000);
-  else
-    nfds = epoll_wait(cupsd_epoll_fd, cupsd_epoll_events, MaxFDs, -1);
-
-  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: epoll() returned %d...",
-                  nfds);
-
-  for (i = nfds, event = cupsd_epoll_events; i > 0; i --, event ++)
-  {
-    fdptr = (_cupsd_fd_t *)event->data.ptr;
-
-    if (cupsArrayFind(cupsd_inactive_fds, fdptr))
-      continue;
-
-    retain_fd(fdptr);
-
-    if (fdptr->read_cb && (event->events & (EPOLLIN | EPOLLERR | EPOLLHUP)))
-    {
-      cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Read on fd %d...",
-                     fdptr->fd);
-      (*(fdptr->read_cb))(fdptr->data);
-    }
-
-    if (fdptr->write_cb && (event->events & (EPOLLOUT | EPOLLERR | EPOLLHUP)))
-    {
-      cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Write on fd %d...",
-                     fdptr->fd);
-      (*(fdptr->write_cb))(fdptr->data);
-    }
-
-    release_fd(fdptr);
-  }
-
-#elif defined(HAVE_KQUEUE)
+#ifdef HAVE_KQUEUE
   int                  i;              /* Looping var */
   struct kevent                *event;         /* Current event */
   struct timespec      ktimeout;       /* kevent() timeout */
@@ -528,6 +492,66 @@ cupsdDoSelect(long timeout)                /* I - Timeout in seconds */
   int                  count;          /* Number of file descriptors */
 
 
+  cupsdLogMessage(CUPSD_LOG_DEBUG2,
+                  "cupsdDoSelect: polling %d fds for %ld seconds...",
+                 cupsArrayCount(cupsd_fds), timeout);
+
+#  ifdef HAVE_EPOLL
+  cupsd_in_select = 1;
+
+  if (cupsd_epoll_fd >= 0)
+  {
+    int                        i;              /* Looping var */
+    struct epoll_event *event;         /* Current event */
+
+
+    if (timeout >= 0 && timeout < 86400)
+      nfds = epoll_wait(cupsd_epoll_fd, cupsd_epoll_events, MaxFDs,
+                       timeout * 1000);
+    else
+      nfds = epoll_wait(cupsd_epoll_fd, cupsd_epoll_events, MaxFDs, -1);
+
+    cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: epoll() returned %d...",
+                    nfds);
+
+    if (nfds < 0 && errno != EINTR)
+    {
+      close(cupsd_epoll_fd);
+      cupsd_epoll_fd = -1;
+    }
+    else
+    {
+      for (i = nfds, event = cupsd_epoll_events; i > 0; i --, event ++)
+      {
+       fdptr = (_cupsd_fd_t *)event->data.ptr;
+
+       if (cupsArrayFind(cupsd_inactive_fds, fdptr))
+         continue;
+
+       retain_fd(fdptr);
+
+       if (fdptr->read_cb && (event->events & (EPOLLIN | EPOLLERR | EPOLLHUP)))
+       {
+         cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Read on fd %d...",
+                         fdptr->fd);
+         (*(fdptr->read_cb))(fdptr->data);
+       }
+
+       if (fdptr->write_cb && (event->events & (EPOLLOUT | EPOLLERR | EPOLLHUP)))
+       {
+         cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Write on fd %d...",
+                         fdptr->fd);
+         (*(fdptr->write_cb))(fdptr->data);
+       }
+
+       release_fd(fdptr);
+      }
+
+      goto release_inactive;
+    }
+  }
+#  endif /* HAVE_EPOLL */
+
   count = cupsArrayCount(cupsd_fds);
 
   if (cupsd_update_pollfds)
@@ -706,13 +730,17 @@ cupsdDoSelect(long timeout)               /* I - Timeout in seconds */
     }
   }
 
-#endif /* HAVE_EPOLL */
+#endif /* HAVE_KQUEUE */
 
 #if defined(HAVE_EPOLL) || defined(HAVE_KQUEUE)
  /*
   * Release all inactive file descriptors...
   */
 
+#  ifndef HAVE_KQUEUE
+  release_inactive:
+#  endif /* !HAVE_KQUEUE */
+
   cupsd_in_select = 0;
 
   for (fdptr = (_cupsd_fd_t *)cupsArrayFirst(cupsd_inactive_fds);
@@ -781,7 +809,12 @@ cupsdRemoveSelect(int fd)          /* I - File descriptor */
     return;
 
 #ifdef HAVE_EPOLL
-  epoll_ctl(cupsd_epoll_fd, EPOLL_CTL_DEL, fd, &event);
+  if (epoll_ctl(cupsd_epoll_fd, EPOLL_CTL_DEL, fd, &event))
+  {
+    close(cupsd_epoll_fd);
+    cupsd_epoll_fd       = -1;
+    cupsd_update_pollfds = 1;
+  }
 
 #elif defined(HAVE_KQUEUE)
   timeout.tv_sec  = 0;
@@ -862,8 +895,9 @@ cupsdStartSelect(void)
 #endif /* HAVE_EPOLL || HAVE_KQUEUE */
 
 #ifdef HAVE_EPOLL
-  cupsd_epoll_fd     = epoll_create(MaxFDs);
-  cupsd_epoll_events = calloc(MaxFDs, sizeof(struct epoll_event));
+  cupsd_epoll_fd       = epoll_create(MaxFDs);
+  cupsd_epoll_events   = calloc(MaxFDs, sizeof(struct epoll_event));
+  cupsd_update_pollfds = 0;
 
 #elif defined(HAVE_KQUEUE)
   cupsd_kqueue_fd      = kqueue();
@@ -903,20 +937,7 @@ cupsdStopSelect(void)
   cupsd_inactive_fds = NULL;
 #endif /* HAVE_EPOLL || HAVE_KQUEUE */
 
-#ifdef HAVE_EPOLL
-  if (cupsd_epoll_events)
-  {
-    free(cupsd_epoll_events);
-    cupsd_epoll_events = NULL;
-  }
-
-  if (cupsd_epoll_fd >= 0)
-  {
-    close(cupsd_epoll_fd);
-    cupsd_epoll_fd = -1;
-  }
-
-#elif defined(HAVE_KQUEUE)
+#ifdef HAVE_KQUEUE
   if (cupsd_kqueue_events)
   {
     free(cupsd_kqueue_events);
@@ -932,6 +953,20 @@ cupsdStopSelect(void)
   cupsd_kqueue_changes = 0;
 
 #elif defined(HAVE_POLL)
+#  ifdef HAVE_EPOLL
+  if (cupsd_epoll_events)
+  {
+    free(cupsd_epoll_events);
+    cupsd_epoll_events = NULL;
+  }
+
+  if (cupsd_epoll_fd >= 0)
+  {
+    close(cupsd_epoll_fd);
+    cupsd_epoll_fd = -1;
+  }
+#  endif /* HAVE_EPOLL */
+
   if (cupsd_pollfds)
   {
     free(cupsd_pollfds);