Sweep-fix comparing pointers with 0 (and assigning 0 to pointers).
[dragonfly.git] / lib / libc / resolv / mtctxres.c
1 #include <port_before.h>
2 #ifdef DO_PTHREADS
3 #include <pthread.h>
4 #ifdef _LIBC
5 #include <pthread_np.h>
6 #endif
7 #endif
8 #include <errno.h>
9 #include <netdb.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include "resolv_mt.h"
13 #ifndef _LIBC
14 #include <irs.h>
15 #endif
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 #endif
59
60 int
61 __res_disable_mt(void) {
62         return (0);
63 }
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         mtctxres_t      *mt = (mtctxres_t *)value;
98
99         if (mt != NULL)
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         /*
116          * This if clause should only be executed if we are linking
117          * statically.  When linked dynamically _mtctxres_init() should
118          * be called at binding time due the #pragma above.
119          */
120         if (!mt_key_initialized) {
121                 static pthread_mutex_t keylock = PTHREAD_MUTEX_INITIALIZER;
122                 if (pthread_mutex_lock(&keylock) == 0) {
123                         _mtctxres_init();
124                         (void) pthread_mutex_unlock(&keylock);
125                 }
126         }
127
128         /*
129          * If we have already been called in this thread return the existing
130          * context.  Otherwise recreat a new context and return it.  If
131          * that fails return a global context.
132          */
133         if (mt_key_initialized) {
134                 if (((mt = pthread_getspecific(key)) != NULL) ||
135                     (__res_init_ctx() == 0 &&
136                      (mt = pthread_getspecific(key)) != NULL)) {
137                         return (mt);
138                 }
139         }
140 #endif
141         return (&sharedctx);
142 }