fdwalk should return 0 on an empty directory
[kopensolaris-gnu/glibc.git] / sunrpc / rpc_thread.c
1 #include <stdio.h>
2 #include <bits/libc-lock.h>
3 #include <rpc/rpc.h>
4 #include <assert.h>
5
6 #include <bits/libc-lock.h>
7 #include <bits/libc-tsd.h>
8
9 #ifdef _RPC_THREAD_SAFE_
10
11 /* Variable used in non-threaded applications or for the first thread.  */
12 static struct rpc_thread_variables __libc_tsd_RPC_VARS_mem;
13 __libc_tsd_define (, RPC_VARS)
14
15 /*
16  * Task-variable destructor
17  */
18 void __attribute__ ((section ("__libc_thread_freeres_fn")))
19 __rpc_thread_destroy (void)
20 {
21         struct rpc_thread_variables *tvp = __libc_tsd_get (RPC_VARS);
22
23         if (tvp != NULL) {
24                 __rpc_thread_svc_cleanup ();
25                 __rpc_thread_clnt_cleanup ();
26                 __rpc_thread_key_cleanup ();
27                 free (tvp->clnt_perr_buf_s);
28                 free (tvp->clntraw_private_s);
29                 free (tvp->svcraw_private_s);
30                 free (tvp->authdes_cache_s);
31                 free (tvp->authdes_lru_s);
32                 if (tvp != &__libc_tsd_RPC_VARS_mem)
33                         free (tvp);
34                 __libc_tsd_set (RPC_VARS, NULL);
35         }
36 }
37 #ifdef _LIBC_REENTRANT
38 text_set_element (__libc_thread_subfreeres, __rpc_thread_destroy);
39 #endif
40 text_set_element (__libc_subfreeres, __rpc_thread_destroy);
41
42
43 /*
44  * Initialize RPC multi-threaded operation
45  */
46 static void
47 rpc_thread_multi (void)
48 {
49   __libc_tsd_set (RPC_VARS, &__libc_tsd_RPC_VARS_mem);
50 }
51
52
53 struct rpc_thread_variables *
54 __rpc_thread_variables (void)
55 {
56         __libc_once_define (static, once);
57         struct rpc_thread_variables *tvp;
58
59         tvp = __libc_tsd_get (RPC_VARS);
60         if (tvp == NULL) {
61                 __libc_once (once, rpc_thread_multi);
62                 tvp = __libc_tsd_get (RPC_VARS);
63                 if (tvp == NULL) {
64                         tvp = calloc (1, sizeof *tvp);
65                         if (tvp != NULL)
66                                 __libc_tsd_set (RPC_VARS, tvp);
67                         else
68                                 tvp = __libc_tsd_get (RPC_VARS);
69                 }
70         }
71         return tvp;
72 }
73
74
75 /* Global variables If we're single-threaded, or if this is the first
76    thread using the variable, use the existing global variable.  This
77    provides backwards compatability for existing applications which
78    dynamically link against this code.  */
79 #undef svc_fdset
80 #undef rpc_createerr
81 #undef svc_pollfd
82 #undef svc_max_pollfd
83
84 fd_set *
85 __rpc_thread_svc_fdset (void)
86 {
87         struct rpc_thread_variables *tvp;
88
89         tvp = __rpc_thread_variables ();
90         if (tvp == &__libc_tsd_RPC_VARS_mem)
91                 return &svc_fdset;
92         return &tvp->svc_fdset_s;
93 }
94 libc_hidden_def (__rpc_thread_svc_fdset)
95
96 struct rpc_createerr *
97 __rpc_thread_createerr (void)
98 {
99         struct rpc_thread_variables *tvp;
100
101         tvp = __rpc_thread_variables ();
102         if (tvp == &__libc_tsd_RPC_VARS_mem)
103                 return &rpc_createerr;
104         return &tvp->rpc_createerr_s;
105 }
106 libc_hidden_def (__rpc_thread_createerr)
107
108 struct pollfd **
109 __rpc_thread_svc_pollfd (void)
110 {
111         struct rpc_thread_variables *tvp;
112
113         tvp = __rpc_thread_variables ();
114         if (tvp == &__libc_tsd_RPC_VARS_mem)
115                 return &svc_pollfd;
116         return &tvp->svc_pollfd_s;
117 }
118 libc_hidden_def (__rpc_thread_svc_pollfd)
119
120 int *
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 libc_hidden_def (__rpc_thread_svc_max_pollfd)
131
132 #endif /* _RPC_THREAD_SAFE_ */