mtctxres.c revision 156952
11556Srgrimes#include <port_before.h>
21556Srgrimes#ifdef DO_PTHREADS
31556Srgrimes#include <pthread.h>
41556Srgrimes#endif
51556Srgrimes#include <errno.h>
61556Srgrimes#include <netdb.h>
71556Srgrimes#include <stdlib.h>
81556Srgrimes#include <string.h>
91556Srgrimes#include <resolv_mt.h>
101556Srgrimes#include <irs.h>
111556Srgrimes#include <port_after.h>
121556Srgrimes
131556Srgrimes#ifdef DO_PTHREADS
141556Srgrimesstatic pthread_key_t	key;
151556Srgrimesstatic int		mt_key_initialized = 0;
161556Srgrimes
171556Srgrimesstatic int		__res_init_ctx(void);
181556Srgrimesstatic void		__res_destroy_ctx(void *);
191556Srgrimes
201556Srgrimes#if defined(sun) && !defined(__GNUC__)
211556Srgrimes#pragma init	(_mtctxres_init)
221556Srgrimes#endif
231556Srgrimes#endif
241556Srgrimes
251556Srgrimesstatic mtctxres_t	sharedctx;
261556Srgrimes
271556Srgrimes#ifdef DO_PTHREADS
281556Srgrimes/*
291556Srgrimes * Initialize the TSD key. By doing this at library load time, we're
301556Srgrimes * implicitly running without interference from other threads, so there's
311556Srgrimes * no need for locking.
321556Srgrimes */
331556Srgrimesstatic void
3420425Ssteve_mtctxres_init(void) {
351556Srgrimes	int pthread_keycreate_ret;
361556Srgrimes
371556Srgrimes	pthread_keycreate_ret = pthread_key_create(&key, __res_destroy_ctx);
381556Srgrimes	if (pthread_keycreate_ret == 0)
391556Srgrimes		mt_key_initialized = 1;
4036150Scharnier}
4136150Scharnier#endif
4236150Scharnier
431556Srgrimes/*
4499110Sobrien * To support binaries that used the private MT-safe interface in
4599110Sobrien * Solaris 8, we still need to provide the __res_enable_mt()
461556Srgrimes * and __res_disable_mt() entry points. They're do-nothing routines.
4717987Speter */
481556Srgrimesint
4917987Speter__res_enable_mt(void) {
5017987Speter	return (-1);
511556Srgrimes}
5217525Sache
5359214Simpint
5417525Sache__res_disable_mt(void) {
551556Srgrimes	return (0);
561556Srgrimes}
571556Srgrimes
581556Srgrimes#ifdef DO_PTHREADS
591556Srgrimesstatic int
601556Srgrimes__res_init_ctx(void) {
611556Srgrimes
6217987Speter	mtctxres_t	*mt;
631556Srgrimes	int		ret;
641556Srgrimes
651556Srgrimes
661556Srgrimes	if (pthread_getspecific(key) != 0) {
671556Srgrimes		/* Already exists */
6817987Speter		return (0);
691556Srgrimes	}
701556Srgrimes
711556Srgrimes	if ((mt = malloc(sizeof (mtctxres_t))) == 0) {
721556Srgrimes		errno = ENOMEM;
7317987Speter		return (-1);
7420425Ssteve	}
75223060Sjilles
761556Srgrimes	memset(mt, 0, sizeof (mtctxres_t));
771556Srgrimes
781556Srgrimes	if ((ret = pthread_setspecific(key, mt)) != 0) {
79200998Sjilles		free(mt);
80221669Sjilles		errno = ret;
811556Srgrimes		return (-1);
82231790Sjilles	}
83222957Sjilles
84213811Sobrien	return (0);
851556Srgrimes}
861556Srgrimes
871556Srgrimesstatic void
881556Srgrimes__res_destroy_ctx(void *value) {
891556Srgrimes
901556Srgrimes	mtctxres_t	*mt = (mtctxres_t *)value;
911556Srgrimes
921556Srgrimes	if (mt != 0)
931556Srgrimes		free(mt);
9417987Speter}
9590111Simp#endif
9617987Speter
97222957Sjillesmtctxres_t *
981556Srgrimes___mtctxres(void) {
991556Srgrimes#ifdef DO_PTHREADS
1001556Srgrimes	mtctxres_t	*mt;
10117525Sache
102221669Sjilles	/*
1031556Srgrimes	 * This if clause should only be executed if we are linking
104200998Sjilles	 * statically.  When linked dynamically _mtctxres_init() should
10520425Ssteve	 * be called at binding time due the #pragma above.
10620425Ssteve	 */
10720425Ssteve	if (!mt_key_initialized) {
10820425Ssteve		static pthread_mutex_t keylock = PTHREAD_MUTEX_INITIALIZER;
10920425Ssteve                pthread_mutex_lock(&keylock);
11020425Ssteve		_mtctxres_init();
11120425Ssteve                pthread_mutex_unlock(&keylock);
11220425Ssteve	}
11320425Ssteve
11420425Ssteve	/*
11520425Ssteve	 * If we have already been called in this thread return the existing
11620425Ssteve	 * context.  Otherwise recreat a new context and return it.  If
11720425Ssteve	 * that fails return a global context.
118220978Sjilles	 */
119220978Sjilles	if (mt_key_initialized) {
120218306Sjilles		if (((mt = pthread_getspecific(key)) != 0) ||
1211556Srgrimes		    (__res_init_ctx() == 0 &&
122215567Sjilles		     (mt = pthread_getspecific(key)) != 0)) {
123215567Sjilles			return (mt);
1241556Srgrimes		}
1251556Srgrimes	}
1261556Srgrimes#endif
1271556Srgrimes	return (&sharedctx);
1281556Srgrimes}
1291556Srgrimes