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