This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: RPC changes


On Tue, Mar 20, 2001 at 10:50:14AM -0800, Ulrich Drepper wrote:
> I've checked in a patch I got quite some time ago and which I delayed
> for the 2.2 release.  It is introducing thread-safe RPC functions,
> similar to what Solaris has.  This should not introduce
> incompatibilities since programs currently using RPC functions in
> different threads are doomed.
> 
> I had to modify the patch quite a lot and have done only a tiny bit of
> testing myself.  Please test it out.

Here is a harmless typo patch.
Anyway, after second look at the patch, the patch does introduce
incompatibilities even in programs not using RPC functions in different
threads, particularly that the exported svc_fdset, rpc_createerr, svc_pollfd
and svc_max_pollfd variables will be always 0 all the time (which breaks I
think am-utils and other programs).
Here is a patch I wrote today, it builds fine but have not tested it yet.
What it does is (in order to avoid having svc_fdset_s etc. as pointers to
the actual variables) exporting svc_fdset etc. as aliases into the
__libc_tsd_RPC_VARS_mem variable and making sure __libc_tsd_RPC_VARS_mem
is used in non-threaded apps and for the first thread using rpc in threaded
apps (several programs like am-utils are linked against -lpthread, yet use
rpc just in one thread) and we should maintain binary compatibility there.
Also, it exports __rpc_thread_variables to userland, so that threads can
access svc_fdset etc. and see there meaningful things.
The __dummy field seems unfortunately necessary, since otherwise the alias
gets for some reason the size of the whole __libc_tsd_RPC_VARS_mem and not
just of the field in it.

2001-03-23  Jakub Jelinek  <jakub@redhat.com>

	* include/rpc/rpc.h (rpc_thread_variables): Use a special structure
	for global exported variables.
	(__rpc_thread_variables): Remove prototype.
	(svc_fdset, rpc_createerr, svc_pollfd, svc_max_pollfd): Remove.
	* sunrpc/rpc/clnt.h (struct __rpc_thread_variables_s): New.
	(__rpc_thread_variables): Add prototype.
	(__RPC_THREAD_VARIABLE, rpc_createerr): Define.
	* sunrpc/rpc/svc.h (svc_fdset, svc_pollfd, svc_max_pollfd): Define.
	* sunrpc/rpc_common.c (svc_fdset, rpc_createerr, svc_pollfd,
	svc_max_pollfd): Only declare if not thread safe.
	* sunrpc/rpc_thread.c (svc_fdset, rpc_createerr, svc_pollfd,
	svc_max_pollfd): Declare as aliases into __libc_tsd_RPC_VARS_mem.
	(__rpc_thread_do_destroy): New.
	(__rpc_thread_destroy): Use it. Don't free __libc_tsd_RPC_VARS_mem.
	(__rpc_thread_variables): In threaded application, use
	__libc_tsd_RPC_VARS_mem for the first thread which calls
	__rpc_thread_variables.
	(free_mem): New.
	* sunrpc/clnt_perr.c (free_mem): Only declare if not thread safe.
	* sunrpc/auth_none.c (authnone_private): Fix a typo.
	* sunrpc/Versions (__rpc_thread_variables): Export @GLIBC_2.2.3.

--- libc/include/rpc/rpc.h.jj	Wed Mar 21 15:44:51 2001
+++ libc/include/rpc/rpc.h	Fri Mar 23 15:24:21 2001
@@ -11,10 +11,7 @@ extern unsigned long _create_xid (void);
  */
 #ifdef _RPC_THREAD_SAFE_
 struct rpc_thread_variables {
-	fd_set		svc_fdset_s;		/* Global, rpc_common.c */
-	struct rpc_createerr rpc_createerr_s;	/* Global, rpc_common.c */
-	struct pollfd	*svc_pollfd_s;		/* Global, rpc_common.c */
-	int		svc_max_pollfd_s;	/* Global, rpc_common.c */
+	struct __rpc_thread_variables_s var_s;	/* Global, rpc_thread.c */
 
 	void		*authnone_private_s;	/* auth_none.c */
 
@@ -38,23 +35,14 @@ struct rpc_thread_variables {
 	void		*svcsimple_transp_s;	/* svc_simple.c */
 };
 
-extern struct rpc_thread_variables *__rpc_thread_variables(void)
-     __attribute__ ((const));
 extern void __rpc_thread_svc_cleanup (void);
 extern void __rpc_thread_clnt_cleanup (void);
 extern void __rpc_thread_key_cleanup (void);
 
 extern void __rpc_thread_destroy (void);
 
-#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)
+#define RPC_THREAD_VARIABLE(x)	\
+  (((struct rpc_thread_variables *)__rpc_thread_variables())->x)
 
 #endif /* _RPC_THREAD_SAFE_ */
 
--- libc/sunrpc/rpc/clnt.h.jj	Wed Aug  2 21:36:33 2000
+++ libc/sunrpc/rpc/clnt.h	Fri Mar 23 15:42:11 2001
@@ -394,7 +394,23 @@ struct rpc_createerr {
 
 extern struct rpc_createerr rpc_createerr;
 
+#if !defined _LIBC || defined _RPC_THREAD_SAFE_
 
+struct __rpc_thread_variables_s {
+	int __dummy;
+	int __svc_max_pollfd;
+	struct pollfd *__svc_pollfd;
+	fd_set __svc_fdset;
+	struct rpc_createerr __rpc_createerr;
+};
+
+extern struct __rpc_thread_variables_s *__rpc_thread_variables(void)
+     __attribute__ ((const));
+
+#define __RPC_THREAD_VARIABLE(x) (__rpc_thread_variables()->x)
+#define rpc_createerr __RPC_THREAD_VARIABLE(__rpc_createerr)
+
+#endif /* _RPC_THREAD_SAFE_ */
 
 /*
  * Copy error message to buffer.
--- libc/sunrpc/rpc/svc.h.jj	Wed Aug  2 21:36:33 2000
+++ libc/sunrpc/rpc/svc.h	Fri Mar 23 15:27:20 2001
@@ -263,6 +263,13 @@ extern void	svcerr_systemerr (SVCXPRT *_
 extern struct pollfd *svc_pollfd;
 extern int svc_max_pollfd;
 extern fd_set svc_fdset;
+
+#if !defined _LIBC || defined _RPC_THREAD_SAFE_
+#define svc_fdset __RPC_THREAD_VARIABLE(__svc_fdset)
+#define svc_pollfd __RPC_THREAD_VARIABLE(__svc_pollfd)
+#define svc_max_pollfd __RPC_THREAD_VARIABLE(__svc_max_pollfd)
+#endif /* _RPC_THREAD_SAFE_ */
+
 #define svc_fds svc_fdset.fds_bits[0]	/* compatibility */
 
 /*
--- libc/sunrpc/auth_none.c.jj	Wed Mar 21 15:44:52 2001
+++ libc/sunrpc/auth_none.c	Fri Mar 23 11:45:54 2001
@@ -62,7 +62,7 @@ struct authnone_private_s {
   u_int mcnt;
 };
 #ifdef _RPC_THREAD_SAFE_
-#define authnone_private ((struct authnone_private_ *)RPC_THREAD_VARIABLE(authnone_private_s))
+#define authnone_private ((struct authnone_private_s *)RPC_THREAD_VARIABLE(authnone_private_s))
 #else
 static struct authnone_private_s *authnone_private;
 #endif
--- libc/sunrpc/rpc_common.c.jj	Wed Mar 21 15:44:52 2001
+++ libc/sunrpc/rpc_common.c	Fri Mar 23 12:21:23 2001
@@ -28,19 +28,14 @@
  */
 #include <rpc/rpc.h>
 
-#ifdef _RPC_THREAD_SAFE_
-#undef svc_fdset
-#undef rpc_createerr
-#undef svc_pollfd
-#undef svc_max_pollfd
-#endif /* _RPC_THREAD_SAFE_ */
-
 /*
  * This file should only contain common data (global data) that is exported
  * by public interfaces
  */
 struct opaque_auth _null_auth;
+#ifndef _RPC_THREAD_SAFE_
 fd_set svc_fdset;
 struct rpc_createerr rpc_createerr;
 struct pollfd *svc_pollfd;
 int svc_max_pollfd;
+#endif
--- libc/sunrpc/rpc_thread.c.jj	Tue Mar 20 19:32:02 2001
+++ libc/sunrpc/rpc_thread.c	Fri Mar 23 15:38:21 2001
@@ -1,3 +1,4 @@
+#include <stddef.h>
 #include <stdio.h>
 #include <bits/libc-lock.h>
 #include <rpc/rpc.h>
@@ -15,41 +16,86 @@ static struct rpc_thread_variables *__li
      &__libc_tsd_RPC_VARS_mem;
 
 /*
+ * Export globally some members of __libc_tsd_RPC_VARS_mem.
+ */
+#define S_(x) #x
+#define S(x) S_(x)
+#ifdef HAVE_ASM_SET_DIRECTIVE
+#define A(x,y) ".set " S_(x) "," S_(y)
+#else
+#define A(x,y) S_(x) " = " S_(y)
+#endif
+#define V(var)								\
+  asm volatile (							\
+    S(ASM_GLOBAL_DIRECTIVE) " " S(C_SYMBOL_NAME(var)) S(ASM_LINE_SEP)	\
+    ".type " S(C_SYMBOL_NAME(var)) ",@object" S(ASM_LINE_SEP)		\
+    ".size " S(C_SYMBOL_NAME(var)) ",%c0" S(ASM_LINE_SEP)		\
+    A(C_SYMBOL_NAME(var),						\
+      C_SYMBOL_NAME(__libc_tsd_RPC_VARS_mem) + %c1) S(ASM_LINE_SEP)	\
+    : : "i" (sizeof (__libc_tsd_RPC_VARS_mem.var_s.__##var)),		\
+	"i" (offsetof (struct rpc_thread_variables, var_s.__##var)));
+
+#undef svc_fdset
+#undef rpc_createerr
+#undef svc_pollfd
+#undef svc_max_pollfd
+
+static void
+__rpc_thread_do_destroy (struct rpc_thread_variables *tvp)
+{
+	V (svc_fdset)
+	V (rpc_createerr)
+	V (svc_pollfd)
+	V (svc_max_pollfd)
+
+	free (tvp->authnone_private_s);
+	free (tvp->clnt_perr_buf_s);
+	free (tvp->clntraw_private_s);
+	free (tvp->svcraw_private_s);
+	free (tvp->authdes_cache_s);
+	free (tvp->authdes_lru_s);
+}
+
+/*
  * Task-variable destructor
  */
 void
 __rpc_thread_destroy (void)
 {
-	struct rpc_thread_variables *tvp = __rpc_thread_variables();
+	struct rpc_thread_variables *tvp =
+		(struct rpc_thread_variables *)__rpc_thread_variables();
 
-	if (tvp != NULL) {
+	if (tvp != NULL && tvp != &__libc_tsd_RPC_VARS_mem) {
 		__rpc_thread_svc_cleanup ();
 		__rpc_thread_clnt_cleanup ();
 		__rpc_thread_key_cleanup ();
-		free (tvp->authnone_private_s);
-		free (tvp->clnt_perr_buf_s);
-		free (tvp->clntraw_private_s);
-		free (tvp->svcraw_private_s);
-		free (tvp->authdes_cache_s);
-		free (tvp->authdes_lru_s);
+		__rpc_thread_do_destroy (tvp);
 		free (tvp);
 	}
 }
 
 
-struct rpc_thread_variables *
+struct __rpc_thread_variables_s *
 __rpc_thread_variables (void)
 {
 	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_lock_define_initialized (static, tvp_lock)
+		if (!__libc_lock_trylock (tvp_lock)
+		    || (tvp = calloc (1, sizeof *tvp)) == NULL)
+			tvp = &__libc_tsd_RPC_VARS_mem;
+		__libc_tsd_set (RPC_VARS, tvp);
 	}
-	return tvp;
+	return (struct __rpc_thread_variables_s *) tvp;
 }
+
+static void __attribute__ ((unused))
+free_mem (void)
+{
+  __rpc_thread_do_destroy (&__libc_tsd_RPC_VARS_mem);
+}
+text_set_element (__libc_subfreeres, free_mem);
+
 #endif /* _RPC_THREAD_SAFE_ */
--- libc/sunrpc/clnt_perr.c.jj	Wed Mar 21 15:44:52 2001
+++ libc/sunrpc/clnt_perr.c	Fri Mar 23 14:16:26 2001
@@ -391,10 +391,11 @@ auth_errmsg (enum auth_stat stat)
   return NULL;
 }
 
-
+#ifndef _RPC_THREAD_SAFE_
 static void __attribute__ ((unused))
 free_mem (void)
 {
   free (buf);
 }
 text_set_element (__libc_subfreeres, free_mem);
+#endif
--- libc/sunrpc/Versions.jj	Wed Mar 21 15:44:52 2001
+++ libc/sunrpc/Versions	Fri Mar 23 15:12:35 2001
@@ -110,6 +110,6 @@ libc {
     svc_getreq_common; svc_getreq_poll; svc_max_pollfd; svc_pollfd;
   }
   GLIBC_2.2.3 {
-    __rpc_thread_destroy;
+    __rpc_thread_destroy; __rpc_thread_variables;
   }
 }


	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]