Add thread and iteration parameters to performance/futex_wait.c

In keeping with the test design philosophy of futextest, add parameters
for threads and iterations to futex_wait. Remove the hard coded
thread count array and relay on run.sh to specify the thread count
array, running the test once for each configuration. Also update the
headers and the logging output to match that of futextest.

Signed-off-by: Darren Hart <dvhltc@us.ibm.com>
diff --git a/performance/futex_wait.c b/performance/futex_wait.c
index bcbca77..9703a1a 100644
--- a/performance/futex_wait.c
+++ b/performance/futex_wait.c
@@ -1,11 +1,62 @@
-// Copyright 2009 Google Inc.
-// Author: walken@google.com (Michel Lespinasse)
+/******************************************************************************
+ *
+ *   Copyright 2009 Google Inc.
+ *   Copyright © International Business Machines  Corp., 2009
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * NAME
+ *      futex_wait.c
+ *
+ * DESCRIPTION
+ *      Measure FUTEX_WAIT operations per second over a configurable number
+ *      of iterations and treads.
+ *
+ * AUTHOR
+ *      Michel Lespinasse <walken@google.com>
+ *
+ * HISTORY
+ *      2009-Nov-16: Initial version by Michel Lespinasse <walken@google.com>
+ *      2009-Nov-30: Optional thread and iteration parameters, general
+ *                   integration into futextest by 
+ *                   Darren Hart <dvhltc@us.ibm.com>
+ *
+ *****************************************************************************/
 
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include "futextest.h"
+#include "logging.h"
 #include "harness.h"
 
-#include <stdio.h>
 
+static int threads = 256;
+static int iterations = 100000000;
+
+void usage(char *prog)
+{
+	printf("Usage: %s\n", prog);
+	printf("  -c	Use color\n");
+	printf("  -h	Display this help message\n");
+	printf("  -i I	Number of iterations (default: %d)\n", iterations);
+	printf("  -n N	Number of threads (default: %d)\n", threads);
+	printf("  -v L	Verbosity level: %d=QUIET %d=CRITICAL %d=INFO\n",
+	       VQUIET, VCRITICAL, VINFO);
+}
 
 static inline void futex_wait_lock(futex_t *futex)
 {
@@ -43,9 +94,38 @@
 	}
 }
 
-int main (void)
+int main(int argc, char *argv[])
 {
-	printf("FUTEX_WAIT test\n");
-	locktest(futex_wait_test, 100000000);
-	return 0;
+	int ret, c;
+	while ((c = getopt(argc, argv, "chi:n:v:")) != -1) {
+		switch(c) {
+		case 'c':
+			log_color(1);
+			break;
+		case 'h':
+			usage(basename(argv[0]));
+			exit(0);
+		case 'i':
+			iterations = atoi(optarg);
+			break;
+		case 'n':
+			threads = atoi(optarg);
+			break;
+		case 'v':
+			log_verbosity(atoi(optarg));
+			break;
+		default:
+			usage(basename(argv[0]));
+			exit(1);
+		}
+	}
+
+	printf("%s: Measure FUTEX_WAIT operations per second\n",
+	       basename(argv[0]));
+	printf("\tArguments: iterations=%d threads=%d\n", iterations, threads);
+
+	/* run the test and display the results */
+	ret = locktest(futex_wait_test, iterations, threads);
+
+	return ret;
 }
diff --git a/performance/harness.h b/performance/harness.h
index 7b23bdc..a395492 100644
--- a/performance/harness.h
+++ b/performance/harness.h
@@ -1,10 +1,45 @@
-// Copyright 2009 Google Inc.
-// Author: walken@google.com (Michel Lespinasse)
+/******************************************************************************
+ *
+ *   Copyright 2009 Google Inc.
+ *   Copyright © International Business Machines  Corp., 2009
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * NAME
+ *      harness.h
+ *
+ * DESCRIPTION
+ *      Common routines for futex_wait and futex_set_wait performance tests.
+ *
+ * AUTHOR
+ *      Michel Lespinasse <walken@google.com>
+ *
+ * HISTORY
+ *      2009-Nov-16: Initial version by Michel Lespinasse <walken@google.com>
+ *      2009-Nov-30: Removal of hard-coded thread count array and general
+ *                   integration into futextest by
+ *                   Darren Hart <dvhltc@us.ibm.com>
+ *
+ *****************************************************************************/
 
+#include <errno.h>
 #include <limits.h>
-#include <sys/times.h>
-#include <stdio.h>
 #include <pthread.h>
+#include <stdio.h>
+#include <sys/times.h>
+#include "logging.h"
 
 
 struct thread_barrier {
@@ -64,54 +99,52 @@
 	return NULL;
 }
 
-static void locktest(void locktest_function(futex_t * ptr, int loops),
-		     int iterations)
+static int locktest(void locktest_function(futex_t * ptr, int loops),
+		     int iterations, int threads)
 {
-	int threads[] = { 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 24, 32,
-			  64, 128, 256, 512, 1024, 0 };
-	int t;
-	for (t = 0; threads[t]; t++) {
-		int num_threads = threads[t];
-		struct locktest_shared shared;
-		pthread_t thread[num_threads];
-		int i;
-		clock_t before, after;
-		struct tms tms_before, tms_after;
-		int wall, user, system;
-		double tick;
+	struct locktest_shared shared;
+	pthread_t thread[threads];
+	int i;
+	clock_t before, after;
+	struct tms tms_before, tms_after;
+	int wall, user, system;
+	double tick;
 
-		barrier_init(&shared.barrier_before, num_threads);
-		barrier_init(&shared.barrier_after, num_threads);
-		shared.locktest_function = locktest_function;
-		shared.loops = iterations / num_threads;
-		shared.futex = 0;
+	barrier_init(&shared.barrier_before, threads);
+	barrier_init(&shared.barrier_after, threads);
+	shared.locktest_function = locktest_function;
+	shared.loops = iterations / threads;
+	shared.futex = 0;
 
-		for (i = 0; i < num_threads; i++)
-			if (pthread_create(thread + i, NULL, locktest_thread,
-					   &shared)) {
-				/* Could not create thread; abort */
-				barrier_unblock(&shared.barrier_before, -1);
-				while (--i >= 0)
-					pthread_join(thread[i], NULL);
-				return;
-			}
-		barrier_wait(&shared.barrier_before);
-		before = times(&tms_before);
-		barrier_unblock(&shared.barrier_before, 1);
-		barrier_wait(&shared.barrier_after);
-		after = times(&tms_after);
-		wall = after - before;
-		user = tms_after.tms_utime - tms_before.tms_utime;
-		system = tms_after.tms_stime - tms_before.tms_stime;
-		tick = 1.0 / sysconf(_SC_CLK_TCK);
-		printf("%d threads: %.0f Kiter/s "
-		       "(%.2fs user %.2fs system %.2fs wall %.2f cores)\n",
-		       num_threads,
-		       (num_threads * shared.loops) / (wall * tick * 1000),
-		       user * tick, system * tick, wall * tick,
-		       wall ? (user + system) * 1. / wall : 1.);
-		barrier_unblock(&shared.barrier_after, 1);
-		for (i = 0; i < num_threads; i++)
-			pthread_join(thread[i], NULL);
-	}
+	for (i = 0; i < threads; i++)
+		if (pthread_create(thread + i, NULL, locktest_thread,
+					&shared)) {
+			error("pthread_create\n", errno);
+			/* Could not create thread; abort */
+			barrier_unblock(&shared.barrier_before, -1);
+			while (--i >= 0)
+				pthread_join(thread[i], NULL);
+			print_result(RET_ERROR);
+			return RET_ERROR;
+		}
+	barrier_wait(&shared.barrier_before);
+	before = times(&tms_before);
+	barrier_unblock(&shared.barrier_before, 1);
+	barrier_wait(&shared.barrier_after);
+	after = times(&tms_after);
+	wall = after - before;
+	user = tms_after.tms_utime - tms_before.tms_utime;
+	system = tms_after.tms_stime - tms_before.tms_stime;
+	tick = 1.0 / sysconf(_SC_CLK_TCK);
+	info("%.2fs user, %.2fs system, %.2fs wall, %.2f cores\n",
+	     user * tick, system * tick, wall * tick,
+	     wall ? (user + system) * 1. / wall : 1.);
+	barrier_unblock(&shared.barrier_after, 1);
+	for (i = 0; i < threads; i++)
+		pthread_join(thread[i], NULL);
+
+	printf("Result: %.0f Kiter/s\n",
+	       (threads * shared.loops) / (wall * tick * 1000));
+
+	return RET_PASS;
 }
diff --git a/performance/run.sh b/performance/run.sh
index a64332e..9aa1850 100755
--- a/performance/run.sh
+++ b/performance/run.sh
@@ -44,6 +44,8 @@
     COLOR="-c"
 fi
 
-./futex_wait
+for THREADS in 1 2 3 4 5 6 8 10 12 16 24 32 64 128 256 512 1024; do
+    ./futex_wait $COLOR -n $THREADS
+done
 
 exit 0