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