1#include <stdio.h>
2#include <rpc/rpc.h>
3#include <assert.h>
4
5#include <libc-lock.h>
6#include <libc-tsd.h>
7#include <shlib-compat.h>
8#include <libc-symbols.h>
9
10
11/* Variable used in non-threaded applications or for the first thread. */
12static struct rpc_thread_variables __libc_tsd_RPC_VARS_mem;
13static __thread struct rpc_thread_variables *thread_rpc_vars
14 attribute_tls_model_ie;
15
16/*
17 * Task-variable destructor
18 */
19void
20__rpc_thread_destroy (void)
21{
22 struct rpc_thread_variables *tvp = thread_rpc_vars;
23
24 if (tvp != NULL) {
25 __rpc_thread_svc_cleanup ();
26 __rpc_thread_clnt_cleanup ();
27 __rpc_thread_key_cleanup ();
28 free (ptr: tvp->clnt_perr_buf_s);
29 free (ptr: tvp->clntraw_private_s);
30 free (ptr: tvp->svcraw_private_s);
31 free (ptr: tvp->authdes_cache_s);
32 free (ptr: tvp->authdes_lru_s);
33 free (ptr: tvp->svc_xports_s);
34 free (ptr: tvp->svc_pollfd_s);
35 if (tvp != &__libc_tsd_RPC_VARS_mem)
36 free (ptr: tvp);
37 thread_rpc_vars = NULL;
38 }
39}
40text_set_element (__libc_subfreeres, __rpc_thread_destroy);
41
42/*
43 * Initialize RPC multi-threaded operation
44 */
45static void
46rpc_thread_multi (void)
47{
48 thread_rpc_vars = &__libc_tsd_RPC_VARS_mem;
49}
50
51
52struct rpc_thread_variables *
53__rpc_thread_variables (void)
54{
55 __libc_once_define (static, once);
56 struct rpc_thread_variables *tvp = thread_rpc_vars;
57
58 if (tvp == NULL) {
59 __libc_once (once, rpc_thread_multi);
60 tvp = thread_rpc_vars;
61 if (tvp == NULL) {
62 tvp = calloc (nmemb: 1, size: sizeof *tvp);
63 if (tvp != NULL)
64 thread_rpc_vars = tvp;
65 }
66 }
67 return tvp;
68}
69
70
71/* Global variables If we're single-threaded, or if this is the first
72 thread using the variable, use the existing global variable. This
73 provides backwards compatibility for existing applications which
74 dynamically link against this code. */
75#undef svc_fdset
76#undef rpc_createerr
77#undef svc_pollfd
78#undef svc_max_pollfd
79
80fd_set *
81__rpc_thread_svc_fdset (void)
82{
83 struct rpc_thread_variables *tvp;
84
85 tvp = __rpc_thread_variables ();
86 if (tvp == &__libc_tsd_RPC_VARS_mem)
87 return &svc_fdset;
88 return &tvp->svc_fdset_s;
89}
90libc_hidden_nolink_sunrpc (__rpc_thread_svc_fdset, GLIBC_2_2_3)
91
92struct rpc_createerr *
93__rpc_thread_createerr (void)
94{
95 struct rpc_thread_variables *tvp;
96
97 tvp = __rpc_thread_variables ();
98 if (tvp == &__libc_tsd_RPC_VARS_mem)
99 return &rpc_createerr;
100 return &tvp->rpc_createerr_s;
101}
102libc_hidden_nolink_sunrpc (__rpc_thread_createerr, GLIBC_2_2_3)
103
104struct pollfd **
105__rpc_thread_svc_pollfd (void)
106{
107 struct rpc_thread_variables *tvp;
108
109 tvp = __rpc_thread_variables ();
110 if (tvp == &__libc_tsd_RPC_VARS_mem)
111 return &svc_pollfd;
112 return &tvp->svc_pollfd_s;
113}
114#ifdef EXPORT_RPC_SYMBOLS
115libc_hidden_def (__rpc_thread_svc_pollfd)
116#else
117libc_hidden_nolink_sunrpc (__rpc_thread_svc_pollfd, GLIBC_2_2_3)
118#endif
119
120int *
121__rpc_thread_svc_max_pollfd (void)
122{
123 struct rpc_thread_variables *tvp;
124
125 tvp = __rpc_thread_variables ();
126 if (tvp == &__libc_tsd_RPC_VARS_mem)
127 return &svc_max_pollfd;
128 return &tvp->svc_max_pollfd_s;
129}
130#ifdef EXPORT_RPC_SYMBOLS
131libc_hidden_def (__rpc_thread_svc_max_pollfd)
132#else
133libc_hidden_nolink_sunrpc (__rpc_thread_svc_max_pollfd, GLIBC_2_2_3)
134#endif
135

source code of glibc/sunrpc/rpc_thread.c