Use ppoll() and pselect() when available.
authorMatt Birkholz <matt@birkholz.chandler.az.us>
Mon, 3 Sep 2012 06:38:12 +0000 (23:38 -0700)
committerMatt Birkholz <matt@birkholz.chandler.az.us>
Mon, 3 Sep 2012 06:38:12 +0000 (23:38 -0700)
Use them only when a test-select- primitive should block.  The old
poll()/select() functions continue to be used when not blocking,
e.g. in uxsock.c's do_connect().

src/microcode/configure.ac
src/microcode/uxio.c

index bd05c00cfdbf46e2a9ea73e64a0981cb03fda2d0..5120a1e414cfb24433d936f9fb71ec564e20339a 100644 (file)
@@ -533,9 +533,9 @@ AC_CHECK_FUNCS([lockf log1p])
 AC_CHECK_FUNCS([madvise memcpy mkdir mktime modf])
 AC_CHECK_FUNCS([nice ntp_adjtime ntp_gettime])
 AC_CHECK_FUNCS([openpty])
-AC_CHECK_FUNCS([poll posix_madvise posix_openpt prealloc])
+AC_CHECK_FUNCS([ppoll poll posix_madvise posix_openpt prealloc])
 AC_CHECK_FUNCS([rename rmdir])
-AC_CHECK_FUNCS([select setitimer setpgrp setpgrp2 shmat sigaction])
+AC_CHECK_FUNCS([pselect select setitimer setpgrp setpgrp2 shmat sigaction])
 AC_CHECK_FUNCS([sighold socket statfs strchr strerror strstr strtol])
 AC_CHECK_FUNCS([strtoul symlink sync_file_range sysconf])
 AC_CHECK_FUNCS([times truncate])
index e3885126d73e0599195223675b11d1f760309788..be4a2f82648d7ea0c7d2e232fc5a544e41470d1b 100644 (file)
@@ -549,16 +549,53 @@ OS_select_registry_result (select_registry_t registry,
   (*mode_r) = (ENCODE_MODE ((SR_ENTRY (r, index)) -> revents));
 }
 
+static int
+safe_poll (struct pollfd *fds, nfds_t nfds, int blockp)
+{
+  int n;
+
+#ifdef HAVE_PPOLL
+  if (!blockp)
+    {
+      n = poll (fds, nfds, 0);
+    }
+  else
+    {
+      sigset_t old, new;
+
+      UX_sigfillset (&new);
+      UX_sigprocmask (SIG_SETMASK, &new, &old);
+      if ((OS_process_any_status_change ())
+         || (pending_interrupts_p ()))
+       {
+         errno = EINTR;
+         n = -1;
+       }
+      else
+       {
+         n = ppoll (fds, nfds, NULL, &old);
+       }
+      UX_sigprocmask (SIG_SETMASK, &old, NULL);
+    }
+#else /* not HAVE_PPOLL */
+  /* There is a signal "hole" here, but what can we do without ppoll()? */
+  INTERRUPTABLE_EXTENT
+    (n, (((OS_process_any_status_change ())
+         || (pending_interrupts_p ()))
+        ? ((errno = EINTR), (-1))
+        : (poll (fds, nfds, (blockp ? INFTIM : 0)))));
+#endif
+
+  return (n);
+}
+
 int
 OS_test_select_registry (select_registry_t registry, int blockp)
 {
   struct select_registry_s * r = registry;
   while (1)
     {
-      int nfds
-       = (poll ((SR_ENTRIES (r)),
-                (SR_N_FDS (r)),
-                (blockp ? INFTIM : 0)));
+      int nfds = safe_poll ((SR_ENTRIES (r)), (SR_N_FDS (r)), blockp);
       if (nfds >= 0)
        return (nfds);
       if (errno != EINTR)
@@ -578,7 +615,7 @@ OS_test_select_descriptor (int fd, int blockp, unsigned int mode)
   ((pfds [0]) . events) = (DECODE_MODE (mode));
   while (1)
     {
-      int nfds = (poll (pfds, 1, (blockp ? INFTIM : 0)));
+      int nfds = safe_poll (pfds, 1, blockp);
       if (nfds > 0)
        return (ENCODE_MODE ((pfds [0]) . revents));
       if (nfds == 0)
@@ -706,26 +743,61 @@ OS_select_registry_result (select_registry_t registry,
     }
 }
 
+static int
+safe_select (int nfds, SELECT_TYPE *readfds, SELECT_TYPE *writefds, int blockp)
+{
+  int n;
+
+#ifdef HAVE_PSELECT
+  if (!blockp)
+    {
+      n = UX_select (nfds, readfds, writefds, NULL, &zero_timeout);
+    }
+  else
+    {
+      sigset_t old, new;
+
+      UX_sigfillset (&new);
+      UX_sigprocmask (SIG_SETMASK, &new, &old);
+      if ((OS_process_any_status_change ())
+         || (pending_interrupts_p ()))
+       {
+         errno = EINTR;
+         n = -1;
+       }
+      else
+       {
+         n = pselect (nfds, readfds, writefds, NULL, NULL, &old);
+       }
+      UX_sigprocmask (SIG_SETMASK, &old, NULL);
+    }
+#else /* not HAVE_PSELECT */
+  /* There is a signal "hole" here, but what can we do without pselect()? */
+  INTERRUPTABLE_EXTENT
+    (n, (((OS_process_any_status_change ())
+         || (pending_interrupts_p ()))
+        ? ((errno = EINTR), (-1))
+        : (UX_select (nfds, readfds, writefds, NULL,
+                      (blockp ? NULL : &zero_timeout)))));
+#endif
+
+  return (n);
+}
+
 int
 OS_test_select_registry (select_registry_t registry, int blockp)
 {
 #ifdef HAVE_SELECT
   struct select_registry_s * r = registry;
+
+  (* (SR_RREADERS (r))) = (* (SR_QREADERS (r)));
+  (* (SR_RWRITERS (r))) = (* (SR_QWRITERS (r)));
   while (1)
     {
-      int nfds;
-
-      (* (SR_RREADERS (r))) = (* (SR_QREADERS (r)));
-      (* (SR_RWRITERS (r))) = (* (SR_QWRITERS (r)));
-      INTERRUPTABLE_EXTENT
-       (nfds,
-        ((OS_process_any_status_change ())
-         ? ((errno = EINTR), (-1))
-         : (UX_select (FD_SETSIZE,
-                       (SR_RREADERS (r)),
-                       (SR_RWRITERS (r)),
-                       0,
-                       (blockp ? 0 : (&zero_timeout))))));
+      int nfds = safe_select (FD_SETSIZE,
+                             (SR_RREADERS (r)),
+                             (SR_RWRITERS (r)),
+                             blockp);
       if (nfds >= 0)
        return (nfds);
       if (errno != EINTR)
@@ -745,29 +817,20 @@ int
 OS_test_select_descriptor (int fd, int blockp, unsigned int mode)
 {
 #ifdef HAVE_SELECT
+  SELECT_TYPE readable;
+  SELECT_TYPE writeable;
+
+  FD_ZERO (&readable);
+  if ((mode & SELECT_MODE_READ) != 0)
+    FD_SET (fd, (&readable));
+
+  FD_ZERO (&writeable);
+  if ((mode & SELECT_MODE_WRITE) != 0)
+    FD_SET (fd, (&writeable));
+
   while (1)
     {
-      SELECT_TYPE readable;
-      SELECT_TYPE writeable;
-      int nfds;
-
-      FD_ZERO (&readable);
-      if ((mode & SELECT_MODE_READ) != 0)
-       FD_SET (fd, (&readable));
-
-      FD_ZERO (&writeable);
-      if ((mode & SELECT_MODE_WRITE) != 0)
-       FD_SET (fd, (&writeable));
-
-      INTERRUPTABLE_EXTENT
-       (nfds,
-        ((OS_process_any_status_change ())
-         ? ((errno = EINTR), (-1))
-         : (UX_select ((fd + 1),
-                       (&readable),
-                       (&writeable),
-                       0,
-                       (blockp ? 0 : (&zero_timeout))))));
+      int nfds = safe_select (fd + 1, &readable, &writeable, blockp);
       if (nfds > 0)
        return
          (((FD_ISSET (fd, (&readable))) ? SELECT_MODE_READ : 0)