do not rely on libc providing TEMP_FAILURE_RETRY
[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)