summaryrefslogtreecommitdiff
path: root/test/tsan
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2014-03-24 14:32:59 +0000
committerDmitry Vyukov <dvyukov@google.com>2014-03-24 14:32:59 +0000
commitd491821dba7a2d73739d4c888d14eadd90471012 (patch)
treedff63d9a6e76cbd417c40dbb835d17f6bad410c1 /test/tsan
parent1e5d8befc4aea476f7d4d1f42b0a935d7e443a68 (diff)
tsan: add benchmarks for synchronization handling
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@204608 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/tsan')
-rw-r--r--test/tsan/bench.h57
-rw-r--r--test/tsan/bench_acquire_only.cc19
-rw-r--r--test/tsan/bench_acquire_release.cc18
-rw-r--r--test/tsan/bench_local_mutex.cc27
-rw-r--r--test/tsan/bench_mutex.cc28
-rw-r--r--test/tsan/bench_release_only.cc23
-rw-r--r--test/tsan/bench_rwmutex.cc25
-rw-r--r--test/tsan/bench_single_writer.cc23
-rw-r--r--test/tsan/bench_ten_mutexes.cc26
9 files changed, 246 insertions, 0 deletions
diff --git a/test/tsan/bench.h b/test/tsan/bench.h
new file mode 100644
index 000000000..4e8fce212
--- /dev/null
+++ b/test/tsan/bench.h
@@ -0,0 +1,57 @@
+#include <pthread.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <time.h>
+
+int bench_nthread;
+int bench_niter;
+int grow_clock_var;
+pthread_barrier_t glow_clock_barrier;
+
+void bench(); // defined by user
+void start_thread_group(int nth, void(*f)(int tid));
+void grow_clock_worker(int tid);
+
+int main(int argc, char **argv) {
+ bench_nthread = 2;
+ if (argc > 1)
+ bench_nthread = atoi(argv[1]);
+ bench_niter = 100;
+ if (argc > 2)
+ bench_niter = atoi(argv[2]);
+
+ // Grow thread's clock.
+ const int kClockSize = 1000;
+ pthread_barrier_init(&glow_clock_barrier, 0, kClockSize);
+ start_thread_group(kClockSize, grow_clock_worker);
+ pthread_barrier_destroy(&glow_clock_barrier);
+ __atomic_load_n(&grow_clock_var, __ATOMIC_ACQUIRE);
+
+ timespec tp0;
+ clock_gettime(CLOCK_MONOTONIC, &tp0);
+ bench();
+ timespec tp1;
+ clock_gettime(CLOCK_MONOTONIC, &tp1);
+ unsigned long long t =
+ (tp1.tv_sec * 1000000000ULL + tp1.tv_nsec) -
+ (tp0.tv_sec * 1000000000ULL + tp0.tv_nsec);
+ fprintf(stderr, "%llu ns/iter\n", t / bench_niter);
+ fprintf(stderr, "DONE\n");
+}
+
+void start_thread_group(int nth, void(*f)(int tid)) {
+ pthread_t *th = (pthread_t*)malloc(nth * sizeof(pthread_t));
+ for (int i = 0; i < nth; i++)
+ pthread_create(&th[i], 0, (void*(*)(void*))f, (void*)(long)i);
+ for (int i = 0; i < nth; i++)
+ pthread_join(th[i], 0);
+}
+
+void grow_clock_worker(int tid) {
+ int res = pthread_barrier_wait(&glow_clock_barrier);
+ if (res == PTHREAD_BARRIER_SERIAL_THREAD)
+ __atomic_store_n(&grow_clock_var, 0, __ATOMIC_RELEASE);
+}
+
diff --git a/test/tsan/bench_acquire_only.cc b/test/tsan/bench_acquire_only.cc
new file mode 100644
index 000000000..f480f0914
--- /dev/null
+++ b/test/tsan/bench_acquire_only.cc
@@ -0,0 +1,19 @@
+// RUN: %clangxx_tsan %s -o %t
+// RUN: %t 2>&1 | FileCheck %s
+
+#include "bench.h"
+
+int x;
+
+void thread(int tid) {
+ for (int i = 0; i < bench_niter; i++)
+ __atomic_load_n(&x, __ATOMIC_ACQUIRE);
+}
+
+void bench() {
+ __atomic_store_n(&x, 0, __ATOMIC_RELEASE);
+ start_thread_group(bench_nthread, thread);
+}
+
+// CHECK: DONE
+
diff --git a/test/tsan/bench_acquire_release.cc b/test/tsan/bench_acquire_release.cc
new file mode 100644
index 000000000..270f00745
--- /dev/null
+++ b/test/tsan/bench_acquire_release.cc
@@ -0,0 +1,18 @@
+// RUN: %clangxx_tsan %s -o %t
+// RUN: %t 2>&1 | FileCheck %s
+
+#include "bench.h"
+
+int x;
+
+void thread(int tid) {
+ for (int i = 0; i < bench_niter; i++)
+ __atomic_fetch_add(&x, 1, __ATOMIC_ACQ_REL);
+}
+
+void bench() {
+ start_thread_group(bench_nthread, thread);
+}
+
+// CHECK: DONE
+
diff --git a/test/tsan/bench_local_mutex.cc b/test/tsan/bench_local_mutex.cc
new file mode 100644
index 000000000..3b656b7b0
--- /dev/null
+++ b/test/tsan/bench_local_mutex.cc
@@ -0,0 +1,27 @@
+// RUN: %clangxx_tsan %s -o %t
+// RUN: %t 2>&1 | FileCheck %s
+
+#include "bench.h"
+
+pthread_mutex_t *mtx;
+const int kStride = 16;
+
+void thread(int tid) {
+ for (int i = 0; i < bench_niter; i++) {
+ pthread_mutex_lock(&mtx[tid * kStride]);
+ pthread_mutex_unlock(&mtx[tid * kStride]);
+ }
+}
+
+void bench() {
+ mtx = (pthread_mutex_t*)malloc(bench_nthread * kStride * sizeof(*mtx));
+ for (int i = 0; i < bench_nthread; i++) {
+ pthread_mutex_init(&mtx[i * kStride], 0);
+ pthread_mutex_lock(&mtx[i * kStride]);
+ pthread_mutex_unlock(&mtx[i * kStride]);
+ }
+ start_thread_group(bench_nthread, thread);
+}
+
+// CHECK: DONE
+
diff --git a/test/tsan/bench_mutex.cc b/test/tsan/bench_mutex.cc
new file mode 100644
index 000000000..4e5b3d6eb
--- /dev/null
+++ b/test/tsan/bench_mutex.cc
@@ -0,0 +1,28 @@
+// RUN: %clangxx_tsan %s -o %t
+// RUN: %t 2>&1 | FileCheck %s
+
+#include "bench.h"
+
+pthread_mutex_t mtx;
+pthread_cond_t cv;
+int x;
+
+void thread(int tid) {
+ for (int i = 0; i < bench_niter; i++) {
+ pthread_mutex_lock(&mtx);
+ while (x != i * 2 + tid)
+ pthread_cond_wait(&cv, &mtx);
+ x++;
+ pthread_cond_signal(&cv);
+ pthread_mutex_unlock(&mtx);
+ }
+}
+
+void bench() {
+ pthread_mutex_init(&mtx, 0);
+ pthread_cond_init(&cv, 0);
+ start_thread_group(2, thread);
+}
+
+// CHECK: DONE
+
diff --git a/test/tsan/bench_release_only.cc b/test/tsan/bench_release_only.cc
new file mode 100644
index 000000000..556c8bcd9
--- /dev/null
+++ b/test/tsan/bench_release_only.cc
@@ -0,0 +1,23 @@
+// RUN: %clangxx_tsan %s -o %t
+// RUN: %t 2>&1 | FileCheck %s
+
+#include "bench.h"
+
+int *x;
+const int kStride = 32;
+
+void thread(int tid) {
+ __atomic_load_n(&x[tid * kStride], __ATOMIC_ACQUIRE);
+ for (int i = 0; i < bench_niter; i++)
+ __atomic_store_n(&x[tid * kStride], 0, __ATOMIC_RELEASE);
+}
+
+void bench() {
+ x = (int*)malloc(bench_nthread * kStride * sizeof(x[0]));
+ for (int i = 0; i < bench_nthread; i++)
+ __atomic_store_n(&x[i * kStride], 0, __ATOMIC_RELEASE);
+ start_thread_group(bench_nthread, thread);
+}
+
+// CHECK: DONE
+
diff --git a/test/tsan/bench_rwmutex.cc b/test/tsan/bench_rwmutex.cc
new file mode 100644
index 000000000..f38f6e516
--- /dev/null
+++ b/test/tsan/bench_rwmutex.cc
@@ -0,0 +1,25 @@
+// RUN: %clangxx_tsan %s -o %t
+// RUN: %t 2>&1 | FileCheck %s
+
+#include "bench.h"
+
+pthread_rwlock_t mtx;
+
+void thread(int tid) {
+ for (int i = 0; i < bench_niter; i++) {
+ pthread_rwlock_rdlock(&mtx);
+ pthread_rwlock_unlock(&mtx);
+ }
+}
+
+void bench() {
+ pthread_rwlock_init(&mtx, 0);
+ pthread_rwlock_wrlock(&mtx);
+ pthread_rwlock_unlock(&mtx);
+ pthread_rwlock_rdlock(&mtx);
+ pthread_rwlock_unlock(&mtx);
+ start_thread_group(bench_nthread, thread);
+}
+
+// CHECK: DONE
+
diff --git a/test/tsan/bench_single_writer.cc b/test/tsan/bench_single_writer.cc
new file mode 100644
index 000000000..bd3d87ede
--- /dev/null
+++ b/test/tsan/bench_single_writer.cc
@@ -0,0 +1,23 @@
+// RUN: %clangxx_tsan %s -o %t
+// RUN: %t 2>&1 | FileCheck %s
+
+#include "bench.h"
+
+int x;
+
+void thread(int tid) {
+ if (tid == 0) {
+ for (int i = 0; i < bench_niter; i++)
+ __atomic_store_n(&x, 0, __ATOMIC_RELEASE);
+ } else {
+ for (int i = 0; i < bench_niter; i++)
+ __atomic_load_n(&x, __ATOMIC_ACQUIRE);
+ }
+}
+
+void bench() {
+ start_thread_group(bench_nthread, thread);
+}
+
+// CHECK: DONE
+
diff --git a/test/tsan/bench_ten_mutexes.cc b/test/tsan/bench_ten_mutexes.cc
new file mode 100644
index 000000000..994d2ac99
--- /dev/null
+++ b/test/tsan/bench_ten_mutexes.cc
@@ -0,0 +1,26 @@
+// RUN: %clangxx_tsan %s -o %t
+// RUN: %t 2>&1 | FileCheck %s
+
+#include "bench.h"
+
+const int kMutex = 10;
+pthread_mutex_t mtx[kMutex];
+
+void thread(int tid) {
+ for (int i = 0; i < bench_niter; i++) {
+ int idx = (i % kMutex);
+ if (tid == 0)
+ idx = kMutex - idx - 1;
+ pthread_mutex_lock(&mtx[idx]);
+ pthread_mutex_unlock(&mtx[idx]);
+ }
+}
+
+void bench() {
+ for (int i = 0; i < kMutex; i++)
+ pthread_mutex_init(&mtx[i], 0);
+ start_thread_group(2, thread);
+}
+
+// CHECK: DONE
+