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