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