Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/kern Move common logic in selcommon() and pollcommon() i...



details:   https://anonhg.NetBSD.org/src/rev/96d01a2d8b03
branches:  trunk
changeset: 748689:96d01a2d8b03
user:      rmind <rmind%NetBSD.org@localhost>
date:      Sun Nov 01 21:14:21 2009 +0000

description:
Move common logic in selcommon() and pollcommon() into sel_do_scan().
Avoids code duplication.  XXX: pollsock() should be converted too, except
it's a bit ugly.

diffstat:

 sys/kern/sys_select.c |  246 +++++++++++++++++++++----------------------------
 1 files changed, 104 insertions(+), 142 deletions(-)

diffs (truncated from 348 to 300 lines):

diff -r 726c22fbc2ce -r 96d01a2d8b03 sys/kern/sys_select.c
--- a/sys/kern/sys_select.c     Sun Nov 01 21:08:32 2009 +0000
+++ b/sys/kern/sys_select.c     Sun Nov 01 21:14:21 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sys_select.c,v 1.16 2009/10/21 21:12:06 rmind Exp $    */
+/*     $NetBSD: sys_select.c,v 1.17 2009/11/01 21:14:21 rmind Exp $    */
 
 /*-
  * Copyright (c) 2007, 2008, 2009 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_select.c,v 1.16 2009/10/21 21:12:06 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_select.c,v 1.17 2009/11/01 21:14:21 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -108,8 +108,8 @@
        uint32_t        sc_mask;
 } selcpu_t;
 
-static int     selscan(lwp_t *, fd_mask *, fd_mask *, int, register_t *);
-static int     pollscan(lwp_t *, struct pollfd *, int, register_t *);
+static int     selscan(char *, u_int, register_t *);
+static int     pollscan(struct pollfd *, u_int, register_t *);
 static void    selclear(void);
 
 static syncobj_t select_sobj = {
@@ -210,6 +210,87 @@
            SCARG(uap, ou), SCARG(uap, ex), ts, NULL);
 }
 
+/*
+ * sel_do_scan: common code to perform the scan on descriptors.
+ */
+static int
+sel_do_scan(void *fds, u_int nfds, struct timespec *ts, sigset_t *mask,
+    register_t *retval, int selpoll)
+{
+       lwp_t           * const l = curlwp;
+       proc_t          * const p = l->l_proc;
+       selcpu_t        *sc;
+       kmutex_t        *lock;
+       sigset_t        oldmask;
+       struct timespec sleepts;
+       int             error, timo;
+
+       timo = 0;
+       if (ts && inittimeleft(ts, &sleepts) == -1) {
+               return EINVAL;
+       }
+
+       if (__predict_false(mask)) {
+               sigminusset(&sigcantmask, mask);
+               mutex_enter(p->p_lock);
+               oldmask = l->l_sigmask;
+               l->l_sigmask = *mask;
+               mutex_exit(p->p_lock);
+       } else {
+               /* XXXgcc */
+               oldmask = l->l_sigmask;
+       }
+
+       sc = curcpu()->ci_data.cpu_selcpu;
+       lock = sc->sc_lock;
+       l->l_selcpu = sc;
+       SLIST_INIT(&l->l_selwait);
+       for (;;) {
+               int ncoll;
+
+               /*
+                * No need to lock.  If this is overwritten by another value
+                * while scanning, we will retry below.  We only need to see
+                * exact state from the descriptors that we are about to poll,
+                * and lock activity resulting from fo_poll is enough to
+                * provide an up to date value for new polling activity.
+                */
+               l->l_selflag = SEL_SCANNING;
+               ncoll = sc->sc_ncoll;
+
+               if (selpoll) {
+                       error = selscan((char *)fds, nfds, retval);
+               } else {
+                       error = pollscan((struct pollfd *)fds, nfds, retval);
+               }
+
+               if (error || *retval)
+                       break;
+               if (ts && (timo = gettimeleft(ts, &sleepts)) <= 0)
+                       break;
+               mutex_spin_enter(lock);
+               if (l->l_selflag != SEL_SCANNING || sc->sc_ncoll != ncoll) {
+                       mutex_spin_exit(lock);
+                       continue;
+               }
+               l->l_selflag = SEL_BLOCKING;
+               l->l_kpriority = true;
+               sleepq_enter(&sc->sc_sleepq, l, lock);
+               sleepq_enqueue(&sc->sc_sleepq, sc, "select", &select_sobj);
+               error = sleepq_block(timo, true);
+               if (error != 0)
+                       break;
+       }
+       selclear();
+
+       if (__predict_false(mask)) {
+               mutex_enter(p->p_lock);
+               l->l_sigmask = oldmask;
+               mutex_exit(p->p_lock);
+       }
+       return error;
+}
+
 int
 selcommon(lwp_t *l, register_t *retval, int nd, fd_set *u_in,
          fd_set *u_ou, fd_set *u_ex, struct timespec *ts, sigset_t *mask)
@@ -218,14 +299,9 @@
                            sizeof(fd_mask) * 6];
        proc_t          * const p = l->l_proc;
        char            *bits;
-       int             ncoll, error, timo, nf;
+       int             error, nf;
        size_t          ni;
-       sigset_t        oldmask;
-       struct timespec sleepts;
-       selcpu_t        *sc;
-       kmutex_t        *lock;
 
-       error = 0;
        if (nd < 0)
                return (EINVAL);
        nf = p->p_fd->fd_dt->dt_nfiles;
@@ -253,65 +329,7 @@
        getbits(ex, 2);
 #undef getbits
 
-       timo = 0;
-       if (ts && inittimeleft(ts, &sleepts) == -1) {
-               error = EINVAL;
-               goto done;
-       }
-
-       if (mask) {
-               sigminusset(&sigcantmask, mask);
-               mutex_enter(p->p_lock);
-               oldmask = l->l_sigmask;
-               l->l_sigmask = *mask;
-               mutex_exit(p->p_lock);
-       } else
-               oldmask = l->l_sigmask; /* XXXgcc */
-
-       sc = curcpu()->ci_data.cpu_selcpu;
-       lock = sc->sc_lock;
-       l->l_selcpu = sc;
-       SLIST_INIT(&l->l_selwait);
-       for (;;) {
-               /*
-                * No need to lock.  If this is overwritten by another
-                * value while scanning, we will retry below.  We only
-                * need to see exact state from the descriptors that
-                * we are about to poll, and lock activity resulting
-                * from fo_poll is enough to provide an up to date value
-                * for new polling activity.
-                */
-               l->l_selflag = SEL_SCANNING;
-               ncoll = sc->sc_ncoll;
-
-               error = selscan(l, (fd_mask *)(bits + ni * 0),
-                   (fd_mask *)(bits + ni * 3), nd, retval);
-
-               if (error || *retval)
-                       break;
-               if (ts && (timo = gettimeleft(ts, &sleepts)) <= 0)
-                       break;
-               mutex_spin_enter(lock);
-               if (l->l_selflag != SEL_SCANNING || sc->sc_ncoll != ncoll) {
-                       mutex_spin_exit(lock);
-                       continue;
-               }
-               l->l_selflag = SEL_BLOCKING;
-               l->l_kpriority = true;
-               sleepq_enter(&sc->sc_sleepq, l, lock);
-               sleepq_enqueue(&sc->sc_sleepq, sc, "select", &select_sobj);
-               error = sleepq_block(timo, true);
-               if (error != 0)
-                       break;
-       }
-       selclear();
-
-       if (mask) {
-               mutex_enter(p->p_lock);
-               l->l_sigmask = oldmask;
-               mutex_exit(p->p_lock);
-       }
-
+       error = sel_do_scan(bits, nd, ts, mask, retval, 1);
  done:
        /* select is not restarted after signals... */
        if (error == ERESTART)
@@ -329,18 +347,22 @@
        return (error);
 }
 
-int
-selscan(lwp_t *l, fd_mask *ibitp, fd_mask *obitp, int nfd,
-       register_t *retval)
+static int
+selscan(char *bits, u_int nfd, register_t *retval)
 {
        static const int flag[3] = { POLLRDNORM | POLLHUP | POLLERR,
                               POLLWRNORM | POLLHUP | POLLERR,
                               POLLRDBAND };
-       int msk, i, j, fd, n;
+       fd_mask *ibitp, *obitp;
+       int msk, i, j, fd, ni, n;
        fd_mask ibits, obits;
        file_t *fp;
 
+       ni = howmany(nfd, NFDBITS) * sizeof(fd_mask);
+       ibitp = (fd_mask *)(bits + ni * 0);
+       obitp = (fd_mask *)(bits + ni * 3);
        n = 0;
+
        for (msk = 0; msk < 3; msk++) {
                for (i = 0; i < nfd; i += NFDBITS) {
                        ibits = *ibitp++;
@@ -426,12 +448,8 @@
        struct pollfd   smallfds[32];
        struct pollfd   *fds;
        proc_t          * const p = l->l_proc;
-       sigset_t        oldmask;
-       int             ncoll, error, timo;
+       int             error;
        size_t          ni, nf;
-       struct timespec sleepts;
-       selcpu_t        *sc;
-       kmutex_t        *lock;
 
        nf = p->p_fd->fd_dt->dt_nfiles;
        if (nfds > nf) {
@@ -450,63 +468,7 @@
        if (error)
                goto done;
 
-       timo = 0;
-       if (ts && inittimeleft(ts, &sleepts) == -1) {
-               error = EINVAL;
-               goto done;
-       }
-
-       if (mask) {
-               sigminusset(&sigcantmask, mask);
-               mutex_enter(p->p_lock);
-               oldmask = l->l_sigmask;
-               l->l_sigmask = *mask;
-               mutex_exit(p->p_lock);
-       } else
-               oldmask = l->l_sigmask; /* XXXgcc */
-
-       sc = curcpu()->ci_data.cpu_selcpu;
-       lock = sc->sc_lock;
-       l->l_selcpu = sc;
-       SLIST_INIT(&l->l_selwait);
-       for (;;) {
-               /*
-                * No need to lock.  If this is overwritten by another
-                * value while scanning, we will retry below.  We only
-                * need to see exact state from the descriptors that
-                * we are about to poll, and lock activity resulting
-                * from fo_poll is enough to provide an up to date value
-                * for new polling activity.
-                */
-               ncoll = sc->sc_ncoll;
-               l->l_selflag = SEL_SCANNING;
-
-               error = pollscan(l, fds, nfds, retval);
-
-               if (error || *retval)
-                       break;
-               if (ts && (timo = gettimeleft(ts, &sleepts)) <= 0)
-                       break;
-               mutex_spin_enter(lock);
-               if (l->l_selflag != SEL_SCANNING || sc->sc_ncoll != ncoll) {
-                       mutex_spin_exit(lock);
-                       continue;
-               }
-               l->l_selflag = SEL_BLOCKING;
-               l->l_kpriority = true;
-               sleepq_enter(&sc->sc_sleepq, l, lock);
-               sleepq_enqueue(&sc->sc_sleepq, sc, "select", &select_sobj);
-               error = sleepq_block(timo, true);
-               if (error != 0)
-                       break;
-       }
-       selclear();
-
-       if (mask) {
-               mutex_enter(p->p_lock);
-               l->l_sigmask = oldmask;



Home | Main Index | Thread Index | Old Index