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))) == 0) { |
---|
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 | mtctxres_t *mt = (mtctxres_t *)value; |
---|
98 | |
---|
99 | if (mt != 0) |
---|
100 | free(mt); |
---|
101 | } |
---|
102 | #endif |
---|
103 | |
---|
104 | mtctxres_t * |
---|
105 | ___mtctxres(void) { |
---|
106 | #ifdef DO_PTHREADS |
---|
107 | mtctxres_t *mt; |
---|
108 | |
---|
109 | #ifdef _LIBC |
---|
110 | if (pthread_main_np() != 0) |
---|
111 | return (&sharedctx); |
---|
112 | #endif |
---|
113 | |
---|
114 | /* |
---|
115 | * This if clause should only be executed if we are linking |
---|
116 | * statically. When linked dynamically _mtctxres_init() should |
---|
117 | * be called at binding time due the #pragma above. |
---|
118 | */ |
---|
119 | if (!mt_key_initialized) { |
---|
120 | static pthread_mutex_t keylock = PTHREAD_MUTEX_INITIALIZER; |
---|
121 | if (pthread_mutex_lock(&keylock) == 0) { |
---|
122 | _mtctxres_init(); |
---|
123 | (void) pthread_mutex_unlock(&keylock); |
---|
124 | } |
---|
125 | } |
---|
126 | |
---|
127 | /* |
---|
128 | * If we have already been called in this thread return the existing |
---|
129 | * context. Otherwise recreat a new context and return it. If |
---|
130 | * that fails return a global context. |
---|
131 | */ |
---|
132 | if (mt_key_initialized) { |
---|
133 | if (((mt = pthread_getspecific(key)) != 0) || |
---|
134 | (__res_init_ctx() == 0 && |
---|
135 | (mt = pthread_getspecific(key)) != 0)) { |
---|
136 | return (mt); |
---|
137 | } |
---|
138 | } |
---|
139 | #endif |
---|
140 | return (&sharedctx); |
---|
141 | } |
---|