1 /* $NetBSD: res_state.c,v 1.6 2008/04/28 20:23:02 martin Exp $ */ 2 3 /*- 4 * Copyright (c) 2004 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #if defined(LIBC_SCCS) && !defined(lint) 34 __RCSID("$NetBSD: res_state.c,v 1.6 2008/04/28 20:23:02 martin Exp $"); 35 #endif 36 37 #include <sys/types.h> 38 #include <sys/queue.h> 39 #include <arpa/inet.h> 40 #include <arpa/nameser.h> 41 #include <stdlib.h> 42 #include <unistd.h> 43 #include <resolv.h> 44 #include <netdb.h> 45 46 #include "pthread.h" 47 #include "pthread_int.h" 48 49 static SLIST_HEAD(, _res_st) res_list = LIST_HEAD_INITIALIZER(&res_list); 50 51 struct _res_st { 52 /* __res_put_state() assumes st_res is the first member. */ 53 struct __res_state st_res; 54 55 SLIST_ENTRY(_res_st) st_list; 56 }; 57 58 static pthread_mutex_t res_mtx = PTHREAD_MUTEX_INITIALIZER; 59 60 res_state __res_state(void); 61 res_state __res_get_state(void); 62 void __res_put_state(res_state); 63 64 #ifdef RES_STATE_DEBUG 65 static void 66 res_state_debug(const char *msg, void *p) 67 { 68 char buf[512]; 69 pthread_t self = pthread__self(); 70 int len = snprintf(buf, sizeof(buf), "%p: %s %p\n", self, msg, p); 71 72 (void)write(STDOUT_FILENO, buf, (size_t)len); 73 } 74 #else 75 #define res_state_debug(a, b) 76 #endif 77 78 79 res_state 80 __res_get_state(void) 81 { 82 res_state res; 83 struct _res_st *st; 84 pthread_mutex_lock(&res_mtx); 85 st = SLIST_FIRST(&res_list); 86 if (st != NULL) { 87 SLIST_REMOVE_HEAD(&res_list, st_list); 88 pthread_mutex_unlock(&res_mtx); 89 res = &st->st_res; 90 res_state_debug("checkout from list", st); 91 } else { 92 pthread_mutex_unlock(&res_mtx); 93 st = malloc(sizeof(*st)); 94 if (st == NULL) { 95 h_errno = NETDB_INTERNAL; 96 return NULL; 97 } 98 res = &st->st_res; 99 res->options = 0; 100 res_state_debug("alloc new", res); 101 } 102 if ((res->options & RES_INIT) == 0) { 103 if (res_ninit(res) == -1) { 104 h_errno = NETDB_INTERNAL; 105 free(st); 106 return NULL; 107 } 108 } 109 return res; 110 } 111 112 void 113 /*ARGSUSED*/ 114 __res_put_state(res_state res) 115 { 116 struct _res_st *st = (struct _res_st *)(void *)res; 117 118 res_state_debug("free", res); 119 pthread_mutex_lock(&res_mtx); 120 SLIST_INSERT_HEAD(&res_list, st, st_list); 121 pthread_mutex_unlock(&res_mtx); 122 } 123 124 /* 125 * This is aliased via a macro to _res; don't allow multi-threaded programs 126 * to use it. 127 */ 128 res_state 129 __res_state(void) 130 { 131 static const char res[] = "_res is not supported for multi-threaded" 132 " programs.\n"; 133 (void)write(STDERR_FILENO, res, sizeof(res) - 1); 134 abort(); 135 return NULL; 136 } 137