1198160Srrs#include <sys/cdefs.h> 2198160Srrs__FBSDID("$FreeBSD$"); 3198160Srrs 4198160Srrs#include <port_before.h> 5198160Srrs#ifdef DO_PTHREADS 6198160Srrs#include <pthread.h> 7198160Srrs#ifdef _LIBC 8198160Srrs#include <pthread_np.h> 9198160Srrs#endif 10198160Srrs#endif 11198160Srrs#include <errno.h> 12198160Srrs#include <netdb.h> 13198160Srrs#include <stdlib.h> 14198160Srrs#include <string.h> 15198160Srrs#include <resolv_mt.h> 16198160Srrs#include <port_after.h> 17198160Srrs 18198160Srrs#ifdef DO_PTHREADS 19198160Srrsstatic pthread_key_t key; 20198160Srrsstatic int mt_key_initialized = 0; 21198160Srrs 22198160Srrsstatic int __res_init_ctx(void); 23198160Srrsstatic void __res_destroy_ctx(void *); 24198160Srrs 25198160Srrs#if defined(sun) && !defined(__GNUC__) 26198160Srrs#pragma init (_mtctxres_init) 27198160Srrs#endif 28198160Srrs#endif 29198160Srrs 30198160Srrsstatic mtctxres_t sharedctx; 31198160Srrs 32198160Srrs#ifdef DO_PTHREADS 33198160Srrs/* 34198160Srrs * Initialize the TSD key. By doing this at library load time, we're 35198160Srrs * implicitly running without interference from other threads, so there's 36198160Srrs * no need for locking. 37198160Srrs */ 38198160Srrsstatic void 39198160Srrs_mtctxres_init(void) { 40198160Srrs int pthread_keycreate_ret; 41198160Srrs 42198160Srrs pthread_keycreate_ret = pthread_key_create(&key, __res_destroy_ctx); 43198160Srrs if (pthread_keycreate_ret == 0) 44198160Srrs mt_key_initialized = 1; 45198160Srrs} 46198160Srrs#endif 47198160Srrs 48198160Srrs#ifndef _LIBC 49198160Srrs/* 50198160Srrs * To support binaries that used the private MT-safe interface in 51198160Srrs * Solaris 8, we still need to provide the __res_enable_mt() 52198160Srrs * and __res_disable_mt() entry points. They're do-nothing routines. 53198160Srrs */ 54198160Srrsint 55198160Srrs__res_enable_mt(void) { 56198160Srrs return (-1); 57198160Srrs} 58198160Srrs 59198160Srrsint 60198160Srrs__res_disable_mt(void) { 61198160Srrs return (0); 62198160Srrs} 63198160Srrs#endif 64198160Srrs 65198160Srrs#ifdef DO_PTHREADS 66198160Srrsstatic int 67198160Srrs__res_init_ctx(void) { 68198160Srrs 69198160Srrs mtctxres_t *mt; 70198160Srrs int ret; 71198160Srrs 72198160Srrs 73198160Srrs if (pthread_getspecific(key) != 0) { 74198160Srrs /* Already exists */ 75198160Srrs return (0); 76198160Srrs } 77198160Srrs 78198160Srrs if ((mt = malloc(sizeof (mtctxres_t))) == 0) { 79198160Srrs errno = ENOMEM; 80198160Srrs return (-1); 81198160Srrs } 82198160Srrs 83198160Srrs memset(mt, 0, sizeof (mtctxres_t)); 84198160Srrs 85198160Srrs if ((ret = pthread_setspecific(key, mt)) != 0) { 86198160Srrs free(mt); 87198160Srrs errno = ret; 88198160Srrs return (-1); 89198160Srrs } 90198160Srrs 91198160Srrs return (0); 92198160Srrs} 93198160Srrs 94198160Srrsstatic void 95198160Srrs__res_destroy_ctx(void *value) { 96198160Srrs 97198160Srrs mtctxres_t *mt = (mtctxres_t *)value; 98198160Srrs 99198160Srrs if (mt != 0) 100198160Srrs free(mt); 101198160Srrs} 102198160Srrs#endif 103198160Srrs 104198160Srrsmtctxres_t * 105198160Srrs___mtctxres(void) { 106198160Srrs#ifdef DO_PTHREADS 107198160Srrs mtctxres_t *mt; 108198160Srrs 109198160Srrs#ifdef _LIBC 110198160Srrs if (pthread_main_np() != 0) 111198160Srrs return (&sharedctx); 112198160Srrs#endif 113198160Srrs 114198160Srrs /* 115198160Srrs * This if clause should only be executed if we are linking 116198160Srrs * statically. When linked dynamically _mtctxres_init() should 117198160Srrs * be called at binding time due the #pragma above. 118198160Srrs */ 119198160Srrs if (!mt_key_initialized) { 120198160Srrs static pthread_mutex_t keylock = PTHREAD_MUTEX_INITIALIZER; 121198160Srrs if (pthread_mutex_lock(&keylock) == 0) { 122198160Srrs _mtctxres_init(); 123198160Srrs (void) pthread_mutex_unlock(&keylock); 124198160Srrs } 125198160Srrs } 126198160Srrs 127198160Srrs /* 128198160Srrs * If we have already been called in this thread return the existing 129198160Srrs * context. Otherwise recreat a new context and return it. If 130198160Srrs * that fails return a global context. 131198160Srrs */ 132198160Srrs if (mt_key_initialized) { 133198160Srrs if (((mt = pthread_getspecific(key)) != 0) || 134198160Srrs (__res_init_ctx() == 0 && 135198160Srrs (mt = pthread_getspecific(key)) != 0)) { 136198160Srrs return (mt); 137198160Srrs } 138198160Srrs } 139198160Srrs#endif 140198160Srrs return (&sharedctx); 141198160Srrs} 142198160Srrs