71303b2be7ef49aa2788c53193bfa34782cf890c
[project/librpc-uclibc.git] / rpc_thread.c
1 /*
2 * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
3 *
4 * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
5 */
6
7 #define __FORCE_GLIBC
8 #include <features.h>
9 #include <stdio.h>
10 #include <assert.h>
11 #include "rpc_private.h"
12
13
14 #ifdef __UCLIBC_HAS_THREADS__
15
16 #include <bits/libc-tsd.h>
17 #include <bits/libc-lock.h>
18
19 /* Variable used in non-threaded applications or for the first thread. */
20 static struct rpc_thread_variables __libc_tsd_RPC_VARS_mem;
21 __libc_tsd_define (, RPC_VARS)
22
23 /*
24 * Task-variable destructor
25 */
26 void
27 __rpc_thread_destroy (void)
28 {
29 struct rpc_thread_variables *tvp = __libc_tsd_get (RPC_VARS);
30
31 if (tvp != NULL && tvp != &__libc_tsd_RPC_VARS_mem) {
32 __rpc_thread_svc_cleanup ();
33 __rpc_thread_clnt_cleanup ();
34 /*__rpc_thread_key_cleanup (); */
35 free (tvp->authnone_private_s);
36 free (tvp->clnt_perr_buf_s);
37 free (tvp->clntraw_private_s);
38 free (tvp->svcraw_private_s);
39 free (tvp->authdes_cache_s);
40 free (tvp->authdes_lru_s);
41 free (tvp);
42 __libc_tsd_set (RPC_VARS, NULL);
43 }
44 }
45
46 /*
47 * Initialize RPC multi-threaded operation
48 */
49 static void
50 rpc_thread_multi (void)
51 {
52 __libc_tsd_set (RPC_VARS, &__libc_tsd_RPC_VARS_mem);
53 }
54
55
56 struct rpc_thread_variables attribute_hidden *
57 __rpc_thread_variables (void)
58 {
59 __libc_once_define (static, once);
60 struct rpc_thread_variables *tvp;
61
62 tvp = __libc_tsd_get (RPC_VARS);
63 if (tvp == NULL) {
64 __libc_once (once, rpc_thread_multi);
65 tvp = __libc_tsd_get (RPC_VARS);
66 if (tvp == NULL) {
67 tvp = calloc (1, sizeof *tvp);
68 if (tvp != NULL)
69 __libc_tsd_set (RPC_VARS, tvp);
70 else
71 tvp = __libc_tsd_get (RPC_VARS);
72 }
73 }
74 return tvp;
75 }
76
77
78 /* Global variables If we're single-threaded, or if this is the first
79 thread using the variable, use the existing global variable. This
80 provides backwards compatability for existing applications which
81 dynamically link against this code. */
82 #undef svc_fdset
83 #undef rpc_createerr
84 #undef svc_pollfd
85 #undef svc_max_pollfd
86
87 fd_set *
88 __rpc_thread_svc_fdset (void)
89 {
90 struct rpc_thread_variables *tvp;
91
92 tvp = __rpc_thread_variables ();
93 if (tvp == &__libc_tsd_RPC_VARS_mem)
94 return &svc_fdset;
95 return &tvp->svc_fdset_s;
96 }
97
98 struct rpc_createerr *
99 __rpc_thread_createerr (void)
100 {
101 struct rpc_thread_variables *tvp;
102
103 tvp = __rpc_thread_variables ();
104 if (tvp == &__libc_tsd_RPC_VARS_mem)
105 return &rpc_createerr;
106 return &tvp->rpc_createerr_s;
107 }
108
109 struct pollfd **
110 __rpc_thread_svc_pollfd (void)
111 {
112 struct rpc_thread_variables *tvp;
113
114 tvp = __rpc_thread_variables ();
115 if (tvp == &__libc_tsd_RPC_VARS_mem)
116 return &svc_pollfd;
117 return &tvp->svc_pollfd_s;
118 }
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 #else
131
132 #undef svc_fdset
133 #undef rpc_createerr
134 #undef svc_pollfd
135 #undef svc_max_pollfd
136
137 extern fd_set svc_fdset;
138 fd_set * __rpc_thread_svc_fdset (void)
139 {
140 return &(svc_fdset);
141 }
142
143 extern struct rpc_createerr rpc_createerr;
144 struct rpc_createerr * __rpc_thread_createerr (void)
145 {
146 return &(rpc_createerr);
147 }
148
149 extern struct pollfd *svc_pollfd;
150 struct pollfd ** __rpc_thread_svc_pollfd (void)
151 {
152 return &(svc_pollfd);
153 }
154
155 extern int svc_max_pollfd;
156 int * __rpc_thread_svc_max_pollfd (void)
157 {
158 return &(svc_max_pollfd);
159 }
160
161 #endif /* __UCLIBC_HAS_THREADS__ */
162
163 libc_hidden_def(__rpc_thread_svc_fdset)
164 libc_hidden_def(__rpc_thread_createerr)
165 libc_hidden_def(__rpc_thread_svc_pollfd)
166 libc_hidden_def(__rpc_thread_svc_max_pollfd)