xref: /netbsd-src/lib/libpthread/res_state.c (revision 65d37ced8e5100803ee57a3724ac09d1e2b6333f)
1*65d37cedSriastradh /*	$NetBSD: res_state.c,v 1.8 2024/12/15 11:34:14 riastradh Exp $	*/
29b99e159Schristos 
39b99e159Schristos /*-
49b99e159Schristos  * Copyright (c) 2004 The NetBSD Foundation, Inc.
59b99e159Schristos  * All rights reserved.
69b99e159Schristos  *
79b99e159Schristos  * This code is derived from software contributed to The NetBSD Foundation
89b99e159Schristos  * by Christos Zoulas.
99b99e159Schristos  *
109b99e159Schristos  * Redistribution and use in source and binary forms, with or without
119b99e159Schristos  * modification, are permitted provided that the following conditions
129b99e159Schristos  * are met:
139b99e159Schristos  * 1. Redistributions of source code must retain the above copyright
149b99e159Schristos  *    notice, this list of conditions and the following disclaimer.
159b99e159Schristos  * 2. Redistributions in binary form must reproduce the above copyright
169b99e159Schristos  *    notice, this list of conditions and the following disclaimer in the
179b99e159Schristos  *    documentation and/or other materials provided with the distribution.
189b99e159Schristos  *
199b99e159Schristos  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
209b99e159Schristos  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
219b99e159Schristos  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
229b99e159Schristos  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
239b99e159Schristos  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
249b99e159Schristos  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
259b99e159Schristos  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
269b99e159Schristos  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
279b99e159Schristos  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
289b99e159Schristos  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
299b99e159Schristos  * POSSIBILITY OF SUCH DAMAGE.
309b99e159Schristos  */
319b99e159Schristos 
329b99e159Schristos #include <sys/cdefs.h>
339b99e159Schristos #if defined(LIBC_SCCS) && !defined(lint)
34*65d37cedSriastradh __RCSID("$NetBSD: res_state.c,v 1.8 2024/12/15 11:34:14 riastradh Exp $");
359b99e159Schristos #endif
369b99e159Schristos 
377adb4107Sriastradh /* Need to use libc-private names for atomic operations. */
387adb4107Sriastradh #include "../../common/lib/libc/atomic/atomic_op_namespace.h"
397adb4107Sriastradh 
409b99e159Schristos #include <sys/types.h>
419b99e159Schristos #include <sys/queue.h>
429b99e159Schristos #include <arpa/inet.h>
439b99e159Schristos #include <arpa/nameser.h>
449b99e159Schristos #include <stdlib.h>
459b99e159Schristos #include <unistd.h>
469b99e159Schristos #include <resolv.h>
47556949a6Schristos #include <netdb.h>
489b99e159Schristos 
499b99e159Schristos #include "pthread.h"
509b99e159Schristos #include "pthread_int.h"
519b99e159Schristos 
5293b9ee23Schristos static SLIST_HEAD(, _res_st) res_list = LIST_HEAD_INITIALIZER(&res_list);
539b99e159Schristos 
5493b9ee23Schristos struct _res_st {
5593b9ee23Schristos 	/* __res_put_state() assumes st_res is the first member. */
569b99e159Schristos 	struct __res_state	st_res;
5793b9ee23Schristos 
5893b9ee23Schristos 	SLIST_ENTRY(_res_st)	st_list;
599b99e159Schristos };
609b99e159Schristos 
619b99e159Schristos static pthread_mutex_t res_mtx = PTHREAD_MUTEX_INITIALIZER;
629b99e159Schristos 
637168861fSchristos res_state __res_state(void);
649b99e159Schristos res_state __res_get_state(void);
659b99e159Schristos void __res_put_state(res_state);
669b99e159Schristos 
679b99e159Schristos #ifdef RES_STATE_DEBUG
689b99e159Schristos static void
699b99e159Schristos res_state_debug(const char *msg, void *p)
709b99e159Schristos {
719b99e159Schristos 	char buf[512];
7215e9cec1Sad 	pthread_t self = pthread__self();
739b99e159Schristos 	int len = snprintf(buf, sizeof(buf), "%p: %s %p\n", self, msg, p);
749b99e159Schristos 
759b99e159Schristos 	(void)write(STDOUT_FILENO, buf, (size_t)len);
769b99e159Schristos }
779b99e159Schristos #else
789b99e159Schristos #define res_state_debug(a, b)
799b99e159Schristos #endif
809b99e159Schristos 
819b99e159Schristos 
829b99e159Schristos res_state
839b99e159Schristos __res_get_state(void)
849b99e159Schristos {
859b99e159Schristos 	res_state res;
8693b9ee23Schristos 	struct _res_st *st;
879b99e159Schristos 	pthread_mutex_lock(&res_mtx);
8893b9ee23Schristos 	st = SLIST_FIRST(&res_list);
899b99e159Schristos 	if (st != NULL) {
9093b9ee23Schristos 		SLIST_REMOVE_HEAD(&res_list, st_list);
91556949a6Schristos 		pthread_mutex_unlock(&res_mtx);
9293b9ee23Schristos 		res = &st->st_res;
9393b9ee23Schristos 		res_state_debug("checkout from list", st);
9493b9ee23Schristos 	} else {
9593b9ee23Schristos 		pthread_mutex_unlock(&res_mtx);
96*65d37cedSriastradh 		st = calloc(1, sizeof(*st));
9793b9ee23Schristos 		if (st == NULL) {
98556949a6Schristos 			h_errno = NETDB_INTERNAL;
99556949a6Schristos 			return NULL;
100556949a6Schristos 		}
10193b9ee23Schristos 		res = &st->st_res;
102556949a6Schristos 		res->options = 0;
1039b99e159Schristos 		res_state_debug("alloc new", res);
1049b99e159Schristos 	}
10593b9ee23Schristos 	if ((res->options & RES_INIT) == 0) {
10693b9ee23Schristos 		if (res_ninit(res) == -1) {
107556949a6Schristos 			h_errno = NETDB_INTERNAL;
10893b9ee23Schristos 			free(st);
109556949a6Schristos 			return NULL;
110556949a6Schristos 		}
11193b9ee23Schristos 	}
1129b99e159Schristos 	return res;
1139b99e159Schristos }
1149b99e159Schristos 
1159b99e159Schristos void
1169b99e159Schristos /*ARGSUSED*/
1179b99e159Schristos __res_put_state(res_state res)
1189b99e159Schristos {
11993b9ee23Schristos 	struct _res_st *st = (struct _res_st *)(void *)res;
12093b9ee23Schristos 
1219b99e159Schristos 	res_state_debug("free", res);
12293b9ee23Schristos 	pthread_mutex_lock(&res_mtx);
12393b9ee23Schristos 	SLIST_INSERT_HEAD(&res_list, st, st_list);
1249b99e159Schristos 	pthread_mutex_unlock(&res_mtx);
1259b99e159Schristos }
1267168861fSchristos 
1277168861fSchristos /*
1287168861fSchristos  * This is aliased via a macro to _res; don't allow multi-threaded programs
1297168861fSchristos  * to use it.
1307168861fSchristos  */
1317168861fSchristos res_state
1327168861fSchristos __res_state(void)
1337168861fSchristos {
1347168861fSchristos 	static const char res[] = "_res is not supported for multi-threaded"
1357168861fSchristos 	    " programs.\n";
1367168861fSchristos 	(void)write(STDERR_FILENO, res, sizeof(res) - 1);
1377168861fSchristos 	abort();
1387168861fSchristos 	return NULL;
1397168861fSchristos }
140