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