return WSACleanup();
}
+BOOL WINAPI DllMain(
+ HINSTANCE hinstDLL,
+ DWORD fdwReason,
+ LPVOID lpvReserved
+)
+{
+ switch (fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ __thr_key = TlsAlloc();
+ break;
+
+ case DLL_PROCESS_DETACH:
+ TlsFree(__thr_key);
+ break;
+
+ case DLL_THREAD_DETACH: {
+ LPVOID ptr=TlsGetValue(__thr_key);
+ if (ptr)
+ free(ptr);
+ }
+ break;
+ }
+ return TRUE;
+}
+
VOID
nt_rpc_report(LPTSTR lpszMsg)
{
xdrstdio_create
xprt_register
xprt_unregister
-onc_svc_fdset DATA
-rpc_createerr DATA
-_null_auth DATA
+DllMain
+_thr_svc_fdset
+_thr_rpc_createerr
+_thr_null_auth
#define auth_destroy(auth) \
((*((auth)->ah_ops->ah_destroy))(auth))
+/*
#ifdef WIN32
#ifdef ONCRPCDLL
extern struct opaque_auth _null_auth;
#else
extern struct opaque_auth _null_auth;
#endif
-
+*/
+#define _null_auth (*_thr_null_auth())
/*
* These are the various implementations of client side authenticators.
/*
* If a creation fails, the following allows the user to figure out why.
*/
-struct rpc_createerr {
+struct rpc_createerr_t {
enum clnt_stat cf_stat;
struct rpc_err cf_error; /* useful when cf_stat == RPC_PMAPFAILURE */
};
+/*
#ifdef WIN32
#ifdef ONCRPCDLL
extern struct rpc_createerr rpc_createerr;
#else
extern struct rpc_createerr rpc_createerr;
#endif
-
+*/
+#define rpc_createerr (*_thr_rpc_createerr())
/*
* Copy error message to buffer.
#define clnttcp_create onc_clnttcp_create
#define clnt_spcreateerror onc_clnt_spcreateerror
-
-#define svcfd_create onc_svcfd_create
#define svc_register onc_svc_register
#define svc_getreqset onc_svc_getreqset
+#define svcfd_create onc_svcfd_create
#ifndef FD_SETSIZE
# define FD_SETSIZE 1024
#endif
+
#ifdef WIN32
#include <stdlib.h>
/* routines for parsing /etc/rpc */
#include <rpc/netdb.h> /* structures and routines to parse /etc/rpc */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Oct 2004: Additions by Scott Cantor to support POSIX and Win32 threads. */
+#ifdef WIN32
+extern DWORD __thr_key; /* Win32 TLS key */
+#endif
+
+extern struct opaque_auth* _thr_null_auth(void);
+extern struct rpc_createerr_t* _thr_rpc_createerr(void);
+extern fd_set* _thr_svc_fdset(void);
+
+#ifdef __cplusplus
+}
+#endif
+
#endif /* ndef __RPC_HEADER__ */
* dynamic; must be inspected before each call to select
*/
#ifdef FD_SETSIZE
-#ifdef WIN32
-#ifdef ONCRPCDLL
-extern fd_set onc_svc_fdset;
-#else
-#ifdef __BORLANDC__
-extern __import fd_set onc_svc_fdset;
-#else
-_declspec(dllimport) fd_set onc_svc_fdset;
-#endif
-#endif
-#else
-extern fd_set onc_svc_fdset;
+#define svc_fdset (*_thr_svc_fdset())
+#ifndef WIN32
+#define svc_fds svc_fdset.fds_bits[0] /* compatibility */
#endif
-#define svc_fds onc_svc_fdset.fds_bits[0] /* compatibility */
#else
extern int svc_fds;
#endif /* def FD_SETSIZE */
* This file should only contain common data (global data) that is exported
* by public interfaces
*/
-#if defined(WIN32) && defined(__BORLANDC__)
-__declspec(dllexport)
+
+/* modified by Scott Cantor to make global data per-thread */
+
+#ifndef WIN32
+#include <pthread.h>
+pthread_once_t __thr_onc_control = PTHREAD_ONCE_INIT; /* insures single execution */
+pthread_key_t __thr_key; /* pthread key */
+void _thr_onc_init(); /* creates pthread key */
+void _thr_onc_term(void*); /* key destructor function */
#endif
-struct opaque_auth _null_auth;
-#ifdef FD_SETSIZE
+
+/* these are only used in an out of memory situation... */
+static fd_set __g_svc_fdset;
+static struct opaque_auth __g_null_auth;
+static struct rpc_createerr_t __g_rpc_createerr_t;
+
+/* per-thread global variables encapsulated in one block, makes TLS mgmt easier */
+struct __thr_rpc_vars {
+ fd_set _svc_fdset;
+ struct opaque_auth __null_auth;
+ struct rpc_createerr_t _rpc_createerr_t;
+};
+
+#ifdef WIN32
+
+DWORD __thr_key;
+
+struct __thr_rpc_vars* _get_thr_rpc_vars()
+{
+ struct __thr_rpc_vars* ptr = TlsGetValue(__thr_key);
+
+ if (!ptr && (ptr=malloc(sizeof(struct __thr_rpc_vars)))) {
+ memset(ptr,0,sizeof(struct __thr_rpc_vars));
+ TlsSetValue(__thr_key, ptr);
+ }
+ else if (!ptr) {
+ nt_rpc_report("out of memory");
+ }
+ return ptr;
+}
+
+#else
+
+struct __thr_rpc_vars* _get_thr_rpc_vars()
+{
+ struct __thr_rpc_vars* ptr = NULL;
+
+ pthread_once(&__thr_onc_control, _thr_onc_init);
+ ptr = pthread_getspecific(__thr_key);
+ if (!ptr && ptr=malloc(sizeof(struct __thr_rpc_vars))) {
+ memset(ptr,0,sizeof(struct __thr_rpc_vars));
+ pthread_setspecific(__thr_key, ptr);
+ }
+ else if (!ptr) {
+ fprintf(stderr,"_get_thr_rpc_vars: out of memory");
+ }
+ return ptr;
+}
+
+void _thr_onc_init()
+{
+ pthread_key_create(&__thr_key, _thr_onc_term);
+}
+
+void _thr_onc_term(void*)
+{
+ void* ptr = pthread_getspecific(__thr_key);
+ if (ptr)
+ free(ptr);
+}
+
+#endif
+
#if defined(WIN32) && defined(__BORLANDC__)
-__declspec(dllexport)
+#define ONC_EXPORT __declspec(dllexport)
+#else
+#define ONC_EXPORT
#endif
-fd_set onc_svc_fdset;
+
+ONC_EXPORT struct opaque_auth* _thr_null_auth(void)
+{
+ struct __thr_rpc_vars* ptr = _get_thr_rpc_vars();
+ return ptr ? &(ptr->__null_auth) : &__g_null_auth;
+}
+
+ONC_EXPORT struct rpc_createerr_t* _thr_rpc_createerr(void)
+{
+ struct __thr_rpc_vars* ptr = _get_thr_rpc_vars();
+ return ptr ? &(ptr->_rpc_createerr_t) : &__g_rpc_createerr_t;
+}
+
+#ifdef FD_SETSIZE
+
+ONC_EXPORT fd_set* _thr_svc_fdset(void)
+{
+ struct __thr_rpc_vars* ptr = _get_thr_rpc_vars();
+ return ptr ? &(ptr->_svc_fdset) : &__g_svc_fdset;
+}
+
#else
+
int svc_fds;
+
#endif /* def FD_SETSIZE */
-#if defined(WIN32) && defined(__BORLANDC__)
-__declspec(dllexport)
-#endif
-struct rpc_createerr rpc_createerr;
+
}
- if (onc_svc_fdset.fd_count < FD_SETSIZE) {
+ if (svc_fdset.fd_count < FD_SETSIZE) {
xports[sock] = xprt;
- FD_SET(sock, &onc_svc_fdset);
+ FD_SET(sock, &svc_fdset);
} else {
char str[256];
#else
if (sock < FD_SETSIZE) {
xports[sock] = xprt;
- FD_SET(sock, &onc_svc_fdset);
+ FD_SET(sock, &svc_fdset);
}
#endif
#else
svc_fds |= (1 << sock);
}
#endif /* def FD_SETSIZE */
-
}
/*
#ifdef WIN32
if ((xports[sock] == xprt)) {
xports[sock] = (SVCXPRT *)0;
- FD_CLR((unsigned)sock, &onc_svc_fdset);
+ FD_CLR((unsigned)sock, &svc_fdset);
#else
if ((sock < FD_SETSIZE) && (xports[sock] == xprt)) {
xports[sock] = (SVCXPRT *)0;
- FD_CLR(sock, &onc_svc_fdset);
+ FD_CLR(sock, &svc_fdset);
#endif
}
#else
for (;;) {
#ifdef FD_SETSIZE
- readfds = onc_svc_fdset;
+ readfds = svc_fdset;
#else
readfds = svc_fds;
#endif /* def FD_SETSIZE */