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