xref: /freebsd/lib/libc/resolv/mtctxres.c (revision 559a218c9b257775fb249b67945fe4a05b7a6b9f)
165e96449SHajimu UMEMOTO #include <port_before.h>
265e96449SHajimu UMEMOTO #ifdef DO_PTHREADS
365e96449SHajimu UMEMOTO #include <pthread.h>
4ab96eeabSHajimu UMEMOTO #ifdef _LIBC
5ab96eeabSHajimu UMEMOTO #include <pthread_np.h>
6ab96eeabSHajimu UMEMOTO #endif
765e96449SHajimu UMEMOTO #endif
865e96449SHajimu UMEMOTO #include <errno.h>
965e96449SHajimu UMEMOTO #include <netdb.h>
1065e96449SHajimu UMEMOTO #include <stdlib.h>
1165e96449SHajimu UMEMOTO #include <string.h>
1265e96449SHajimu UMEMOTO #include <resolv_mt.h>
1365e96449SHajimu UMEMOTO #include <port_after.h>
1465e96449SHajimu UMEMOTO 
1565e96449SHajimu UMEMOTO #ifdef DO_PTHREADS
1665e96449SHajimu UMEMOTO static pthread_key_t	key;
1765e96449SHajimu UMEMOTO static int		mt_key_initialized = 0;
1865e96449SHajimu UMEMOTO 
1965e96449SHajimu UMEMOTO static int		__res_init_ctx(void);
2065e96449SHajimu UMEMOTO static void		__res_destroy_ctx(void *);
2165e96449SHajimu UMEMOTO 
2265e96449SHajimu UMEMOTO #if defined(sun) && !defined(__GNUC__)
2365e96449SHajimu UMEMOTO #pragma init	(_mtctxres_init)
2465e96449SHajimu UMEMOTO #endif
2565e96449SHajimu UMEMOTO #endif
2665e96449SHajimu UMEMOTO 
2765e96449SHajimu UMEMOTO static mtctxres_t	sharedctx;
2865e96449SHajimu UMEMOTO 
2965e96449SHajimu UMEMOTO #ifdef DO_PTHREADS
3065e96449SHajimu UMEMOTO /*
3165e96449SHajimu UMEMOTO  * Initialize the TSD key. By doing this at library load time, we're
3265e96449SHajimu UMEMOTO  * implicitly running without interference from other threads, so there's
3365e96449SHajimu UMEMOTO  * no need for locking.
3465e96449SHajimu UMEMOTO  */
3565e96449SHajimu UMEMOTO static void
_mtctxres_init(void)3665e96449SHajimu UMEMOTO _mtctxres_init(void) {
3765e96449SHajimu UMEMOTO 	int pthread_keycreate_ret;
3865e96449SHajimu UMEMOTO 
3965e96449SHajimu UMEMOTO 	pthread_keycreate_ret = pthread_key_create(&key, __res_destroy_ctx);
4065e96449SHajimu UMEMOTO 	if (pthread_keycreate_ret == 0)
4165e96449SHajimu UMEMOTO 		mt_key_initialized = 1;
4265e96449SHajimu UMEMOTO }
4365e96449SHajimu UMEMOTO #endif
4465e96449SHajimu UMEMOTO 
45ab96eeabSHajimu UMEMOTO #ifndef _LIBC
4665e96449SHajimu UMEMOTO /*
4765e96449SHajimu UMEMOTO  * To support binaries that used the private MT-safe interface in
4865e96449SHajimu UMEMOTO  * Solaris 8, we still need to provide the __res_enable_mt()
4965e96449SHajimu UMEMOTO  * and __res_disable_mt() entry points. They're do-nothing routines.
5065e96449SHajimu UMEMOTO  */
5165e96449SHajimu UMEMOTO int
__res_enable_mt(void)5265e96449SHajimu UMEMOTO __res_enable_mt(void) {
5365e96449SHajimu UMEMOTO 	return (-1);
5465e96449SHajimu UMEMOTO }
5565e96449SHajimu UMEMOTO 
5665e96449SHajimu UMEMOTO int
__res_disable_mt(void)5765e96449SHajimu UMEMOTO __res_disable_mt(void) {
5865e96449SHajimu UMEMOTO 	return (0);
5965e96449SHajimu UMEMOTO }
60ab96eeabSHajimu UMEMOTO #endif
6165e96449SHajimu UMEMOTO 
6265e96449SHajimu UMEMOTO #ifdef DO_PTHREADS
6365e96449SHajimu UMEMOTO static int
__res_init_ctx(void)6465e96449SHajimu UMEMOTO __res_init_ctx(void) {
6565e96449SHajimu UMEMOTO 
6665e96449SHajimu UMEMOTO 	mtctxres_t	*mt;
6765e96449SHajimu UMEMOTO 	int		ret;
6865e96449SHajimu UMEMOTO 
6965e96449SHajimu UMEMOTO 
7065e96449SHajimu UMEMOTO 	if (pthread_getspecific(key) != 0) {
7165e96449SHajimu UMEMOTO 		/* Already exists */
7265e96449SHajimu UMEMOTO 		return (0);
7365e96449SHajimu UMEMOTO 	}
7465e96449SHajimu UMEMOTO 
75*513004a2SPedro F. Giffuni 	if ((mt = malloc(sizeof(mtctxres_t))) == NULL) {
7665e96449SHajimu UMEMOTO 		errno = ENOMEM;
7765e96449SHajimu UMEMOTO 		return (-1);
7865e96449SHajimu UMEMOTO 	}
7965e96449SHajimu UMEMOTO 
8065e96449SHajimu UMEMOTO 	memset(mt, 0, sizeof (mtctxres_t));
8165e96449SHajimu UMEMOTO 
8265e96449SHajimu UMEMOTO 	if ((ret = pthread_setspecific(key, mt)) != 0) {
8365e96449SHajimu UMEMOTO 		free(mt);
8465e96449SHajimu UMEMOTO 		errno = ret;
8565e96449SHajimu UMEMOTO 		return (-1);
8665e96449SHajimu UMEMOTO 	}
8765e96449SHajimu UMEMOTO 
8865e96449SHajimu UMEMOTO 	return (0);
8965e96449SHajimu UMEMOTO }
9065e96449SHajimu UMEMOTO 
9165e96449SHajimu UMEMOTO static void
__res_destroy_ctx(void * value)9265e96449SHajimu UMEMOTO __res_destroy_ctx(void *value) {
9365e96449SHajimu UMEMOTO 
94*513004a2SPedro F. Giffuni 	free(value);
9565e96449SHajimu UMEMOTO }
9665e96449SHajimu UMEMOTO #endif
9765e96449SHajimu UMEMOTO 
9865e96449SHajimu UMEMOTO mtctxres_t *
___mtctxres(void)9965e96449SHajimu UMEMOTO ___mtctxres(void) {
10065e96449SHajimu UMEMOTO #ifdef DO_PTHREADS
10165e96449SHajimu UMEMOTO 	mtctxres_t	*mt;
10265e96449SHajimu UMEMOTO 
103ab96eeabSHajimu UMEMOTO #ifdef _LIBC
104ab96eeabSHajimu UMEMOTO 	if (pthread_main_np() != 0)
105ab96eeabSHajimu UMEMOTO 		return (&sharedctx);
106ab96eeabSHajimu UMEMOTO #endif
107ab96eeabSHajimu UMEMOTO 
10865e96449SHajimu UMEMOTO 	/*
10965e96449SHajimu UMEMOTO 	 * This if clause should only be executed if we are linking
11065e96449SHajimu UMEMOTO 	 * statically.  When linked dynamically _mtctxres_init() should
11165e96449SHajimu UMEMOTO 	 * be called at binding time due the #pragma above.
11265e96449SHajimu UMEMOTO 	 */
11365e96449SHajimu UMEMOTO 	if (!mt_key_initialized) {
11465e96449SHajimu UMEMOTO 		static pthread_mutex_t keylock = PTHREAD_MUTEX_INITIALIZER;
1152cd19db2SHajimu UMEMOTO                 if (pthread_mutex_lock(&keylock) == 0) {
11665e96449SHajimu UMEMOTO 			_mtctxres_init();
1172cd19db2SHajimu UMEMOTO 			(void) pthread_mutex_unlock(&keylock);
1182cd19db2SHajimu UMEMOTO 		}
11965e96449SHajimu UMEMOTO 	}
12065e96449SHajimu UMEMOTO 
12165e96449SHajimu UMEMOTO 	/*
12265e96449SHajimu UMEMOTO 	 * If we have already been called in this thread return the existing
12365e96449SHajimu UMEMOTO 	 * context.  Otherwise recreat a new context and return it.  If
12465e96449SHajimu UMEMOTO 	 * that fails return a global context.
12565e96449SHajimu UMEMOTO 	 */
12665e96449SHajimu UMEMOTO 	if (mt_key_initialized) {
127*513004a2SPedro F. Giffuni 		if (((mt = pthread_getspecific(key)) != NULL) ||
12865e96449SHajimu UMEMOTO 		    (__res_init_ctx() == 0 &&
129*513004a2SPedro F. Giffuni 		     (mt = pthread_getspecific(key)) != NULL)) {
13065e96449SHajimu UMEMOTO 			return (mt);
13165e96449SHajimu UMEMOTO 		}
13265e96449SHajimu UMEMOTO 	}
13365e96449SHajimu UMEMOTO #endif
13465e96449SHajimu UMEMOTO 	return (&sharedctx);
13565e96449SHajimu UMEMOTO }
136