Module Name: src Committed By: rmind Date: Sun Mar 6 04:41:58 UTC 2011
Modified Files: src/sys/kern: sys_select.c Log Message: 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. To generate a diff of this commit: cvs rdiff -u -r1.29 -r1.30 src/sys/kern/sys_select.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/sys_select.c diff -u src/sys/kern/sys_select.c:1.29 src/sys/kern/sys_select.c:1.30 --- src/sys/kern/sys_select.c:1.29 Sat Dec 18 01:36:19 2010 +++ src/sys/kern/sys_select.c Sun Mar 6 04:41:58 2011 @@ -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) { - fd_mask *fds = (fd_mask *)l->l_selbits; const size_t ni = l->l_selni; - const int fd = sip->sel_fdinfo; + fd_mask *fds = (fd_mask *)l->l_selbits; + 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