aboutsummaryrefslogtreecommitdiff
path: root/tools/regression/gaithrstress
diff options
context:
space:
mode:
authorBrian Feldman <green@FreeBSD.org>2004-02-20 16:54:01 +0000
committerBrian Feldman <green@FreeBSD.org>2004-02-20 16:54:01 +0000
commite858faa9bb929e040dfa2ee6f9e4806cec4d685d (patch)
treee75d45a82c8f84c5a43e6bce66d9b763e95e00f4 /tools/regression/gaithrstress
parent607ee6431fa6a3ccb30f258120fc1cad4025368a (diff)
downloadsrc-e858faa9bb929e040dfa2ee6f9e4806cec4d685d.tar.gz
src-e858faa9bb929e040dfa2ee6f9e4806cec4d685d.zip
Add my getaddrinfo(3) stress-tester as gaithrstress. The most obvious
regressions would be to see the program or your kernel crashing. If you want to give it something to really test out, try a much more reentrant version of the resolver. <URL:http://green.homeunix.org/~green/reentrant_resolver.patch> Any Mozilla-based browser would show you a clear difference.
Notes
Notes: svn path=/head/; revision=126049
Diffstat (limited to 'tools/regression/gaithrstress')
-rw-r--r--tools/regression/gaithrstress/Makefile7
-rw-r--r--tools/regression/gaithrstress/gaithrstress.c245
2 files changed, 252 insertions, 0 deletions
diff --git a/tools/regression/gaithrstress/Makefile b/tools/regression/gaithrstress/Makefile
new file mode 100644
index 000000000000..2166aee20fa1
--- /dev/null
+++ b/tools/regression/gaithrstress/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+PROG= gaithrstress
+LDADD+= -pthread
+
+NOMAN= yes
+.include <bsd.prog.mk>
diff --git a/tools/regression/gaithrstress/gaithrstress.c b/tools/regression/gaithrstress/gaithrstress.c
new file mode 100644
index 000000000000..18a7ec806450
--- /dev/null
+++ b/tools/regression/gaithrstress/gaithrstress.c
@@ -0,0 +1,245 @@
+/*-
+ * Copyright (c) 2004 Brian Fundakowski Feldman
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ * $Id: getaddrinfo-pthreads-stresstest.c,v 1.4 2004/02/20 03:54:17 green Exp green $
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <err.h>
+#include <netdb.h>
+#include <pthread.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Per-thread struct containing all important data. */
+struct worker {
+ pthread_t w_thread; /* self */
+ uintmax_t w_lookup_success, w_lookup_failure; /* getaddrinfo stats */
+};
+
+static volatile int workers_stop = 0;
+static double max_random_sleep = 1.0;
+static char **randwords;
+static size_t nrandwords;
+
+/*
+ * We don't have good random(3)-type functions that are thread-safe,
+ * unfortunately.
+ */
+static u_int32_t
+my_arc4random_r(void)
+{
+ static pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;
+ u_int32_t ret;
+
+ (void)pthread_mutex_lock(&mymutex);
+ ret = arc4random();
+ (void)pthread_mutex_unlock(&mymutex);
+ return (ret);
+}
+
+static void
+randomsleep(double max_sleep_sec)
+{
+ struct timespec slptime = { 0, 0 };
+ double rndsleep;
+
+ rndsleep = (double)my_arc4random_r() / 4294967296.0 * max_sleep_sec;
+ while (rndsleep >= 1.0) {
+ slptime.tv_sec++;
+ rndsleep -= 1.0;
+ }
+ slptime.tv_nsec = rndsleep * 1e9;
+ (void)nanosleep(&slptime, NULL);
+}
+
+/*
+ * Start looking up arbitrary hostnames and record the successes/failures.
+ * Between lookups, sleep a random amount of time to make sure threads
+ * stay well out of synchronization.
+ */
+static void *
+work(void *arg)
+{
+ struct worker *w = arg;
+
+ /* Turn off domain name list searching. */
+ if (_res.options & RES_INIT || res_init() == 0)
+ _res.options &= ~RES_DNSRCH;
+ do {
+ const char *suffixes[] = { "net", "com", "org" };
+ const size_t nsuffixes = sizeof(suffixes) / sizeof(suffixes[0]);
+ struct addrinfo *res;
+ char *hostname;
+ int error;
+
+ randomsleep(max_random_sleep);
+ if (asprintf(&hostname, "%s%s%s.%s",
+ (my_arc4random_r() % 2) == 0 ? "www." : "",
+ randwords[my_arc4random_r() % nrandwords],
+ (my_arc4random_r() % 3) == 0 ?
+ randwords[my_arc4random_r() % nrandwords] : "",
+ suffixes[my_arc4random_r() % nsuffixes]) == -1)
+ continue;
+ error = getaddrinfo(hostname, NULL, NULL, &res);
+ free(hostname);
+ if (error == 0) {
+ w->w_lookup_success++;
+ freeaddrinfo(res);
+ } else {
+ w->w_lookup_failure++;
+ }
+ } while (!workers_stop);
+
+ pthread_exit(NULL);
+}
+
+int
+dowordfile(const char *fname)
+{
+ FILE *fp;
+ char newword[64];
+ size_t n;
+
+ fp = fopen(fname, "r");
+ if (fp == NULL)
+ return (-1);
+ nrandwords = 0;
+ while (fgets(newword, sizeof(newword), fp) != NULL)
+ nrandwords++;
+ if (ferror(fp) || fseek(fp, 0, SEEK_SET) != 0)
+ goto fail;
+ randwords = calloc(nrandwords, sizeof(char *));
+ if (randwords == NULL)
+ goto fail;
+ n = nrandwords;
+ nrandwords = 0;
+ while (fgets(newword, sizeof(newword), fp) != NULL) {
+ newword[strcspn(newword, "\r\n")] = '\0';
+ randwords[nrandwords] = strdup(newword);
+ if (randwords[nrandwords] == NULL)
+ err(1, "reading words file");
+ if (++nrandwords == n)
+ break;
+ }
+ nrandwords = n;
+ fclose(fp);
+ return (0);
+fail:
+ fclose(fp);
+ return (-1);
+}
+
+int
+main(int argc, char **argv) {
+ unsigned long nworkers = 1;
+ struct worker *workers;
+ size_t i;
+ char waiting[3], *send, *wordfile = "/usr/share/dict/words";
+ int ch;
+
+ if (getprogname() == NULL)
+ setprogname(argv[0]);
+ printf("%s: threaded stress-tester for getaddrinfo(3)\n",
+ getprogname());
+ printf("(c) 2004 Brian Feldman <green@FreeBSD.org>\n");
+ while ((ch = getopt(argc, argv, "s:t:w:")) != -1) {
+ switch (ch) {
+ case 's':
+ max_random_sleep = strtod(optarg, &send);
+ if (*send != '\0')
+ goto usage;
+ break;
+ case 't':
+ nworkers = strtoul(optarg, &send, 0);
+ if (*send != '\0')
+ goto usage;
+ break;
+ case 'w':
+ wordfile = optarg;
+ break;
+ default:
+usage:
+ fprintf(stderr, "usage: %s [-s sleep] [-t threads] "
+ "[-w wordfile]\n", getprogname());
+ exit(2);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (nworkers < 1 || nworkers != (size_t)nworkers)
+ goto usage;
+ if (dowordfile(wordfile) == -1)
+ err(1, "reading word file %s", wordfile);
+ if (nrandwords < 1)
+ errx(1, "word file %s did not have >0 words", wordfile);
+ printf("Read %u random words from %s.\n", nrandwords, wordfile);
+ workers = calloc(nworkers, sizeof(*workers));
+ if (workers == NULL)
+ err(1, "allocating workers");
+ printf("Intra-query delay time is from 0 to %g seconds (random).\n",
+ max_random_sleep);
+
+ printf("Starting %lu worker%.*s: ", nworkers, nworkers > 1, "s");
+ fflush(stdout);
+ for (i = 0; i < nworkers; i++) {
+ if (pthread_create(&workers[i].w_thread, NULL, work,
+ &workers[i]) == -1)
+ err(1, "creating worker %u", i);
+ printf("%u%s", i, i == nworkers - 1 ? ".\n" : ", ");
+ fflush(stdout);
+ }
+
+ printf("<Press enter key to end test.>\n");
+ (void)fgets(waiting, sizeof(waiting), stdin);
+ workers_stop = 1;
+
+ printf("Stopping %lu worker%.*s: ", nworkers, nworkers > 1, "s");
+ fflush(stdout);
+ for (i = 0; i < nworkers; i++) {
+ pthread_join(workers[i].w_thread, NULL);
+ printf("%u%s", i, i == nworkers - 1 ? ".\n" : ", ");
+ fflush(stdout);
+ }
+
+ printf("%-10s%-20s%-20s\n", "Worker", "Successful GAI", "Failed GAI");
+ printf("%-10s%-20s%-20s\n", "------", "--------------", "----------");
+ for (i = 0; i < nworkers; i++) {
+ printf("%-10u%-20ju%-20ju\n", i, workers[i].w_lookup_success,
+ workers[i].w_lookup_failure);
+ }
+
+ exit(0);
+}