]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - lib/libc/resolv/mtctxres.c
MFH (r325010): don't bother verifying a password that we know is too long.
[FreeBSD/stable/10.git] / lib / libc / resolv / mtctxres.c
1 #include <sys/cdefs.h>
2 __FBSDID("$FreeBSD$");
3
4 #include <port_before.h>
5 #ifdef DO_PTHREADS
6 #include <pthread.h>
7 #ifdef _LIBC
8 #include <pthread_np.h>
9 #endif
10 #endif
11 #include <errno.h>
12 #include <netdb.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <resolv_mt.h>
16 #include <port_after.h>
17
18 #ifdef DO_PTHREADS
19 static pthread_key_t    key;
20 static int              mt_key_initialized = 0;
21
22 static int              __res_init_ctx(void);
23 static void             __res_destroy_ctx(void *);
24
25 #if defined(sun) && !defined(__GNUC__)
26 #pragma init    (_mtctxres_init)
27 #endif
28 #endif
29
30 static mtctxres_t       sharedctx;
31
32 #ifdef DO_PTHREADS
33 /*
34  * Initialize the TSD key. By doing this at library load time, we're
35  * implicitly running without interference from other threads, so there's
36  * no need for locking.
37  */
38 static void
39 _mtctxres_init(void) {
40         int pthread_keycreate_ret;
41
42         pthread_keycreate_ret = pthread_key_create(&key, __res_destroy_ctx);
43         if (pthread_keycreate_ret == 0)
44                 mt_key_initialized = 1;
45 }
46 #endif
47
48 #ifndef _LIBC
49 /*
50  * To support binaries that used the private MT-safe interface in
51  * Solaris 8, we still need to provide the __res_enable_mt()
52  * and __res_disable_mt() entry points. They're do-nothing routines.
53  */
54 int
55 __res_enable_mt(void) {
56         return (-1);
57 }
58
59 int
60 __res_disable_mt(void) {
61         return (0);
62 }
63 #endif
64
65 #ifdef DO_PTHREADS
66 static int
67 __res_init_ctx(void) {
68
69         mtctxres_t      *mt;
70         int             ret;
71
72
73         if (pthread_getspecific(key) != 0) {
74                 /* Already exists */
75                 return (0);
76         }
77
78         if ((mt = malloc(sizeof(mtctxres_t))) == NULL) {
79                 errno = ENOMEM;
80                 return (-1);
81         }
82
83         memset(mt, 0, sizeof (mtctxres_t));
84
85         if ((ret = pthread_setspecific(key, mt)) != 0) {
86                 free(mt);
87                 errno = ret;
88                 return (-1);
89         }
90
91         return (0);
92 }
93
94 static void
95 __res_destroy_ctx(void *value) {
96
97         free(value);
98 }
99 #endif
100
101 mtctxres_t *
102 ___mtctxres(void) {
103 #ifdef DO_PTHREADS
104         mtctxres_t      *mt;
105
106 #ifdef _LIBC
107         if (pthread_main_np() != 0)
108                 return (&sharedctx);
109 #endif
110
111         /*
112          * This if clause should only be executed if we are linking
113          * statically.  When linked dynamically _mtctxres_init() should
114          * be called at binding time due the #pragma above.
115          */
116         if (!mt_key_initialized) {
117                 static pthread_mutex_t keylock = PTHREAD_MUTEX_INITIALIZER;
118                 if (pthread_mutex_lock(&keylock) == 0) {
119                         _mtctxres_init();
120                         (void) pthread_mutex_unlock(&keylock);
121                 }
122         }
123
124         /*
125          * If we have already been called in this thread return the existing
126          * context.  Otherwise recreat a new context and return it.  If
127          * that fails return a global context.
128          */
129         if (mt_key_initialized) {
130                 if (((mt = pthread_getspecific(key)) != NULL) ||
131                     (__res_init_ctx() == 0 &&
132                      (mt = pthread_getspecific(key)) != NULL)) {
133                         return (mt);
134                 }
135         }
136 #endif
137         return (&sharedctx);
138 }