fix build with uclibc-ng
[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 /* Variable used in non-threaded applications or for the first thread. */
17 static struct rpc_thread_variables __libc_tsd_RPC_VARS_mem;
18 __libc_tsd_define (, RPC_VARS)
19
20 /*
21 * Task-variable destructor
22 */
23 void
24 __rpc_thread_destroy (void)
25 {
26 struct rpc_thread_variables *tvp = __libc_tsd_get (RPC_VARS);
27
28 if (tvp != NULL && tvp != &__libc_tsd_RPC_VARS_mem) {
29 __rpc_thread_svc_cleanup ();
30 __rpc_thread_clnt_cleanup ();
31 /*__rpc_thread_key_cleanup (); */
32 free (tvp->authnone_private_s);
33 free (tvp->clnt_perr_buf_s);
34 free (tvp->clntraw_private_s);
35 free (tvp->svcraw_private_s);
36 free (tvp->authdes_cache_s);
37 free (tvp->authdes_lru_s);
38 free (tvp);
39 __libc_tsd_set (RPC_VARS, NULL);
40 }
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 __UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
53
54 struct rpc_thread_variables attribute_hidden *
55 __rpc_thread_variables (void)
56 {
57 struct rpc_thread_variables *tvp;
58
59 __UCLIBC_MUTEX_LOCK(mylock);
60 tvp = __libc_tsd_get (RPC_VARS);
61 if (tvp == NULL) {
62 rpc_thread_multi();
63 tvp = __libc_tsd_get (RPC_VARS);
64 if (tvp == NULL) {
65 tvp = calloc (1, sizeof *tvp);
66 if (tvp != NULL)
67 __libc_tsd_set (RPC_VARS, tvp);
68 else
69 tvp = __libc_tsd_get (RPC_VARS);
70 }
71 }
72 __UCLIBC_MUTEX_UNLOCK(mylock);
73 return tvp;
74 }
75
76
77 /* Global variables If we're single-threaded, or if this is the first
78 thread using the variable, use the existing global variable. This
79 provides backwards compatability for existing applications which
80 dynamically link against this code. */
81 #undef svc_fdset
82 #undef rpc_createerr
83 #undef svc_pollfd
84 #undef svc_max_pollfd
85
86 fd_set *
87 __rpc_thread_svc_fdset (void)
88 {
89 struct rpc_thread_variables *tvp;
90
91 tvp = __rpc_thread_variables ();
92 if (tvp == &__libc_tsd_RPC_VARS_mem)
93 return &svc_fdset;
94 return &tvp->svc_fdset_s;
95 }
96
97 struct rpc_createerr *
98 __rpc_thread_createerr (void)
99 {
100 struct rpc_thread_variables *tvp;
101
102 tvp = __rpc_thread_variables ();
103 if (tvp == &__libc_tsd_RPC_VARS_mem)
104 return &rpc_createerr;
105 return &tvp->rpc_createerr_s;
106 }
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
119 int *
120 __rpc_thread_svc_max_pollfd (void)
121 {
122 struct rpc_thread_variables *tvp;
123
124 tvp = __rpc_thread_variables ();
125 if (tvp == &__libc_tsd_RPC_VARS_mem)
126 return &svc_max_pollfd;
127 return &tvp->svc_max_pollfd_s;
128 }
129 #else
130
131 #undef svc_fdset
132 #undef rpc_createerr
133 #undef svc_pollfd
134 #undef svc_max_pollfd
135
136 extern fd_set svc_fdset;
137 fd_set * __rpc_thread_svc_fdset (void)
138 {
139 return &(svc_fdset);
140 }
141
142 extern struct rpc_createerr rpc_createerr;
143 struct rpc_createerr * __rpc_thread_createerr (void)
144 {
145 return &(rpc_createerr);
146 }
147
148 extern struct pollfd *svc_pollfd;
149 struct pollfd ** __rpc_thread_svc_pollfd (void)
150 {
151 return &(svc_pollfd);
152 }
153
154 extern int svc_max_pollfd;
155 int * __rpc_thread_svc_max_pollfd (void)
156 {
157 return &(svc_max_pollfd);
158 }
159
160 #endif /* __UCLIBC_HAS_THREADS__ */
161
162 libc_hidden_def(__rpc_thread_svc_fdset)
163 libc_hidden_def(__rpc_thread_createerr)
164 libc_hidden_def(__rpc_thread_svc_pollfd)
165 libc_hidden_def(__rpc_thread_svc_max_pollfd)