diff options
author | Dmitry Vyukov <dvyukov@google.com> | 2014-03-24 14:32:59 +0000 |
---|---|---|
committer | Dmitry Vyukov <dvyukov@google.com> | 2014-03-24 14:32:59 +0000 |
commit | d491821dba7a2d73739d4c888d14eadd90471012 (patch) | |
tree | dff63d9a6e76cbd417c40dbb835d17f6bad410c1 /test/tsan | |
parent | 1e5d8befc4aea476f7d4d1f42b0a935d7e443a68 (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.h | 57 | ||||
-rw-r--r-- | test/tsan/bench_acquire_only.cc | 19 | ||||
-rw-r--r-- | test/tsan/bench_acquire_release.cc | 18 | ||||
-rw-r--r-- | test/tsan/bench_local_mutex.cc | 27 | ||||
-rw-r--r-- | test/tsan/bench_mutex.cc | 28 | ||||
-rw-r--r-- | test/tsan/bench_release_only.cc | 23 | ||||
-rw-r--r-- | test/tsan/bench_rwmutex.cc | 25 | ||||
-rw-r--r-- | test/tsan/bench_single_writer.cc | 23 | ||||
-rw-r--r-- | test/tsan/bench_ten_mutexes.cc | 26 |
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 + |