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