Source-Changes-HG archive

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

[src/trunk]: src/sys/kern In a case of direct select, set only masked events, ...



details:   https://anonhg.NetBSD.org/src/rev/bc88ba118e60
branches:  trunk
changeset: 762937:bc88ba118e60
user:      rmind <rmind%NetBSD.org@localhost>
date:      Sun Mar 06 04:41:58 2011 +0000

description:
In a case of direct select, set only masked events, do not wakeup LWP
if no polled/selected events were set; also, count the correct return
value for the select.

diffstat:

 sys/kern/sys_select.c |  42 ++++++++++++++++++++++++++++++------------
 1 files changed, 30 insertions(+), 12 deletions(-)

diffs (106 lines):

diff -r 470a0252b43c -r bc88ba118e60 sys/kern/sys_select.c
--- a/sys/kern/sys_select.c     Sun Mar 06 04:34:25 2011 +0000
+++ b/sys/kern/sys_select.c     Sun Mar 06 04:41:58 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sys_select.c,v 1.29 2010/12/18 01:36:19 rmind Exp $    */
+/*     $NetBSD: sys_select.c,v 1.30 2011/03/06 04:41:58 rmind Exp $    */
 
 /*-
  * Copyright (c) 2007, 2008, 2009, 2010 The NetBSD Foundation, Inc.
@@ -84,7 +84,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_select.c,v 1.29 2010/12/18 01:36:19 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_select.c,v 1.30 2011/03/06 04:41:58 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -249,7 +249,7 @@
 
        l->l_selret = 0;
        if (op == SELOP_SELECT) {
-               l->l_selbits = (char *)fds + ni * 3;
+               l->l_selbits = fds;
                l->l_selni = ni;
        } else {
                l->l_selbits = NULL;
@@ -612,10 +612,11 @@
  * sel_setevents: a helper function for selnotify(), to set the events
  * for LWP sleeping in selcommon() or pollcommon().
  */
-static inline void
+static inline bool
 sel_setevents(lwp_t *l, struct selinfo *sip, const int events)
 {
        const int oflag = l->l_selflag;
+       int ret = 0;
 
        /*
         * If we require re-scan or it was required by somebody else,
@@ -623,32 +624,45 @@
         */
        if (__predict_false(events == 0 || oflag == SEL_RESET)) {
                l->l_selflag = SEL_RESET;
-               return;
+               return true;
        }
        /*
         * Direct set.  Note: select state of LWP is locked.  First,
         * determine whether it is selcommon() or pollcommon().
         */
        if (l->l_selbits != NULL) {
+               const size_t ni = l->l_selni;
                fd_mask *fds = (fd_mask *)l->l_selbits;
-               const size_t ni = l->l_selni;
-               const int fd = sip->sel_fdinfo;
+               fd_mask *ofds = (fd_mask *)((char *)fds + ni * 3);
+               const int fd = sip->sel_fdinfo, fbit = 1 << (fd & __NFDMASK);
                const int idx = fd >> __NFDSHIFT;
                int n;
 
                for (n = 0; n < 3; n++) {
-                       if (sel_flag[n] & events) {
-                               fds[idx] |= 1 << (fd & __NFDMASK);
+                       if ((fds[idx] & fbit) != 0 && (sel_flag[n] & events)) {
+                               ofds[idx] |= fbit;
+                               ret++;
                        }
                        fds = (fd_mask *)((char *)fds + ni);
+                       ofds = (fd_mask *)((char *)ofds + ni);
                }
        } else {
                struct pollfd *pfd = (void *)sip->sel_fdinfo;
-               pfd->revents |= events;
+               int revents = events & (pfd->events | POLLERR | POLLHUP);
+
+               if (revents) {
+                       pfd->revents |= revents;
+                       ret = 1;
+               }
+       }
+       /* Check whether there are any events to return. */
+       if (!ret) {
+               return false;
        }
        /* Indicate direct set and note the event (cluster lock is held). */
        l->l_selflag = SEL_EVENT;
-       l->l_selret++;
+       l->l_selret += ret;
+       return true;
 }
 
 /*
@@ -688,7 +702,11 @@
                        l = sip->sel_lwp;
                        oflag = l->l_selflag;
 #ifndef NO_DIRECT_SELECT
-                       sel_setevents(l, sip, events);
+                       if (!sel_setevents(l, sip, events)) {
+                               /* No events to return. */
+                               mutex_spin_exit(lock);
+                               return;
+                       }
 #else
                        l->l_selflag = SEL_RESET;
 #endif



Home | Main Index | Thread Index | Old Index