tsan: add benchmarks for synchronization handling
llvm-svn: 204608
This commit is contained in:
parent
e3df81f3ab
commit
238bd23534
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
Loading…
Reference in New Issue