Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/libc/rpc - Provide multi-threaded fdset's for everyone n...



details:   https://anonhg.NetBSD.org/src/rev/f249e81ae442
branches:  trunk
changeset: 341448:f249e81ae442
user:      christos <christos%NetBSD.org@localhost>
date:      Fri Nov 06 19:34:13 2015 +0000

description:
- 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.

diffstat:

 lib/libc/rpc/Makefile.inc |    4 +-
 lib/libc/rpc/svc.c        |  115 +++++++++++-----
 lib/libc/rpc/svc_fdset.c  |  309 ++++++++++++++++++++++++++++++++++++++++-----
 lib/libc/rpc/svc_fdset.h  |   14 +-
 lib/libc/rpc/svc_run.c    |   36 +++-
 lib/libc/rpc/svc_vc.c     |   60 ++++----
 6 files changed, 410 insertions(+), 128 deletions(-)

diffs (truncated from 783 to 300 lines):

diff -r 921987036c2f -r f249e81ae442 lib/libc/rpc/Makefile.inc
--- a/lib/libc/rpc/Makefile.inc Fri Nov 06 19:32:08 2015 +0000
+++ b/lib/libc/rpc/Makefile.inc Fri Nov 06 19:34:13 2015 +0000
@@ -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 @@
        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
 
diff -r 921987036c2f -r f249e81ae442 lib/libc/rpc/svc.c
--- a/lib/libc/rpc/svc.c        Fri Nov 06 19:32:08 2015 +0000
+++ b/lib/libc/rpc/svc.c        Fri Nov 06 19:34:13 2015 +0000
@@ -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(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 @@
 
 /* ***************  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 @@
 
        _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 (!xprt_alloc(sock))
+               goto out;
+
+       __svc_xports[sock] = xprt;
+       if (sock != -1) {
+               svc_fdset_set(sock);
        }
-       if (sock >= FD_SETSIZE) {
-               warnx("%s: socket descriptor %d too large for setsize %u",
-                   __func__, sock, (unsigned)FD_SETSIZE);
-               goto out;
-       }
-       __svc_xports[sock] = xprt;
-       FD_SET(sock, get_fdset());
-       *get_fdsetmax() = max(*get_fdsetmax(), sock);
        rwlock_unlock(&svc_fd_lock);
        return (TRUE);
 
@@ -180,24 +207,30 @@
 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 @@
 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 @@
        _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 @@
 }
 
 void
+svc_getreqset(fd_set *readfds)
+{
+       svc_getreqset2(readfds, FD_SETSIZE);
+}
+
+void
 svc_getreq_common(int fd)
 {
        SVCXPRT *xprt;
@@ -740,7 +779,7 @@
                         */
                        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);
diff -r 921987036c2f -r f249e81ae442 lib/libc/rpc/svc_fdset.c
--- a/lib/libc/rpc/svc_fdset.c  Fri Nov 06 19:32:08 2015 +0000
+++ b/lib/libc/rpc/svc_fdset.c  Fri Nov 06 19:34:13 2015 +0000
@@ -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 <pthread.h>
+#include <sys/fd_set.h>
+
+#include <rpc/rpc.h>
+
 #include <stdlib.h>
 #include <string.h>
-#include <sys/select.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);
+}
 
-#include "svc_fdset.h"
+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");
+}



Home | Main Index | Thread Index | Old Index