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

Reply via email to