Module Name: src Committed By: christos Date: Fri Nov 6 19:34:14 UTC 2015
Modified Files: src/lib/libc/rpc: Makefile.inc svc.c svc_fdset.c svc_fdset.h svc_run.c svc_vc.c Log Message: - Provide multi-threaded fdset's for everyone not just rump if requested. - Abstract fd_set access, and don't limit the fd_set size. - Maintain binary compatibility by keeping the old global variables around. To generate a diff of this commit: cvs rdiff -u -r1.22 -r1.23 src/lib/libc/rpc/Makefile.inc \ src/lib/libc/rpc/svc_run.c cvs rdiff -u -r1.34 -r1.35 src/lib/libc/rpc/svc.c cvs rdiff -u -r1.1 -r1.2 src/lib/libc/rpc/svc_fdset.c \ src/lib/libc/rpc/svc_fdset.h cvs rdiff -u -r1.30 -r1.31 src/lib/libc/rpc/svc_vc.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libc/rpc/Makefile.inc diff -u src/lib/libc/rpc/Makefile.inc:1.22 src/lib/libc/rpc/Makefile.inc:1.23 --- src/lib/libc/rpc/Makefile.inc:1.22 Wed Apr 15 15:13:47 2015 +++ src/lib/libc/rpc/Makefile.inc Fri Nov 6 14:34:13 2015 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile.inc,v 1.22 2015/04/15 19:13:47 mrg Exp $ +# $NetBSD: Makefile.inc,v 1.23 2015/11/06 19:34:13 christos Exp $ # librpc sources .PATH: ${.CURDIR}/rpc @@ -12,7 +12,7 @@ SRCS+= auth_none.c auth_unix.c authunix_ pmap_prot2.c pmap_rmt.c rpc_prot.c rpc_commondata.c rpc_callmsg.c \ rpc_generic.c rpc_soc.c rpcb_clnt.c rpcb_prot.c rpcb_st_xdr.c \ svc.c svc_auth.c svc_dg.c svc_auth_unix.c svc_generic.c svc_raw.c \ - svc_run.c svc_simple.c svc_vc.c \ + svc_run.c svc_simple.c svc_vc.c svc_fdset.c \ xdr.c xdr_array.c xdr_float.c xdr_mem.c xdr_rec.c xdr_reference.c \ xdr_stdio.c xdr_sizeof.c __rpc_getxid.c Index: src/lib/libc/rpc/svc_run.c diff -u src/lib/libc/rpc/svc_run.c:1.22 src/lib/libc/rpc/svc_run.c:1.23 --- src/lib/libc/rpc/svc_run.c:1.22 Mon Mar 11 16:19:29 2013 +++ src/lib/libc/rpc/svc_run.c Fri Nov 6 14:34:13 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: svc_run.c,v 1.22 2013/03/11 20:19:29 tron Exp $ */ +/* $NetBSD: svc_run.c,v 1.23 2015/11/06 19:34:13 christos Exp $ */ /* * Copyright (c) 2010, Oracle America, Inc. @@ -37,7 +37,7 @@ static char *sccsid = "@(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro"; static char *sccsid = "@(#)svc_run.c 2.1 88/07/29 4.0 RPCSRC"; #else -__RCSID("$NetBSD: svc_run.c,v 1.22 2013/03/11 20:19:29 tron Exp $"); +__RCSID("$NetBSD: svc_run.c,v 1.23 2015/11/06 19:34:13 christos Exp $"); #endif #endif @@ -50,6 +50,7 @@ __RCSID("$NetBSD: svc_run.c,v 1.22 2013/ #include <err.h> #include <errno.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <unistd.h> @@ -66,9 +67,9 @@ __weak_alias(svc_exit,_svc_exit) void svc_run(void) { - fd_set readfds, cleanfds; + fd_set *readfds, *cleanfds; struct timeval timeout; - int maxfd; + int maxfd, fdsize; #ifndef RUMP_RPC int probs = 0; #endif @@ -76,16 +77,24 @@ svc_run(void) extern rwlock_t svc_fd_lock; #endif + readfds = NULL; + cleanfds = NULL; + fdsize = 0; timeout.tv_sec = 30; timeout.tv_usec = 0; for (;;) { rwlock_rdlock(&svc_fd_lock); - readfds = *get_fdset(); - cleanfds = *get_fdset(); - maxfd = *get_fdsetmax(); + if (fdsize != svc_fdset_getsize(0)) { + fdsize = svc_fdset_getsize(0); + free(readfds); + readfds = svc_fdset_copy(svc_fdset_get()); + free(cleanfds); + cleanfds = svc_fdset_copy(svc_fdset_get()); + } + maxfd = *svc_fdset_getmax(); rwlock_unlock(&svc_fd_lock); - switch (select(maxfd + 1, &readfds, NULL, NULL, &timeout)) { + switch (select(maxfd + 1, readfds, NULL, NULL, &timeout)) { case -1: #ifndef RUMP_RPC if ((errno == EINTR || errno == EBADF) && probs < 100) { @@ -97,17 +106,20 @@ svc_run(void) continue; } warn("%s: select failed", __func__); - return; + goto out; case 0: - __svc_clean_idle(&cleanfds, 30, FALSE); + __svc_clean_idle(cleanfds, 30, FALSE); continue; default: - svc_getreqset(&readfds); + svc_getreqset2(readfds, fdsize); #ifndef RUMP_RPC probs = 0; #endif } } +out: + free(readfds); + free(cleanfds); } /* @@ -122,6 +134,6 @@ svc_exit(void) #endif rwlock_wrlock(&svc_fd_lock); - FD_ZERO(get_fdset()); + svc_fdset_zero(); rwlock_unlock(&svc_fd_lock); } Index: src/lib/libc/rpc/svc.c diff -u src/lib/libc/rpc/svc.c:1.34 src/lib/libc/rpc/svc.c:1.35 --- src/lib/libc/rpc/svc.c:1.34 Mon Mar 11 16:19:29 2013 +++ src/lib/libc/rpc/svc.c Fri Nov 6 14:34:13 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: svc.c,v 1.34 2013/03/11 20:19:29 tron Exp $ */ +/* $NetBSD: svc.c,v 1.35 2015/11/06 19:34:13 christos Exp $ */ /* * Copyright (c) 2010, Oracle America, Inc. @@ -37,7 +37,7 @@ static char *sccsid = "@(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro"; static char *sccsid = "@(#)svc.c 2.4 88/08/11 4.0 RPCSRC"; #else -__RCSID("$NetBSD: svc.c,v 1.34 2013/03/11 20:19:29 tron Exp $"); +__RCSID("$NetBSD: svc.c,v 1.35 2015/11/06 19:34:13 christos Exp $"); #endif #endif @@ -90,7 +90,9 @@ __weak_alias(xprt_unregister,_xprt_unreg __weak_alias(rpc_control,_rpc_control) #endif +/* __svc_xports[-1] is reserved for raw */ SVCXPRT **__svc_xports; +int __svc_maxxports; int __svc_maxrec; #define RQCRED_SIZE 400 /* this size is excessive */ @@ -125,6 +127,40 @@ static void __xprt_do_unregister(SVCXPRT /* *************** SVCXPRT related stuff **************** */ +static bool_t +xprt_alloc(int sock) +{ + int maxset; + char *newxports; + + if (++sock < 0) + return FALSE; + + maxset = svc_fdset_getsize(sock); + if (maxset == -1) + return FALSE; + + if (__svc_xports != NULL && maxset <= __svc_maxxports) + return TRUE; + + if (__svc_xports != NULL) + --__svc_xports; + newxports = realloc(__svc_xports, maxset * sizeof(SVCXPRT *)); + if (newxports == NULL) { + warn("%s: out of memory", __func__); + return FALSE; + } + + memset(newxports + __svc_maxxports * sizeof(SVCXPRT *), 0, + (maxset - __svc_maxxports) * sizeof(SVCXPRT *)); + + __svc_xports = (void *)newxports; + __svc_xports++; + __svc_maxxports = maxset; + + return TRUE; +} + /* * Activate a transport handle. */ @@ -135,25 +171,16 @@ xprt_register(SVCXPRT *xprt) _DIAGASSERT(xprt != NULL); + rwlock_wrlock(&svc_fd_lock); sock = xprt->xp_fd; - rwlock_wrlock(&svc_fd_lock); - if (__svc_xports == NULL) { - __svc_xports = mem_alloc(FD_SETSIZE * sizeof(SVCXPRT *)); - if (__svc_xports == NULL) { - warn("%s: out of memory", __func__); - goto out; - } - memset(__svc_xports, '\0', FD_SETSIZE * sizeof(SVCXPRT *)); - } - if (sock >= FD_SETSIZE) { - warnx("%s: socket descriptor %d too large for setsize %u", - __func__, sock, (unsigned)FD_SETSIZE); + if (!xprt_alloc(sock)) goto out; - } + __svc_xports[sock] = xprt; - FD_SET(sock, get_fdset()); - *get_fdsetmax() = max(*get_fdsetmax(), sock); + if (sock != -1) { + svc_fdset_set(sock); + } rwlock_unlock(&svc_fd_lock); return (TRUE); @@ -180,24 +207,30 @@ __xprt_unregister_unlocked(SVCXPRT *xprt static void __xprt_do_unregister(SVCXPRT *xprt, bool_t dolock) { - int sock; + int sock, *fdmax; _DIAGASSERT(xprt != NULL); - sock = xprt->xp_fd; - if (dolock) rwlock_wrlock(&svc_fd_lock); - if ((sock < FD_SETSIZE) && (__svc_xports[sock] == xprt)) { - __svc_xports[sock] = NULL; - FD_CLR(sock, get_fdset()); - if (sock >= *get_fdsetmax()) { - for ((*get_fdsetmax())--; *get_fdsetmax() >= 0; - (*get_fdsetmax())--) - if (__svc_xports[*get_fdsetmax()]) - break; - } - } + + sock = xprt->xp_fd; + if (sock >= __svc_maxxports || __svc_xports[sock] != xprt) + goto out; + + __svc_xports[sock] = NULL; + if (sock == -1) + goto out; + fdmax = svc_fdset_getmax(); + if (sock < *fdmax) + goto clr; + + for ((*fdmax)--; *fdmax >= 0; (*fdmax)--) + if (__svc_xports[*fdmax]) + break; +clr: + svc_fdset_clr(sock); +out: if (dolock) rwlock_unlock(&svc_fd_lock); } @@ -600,15 +633,15 @@ svcerr_progvers(SVCXPRT *xprt, rpcvers_t void svc_getreq(int rdfds) { - fd_set readfds; + fd_set *readfds = svc_fdset_copy(NULL); - FD_ZERO(&readfds); - readfds.fds_bits[0] = (unsigned int)rdfds; - svc_getreqset(&readfds); + readfds->fds_bits[0] = (unsigned int)rdfds; + svc_getreqset(readfds); + free(readfds); } void -svc_getreqset(fd_set *readfds) +svc_getreqset2(fd_set *readfds, int maxsize) { uint32_t mask, *maskp; int sock, bit, fd; @@ -616,7 +649,7 @@ svc_getreqset(fd_set *readfds) _DIAGASSERT(readfds != NULL); maskp = readfds->fds_bits; - for (sock = 0; sock < FD_SETSIZE; sock += NFDBITS) { + for (sock = 0; sock < maxsize; sock += NFDBITS) { for (mask = *maskp++; (bit = ffs((int)mask)) != 0; mask ^= (1 << (bit - 1))) { /* sock has input waiting */ @@ -627,6 +660,12 @@ svc_getreqset(fd_set *readfds) } void +svc_getreqset(fd_set *readfds) +{ + svc_getreqset2(readfds, FD_SETSIZE); +} + +void svc_getreq_common(int fd) { SVCXPRT *xprt; @@ -740,7 +779,7 @@ svc_getreq_poll(struct pollfd *pfdp, int */ if (p->revents & POLLNVAL) { rwlock_wrlock(&svc_fd_lock); - FD_CLR(p->fd, get_fdset()); + svc_fdset_clr(p->fd); rwlock_unlock(&svc_fd_lock); } else svc_getreq_common(p->fd); Index: src/lib/libc/rpc/svc_fdset.c diff -u src/lib/libc/rpc/svc_fdset.c:1.1 src/lib/libc/rpc/svc_fdset.c:1.2 --- src/lib/libc/rpc/svc_fdset.c:1.1 Tue Mar 5 14:55:23 2013 +++ src/lib/libc/rpc/svc_fdset.c Fri Nov 6 14:34:13 2015 @@ -1,63 +1,300 @@ -/* $NetBSD: svc_fdset.c,v 1.1 2013/03/05 19:55:23 christos Exp $ */ +/* $NetBSD: svc_fdset.c,v 1.2 2015/11/06 19:34:13 christos Exp $ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: svc_fdset.c,v 1.1 2013/03/05 19:55:23 christos Exp $"); +__RCSID("$NetBSD: svc_fdset.c,v 1.2 2015/11/06 19:34:13 christos Exp $"); + + +#include "reentrant.h" + +#include <sys/fd_set.h> + +#include <rpc/rpc.h> -#include <pthread.h> #include <stdlib.h> #include <string.h> -#include <sys/select.h> -#include "svc_fdset.h" +struct svc_fdset { + fd_set *fdset; + int fdmax; + int fdsize; +}; + + +/* The single threaded, one global fd_set version */ +static fd_set *__svc_fdset; +static int svc_fdsize = 0; + +/* + * Update the old global svc_fdset if needed for binary compatibility + */ +#define COMPAT_UPDATE(a) \ + do \ + if ((a) == __svc_fdset) \ + svc_fdset = *__svc_fdset; \ + while (/*CONSTCOND*/0) + +static thread_key_t fdsetkey = -2; + +#ifdef FDSET_DEBUG +#include <stdio.h> +#include <stdarg.h> +#include <unistd.h> +#include <lwp.h> + +static void __printflike(3, 0) +svc_header(const char *func, size_t line, const char *fmt, va_list ap) +{ + fprintf(stderr, "%s[%d.%d]: %s, %zu: ", getprogname(), (int)getpid(), + (int)_lwp_self(), func, line); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + +static void __printflike(5, 6) +svc_fdset_print(const char *func, size_t line, const fd_set *fds, int fdmax, + const char *fmt, ...) +{ + va_list ap; + const char *did = ""; + + va_start(ap, fmt); + svc_header(func, line, fmt, ap); + va_end(ap); + + if (fdmax == 0) + fdmax = FD_SETSIZE; + + fprintf(stderr, "%p[%d] <", fds, fdmax); + for (int i = 0; i <= fdmax; i++) { + if (!FD_ISSET(i, fds)) + continue; + fprintf(stderr, "%s%d", did, i); + did = ", "; + } + fprintf(stderr, ">\n"); +} + +static void __printflike(3, 4) +svc_print(const char *func, size_t line, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + svc_header(func, line, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +#define DPRINTF_FDSET(...) svc_fdset_print(__func__, __LINE__, __VA_ARGS__) +#define DPRINTF(...) svc_print(__func__, __LINE__, __VA_ARGS__) +#else +#define DPRINTF_FDSET(...) +#define DPRINTF(...) +#endif + + +static void +svc_fdset_free(void *v) +{ + struct svc_fdset *rv = v; + DPRINTF_FDSET(rv->fdset, 0, "free"); + + free(rv->fdset); + free(rv); +} + +static fd_set * +svc_fdset_resize(int fd, fd_set **fdset, int *fdsize) +{ + if (*fdset && fd < *fdsize) { + DPRINTF_FDSET(*fdset, 0, "keeping %d < %d", + fd, *fdsize); + return *fdset; + } + + fd += FD_SETSIZE; + if (fd == 517) + abort(); + + char *newfdset = realloc(*fdset, __NFD_BYTES(fd)); + if (newfdset == NULL) + return NULL; + + memset(newfdset + __NFD_BYTES(*fdsize), 0, + __NFD_BYTES(fd) - __NFD_BYTES(*fdsize)); + + + *fdset = (void *)newfdset; + DPRINTF_FDSET(*fdset, 0, "resize %d > %d", fd, *fdsize); + *fdsize = fd; + + COMPAT_UPDATE(*fdset); + + return *fdset; +} + +static struct svc_fdset * +svc_fdset_alloc(int fd) +{ + struct svc_fdset *rv; + + if (fdsetkey == -1) + thr_keycreate(&fdsetkey, svc_fdset_free); + + if ((rv = thr_getspecific(fdsetkey)) == NULL) { + + rv = calloc(1, sizeof(*rv)); + if (rv == NULL) + return NULL; + + (void)thr_setspecific(fdsetkey, rv); + + if (svc_fdsize != 0) { + rv->fdset = __svc_fdset; + DPRINTF("switching to %p", rv->fdset); + rv->fdmax = svc_maxfd; + rv->fdsize = svc_fdsize; + + svc_fdsize = 0; + } else { + DPRINTF("first thread time %p", rv->fdset); + } + } else { + DPRINTF("again for %p", rv->fdset); + if (fd < rv->fdsize) + return rv; + } + if (svc_fdset_resize(fd, &rv->fdset, &rv->fdsize) == NULL) + return NULL; + return rv; +} + +static fd_set * +svc_fdset_get_internal(int fd) +{ + struct svc_fdset *rv; + + if (!__isthreaded || fdsetkey == -2) + return svc_fdset_resize(fd, &__svc_fdset, &svc_fdsize); + + rv = svc_fdset_alloc(fd); + if (rv == NULL) + return NULL; + return rv->fdset; +} + -static pthread_key_t fdsetkey; -static pthread_key_t fdmaxkey; -static fd_set thefdset; -static int thefdmax; +/* allow each thread to have their own copy */ +void +svc_fdset_init(int flags) +{ + DPRINTF("%x", flags); + if ((flags & SVC_FDSET_MT) && fdsetkey == -2) + fdsetkey = -1; +} void -init_fdsets(void) +svc_fdset_zero(void) { + DPRINTF("zero"); + fd_set *fds = svc_fdset_get_internal(0); + int size = svc_fdset_getsize(0); + memset(fds, 0, __NFD_BYTES(size)); + *svc_fdset_getmax() = 0; + + COMPAT_UPDATE(fds); - pthread_key_create(&fdsetkey, NULL); - pthread_key_create(&fdmaxkey, NULL); } void -alloc_fdset(void) +svc_fdset_set(int fd) { - fd_set *fdsetti; - int *fdmax; + fd_set *fds = svc_fdset_get_internal(fd); + int *fdmax = svc_fdset_getmax(); + FD_SET(fd, fds); + if (fd > *fdmax) + *fdmax = fd; + DPRINTF_FDSET(fds, *fdmax, "%d", fd); - fdsetti = malloc(sizeof(*fdsetti)); - memset(fdsetti, 0, sizeof(*fdsetti)); - pthread_setspecific(fdsetkey, fdsetti); - - fdmax = malloc(sizeof(*fdmax)); - memset(fdmax, 0, sizeof(*fdmax)); - pthread_setspecific(fdmaxkey, fdmax); + COMPAT_UPDATE(fds); +} + +int +svc_fdset_isset(int fd) +{ + fd_set *fds = svc_fdset_get_internal(fd); + DPRINTF_FDSET(fds, 0, "%d", fd); + return FD_ISSET(fd, fds); +} + +void +svc_fdset_clr(int fd) +{ + fd_set *fds = svc_fdset_get_internal(fd); + FD_CLR(fd, fds); + /* XXX: update fdmax? */ + DPRINTF_FDSET(fds, 0, "%d", fd); + + COMPAT_UPDATE(fds); } fd_set * -get_fdset(void) +svc_fdset_copy(const fd_set *orig) { - fd_set *rv; + int len, fdmax; + fd_set *fds; + + len = 0; + fds = 0; + fdmax = *svc_fdset_getmax(); + + DPRINTF_FDSET(orig, 0, "[orig]"); + fds = svc_fdset_resize(fdmax, &fds, &len); + if (fds == NULL) + return NULL; + + if (orig) + memcpy(fds, orig, __NFD_BYTES(fdmax)); + DPRINTF_FDSET(fds, 0, "[copy]"); + return fds; +} - rv = pthread_getspecific(fdsetkey); - if (rv) - return rv; - else - return &thefdset; +fd_set * +svc_fdset_get(void) +{ + fd_set *fds = svc_fdset_get_internal(0); + DPRINTF_FDSET(fds, 0, "get"); + return fds; } int * -get_fdsetmax(void) +svc_fdset_getmax(void) +{ + struct svc_fdset *rv; + + if (!__isthreaded || fdsetkey == -2) + return &svc_maxfd; + + rv = svc_fdset_alloc(0); + if (rv == NULL) + return NULL; + return &rv->fdmax; +} + +int +svc_fdset_getsize(int fd) { - int *rv; + struct svc_fdset *rv; - rv = pthread_getspecific(fdmaxkey); - if (rv) - return rv; - else - return &thefdmax; + if (!__isthreaded || fdsetkey == -2) { + if (svc_fdset_resize(fd, &__svc_fdset, &svc_fdsize) == NULL) + return -1; + else + return svc_fdsize; + } + + rv = svc_fdset_alloc(fd); + if (rv == NULL) + return -1; + return rv->fdsize; } Index: src/lib/libc/rpc/svc_fdset.h diff -u src/lib/libc/rpc/svc_fdset.h:1.1 src/lib/libc/rpc/svc_fdset.h:1.2 --- src/lib/libc/rpc/svc_fdset.h:1.1 Tue Mar 5 14:55:23 2013 +++ src/lib/libc/rpc/svc_fdset.h Fri Nov 6 14:34:13 2015 @@ -1,11 +1,4 @@ -/* $NetBSD: svc_fdset.h,v 1.1 2013/03/05 19:55:23 christos Exp $ */ - -#ifndef _LIBC - -void init_fdsets(void); -void alloc_fdset(void); -fd_set *get_fdset(void); -int *get_fdsetmax(void); +/* $NetBSD: svc_fdset.h,v 1.2 2015/11/06 19:34:13 christos Exp $ */ # ifdef RUMP_RPC # include <rump/rump.h> @@ -23,8 +16,3 @@ int *get_fdsetmax(void); # undef select # define select(a, b, c, d, e) rump_sys_select(a, b, c, d, e) # endif - -#else -# define get_fdset() (&svc_fdset) -# define get_fdsetmax() (&svc_maxfd) -#endif Index: src/lib/libc/rpc/svc_vc.c diff -u src/lib/libc/rpc/svc_vc.c:1.30 src/lib/libc/rpc/svc_vc.c:1.31 --- src/lib/libc/rpc/svc_vc.c:1.30 Mon Mar 11 16:19:29 2013 +++ src/lib/libc/rpc/svc_vc.c Fri Nov 6 14:34:13 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: svc_vc.c,v 1.30 2013/03/11 20:19:29 tron Exp $ */ +/* $NetBSD: svc_vc.c,v 1.31 2015/11/06 19:34:13 christos Exp $ */ /* * Copyright (c) 2010, Oracle America, Inc. @@ -37,7 +37,7 @@ static char *sccsid = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro"; static char *sccsid = "@(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC"; #else -__RCSID("$NetBSD: svc_vc.c,v 1.30 2013/03/11 20:19:29 tron Exp $"); +__RCSID("$NetBSD: svc_vc.c,v 1.31 2015/11/06 19:34:13 christos Exp $"); #endif #endif @@ -312,7 +312,6 @@ rendezvous_request(SVCXPRT *xprt, struct socklen_t len; struct __rpc_sockinfo si; SVCXPRT *newxprt; - fd_set cleanfds; _DIAGASSERT(xprt != NULL); _DIAGASSERT(msg != NULL); @@ -329,8 +328,10 @@ again: * running out. */ if (errno == EMFILE || errno == ENFILE) { - cleanfds = *get_fdset(); - if (__svc_clean_idle(&cleanfds, 0, FALSE)) + fd_set *cleanfds = svc_fdset_copy(svc_fdset_get()); + int rv = __svc_clean_idle(cleanfds, 0, FALSE); + free(cleanfds); + if (rv) goto again; } return FALSE; @@ -760,7 +761,7 @@ svc_vc_rendezvous_ops(SVCXPRT *xprt) bool_t __svc_clean_idle(fd_set *fds, int timeout, bool_t cleanblock) { - int i, ncleaned; + int i, ncleaned, fdmax; SVCXPRT *xprt, *least_active; struct timeval tv, tdiff, tmax; struct cf_conn *cd; @@ -769,28 +770,33 @@ __svc_clean_idle(fd_set *fds, int timeou tmax.tv_sec = tmax.tv_usec = 0; least_active = NULL; rwlock_wrlock(&svc_fd_lock); - for (i = ncleaned = 0; i <= svc_maxfd; i++) { - if (FD_ISSET(i, fds)) { - xprt = __svc_xports[i]; - if (xprt == NULL || xprt->xp_ops == NULL || - xprt->xp_ops->xp_recv != svc_vc_recv) - continue; - cd = (struct cf_conn *)xprt->xp_p1; - if (!cleanblock && !cd->nonblock) - continue; - if (timeout == 0) { - timersub(&tv, &cd->last_recv_time, &tdiff); - if (timercmp(&tdiff, &tmax, >)) { - tmax = tdiff; - least_active = xprt; - } - continue; - } - if (tv.tv_sec - cd->last_recv_time.tv_sec > timeout) { - __xprt_unregister_unlocked(xprt); - __svc_vc_dodestroy(xprt); - ncleaned++; + fdmax = *svc_fdset_getmax(); + for (i = ncleaned = 0; i <= fdmax; i++) { + if (!svc_fdset_isset(i)) + continue; + + xprt = __svc_xports[i]; + if (xprt == NULL || xprt->xp_ops == NULL || + xprt->xp_ops->xp_recv != svc_vc_recv) + continue; + + cd = (struct cf_conn *)xprt->xp_p1; + if (!cleanblock && !cd->nonblock) + continue; + + if (timeout == 0) { + timersub(&tv, &cd->last_recv_time, &tdiff); + if (timercmp(&tdiff, &tmax, >)) { + tmax = tdiff; + least_active = xprt; } + continue; + } + + if (tv.tv_sec - cd->last_recv_time.tv_sec > timeout) { + __xprt_unregister_unlocked(xprt); + __svc_vc_dodestroy(xprt); + ncleaned++; } } if (timeout == 0 && least_active != NULL) {