mtctxres.c revision 156952
1156952Sume#include <port_before.h> 2156952Sume#ifdef DO_PTHREADS 3156952Sume#include <pthread.h> 4156952Sume#endif 5156952Sume#include <errno.h> 6156952Sume#include <netdb.h> 7156952Sume#include <stdlib.h> 8156952Sume#include <string.h> 9156952Sume#include <resolv_mt.h> 10156952Sume#include <irs.h> 11156952Sume#include <port_after.h> 12156952Sume 13156952Sume#ifdef DO_PTHREADS 14156952Sumestatic pthread_key_t key; 15156952Sumestatic int mt_key_initialized = 0; 16156952Sume 17156952Sumestatic int __res_init_ctx(void); 18156952Sumestatic void __res_destroy_ctx(void *); 19156952Sume 20156952Sume#if defined(sun) && !defined(__GNUC__) 21156952Sume#pragma init (_mtctxres_init) 22156952Sume#endif 23156952Sume#endif 24156952Sume 25156952Sumestatic mtctxres_t sharedctx; 26156952Sume 27156952Sume#ifdef DO_PTHREADS 28156952Sume/* 29156952Sume * Initialize the TSD key. By doing this at library load time, we're 30156952Sume * implicitly running without interference from other threads, so there's 31156952Sume * no need for locking. 32156952Sume */ 33156952Sumestatic void 34156952Sume_mtctxres_init(void) { 35156952Sume int pthread_keycreate_ret; 36156952Sume 37156952Sume pthread_keycreate_ret = pthread_key_create(&key, __res_destroy_ctx); 38156952Sume if (pthread_keycreate_ret == 0) 39156952Sume mt_key_initialized = 1; 40156952Sume} 41156952Sume#endif 42156952Sume 43156952Sume/* 44156952Sume * To support binaries that used the private MT-safe interface in 45156952Sume * Solaris 8, we still need to provide the __res_enable_mt() 46156952Sume * and __res_disable_mt() entry points. They're do-nothing routines. 47156952Sume */ 48156952Sumeint 49156952Sume__res_enable_mt(void) { 50156952Sume return (-1); 51156952Sume} 52156952Sume 53156952Sumeint 54156952Sume__res_disable_mt(void) { 55156952Sume return (0); 56156952Sume} 57156952Sume 58156952Sume#ifdef DO_PTHREADS 59156952Sumestatic int 60156952Sume__res_init_ctx(void) { 61156952Sume 62156952Sume mtctxres_t *mt; 63156952Sume int ret; 64156952Sume 65156952Sume 66156952Sume if (pthread_getspecific(key) != 0) { 67156952Sume /* Already exists */ 68156952Sume return (0); 69156952Sume } 70156952Sume 71156952Sume if ((mt = malloc(sizeof (mtctxres_t))) == 0) { 72156952Sume errno = ENOMEM; 73156952Sume return (-1); 74156952Sume } 75156952Sume 76156952Sume memset(mt, 0, sizeof (mtctxres_t)); 77156952Sume 78156952Sume if ((ret = pthread_setspecific(key, mt)) != 0) { 79156952Sume free(mt); 80156952Sume errno = ret; 81156952Sume return (-1); 82156952Sume } 83156952Sume 84156952Sume return (0); 85156952Sume} 86156952Sume 87156952Sumestatic void 88156952Sume__res_destroy_ctx(void *value) { 89156952Sume 90156952Sume mtctxres_t *mt = (mtctxres_t *)value; 91156952Sume 92156952Sume if (mt != 0) 93156952Sume free(mt); 94156952Sume} 95156952Sume#endif 96156952Sume 97156952Sumemtctxres_t * 98156952Sume___mtctxres(void) { 99156952Sume#ifdef DO_PTHREADS 100156952Sume mtctxres_t *mt; 101156952Sume 102156952Sume /* 103156952Sume * This if clause should only be executed if we are linking 104156952Sume * statically. When linked dynamically _mtctxres_init() should 105156952Sume * be called at binding time due the #pragma above. 106156952Sume */ 107156952Sume if (!mt_key_initialized) { 108156952Sume static pthread_mutex_t keylock = PTHREAD_MUTEX_INITIALIZER; 109156952Sume pthread_mutex_lock(&keylock); 110156952Sume _mtctxres_init(); 111156952Sume pthread_mutex_unlock(&keylock); 112156952Sume } 113156952Sume 114156952Sume /* 115156952Sume * If we have already been called in this thread return the existing 116156952Sume * context. Otherwise recreat a new context and return it. If 117156952Sume * that fails return a global context. 118156952Sume */ 119156952Sume if (mt_key_initialized) { 120156952Sume if (((mt = pthread_getspecific(key)) != 0) || 121156952Sume (__res_init_ctx() == 0 && 122156952Sume (mt = pthread_getspecific(key)) != 0)) { 123156952Sume return (mt); 124156952Sume } 125156952Sume } 126156952Sume#endif 127156952Sume return (&sharedctx); 128156952Sume} 129