xref: /netbsd-src/tests/lib/libpthread/h_resolv.c (revision f0d208fdc0f2f0500e7c6a177545488b8a3c70a7)
1*f0d208fdSchristos /* $NetBSD: h_resolv.c,v 1.3 2019/03/06 01:20:15 christos Exp $ */
2ac555471Sjmmv 
3ac555471Sjmmv /*-
4ac555471Sjmmv  * Copyright (c) 2004, 2008 The NetBSD Foundation, Inc.
5ac555471Sjmmv  * All rights reserved.
6ac555471Sjmmv  *
7ac555471Sjmmv  * This code is derived from software contributed to The NetBSD Foundation
8ac555471Sjmmv  * by Christos Zoulas.
9ac555471Sjmmv  *
10ac555471Sjmmv  * Redistribution and use in source and binary forms, with or without
11ac555471Sjmmv  * modification, are permitted provided that the following conditions
12ac555471Sjmmv  * are met:
13ac555471Sjmmv  * 1. Redistributions of source code must retain the above copyright
14ac555471Sjmmv  *    notice, this list of conditions and the following disclaimer.
15ac555471Sjmmv  * 2. Redistributions in binary form must reproduce the above copyright
16ac555471Sjmmv  *    notice, this list of conditions and the following disclaimer in the
17ac555471Sjmmv  *    documentation and/or other materials provided with the distribution.
18ac555471Sjmmv  *
19ac555471Sjmmv  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20ac555471Sjmmv  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21ac555471Sjmmv  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22ac555471Sjmmv  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23ac555471Sjmmv  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24ac555471Sjmmv  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25ac555471Sjmmv  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26ac555471Sjmmv  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27ac555471Sjmmv  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28ac555471Sjmmv  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29ac555471Sjmmv  * POSSIBILITY OF SUCH DAMAGE.
30ac555471Sjmmv  */
31ac555471Sjmmv 
32ac555471Sjmmv #include <sys/cdefs.h>
33ac555471Sjmmv __COPYRIGHT("@(#) Copyright (c) 2008\
34ac555471Sjmmv  The NetBSD Foundation, inc. All rights reserved.");
35*f0d208fdSchristos __RCSID("$NetBSD: h_resolv.c,v 1.3 2019/03/06 01:20:15 christos Exp $");
36ac555471Sjmmv 
37ac555471Sjmmv #include <pthread.h>
38ac555471Sjmmv #include <stdio.h>
39ac555471Sjmmv #include <netdb.h>
40ac555471Sjmmv #include <stdlib.h>
41ac555471Sjmmv #include <unistd.h>
42ac555471Sjmmv #include <err.h>
43ac555471Sjmmv #include <string.h>
44ac555471Sjmmv #include <stringlist.h>
45ac555471Sjmmv 
46ac555471Sjmmv #define NTHREADS    10
47ac555471Sjmmv #define NHOSTS        100
48ac555471Sjmmv #define WS        " \t\n\r"
49ac555471Sjmmv 
50ac555471Sjmmv static StringList *hosts = NULL;
51ac555471Sjmmv static int debug = 0;
52ac555471Sjmmv static int *ask = NULL;
53ac555471Sjmmv static int *got = NULL;
54ac555471Sjmmv 
55ac555471Sjmmv static void usage(void)  __attribute__((__noreturn__));
56ac555471Sjmmv static void load(const char *);
57ac555471Sjmmv static void resolvone(int);
58ac555471Sjmmv static void *resolvloop(void *);
59*f0d208fdSchristos static pthread_t run(int *);
60ac555471Sjmmv 
61ac555471Sjmmv static pthread_mutex_t stats = PTHREAD_MUTEX_INITIALIZER;
62ac555471Sjmmv 
63ac555471Sjmmv static void
usage(void)64ac555471Sjmmv usage(void)
65ac555471Sjmmv {
66ac555471Sjmmv 	(void)fprintf(stderr,
67ac555471Sjmmv 		"Usage: %s [-d] [-h <nhosts>] [-n <nthreads>] <file> ...\n",
68ac555471Sjmmv 		getprogname());
69ac555471Sjmmv 	exit(1);
70ac555471Sjmmv }
71ac555471Sjmmv 
72ac555471Sjmmv static void
load(const char * fname)73ac555471Sjmmv load(const char *fname)
74ac555471Sjmmv {
75ac555471Sjmmv 	FILE *fp;
76ac555471Sjmmv 	size_t len;
77ac555471Sjmmv 	char *line;
78ac555471Sjmmv 
79ac555471Sjmmv 	if ((fp = fopen(fname, "r")) == NULL)
80*f0d208fdSchristos 		err(EXIT_FAILURE, "Cannot open `%s'", fname);
81ac555471Sjmmv 	while ((line = fgetln(fp, &len)) != NULL) {
82ac555471Sjmmv 		char c = line[len];
83ac555471Sjmmv 		char *ptr;
84ac555471Sjmmv 		line[len] = '\0';
85ac555471Sjmmv 		for (ptr = strtok(line, WS); ptr; ptr = strtok(NULL, WS))
86ac555471Sjmmv 			sl_add(hosts, strdup(ptr));
87ac555471Sjmmv 		line[len] = c;
88ac555471Sjmmv 	}
89ac555471Sjmmv 
90ac555471Sjmmv 	(void)fclose(fp);
91ac555471Sjmmv }
92ac555471Sjmmv 
93ac555471Sjmmv static void
resolvone(int n)94ac555471Sjmmv resolvone(int n)
95ac555471Sjmmv {
96ac555471Sjmmv 	char buf[1024];
97ac555471Sjmmv 	pthread_t self = pthread_self();
98ac555471Sjmmv 	size_t i = (random() & 0x0fffffff) % hosts->sl_cur;
99ac555471Sjmmv 	char *host = hosts->sl_str[i];
100ac555471Sjmmv 	struct addrinfo *res;
101ac555471Sjmmv 	int error, len;
102ac555471Sjmmv 	if (debug) {
103ac555471Sjmmv 		len = snprintf(buf, sizeof(buf), "%p: %d resolving %s %d\n",
104ac555471Sjmmv 			self, n, host, (int)i);
105ac555471Sjmmv 		(void)write(STDOUT_FILENO, buf, len);
106ac555471Sjmmv 	}
107ac555471Sjmmv 	error = getaddrinfo(host, NULL, NULL, &res);
108ac555471Sjmmv 	if (debug) {
109ac555471Sjmmv 		len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
110ac555471Sjmmv 			self, host, error ? "not found" : "ok");
111ac555471Sjmmv 		(void)write(STDOUT_FILENO, buf, len);
112ac555471Sjmmv 	}
113ac555471Sjmmv 	pthread_mutex_lock(&stats);
114ac555471Sjmmv 	ask[i]++;
115ac555471Sjmmv 	got[i] += error == 0;
116ac555471Sjmmv 	pthread_mutex_unlock(&stats);
117ac555471Sjmmv 	if (error == 0)
118ac555471Sjmmv 		freeaddrinfo(res);
119ac555471Sjmmv }
120ac555471Sjmmv 
121ac555471Sjmmv static void *
resolvloop(void * p)122ac555471Sjmmv resolvloop(void *p)
123ac555471Sjmmv {
124ac555471Sjmmv 	int *nhosts = (int *)p;
125ac555471Sjmmv 	if (*nhosts == 0)
126ac555471Sjmmv 		return NULL;
127ac555471Sjmmv 	do
128ac555471Sjmmv 		resolvone(*nhosts);
129ac555471Sjmmv 	while (--(*nhosts));
130ac555471Sjmmv 	return NULL;
131ac555471Sjmmv }
132ac555471Sjmmv 
133*f0d208fdSchristos static pthread_t
run(int * nhosts)134ac555471Sjmmv run(int *nhosts)
135ac555471Sjmmv {
136ac555471Sjmmv 	pthread_t self = pthread_self();
137ac555471Sjmmv 	if (pthread_create(&self, NULL, resolvloop, nhosts) != 0)
138*f0d208fdSchristos 		err(EXIT_FAILURE, "pthread_create");
139*f0d208fdSchristos 	return self;
140ac555471Sjmmv }
141ac555471Sjmmv 
142ac555471Sjmmv int
main(int argc,char * argv[])143ac555471Sjmmv main(int argc, char *argv[])
144ac555471Sjmmv {
145ac555471Sjmmv 	int nthreads = NTHREADS;
146*f0d208fdSchristos 	pthread_t *threads;
147ac555471Sjmmv 	int nhosts = NHOSTS;
148ac555471Sjmmv 	int i, c, done, *nleft;
149ac555471Sjmmv 	hosts = sl_init();
150ac555471Sjmmv 
151ac555471Sjmmv 	srandom(1234);
152ac555471Sjmmv 
153ac555471Sjmmv 	while ((c = getopt(argc, argv, "dh:n:")) != -1)
154ac555471Sjmmv 		switch (c) {
155ac555471Sjmmv 		case 'd':
156ac555471Sjmmv 			debug++;
157ac555471Sjmmv 			break;
158ac555471Sjmmv 		case 'h':
159ac555471Sjmmv 			nhosts = atoi(optarg);
160ac555471Sjmmv 			break;
161ac555471Sjmmv 		case 'n':
162ac555471Sjmmv 			nthreads = atoi(optarg);
163ac555471Sjmmv 			break;
164ac555471Sjmmv 		default:
165ac555471Sjmmv 			usage();
166ac555471Sjmmv 		}
167ac555471Sjmmv 
168ac555471Sjmmv 	for (i = optind; i < argc; i++)
169ac555471Sjmmv 		load(argv[i]);
170ac555471Sjmmv 
171ac555471Sjmmv 	if (hosts->sl_cur == 0)
172ac555471Sjmmv 		usage();
173ac555471Sjmmv 
174ac555471Sjmmv 	if ((nleft = malloc(nthreads * sizeof(int))) == NULL)
175*f0d208fdSchristos 		err(EXIT_FAILURE, "malloc");
176ac555471Sjmmv 	if ((ask = calloc(hosts->sl_cur, sizeof(int))) == NULL)
177*f0d208fdSchristos 		err(EXIT_FAILURE, "calloc");
178ac555471Sjmmv 	if ((got = calloc(hosts->sl_cur, sizeof(int))) == NULL)
179*f0d208fdSchristos 		err(EXIT_FAILURE, "calloc");
180*f0d208fdSchristos 	if ((threads = malloc(nthreads * sizeof(pthread_t))) == NULL)
181*f0d208fdSchristos 		err(EXIT_FAILURE, "calloc");
182ac555471Sjmmv 
183ac555471Sjmmv 
184ac555471Sjmmv 	for (i = 0; i < nthreads; i++) {
185ac555471Sjmmv 		nleft[i] = nhosts;
186*f0d208fdSchristos 		threads[i] = run(&nleft[i]);
187ac555471Sjmmv 	}
188ac555471Sjmmv 
189ac555471Sjmmv 	for (done = 0; !done;) {
190ac555471Sjmmv 		done = 1;
191ac555471Sjmmv 		for (i = 0; i < nthreads; i++) {
192ac555471Sjmmv 			if (nleft[i] != 0) {
193ac555471Sjmmv 				done = 0;
194ac555471Sjmmv 				break;
195ac555471Sjmmv 			}
196ac555471Sjmmv 		}
197ac555471Sjmmv 		sleep(1);
198ac555471Sjmmv 	}
199ac555471Sjmmv 	c = 0;
2000f10aa9dSchristos 	for (i = 0; i < (int)hosts->sl_cur; i++) {
201ac555471Sjmmv 		if (ask[i] != got[i] && got[i] != 0) {
202ac555471Sjmmv 			warnx("Error: host %s ask %d got %d\n",
203ac555471Sjmmv 				hosts->sl_str[i], ask[i], got[i]);
204ac555471Sjmmv 			c++;
205ac555471Sjmmv 		}
206ac555471Sjmmv 	}
207*f0d208fdSchristos 	for (i = 0; i < nthreads; i++)
208*f0d208fdSchristos 		pthread_join(threads[i], NULL);
209*f0d208fdSchristos 	free(threads);
210ac555471Sjmmv 	free(nleft);
211ac555471Sjmmv 	free(ask);
212ac555471Sjmmv 	free(got);
213ac555471Sjmmv 	sl_free(hosts, 1);
214ac555471Sjmmv 	return c;
215ac555471Sjmmv }
216