aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarren Hart <dvhltc@us.ibm.com>2009-11-18 22:31:37 -0800
committerDarren Hart <dvhltc@us.ibm.com>2009-11-23 09:59:27 -0800
commitb9f837800ff7b64a56274760044585c92ad8866b (patch)
tree550a1e50e1d57228da579bc66e6f5874ae8f7739
parentd5bdd21887e66f7af6a631083a15104cebc82a52 (diff)
downloadfutextest-b9f837800ff7b64a56274760044585c92ad8866b.tar.gz
Add futex_wait performance test
This is the first half of a patch from Michel adding futex_set_wait and futex_wait performance tests. This patch adds the futex_wait performance test and the necessary infrastructure. Signed-off-by: Michel Lespinasse <walken@google.com> Signed-off-by: Darren Hart <dvhltc@us.ibm.com>
-rw-r--r--.gitignore4
-rw-r--r--performance/Makefile2
-rw-r--r--performance/futex_wait.c56
-rw-r--r--performance/harness.h103
-rwxr-xr-xperformance/run.sh1
5 files changed, 164 insertions, 2 deletions
diff --git a/.gitignore b/.gitignore
index 0a64487..f0c74c6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,8 @@
functional/futex_requeue_pi
functional/futex_requeue_pi_signal_restart
functional/futex_wait_timeout
-
functional/futex_requeue_pi_mismatched_ops
functional/futex_wait_wouldblock
+
+performance/futex_wait
+performance/futex_set_wait
diff --git a/performance/Makefile b/performance/Makefile
index 9589e49..abd4dd8 100644
--- a/performance/Makefile
+++ b/performance/Makefile
@@ -3,7 +3,7 @@ CFLAGS := $(CFLAGS) -g -O2 -Wall -D_GNU_SOURCE $(INCLUDES)
LDFLAGS := $(LDFLAGS) -lpthread -lrt
HEADERS := ../include/futextest.h
-TARGETS :=
+TARGETS := futex_wait
.PHONY: all clean
all: $(TARGETS)
diff --git a/performance/futex_wait.c b/performance/futex_wait.c
new file mode 100644
index 0000000..88ce2f2
--- /dev/null
+++ b/performance/futex_wait.c
@@ -0,0 +1,56 @@
+// Copyright 2009 Google Inc.
+// Author: walken@google.com (Michel Lespinasse)
+
+#include "futextest.h"
+#include "harness.h"
+
+#include <stdio.h>
+
+
+static inline void futex_wait_lock(futex_t *futex)
+{
+ int status = *futex;
+ if (status == 0)
+ status = futex_cmpxchg(futex, 0, 1);
+ while (status != 0) {
+ if (status == 1)
+ status = futex_cmpxchg(futex, 1, 2);
+ if (status != 0) {
+ futex_wait(futex, 2, NULL, FUTEX_PRIVATE_FLAG);
+ status = *futex;
+ }
+ if (status == 0)
+ status = futex_cmpxchg(futex, 0, 2);
+ }
+}
+
+static inline void futex_cmpxchg_unlock(futex_t *futex)
+{
+ int status = *futex;
+ if (status == 1)
+ status = futex_cmpxchg(futex, 1, 0);
+ if (status == 2) {
+ futex_cmpxchg(futex, 2, 0);
+ futex_wake(futex, 1, FUTEX_PRIVATE_FLAG);
+ }
+}
+
+static void * futex_wait_test(void * dummy)
+{
+ struct locktest_shared * shared = dummy;
+ int i = shared->loops;
+ barrier_sync(&shared->barrier_before);
+ while (i--) {
+ futex_wait_lock(&shared->futex);
+ futex_cmpxchg_unlock(&shared->futex);
+ }
+ barrier_sync(&shared->barrier_after);
+ return NULL;
+}
+
+int main (void)
+{
+ printf("FUTEX_WAIT test\n");
+ locktest(futex_wait_test, 100000000);
+ return 0;
+}
diff --git a/performance/harness.h b/performance/harness.h
new file mode 100644
index 0000000..9d74d17
--- /dev/null
+++ b/performance/harness.h
@@ -0,0 +1,103 @@
+// Copyright 2009 Google Inc.
+// Author: walken@google.com (Michel Lespinasse)
+
+#include <limits.h>
+#include <sys/times.h>
+#include <stdio.h>
+#include <pthread.h>
+
+
+struct thread_barrier {
+ futex_t threads;
+ futex_t unblock;
+};
+
+struct locktest_shared {
+ struct thread_barrier barrier_before;
+ struct thread_barrier barrier_after;
+ int loops;
+ futex_t futex;
+};
+
+static inline void decrement(futex_t *ptr)
+{
+ __sync_fetch_and_add(ptr, -1);
+}
+
+/* Called by main thread to initialize barrier */
+static void barrier_init(struct thread_barrier *barrier, int threads)
+{
+ barrier->threads = threads;
+ barrier->unblock = 0;
+}
+
+/* Called by worker threads to synchronize with main thread */
+static void barrier_sync(struct thread_barrier *barrier)
+{
+ decrement(&barrier->threads);
+ if (barrier->threads == 0)
+ futex_wake(&barrier->threads, 1, FUTEX_PRIVATE_FLAG);
+ while (barrier->unblock == 0)
+ futex_wait(&barrier->unblock, 0, NULL, FUTEX_PRIVATE_FLAG);
+}
+
+/* Called by main thread to wait for all workers to reach sync point */
+static void barrier_wait(struct thread_barrier *barrier)
+{
+ int threads;
+ while ((threads = barrier->threads) > 0)
+ futex_wait(&barrier->threads, threads, NULL,
+ FUTEX_PRIVATE_FLAG);
+}
+
+/* Called by main thread to unblock worker threads from their sync point */
+static void barrier_unblock(struct thread_barrier *barrier)
+{
+ barrier->unblock = 1;
+ futex_wake(&barrier->unblock, INT_MAX, FUTEX_PRIVATE_FLAG);
+}
+
+
+static void locktest(void * thread_function(void *), int iterations)
+{
+ 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;
+
+ barrier_init(&shared.barrier_before, num_threads);
+ barrier_init(&shared.barrier_after, num_threads);
+ shared.loops = iterations / num_threads;
+ shared.futex = 0;
+
+ for (i = 0; i < num_threads; i++)
+ pthread_create(thread + i, NULL, thread_function,
+ &shared);
+ barrier_wait(&shared.barrier_before);
+ before = times(&tms_before);
+ barrier_unblock(&shared.barrier_before);
+ 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);
+ for (i = 0; i < num_threads; i++)
+ pthread_join(thread[i], NULL);
+ }
+}
diff --git a/performance/run.sh b/performance/run.sh
index c5acf10..a64332e 100755
--- a/performance/run.sh
+++ b/performance/run.sh
@@ -44,5 +44,6 @@ if [ "$USE_COLOR" -eq 1 ]; then
COLOR="-c"
fi
+./futex_wait
exit 0