mtctxres.c revision 297790
11638Srgrimes#include <sys/cdefs.h> 21638Srgrimes__FBSDID("$FreeBSD: head/lib/libc/resolv/mtctxres.c 297790 2016-04-10 19:33:58Z pfg $"); 31638Srgrimes 41638Srgrimes#include <port_before.h> 51638Srgrimes#ifdef DO_PTHREADS 61638Srgrimes#include <pthread.h> 71638Srgrimes#ifdef _LIBC 81638Srgrimes#include <pthread_np.h> 91638Srgrimes#endif 101638Srgrimes#endif 111638Srgrimes#include <errno.h> 12263142Seadler#include <netdb.h> 131638Srgrimes#include <stdlib.h> 141638Srgrimes#include <string.h> 151638Srgrimes#include <resolv_mt.h> 161638Srgrimes#include <port_after.h> 171638Srgrimes 181638Srgrimes#ifdef DO_PTHREADS 191638Srgrimesstatic pthread_key_t key; 201638Srgrimesstatic int mt_key_initialized = 0; 211638Srgrimes 221638Srgrimesstatic int __res_init_ctx(void); 231638Srgrimesstatic void __res_destroy_ctx(void *); 241638Srgrimes 251638Srgrimes#if defined(sun) && !defined(__GNUC__) 261638Srgrimes#pragma init (_mtctxres_init) 271638Srgrimes#endif 281638Srgrimes#endif 291638Srgrimes 301638Srgrimesstatic mtctxres_t sharedctx; 311638Srgrimes 321638Srgrimes#ifdef DO_PTHREADS 331638Srgrimes/* 341638Srgrimes * Initialize the TSD key. By doing this at library load time, we're 351638Srgrimes * implicitly running without interference from other threads, so there's 361638Srgrimes * no need for locking. 371638Srgrimes */ 381638Srgrimesstatic void 391638Srgrimes_mtctxres_init(void) { 401638Srgrimes int pthread_keycreate_ret; 411638Srgrimes 421638Srgrimes pthread_keycreate_ret = pthread_key_create(&key, __res_destroy_ctx); 431638Srgrimes if (pthread_keycreate_ret == 0) 441638Srgrimes mt_key_initialized = 1; 451638Srgrimes} 461638Srgrimes#endif 471638Srgrimes 481638Srgrimes#ifndef _LIBC 491638Srgrimes/* 501638Srgrimes * To support binaries that used the private MT-safe interface in 511638Srgrimes * Solaris 8, we still need to provide the __res_enable_mt() 521638Srgrimes * and __res_disable_mt() entry points. They're do-nothing routines. 531638Srgrimes */ 541638Srgrimesint 551638Srgrimes__res_enable_mt(void) { 561638Srgrimes return (-1); 571638Srgrimes} 581638Srgrimes 591638Srgrimesint 601638Srgrimes__res_disable_mt(void) { 611638Srgrimes return (0); 621638Srgrimes} 631638Srgrimes#endif 641638Srgrimes 651638Srgrimes#ifdef DO_PTHREADS 661638Srgrimesstatic int 671638Srgrimes__res_init_ctx(void) { 681638Srgrimes 691638Srgrimes mtctxres_t *mt; 701638Srgrimes int ret; 711638Srgrimes 721638Srgrimes 731638Srgrimes if (pthread_getspecific(key) != 0) { 741638Srgrimes /* Already exists */ 751638Srgrimes return (0); 761638Srgrimes } 771638Srgrimes 781638Srgrimes if ((mt = malloc(sizeof(mtctxres_t))) == NULL) { 791638Srgrimes errno = ENOMEM; 801638Srgrimes return (-1); 811638Srgrimes } 821638Srgrimes 831638Srgrimes memset(mt, 0, sizeof (mtctxres_t)); 841638Srgrimes 851638Srgrimes if ((ret = pthread_setspecific(key, mt)) != 0) { 861638Srgrimes free(mt); 871638Srgrimes errno = ret; 881638Srgrimes return (-1); 891638Srgrimes } 901638Srgrimes 911638Srgrimes return (0); 921638Srgrimes} 931638Srgrimes 941638Srgrimesstatic void 951638Srgrimes__res_destroy_ctx(void *value) { 961638Srgrimes 971638Srgrimes free(value); 981638Srgrimes} 991638Srgrimes#endif 1001638Srgrimes 1011638Srgrimesmtctxres_t * 1021638Srgrimes___mtctxres(void) { 1031638Srgrimes#ifdef DO_PTHREADS 1041638Srgrimes mtctxres_t *mt; 1051638Srgrimes 1061638Srgrimes#ifdef _LIBC 1071638Srgrimes if (pthread_main_np() != 0) 1081638Srgrimes return (&sharedctx); 1091638Srgrimes#endif 1101638Srgrimes 1111638Srgrimes /* 1121638Srgrimes * This if clause should only be executed if we are linking 1131638Srgrimes * statically. When linked dynamically _mtctxres_init() should 1141638Srgrimes * be called at binding time due the #pragma above. 1151638Srgrimes */ 1161638Srgrimes if (!mt_key_initialized) { 1171638Srgrimes static pthread_mutex_t keylock = PTHREAD_MUTEX_INITIALIZER; 1181638Srgrimes if (pthread_mutex_lock(&keylock) == 0) { 1191638Srgrimes _mtctxres_init(); 1201638Srgrimes (void) pthread_mutex_unlock(&keylock); 1211638Srgrimes } 1221638Srgrimes } 1231638Srgrimes 1241638Srgrimes /* 1251638Srgrimes * If we have already been called in this thread return the existing 1261638Srgrimes * context. Otherwise recreat a new context and return it. If 1271638Srgrimes * that fails return a global context. 1281638Srgrimes */ 1291638Srgrimes if (mt_key_initialized) { 1301638Srgrimes if (((mt = pthread_getspecific(key)) != NULL) || 1311638Srgrimes (__res_init_ctx() == 0 && 1321638Srgrimes (mt = pthread_getspecific(key)) != NULL)) { 1331638Srgrimes return (mt); 1341638Srgrimes } 1351638Srgrimes } 1361638Srgrimes#endif 1371638Srgrimes return (&sharedctx); 1381638Srgrimes} 1391638Srgrimes