tsan: add benchmarks for synchronization handling

llvm-svn: 204608
This commit is contained in:
Dmitry Vyukov 2014-03-24 14:32:59 +00:00
parent e3df81f3ab
commit 238bd23534
9 changed files with 246 additions and 0 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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