- 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.diff -r1.22 -r1.23 src/lib/libc/rpc/Makefile.inc
(christos)
--- src/lib/libc/rpc/Makefile.inc 2015/04/15 19:13:47 1.22
+++ src/lib/libc/rpc/Makefile.inc 2015/11/06 19:34:13 1.23
@@ -1,28 +1,28 @@ | @@ -1,28 +1,28 @@ | |||
1 | # $NetBSD: Makefile.inc,v 1.22 2015/04/15 19:13:47 mrg Exp $ | 1 | # $NetBSD: Makefile.inc,v 1.23 2015/11/06 19:34:13 christos Exp $ | |
2 | 2 | |||
3 | # librpc sources | 3 | # librpc sources | |
4 | .PATH: ${.CURDIR}/rpc | 4 | .PATH: ${.CURDIR}/rpc | |
5 | 5 | |||
6 | SRCS+= auth_none.c auth_unix.c authunix_prot.c bindresvport.c \ | 6 | SRCS+= auth_none.c auth_unix.c authunix_prot.c bindresvport.c \ | |
7 | clnt_bcast.c clnt_dg.c clnt_generic.c clnt_perror.c \ | 7 | clnt_bcast.c clnt_dg.c clnt_generic.c clnt_perror.c \ | |
8 | clnt_raw.c clnt_simple.c \ | 8 | clnt_raw.c clnt_simple.c \ | |
9 | clnt_vc.c rpc_dtablesize.c \ | 9 | clnt_vc.c rpc_dtablesize.c \ | |
10 | getnetconfig.c getnetpath.c getrpcent.c getrpcport.c \ | 10 | getnetconfig.c getnetpath.c getrpcent.c getrpcport.c \ | |
11 | mt_misc.c pmap_clnt.c pmap_getmaps.c pmap_getport.c pmap_prot.c \ | 11 | mt_misc.c pmap_clnt.c pmap_getmaps.c pmap_getport.c pmap_prot.c \ | |
12 | pmap_prot2.c pmap_rmt.c rpc_prot.c rpc_commondata.c rpc_callmsg.c \ | 12 | pmap_prot2.c pmap_rmt.c rpc_prot.c rpc_commondata.c rpc_callmsg.c \ | |
13 | rpc_generic.c rpc_soc.c rpcb_clnt.c rpcb_prot.c rpcb_st_xdr.c \ | 13 | rpc_generic.c rpc_soc.c rpcb_clnt.c rpcb_prot.c rpcb_st_xdr.c \ | |
14 | svc.c svc_auth.c svc_dg.c svc_auth_unix.c svc_generic.c svc_raw.c \ | 14 | svc.c svc_auth.c svc_dg.c svc_auth_unix.c svc_generic.c svc_raw.c \ | |
15 | svc_run.c svc_simple.c svc_vc.c \ | 15 | svc_run.c svc_simple.c svc_vc.c svc_fdset.c \ | |
16 | xdr.c xdr_array.c xdr_float.c xdr_mem.c xdr_rec.c xdr_reference.c \ | 16 | xdr.c xdr_array.c xdr_float.c xdr_mem.c xdr_rec.c xdr_reference.c \ | |
17 | xdr_stdio.c xdr_sizeof.c __rpc_getxid.c | 17 | xdr_stdio.c xdr_sizeof.c __rpc_getxid.c | |
18 | 18 | |||
19 | CPPFLAGS+= -DPORTMAP | 19 | CPPFLAGS+= -DPORTMAP | |
20 | 20 | |||
21 | MAN+= bindresvport.3 getnetconfig.3 getnetpath.3 getrpcent.3 getrpcport.3 \ | 21 | MAN+= bindresvport.3 getnetconfig.3 getnetpath.3 getrpcent.3 getrpcport.3 \ | |
22 | rpc.3 rpc_soc.3 rpc_clnt_auth.3 rpc_clnt_calls.3 rpc_clnt_create.3 \ | 22 | rpc.3 rpc_soc.3 rpc_clnt_auth.3 rpc_clnt_calls.3 rpc_clnt_create.3 \ | |
23 | rpc_svc_calls.3 rpc_svc_create.3 rpc_svc_err.3 rpc_svc_reg.3 \ | 23 | rpc_svc_calls.3 rpc_svc_create.3 rpc_svc_err.3 rpc_svc_reg.3 \ | |
24 | rpc_xdr.3 rpcbind.3 xdr.3 | 24 | rpc_xdr.3 rpcbind.3 xdr.3 | |
25 | MLINKS+= bindresvport.3 bindresvport_sa.3 \ | 25 | MLINKS+= bindresvport.3 bindresvport_sa.3 \ | |
26 | getnetconfig.3 setnetconfig.3 \ | 26 | getnetconfig.3 setnetconfig.3 \ | |
27 | getnetconfig.3 getnetconfigent.3 \ | 27 | getnetconfig.3 getnetconfigent.3 \ | |
28 | getnetconfig.3 endnetconfig.3 \ | 28 | getnetconfig.3 endnetconfig.3 \ |
--- src/lib/libc/rpc/svc_run.c 2013/03/11 20:19:29 1.22
+++ src/lib/libc/rpc/svc_run.c 2015/11/06 19:34:13 1.23
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: svc_run.c,v 1.22 2013/03/11 20:19:29 tron Exp $ */ | 1 | /* $NetBSD: svc_run.c,v 1.23 2015/11/06 19:34:13 christos Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2010, Oracle America, Inc. | 4 | * Copyright (c) 2010, Oracle America, Inc. | |
5 | * | 5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | 6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions are | 7 | * modification, are permitted provided that the following conditions are | |
8 | * met: | 8 | * met: | |
9 | * | 9 | * | |
10 | * * Redistributions of source code must retain the above copyright | 10 | * * Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * * Redistributions in binary form must reproduce the above | 12 | * * Redistributions in binary form must reproduce the above | |
13 | * copyright notice, this list of conditions and the following | 13 | * copyright notice, this list of conditions and the following | |
14 | * disclaimer in the documentation and/or other materials | 14 | * disclaimer in the documentation and/or other materials | |
@@ -27,101 +27,113 @@ | @@ -27,101 +27,113 @@ | |||
27 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 27 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
29 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 29 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
30 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 30 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | 32 | */ | |
33 | 33 | |||
34 | #include <sys/cdefs.h> | 34 | #include <sys/cdefs.h> | |
35 | #if defined(LIBC_SCCS) && !defined(lint) | 35 | #if defined(LIBC_SCCS) && !defined(lint) | |
36 | #if 0 | 36 | #if 0 | |
37 | static char *sccsid = "@(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro"; | 37 | static char *sccsid = "@(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro"; | |
38 | static char *sccsid = "@(#)svc_run.c 2.1 88/07/29 4.0 RPCSRC"; | 38 | static char *sccsid = "@(#)svc_run.c 2.1 88/07/29 4.0 RPCSRC"; | |
39 | #else | 39 | #else | |
40 | __RCSID("$NetBSD: svc_run.c,v 1.22 2013/03/11 20:19:29 tron Exp $"); | 40 | __RCSID("$NetBSD: svc_run.c,v 1.23 2015/11/06 19:34:13 christos Exp $"); | |
41 | #endif | 41 | #endif | |
42 | #endif | 42 | #endif | |
43 | 43 | |||
44 | /* | 44 | /* | |
45 | * This is the rpc server side idle loop | 45 | * This is the rpc server side idle loop | |
46 | * Wait for input, call server program. | 46 | * Wait for input, call server program. | |
47 | */ | 47 | */ | |
48 | #include "namespace.h" | 48 | #include "namespace.h" | |
49 | #include "reentrant.h" | 49 | #include "reentrant.h" | |
50 | #include <err.h> | 50 | #include <err.h> | |
51 | #include <errno.h> | 51 | #include <errno.h> | |
52 | #include <stdio.h> | 52 | #include <stdio.h> | |
53 | #include <stdlib.h> | |||
53 | #include <string.h> | 54 | #include <string.h> | |
54 | #include <unistd.h> | 55 | #include <unistd.h> | |
55 | 56 | |||
56 | #include <rpc/rpc.h> | 57 | #include <rpc/rpc.h> | |
57 | 58 | |||
58 | #include "svc_fdset.h" | 59 | #include "svc_fdset.h" | |
59 | #include "rpc_internal.h" | 60 | #include "rpc_internal.h" | |
60 | 61 | |||
61 | #ifdef __weak_alias | 62 | #ifdef __weak_alias | |
62 | __weak_alias(svc_run,_svc_run) | 63 | __weak_alias(svc_run,_svc_run) | |
63 | __weak_alias(svc_exit,_svc_exit) | 64 | __weak_alias(svc_exit,_svc_exit) | |
64 | #endif | 65 | #endif | |
65 | 66 | |||
66 | void | 67 | void | |
67 | svc_run(void) | 68 | svc_run(void) | |
68 | { | 69 | { | |
69 | fd_set readfds, cleanfds; | 70 | fd_set *readfds, *cleanfds; | |
70 | struct timeval timeout; | 71 | struct timeval timeout; | |
71 | int maxfd; | 72 | int maxfd, fdsize; | |
72 | #ifndef RUMP_RPC | 73 | #ifndef RUMP_RPC | |
73 | int probs = 0; | 74 | int probs = 0; | |
74 | #endif | 75 | #endif | |
75 | #ifdef _REENTRANT | 76 | #ifdef _REENTRANT | |
76 | extern rwlock_t svc_fd_lock; | 77 | extern rwlock_t svc_fd_lock; | |
77 | #endif | 78 | #endif | |
78 | 79 | |||
80 | readfds = NULL; | |||
81 | cleanfds = NULL; | |||
82 | fdsize = 0; | |||
79 | timeout.tv_sec = 30; | 83 | timeout.tv_sec = 30; | |
80 | timeout.tv_usec = 0; | 84 | timeout.tv_usec = 0; | |
81 | 85 | |||
82 | for (;;) { | 86 | for (;;) { | |
83 | rwlock_rdlock(&svc_fd_lock); | 87 | rwlock_rdlock(&svc_fd_lock); | |
84 | readfds = *get_fdset(); | 88 | if (fdsize != svc_fdset_getsize(0)) { | |
85 | cleanfds = *get_fdset(); | 89 | fdsize = svc_fdset_getsize(0); | |
86 | maxfd = *get_fdsetmax(); | 90 | free(readfds); | |
91 | readfds = svc_fdset_copy(svc_fdset_get()); | |||
92 | free(cleanfds); | |||
93 | cleanfds = svc_fdset_copy(svc_fdset_get()); | |||
94 | } | |||
95 | maxfd = *svc_fdset_getmax(); | |||
87 | rwlock_unlock(&svc_fd_lock); | 96 | rwlock_unlock(&svc_fd_lock); | |
88 | switch (select(maxfd + 1, &readfds, NULL, NULL, &timeout)) { | 97 | switch (select(maxfd + 1, readfds, NULL, NULL, &timeout)) { | |
89 | case -1: | 98 | case -1: | |
90 | #ifndef RUMP_RPC | 99 | #ifndef RUMP_RPC | |
91 | if ((errno == EINTR || errno == EBADF) && probs < 100) { | 100 | if ((errno == EINTR || errno == EBADF) && probs < 100) { | |
92 | probs++; | 101 | probs++; | |
93 | continue; | 102 | continue; | |
94 | } | 103 | } | |
95 | #endif | 104 | #endif | |
96 | if (errno == EINTR) { | 105 | if (errno == EINTR) { | |
97 | continue; | 106 | continue; | |
98 | } | 107 | } | |
99 | warn("%s: select failed", __func__); | 108 | warn("%s: select failed", __func__); | |
100 | return; | 109 | goto out; | |
101 | case 0: | 110 | case 0: | |
102 | __svc_clean_idle(&cleanfds, 30, FALSE); | 111 | __svc_clean_idle(cleanfds, 30, FALSE); | |
103 | continue; | 112 | continue; | |
104 | default: | 113 | default: | |
105 | svc_getreqset(&readfds); | 114 | svc_getreqset2(readfds, fdsize); | |
106 | #ifndef RUMP_RPC | 115 | #ifndef RUMP_RPC | |
107 | probs = 0; | 116 | probs = 0; | |
108 | #endif | 117 | #endif | |
109 | } | 118 | } | |
110 | } | 119 | } | |
120 | out: | |||
121 | free(readfds); | |||
122 | free(cleanfds); | |||
111 | } | 123 | } | |
112 | 124 | |||
113 | /* | 125 | /* | |
114 | * This function causes svc_run() to exit by telling it that it has no | 126 | * This function causes svc_run() to exit by telling it that it has no | |
115 | * more work to do. | 127 | * more work to do. | |
116 | */ | 128 | */ | |
117 | void | 129 | void | |
118 | svc_exit(void) | 130 | svc_exit(void) | |
119 | { | 131 | { | |
120 | #ifdef _REENTRANT | 132 | #ifdef _REENTRANT | |
121 | extern rwlock_t svc_fd_lock; | 133 | extern rwlock_t svc_fd_lock; | |
122 | #endif | 134 | #endif | |
123 | 135 | |||
124 | rwlock_wrlock(&svc_fd_lock); | 136 | rwlock_wrlock(&svc_fd_lock); | |
125 | FD_ZERO(get_fdset()); | 137 | svc_fdset_zero(); | |
126 | rwlock_unlock(&svc_fd_lock); | 138 | rwlock_unlock(&svc_fd_lock); | |
127 | } | 139 | } |
--- src/lib/libc/rpc/svc.c 2013/03/11 20:19:29 1.34
+++ src/lib/libc/rpc/svc.c 2015/11/06 19:34:13 1.35
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: svc.c,v 1.34 2013/03/11 20:19:29 tron Exp $ */ | 1 | /* $NetBSD: svc.c,v 1.35 2015/11/06 19:34:13 christos Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2010, Oracle America, Inc. | 4 | * Copyright (c) 2010, Oracle America, Inc. | |
5 | * | 5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | 6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions are | 7 | * modification, are permitted provided that the following conditions are | |
8 | * met: | 8 | * met: | |
9 | * | 9 | * | |
10 | * * Redistributions of source code must retain the above copyright | 10 | * * Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * * Redistributions in binary form must reproduce the above | 12 | * * Redistributions in binary form must reproduce the above | |
13 | * copyright notice, this list of conditions and the following | 13 | * copyright notice, this list of conditions and the following | |
14 | * disclaimer in the documentation and/or other materials | 14 | * disclaimer in the documentation and/or other materials | |
@@ -27,27 +27,27 @@ | @@ -27,27 +27,27 @@ | |||
27 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 27 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
29 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 29 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
30 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 30 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | 32 | */ | |
33 | 33 | |||
34 | #include <sys/cdefs.h> | 34 | #include <sys/cdefs.h> | |
35 | #if defined(LIBC_SCCS) && !defined(lint) | 35 | #if defined(LIBC_SCCS) && !defined(lint) | |
36 | #if 0 | 36 | #if 0 | |
37 | static char *sccsid = "@(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro"; | 37 | static char *sccsid = "@(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro"; | |
38 | static char *sccsid = "@(#)svc.c 2.4 88/08/11 4.0 RPCSRC"; | 38 | static char *sccsid = "@(#)svc.c 2.4 88/08/11 4.0 RPCSRC"; | |
39 | #else | 39 | #else | |
40 | __RCSID("$NetBSD: svc.c,v 1.34 2013/03/11 20:19:29 tron Exp $"); | 40 | __RCSID("$NetBSD: svc.c,v 1.35 2015/11/06 19:34:13 christos Exp $"); | |
41 | #endif | 41 | #endif | |
42 | #endif | 42 | #endif | |
43 | 43 | |||
44 | /* | 44 | /* | |
45 | * svc.c, Server-side remote procedure call interface. | 45 | * svc.c, Server-side remote procedure call interface. | |
46 | * | 46 | * | |
47 | * There are two sets of procedures here. The xprt routines are | 47 | * There are two sets of procedures here. The xprt routines are | |
48 | * for handling transport handles. The svc routines handle the | 48 | * for handling transport handles. The svc routines handle the | |
49 | * list of service routines. | 49 | * list of service routines. | |
50 | * | 50 | * | |
51 | * Copyright (C) 1984, Sun Microsystems, Inc. | 51 | * Copyright (C) 1984, Sun Microsystems, Inc. | |
52 | */ | 52 | */ | |
53 | 53 | |||
@@ -80,27 +80,29 @@ __weak_alias(svc_sendreply,_svc_sendrepl | @@ -80,27 +80,29 @@ __weak_alias(svc_sendreply,_svc_sendrepl | |||
80 | __weak_alias(svc_unregister,_svc_unregister) | 80 | __weak_alias(svc_unregister,_svc_unregister) | |
81 | __weak_alias(svcerr_auth,_svcerr_auth) | 81 | __weak_alias(svcerr_auth,_svcerr_auth) | |
82 | __weak_alias(svcerr_decode,_svcerr_decode) | 82 | __weak_alias(svcerr_decode,_svcerr_decode) | |
83 | __weak_alias(svcerr_noproc,_svcerr_noproc) | 83 | __weak_alias(svcerr_noproc,_svcerr_noproc) | |
84 | __weak_alias(svcerr_noprog,_svcerr_noprog) | 84 | __weak_alias(svcerr_noprog,_svcerr_noprog) | |
85 | __weak_alias(svcerr_progvers,_svcerr_progvers) | 85 | __weak_alias(svcerr_progvers,_svcerr_progvers) | |
86 | __weak_alias(svcerr_systemerr,_svcerr_systemerr) | 86 | __weak_alias(svcerr_systemerr,_svcerr_systemerr) | |
87 | __weak_alias(svcerr_weakauth,_svcerr_weakauth) | 87 | __weak_alias(svcerr_weakauth,_svcerr_weakauth) | |
88 | __weak_alias(xprt_register,_xprt_register) | 88 | __weak_alias(xprt_register,_xprt_register) | |
89 | __weak_alias(xprt_unregister,_xprt_unregister) | 89 | __weak_alias(xprt_unregister,_xprt_unregister) | |
90 | __weak_alias(rpc_control,_rpc_control) | 90 | __weak_alias(rpc_control,_rpc_control) | |
91 | #endif | 91 | #endif | |
92 | 92 | |||
93 | /* __svc_xports[-1] is reserved for raw */ | |||
93 | SVCXPRT **__svc_xports; | 94 | SVCXPRT **__svc_xports; | |
95 | int __svc_maxxports; | |||
94 | int __svc_maxrec; | 96 | int __svc_maxrec; | |
95 | 97 | |||
96 | #define RQCRED_SIZE 400 /* this size is excessive */ | 98 | #define RQCRED_SIZE 400 /* this size is excessive */ | |
97 | 99 | |||
98 | #define SVC_VERSQUIET 0x0001 /* keep quiet about vers mismatch */ | 100 | #define SVC_VERSQUIET 0x0001 /* keep quiet about vers mismatch */ | |
99 | #define version_keepquiet(xp) ((u_long)(xp)->xp_p3 & SVC_VERSQUIET) | 101 | #define version_keepquiet(xp) ((u_long)(xp)->xp_p3 & SVC_VERSQUIET) | |
100 | 102 | |||
101 | #define max(a, b) (a > b ? a : b) | 103 | #define max(a, b) (a > b ? a : b) | |
102 | 104 | |||
103 | /* | 105 | /* | |
104 | * The services list | 106 | * The services list | |
105 | * Each entry represents a set of procedures (an rpc program). | 107 | * Each entry represents a set of procedures (an rpc program). | |
106 | * The dispatch routine takes request structs and runs the | 108 | * The dispatch routine takes request structs and runs the | |
@@ -115,99 +117,130 @@ static struct svc_callout { | @@ -115,99 +117,130 @@ static struct svc_callout { | |||
115 | } *svc_head; | 117 | } *svc_head; | |
116 | 118 | |||
117 | #ifdef _REENTRANT | 119 | #ifdef _REENTRANT | |
118 | extern rwlock_t svc_lock; | 120 | extern rwlock_t svc_lock; | |
119 | extern rwlock_t svc_fd_lock; | 121 | extern rwlock_t svc_fd_lock; | |
120 | #endif | 122 | #endif | |
121 | 123 | |||
122 | static struct svc_callout *svc_find(rpcprog_t, rpcvers_t, | 124 | static struct svc_callout *svc_find(rpcprog_t, rpcvers_t, | |
123 | struct svc_callout **, char *); | 125 | struct svc_callout **, char *); | |
124 | static void __xprt_do_unregister(SVCXPRT *xprt, bool_t dolock); | 126 | static void __xprt_do_unregister(SVCXPRT *xprt, bool_t dolock); | |
125 | 127 | |||
126 | /* *************** SVCXPRT related stuff **************** */ | 128 | /* *************** SVCXPRT related stuff **************** */ | |
127 | 129 | |||
130 | static bool_t | |||
131 | xprt_alloc(int sock) | |||
132 | { | |||
133 | int maxset; | |||
134 | char *newxports; | |||
135 | ||||
136 | if (++sock < 0) | |||
137 | return FALSE; | |||
138 | ||||
139 | maxset = svc_fdset_getsize(sock); | |||
140 | if (maxset == -1) | |||
141 | return FALSE; | |||
142 | ||||
143 | if (__svc_xports != NULL && maxset <= __svc_maxxports) | |||
144 | return TRUE; | |||
145 | ||||
146 | if (__svc_xports != NULL) | |||
147 | --__svc_xports; | |||
148 | newxports = realloc(__svc_xports, maxset * sizeof(SVCXPRT *)); | |||
149 | if (newxports == NULL) { | |||
150 | warn("%s: out of memory", __func__); | |||
151 | return FALSE; | |||
152 | } | |||
153 | ||||
154 | memset(newxports + __svc_maxxports * sizeof(SVCXPRT *), 0, | |||
155 | (maxset - __svc_maxxports) * sizeof(SVCXPRT *)); | |||
156 | ||||
157 | __svc_xports = (void *)newxports; | |||
158 | __svc_xports++; | |||
159 | __svc_maxxports = maxset; | |||
160 | ||||
161 | return TRUE; | |||
162 | } | |||
163 | ||||
128 | /* | 164 | /* | |
129 | * Activate a transport handle. | 165 | * Activate a transport handle. | |
130 | */ | 166 | */ | |
131 | bool_t | 167 | bool_t | |
132 | xprt_register(SVCXPRT *xprt) | 168 | xprt_register(SVCXPRT *xprt) | |
133 | { | 169 | { | |
134 | int sock; | 170 | int sock; | |
135 | 171 | |||
136 | _DIAGASSERT(xprt != NULL); | 172 | _DIAGASSERT(xprt != NULL); | |
137 | 173 | |||
174 | rwlock_wrlock(&svc_fd_lock); | |||
138 | sock = xprt->xp_fd; | 175 | sock = xprt->xp_fd; | |
139 | 176 | |||
140 | rwlock_wrlock(&svc_fd_lock); | 177 | if (!xprt_alloc(sock)) | |
141 | if (__svc_xports == NULL) { | |||
142 | __svc_xports = mem_alloc(FD_SETSIZE * sizeof(SVCXPRT *)); | |||
143 | if (__svc_xports == NULL) { | |||
144 | warn("%s: out of memory", __func__); | |||
145 | goto out; | |||
146 | } | |||
147 | memset(__svc_xports, '\0', FD_SETSIZE * sizeof(SVCXPRT *)); | |||
148 | } | |||
149 | if (sock >= FD_SETSIZE) { | |||
150 | warnx("%s: socket descriptor %d too large for setsize %u", | |||
151 | __func__, sock, (unsigned)FD_SETSIZE); | |||
152 | goto out; | 178 | goto out; | |
153 | } | 179 | ||
154 | __svc_xports[sock] = xprt; | 180 | __svc_xports[sock] = xprt; | |
155 | FD_SET(sock, get_fdset()); | 181 | if (sock != -1) { | |
156 | *get_fdsetmax() = max(*get_fdsetmax(), sock); | 182 | svc_fdset_set(sock); | |
183 | } | |||
157 | rwlock_unlock(&svc_fd_lock); | 184 | rwlock_unlock(&svc_fd_lock); | |
158 | return (TRUE); | 185 | return (TRUE); | |
159 | 186 | |||
160 | out: | 187 | out: | |
161 | rwlock_unlock(&svc_fd_lock); | 188 | rwlock_unlock(&svc_fd_lock); | |
162 | return (FALSE); | 189 | return (FALSE); | |
163 | } | 190 | } | |
164 | 191 | |||
165 | void | 192 | void | |
166 | xprt_unregister(SVCXPRT *xprt) | 193 | xprt_unregister(SVCXPRT *xprt) | |
167 | { | 194 | { | |
168 | __xprt_do_unregister(xprt, TRUE); | 195 | __xprt_do_unregister(xprt, TRUE); | |
169 | } | 196 | } | |
170 | 197 | |||
171 | void | 198 | void | |
172 | __xprt_unregister_unlocked(SVCXPRT *xprt) | 199 | __xprt_unregister_unlocked(SVCXPRT *xprt) | |
173 | { | 200 | { | |
174 | __xprt_do_unregister(xprt, FALSE); | 201 | __xprt_do_unregister(xprt, FALSE); | |
175 | } | 202 | } | |
176 | 203 | |||
177 | /* | 204 | /* | |
178 | * De-activate a transport handle. | 205 | * De-activate a transport handle. | |
179 | */ | 206 | */ | |
180 | static void | 207 | static void | |
181 | __xprt_do_unregister(SVCXPRT *xprt, bool_t dolock) | 208 | __xprt_do_unregister(SVCXPRT *xprt, bool_t dolock) | |
182 | { | 209 | { | |
183 | int sock; | 210 | int sock, *fdmax; | |
184 | 211 | |||
185 | _DIAGASSERT(xprt != NULL); | 212 | _DIAGASSERT(xprt != NULL); | |
186 | 213 | |||
187 | sock = xprt->xp_fd; | |||
188 | ||||
189 | if (dolock) | 214 | if (dolock) | |
190 | rwlock_wrlock(&svc_fd_lock); | 215 | rwlock_wrlock(&svc_fd_lock); | |
191 | if ((sock < FD_SETSIZE) && (__svc_xports[sock] == xprt)) { | 216 | ||
192 | __svc_xports[sock] = NULL; | 217 | sock = xprt->xp_fd; | |
193 | FD_CLR(sock, get_fdset()); | 218 | if (sock >= __svc_maxxports || __svc_xports[sock] != xprt) | |
194 | if (sock >= *get_fdsetmax()) { | 219 | goto out; | |
195 | for ((*get_fdsetmax())--; *get_fdsetmax() >= 0; | 220 | ||
196 | (*get_fdsetmax())--) | 221 | __svc_xports[sock] = NULL; | |
197 | if (__svc_xports[*get_fdsetmax()]) | 222 | if (sock == -1) | |
198 | break; | 223 | goto out; | |
199 | } | 224 | fdmax = svc_fdset_getmax(); | |
200 | } | 225 | if (sock < *fdmax) | |
226 | goto clr; | |||
227 | ||||
228 | for ((*fdmax)--; *fdmax >= 0; (*fdmax)--) | |||
229 | if (__svc_xports[*fdmax]) | |||
230 | break; | |||
231 | clr: | |||
232 | svc_fdset_clr(sock); | |||
233 | out: | |||
201 | if (dolock) | 234 | if (dolock) | |
202 | rwlock_unlock(&svc_fd_lock); | 235 | rwlock_unlock(&svc_fd_lock); | |
203 | } | 236 | } | |
204 | 237 | |||
205 | /* | 238 | /* | |
206 | * Add a service program to the callout list. | 239 | * Add a service program to the callout list. | |
207 | * The dispatch routine will be called when a rpc request for this | 240 | * The dispatch routine will be called when a rpc request for this | |
208 | * program number comes in. | 241 | * program number comes in. | |
209 | */ | 242 | */ | |
210 | bool_t | 243 | bool_t | |
211 | svc_reg(SVCXPRT *xprt, const rpcprog_t prog, const rpcvers_t vers, | 244 | svc_reg(SVCXPRT *xprt, const rpcprog_t prog, const rpcvers_t vers, | |
212 | void (*dispatch)(struct svc_req *, SVCXPRT *), | 245 | void (*dispatch)(struct svc_req *, SVCXPRT *), | |
213 | const struct netconfig *nconf) | 246 | const struct netconfig *nconf) | |
@@ -590,53 +623,59 @@ svcerr_progvers(SVCXPRT *xprt, rpcvers_t | @@ -590,53 +623,59 @@ svcerr_progvers(SVCXPRT *xprt, rpcvers_t | |||
590 | * the "cooked" credentials (rqst->rq_clntcred). | 623 | * the "cooked" credentials (rqst->rq_clntcred). | |
591 | * However, this function does not know the structure of the cooked | 624 | * However, this function does not know the structure of the cooked | |
592 | * credentials, so it make the following assumptions: | 625 | * credentials, so it make the following assumptions: | |
593 | * a) the structure is contiguous (no pointers), and | 626 | * a) the structure is contiguous (no pointers), and | |
594 | * b) the cred structure size does not exceed RQCRED_SIZE bytes. | 627 | * b) the cred structure size does not exceed RQCRED_SIZE bytes. | |
595 | * In all events, all three parameters are freed upon exit from this routine. | 628 | * In all events, all three parameters are freed upon exit from this routine. | |
596 | * The storage is trivially management on the call stack in user land, but | 629 | * The storage is trivially management on the call stack in user land, but | |
597 | * is mallocated in kernel land. | 630 | * is mallocated in kernel land. | |
598 | */ | 631 | */ | |
599 | 632 | |||
600 | void | 633 | void | |
601 | svc_getreq(int rdfds) | 634 | svc_getreq(int rdfds) | |
602 | { | 635 | { | |
603 | fd_set readfds; | 636 | fd_set *readfds = svc_fdset_copy(NULL); | |
604 | 637 | |||
605 | FD_ZERO(&readfds); | 638 | readfds->fds_bits[0] = (unsigned int)rdfds; | |
606 | readfds.fds_bits[0] = (unsigned int)rdfds; | 639 | svc_getreqset(readfds); | |
607 | svc_getreqset(&readfds); | 640 | free(readfds); | |
608 | } | 641 | } | |
609 | 642 | |||
610 | void | 643 | void | |
611 | svc_getreqset(fd_set *readfds) | 644 | svc_getreqset2(fd_set *readfds, int maxsize) | |
612 | { | 645 | { | |
613 | uint32_t mask, *maskp; | 646 | uint32_t mask, *maskp; | |
614 | int sock, bit, fd; | 647 | int sock, bit, fd; | |
615 | 648 | |||
616 | _DIAGASSERT(readfds != NULL); | 649 | _DIAGASSERT(readfds != NULL); | |
617 | 650 | |||
618 | maskp = readfds->fds_bits; | 651 | maskp = readfds->fds_bits; | |
619 | for (sock = 0; sock < FD_SETSIZE; sock += NFDBITS) { | 652 | for (sock = 0; sock < maxsize; sock += NFDBITS) { | |
620 | for (mask = *maskp++; (bit = ffs((int)mask)) != 0; | 653 | for (mask = *maskp++; (bit = ffs((int)mask)) != 0; | |
621 | mask ^= (1 << (bit - 1))) { | 654 | mask ^= (1 << (bit - 1))) { | |
622 | /* sock has input waiting */ | 655 | /* sock has input waiting */ | |
623 | fd = sock + bit - 1; | 656 | fd = sock + bit - 1; | |
624 | svc_getreq_common(fd); | 657 | svc_getreq_common(fd); | |
625 | } | 658 | } | |
626 | } | 659 | } | |
627 | } | 660 | } | |
628 | 661 | |||
629 | void | 662 | void | |
663 | svc_getreqset(fd_set *readfds) | |||
664 | { | |||
665 | svc_getreqset2(readfds, FD_SETSIZE); | |||
666 | } | |||
667 | ||||
668 | void | |||
630 | svc_getreq_common(int fd) | 669 | svc_getreq_common(int fd) | |
631 | { | 670 | { | |
632 | SVCXPRT *xprt; | 671 | SVCXPRT *xprt; | |
633 | struct svc_req r; | 672 | struct svc_req r; | |
634 | struct rpc_msg msg; | 673 | struct rpc_msg msg; | |
635 | int prog_found; | 674 | int prog_found; | |
636 | rpcvers_t low_vers; | 675 | rpcvers_t low_vers; | |
637 | rpcvers_t high_vers; | 676 | rpcvers_t high_vers; | |
638 | enum xprt_stat stat; | 677 | enum xprt_stat stat; | |
639 | char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE]; | 678 | char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE]; | |
640 | 679 | |||
641 | msg.rm_call.cb_cred.oa_base = cred_area; | 680 | msg.rm_call.cb_cred.oa_base = cred_area; | |
642 | msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]); | 681 | msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]); | |
@@ -730,27 +769,27 @@ svc_getreq_poll(struct pollfd *pfdp, int | @@ -730,27 +769,27 @@ svc_getreq_poll(struct pollfd *pfdp, int | |||
730 | /* | 769 | /* | |
731 | * We assume that this function is only called | 770 | * We assume that this function is only called | |
732 | * via someone select()ing from svc_fdset or | 771 | * via someone select()ing from svc_fdset or | |
733 | * pollts()ing from svc_pollset[]. Thus it's safe | 772 | * pollts()ing from svc_pollset[]. Thus it's safe | |
734 | * to handle the POLLNVAL event by simply turning | 773 | * to handle the POLLNVAL event by simply turning | |
735 | * the corresponding bit off in svc_fdset. The | 774 | * the corresponding bit off in svc_fdset. The | |
736 | * svc_pollset[] array is derived from svc_fdset | 775 | * svc_pollset[] array is derived from svc_fdset | |
737 | * and so will also be updated eventually. | 776 | * and so will also be updated eventually. | |
738 | * | 777 | * | |
739 | * XXX Should we do an xprt_unregister() instead? | 778 | * XXX Should we do an xprt_unregister() instead? | |
740 | */ | 779 | */ | |
741 | if (p->revents & POLLNVAL) { | 780 | if (p->revents & POLLNVAL) { | |
742 | rwlock_wrlock(&svc_fd_lock); | 781 | rwlock_wrlock(&svc_fd_lock); | |
743 | FD_CLR(p->fd, get_fdset()); | 782 | svc_fdset_clr(p->fd); | |
744 | rwlock_unlock(&svc_fd_lock); | 783 | rwlock_unlock(&svc_fd_lock); | |
745 | } else | 784 | } else | |
746 | svc_getreq_common(p->fd); | 785 | svc_getreq_common(p->fd); | |
747 | } | 786 | } | |
748 | } | 787 | } | |
749 | } | 788 | } | |
750 | 789 | |||
751 | bool_t | 790 | bool_t | |
752 | rpc_control(int what, void *arg) | 791 | rpc_control(int what, void *arg) | |
753 | { | 792 | { | |
754 | int val; | 793 | int val; | |
755 | 794 | |||
756 | switch (what) { | 795 | switch (what) { |
--- src/lib/libc/rpc/svc_fdset.c 2013/03/05 19:55:23 1.1
+++ src/lib/libc/rpc/svc_fdset.c 2015/11/06 19:34:13 1.2
@@ -1,63 +1,300 @@ | @@ -1,63 +1,300 @@ | |||
1 | /* $NetBSD: svc_fdset.c,v 1.1 2013/03/05 19:55:23 christos Exp $ */ | 1 | /* $NetBSD: svc_fdset.c,v 1.2 2015/11/06 19:34:13 christos Exp $ */ | |
2 | 2 | |||
3 | #include <sys/cdefs.h> | 3 | #include <sys/cdefs.h> | |
4 | __RCSID("$NetBSD: svc_fdset.c,v 1.1 2013/03/05 19:55:23 christos Exp $"); | 4 | __RCSID("$NetBSD: svc_fdset.c,v 1.2 2015/11/06 19:34:13 christos Exp $"); | |
5 | ||||
6 | ||||
7 | #include "reentrant.h" | |||
8 | ||||
9 | #include <sys/fd_set.h> | |||
10 | ||||
11 | #include <rpc/rpc.h> | |||
5 | 12 | |||
6 | #include <pthread.h> | |||
7 | #include <stdlib.h> | 13 | #include <stdlib.h> | |
8 | #include <string.h> | 14 | #include <string.h> | |
9 | #include <sys/select.h> | |||
10 | 15 | |||
11 | #include "svc_fdset.h" | 16 | struct svc_fdset { | |
17 | fd_set *fdset; | |||
18 | int fdmax; | |||
19 | int fdsize; | |||
20 | }; | |||
21 | ||||
22 | ||||
23 | /* The single threaded, one global fd_set version */ | |||
24 | static fd_set *__svc_fdset; | |||
25 | static int svc_fdsize = 0; | |||
26 | ||||
27 | /* | |||
28 | * Update the old global svc_fdset if needed for binary compatibility | |||
29 | */ | |||
30 | #define COMPAT_UPDATE(a) \ | |||
31 | do \ | |||
32 | if ((a) == __svc_fdset) \ | |||
33 | svc_fdset = *__svc_fdset; \ | |||
34 | while (/*CONSTCOND*/0) | |||
35 | ||||
36 | static thread_key_t fdsetkey = -2; | |||
37 | ||||
38 | #ifdef FDSET_DEBUG | |||
39 | #include <stdio.h> | |||
40 | #include <stdarg.h> | |||
41 | #include <unistd.h> | |||
42 | #include <lwp.h> | |||
43 | ||||
44 | static void __printflike(3, 0) | |||
45 | svc_header(const char *func, size_t line, const char *fmt, va_list ap) | |||
46 | { | |||
47 | fprintf(stderr, "%s[%d.%d]: %s, %zu: ", getprogname(), (int)getpid(), | |||
48 | (int)_lwp_self(), func, line); | |||
49 | vfprintf(stderr, fmt, ap); | |||
50 | va_end(ap); | |||
51 | } | |||
52 | ||||
53 | static void __printflike(5, 6) | |||
54 | svc_fdset_print(const char *func, size_t line, const fd_set *fds, int fdmax, | |||
55 | const char *fmt, ...) | |||
56 | { | |||
57 | va_list ap; | |||
58 | const char *did = ""; | |||
59 | ||||
60 | va_start(ap, fmt); | |||
61 | svc_header(func, line, fmt, ap); | |||
62 | va_end(ap); | |||
63 | ||||
64 | if (fdmax == 0) | |||
65 | fdmax = FD_SETSIZE; | |||
66 | ||||
67 | fprintf(stderr, "%p[%d] <", fds, fdmax); | |||
68 | for (int i = 0; i <= fdmax; i++) { | |||
69 | if (!FD_ISSET(i, fds)) | |||
70 | continue; | |||
71 | fprintf(stderr, "%s%d", did, i); | |||
72 | did = ", "; | |||
73 | } | |||
74 | fprintf(stderr, ">\n"); | |||
75 | } | |||
76 | ||||
77 | static void __printflike(3, 4) | |||
78 | svc_print(const char *func, size_t line, const char *fmt, ...) | |||
79 | { | |||
80 | va_list ap; | |||
81 | ||||
82 | va_start(ap, fmt); | |||
83 | svc_header(func, line, fmt, ap); | |||
84 | va_end(ap); | |||
85 | fprintf(stderr, "\n"); | |||
86 | } | |||
87 | ||||
88 | #define DPRINTF_FDSET(...) svc_fdset_print(__func__, __LINE__, __VA_ARGS__) | |||
89 | #define DPRINTF(...) svc_print(__func__, __LINE__, __VA_ARGS__) | |||
90 | #else | |||
91 | #define DPRINTF_FDSET(...) | |||
92 | #define DPRINTF(...) | |||
93 | #endif | |||
94 | ||||
95 | ||||
96 | static void | |||
97 | svc_fdset_free(void *v) | |||
98 | { | |||
99 | struct svc_fdset *rv = v; | |||
100 | DPRINTF_FDSET(rv->fdset, 0, "free"); | |||
101 | ||||
102 | free(rv->fdset); | |||
103 | free(rv); | |||
104 | } | |||
105 | ||||
106 | static fd_set * | |||
107 | svc_fdset_resize(int fd, fd_set **fdset, int *fdsize) | |||
108 | { | |||
109 | if (*fdset && fd < *fdsize) { | |||
110 | DPRINTF_FDSET(*fdset, 0, "keeping %d < %d", | |||
111 | fd, *fdsize); | |||
112 | return *fdset; | |||
113 | } | |||
114 | ||||
115 | fd += FD_SETSIZE; | |||
116 | if (fd == 517) | |||
117 | abort(); | |||
118 | ||||
119 | char *newfdset = realloc(*fdset, __NFD_BYTES(fd)); | |||
120 | if (newfdset == NULL) | |||
121 | return NULL; | |||
122 | ||||
123 | memset(newfdset + __NFD_BYTES(*fdsize), 0, | |||
124 | __NFD_BYTES(fd) - __NFD_BYTES(*fdsize)); | |||
125 | ||||
126 | ||||
127 | *fdset = (void *)newfdset; | |||
128 | DPRINTF_FDSET(*fdset, 0, "resize %d > %d", fd, *fdsize); | |||
129 | *fdsize = fd; | |||
130 | ||||
131 | COMPAT_UPDATE(*fdset); | |||
132 | ||||
133 | return *fdset; | |||
134 | } | |||
135 | ||||
136 | static struct svc_fdset * | |||
137 | svc_fdset_alloc(int fd) | |||
138 | { | |||
139 | struct svc_fdset *rv; | |||
140 | ||||
141 | if (fdsetkey == -1) | |||
142 | thr_keycreate(&fdsetkey, svc_fdset_free); | |||
143 | ||||
144 | if ((rv = thr_getspecific(fdsetkey)) == NULL) { | |||
145 | ||||
146 | rv = calloc(1, sizeof(*rv)); | |||
147 | if (rv == NULL) | |||
148 | return NULL; | |||
149 | ||||
150 | (void)thr_setspecific(fdsetkey, rv); | |||
151 | ||||
152 | if (svc_fdsize != 0) { | |||
153 | rv->fdset = __svc_fdset; | |||
154 | DPRINTF("switching to %p", rv->fdset); | |||
155 | rv->fdmax = svc_maxfd; | |||
156 | rv->fdsize = svc_fdsize; | |||
157 | ||||
158 | svc_fdsize = 0; | |||
159 | } else { | |||
160 | DPRINTF("first thread time %p", rv->fdset); | |||
161 | } | |||
162 | } else { | |||
163 | DPRINTF("again for %p", rv->fdset); | |||
164 | if (fd < rv->fdsize) | |||
165 | return rv; | |||
166 | } | |||
167 | if (svc_fdset_resize(fd, &rv->fdset, &rv->fdsize) == NULL) | |||
168 | return NULL; | |||
169 | return rv; | |||
170 | } | |||
171 | ||||
172 | static fd_set * | |||
173 | svc_fdset_get_internal(int fd) | |||
174 | { | |||
175 | struct svc_fdset *rv; | |||
176 | ||||
177 | if (!__isthreaded || fdsetkey == -2) | |||
178 | return svc_fdset_resize(fd, &__svc_fdset, &svc_fdsize); | |||
179 | ||||
180 | rv = svc_fdset_alloc(fd); | |||
181 | if (rv == NULL) | |||
182 | return NULL; | |||
183 | return rv->fdset; | |||
184 | } | |||
185 | ||||
12 | 186 | |||
13 | static pthread_key_t fdsetkey; | 187 | /* allow each thread to have their own copy */ | |
14 | static pthread_key_t fdmaxkey; | 188 | void | |
15 | static fd_set thefdset; | 189 | svc_fdset_init(int flags) | |
16 | static int thefdmax; | 190 | { | |
191 | DPRINTF("%x", flags); | |||
192 | if ((flags & SVC_FDSET_MT) && fdsetkey == -2) | |||
193 | fdsetkey = -1; | |||
194 | } | |||
17 | 195 | |||
18 | void | 196 | void | |
19 | init_fdsets(void) | 197 | svc_fdset_zero(void) | |
20 | { | 198 | { | |
199 | DPRINTF("zero"); | |||
200 | fd_set *fds = svc_fdset_get_internal(0); | |||
201 | int size = svc_fdset_getsize(0); | |||
202 | memset(fds, 0, __NFD_BYTES(size)); | |||
203 | *svc_fdset_getmax() = 0; | |||
204 | ||||
205 | COMPAT_UPDATE(fds); | |||
21 | 206 | |||
22 | pthread_key_create(&fdsetkey, NULL); | |||
23 | pthread_key_create(&fdmaxkey, NULL); | |||
24 | } | 207 | } | |
25 | 208 | |||
26 | void | 209 | void | |
27 | alloc_fdset(void) | 210 | svc_fdset_set(int fd) | |
28 | { | 211 | { | |
29 | fd_set *fdsetti; | 212 | fd_set *fds = svc_fdset_get_internal(fd); | |
30 | int *fdmax; | 213 | int *fdmax = svc_fdset_getmax(); | |
214 | FD_SET(fd, fds); | |||
215 | if (fd > *fdmax) | |||
216 | *fdmax = fd; | |||
217 | DPRINTF_FDSET(fds, *fdmax, "%d", fd); | |||
31 | 218 | |||
32 | fdsetti = malloc(sizeof(*fdsetti)); | 219 | COMPAT_UPDATE(fds); | |
33 | memset(fdsetti, 0, sizeof(*fdsetti)); | 220 | } | |
34 | pthread_setspecific(fdsetkey, fdsetti); | 221 | ||
35 | 222 | int | ||
36 | fdmax = malloc(sizeof(*fdmax)); | 223 | svc_fdset_isset(int fd) | |
37 | memset(fdmax, 0, sizeof(*fdmax)); | 224 | { | |
38 | pthread_setspecific(fdmaxkey, fdmax); | 225 | fd_set *fds = svc_fdset_get_internal(fd); | |
226 | DPRINTF_FDSET(fds, 0, "%d", fd); | |||
227 | return FD_ISSET(fd, fds); | |||
228 | } | |||
229 | ||||
230 | void | |||
231 | svc_fdset_clr(int fd) | |||
232 | { | |||
233 | fd_set *fds = svc_fdset_get_internal(fd); | |||
234 | FD_CLR(fd, fds); | |||
235 | /* XXX: update fdmax? */ | |||
236 | DPRINTF_FDSET(fds, 0, "%d", fd); | |||
237 | ||||
238 | COMPAT_UPDATE(fds); | |||
39 | } | 239 | } | |
40 | 240 | |||
41 | fd_set * | 241 | fd_set * | |
42 | get_fdset(void) | 242 | svc_fdset_copy(const fd_set *orig) | |
43 | { | 243 | { | |
44 | fd_set *rv; | 244 | int len, fdmax; | |
245 | fd_set *fds; | |||
246 | ||||
247 | len = 0; | |||
248 | fds = 0; | |||
249 | fdmax = *svc_fdset_getmax(); | |||
250 | ||||
251 | DPRINTF_FDSET(orig, 0, "[orig]"); | |||
252 | fds = svc_fdset_resize(fdmax, &fds, &len); | |||
253 | if (fds == NULL) | |||
254 | return NULL; | |||
255 | ||||
256 | if (orig) | |||
257 | memcpy(fds, orig, __NFD_BYTES(fdmax)); | |||
258 | DPRINTF_FDSET(fds, 0, "[copy]"); | |||
259 | return fds; | |||
260 | } | |||
45 | 261 | |||
46 | rv = pthread_getspecific(fdsetkey); | 262 | fd_set * | |
47 | if (rv) | 263 | svc_fdset_get(void) | |
48 | return rv; | 264 | { | |
49 | else | 265 | fd_set *fds = svc_fdset_get_internal(0); | |
50 | return &thefdset; | 266 | DPRINTF_FDSET(fds, 0, "get"); | |
267 | return fds; | |||
51 | } | 268 | } | |
52 | 269 | |||
53 | int * | 270 | int * | |
54 | get_fdsetmax(void) | 271 | svc_fdset_getmax(void) | |
272 | { | |||
273 | struct svc_fdset *rv; | |||
274 | ||||
275 | if (!__isthreaded || fdsetkey == -2) | |||
276 | return &svc_maxfd; | |||
277 | ||||
278 | rv = svc_fdset_alloc(0); | |||
279 | if (rv == NULL) | |||
280 | return NULL; | |||
281 | return &rv->fdmax; | |||
282 | } | |||
283 | ||||
284 | int | |||
285 | svc_fdset_getsize(int fd) | |||
55 | { | 286 | { | |
56 | int *rv; | 287 | struct svc_fdset *rv; | |
57 | 288 | |||
58 | rv = pthread_getspecific(fdmaxkey); | 289 | if (!__isthreaded || fdsetkey == -2) { | |
59 | if (rv) | 290 | if (svc_fdset_resize(fd, &__svc_fdset, &svc_fdsize) == NULL) | |
60 | return rv; | 291 | return -1; | |
61 | else | 292 | else | |
62 | return &thefdmax; | 293 | return svc_fdsize; | |
294 | } | |||
295 | ||||
296 | rv = svc_fdset_alloc(fd); | |||
297 | if (rv == NULL) | |||
298 | return -1; | |||
299 | return rv->fdsize; | |||
63 | } | 300 | } |
--- src/lib/libc/rpc/svc_fdset.h 2013/03/05 19:55:23 1.1
+++ src/lib/libc/rpc/svc_fdset.h 2015/11/06 19:34:13 1.2
@@ -1,30 +1,18 @@ | @@ -1,30 +1,18 @@ | |||
1 | /* $NetBSD: svc_fdset.h,v 1.1 2013/03/05 19:55:23 christos Exp $ */ | 1 | /* $NetBSD: svc_fdset.h,v 1.2 2015/11/06 19:34:13 christos Exp $ */ | |
2 | ||||
3 | #ifndef _LIBC | |||
4 | ||||
5 | void init_fdsets(void); | |||
6 | void alloc_fdset(void); | |||
7 | fd_set *get_fdset(void); | |||
8 | int *get_fdsetmax(void); | |||
9 | 2 | |||
10 | # ifdef RUMP_RPC | 3 | # ifdef RUMP_RPC | |
11 | # include <rump/rump.h> | 4 | # include <rump/rump.h> | |
12 | # include <rump/rump_syscalls.h> | 5 | # include <rump/rump_syscalls.h> | |
13 | # undef close | 6 | # undef close | |
14 | # define close(a) rump_sys_close(a) | 7 | # define close(a) rump_sys_close(a) | |
15 | # undef fcntl | 8 | # undef fcntl | |
16 | # define fcntl(a, b, c) rump_sys_fcntl(a, b, c) | 9 | # define fcntl(a, b, c) rump_sys_fcntl(a, b, c) | |
17 | # undef read | 10 | # undef read | |
18 | # define read(a, b, c) rump_sys_read(a, b, c) | 11 | # define read(a, b, c) rump_sys_read(a, b, c) | |
19 | # undef write | 12 | # undef write | |
20 | # define write(a, b, c) rump_sys_write(a, b, c) | 13 | # define write(a, b, c) rump_sys_write(a, b, c) | |
21 | # undef pollts | 14 | # undef pollts | |
22 | # define pollts(a, b, c, d) rump_sys_pollts(a, b, c, d) | 15 | # define pollts(a, b, c, d) rump_sys_pollts(a, b, c, d) | |
23 | # undef select | 16 | # undef select | |
24 | # define select(a, b, c, d, e) rump_sys_select(a, b, c, d, e) | 17 | # define select(a, b, c, d, e) rump_sys_select(a, b, c, d, e) | |
25 | # endif | 18 | # endif | |
26 | ||||
27 | #else | |||
28 | # define get_fdset() (&svc_fdset) | |||
29 | # define get_fdsetmax() (&svc_maxfd) | |||
30 | #endif |
--- src/lib/libc/rpc/svc_vc.c 2013/03/11 20:19:29 1.30
+++ src/lib/libc/rpc/svc_vc.c 2015/11/06 19:34:13 1.31
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: svc_vc.c,v 1.30 2013/03/11 20:19:29 tron Exp $ */ | 1 | /* $NetBSD: svc_vc.c,v 1.31 2015/11/06 19:34:13 christos Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2010, Oracle America, Inc. | 4 | * Copyright (c) 2010, Oracle America, Inc. | |
5 | * | 5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | 6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions are | 7 | * modification, are permitted provided that the following conditions are | |
8 | * met: | 8 | * met: | |
9 | * | 9 | * | |
10 | * * Redistributions of source code must retain the above copyright | 10 | * * Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * * Redistributions in binary form must reproduce the above | 12 | * * Redistributions in binary form must reproduce the above | |
13 | * copyright notice, this list of conditions and the following | 13 | * copyright notice, this list of conditions and the following | |
14 | * disclaimer in the documentation and/or other materials | 14 | * disclaimer in the documentation and/or other materials | |
@@ -27,27 +27,27 @@ | @@ -27,27 +27,27 @@ | |||
27 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 27 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
29 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 29 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
30 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 30 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | 32 | */ | |
33 | 33 | |||
34 | #include <sys/cdefs.h> | 34 | #include <sys/cdefs.h> | |
35 | #if defined(LIBC_SCCS) && !defined(lint) | 35 | #if defined(LIBC_SCCS) && !defined(lint) | |
36 | #if 0 | 36 | #if 0 | |
37 | static char *sccsid = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro"; | 37 | static char *sccsid = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro"; | |
38 | static char *sccsid = "@(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC"; | 38 | static char *sccsid = "@(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC"; | |
39 | #else | 39 | #else | |
40 | __RCSID("$NetBSD: svc_vc.c,v 1.30 2013/03/11 20:19:29 tron Exp $"); | 40 | __RCSID("$NetBSD: svc_vc.c,v 1.31 2015/11/06 19:34:13 christos Exp $"); | |
41 | #endif | 41 | #endif | |
42 | #endif | 42 | #endif | |
43 | 43 | |||
44 | /* | 44 | /* | |
45 | * svc_vc.c, Server side for Connection Oriented based RPC. | 45 | * svc_vc.c, Server side for Connection Oriented based RPC. | |
46 | * | 46 | * | |
47 | * Actually implements two flavors of transporter - | 47 | * Actually implements two flavors of transporter - | |
48 | * a tcp rendezvouser (a listner and connection establisher) | 48 | * a tcp rendezvouser (a listner and connection establisher) | |
49 | * and a record/tcp stream. | 49 | * and a record/tcp stream. | |
50 | */ | 50 | */ | |
51 | 51 | |||
52 | #include "namespace.h" | 52 | #include "namespace.h" | |
53 | #include "reentrant.h" | 53 | #include "reentrant.h" | |
@@ -302,45 +302,46 @@ out: | @@ -302,45 +302,46 @@ out: | |||
302 | } | 302 | } | |
303 | 303 | |||
304 | /*ARGSUSED*/ | 304 | /*ARGSUSED*/ | |
305 | static bool_t | 305 | static bool_t | |
306 | rendezvous_request(SVCXPRT *xprt, struct rpc_msg *msg) | 306 | rendezvous_request(SVCXPRT *xprt, struct rpc_msg *msg) | |
307 | { | 307 | { | |
308 | int sock, flags; | 308 | int sock, flags; | |
309 | struct cf_rendezvous *r; | 309 | struct cf_rendezvous *r; | |
310 | struct cf_conn *cd; | 310 | struct cf_conn *cd; | |
311 | struct sockaddr_storage addr; | 311 | struct sockaddr_storage addr; | |
312 | socklen_t len; | 312 | socklen_t len; | |
313 | struct __rpc_sockinfo si; | 313 | struct __rpc_sockinfo si; | |
314 | SVCXPRT *newxprt; | 314 | SVCXPRT *newxprt; | |
315 | fd_set cleanfds; | |||
316 | 315 | |||
317 | _DIAGASSERT(xprt != NULL); | 316 | _DIAGASSERT(xprt != NULL); | |
318 | _DIAGASSERT(msg != NULL); | 317 | _DIAGASSERT(msg != NULL); | |
319 | 318 | |||
320 | r = (struct cf_rendezvous *)xprt->xp_p1; | 319 | r = (struct cf_rendezvous *)xprt->xp_p1; | |
321 | again: | 320 | again: | |
322 | len = sizeof addr; | 321 | len = sizeof addr; | |
323 | if ((sock = accept(xprt->xp_fd, (struct sockaddr *)(void *)&addr, | 322 | if ((sock = accept(xprt->xp_fd, (struct sockaddr *)(void *)&addr, | |
324 | &len)) < 0) { | 323 | &len)) < 0) { | |
325 | if (errno == EINTR) | 324 | if (errno == EINTR) | |
326 | goto again; | 325 | goto again; | |
327 | /* | 326 | /* | |
328 | * Clean out the most idle file descriptor when we're | 327 | * Clean out the most idle file descriptor when we're | |
329 | * running out. | 328 | * running out. | |
330 | */ | 329 | */ | |
331 | if (errno == EMFILE || errno == ENFILE) { | 330 | if (errno == EMFILE || errno == ENFILE) { | |
332 | cleanfds = *get_fdset(); | 331 | fd_set *cleanfds = svc_fdset_copy(svc_fdset_get()); | |
333 | if (__svc_clean_idle(&cleanfds, 0, FALSE)) | 332 | int rv = __svc_clean_idle(cleanfds, 0, FALSE); | |
333 | free(cleanfds); | |||
334 | if (rv) | |||
334 | goto again; | 335 | goto again; | |
335 | } | 336 | } | |
336 | return FALSE; | 337 | return FALSE; | |
337 | } | 338 | } | |
338 | /* | 339 | /* | |
339 | * make a new transporter (re-uses xprt) | 340 | * make a new transporter (re-uses xprt) | |
340 | */ | 341 | */ | |
341 | newxprt = makefd_xprt(sock, r->sendsize, r->recvsize); | 342 | newxprt = makefd_xprt(sock, r->sendsize, r->recvsize); | |
342 | if (newxprt == NULL) | 343 | if (newxprt == NULL) | |
343 | goto out; | 344 | goto out; | |
344 | newxprt->xp_rtaddr.buf = mem_alloc(len); | 345 | newxprt->xp_rtaddr.buf = mem_alloc(len); | |
345 | if (newxprt->xp_rtaddr.buf == NULL) | 346 | if (newxprt->xp_rtaddr.buf == NULL) | |
346 | goto out; | 347 | goto out; | |
@@ -750,54 +751,59 @@ svc_vc_rendezvous_ops(SVCXPRT *xprt) | @@ -750,54 +751,59 @@ svc_vc_rendezvous_ops(SVCXPRT *xprt) | |||
750 | xprt->xp_ops = &ops; | 751 | xprt->xp_ops = &ops; | |
751 | xprt->xp_ops2 = &ops2; | 752 | xprt->xp_ops2 = &ops2; | |
752 | mutex_unlock(&ops_lock); | 753 | mutex_unlock(&ops_lock); | |
753 | } | 754 | } | |
754 | 755 | |||
755 | /* | 756 | /* | |
756 | * Destroy xprts that have not have had any activity in 'timeout' seconds. | 757 | * Destroy xprts that have not have had any activity in 'timeout' seconds. | |
757 | * If 'cleanblock' is true, blocking connections (the default) are also | 758 | * If 'cleanblock' is true, blocking connections (the default) are also | |
758 | * cleaned. If timeout is 0, the least active connection is picked. | 759 | * cleaned. If timeout is 0, the least active connection is picked. | |
759 | */ | 760 | */ | |
760 | bool_t | 761 | bool_t | |
761 | __svc_clean_idle(fd_set *fds, int timeout, bool_t cleanblock) | 762 | __svc_clean_idle(fd_set *fds, int timeout, bool_t cleanblock) | |
762 | { | 763 | { | |
763 | int i, ncleaned; | 764 | int i, ncleaned, fdmax; | |
764 | SVCXPRT *xprt, *least_active; | 765 | SVCXPRT *xprt, *least_active; | |
765 | struct timeval tv, tdiff, tmax; | 766 | struct timeval tv, tdiff, tmax; | |
766 | struct cf_conn *cd; | 767 | struct cf_conn *cd; | |
767 | 768 | |||
768 | gettimeofday(&tv, NULL); | 769 | gettimeofday(&tv, NULL); | |
769 | tmax.tv_sec = tmax.tv_usec = 0; | 770 | tmax.tv_sec = tmax.tv_usec = 0; | |
770 | least_active = NULL; | 771 | least_active = NULL; | |
771 | rwlock_wrlock(&svc_fd_lock); | 772 | rwlock_wrlock(&svc_fd_lock); | |
772 | for (i = ncleaned = 0; i <= svc_maxfd; i++) { | 773 | fdmax = *svc_fdset_getmax(); | |
773 | if (FD_ISSET(i, fds)) { | 774 | for (i = ncleaned = 0; i <= fdmax; i++) { | |
774 | xprt = __svc_xports[i]; | 775 | if (!svc_fdset_isset(i)) | |
775 | if (xprt == NULL || xprt->xp_ops == NULL || | 776 | continue; | |
776 | xprt->xp_ops->xp_recv != svc_vc_recv) | 777 | ||
777 | continue; | 778 | xprt = __svc_xports[i]; | |
778 | cd = (struct cf_conn *)xprt->xp_p1; | 779 | if (xprt == NULL || xprt->xp_ops == NULL || | |
779 | if (!cleanblock && !cd->nonblock) | 780 | xprt->xp_ops->xp_recv != svc_vc_recv) | |
780 | continue; | 781 | continue; | |
781 | if (timeout == 0) { | 782 | ||
782 | timersub(&tv, &cd->last_recv_time, &tdiff); | 783 | cd = (struct cf_conn *)xprt->xp_p1; | |
783 | if (timercmp(&tdiff, &tmax, >)) { | 784 | if (!cleanblock && !cd->nonblock) | |
784 | tmax = tdiff; | 785 | continue; | |
785 | least_active = xprt; | 786 | ||
786 | } | 787 | if (timeout == 0) { | |
787 | continue; | 788 | timersub(&tv, &cd->last_recv_time, &tdiff); | |
788 | } | 789 | if (timercmp(&tdiff, &tmax, >)) { | |
789 | if (tv.tv_sec - cd->last_recv_time.tv_sec > timeout) { | 790 | tmax = tdiff; | |
790 | __xprt_unregister_unlocked(xprt); | 791 | least_active = xprt; | |
791 | __svc_vc_dodestroy(xprt); | |||
792 | ncleaned++; | |||
793 | } | 792 | } | |
793 | continue; | |||
794 | } | |||
795 | ||||
796 | if (tv.tv_sec - cd->last_recv_time.tv_sec > timeout) { | |||
797 | __xprt_unregister_unlocked(xprt); | |||
798 | __svc_vc_dodestroy(xprt); | |||
799 | ncleaned++; | |||
794 | } | 800 | } | |
795 | } | 801 | } | |
796 | if (timeout == 0 && least_active != NULL) { | 802 | if (timeout == 0 && least_active != NULL) { | |
797 | __xprt_unregister_unlocked(least_active); | 803 | __xprt_unregister_unlocked(least_active); | |
798 | __svc_vc_dodestroy(least_active); | 804 | __svc_vc_dodestroy(least_active); | |
799 | ncleaned++; | 805 | ncleaned++; | |
800 | } | 806 | } | |
801 | rwlock_unlock(&svc_fd_lock); | 807 | rwlock_unlock(&svc_fd_lock); | |
802 | return ncleaned > 0 ? TRUE : FALSE; | 808 | return ncleaned > 0 ? TRUE : FALSE; | |
803 | } | 809 | } |