fix __set_errno
[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)