diff options
Diffstat (limited to 'lib/libc/resolv/mtctxres.c')
| -rw-r--r-- | lib/libc/resolv/mtctxres.c | 128 | 
1 files changed, 128 insertions, 0 deletions
| diff --git a/lib/libc/resolv/mtctxres.c b/lib/libc/resolv/mtctxres.c new file mode 100644 index 000000000000..f33cf11e3f42 --- /dev/null +++ b/lib/libc/resolv/mtctxres.c @@ -0,0 +1,128 @@ +#include <port_before.h> +#ifdef DO_PTHREADS +#include <pthread.h> +#endif +#include <errno.h> +#include <netdb.h> +#include <stdlib.h> +#include <string.h> +#include <resolv_mt.h> +#include <irs.h> +#include <port_after.h> + +#ifdef DO_PTHREADS +static pthread_key_t	key; +static int		mt_key_initialized = 0; + +static int		__res_init_ctx(void); +static void		__res_destroy_ctx(void *); + +#if defined(sun) && !defined(__GNUC__) +#pragma init	(_mtctxres_init) +#endif +#endif + +static mtctxres_t	sharedctx; + +#ifdef DO_PTHREADS +/* + * Initialize the TSD key. By doing this at library load time, we're + * implicitly running without interference from other threads, so there's + * no need for locking. + */ +static void +_mtctxres_init(void) { +	int pthread_keycreate_ret; + +	pthread_keycreate_ret = pthread_key_create(&key, __res_destroy_ctx); +	if (pthread_keycreate_ret == 0) +		mt_key_initialized = 1; +} +#endif + +/* + * To support binaries that used the private MT-safe interface in + * Solaris 8, we still need to provide the __res_enable_mt() + * and __res_disable_mt() entry points. They're do-nothing routines. + */ +int +__res_enable_mt(void) { +	return (-1); +} + +int +__res_disable_mt(void) { +	return (0); +} + +#ifdef DO_PTHREADS +static int +__res_init_ctx(void) { + +	mtctxres_t	*mt; +	int		ret; + + +	if (pthread_getspecific(key) != 0) { +		/* Already exists */ +		return (0); +	} + +	if ((mt = malloc(sizeof (mtctxres_t))) == 0) { +		errno = ENOMEM; +		return (-1); +	} + +	memset(mt, 0, sizeof (mtctxres_t)); + +	if ((ret = pthread_setspecific(key, mt)) != 0) { +		free(mt); +		errno = ret; +		return (-1); +	} + +	return (0); +} + +static void +__res_destroy_ctx(void *value) { + +	mtctxres_t	*mt = (mtctxres_t *)value; + +	if (mt != 0) +		free(mt); +} +#endif + +mtctxres_t * +___mtctxres(void) { +#ifdef DO_PTHREADS +	mtctxres_t	*mt; + +	/* +	 * This if clause should only be executed if we are linking +	 * statically.  When linked dynamically _mtctxres_init() should +	 * be called at binding time due the #pragma above. +	 */ +	if (!mt_key_initialized) { +		static pthread_mutex_t keylock = PTHREAD_MUTEX_INITIALIZER; +                pthread_mutex_lock(&keylock); +		_mtctxres_init(); +                pthread_mutex_unlock(&keylock); +	} + +	/* +	 * If we have already been called in this thread return the existing +	 * context.  Otherwise recreat a new context and return it.  If +	 * that fails return a global context. +	 */ +	if (mt_key_initialized) { +		if (((mt = pthread_getspecific(key)) != 0) || +		    (__res_init_ctx() == 0 && +		     (mt = pthread_getspecific(key)) != 0)) { +			return (mt); +		} +	} +#endif +	return (&sharedctx); +} | 
