2001-03-25 Ulrich Drepper <drepper@redhat.com>
+ Add changes which were in this form in the original patch by
+ Eric Norum <eric.norum@usask.ca>.
+ * include/rpc/rpc.h: Remove svc_fdset, rpc_createerr, svc_pollfd, and
+ svc_max_pollfd.
+ * sunrpc/rpc/rpc.h: Declare __rpc_thread_svc_fdset,
+ __rpc_thread_createerr, __rpc_thread_svc_pollfd, and
+ __rpc_thread_svc_max_pollfd.
+ Define svc_fdset, get_rpc_createerr, svc_pollfd, and
+ svc_max_pollfd.
+ * sunrpc/rpc_thread.c: Handle first thread special, it uses the
+ global variables.
+ Define __rpc_thread_svc_fdset, __rpc_thread_createerr,
+ __rpc_thread_svc_pollfd, and __rpc_thread_svc_max_pollfd.
+ * sunrpc/Versions [libc] (GLIBC_2.2.3): Export __rpc_thread_svc_fdset,
+ __rpc_thread_createerr, __rpc_thread_svc_pollfd, and
+ __rpc_thread_svc_max_pollfd.
+ * sunrpc/clnt_gen.c: Replace use of rpc_createerr by call to
+ get_rpc_createerr.
+ * sunrpc/clnt_perr.c: Likewise.
+ * sunrpc/clnt_simp.c: Likewise.
+ * sunrpc/clnt_tcp.c: Likewise.
+ * sunrpc/clnt_udp.c: Likewise.
+ * sunrpc/clnt_unix.c: Likewise.
+ * sunrpc/pm_getport.c: Likewise.
+
* sysdeps/unix/sysv/linux/i386/getgroups.c (__getgroups): getgroups32
syscall checks for negative n so don't test here as well.
#define RPC_THREAD_VARIABLE(x) (__rpc_thread_variables()->x)
-/*
- * Global variables
- */
-#define svc_fdset RPC_THREAD_VARIABLE(svc_fdset_s)
-#define rpc_createerr RPC_THREAD_VARIABLE(rpc_createerr_s)
-#define svc_pollfd RPC_THREAD_VARIABLE(svc_pollfd_s)
-#define svc_max_pollfd RPC_THREAD_VARIABLE(svc_max_pollfd_s)
-
#endif /* _RPC_THREAD_SAFE_ */
#endif
svc_getreq_common; svc_getreq_poll; svc_max_pollfd; svc_pollfd;
}
GLIBC_2.2.3 {
- __rpc_thread_destroy;
+ __rpc_thread_destroy; __rpc_thread_svc_fdset; __rpc_thread_createerr;
+ __rpc_thread_svc_pollfd; __rpc_thread_svc_max_pollfd;
}
}
|| h == NULL)
if (herr != NETDB_INTERNAL || errno != ERANGE)
{
- rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
+ get_rpc_createerr().cf_stat = RPC_UNKNOWNHOST;
return NULL;
}
else
/*
* Only support INET for now
*/
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = EAFNOSUPPORT;
+ struct rpc_createerr *ce = &get_rpc_createerr ();
+ ce->cf_stat = RPC_SYSTEMERROR;
+ ce->cf_error.re_errno = EAFNOSUPPORT;
return NULL;
}
sin.sin_family = h->h_addrtype;
|| p == NULL)
if (errno != ERANGE)
{
- rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- rpc_createerr.cf_error.re_errno = EPFNOSUPPORT;
+ struct rpc_createerr *ce = &get_rpc_createerr ();
+ ce->cf_stat = RPC_UNKNOWNPROTO;
+ ce->cf_error.re_errno = EPFNOSUPPORT;
return NULL;
}
else
#endif
break;
default:
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = EPFNOSUPPORT;
+ {
+ struct rpc_createerr *ce = &get_rpc_createerr ();
+ ce->cf_stat = RPC_SYSTEMERROR;
+ ce->cf_error.re_errno = EPFNOSUPPORT;
+ }
return (NULL);
}
return client;
char *str = _buf ();
char *cp;
int len;
+ struct rpc_createerr *ce;
if (str == NULL)
return NULL;
+ ce = &get_rpc_createerr ();
len = sprintf (str, "%s: ", msg);
cp = str + len;
- cp = stpcpy (cp, clnt_sperrno (rpc_createerr.cf_stat));
- switch (rpc_createerr.cf_stat)
+ cp = stpcpy (cp, clnt_sperrno (ce->cf_stat));
+ switch (ce->cf_stat)
{
case RPC_PMAPFAILURE:
cp = stpcpy (stpcpy (cp, " - "),
- clnt_sperrno (rpc_createerr.cf_error.re_status));
+ clnt_sperrno (ce->cf_error.re_status));
break;
case RPC_SYSTEMERROR:
cp = stpcpy (stpcpy (cp, " - "),
- __strerror_r (rpc_createerr.cf_error.re_errno,
+ __strerror_r (ce->cf_error.re_errno,
chrbuf, sizeof chrbuf));
break;
default:
server_addr.sin_port = 0;
if ((crp->client = clntudp_create (&server_addr, (u_long) prognum,
(u_long) versnum, timeout, &crp->socket)) == NULL)
- return (int) rpc_createerr.cf_stat;
+ return (int) get_rpc_createerr().cf_stat;
crp->valid = 1;
crp->oldprognum = prognum;
crp->oldversnum = versnum;
h = (CLIENT *) mem_alloc (sizeof (*h));
if (h == NULL)
{
+ struct rpc_createerr *ce = &get_rpc_createerr ();
(void) fprintf (stderr, _("clnttcp_create: out of memory\n"));
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = errno;
+ ce->cf_stat = RPC_SYSTEMERROR;
+ ce->cf_error.re_errno = errno;
goto fooy;
}
/* ct = (struct ct_data *) mem_alloc (sizeof (*ct)); */
if (ct == NULL)
{
+ struct rpc_createerr *ce = &get_rpc_createerr ();
(void) fprintf (stderr, _("clnttcp_create: out of memory\n"));
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = errno;
+ ce->cf_stat = RPC_SYSTEMERROR;
+ ce->cf_error.re_errno = errno;
goto fooy;
}
|| (__connect (*sockp, (struct sockaddr *) raddr,
sizeof (*raddr)) < 0))
{
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = errno;
+ struct rpc_createerr *ce = &get_rpc_createerr ();
+ ce->cf_stat = RPC_SYSTEMERROR;
+ ce->cf_error.re_errno = errno;
if (*sockp >= 0)
(void) __close (*sockp);
goto fooy;
cl = (CLIENT *) mem_alloc (sizeof (CLIENT));
if (cl == NULL)
{
+ struct rpc_createerr *ce = &get_rpc_createerr ();
(void) fprintf (stderr, _("clntudp_create: out of memory\n"));
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = errno;
+ ce->cf_stat = RPC_SYSTEMERROR;
+ ce->cf_error.re_errno = errno;
goto fooy;
}
sendsz = ((sendsz + 3) / 4) * 4;
cu = (struct cu_data *) mem_alloc (sizeof (*cu) + sendsz + recvsz);
if (cu == NULL)
{
+ struct rpc_createerr *ce = &get_rpc_createerr ();
(void) fprintf (stderr, _("clntudp_create: out of memory\n"));
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = errno;
+ ce->cf_stat = RPC_SYSTEMERROR;
+ ce->cf_error.re_errno = errno;
goto fooy;
}
cu->cu_outbuf = &cu->cu_inbuf[recvsz];
*sockp = __socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (*sockp < 0)
{
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = errno;
+ struct rpc_createerr *ce = &get_rpc_createerr ();
+ ce->cf_stat = RPC_SYSTEMERROR;
+ ce->cf_error.re_errno = errno;
goto fooy;
}
/* attempt to bind to prov port */
h = (CLIENT *) mem_alloc (sizeof (*h));
if (h == NULL)
{
+ struct rpc_createerr *ce = &get_rpc_createerr ();
(void) fputs (_("clntunix_create: out of memory\n"), stderr);
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = errno;
+ ce->cf_stat = RPC_SYSTEMERROR;
+ ce->cf_error.re_errno = errno;
goto fooy;
}
/* ct = (struct ct_data *) mem_alloc (sizeof (*ct)); */
if (ct == NULL)
{
+ struct rpc_createerr *ce = &get_rpc_createerr ();
(void) fputs (_("clntunix_create: out of memory\n"), stderr);
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = errno;
+ ce->cf_stat = RPC_SYSTEMERROR;
+ ce->cf_error.re_errno = errno;
goto fooy;
}
if (*sockp < 0
|| __connect (*sockp, (struct sockaddr *) raddr, len) < 0)
{
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = errno;
+ struct rpc_createerr *ce = &get_rpc_createerr ();
+ ce->cf_stat = RPC_SYSTEMERROR;
+ ce->cf_error.re_errno = errno;
if (*sockp != -1)
__close (*sockp);
goto fooy;
PMAPVERS, timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
if (client != (CLIENT *) NULL)
{
+ struct rpc_createerr *ce = &get_rpc_createerr ();
parms.pm_prog = program;
parms.pm_vers = version;
parms.pm_prot = protocol;
(caddr_t)&parms, (xdrproc_t)xdr_u_short,
(caddr_t)&port, tottimeout) != RPC_SUCCESS)
{
- rpc_createerr.cf_stat = RPC_PMAPFAILURE;
- clnt_geterr (client, &rpc_createerr.cf_error);
+ ce->cf_stat = RPC_PMAPFAILURE;
+ clnt_geterr (client, &ce->cf_error);
}
else if (port == 0)
{
- rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
+ ce->cf_stat = RPC_PROGNOTREGISTERED;
}
CLNT_DESTROY (client);
}
/* routines for parsing /etc/rpc */
#include <rpc/netdb.h> /* structures and routines to parse /etc/rpc */
+
+/* Global variables, protected for multi-threaded applications. */
+extern fd_set *__rpc_thread_svc_fdset (void) __attribute__ ((__const__));
+#define svc_fdset (*__rpc_thread_svc_fdset ())
+
+extern struct rpc_createerr *__rpc_thread_createerr (void)
+ __attribute__ ((__const__));
+#define get_rpc_createerr() (*__rpc_thread_createerr ())
+/* The people who "engineered" RPC should bee punished for naming the
+ data structure and the variable the same. We cannot always define the
+ macro 'rpc_createerr' because this would prevent people from defining
+ object of type 'struct rpc_createerr'. So we leave it up to the user
+ to select transparent replacement also of this variable. */
+#ifdef _RPC_MT_VARS
+# define rpc_createerr (*__rpc_thread_createerr ())
+#endif
+
+extern struct pollfd **__rpc_thread_svc_pollfd (void)
+ __attribute__ ((__const__));
+#define svc_pollfd (*__rpc_thread_svc_pollfd ())
+
+extern int *__rpc_thread_svc_max_pollfd (void) __attribute__ ((__const__));
+#define svc_max_pollfd (*__rpc_thread_svc_max_pollfd ())
+
#endif /* rpc/rpc.h */
static struct rpc_thread_variables *__libc_tsd_RPC_VARS_data =
&__libc_tsd_RPC_VARS_mem;
+
+/* This is the variable used for the first thread. */
+static struct rpc_thread_variables rpc_default;
+
/*
* Task-variable destructor
*/
{
struct rpc_thread_variables *tvp = __rpc_thread_variables();
- if (tvp != NULL) {
+ if (tvp != NULL && tvp != &rpc_default) {
__rpc_thread_svc_cleanup ();
__rpc_thread_clnt_cleanup ();
__rpc_thread_key_cleanup ();
}
+/*
+ * Initialize RPC multi-threaded operation
+ */
+static void
+rpc_thread_multi (void)
+{
+ __libc_tsd_set (RPC_VARS, &rpc_default);
+}
+
+
struct rpc_thread_variables *
__rpc_thread_variables (void)
{
+ __libc_once_define (static, once);
struct rpc_thread_variables *tvp;
tvp = __libc_tsd_get (RPC_VARS);
if (tvp == NULL) {
- tvp = calloc (1, sizeof *tvp);
- if (tvp != NULL)
- __libc_tsd_set (RPC_VARS, tvp);
- else
- tvp = __libc_tsd_RPC_VARS_data;
+ __libc_once (once, rpc_thread_multi);
+ tvp = __libc_tsd_get (RPC_VARS);
+ if (tvp == NULL) {
+ tvp = calloc (1, sizeof *tvp);
+ if (tvp != NULL)
+ __libc_tsd_set (RPC_VARS, tvp);
+ else
+ tvp = __libc_tsd_RPC_VARS_data;
+ }
}
return tvp;
}
+
+
+/* Global variables If we're single-threaded, or if this is the first
+ thread using the variable, use the existing global variable. This
+ provides backwards compatability for existing applications which
+ dynamically link against this code. */
+#undef svc_fdset
+#undef rpc_createerr
+#undef svc_pollfd
+#undef svc_max_pollfd
+
+fd_set *
+__rpc_thread_svc_fdset (void)
+{
+ struct rpc_thread_variables *tvp;
+
+ tvp = __rpc_thread_variables ();
+ if (tvp == &rpc_default)
+ return &svc_fdset;
+ return &tvp->svc_fdset_s;
+}
+
+struct rpc_createerr *
+__rpc_thread_createerr (void)
+{
+ struct rpc_thread_variables *tvp;
+
+ tvp = __rpc_thread_variables ();
+ if (tvp == &rpc_default)
+ return &rpc_createerr;
+ return &tvp->rpc_createerr_s;
+}
+
+struct pollfd **
+__rpc_thread_svc_pollfd (void)
+{
+ struct rpc_thread_variables *tvp;
+
+ tvp = __rpc_thread_variables ();
+ if (tvp == &rpc_default)
+ return &svc_pollfd;
+ return &tvp->svc_pollfd_s;
+}
+
+int *
+__rpc_thread_svc_max_pollfd (void)
+{
+ struct rpc_thread_variables *tvp;
+
+ tvp = __rpc_thread_variables ();
+ if (tvp == &rpc_default)
+ return &svc_max_pollfd;
+ return &tvp->svc_max_pollfd_s;
+}
#endif /* _RPC_THREAD_SAFE_ */