From 2209d3c850d80c0681948f966816f28f767575cb Mon Sep 17 00:00:00 2001 From: Richard Lowe Date: Thu, 20 Jun 2013 00:27:41 +0000 Subject: [PATCH] 3772 consider raising default descriptor soft limit Reviewed by: Igor Kozhukhov Reviewed by: Robert Mustacchi Reviewed by: Juraj Lutter Reviewed by: Patrick Mooney Approved by: Dan McDonald --- usr/src/cmd/sendmail/libsm/Makefile | 6 +- usr/src/lib/libc/i386/Makefile.com | 1 - usr/src/lib/libc/port/gen/select.c | 94 ++- usr/src/lib/libc/port/gen/select_large_fdset.c | 392 --------- usr/src/lib/libc/sparc/Makefile.com | 1 - usr/src/lib/libnsl/Makefile.com | 3 +- usr/src/lib/libnsl/rpc/rpc_comdata.c | 9 +- usr/src/lib/libnsl/rpc/rpc_comdata1.c | 64 -- usr/src/lib/libnsl/rpc/svc.c | 20 +- usr/src/man/man3c/select.3c | 927 ++++++++++++--------- usr/src/pkg/manifests/system-test-libctest.mf | 3 + usr/src/test/libc-tests/runfiles/default.run | 3 + usr/src/test/libc-tests/tests/Makefile | 1 + usr/src/test/libc-tests/tests/select/Makefile | 64 ++ usr/src/test/libc-tests/tests/select/select.sh | 41 + usr/src/test/libc-tests/tests/select/select_test.c | 126 +++ usr/src/uts/common/conf/param.c | 4 +- usr/src/uts/common/rpc/svc.h | 8 - usr/src/uts/common/sys/select.h | 18 +- 19 files changed, 857 insertions(+), 928 deletions(-) delete mode 100644 usr/src/lib/libc/port/gen/select_large_fdset.c delete mode 100644 usr/src/lib/libnsl/rpc/rpc_comdata1.c rewrite usr/src/man/man3c/select.3c (74%) create mode 100644 usr/src/test/libc-tests/tests/select/Makefile create mode 100644 usr/src/test/libc-tests/tests/select/select.sh create mode 100644 usr/src/test/libc-tests/tests/select/select_test.c diff --git a/usr/src/cmd/sendmail/libsm/Makefile b/usr/src/cmd/sendmail/libsm/Makefile index 4eda2239b7..da14b1d0e0 100644 --- a/usr/src/cmd/sendmail/libsm/Makefile +++ b/usr/src/cmd/sendmail/libsm/Makefile @@ -23,10 +23,6 @@ # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# -# cmd/sendmail/libsm/Makefile -# include ../../Makefile.cmd include ../Makefile.cmd @@ -54,6 +50,8 @@ TESTS= t-event t-exc t-rpool t-string t-smstdio t-match t-strio t-heap \ libsm= libsm.a +CERRWARN += -_gcc=-Wno-type-limits + .KEEP_STATE: all: $(libsm) diff --git a/usr/src/lib/libc/i386/Makefile.com b/usr/src/lib/libc/i386/Makefile.com index c99eab68dc..6f2d3fe494 100644 --- a/usr/src/lib/libc/i386/Makefile.com +++ b/usr/src/lib/libc/i386/Makefile.com @@ -551,7 +551,6 @@ PORTGEN= \ scandir.o \ seekdir.o \ select.o \ - select_large_fdset.o \ setlabel.o \ setpriority.o \ settimeofday.o \ diff --git a/usr/src/lib/libc/port/gen/select.c b/usr/src/lib/libc/port/gen/select.c index ed39ba9efb..24852149ed 100644 --- a/usr/src/lib/libc/port/gen/select.c +++ b/usr/src/lib/libc/port/gen/select.c @@ -27,8 +27,6 @@ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Emulation of select() system call using poll() system call. * @@ -47,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -54,9 +53,58 @@ #include #include "libc.h" +/* + * STACK_PFD_LIM + * + * The limit at which pselect allocates pollfd structures in the heap, + * rather than on the stack. These limits match the historical behaviour + * with the * _large_fdset implementations. + * + * BULK_ALLOC_LIM + * + * The limit below which we'll just allocate nfds pollfds, rather than + * counting how many we actually need. + */ +#if defined(_LP64) +#define STACK_PFD_LIM FD_SETSIZE +#define BULK_ALLOC_LIM 8192 +#else +#define STACK_PFD_LIM 1024 +#define BULK_ALLOC_LIM 1024 +#endif + +/* + * The previous _large_fdset implementations are, unfortunately, baked into + * the ABI. + */ +#pragma weak select_large_fdset = select +#pragma weak pselect_large_fdset = pselect + +#define fd_set_size(nfds) (((nfds) + (NFDBITS - 1)) / NFDBITS) + +static nfds_t +fd_sets_count(int limit, fd_set *in, fd_set *out, fd_set *ex) +{ + nfds_t total = 0; + + if (limit <= 0) + return (0); + + for (int i = 0; i < fd_set_size(limit); i++) { + long v = (in->fds_bits[i] | out->fds_bits[i] | ex->fds_bits[i]); + + while (v != 0) { + v &= v - 1; + total++; + } + } + + return (total); +} + int pselect(int nfds, fd_set *in0, fd_set *out0, fd_set *ex0, - const timespec_t *tsp, const sigset_t *sigmask) + const timespec_t *tsp, const sigset_t *sigmask) { long *in, *out, *ex; ulong_t m; /* bit mask */ @@ -66,6 +114,8 @@ pselect(int nfds, fd_set *in0, fd_set *out0, fd_set *ex0, struct pollfd *pfd; struct pollfd *p; int lastj = -1; + nfds_t npfds = 0; + boolean_t heap_pfds = B_FALSE; /* "zero" is read-only, it could go in the text segment */ static fd_set zero = { 0 }; @@ -80,7 +130,6 @@ pselect(int nfds, fd_set *in0, fd_set *out0, fd_set *ex0, errno = EINVAL; return (-1); } - p = pfd = (struct pollfd *)alloca(nfds * sizeof (struct pollfd)); if (tsp != NULL) { /* check timespec validity */ @@ -102,6 +151,21 @@ pselect(int nfds, fd_set *in0, fd_set *out0, fd_set *ex0, if (ex0 == NULL) ex0 = &zero; + if (nfds <= BULK_ALLOC_LIM) { + p = pfd = alloca(nfds * sizeof (struct pollfd)); + } else { + npfds = fd_sets_count(nfds, in0, out0, ex0); + + if (npfds > STACK_PFD_LIM) { + p = pfd = malloc(npfds * sizeof (struct pollfd)); + if (p == NULL) + return (-1); + heap_pfds = B_TRUE; + } else { + p = pfd = alloca(npfds * sizeof (struct pollfd)); + } + } + /* * For each fd, if any bits are set convert them into * the appropriate pollfd struct. @@ -134,13 +198,13 @@ done: /* * Now do the poll. */ - n = (int)(p - pfd); /* number of pollfd's */ + npfds = (int)(p - pfd); do { - rv = _pollsys(pfd, (nfds_t)n, tsp, sigmask); + rv = _pollsys(pfd, npfds, tsp, sigmask); } while (rv < 0 && errno == EAGAIN); if (rv < 0) /* no need to set bit masks */ - return (rv); + goto out; if (rv == 0) { /* @@ -163,14 +227,15 @@ done: for (n = 0; n < nfds; n += NFDBITS) *ex++ = 0; } - return (0); + rv = 0; + goto out; } /* * Check for EINVAL error case first to avoid changing any bits * if we're going to return an error. */ - for (p = pfd, j = n; j-- > 0; p++) { + for (p = pfd, n = npfds; n-- > 0; p++) { /* * select will return EBADF immediately if any fd's * are bad. poll will complete the poll on the @@ -181,7 +246,8 @@ done: */ if (p->revents & POLLNVAL) { errno = EBADF; - return (-1); + rv = -1; + goto out; } /* * We would like to make POLLHUP available to select, @@ -194,7 +260,8 @@ done: * if ((p->revents & POLLHUP) && * !(p->revents & (POLLRDNORM|POLLRDBAND))) { * errno = EINTR; - * return (-1); + * rv = -1; + * goto out; * } */ } @@ -212,7 +279,7 @@ done: * (as the man page says, and as poll() does). */ rv = 0; - for (p = pfd; n-- > 0; p++) { + for (p = pfd, n = npfds; n-- > 0; p++) { j = (int)(p->fd / NFDBITS); /* have we moved into another word of the bit mask yet? */ if (j != lastj) { @@ -278,6 +345,9 @@ done: } } } +out: + if (heap_pfds) + free(pfd); return (rv); } diff --git a/usr/src/lib/libc/port/gen/select_large_fdset.c b/usr/src/lib/libc/port/gen/select_large_fdset.c deleted file mode 100644 index 4411d38d58..0000000000 --- a/usr/src/lib/libc/port/gen/select_large_fdset.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* Copyright (c) 1988 AT&T */ -/* All Rights Reserved */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Emulation of select() system call using _pollsys() system call. - * - * Assumptions: - * polling for input only is most common. - * polling for exceptional conditions is very rare. - * - * Note that is it not feasible to emulate all error conditions, - * in particular conditions that would return EFAULT are far too - * difficult to check for in a library routine. - * - * This is the alternate large fd_set select. - * - */ - -/* - * Must precede any include files - */ -#ifdef FD_SETSIZE -#undef FD_SETSIZE -#endif -#define FD_SETSIZE 65536 - -#include "lint.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "libc.h" - -#define DEFAULT_POLL_SIZE 64 - -static struct pollfd *realloc_fds(int *, struct pollfd **, struct pollfd *); - -int -pselect_large_fdset(int nfds, fd_set *in0, fd_set *out0, fd_set *ex0, - const timespec_t *tsp, const sigset_t *sigmask) -{ - long *in, *out, *ex; - ulong_t m; /* bit mask */ - int j; /* loop counter */ - ulong_t b; /* bits to test */ - int n, rv; - int lastj = -1; - int nused; - - /* - * Rather than have a mammoth pollfd (65K) list on the stack - * we start with a small one and then malloc larger chunks - * on the heap if necessary. - */ - - struct pollfd pfd[DEFAULT_POLL_SIZE]; - struct pollfd *p; - struct pollfd *pfd_list; - int nfds_on_list; - - fd_set zero; - - /* - * Check for invalid conditions at outset. - * Required for spec1170. - * SUSV3: We must behave as a cancellation point even if we fail early. - */ - if (nfds >= 0 && nfds <= FD_SETSIZE) { - if (tsp != NULL) { - if (tsp->tv_nsec < 0 || tsp->tv_nsec >= NANOSEC || - tsp->tv_sec < 0) { - pthread_testcancel(); - errno = EINVAL; - return (-1); - } - } - } else { - pthread_testcancel(); - errno = EINVAL; - return (-1); - } - - /* - * If any input args are null, point them at the null array. - */ - (void) memset(&zero, 0, sizeof (fd_set)); - if (in0 == NULL) - in0 = &zero; - if (out0 == NULL) - out0 = &zero; - if (ex0 == NULL) - ex0 = &zero; - - nfds_on_list = DEFAULT_POLL_SIZE; - pfd_list = pfd; - p = pfd_list; - (void) memset(pfd, 0, sizeof (pfd)); - /* - * For each fd, if any bits are set convert them into - * the appropriate pollfd struct. - */ - in = (long *)in0->fds_bits; - out = (long *)out0->fds_bits; - ex = (long *)ex0->fds_bits; - nused = 0; - /* - * nused reflects the number of pollfd structs currently used - * less one. If realloc_fds returns NULL it is because malloc - * failed. We expect malloc() to have done the proper - * thing with errno. - */ - for (n = 0; n < nfds; n += NFDBITS) { - b = (ulong_t)(*in | *out | *ex); - for (j = 0, m = 1; b != 0; j++, b >>= 1, m <<= 1) { - if (b & 1) { - p->fd = n + j; - if (p->fd < nfds) { - p->events = 0; - if (*in & m) - p->events |= POLLRDNORM; - if (*out & m) - p->events |= POLLWRNORM; - if (*ex & m) - p->events |= POLLRDBAND; - if (nused < (nfds_on_list - 1)) { - p++; - } else if ((p = realloc_fds( - &nfds_on_list, &pfd_list, pfd)) - == NULL) { - if (pfd_list != pfd) - free(pfd_list); - pthread_testcancel(); - return (-1); - } - nused++; - } else - goto done; - } - } - in++; - out++; - ex++; - } -done: - /* - * Now do the poll. - */ - do { - rv = _pollsys(pfd_list, (nfds_t)nused, tsp, sigmask); - } while (rv < 0 && errno == EAGAIN); - - if (rv < 0) { /* no need to set bit masks */ - if (pfd_list != pfd) - free(pfd_list); - return (rv); - } else if (rv == 0) { - /* - * Clear out bit masks, just in case. - * On the assumption that usually only - * one bit mask is set, use three loops. - */ - if (in0 != &zero) { - in = (long *)in0->fds_bits; - for (n = 0; n < nfds; n += NFDBITS) - *in++ = 0; - } - if (out0 != &zero) { - out = (long *)out0->fds_bits; - for (n = 0; n < nfds; n += NFDBITS) - *out++ = 0; - } - if (ex0 != &zero) { - ex = (long *)ex0->fds_bits; - for (n = 0; n < nfds; n += NFDBITS) - *ex++ = 0; - } - if (pfd_list != pfd) - free(pfd_list); - return (0); - } - - /* - * Check for EINVAL error case first to avoid changing any bits - * if we're going to return an error. - */ - for (p = pfd_list, j = nused; j-- > 0; p++) { - /* - * select will return EBADF immediately if any fd's - * are bad. poll will complete the poll on the - * rest of the fd's and include the error indication - * in the returned bits. This is a rare case so we - * accept this difference and return the error after - * doing more work than select would've done. - */ - if (p->revents & POLLNVAL) { - errno = EBADF; - if (pfd_list != pfd) - free(pfd_list); - return (-1); - } - /* - * We would like to make POLLHUP available to select, - * checking to see if we have pending data to be read. - * BUT until we figure out how not to break Xsun's - * dependencies on select's existing features... - * This is what we _thought_ would work ... sigh! - */ - /* - * if ((p->revents & POLLHUP) && - * !(p->revents & (POLLRDNORM|POLLRDBAND))) { - * errno = EINTR; - * return (-1); - * } - */ - } - - /* - * Convert results of poll back into bits - * in the argument arrays. - * - * We assume POLLRDNORM, POLLWRNORM, and POLLRDBAND will only be set - * on return from poll if they were set on input, thus we don't - * worry about accidentally setting the corresponding bits in the - * zero array if the input bit masks were null. - * - * Must return number of bits set, not number of ready descriptors - * (as the man page says, and as poll() does). - */ - rv = 0; - for (p = pfd_list; nused-- > 0; p++) { - j = (int)(p->fd / NFDBITS); - /* have we moved into another word of the bit mask yet? */ - if (j != lastj) { - /* clear all output bits to start with */ - in = (long *)&in0->fds_bits[j]; - out = (long *)&out0->fds_bits[j]; - ex = (long *)&ex0->fds_bits[j]; - /* - * In case we made "zero" read-only (e.g., with - * cc -R), avoid actually storing into it. - */ - if (in0 != &zero) - *in = 0; - if (out0 != &zero) - *out = 0; - if (ex0 != &zero) - *ex = 0; - lastj = j; - } - if (p->revents) { - m = 1L << (p->fd % NFDBITS); - if (p->revents & POLLRDNORM) { - *in |= m; - rv++; - } - if (p->revents & POLLWRNORM) { - *out |= m; - rv++; - } - if (p->revents & POLLRDBAND) { - *ex |= m; - rv++; - } - /* - * Only set this bit on return if we asked about - * input conditions. - */ - if ((p->revents & (POLLHUP|POLLERR)) && - (p->events & POLLRDNORM)) { - if ((*in & m) == 0) - rv++; /* wasn't already set */ - *in |= m; - } - /* - * Only set this bit on return if we asked about - * output conditions. - */ - if ((p->revents & (POLLHUP|POLLERR)) && - (p->events & POLLWRNORM)) { - if ((*out & m) == 0) - rv++; /* wasn't already set */ - *out |= m; - } - /* - * Only set this bit on return if we asked about - * output conditions. - */ - if ((p->revents & (POLLHUP|POLLERR)) && - (p->events & POLLRDBAND)) { - if ((*ex & m) == 0) - rv++; /* wasn't already set */ - *ex |= m; - } - } - } - if (pfd_list != pfd) - free(pfd_list); - return (rv); -} - -int -select_large_fdset(int nfds, fd_set *in0, fd_set *out0, fd_set *ex0, - struct timeval *tv) -{ - timespec_t ts; - timespec_t *tsp; - - if (tv == NULL) - tsp = NULL; - else { - /* check timeval validity */ - if (tv->tv_usec < 0 || tv->tv_usec >= MICROSEC) { - errno = EINVAL; - return (-1); - } - /* - * Convert timeval to timespec. - * To preserve compatibility with past behavior, - * when select was built upon poll(2), which has a - * minimum non-zero timeout of 1 millisecond, force - * a minimum non-zero timeout of 500 microseconds. - */ - ts.tv_sec = tv->tv_sec; - ts.tv_nsec = tv->tv_usec * 1000; - if (ts.tv_nsec != 0 && ts.tv_nsec < 500000) - ts.tv_nsec = 500000; - tsp = &ts; - } - - return (pselect_large_fdset(nfds, in0, out0, ex0, tsp, NULL)); -} - -/* - * Reallocate buffers of pollfds for our list. We malloc a new buffer - * and, in the case where the old buffer does not match what is passed - * in orig, free the buffer after copying the contents. - */ -struct pollfd * -realloc_fds(int *num, struct pollfd **list_head, struct pollfd *orig) -{ - struct pollfd *b; - int nta; - int n2; - - n2 = *num * 2; - nta = n2 * sizeof (struct pollfd); - b = malloc(nta); - if (b) { - (void) memset(b, 0, (size_t)nta); - (void) memcpy(b, *list_head, nta / 2); - if (*list_head != orig) - free(*list_head); - *list_head = b; - b += *num; - *num = n2; - } - return (b); -} diff --git a/usr/src/lib/libc/sparc/Makefile.com b/usr/src/lib/libc/sparc/Makefile.com index f67bae0a76..2f5f67dd8f 100644 --- a/usr/src/lib/libc/sparc/Makefile.com +++ b/usr/src/lib/libc/sparc/Makefile.com @@ -583,7 +583,6 @@ PORTGEN= \ scandir.o \ seekdir.o \ select.o \ - select_large_fdset.o \ setlabel.o \ setpriority.o \ settimeofday.o \ diff --git a/usr/src/lib/libnsl/Makefile.com b/usr/src/lib/libnsl/Makefile.com index 809a7edf4a..4885156c2b 100644 --- a/usr/src/lib/libnsl/Makefile.com +++ b/usr/src/lib/libnsl/Makefile.com @@ -69,8 +69,7 @@ clnt_bcast.o clnt_dg.o clnt_door.o clnt_generic.o clnt_perror.o \ clnt_raw.o clnt_simple.o clnt_vc.o fdsync.o getdname.o \ inet_ntoa.o key_call.o key_prot.o mt_misc.o \ netname.o netnamer.o pmap_clnt.o pmap_prot.o \ -rpc_callmsg.o rpc_comdata.o rpc_comdata1.o rpc_generic.o rpc_prot.o \ -rpc_sel2poll.o \ +rpc_callmsg.o rpc_comdata.o rpc_generic.o rpc_prot.o rpc_sel2poll.o \ rpc_soc.o rpc_td.o rpcb_clnt.o rpcb_prot.o \ rpcb_st_xdr.o rpcdname.o rpcsec_gss_if.o rtime_tli.o svc.o \ svc_auth.o svc_auth_loopb.o svc_auth_sys.o svc_dg.o \ diff --git a/usr/src/lib/libnsl/rpc/rpc_comdata.c b/usr/src/lib/libnsl/rpc/rpc_comdata.c index be46323cc6..c392f661e7 100644 --- a/usr/src/lib/libnsl/rpc/rpc_comdata.c +++ b/usr/src/lib/libnsl/rpc/rpc_comdata.c @@ -33,8 +33,6 @@ * California. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "mt.h" #include @@ -44,5 +42,12 @@ */ struct opaque_auth _null_auth; fd_set svc_fdset; +#if !defined(_LP64) +/* + * This used to be how we dealt with larger than default fdsets on 32bit + * systems, the symbol is unfortunately part of the ABI. + */ +fd_set _new_svc_fdset; +#endif pollfd_t *svc_pollfd; void (*_svc_getreqset_proc)(); diff --git a/usr/src/lib/libnsl/rpc/rpc_comdata1.c b/usr/src/lib/libnsl/rpc/rpc_comdata1.c deleted file mode 100644 index ccfc8ca160..0000000000 --- a/usr/src/lib/libnsl/rpc/rpc_comdata1.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * FD_SETSIZE definition must precede any save isa_defs.h since that - * is where _LP64 is defined.... - */ -#include "mt.h" -#include -#if !defined(_LP64) -#ifdef FD_SETSIZE -#undef FD_SETSIZE -#endif -#define FD_SETSIZE 65536 - -#include - -/* - * This file should only contain common data (global data) that is exported - * by public interfaces - */ - -/* - * Definition of alternate fd_set for svc_fdset to be used when - * someone redefine SVC_FDSETSIZE. This is here solely to - * protect against someone doing a svc_fdset = a_larger_fd_set. - * If we're not a 64 bit app and someone defines fd_setsize > 1024 - * then svc_fdset is redefined to be _new_svc_fdset (in ) - * which we size here at the maximum size. - */ - -fd_set _new_svc_fdset; -#else - -#include - -extern fd_set svc_fdset; /* to avoid "empty translation unit" */ -#endif diff --git a/usr/src/lib/libnsl/rpc/svc.c b/usr/src/lib/libnsl/rpc/svc.c index c398dce732..113c76ae39 100644 --- a/usr/src/lib/libnsl/rpc/svc.c +++ b/usr/src/lib/libnsl/rpc/svc.c @@ -103,7 +103,9 @@ extern SVCXPRT_LIST *_svc_xprtlist; extern mutex_t xprtlist_lock; extern void __svc_rm_from_xlist(); +#if !defined(_LP64) extern fd_set _new_svc_fdset; +#endif /* * If the allocated array of reactor is too small, this value is used as a @@ -854,7 +856,7 @@ xprt_unregister(const SVCXPRT *xprt) */ bool_t svc_reg(const SVCXPRT *xprt, const rpcprog_t prog, const rpcvers_t vers, - void (*dispatch)(), const struct netconfig *nconf) + void (*dispatch)(), const struct netconfig *nconf) { struct svc_callout *prev; struct svc_callout *s, **s2; @@ -966,7 +968,7 @@ svc_unreg(const rpcprog_t prog, const rpcvers_t vers) */ bool_t svc_register(SVCXPRT *xprt, rpcprog_t prog, rpcvers_t vers, - void (*dispatch)(), int protocol) + void (*dispatch)(), int protocol) { struct svc_callout *prev; struct svc_callout *s; @@ -1092,7 +1094,7 @@ svc_find(rpcprog_t prog, rpcvers_t vers, struct svc_callout **prev, char *netid) */ bool_t svc_sendreply(const SVCXPRT *xprt, const xdrproc_t xdr_results, - const caddr_t xdr_location) + const caddr_t xdr_location) { struct rpc_msg rply; @@ -1227,7 +1229,7 @@ svcerr_noprog(const SVCXPRT *xprt) */ void svcerr_progvers(const SVCXPRT *xprt, const rpcvers_t low_vers, - const rpcvers_t high_vers) + const rpcvers_t high_vers) { struct rpc_msg rply; @@ -1764,7 +1766,7 @@ __svc_dupcache_init(void *condition, int basis, char **xprt_cache) */ int __svc_dup(struct svc_req *req, caddr_t *resp_buf, uint_t *resp_bufsz, - char *xprt_cache) + char *xprt_cache) { uint32_t drxid, drhash; int rc; @@ -1812,7 +1814,7 @@ __svc_dup(struct svc_req *req, caddr_t *resp_buf, uint_t *resp_bufsz, */ static int __svc_dupcache_check(struct svc_req *req, caddr_t *resp_buf, uint_t *resp_bufsz, - struct dupcache *dc, uint32_t drxid, uint32_t drhash) + struct dupcache *dc, uint32_t drxid, uint32_t drhash) { struct dupreq *dr = NULL; @@ -1971,7 +1973,7 @@ __svc_dupcache_victim(struct dupcache *dc, time_t timenow) */ static int __svc_dupcache_enter(struct svc_req *req, struct dupreq *dr, - struct dupcache *dc, uint32_t drxid, uint32_t drhash, time_t timenow) + struct dupcache *dc, uint32_t drxid, uint32_t drhash, time_t timenow) { dr->dr_xid = drxid; dr->dr_prog = req->rq_prog; @@ -2014,7 +2016,7 @@ __svc_dupcache_enter(struct svc_req *req, struct dupreq *dr, */ int __svc_dupdone(struct svc_req *req, caddr_t resp_buf, uint_t resp_bufsz, - int status, char *xprt_cache) + int status, char *xprt_cache) { uint32_t drxid, drhash; int rc; @@ -2060,7 +2062,7 @@ __svc_dupdone(struct svc_req *req, caddr_t resp_buf, uint_t resp_bufsz, */ static int __svc_dupcache_update(struct svc_req *req, caddr_t resp_buf, uint_t resp_bufsz, - int status, struct dupcache *dc, uint32_t drxid, uint32_t drhash) + int status, struct dupcache *dc, uint32_t drxid, uint32_t drhash) { struct dupreq *dr = NULL; time_t timenow = time(NULL); diff --git a/usr/src/man/man3c/select.3c b/usr/src/man/man3c/select.3c dissimilarity index 74% index 0b154856e0..2cf0538f82 100644 --- a/usr/src/man/man3c/select.3c +++ b/usr/src/man/man3c/select.3c @@ -1,414 +1,513 @@ -'\" te -.\" Copyright (c) 2004, Sun Microsystems, Inc. All Rights Reserved. Portions Copyright (c) 1992, X/Open Company Limited. All Rights Reserved. -.\" Sun Microsystems, Inc. gratefully acknowledges The Open Group for permission to reproduce portions of its copyrighted documentation. Original documentation from The Open Group can be obtained online at -.\" http://www.opengroup.org/bookstore/. -.\" The Institute of Electrical and Electronics Engineers and The Open Group, have given us permission to reprint portions of their documentation. In the following statement, the phrase "this text" refers to portions of the system documentation. Portions of this text are reprinted and reproduced in electronic form in the Sun OS Reference Manual, from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology -- Portable Operating System Interface (POSIX), The Open Group Base Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of Electrical and Electronics Engineers, Inc and The Open Group. In the event of any discrepancy between these versions and the original IEEE and The Open Group Standard, the original IEEE and The Open Group Standard is the referee document. The original Standard can be obtained online at http://www.opengroup.org/unix/online.html. -.\" This notice shall appear on any product containing this material. -.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. -.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. -.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH SELECT 3C "Nov 1, 2004" -.SH NAME -select, pselect, FD_SET, FD_CLR, FD_ISSET, FD_ZERO \- synchronous I/O -multiplexing -.SH SYNOPSIS -.LP -.nf -#include - -\fBint\fR \fBselect\fR(\fBint\fR \fInfds\fR, - \fBfd_set *restrict\fR \fIreadfds\fR, \fBfd_set *restrict\fR \fIwritefds\fR, - \fBfd_set *restrict\fR \fIerrorfds\fR, - \fBstruct timeval *restrict\fR \fItimeout\fR); -.fi - -.LP -.nf -\fBint\fR \fBpselect\fR(\fBint\fR \fInfds\fR, - \fBfd_set *restrict\fR \fIreadfds\fR, \fBfd_set *restrict\fR \fIwritefds\fR, - \fBfd_set *restrict\fR \fIerrorfds\fR, - \fBconst struct timespec *restrict\fR \fItimeout\fR, - \fBconst sigset_t *restrict\fR \fIsigmask\fR); -.fi - -.LP -.nf -\fBvoid\fR \fBFD_SET\fR(\fBint\fR \fIfd\fR, \fBfd_set *\fR\fIfdset\fR); -.fi - -.LP -.nf -\fBvoid\fR \fBFD_CLR\fR(\fBint\fR \fIfd\fR, \fBfd_set *\fR\fIfdset\fR); -.fi - -.LP -.nf -\fBint\fR \fBFD_ISSET\fR(\fBint\fR \fIfd\fR, \fBfd_set *\fR\fIfdset\fR); -.fi - -.LP -.nf -\fBvoid\fR \fBFD_ZERO\fR(\fBfd_set *\fR\fIfdset\fR); -.fi - -.SH DESCRIPTION -.sp -.LP -The \fBpselect()\fR function examines the file descriptor sets whose addresses -are passed in the \fIreadfds\fR, \fIwritefds\fR, and \fIerrorfds\fR parameters -to see if some of their descriptors are ready for reading, are ready for -writing, or have an exceptional condition pending, respectively. -.sp -.LP -The \fBselect()\fR function is equivalent to the \fBpselect()\fR function, -except as follows: -.RS +4 -.TP -.ie t \(bu -.el o -For the \fBselect()\fR function, the timeout period is given in seconds and -microseconds in an argument of type \fBstruct timeval\fR, whereas for the -\fBpselect()\fR function the timeout period is given in seconds and nanoseconds -in an argument of type \fBstruct timespec\fR. -.RE -.RS +4 -.TP -.ie t \(bu -.el o -The \fBselect()\fR function has no \fIsigmask\fR argument. It behaves as -\fBpselect()\fR does when \fIsigmask\fR is a null pointer. -.RE -.RS +4 -.TP -.ie t \(bu -.el o -Upon successful completion, the \fBselect()\fR function might modify the object -pointed to by the \fItimeout\fR argument. -.RE -.sp -.LP -The \fBselect()\fR and \fBpselect()\fR functions support regular files, -terminal and pseudo-terminal devices, STREAMS-based files, FIFOs, pipes, and -sockets. The behavior of \fBselect()\fR and \fBpselect()\fR on file descriptors -that refer to other types of file is unspecified. -.sp -.LP -The \fInfds\fR argument specifies the range of file descriptors to be tested. -The first \fInfds\fR descriptors are checked in each set; that is, the -descriptors from zero through \fInfds\fR-1 in the descriptor sets are examined. -.sp -.LP -If the \fIreadfs\fR argument is not a null pointer, it points to an object of -type \fBfd_set\fR that on input specifies the file descriptors to be checked -for being ready to read, and on output indicates which file descriptors are -ready to read. -.sp -.LP -If the \fIwritefs\fR argument is not a null pointer, it points to an object of -type \fBfd_set\fR that on input specifies the file descriptors to be checked -for being ready to write, and on output indicates which file descriptors are -ready to write. -.sp -.LP -If the \fIerrorfds\fR argument is not a null pointer, it points to an object of -type \fBfd_set\fR that on input specifies the file descriptors to be checked -for error conditions pending, and on output indicates which file descriptors -have error conditions pending. -.sp -.LP -Upon successful completion, the objects pointed to by the \fIreadfs\fR, -\fIwritefs\fR, and \fIerrorfds\fR arguments are modified to indicate which file -descriptors are ready for reading, ready for writing, or have an error -condition pending, respectively, and return the total number of ready -descriptors in all the output sets. For each file descriptor less than -\fInfds\fR, the corresponding bit will be set on successful completion if it -was set on input and the associated condition is true for that file descriptor. -.sp -.LP -If none of the selected descriptors are ready for the requested operation, the -\fBselect()\fR or \fBpselect()\fR function blocks until at least one of the -requested operations becomes ready, until the timeout occurs, or until -interrupted by a signal. The \fItimeout\fR parameter controls how long the -\fBselect()\fR or \fBpselect()\fR function takes before timing out. If the -\fItimeout\fR parameter is not a null pointer, it specifies a maximum interval -to wait for the selection to complete. If the specified time interval expires -without any requested operation becoming ready, the function returns. If the -\fItimeout\fR parameter is a null pointer, then the call to \fBselect()\fR or -\fBpselect()\fR blocks indefinitely until at least one descriptor meets the -specified criteria. To effect a poll, the \fItimeout\fR parameter should not be -a null pointer, and should point to a zero-valued \fBtimespec\fR structure. -.sp -.LP -The use of a \fItimeout\fR does not affect any pending timers set up by -\fBalarm\fR(2), \fBualarm\fR(3C), or \fBsetitimer\fR(2). -.sp -.LP -If \fIsigmask\fR is not a null pointer, then the \fBpselect()\fR function -replaces the signal mask of the process by the set of signals pointed to by -\fIsigmask\fR before examining the descriptors, and restores the signal mask of -the process before returning. -.sp -.LP -A descriptor is considered ready for reading when a call to an input function -with \fBO_NONBLOCK\fR clear would not block, whether or not the function would -transfer data successfully. (The function might return data, an end-of-file -indication, or an error other than one indicating that it is blocked, and in -each of these cases the descriptor will be considered ready for reading.) -.sp -.LP -A descriptor is considered ready for writing when a call to an output function -with \fBO_NONBLOCK\fR clear would not block, whether or not the function would -transfer data successfully. -.sp -.LP -If a socket has a pending error, it is considered to have an exceptional -condition pending. Otherwise, what constitutes an exceptional condition is file -type-specific. For a file descriptor for use with a socket, it is -protocol-specific except as noted below. For other file types, if the operation -is meaningless for a particular file type, \fBselect()\fR or \fBpselect()\fR -indicates that the descriptor is ready for read or write operations and -indicates that the descriptor has no exceptional condition pending. -.sp -.LP -If a descriptor refers to a socket, the implied input function is the -\fBrecvmsg\fR(3XNET) function with parameters requesting normal and ancillary -data, such that the presence of either type causes the socket to be marked as -readable. The presence of out-of-band data is checked if the socket option -\fBSO_OOBINLINE\fR has been enabled, as out-of-band data is enqueued with -normal data. If the socket is currently listening, then it is marked as -readable if an incoming connection request has been received, and a call to the -accept function completes without blocking. -.sp -.LP -If a descriptor refers to a socket, the implied output function is the -\fBsendmsg\fR(3XNET) function supplying an amount of normal data equal to the -current value of the \fBSO_SNDLOWAT\fR option for the socket. If a non-blocking -call to the connect function has been made for a socket, and the connection -attempt has either succeeded or failed leaving a pending error, the socket is -marked as writable. -.sp -.LP -A socket is considered to have an exceptional condition pending if a receive -operation with \fBO_NONBLOCK\fR clear for the open file description and with -the \fBMSG_OOB\fR flag set would return out-of-band data without blocking. (It -is protocol-specific whether the \fBMSG_OOB\fR flag would be used to read -out-of-band data.) A socket will also be considered to have an exceptional -condition pending if an out-of-band data mark is present in the receive queue. -.sp -.LP -A file descriptor for a socket that is listening for connections will indicate -that it is ready for reading, when connections are available. A file -descriptor for a socket that is connecting asynchronously will indicate that it -is ready for writing, when a connection has been established. -.sp -.LP -Selecting true for reading on a socket descriptor upon which a -\fBlisten\fR(3XNET) call has been performed indicates that a subsequent -\fBaccept\fR(3XNET) call on that descriptor will not block. -.sp -.LP -If the \fItimeout\fR argument is not a null pointer, it points to an object of -type \fBstruct timeval\fR that specifies a maximum interval to wait for the -selection to complete. If the \fItimeout\fR argument points to an object of -type \fBstruct timeval\fR whose members are 0, \fBselect()\fR does not block. -If the \fItimeout\fR argument is a null pointer, \fBselect()\fR blocks until an -event causes one of the masks to be returned with a valid (non-zero) value. If -the time limit expires before any event occurs that would cause one of the -masks to be set to a non-zero value, \fBselect()\fR completes successfully and -returns 0. -.sp -.LP -If the \fIreadfs\fR, \fIwritefs\fR, and \fIerrorfds\fR arguments are all null -pointers and the \fItimeout\fR argument is not a null pointer, \fBselect()\fR -or \fBpselect()\fR blocks for the time specified, or until interrupted by a -signal. If the \fIreadfs\fR, \fIwritefs\fR, and \fIerrorfds\fR arguments are -all null pointers and the \fItimeout\fR argument is a null pointer, -\fBselect()\fR blocks until interrupted by a signal. -.sp -.LP -File descriptors associated with regular files always select true for ready to -read, ready to write, and error conditions. -.sp -.LP -On failure, the objects pointed to by the \fIreadfs\fR, \fIwritefs\fR, and -\fIerrorfds\fR arguments are not modified. If the timeout interval expires -without the specified condition being true for any of the specified file -descriptors, the objects pointed to by the \fIreadfs\fR, \fIwritefs\fR, and -\fIerrorfds\fR arguments have all bits set to 0. -.sp -.LP -File descriptor masks of type \fBfd_set\fR can be initialized and tested with -the macros \fBFD_CLR()\fR, \fBFD_ISSET()\fR, \fBFD_SET()\fR, and -\fBFD_ZERO()\fR. -.sp -.ne 2 -.na -\fB\fBFD_CLR\fR(\fIfd\fR, &\fIfdset\fR)\fR -.ad -.RS 24n -Clears the bit for the file descriptor \fIfd\fR in the file descriptor set -\fIfdset\fR. -.RE - -.sp -.ne 2 -.na -\fB\fBFD_ISSET\fR(\fIfd\fR, &\fIfdset\fR)\fR -.ad -.RS 24n -Returns a non-zero value if the bit for the file descriptor \fIfd\fR is set in -the file descriptor set pointed to by \fIfdset\fR, and 0 otherwise. -.RE - -.sp -.ne 2 -.na -\fB\fBFD_SET\fR(\fIfd\fR, &\fIfdset\fR)\fR -.ad -.RS 24n -Sets the bit for the file descriptor \fIfd\fR in the file descriptor set -\fIfdset\fR. -.RE - -.sp -.ne 2 -.na -\fB\fBFD_ZERO\fR(&\fIfdset\fR)\fR -.ad -.RS 24n -Initializes the file descriptor set \fIfdset\fR to have zero bits for all file -descriptors. -.RE - -.sp -.LP -The behavior of these macros is undefined if the \fIfd\fR argument is less than -0 or greater than or equal to \fBFD_SETSIZE\fR, or if \fIfd\fR is not a valid -file descriptor, or if any of the arguments are expressions with side effects. -.SH RETURN VALUES -.sp -.LP -On successful completion, \fBselect()\fR and \fBpselect()\fR return the total -number of bits set in the bit masks. Otherwise, \fB\(mi1\fR is returned and -\fBerrno\fR is set to indicate the error. -.sp -.LP -The \fBFD_CLR()\fR, \fBFD_SET()\fR, and \fBFD_ZERO()\fR macros return no value. -The \fBFD_ISSET()\fR macro returns a non-zero value if the bit for the file -descriptor \fIfd\fR is set in the file descriptor set pointed to by -\fIfdset\fR, and \fB0\fR otherwise. -.SH ERRORS -.sp -.LP -The \fBselect()\fR and \fBpselect()\fR functions will fail if: -.sp -.ne 2 -.na -\fB\fBEBADF\fR\fR -.ad -.RS 10n -One or more of the file descriptor sets specified a file descriptor that is not -a valid open file descriptor. -.RE - -.sp -.ne 2 -.na -\fB\fBEINTR\fR\fR -.ad -.RS 10n -The function was interrupted before any of the selected events occurred and -before the timeout interval expired. -.sp -If \fBSA_RESTART\fR has been set for the interrupting signal, it is -implementation-dependent whether \fBselect()\fR restarts or returns with -\fBEINTR\fR. -.RE - -.sp -.ne 2 -.na -\fB\fBEINVAL\fR\fR -.ad -.RS 10n -An invalid timeout interval was specified. -.RE - -.sp -.ne 2 -.na -\fB\fBEINVAL\fR\fR -.ad -.RS 10n -The \fInfds\fR argument is less than 0 or greater than \fBFD_SETSIZE\fR. -.RE - -.sp -.ne 2 -.na -\fB\fBEINVAL\fR\fR -.ad -.RS 10n -One of the specified file descriptors refers to a STREAM or multiplexer that is -linked (directly or indirectly) downstream from a multiplexer. -.RE - -.sp -.ne 2 -.na -\fB\fBEINVAL\fR\fR -.ad -.RS 10n -A component of the pointed-to time limit is outside the acceptable range: -\fBt_sec\fR must be between \fB0\fR and 10^8, inclusive. \fBt_usec\fR must be -greater than or equal to \fB0\fR, and less than 10^6. -.RE - -.SH USAGE -.sp -.LP -The \fBpoll\fR(2) function is preferred over this function. It must be used -when the number of file descriptors exceeds \fBFD_SETSIZE\fR. -.sp -.LP -The use of a timeout does not affect any pending timers set up by -\fBalarm\fR(2), \fBualarm\fR(3C) or \fBsetitimer\fR(2). -.sp -.LP -On successful completion, the object pointed to by the \fItimeout\fR argument -may be modified. -.SH ATTRIBUTES -.sp -.LP -See \fBattributes\fR(5) for descriptions of the following attributes: -.sp - -.sp -.TS -box; -c | c -l | l . -ATTRIBUTE TYPE ATTRIBUTE VALUE -_ -Interface Stability Standard -_ -MT-Level MT-Safe -.TE - -.SH SEE ALSO -.sp -.LP -\fBalarm\fR(2), \fBfcntl\fR(2), \fBpoll\fR(2), \fBread\fR(2), -\fBsetitimer\fR(2), \fBwrite\fR(2), \fBaccept\fR(3SOCKET), -\fBlisten\fR(3SOCKET), \fBualarm\fR(3C), \fBattributes\fR(5), -\fBstandards\fR(5) -.SH NOTES -.sp -.LP -The default value for \fBFD_SETSIZE\fR (currently 1024) is larger than the -default limit on the number of open files. To accommodate 32-bit applications -that wish to use a larger number of open files with \fBselect()\fR, it is -possible to increase this size at compile time by providing a larger definition -of \fBFD_SETSIZE\fR before the inclusion of any system-supplied header. The -maximum supported size for \fBFD_SETSIZE\fR is 65536. The default value is -already 65536 for 64-bit applications. +.\" Copyright (c) 2004, Sun Microsystems, Inc. All Rights Reserved. +.\" Portions Copyright (c) 1992, X/Open Company Limited. All Rights +.\" Reserved. +.\" +.\" Sun Microsystems, Inc. gratefully acknowledges The Open +.\" Group for permission to reproduce portions of its copyrighted +.\" documentation. Original documentation from The Open Group can be +.\" obtained online at http://www.opengroup.org/bookstore/. The Institute +.\" of Electrical and Electronics Engineers and The Open Group, have given +.\" us permission to reprint portions of their documentation. In the +.\" following statement, the phrase "this text" refers to portions of the +.\" system documentation. Portions of this text are reprinted and +.\" reproduced in electronic form in the Sun OS Reference Manual, from +.\" IEEE Std 1003.1, 2004 Edition, Standard for Information Technology -- +.\" Portable Operating System Interface (POSIX), The Open Group Base +.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of +.\" Electrical and Electronics Engineers, Inc and The Open Group. In the +.\" event of any discrepancy between these versions and the original IEEE +.\" and The Open Group Standard, the original IEEE and The Open Group +.\" Standard is the referee document. The original Standard can be +.\" obtained online at http://www.opengroup.org/unix/online.html. +.\" +.\" This notice shall appear on any product containing this material. +.\" +.\" CDDL HEADER START +.\" +.\" The contents of this file are subject to the terms of the +.\" Common Development and Distribution License (the "License"). +.\" You may not use this file except in compliance with the License. +.\" +.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +.\" or http://www.opensolaris.org/os/licensing. +.\" See the License for the specific language governing permissions +.\" and limitations under the License. +.\" +.\" When distributing Covered Code, include this CDDL HEADER in each +.\" file and include the License file at usr/src/OPENSOLARIS.LICENSE. +.\" If applicable, add the following below this CDDL HEADER, with the +.\" fields enclosed by brackets "[]" replaced with your own identifying +.\" information: Portions Copyright [yyyy] [name of copyright owner] +.\" +.\" CDDL HEADER END +.\" +.Dd "Dec 28, 2016" +.Dt SELECT 3C +.Os +.Sh NAME +.Nm select , +.Nm pselect , +.Nm FD_SET , +.Nm FD_CLR , +.Nm FD_ISSET , +.Nm FD_ZERO +.Nd synchronous I/O multiplexing +.Sh SYNOPSIS +.In sys/time.h +.Ft int +.Fo select +.Fa "int nfds" +.Fa "fd_set *restrict readfds" +.Fa "fd_set *restrict writefds" +.Fa "fd_set *restrict errorfds" +.Fa "struct timeval *restrict timeout" +.Fc +.Ft int +.Fo pselect +.Fa "int nfds" +.Fa "fd_set *restrict readfds" +.Fa "fd_set *restrict writefds" +.Fa "fd_set *restrict errorfds" +.Fa "const struct timespec *restrict timeout" +.Fa "const sigset_t *restrict sigmask" +.Fc +.Ft void +.Fo FD_SET +.Fa "int fd" +.Fa "fd_set *fdset" +.Fc +.Ft void +.Fo FD_CLR +.Fa "int fd" +.Fa "fd_set *fdset" +.Fc +.Ft int +.Fo FD_ISSET +.Fa "int fd" +.Fa "fd_set *fd_set" +.Fc +.Ft void +.Fo FD_ZERO +.Fa "fd_set *fdset" +.Fc +.Sh DESCRIPTION +The +.Fn pselect +function examines the file descriptor sets whose addresses +are passed in the +.Fa readfds , +.Fa writefds , +and +.Fa errorfds +parameters to see if some of their descriptors are ready for reading, +are ready for writing, or have an exceptional condition pending, +respectively. +.Pp +The +.Fn select +function is equivalent to the +.Fn pselect +function, except as follows: +.Bl -bullet +.It +For the +.Fn select +function, the timeout period is given in seconds and +microseconds in an argument of type +.Vt struct timeval , +whereas for the +.Fn pselect +function the timeout period is given in seconds and nanoseconds +in an argument of type +.Vt struct timespec +.It +The +.Fn select +function has no +.Fa sigmask +argument. It behaves as +.Fn pselect +does when +.Fa sigmask +is a null pointer. +.It +Upon successful completion, the +.Fn select +function might modify the object pointed to by the +.Fa Itimeout +argument. +.El +.Pp +The +.Fn select +and +.Fn pselect +functions support regular files, +terminal and pseudo-terminal devices, STREAMS-based files, FIFOs, pipes, and +sockets. The behavior of +.Fn select +and +.Fn pselect +on file descriptors that refer to other types of file is unspecified. +.Pp +The +.Fa nfds +argument specifies the range of file descriptors to be tested. +The first +.Fa nfds +descriptors are checked in each set; that is, the +descriptors from zero through +.Dq Li nfds - 1 +in the descriptor sets are examined. +.Pp +If the +.Fa readfs +argument is not a null pointer, it points to an object of +type +.Vt fd_set +that on input specifies the file descriptors to be checked +for being ready to read, and on output indicates which file descriptors are +ready to read. +.Pp +If the +.Fa writefs +argument is not a null pointer, it points to an object of +type +.Vt fd_set +that on input specifies the file descriptors to be checked +for being ready to write, and on output indicates which file descriptors are +ready to write. +.Pp +If the +.Fa errorfds +argument is not a null pointer, it points to an object of +type +.Vt fd_set +that on input specifies the file descriptors to be checked +for error conditions pending, and on output indicates which file descriptors +have error conditions pending. +.Pp +Upon successful completion, the objects pointed to by the +.Fa readfs , +.Fa writefs , +and +.Fa errorfds +arguments are modified to indicate which file +descriptors are ready for reading, ready for writing, or have an error +condition pending, respectively, and return the total number of ready +descriptors in all the output sets. For each file descriptor less than +.Fa nfds , +the corresponding bit will be set on successful completion if it +was set on input and the associated condition is true for that file descriptor. +.Pp +If none of the selected descriptors are ready for the requested operation, the +.Fn select +or +.Fn pselect +function blocks until at least one of the +requested operations becomes ready, until the timeout occurs, or until +interrupted by a signal. The +.Fa timeout +parameter controls how long the +.Fn select +or +.Fn pselect +function takes before timing out. If the +.Fa timeout +parameter is not a null pointer, it specifies a maximum interval +to wait for the selection to complete. If the specified time interval expires +without any requested operation becoming ready, the function returns. If the +.Fa timeout +parameter is a null pointer, then the call to +.Fn select +or +.Fn pselect +blocks indefinitely until at least one descriptor meets the +specified criteria. To effect a poll, the +.Fa timeout +parameter should not be a null pointer, and should point to a zero-valued +.Vt timespec +structure. +.Pp +The use of a +.Fa timeout +does not affect any pending timers set up by +.Xr alarm 2 , +.Xr ualarm 3C , +or +.Xr setitimer 2 . +.Pp +If +.Fa sigmask +is not a null pointer, then the +.Fn pselect +function replaces the signal mask of the process by the set of signals pointed +to by +.Fa sigmask +before examining the descriptors, and restores the signal mask of +the process before returning. +.Pp +A descriptor is considered ready for reading when a call to an input function +with +.Dv O_NONBLOCK +clear would not block, whether or not the function would +transfer data successfully. (The function might return data, an end-of-file +indication, or an error other than one indicating that it is blocked, and in +each of these cases the descriptor will be considered ready for reading.) +.Pp +A descriptor is considered ready for writing when a call to an output function +with +.Dv O_NONBLOCK +clear would not block, whether or not the function would +transfer data successfully. +.Pp +If a socket has a pending error, it is considered to have an exceptional +condition pending. Otherwise, what constitutes an exceptional condition is file +type-specific. For a file descriptor for use with a socket, it is +protocol-specific except as noted below. For other file types, if the operation +is meaningless for a particular file type, +.Fn select +or +.Fn pselect +indicates that the descriptor is ready for read or write operations and +indicates that the descriptor has no exceptional condition pending. +.Pp +If a descriptor refers to a socket, the implied input function is the +.Xr recvmsg 3XNET +function with parameters requesting normal and ancillary +data, such that the presence of either type causes the socket to be marked as +readable. The presence of out-of-band data is checked if the socket option +.Dv SO_OOBINLINE +has been enabled, as out-of-band data is enqueued with +normal data. If the socket is currently listening, then it is marked as +readable if an incoming connection request has been received, and a call to the +accept function completes without blocking. +.Pp +If a descriptor refers to a socket, the implied output function is the +.Xr sendmsg 3XNET +function supplying an amount of normal data equal to the +current value of the +.Dv SO_SNDLOWAT +option for the socket. If a non-blocking +call to the connect function has been made for a socket, and the connection +attempt has either succeeded or failed leaving a pending error, the socket is +marked as writable. +.Pp +A socket is considered to have an exceptional condition pending if a receive +operation with +.Dv O_NONBLOCK +clear for the open file description and with the +.Dv MSG_OOB +flag set would return out-of-band data without blocking. (It +is protocol-specific whether the +.Dv MSG_OOB +flag would be used to read out-of-band data.) A socket will also be considered +to have an exceptional condition pending if an out-of-band data mark is +present in the receive queue. +.Pp +A file descriptor for a socket that is listening for connections will indicate +that it is ready for reading, when connections are available. A file +descriptor for a socket that is connecting asynchronously will indicate that it +is ready for writing, when a connection has been established. +.Pp +Selecting true for reading on a socket descriptor upon which a +.Xr listen 3XNET +call has been performed indicates that a subsequent +.Xr accept 3XNET +call on that descriptor will not block. +.Pp +If the +.Fa timeout +argument is not a null pointer, it points to an object of type +.Vt struct timeval +that specifies a maximum interval to wait for the +selection to complete. If the \fItimeout\fR argument points to an object of +type +.Vt struct timeval +whose members are 0, +.Fn select +does not block. +If the +.Fa timeout +argument is a null pointer, +.Fn select +blocks until an event causes one of the masks to be returned with a valid +(non-zero) value. If the time limit expires before any event occurs that +would cause one of the masks to be set to a non-zero value, +.Fn select +completes successfully and returns 0. +.Pp +If the +.Fa readfs , +.Fa writefds , +and +.Fa errorfds +arguments are all null pointers and the +.Fa timeout +argument is not a null pointer, +.Fn select +or +.Fn pselect +blocks for the time specified, or until interrupted by a +signal. If the +.Fa readfds , +.Fa writefds , +and +.Fa errorfds +arguments are all null pointers and the +.Fa timeout +argument is a null pointer, +.Fn select +blocks until interrupted by a signal. +.Pp +File descriptors associated with regular files always select true for ready to +read, ready to write, and error conditions. +.Pp +On failure, the objects pointed to by the +.Fa readfds , +.Fa writefds , +and +.Fa errorfds +arguments are not modified. If the timeout interval expires +without the specified condition being true for any of the specified file +descriptors, the objects pointed to by the +.Fa readfds , +.Fa writefds , +and +.Fa errorfds +arguments have all bits set to 0. +.Pp +File descriptor masks of type +.Vt fd_set +can be initialized and tested with the macros +.Fn FD_CLR , +.Fn FD_ISSET , +.Fn FD_SET , +and +.Fn FD_ZERO . +.Bl -tag -width indent +.It Fn FD_CLR "fd" "&fdset" +Clears the bit for the file descriptor +.Fa fd +in the file descriptor set +.Fa fdset . +.It Fn FD_ISSET "fd" "&fdset" +Returns a non-zero value if the bit for the file descriptor +.Fa fd +is set in +the file descriptor set pointed to by +.Fa fdset , +and 0 otherwise. +.It Fn FD_SET "fd" "&fdset" +Sets the bit for the file descriptor +.Fa fd +in the file descriptor set +.Fa fdset +.It Fn FD_ZERO "&fdset" +Initializes the file descriptor set \fIfdset\fR to have zero bits for all file +descriptors. +.El +.Pp +The behavior of these macros is undefined if the +.Fa fd +argument is less than 0 or greater than or equal to +.Dv FD_SETSIZE , +or if +.Fa fd +is not a valid file descriptor, or if any of the arguments are expressions +with side effects. +.Sh RETURN VALUES +On successful completion, +.Fn select +and +.Fn pselect +return the total +number of bits set in the bit masks. Otherwise, +.Sy 1 +is returned and +.Dv errno +is set to indicate the error. +.Pp +The +.Fn FD_CLR , +.Fn FD_SET , +and +.Fn FD_ZERO , +macros return no value. +The +.Fn FD_ISSET +macro returns a non-zero value if the bit for the file +descriptor +.Fa fd +is set in the file descriptor set pointed to by +.Fa fdset , +and +.Sy 0 +otherwise. +.Sh ERRORS +The +.Fn select +and +.Fn pselect +functions will fail if: +.Bl -tag -width indent +.It Er EBADF +One or more of the file descriptor sets specified a file descriptor that is not +a valid open file descriptor. +.It Er EINTR +The function was interrupted before any of the selected events occurred and +before the timeout interval expired. +.Pp +If +.Dv SA_RESTART +has been set for the interrupting signal, it is implementation-dependent whether +.Fn select +restarts or returns with +.Dv EINTR +.It Er EINVAL +An invalid timeout interval was specified. +.It Er EINVAL +The +.Fa nfds +argument is less than 0 or greater than +.Dv FD_SETSIZE . +.It Er EINVAL +One of the specified file descriptors refers to a STREAM or multiplexer that is +linked (directly or indirectly) downstream from a multiplexer. +.It Er EINVAL +A component of the pointed-to time limit is outside the acceptable range: +.Dv t_sec +must be between 0 and 10^8, inclusive. +.Dv t_usec +must be greater than or equal to 0, and less than 10^6. +.El +.Sh USAGE +The +.Xr poll 2 +function is preferred over this function. +.Pp +The use of a timeout does not affect any pending timers set up by +.Xr alarm 2 , +.Xr ualarm 3C , +or +.Xr setitimer 2 . +.Pp +On successful completion, the object pointed to by the +.Fa timeout +argument may be modified. +.Sh INTERFACE STABILITY +.Sy Standard +.Sh MT Level +.Sy MT-Safe +.Sh SEE ALSO +.Xr alarm 2 , +.Xr fcntl 2 , +.Xr poll 2 , +.Xr read 2 , +.Xr setitimer 2 , +.Xr write 2 , +.Xr ualarm 3C , +.Xr accept 3SOCKET , +.Xr listen 3SOCKET , +.Xr attributes 5 , +.Xr standards 5 diff --git a/usr/src/pkg/manifests/system-test-libctest.mf b/usr/src/pkg/manifests/system-test-libctest.mf index db39430af6..3412500cff 100644 --- a/usr/src/pkg/manifests/system-test-libctest.mf +++ b/usr/src/pkg/manifests/system-test-libctest.mf @@ -28,6 +28,7 @@ dir path=opt/libc-tests/cfg/symbols dir path=opt/libc-tests/runfiles dir path=opt/libc-tests/tests dir path=opt/libc-tests/tests/random +dir path=opt/libc-tests/tests/select dir path=opt/libc-tests/tests/symbols dir path=usr group=sys dir path=usr/lib @@ -119,6 +120,8 @@ file path=opt/libc-tests/tests/random/inz_region mode=0555 file path=opt/libc-tests/tests/random/inz_split mode=0555 file path=opt/libc-tests/tests/random/inz_split_vpp mode=0555 file path=opt/libc-tests/tests/random/inz_vpp mode=0555 +file path=opt/libc-tests/tests/select/select.sh mode=0555 +file path=opt/libc-tests/tests/select/select_test mode=0555 file path=opt/libc-tests/tests/strerror mode=0555 file path=opt/libc-tests/tests/symbols/setup mode=0555 file path=opt/libc-tests/tests/symbols/symbols_test.$(ARCH) mode=0555 diff --git a/usr/src/test/libc-tests/runfiles/default.run b/usr/src/test/libc-tests/runfiles/default.run index baff3372da..9ac4e183cd 100644 --- a/usr/src/test/libc-tests/runfiles/default.run +++ b/usr/src/test/libc-tests/runfiles/default.run @@ -54,6 +54,9 @@ outputdir = /var/tmp/test_results [/opt/libc-tests/tests/random/arc4random_preforksig] [/opt/libc-tests/tests/random/arc4key.ksh] +[/opt/libc-tests/tests/select/select.sh] +timeout = 600 + [/opt/libc-tests/tests/aligned_alloc.32] [/opt/libc-tests/tests/aligned_alloc.64] [/opt/libc-tests/tests/c11_threads.32] diff --git a/usr/src/test/libc-tests/tests/Makefile b/usr/src/test/libc-tests/tests/Makefile index a259d28c89..586ac08383 100644 --- a/usr/src/test/libc-tests/tests/Makefile +++ b/usr/src/test/libc-tests/tests/Makefile @@ -22,6 +22,7 @@ SUBDIRS = \ nl_langinfo \ priv_gettext \ random \ + select \ strerror \ symbols \ threads \ diff --git a/usr/src/test/libc-tests/tests/select/Makefile b/usr/src/test/libc-tests/tests/select/Makefile new file mode 100644 index 0000000000..d7d6fa7641 --- /dev/null +++ b/usr/src/test/libc-tests/tests/select/Makefile @@ -0,0 +1,64 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# Copyright 2016, Richard Lowe. + +include $(SRC)/Makefile.master +include $(SRC)/Makefile.master.64 +include $(SRC)/cmd/Makefile.cmd +include $(SRC)/cmd/Makefile.cmd.64 + +ROOTOPTPKG = $(ROOT)/opt/libc-tests +TESTDIR = $(ROOTOPTPKG)/tests/select +ROOTBINDIR = $(ROOTOPTPKG)/bin + +PROGS= select_test + +C99MODE= $(C99_ENABLE) + +select_test: select_test.c + $(LINK64.c) -o $@ select_test.c $(LDLIBS64) + $(POST_PROCESS) + +SCRIPTS=select.sh +CMDS = $(PROGS:%=$(TESTDIR)/%) $(SCRIPTS:%=$(TESTDIR)/%) + +$(SCRIPTS) $(CMDS) := FILEMODE = 0555 + +$(CMDS): $(TESTDIR) $(PROGS) + +all: $(PROGS) + +clean: + +clobber: clean + -$(RM) $(PROGS) + +install: all $(CMDS) + +lint: + +$(ROOTBINDIR): + $(INS.dir) + +$(ROOTBINDIR)/%: % + $(INS.file) + +$(TESTDIR): + $(INS.dir) + +$(TESTDIR)/%: % + $(INS.file) + +$(TESTDIR)/%: % + $(INS.file) + +.KEEP_STATE: diff --git a/usr/src/test/libc-tests/tests/select/select.sh b/usr/src/test/libc-tests/tests/select/select.sh new file mode 100644 index 0000000000..f0bd25c68f --- /dev/null +++ b/usr/src/test/libc-tests/tests/select/select.sh @@ -0,0 +1,41 @@ +#! /usr/bin/sh +# +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# Copyright 2016, Richard Lowe. + +select_test=$(dirname $0)/select_test + + +# Below the stack and bulk alloc limits +i=0 +while (( $i < 500 )); do + i=$(($i + 1)) + + $select_test 512 || exit 1 +done; + +# above the stack limit +i=0 +while (( $i < 500 )); do + i=$(($i + 1)) + + $select_test 2048 || exit 1 +done; + +# above the bulk limit +i=0 +while (( $i < 500 )); do + i=$(($i + 1)) + + $select_test 9001 || exit 1 +done; diff --git a/usr/src/test/libc-tests/tests/select/select_test.c b/usr/src/test/libc-tests/tests/select/select_test.c new file mode 100644 index 0000000000..f6af3718cb --- /dev/null +++ b/usr/src/test/libc-tests/tests/select/select_test.c @@ -0,0 +1,126 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* Copyright 2016, Richard Lowe. */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +void +diff_sets(fd_set *a, fd_set *b, size_t size) +{ + for (int i = 0; i < size; i++) { + if (FD_ISSET(i, a) != FD_ISSET(i, b)) + printf("fd %d: %d should be %d\n", i, FD_ISSET(i, a), + FD_ISSET(i, b)); + } +} + +void +print_set(fd_set *a, size_t size) +{ + for (int i = 0; i < size; i++) { + if (FD_ISSET(i, a)) + putc('1', stdout); + else + putc('0', stdout); + } + + putc('\n', stdout); +} + +int +main(int argc, char **argv) +{ + struct timeval tv = {0, 0}; + fd_set check, proto; + fd_set *sread = NULL, *swrite = NULL, *serr = NULL; + int null, zero, maxfd = -1, nfds; + char buf[1]; + + if (argc != 2) + errx(1, "usage: select_test "); + + nfds = atoi(argv[1]); + if (errno != 0) + err(1, "couldn't convert %s to int", argv[1]); + + if (nfds > FD_SETSIZE) + errx(1, "can't have more fds than FD_SETSIZE %d", FD_SETSIZE); + + FD_ZERO(&proto); + FD_ZERO(&check); + + switch (arc4random_uniform(3)) { + case 0: + sread = ✓ + break; + case 1: + swrite = ✓ + break; + case 2: + serr = ✓ + break; + } + + closefrom(3); + + if ((null = open("/dev/null", O_RDONLY)) == -1) + err(1, "couldn't open /dev/null"); + read(null, &buf, 1); + read(null, &buf, 1); + + if ((zero = open("/dev/zero", O_RDWR)) == -1) + err(1, "couldn't open /dev/zero"); + + for (int i = zero; i < (zero + nfds); i++) { + int fd = (serr != NULL) ? null : zero; + if (arc4random_uniform(100) > 90) { + FD_SET(i, &proto); + } + + if (dup2(fd, i) == -1) + err(1, "couldn't dup fd to fd %d", i); + maxfd = i; + } + + if (swrite != NULL) + puts("write"); + else if (sread != NULL) + puts("read"); + else if (serr != NULL) + puts("err"); + + print_set(&proto, 80); + + memcpy(&check, &proto, sizeof (check)); + + if (select(maxfd + 1, sread, swrite, serr, &tv) == -1) + err(1, "select failed"); + + if (memcmp(&check, &proto, sizeof (check)) != 0) { + diff_sets(&check, &proto, sizeof (check)); + warnx("fd set mismatch: check: %p proto: %p", &check, &proto); + abort(); + } + + return (0); +} diff --git a/usr/src/uts/common/conf/param.c b/usr/src/uts/common/conf/param.c index 6b3ba51f31..64227a3998 100644 --- a/usr/src/uts/common/conf/param.c +++ b/usr/src/uts/common/conf/param.c @@ -404,10 +404,10 @@ int nexectype = sizeof (execsw) / sizeof (execsw[0]); /* # of exec types */ kmutex_t execsw_lock; /* Used for allocation of execsw entries */ /* - * symbols added to make changing max-file-descriptors + * symbols added to make changing proc.max-file-descriptor * simple via /etc/system */ -#define RLIM_FD_CUR 0x100 +#define RLIM_FD_CUR 0x10000 #define RLIM_FD_MAX 0x10000 uint_t rlim_fd_cur = RLIM_FD_CUR; diff --git a/usr/src/uts/common/rpc/svc.h b/usr/src/uts/common/rpc/svc.h index 134b690a3f..f7f8df05db 100644 --- a/usr/src/uts/common/rpc/svc.h +++ b/usr/src/uts/common/rpc/svc.h @@ -852,14 +852,6 @@ extern void rpc_gss_cleanup(SVCXPRT *); extern pollfd_t *svc_pollfd; extern int svc_max_pollfd; extern fd_set svc_fdset; -#if !defined(_LP64) && FD_SETSIZE > 1024 -extern fd_set _new_svc_fdset; -#ifdef __PRAGMA_REDEFINE_EXTNAME -#pragma redefine_extname svc_fdset _new_svc_fdset -#else /* __PRAGMA_REDEFINE_EXTNAME */ -#define svc_fdset _new_svc_fdset -#endif /* __PRAGMA_REDEFINE_EXTNAME */ -#endif /* LP64 && FD_SETSIZE > 1024 */ #define svc_fds svc_fdset.fds_bits[0] /* compatibility */ /* diff --git a/usr/src/uts/common/sys/select.h b/usr/src/uts/common/sys/select.h index aa6ef3185e..e4dd11968d 100644 --- a/usr/src/uts/common/sys/select.h +++ b/usr/src/uts/common/sys/select.h @@ -82,26 +82,10 @@ typedef struct { /* signal set type */ * Select uses bit masks of file descriptors in longs. * These macros manipulate such bit fields. * FD_SETSIZE may be defined by the user, but the default here - * should be >= NOFILE (param.h). + * should be >= RLIM_FD_MAX. */ #ifndef FD_SETSIZE -#ifdef _LP64 #define FD_SETSIZE 65536 -#else -#define FD_SETSIZE 1024 -#endif /* _LP64 */ -#elif FD_SETSIZE > 1024 && !defined(_LP64) -#ifdef __PRAGMA_REDEFINE_EXTNAME -#pragma redefine_extname select select_large_fdset -#if !defined(__XOPEN_OR_POSIX) || defined(_XPG6) || defined(__EXTENSIONS__) -#pragma redefine_extname pselect pselect_large_fdset -#endif -#else /* __PRAGMA_REDEFINE_EXTNAME */ -#define select select_large_fdset -#if !defined(__XOPEN_OR_POSIX) || defined(_XPG6) || defined(__EXTENSIONS__) -#define pselect pselect_large_fdset -#endif -#endif /* __PRAGMA_REDEFINE_EXTNAME */ #endif /* FD_SETSIZE */ #if !defined(_XPG4_2) || defined(__EXTENSIONS__) -- 2.11.4.GIT