[llvm-commits] [compiler-rt] r156545 - in /compiler-rt/trunk/lib/tsan: benchmarks/ output_tests/ rtl_tests/ unit_tests/
Kostya Serebryany
kcc at google.com
Thu May 10 07:18:22 PDT 2012
Author: kcc
Date: Thu May 10 09:18:22 2012
New Revision: 156545
URL: http://llvm.org/viewvc/llvm-project?rev=156545&view=rev
Log:
[tsan] ThreadSanitizer tests and micro benchmarks. No makefiles yet.
Added:
compiler-rt/trunk/lib/tsan/benchmarks/
compiler-rt/trunk/lib/tsan/benchmarks/mini_bench_local.cc
compiler-rt/trunk/lib/tsan/benchmarks/mini_bench_shared.cc
compiler-rt/trunk/lib/tsan/benchmarks/start_many_threads.cc
compiler-rt/trunk/lib/tsan/benchmarks/vts_many_threads_bench.cc
compiler-rt/trunk/lib/tsan/output_tests/
compiler-rt/trunk/lib/tsan/output_tests/free_race.c
compiler-rt/trunk/lib/tsan/output_tests/heap_race.cc
compiler-rt/trunk/lib/tsan/output_tests/memcpy_race.cc
compiler-rt/trunk/lib/tsan/output_tests/mop_with_offset.cc
compiler-rt/trunk/lib/tsan/output_tests/mop_with_offset2.cc
compiler-rt/trunk/lib/tsan/output_tests/race_on_barrier.c
compiler-rt/trunk/lib/tsan/output_tests/race_on_barrier2.c
compiler-rt/trunk/lib/tsan/output_tests/race_on_mutex.c
compiler-rt/trunk/lib/tsan/output_tests/race_with_finished_thread.cc
compiler-rt/trunk/lib/tsan/output_tests/simple_race.c
compiler-rt/trunk/lib/tsan/output_tests/simple_race.cc
compiler-rt/trunk/lib/tsan/output_tests/simple_stack.c
compiler-rt/trunk/lib/tsan/output_tests/simple_stack2.cc
compiler-rt/trunk/lib/tsan/output_tests/static_init1.cc
compiler-rt/trunk/lib/tsan/output_tests/static_init2.cc
compiler-rt/trunk/lib/tsan/output_tests/static_init3.cc
compiler-rt/trunk/lib/tsan/output_tests/static_init4.cc
compiler-rt/trunk/lib/tsan/output_tests/static_init5.cc
compiler-rt/trunk/lib/tsan/output_tests/suppress_same_address.cc
compiler-rt/trunk/lib/tsan/output_tests/suppress_same_stacks.cc
compiler-rt/trunk/lib/tsan/output_tests/suppress_sequence.cc
compiler-rt/trunk/lib/tsan/output_tests/test_output.sh (with props)
compiler-rt/trunk/lib/tsan/output_tests/thread_leak.c
compiler-rt/trunk/lib/tsan/output_tests/thread_leak2.c
compiler-rt/trunk/lib/tsan/output_tests/thread_leak3.c
compiler-rt/trunk/lib/tsan/output_tests/vptr_benign_race.cc
compiler-rt/trunk/lib/tsan/output_tests/vptr_harmful_race.cc
compiler-rt/trunk/lib/tsan/rtl_tests/
compiler-rt/trunk/lib/tsan/rtl_tests/tsan_bench.cc
compiler-rt/trunk/lib/tsan/rtl_tests/tsan_mop.cc
compiler-rt/trunk/lib/tsan/rtl_tests/tsan_mutex.cc
compiler-rt/trunk/lib/tsan/rtl_tests/tsan_posix.cc
compiler-rt/trunk/lib/tsan/rtl_tests/tsan_string.cc
compiler-rt/trunk/lib/tsan/rtl_tests/tsan_test.cc
compiler-rt/trunk/lib/tsan/rtl_tests/tsan_test_util.h
compiler-rt/trunk/lib/tsan/rtl_tests/tsan_test_util_linux.cc
compiler-rt/trunk/lib/tsan/rtl_tests/tsan_thread.cc
compiler-rt/trunk/lib/tsan/unit_tests/
compiler-rt/trunk/lib/tsan/unit_tests/tsan_allocator_test.cc
compiler-rt/trunk/lib/tsan/unit_tests/tsan_clock_test.cc
compiler-rt/trunk/lib/tsan/unit_tests/tsan_flags_test.cc
compiler-rt/trunk/lib/tsan/unit_tests/tsan_mman_test.cc
compiler-rt/trunk/lib/tsan/unit_tests/tsan_mutex_test.cc
compiler-rt/trunk/lib/tsan/unit_tests/tsan_platform_test.cc
compiler-rt/trunk/lib/tsan/unit_tests/tsan_printf_test.cc
compiler-rt/trunk/lib/tsan/unit_tests/tsan_shadow_test.cc
compiler-rt/trunk/lib/tsan/unit_tests/tsan_suppressions_test.cc
compiler-rt/trunk/lib/tsan/unit_tests/tsan_sync_test.cc
compiler-rt/trunk/lib/tsan/unit_tests/tsan_vector_test.cc
Added: compiler-rt/trunk/lib/tsan/benchmarks/mini_bench_local.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/benchmarks/mini_bench_local.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/benchmarks/mini_bench_local.cc (added)
+++ compiler-rt/trunk/lib/tsan/benchmarks/mini_bench_local.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,49 @@
+// Mini-benchmark for tsan: non-shared memory writes.
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+int len;
+int *a;
+const int kNumIter = 1000;
+
+__attribute__((noinline))
+void Run(int idx) {
+ for (int i = 0, n = len; i < n; i++)
+ a[i + idx * n] = i;
+}
+
+void *Thread(void *arg) {
+ long idx = (long)arg;
+ printf("Thread %ld started\n", idx);
+ for (int i = 0; i < kNumIter; i++)
+ Run(idx);
+ printf("Thread %ld done\n", idx);
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ int n_threads = 0;
+ if (argc != 3) {
+ n_threads = 4;
+ len = 1000000;
+ } else {
+ n_threads = atoi(argv[1]);
+ assert(n_threads > 0 && n_threads <= 32);
+ len = atoi(argv[2]);
+ }
+ printf("%s: n_threads=%d len=%d iter=%d\n",
+ __FILE__, n_threads, len, kNumIter);
+ a = new int[n_threads * len];
+ pthread_t *t = new pthread_t[n_threads];
+ for (int i = 0; i < n_threads; i++) {
+ pthread_create(&t[i], 0, Thread, (void*)i);
+ }
+ for (int i = 0; i < n_threads; i++) {
+ pthread_join(t[i], 0);
+ }
+ delete [] t;
+ delete [] a;
+ return 0;
+}
Added: compiler-rt/trunk/lib/tsan/benchmarks/mini_bench_shared.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/benchmarks/mini_bench_shared.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/benchmarks/mini_bench_shared.cc (added)
+++ compiler-rt/trunk/lib/tsan/benchmarks/mini_bench_shared.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,51 @@
+// Mini-benchmark for tsan: shared memory reads.
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+int len;
+int *a;
+const int kNumIter = 1000;
+
+__attribute__((noinline))
+void Run(int idx) {
+ for (int i = 0, n = len; i < n; i++)
+ if (a[i] != i) abort();
+}
+
+void *Thread(void *arg) {
+ long idx = (long)arg;
+ printf("Thread %ld started\n", idx);
+ for (int i = 0; i < kNumIter; i++)
+ Run(idx);
+ printf("Thread %ld done\n", idx);
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ int n_threads = 0;
+ if (argc != 3) {
+ n_threads = 4;
+ len = 1000000;
+ } else {
+ n_threads = atoi(argv[1]);
+ assert(n_threads > 0 && n_threads <= 32);
+ len = atoi(argv[2]);
+ }
+ printf("%s: n_threads=%d len=%d iter=%d\n",
+ __FILE__, n_threads, len, kNumIter);
+ a = new int[len];
+ for (int i = 0, n = len; i < n; i++)
+ a[i] = i;
+ pthread_t *t = new pthread_t[n_threads];
+ for (int i = 0; i < n_threads; i++) {
+ pthread_create(&t[i], 0, Thread, (void*)i);
+ }
+ for (int i = 0; i < n_threads; i++) {
+ pthread_join(t[i], 0);
+ }
+ delete [] t;
+ delete [] a;
+ return 0;
+}
Added: compiler-rt/trunk/lib/tsan/benchmarks/start_many_threads.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/benchmarks/start_many_threads.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/benchmarks/start_many_threads.cc (added)
+++ compiler-rt/trunk/lib/tsan/benchmarks/start_many_threads.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,52 @@
+// Mini-benchmark for creating a lot of threads.
+//
+// Some facts:
+// a) clang -O1 takes <15ms to start N=500 threads,
+// consuming ~4MB more RAM than N=1.
+// b) clang -O1 -ftsan takes ~26s to start N=500 threads,
+// eats 5GB more RAM than N=1 (which is somewhat expected but still a lot)
+// but then it consumes ~4GB of extra memory when the threads shut down!
+// (definitely not in the barrier_wait interceptor)
+// Also, it takes 26s to run with N=500 vs just 1.1s to run with N=1.
+#include <assert.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+pthread_barrier_t all_threads_ready;
+
+void* Thread(void *unused) {
+ pthread_barrier_wait(&all_threads_ready);
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ int n_threads;
+ if (argc == 1) {
+ n_threads = 100;
+ } else if (argc == 2) {
+ n_threads = atoi(argv[1]);
+ } else {
+ printf("Usage: %s n_threads\n", argv[0]);
+ return 1;
+ }
+ printf("%s: n_threads=%d\n", __FILE__, n_threads);
+
+ pthread_barrier_init(&all_threads_ready, NULL, n_threads + 1);
+
+ pthread_t *t = new pthread_t[n_threads];
+ for (int i = 0; i < n_threads; i++) {
+ int status = pthread_create(&t[i], 0, Thread, (void*)i);
+ assert(status == 0);
+ }
+ // sleep(5); // FIXME: simplify measuring the memory usage.
+ pthread_barrier_wait(&all_threads_ready);
+ for (int i = 0; i < n_threads; i++) {
+ pthread_join(t[i], 0);
+ }
+ // sleep(5); // FIXME: simplify measuring the memory usage.
+ delete [] t;
+
+ return 0;
+}
Added: compiler-rt/trunk/lib/tsan/benchmarks/vts_many_threads_bench.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/benchmarks/vts_many_threads_bench.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/benchmarks/vts_many_threads_bench.cc (added)
+++ compiler-rt/trunk/lib/tsan/benchmarks/vts_many_threads_bench.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,120 @@
+// Mini-benchmark for tsan VTS worst case performance
+// Idea:
+// 1) Spawn M + N threads (M >> N)
+// We'll call the 'M' threads as 'garbage threads'.
+// 2) Make sure all threads have created thus no TIDs were reused
+// 3) Join the garbage threads
+// 4) Do many sync operations on the remaining N threads
+//
+// It turns out that due to O(M+N) VTS complexity the (4) is much slower with
+// when N is large.
+//
+// Some numbers:
+// a) clang++ native O1 with n_iterations=200kk takes
+// 5s regardless of M
+// clang++ tsanv2 O1 with n_iterations=20kk takes
+// 23.5s with M=200
+// 11.5s with M=1
+// i.e. tsanv2 is ~23x to ~47x slower than native, depends on M.
+// b) g++ native O1 with n_iterations=200kk takes
+// 5.5s regardless of M
+// g++ tsanv1 O1 with n_iterations=2kk takes
+// 39.5s with M=200
+// 20.5s with M=1
+// i.e. tsanv1 is ~370x to ~720x slower than native, depends on M.
+
+#include <assert.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+class __attribute__((aligned(64))) Mutex {
+ public:
+ Mutex() { pthread_mutex_init(&m_, NULL); }
+ ~Mutex() { pthread_mutex_destroy(&m_); }
+ void Lock() { pthread_mutex_lock(&m_); }
+ void Unlock() { pthread_mutex_unlock(&m_); }
+
+ private:
+ pthread_mutex_t m_;
+};
+
+const int kNumMutexes = 1024;
+Mutex mutexes[kNumMutexes];
+
+int n_threads, n_iterations;
+
+pthread_barrier_t all_threads_ready, main_threads_ready;
+
+void* GarbageThread(void *unused) {
+ pthread_barrier_wait(&all_threads_ready);
+ return 0;
+}
+
+void *Thread(void *arg) {
+ long idx = (long)arg;
+ pthread_barrier_wait(&all_threads_ready);
+
+ // Wait for the main thread to join the garbage threads.
+ pthread_barrier_wait(&main_threads_ready);
+
+ printf("Thread %ld go!\n", idx);
+ int offset = idx * kNumMutexes / n_threads;
+ for (int i = 0; i < n_iterations; i++) {
+ mutexes[(offset + i) % kNumMutexes].Lock();
+ mutexes[(offset + i) % kNumMutexes].Unlock();
+ }
+ printf("Thread %ld done\n", idx);
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ int n_garbage_threads;
+ if (argc == 1) {
+ n_threads = 2;
+ n_garbage_threads = 200;
+ n_iterations = 20000000;
+ } else if (argc == 4) {
+ n_threads = atoi(argv[1]);
+ assert(n_threads > 0 && n_threads <= 32);
+ n_garbage_threads = atoi(argv[2]);
+ assert(n_garbage_threads > 0 && n_garbage_threads <= 16000);
+ n_iterations = atoi(argv[3]);
+ } else {
+ printf("Usage: %s n_threads n_garbage_threads n_iterations\n", argv[0]);
+ return 1;
+ }
+ printf("%s: n_threads=%d n_garbage_threads=%d n_iterations=%d\n",
+ __FILE__, n_threads, n_garbage_threads, n_iterations);
+
+ pthread_barrier_init(&all_threads_ready, NULL, n_garbage_threads + n_threads + 1);
+ pthread_barrier_init(&main_threads_ready, NULL, n_threads + 1);
+
+ pthread_t *t = new pthread_t[n_threads];
+ {
+ pthread_t *g_t = new pthread_t[n_garbage_threads];
+ for (int i = 0; i < n_garbage_threads; i++) {
+ int status = pthread_create(&g_t[i], 0, GarbageThread, NULL);
+ assert(status == 0);
+ }
+ for (int i = 0; i < n_threads; i++) {
+ int status = pthread_create(&t[i], 0, Thread, (void*)i);
+ assert(status == 0);
+ }
+ pthread_barrier_wait(&all_threads_ready);
+ printf("All threads started! Killing the garbage threads.\n");
+ for (int i = 0; i < n_garbage_threads; i++) {
+ pthread_join(g_t[i], 0);
+ }
+ delete [] g_t;
+ }
+ printf("Resuming the main threads.\n");
+ pthread_barrier_wait(&main_threads_ready);
+
+
+ for (int i = 0; i < n_threads; i++) {
+ pthread_join(t[i], 0);
+ }
+ delete [] t;
+ return 0;
+}
Added: compiler-rt/trunk/lib/tsan/output_tests/free_race.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/free_race.c?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/free_race.c (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/free_race.c Thu May 10 09:18:22 2012
@@ -0,0 +1,36 @@
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <unistd.h>
+
+int *mem;
+pthread_mutex_t mtx;
+
+void *Thread1(void *x) {
+ pthread_mutex_lock(&mtx);
+ free(mem);
+ pthread_mutex_unlock(&mtx);
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ usleep(1000000);
+ pthread_mutex_lock(&mtx);
+ mem[0] = 42;
+ pthread_mutex_unlock(&mtx);
+ return NULL;
+}
+
+int main() {
+ mem = (int*)malloc(100);
+ pthread_mutex_init(&mtx, 0);
+ pthread_t t;
+ pthread_create(&t, NULL, Thread1, NULL);
+ Thread2(0);
+ pthread_join(t, NULL);
+ pthread_mutex_destroy(&mtx);
+ return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
Added: compiler-rt/trunk/lib/tsan/output_tests/heap_race.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/heap_race.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/heap_race.cc (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/heap_race.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,19 @@
+#include <pthread.h>
+#include <stdio.h>
+#include <stddef.h>
+
+void *Thread(void *a) {
+ ((int*)a)[0]++;
+ return NULL;
+}
+
+int main() {
+ int *p = new int(42);
+ pthread_t t;
+ pthread_create(&t, NULL, Thread, p);
+ p[0]++;
+ pthread_join(t, NULL);
+ delete p;
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
Added: compiler-rt/trunk/lib/tsan/output_tests/memcpy_race.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/memcpy_race.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/memcpy_race.cc (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/memcpy_race.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,40 @@
+#include <pthread.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+char *data = new char[10];
+char *data1 = new char[10];
+char *data2 = new char[10];
+
+void *Thread1(void *x) {
+ memcpy(data+5, data1, 1);
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ usleep(500*1000);
+ memcpy(data+3, data2, 4);
+ return NULL;
+}
+
+int main() {
+ fprintf(stderr, "addr=%p\n", &data[5]);
+ pthread_t t[2];
+ pthread_create(&t[0], NULL, Thread1, NULL);
+ pthread_create(&t[1], NULL, Thread2, NULL);
+ pthread_join(t[0], NULL);
+ pthread_join(t[1], NULL);
+ return 0;
+}
+
+// CHECK: addr=[[ADDR:0x[0-9,a-f]+]]
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: Write of size 1 at [[ADDR]] by thread 2:
+// CHECK: #0 memcpy
+// CHECK: #1 Thread2
+// CHECK: Previous write of size 1 at [[ADDR]] by thread 1:
+// CHECK: #0 memcpy
+// CHECK: #1 Thread1
+
Added: compiler-rt/trunk/lib/tsan/output_tests/mop_with_offset.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/mop_with_offset.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/mop_with_offset.cc (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/mop_with_offset.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,35 @@
+#include <pthread.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <unistd.h>
+
+void *Thread1(void *x) {
+ int *p = (int*)x;
+ p[0] = 1;
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ usleep(500*1000);
+ char *p = (char*)x;
+ p[2] = 1;
+ return NULL;
+}
+
+int main() {
+ int data = 42;
+ fprintf(stderr, "ptr1=%p\n", &data);
+ fprintf(stderr, "ptr2=%p\n", (char*)&data + 2);
+ pthread_t t[2];
+ pthread_create(&t[0], NULL, Thread1, &data);
+ pthread_create(&t[1], NULL, Thread2, &data);
+ pthread_join(t[0], NULL);
+ pthread_join(t[1], NULL);
+}
+
+// CHECK: ptr1=[[PTR1:0x[0-9,a-f]+]]
+// CHECK: ptr2=[[PTR2:0x[0-9,a-f]+]]
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: Write of size 1 at [[PTR2]] by thread 2:
+// CHECK: Previous write of size 4 at [[PTR1]] by thread 1:
+
Added: compiler-rt/trunk/lib/tsan/output_tests/mop_with_offset2.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/mop_with_offset2.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/mop_with_offset2.cc (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/mop_with_offset2.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,35 @@
+#include <pthread.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <unistd.h>
+
+void *Thread1(void *x) {
+ usleep(500*1000);
+ int *p = (int*)x;
+ p[0] = 1;
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ char *p = (char*)x;
+ p[2] = 1;
+ return NULL;
+}
+
+int main() {
+ int data = 42;
+ fprintf(stderr, "ptr1=%p\n", &data);
+ fprintf(stderr, "ptr2=%p\n", (char*)&data + 2);
+ pthread_t t[2];
+ pthread_create(&t[0], NULL, Thread1, &data);
+ pthread_create(&t[1], NULL, Thread2, &data);
+ pthread_join(t[0], NULL);
+ pthread_join(t[1], NULL);
+}
+
+// CHECK: ptr1=[[PTR1:0x[0-9,a-f]+]]
+// CHECK: ptr2=[[PTR2:0x[0-9,a-f]+]]
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: Write of size 4 at [[PTR1]] by thread 1:
+// CHECK: Previous write of size 1 at [[PTR2]] by thread 2:
+
Added: compiler-rt/trunk/lib/tsan/output_tests/race_on_barrier.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/race_on_barrier.c?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/race_on_barrier.c (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/race_on_barrier.c Thu May 10 09:18:22 2012
@@ -0,0 +1,31 @@
+#include <pthread.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <unistd.h>
+
+pthread_barrier_t B;
+int Global;
+
+void *Thread1(void *x) {
+ pthread_barrier_init(&B, 0, 2);
+ pthread_barrier_wait(&B);
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ usleep(1000000);
+ pthread_barrier_wait(&B);
+ return NULL;
+}
+
+int main() {
+ pthread_t t;
+ pthread_create(&t, NULL, Thread1, NULL);
+ Thread2(0);
+ pthread_join(t, NULL);
+ pthread_barrier_destroy(&B);
+ return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+
Added: compiler-rt/trunk/lib/tsan/output_tests/race_on_barrier2.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/race_on_barrier2.c?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/race_on_barrier2.c (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/race_on_barrier2.c Thu May 10 09:18:22 2012
@@ -0,0 +1,30 @@
+#include <pthread.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <unistd.h>
+
+pthread_barrier_t B;
+int Global;
+
+void *Thread1(void *x) {
+ if (pthread_barrier_wait(&B) == PTHREAD_BARRIER_SERIAL_THREAD)
+ pthread_barrier_destroy(&B);
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ if (pthread_barrier_wait(&B) == PTHREAD_BARRIER_SERIAL_THREAD)
+ pthread_barrier_destroy(&B);
+ return NULL;
+}
+
+int main() {
+ pthread_barrier_init(&B, 0, 2);
+ pthread_t t;
+ pthread_create(&t, NULL, Thread1, NULL);
+ Thread2(0);
+ pthread_join(t, NULL);
+ return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
Added: compiler-rt/trunk/lib/tsan/output_tests/race_on_mutex.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/race_on_mutex.c?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/race_on_mutex.c (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/race_on_mutex.c Thu May 10 09:18:22 2012
@@ -0,0 +1,42 @@
+#include <pthread.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <unistd.h>
+
+pthread_mutex_t Mtx;
+int Global;
+
+void *Thread1(void *x) {
+ pthread_mutex_init(&Mtx, 0);
+ pthread_mutex_lock(&Mtx);
+ Global = 42;
+ pthread_mutex_unlock(&Mtx);
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ usleep(1000000);
+ pthread_mutex_lock(&Mtx);
+ Global = 43;
+ pthread_mutex_unlock(&Mtx);
+ return NULL;
+}
+
+int main() {
+ pthread_t t[2];
+ pthread_create(&t[0], NULL, Thread1, NULL);
+ pthread_create(&t[1], NULL, Thread2, NULL);
+ pthread_join(t[0], NULL);
+ pthread_join(t[1], NULL);
+ pthread_mutex_destroy(&Mtx);
+ return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK-NEXT: Read of size 1 at {{.*}} by thread 2:
+// CHECK-NEXT: #0 pthread_mutex_lock {{.*}} ({{.*}})
+// CHECK-NEXT: #1 Thread2 {{.*}}race_on_mutex.c:19 ({{.*}})
+// CHECK-NEXT: Previous write of size 1 at {{.*}} by thread 1:
+// CHECK-NEXT: #0 pthread_mutex_init {{.*}} ({{.*}})
+// CHECK-NEXT: #1 Thread1 {{.*}}race_on_mutex.c:10 ({{.*}})
+
Added: compiler-rt/trunk/lib/tsan/output_tests/race_with_finished_thread.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/race_with_finished_thread.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/race_with_finished_thread.cc (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/race_with_finished_thread.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,43 @@
+#include <pthread.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+// Ensure that we can restore a stack of a finished thread.
+
+int g_data;
+
+void __attribute__((noinline)) foobar(int *p) {
+ *p = 42;
+}
+
+void *Thread1(void *x) {
+ foobar(&g_data);
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ usleep(1000*1000);
+ g_data = 43;
+ return NULL;
+}
+
+int main() {
+ pthread_t t[2];
+ pthread_create(&t[0], NULL, Thread1, NULL);
+ pthread_create(&t[1], NULL, Thread2, NULL);
+ pthread_join(t[0], NULL);
+ pthread_join(t[1], NULL);
+ return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: Write of size 4 at {{.*}} by thread 2:
+// CHECK: Previous write of size 4 at {{.*}} by thread 1:
+// CHECK: #0 foobar
+// CHECK: #1 Thread1
+// CHECK: Thread 1 (finished) created at:
+// CHECK: #0 pthread_create
+// CHECK: #1 main
+
Added: compiler-rt/trunk/lib/tsan/output_tests/simple_race.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/simple_race.c?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/simple_race.c (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/simple_race.c Thu May 10 09:18:22 2012
@@ -0,0 +1,25 @@
+#include <pthread.h>
+#include <stdio.h>
+
+int Global;
+
+void *Thread1(void *x) {
+ Global = 42;
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ Global = 43;
+ return NULL;
+}
+
+int main() {
+ pthread_t t[2];
+ pthread_create(&t[0], NULL, Thread1, NULL);
+ pthread_create(&t[1], NULL, Thread2, NULL);
+ pthread_join(t[0], NULL);
+ pthread_join(t[1], NULL);
+ return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
Added: compiler-rt/trunk/lib/tsan/output_tests/simple_race.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/simple_race.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/simple_race.cc (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/simple_race.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,24 @@
+#include <pthread.h>
+#include <stdio.h>
+
+int Global;
+
+void *Thread1(void *x) {
+ Global++;
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ Global--;
+ return NULL;
+}
+
+int main() {
+ pthread_t t[2];
+ pthread_create(&t[0], NULL, Thread1, NULL);
+ pthread_create(&t[1], NULL, Thread2, NULL);
+ pthread_join(t[0], NULL);
+ pthread_join(t[1], NULL);
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
Added: compiler-rt/trunk/lib/tsan/output_tests/simple_stack.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/simple_stack.c?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/simple_stack.c (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/simple_stack.c Thu May 10 09:18:22 2012
@@ -0,0 +1,66 @@
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int Global;
+
+void __attribute__((noinline)) foo1() {
+ Global = 42;
+}
+
+void __attribute__((noinline)) bar1() {
+ volatile int tmp = 42; (void)tmp;
+ foo1();
+}
+
+void __attribute__((noinline)) foo2() {
+ volatile int v = Global; (void)v;
+}
+
+void __attribute__((noinline)) bar2() {
+ volatile int tmp = 42; (void)tmp;
+ foo2();
+}
+
+void *Thread1(void *x) {
+ usleep(1000000);
+ bar1();
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ bar2();
+ return NULL;
+}
+
+void StartThread(pthread_t *t, void *(*f)(void*)) {
+ pthread_create(t, NULL, f, NULL);
+}
+
+int main() {
+ pthread_t t[2];
+ StartThread(&t[0], Thread1);
+ StartThread(&t[1], Thread2);
+ pthread_join(t[0], NULL);
+ pthread_join(t[1], NULL);
+ return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK-NEXT: Write of size 4 at {{.*}} by thread 1:
+// CHECK-NEXT: #0 foo1 {{.*}}simple_stack.c:8 ({{.*}})
+// CHECK-NEXT: #1 bar1 {{.*}}simple_stack.c:13 ({{.*}})
+// CHECK-NEXT: #2 Thread1 {{.*}}simple_stack.c:27 ({{.*}})
+// CHECK-NEXT: Previous read of size 4 at {{.*}} by thread 2:
+// CHECK-NEXT: #0 foo2 {{.*}}simple_stack.c:17 ({{.*}})
+// CHECK-NEXT: #1 bar2 {{.*}}simple_stack.c:22 ({{.*}})
+// CHECK-NEXT: #2 Thread2 {{.*}}simple_stack.c:32 ({{.*}})
+// CHECK-NEXT: Thread 1 (running) created at:
+// CHECK-NEXT: #0 pthread_create {{.*}} ({{.*}})
+// CHECK-NEXT: #1 StartThread {{.*}}simple_stack.c:37 ({{.*}})
+// CHECK-NEXT: #2 main {{.*}}simple_stack.c:42 ({{.*}})
+// CHECK-NEXT: Thread 2 ({{.*}}) created at:
+// CHECK-NEXT: #0 pthread_create {{.*}} ({{.*}})
+// CHECK-NEXT: #1 StartThread {{.*}}simple_stack.c:37 ({{.*}})
+// CHECK-NEXT: #2 main {{.*}}simple_stack.c:43 ({{.*}})
+
Added: compiler-rt/trunk/lib/tsan/output_tests/simple_stack2.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/simple_stack2.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/simple_stack2.cc (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/simple_stack2.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,48 @@
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int Global;
+
+void __attribute__((noinline)) foo1() {
+ Global = 42;
+}
+
+void __attribute__((noinline)) bar1() {
+ volatile int tmp = 42; (void)tmp;
+ foo1();
+}
+
+void __attribute__((noinline)) foo2() {
+ volatile int v = Global; (void)v;
+}
+
+void __attribute__((noinline)) bar2() {
+ volatile int tmp = 42; (void)tmp;
+ foo2();
+}
+
+void *Thread1(void *x) {
+ usleep(1000000);
+ bar1();
+ return NULL;
+}
+
+int main() {
+ pthread_t t;
+ pthread_create(&t, NULL, Thread1, NULL);
+ bar2();
+ pthread_join(t, NULL);
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK-NEXT: Write of size 4 at {{.*}} by thread 1:
+// CHECK-NEXT: #0 foo1() {{.*}}simple_stack2.cc:8 ({{.*}})
+// CHECK-NEXT: #1 bar1() {{.*}}simple_stack2.cc:13 ({{.*}})
+// CHECK-NEXT: #2 Thread1(void*) {{.*}}simple_stack2.cc:27 ({{.*}})
+// CHECK-NEXT: Previous read of size 4 at {{.*}} by main thread:
+// CHECK-NEXT: #0 foo2() {{.*}}simple_stack2.cc:17 ({{.*}})
+// CHECK-NEXT: #1 bar2() {{.*}}simple_stack2.cc:22 ({{.*}})
+// CHECK-NEXT: #2 main {{.*}}simple_stack2.cc:34 ({{.*}})
+
+
Added: compiler-rt/trunk/lib/tsan/output_tests/static_init1.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/static_init1.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/static_init1.cc (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/static_init1.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,25 @@
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+struct P {
+ int x;
+ int y;
+};
+
+void *Thread(void *x) {
+ static P p = {rand(), rand()};
+ if (p.x > RAND_MAX || p.y > RAND_MAX)
+ exit(1);
+ return 0;
+}
+
+int main() {
+ pthread_t t[2];
+ pthread_create(&t[0], 0, Thread, 0);
+ pthread_create(&t[1], 0, Thread, 0);
+ pthread_join(t[0], 0);
+ pthread_join(t[1], 0);
+}
+
+// CHECK-NOT: WARNING: ThreadSanitizer: data race
Added: compiler-rt/trunk/lib/tsan/output_tests/static_init2.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/static_init2.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/static_init2.cc (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/static_init2.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,31 @@
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+struct Cache {
+ int x;
+ Cache(int x)
+ : x(x) {
+ }
+};
+
+void foo(Cache *my) {
+ static Cache *c = my ? my : new Cache(rand());
+ if (c->x >= RAND_MAX)
+ exit(1);
+}
+
+void *Thread(void *x) {
+ foo(new Cache(rand()));
+ return 0;
+}
+
+int main() {
+ pthread_t t[2];
+ pthread_create(&t[0], 0, Thread, 0);
+ pthread_create(&t[1], 0, Thread, 0);
+ pthread_join(t[0], 0);
+ pthread_join(t[1], 0);
+}
+
+// CHECK-NOT: WARNING: ThreadSanitizer: data race
Added: compiler-rt/trunk/lib/tsan/output_tests/static_init3.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/static_init3.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/static_init3.cc (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/static_init3.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,46 @@
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sched.h>
+
+struct Cache {
+ int x;
+};
+
+Cache g_cache;
+
+Cache *CreateCache() {
+ g_cache.x = rand();
+ return &g_cache;
+}
+
+_Atomic(Cache*) queue;
+
+void *Thread1(void *x) {
+ static Cache *c = CreateCache();
+ __c11_atomic_store(&queue, c, 0);
+ return 0;
+}
+
+void *Thread2(void *x) {
+ Cache *c = 0;
+ for (;;) {
+ c = __c11_atomic_load(&queue, 0);
+ if (c)
+ break;
+ sched_yield();
+ }
+ if (c->x >= RAND_MAX)
+ exit(1);
+ return 0;
+}
+
+int main() {
+ pthread_t t[2];
+ pthread_create(&t[0], 0, Thread1, 0);
+ pthread_create(&t[1], 0, Thread2, 0);
+ pthread_join(t[0], 0);
+ pthread_join(t[1], 0);
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
Added: compiler-rt/trunk/lib/tsan/output_tests/static_init4.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/static_init4.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/static_init4.cc (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/static_init4.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,35 @@
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sched.h>
+
+struct Cache {
+ int x;
+ Cache(int x)
+ : x(x) {
+ }
+};
+
+int g_other;
+
+Cache *CreateCache() {
+ g_other = rand();
+ return new Cache(rand());
+}
+
+void *Thread1(void *x) {
+ static Cache *c = CreateCache();
+ if (c->x == g_other)
+ exit(1);
+ return 0;
+}
+
+int main() {
+ pthread_t t[2];
+ pthread_create(&t[0], 0, Thread1, 0);
+ pthread_create(&t[1], 0, Thread1, 0);
+ pthread_join(t[0], 0);
+ pthread_join(t[1], 0);
+}
+
+// CHECK-NOT: WARNING: ThreadSanitizer: data race
Added: compiler-rt/trunk/lib/tsan/output_tests/static_init5.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/static_init5.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/static_init5.cc (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/static_init5.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,40 @@
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sched.h>
+
+struct Cache {
+ int x;
+ Cache(int x)
+ : x(x) {
+ }
+};
+
+void *AsyncInit(void *p) {
+ return new Cache((int)(long)p);
+}
+
+Cache *CreateCache() {
+ pthread_t t;
+ pthread_create(&t, 0, AsyncInit, (void*)rand());
+ void *res;
+ pthread_join(t, &res);
+ return (Cache*)res;
+}
+
+void *Thread1(void *x) {
+ static Cache *c = CreateCache();
+ if (c->x >= RAND_MAX)
+ exit(1);
+ return 0;
+}
+
+int main() {
+ pthread_t t[2];
+ pthread_create(&t[0], 0, Thread1, 0);
+ pthread_create(&t[1], 0, Thread1, 0);
+ pthread_join(t[0], 0);
+ pthread_join(t[1], 0);
+}
+
+// CHECK-NOT: WARNING: ThreadSanitizer: data race
Added: compiler-rt/trunk/lib/tsan/output_tests/suppress_same_address.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/suppress_same_address.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/suppress_same_address.cc (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/suppress_same_address.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,27 @@
+#include <pthread.h>
+
+int X;
+
+void *Thread1(void *x) {
+ X = 42;
+ X = 66;
+ X = 78;
+ return 0;
+}
+
+void *Thread2(void *x) {
+ X = 11;
+ X = 99;
+ X = 73;
+ return 0;
+}
+
+int main() {
+ pthread_t t;
+ pthread_create(&t, 0, Thread1, 0);
+ Thread2(0);
+ pthread_join(t, 0);
+}
+
+// CHECK: ThreadSanitizer: reported 1 warnings
+
Added: compiler-rt/trunk/lib/tsan/output_tests/suppress_same_stacks.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/suppress_same_stacks.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/suppress_same_stacks.cc (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/suppress_same_stacks.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,27 @@
+#include <pthread.h>
+
+volatile int N; // Prevent loop unrolling.
+int **data;
+
+void *Thread1(void *x) {
+ for (int i = 0; i < N; i++)
+ data[i][0] = 42;
+ return 0;
+}
+
+int main() {
+ N = 4;
+ data = new int*[N];
+ for (int i = 0; i < N; i++)
+ data[i] = new int;
+ pthread_t t;
+ pthread_create(&t, 0, Thread1, 0);
+ Thread1(0);
+ pthread_join(t, 0);
+ for (int i = 0; i < N; i++)
+ delete data[i];
+ delete[] data;
+}
+
+// CHECK: ThreadSanitizer: reported 1 warnings
+
Added: compiler-rt/trunk/lib/tsan/output_tests/suppress_sequence.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/suppress_sequence.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/suppress_sequence.cc (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/suppress_sequence.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,26 @@
+#include <pthread.h>
+#include <unistd.h>
+
+volatile int g_data1;
+volatile int g_data2;
+volatile int g_data3;
+volatile int g_data4;
+
+void *Thread1(void *x) {
+ if (x)
+ usleep(1000000);
+ g_data1 = 42;
+ g_data2 = 43;
+ g_data3 = 44;
+ g_data4 = 45;
+ return 0;
+}
+
+int main() {
+ pthread_t t;
+ pthread_create(&t, 0, Thread1, (void*)1);
+ Thread1(0);
+ pthread_join(t, 0);
+}
+
+// CHECK: ThreadSanitizer: reported 1 warnings
Added: compiler-rt/trunk/lib/tsan/output_tests/test_output.sh
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/test_output.sh?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/test_output.sh (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/test_output.sh Thu May 10 09:18:22 2012
@@ -0,0 +1,61 @@
+#!/bin/bash
+
+ulimit -s 8192;
+set -e # fail on any error
+
+ROOTDIR=`dirname $0`/..
+
+# Assuming clang is in path.
+CC=clang
+CXX=clang++
+
+# TODO: add testing for all of -O0...-O3
+CFLAGS="-fthread-sanitizer -fPIE -O1 -g -fno-builtin -Wall -Werror=return-type"
+LDFLAGS="-pie -lpthread -ldl $ROOTDIR/tsan/libtsan.a"
+if [ "$LLDB" != "" ]; then
+ LDFLAGS+=" -L$LLDB -llldb"
+fi
+
+strip() {
+ grep -v "$1" test.out > test.out2
+ mv -f test.out2 test.out
+}
+
+test_file() {
+ SRC=$1
+ COMPILER=$2
+ echo ----- TESTING $1
+ OBJ=$SRC.o
+ EXE=$SRC.exe
+ $COMPILER $SRC $CFLAGS -c -o $OBJ
+ # Link with CXX, because lldb and suppressions require C++.
+ $CXX $OBJ $LDFLAGS -o $EXE
+ LD_LIBRARY_PATH=$LLDB TSAN_OPTIONS="atexit_sleep_ms=0" $EXE 2> test.out || echo -n
+ if [ "$3" != "" ]; then
+ cat test.out
+ fi
+ echo >>test.out # FileCheck fails on empty files
+ FileCheck < test.out $SRC
+ if [ "$3" == "" ]; then
+ rm -f $EXE $OBJ test.out *.tmp *.tmp2
+ fi
+}
+
+if [ "$1" == "" ]; then
+ for c in $ROOTDIR/output_tests/*.c; do
+ if [[ $c == */failing_* ]]; then
+ echo SKIPPING FAILING TEST $c
+ continue
+ fi
+ test_file $c $CC
+ done
+ for c in $ROOTDIR/output_tests/*.cc; do
+ if [[ $c == */failing_* ]]; then
+ echo SKIPPING FAILING TEST $c
+ continue
+ fi
+ test_file $c $CXX
+ done
+else
+ test_file $ROOTDIR/output_tests/$1 $CXX "DUMP"
+fi
Propchange: compiler-rt/trunk/lib/tsan/output_tests/test_output.sh
------------------------------------------------------------------------------
svn:executable = *
Added: compiler-rt/trunk/lib/tsan/output_tests/thread_leak.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/thread_leak.c?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/thread_leak.c (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/thread_leak.c Thu May 10 09:18:22 2012
@@ -0,0 +1,15 @@
+#include <pthread.h>
+
+void *Thread(void *x) {
+ return 0;
+}
+
+int main() {
+ pthread_t t;
+ pthread_create(&t, 0, Thread, 0);
+ pthread_join(t, 0);
+ return 0;
+}
+
+// CHECK-NOT: WARNING: ThreadSanitizer: thread leak
+
Added: compiler-rt/trunk/lib/tsan/output_tests/thread_leak2.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/thread_leak2.c?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/thread_leak2.c (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/thread_leak2.c Thu May 10 09:18:22 2012
@@ -0,0 +1,15 @@
+#include <pthread.h>
+
+void *Thread(void *x) {
+ return 0;
+}
+
+int main() {
+ pthread_t t;
+ pthread_create(&t, 0, Thread, 0);
+ pthread_detach(t);
+ return 0;
+}
+
+// CHECK-NOT: WARNING: ThreadSanitizer: thread leak
+
Added: compiler-rt/trunk/lib/tsan/output_tests/thread_leak3.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/thread_leak3.c?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/thread_leak3.c (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/thread_leak3.c Thu May 10 09:18:22 2012
@@ -0,0 +1,14 @@
+#include <pthread.h>
+
+void *Thread(void *x) {
+ return 0;
+}
+
+int main() {
+ pthread_t t;
+ pthread_create(&t, 0, Thread, 0);
+ return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: thread leak
+
Added: compiler-rt/trunk/lib/tsan/output_tests/vptr_benign_race.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/vptr_benign_race.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/vptr_benign_race.cc (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/vptr_benign_race.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,50 @@
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+
+struct A {
+ A() {
+ sem_init(&sem_, 0, 0);
+ }
+ virtual void F() {
+ }
+ void Done() {
+ sem_post(&sem_);
+ }
+ virtual ~A() {
+ }
+ sem_t sem_;
+};
+
+struct B : A {
+ virtual void F() {
+ }
+ virtual ~B() {
+ sem_wait(&sem_);
+ sem_destroy(&sem_);
+ }
+};
+
+static A *obj = new B;
+
+void *Thread1(void *x) {
+ obj->F();
+ obj->Done();
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ delete obj;
+ return NULL;
+}
+
+int main() {
+ pthread_t t[2];
+ pthread_create(&t[0], NULL, Thread1, NULL);
+ pthread_create(&t[1], NULL, Thread2, NULL);
+ pthread_join(t[0], NULL);
+ pthread_join(t[1], NULL);
+ fprintf(stderr, "PASS\n");
+}
+// CHECK: PASS
+// CHECK-NOT: WARNING: ThreadSanitizer: data race
Added: compiler-rt/trunk/lib/tsan/output_tests/vptr_harmful_race.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/output_tests/vptr_harmful_race.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/output_tests/vptr_harmful_race.cc (added)
+++ compiler-rt/trunk/lib/tsan/output_tests/vptr_harmful_race.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,48 @@
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+
+struct A {
+ A() {
+ sem_init(&sem_, 0, 0);
+ }
+ virtual void F() {
+ }
+ void Done() {
+ sem_post(&sem_);
+ }
+ virtual ~A() {
+ sem_wait(&sem_);
+ sem_destroy(&sem_);
+ }
+ sem_t sem_;
+};
+
+struct B : A {
+ virtual void F() {
+ }
+ virtual ~B() { }
+};
+
+static A *obj = new B;
+
+void *Thread1(void *x) {
+ obj->F();
+ obj->Done();
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ delete obj;
+ return NULL;
+}
+
+int main() {
+ pthread_t t[2];
+ pthread_create(&t[0], NULL, Thread1, NULL);
+ pthread_create(&t[1], NULL, Thread2, NULL);
+ pthread_join(t[0], NULL);
+ pthread_join(t[1], NULL);
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
Added: compiler-rt/trunk/lib/tsan/rtl_tests/tsan_bench.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl_tests/tsan_bench.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl_tests/tsan_bench.cc (added)
+++ compiler-rt/trunk/lib/tsan/rtl_tests/tsan_bench.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,105 @@
+//===-- tsan_bench.cc -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_test_util.h"
+#include "tsan_interface.h"
+#include "tsan_defs.h"
+#include "gtest/gtest.h"
+#include <stdint.h>
+
+const int kSize = 128;
+const int kRepeat = 2*1024*1024;
+
+void noinstr(void *p) {}
+
+template<typename T, void(*__tsan_mop)(void *p)>
+static void Benchmark() {
+ volatile T data[kSize];
+ for (int i = 0; i < kRepeat; i++) {
+ for (int j = 0; j < kSize; j++) {
+ __tsan_mop((void*)&data[j]);
+ data[j]++;
+ }
+ }
+}
+
+TEST(DISABLED_BENCH, Mop1) {
+ Benchmark<uint8_t, noinstr>();
+}
+
+TEST(DISABLED_BENCH, Mop1Read) {
+ Benchmark<uint8_t, __tsan_read1>();
+}
+
+TEST(DISABLED_BENCH, Mop1Write) {
+ Benchmark<uint8_t, __tsan_write1>();
+}
+
+TEST(DISABLED_BENCH, Mop2) {
+ Benchmark<uint16_t, noinstr>();
+}
+
+TEST(DISABLED_BENCH, Mop2Read) {
+ Benchmark<uint16_t, __tsan_read2>();
+}
+
+TEST(DISABLED_BENCH, Mop2Write) {
+ Benchmark<uint16_t, __tsan_write2>();
+}
+
+TEST(DISABLED_BENCH, Mop4) {
+ Benchmark<uint32_t, noinstr>();
+}
+
+TEST(DISABLED_BENCH, Mop4Read) {
+ Benchmark<uint32_t, __tsan_read4>();
+}
+
+TEST(DISABLED_BENCH, Mop4Write) {
+ Benchmark<uint32_t, __tsan_write4>();
+}
+
+TEST(DISABLED_BENCH, Mop8) {
+ Benchmark<uint8_t, noinstr>();
+}
+
+TEST(DISABLED_BENCH, Mop8Read) {
+ Benchmark<uint64_t, __tsan_read8>();
+}
+
+TEST(DISABLED_BENCH, Mop8Write) {
+ Benchmark<uint64_t, __tsan_write8>();
+}
+
+TEST(DISABLED_BENCH, FuncCall) {
+ for (int i = 0; i < kRepeat; i++) {
+ for (int j = 0; j < kSize; j++)
+ __tsan_func_entry((void*)(uintptr_t)j);
+ for (int j = 0; j < kSize; j++)
+ __tsan_func_exit();
+ }
+}
+
+TEST(DISABLED_BENCH, MutexLocal) {
+ Mutex m;
+ ScopedThread().Create(m);
+ for (int i = 0; i < 50; i++) {
+ ScopedThread t;
+ t.Lock(m);
+ t.Unlock(m);
+ }
+ for (int i = 0; i < 16*1024*1024; i++) {
+ m.Lock();
+ m.Unlock();
+ }
+ ScopedThread().Destroy(m);
+}
Added: compiler-rt/trunk/lib/tsan/rtl_tests/tsan_mop.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl_tests/tsan_mop.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl_tests/tsan_mop.cc (added)
+++ compiler-rt/trunk/lib/tsan/rtl_tests/tsan_mop.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,231 @@
+//===-- tsan_mop.cc ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_interface.h"
+#include "tsan_test_util.h"
+#include "gtest/gtest.h"
+#include <stddef.h>
+#include <stdint.h>
+
+TEST(ThreadSanitizer, SimpleWrite) {
+ ScopedThread t;
+ MemLoc l;
+ t.Write1(l);
+}
+
+TEST(ThreadSanitizer, SimpleWriteWrite) {
+ ScopedThread t1, t2;
+ MemLoc l1, l2;
+ t1.Write1(l1);
+ t2.Write1(l2);
+}
+
+TEST(ThreadSanitizer, WriteWriteRace) {
+ ScopedThread t1, t2;
+ MemLoc l;
+ t1.Write1(l);
+ t2.Write1(l, true);
+}
+
+TEST(ThreadSanitizer, ReadWriteRace) {
+ ScopedThread t1, t2;
+ MemLoc l;
+ t1.Read1(l);
+ t2.Write1(l, true);
+}
+
+TEST(ThreadSanitizer, WriteReadRace) {
+ ScopedThread t1, t2;
+ MemLoc l;
+ t1.Write1(l);
+ t2.Read1(l, true);
+}
+
+TEST(ThreadSanitizer, ReadReadNoRace) {
+ ScopedThread t1, t2;
+ MemLoc l;
+ t1.Read1(l);
+ t2.Read1(l);
+}
+
+TEST(ThreadSanitizer, WriteThenRead) {
+ MemLoc l;
+ ScopedThread t1, t2;
+ t1.Write1(l);
+ t1.Read1(l);
+ t2.Read1(l, true);
+}
+
+TEST(ThreadSanitizer, WriteThenLockedRead) {
+ Mutex m(Mutex::RW);
+ MainThread t0;
+ t0.Create(m);
+ MemLoc l;
+ {
+ ScopedThread t1, t2;
+
+ t1.Write8(l);
+
+ t1.Lock(m);
+ t1.Read8(l);
+ t1.Unlock(m);
+
+ t2.Read8(l, true);
+ }
+ t0.Destroy(m);
+}
+
+TEST(ThreadSanitizer, LockedWriteThenRead) {
+ Mutex m(Mutex::RW);
+ MainThread t0;
+ t0.Create(m);
+ MemLoc l;
+ {
+ ScopedThread t1, t2;
+
+ t1.Lock(m);
+ t1.Write8(l);
+ t1.Unlock(m);
+
+ t1.Read8(l);
+
+ t2.Read8(l, true);
+ }
+ t0.Destroy(m);
+}
+
+
+TEST(ThreadSanitizer, RaceWithOffset) {
+ ScopedThread t1, t2;
+ {
+ MemLoc l;
+ t1.Access(l.loc(), true, 8, false);
+ t2.Access((char*)l.loc() + 4, true, 4, true);
+ }
+ {
+ MemLoc l;
+ t1.Access(l.loc(), true, 8, false);
+ t2.Access((char*)l.loc() + 7, true, 1, true);
+ }
+ {
+ MemLoc l;
+ t1.Access((char*)l.loc() + 4, true, 4, false);
+ t2.Access((char*)l.loc() + 4, true, 2, true);
+ }
+ {
+ MemLoc l;
+ t1.Access((char*)l.loc() + 4, true, 4, false);
+ t2.Access((char*)l.loc() + 6, true, 2, true);
+ }
+ {
+ MemLoc l;
+ t1.Access((char*)l.loc() + 3, true, 2, false);
+ t2.Access((char*)l.loc() + 4, true, 1, true);
+ }
+ {
+ MemLoc l;
+ t1.Access((char*)l.loc() + 1, true, 8, false);
+ t2.Access((char*)l.loc() + 3, true, 1, true);
+ }
+}
+
+TEST(ThreadSanitizer, RaceWithOffset2) {
+ ScopedThread t1, t2;
+ {
+ MemLoc l;
+ t1.Access((char*)l.loc(), true, 4, false);
+ t2.Access((char*)l.loc() + 2, true, 1, true);
+ }
+ {
+ MemLoc l;
+ t1.Access((char*)l.loc() + 2, true, 1, false);
+ t2.Access((char*)l.loc(), true, 4, true);
+ }
+}
+
+TEST(ThreadSanitizer, NoRaceWithOffset) {
+ ScopedThread t1, t2;
+ {
+ MemLoc l;
+ t1.Access(l.loc(), true, 4, false);
+ t2.Access((char*)l.loc() + 4, true, 4, false);
+ }
+ {
+ MemLoc l;
+ t1.Access((char*)l.loc() + 3, true, 2, false);
+ t2.Access((char*)l.loc() + 1, true, 2, false);
+ t2.Access((char*)l.loc() + 5, true, 2, false);
+ }
+}
+
+TEST(ThreadSanitizer, RaceWithDeadThread) {
+ MemLoc l;
+ ScopedThread t;
+ ScopedThread().Write1(l);
+ t.Write1(l, true);
+}
+
+TEST(ThreadSanitizer, BenignRaceOnVptr) {
+ void *vptr_storage;
+ MemLoc vptr(&vptr_storage), val;
+ vptr_storage = val.loc();
+ ScopedThread t1, t2;
+ t1.VptrUpdate(vptr, val);
+ t2.Read8(vptr);
+}
+
+TEST(ThreadSanitizer, HarmfulRaceOnVptr) {
+ void *vptr_storage;
+ MemLoc vptr(&vptr_storage), val1, val2;
+ vptr_storage = val1.loc();
+ ScopedThread t1, t2;
+ t1.VptrUpdate(vptr, val2);
+ t2.Read8(vptr, true);
+}
+
+static void foo() {
+ volatile int x = 42;
+ (void)x;
+}
+
+static void bar() {
+ volatile int x = 43;
+ (void)x;
+}
+
+TEST(ThreadSanitizer, ReportDeadThread) {
+ MemLoc l;
+ ScopedThread t1;
+ {
+ ScopedThread t2;
+ t2.Call(&foo);
+ t2.Call(&bar);
+ t2.Write1(l);
+ }
+ t1.Write1(l, true);
+}
+
+struct ClassWithStatic {
+ static int Data[4];
+};
+
+int ClassWithStatic::Data[4];
+
+static void foobarbaz() {}
+
+TEST(ThreadSanitizer, ReportRace) {
+ ScopedThread t1;
+ MainThread().Access(&ClassWithStatic::Data, true, 4, false);
+ t1.Call(&foobarbaz);
+ t1.Access(&ClassWithStatic::Data, true, 2, true);
+ t1.Return();
+}
Added: compiler-rt/trunk/lib/tsan/rtl_tests/tsan_mutex.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl_tests/tsan_mutex.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl_tests/tsan_mutex.cc (added)
+++ compiler-rt/trunk/lib/tsan/rtl_tests/tsan_mutex.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,221 @@
+//===-- tsan_mutex.cc -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_atomic.h"
+#include "tsan_interface.h"
+#include "tsan_interface_ann.h"
+#include "tsan_test_util.h"
+#include "gtest/gtest.h"
+#include <stdint.h>
+
+namespace __tsan {
+
+TEST(ThreadSanitizer, BasicMutex) {
+ ScopedThread t;
+ Mutex m;
+ t.Create(m);
+
+ t.Lock(m);
+ t.Unlock(m);
+
+ CHECK(t.TryLock(m));
+ t.Unlock(m);
+
+ t.Lock(m);
+ CHECK(!t.TryLock(m));
+ t.Unlock(m);
+
+ t.Destroy(m);
+}
+
+TEST(ThreadSanitizer, BasicSpinMutex) {
+ ScopedThread t;
+ Mutex m(Mutex::Spin);
+ t.Create(m);
+
+ t.Lock(m);
+ t.Unlock(m);
+
+ CHECK(t.TryLock(m));
+ t.Unlock(m);
+
+ t.Lock(m);
+ CHECK(!t.TryLock(m));
+ t.Unlock(m);
+
+ t.Destroy(m);
+}
+
+TEST(ThreadSanitizer, BasicRwMutex) {
+ ScopedThread t;
+ Mutex m(Mutex::RW);
+ t.Create(m);
+
+ t.Lock(m);
+ t.Unlock(m);
+
+ CHECK(t.TryLock(m));
+ t.Unlock(m);
+
+ t.Lock(m);
+ CHECK(!t.TryLock(m));
+ t.Unlock(m);
+
+ t.ReadLock(m);
+ t.ReadUnlock(m);
+
+ CHECK(t.TryReadLock(m));
+ t.ReadUnlock(m);
+
+ t.Lock(m);
+ CHECK(!t.TryReadLock(m));
+ t.Unlock(m);
+
+ t.ReadLock(m);
+ CHECK(!t.TryLock(m));
+ t.ReadUnlock(m);
+
+ t.ReadLock(m);
+ CHECK(t.TryReadLock(m));
+ t.ReadUnlock(m);
+ t.ReadUnlock(m);
+
+ t.Destroy(m);
+}
+
+TEST(ThreadSanitizer, Mutex) {
+ Mutex m;
+ MainThread t0;
+ t0.Create(m);
+
+ ScopedThread t1, t2;
+ MemLoc l;
+ t1.Lock(m);
+ t1.Write1(l);
+ t1.Unlock(m);
+ t2.Lock(m);
+ t2.Write1(l);
+ t2.Unlock(m);
+ t2.Destroy(m);
+}
+
+TEST(ThreadSanitizer, SpinMutex) {
+ Mutex m(Mutex::Spin);
+ MainThread t0;
+ t0.Create(m);
+
+ ScopedThread t1, t2;
+ MemLoc l;
+ t1.Lock(m);
+ t1.Write1(l);
+ t1.Unlock(m);
+ t2.Lock(m);
+ t2.Write1(l);
+ t2.Unlock(m);
+ t2.Destroy(m);
+}
+
+TEST(ThreadSanitizer, RwMutex) {
+ Mutex m(Mutex::RW);
+ MainThread t0;
+ t0.Create(m);
+
+ ScopedThread t1, t2, t3;
+ MemLoc l;
+ t1.Lock(m);
+ t1.Write1(l);
+ t1.Unlock(m);
+ t2.Lock(m);
+ t2.Write1(l);
+ t2.Unlock(m);
+ t1.ReadLock(m);
+ t3.ReadLock(m);
+ t1.Read1(l);
+ t3.Read1(l);
+ t1.ReadUnlock(m);
+ t3.ReadUnlock(m);
+ t2.Lock(m);
+ t2.Write1(l);
+ t2.Unlock(m);
+ t2.Destroy(m);
+}
+
+TEST(ThreadSanitizer, StaticMutex) {
+ // Emulates statically initialized mutex.
+ Mutex m;
+ m.StaticInit();
+ {
+ ScopedThread t1, t2;
+ t1.Lock(m);
+ t1.Unlock(m);
+ t2.Lock(m);
+ t2.Unlock(m);
+ }
+ MainThread().Destroy(m);
+}
+
+static void *singleton_thread(void *param) {
+ atomic_uintptr_t *singleton = (atomic_uintptr_t *)param;
+ for (int i = 0; i < 4*1024*1024; i++) {
+ int *val = (int *)atomic_load(singleton, memory_order_acquire);
+ __tsan_acquire(singleton);
+ __tsan_read4(val);
+ CHECK_EQ(*val, 42);
+ }
+ return 0;
+}
+
+TEST(DISABLED_BENCH_ThreadSanitizer, Singleton) {
+ const int kClockSize = 100;
+ const int kThreadCount = 8;
+
+ // Puff off thread's clock.
+ for (int i = 0; i < kClockSize; i++) {
+ ScopedThread t1;
+ (void)t1;
+ }
+ // Create the singleton.
+ int val = 42;
+ __tsan_write4(&val);
+ atomic_uintptr_t singleton;
+ __tsan_release(&singleton);
+ atomic_store(&singleton, (uintptr_t)&val, memory_order_release);
+ // Create reader threads.
+ pthread_t threads[kThreadCount];
+ for (int t = 0; t < kThreadCount; t++)
+ pthread_create(&threads[t], 0, singleton_thread, &singleton);
+ for (int t = 0; t < kThreadCount; t++)
+ pthread_join(threads[t], 0);
+}
+
+TEST(DISABLED_BENCH_ThreadSanitizer, StopFlag) {
+ const int kClockSize = 100;
+ const int kIters = 16*1024*1024;
+
+ // Puff off thread's clock.
+ for (int i = 0; i < kClockSize; i++) {
+ ScopedThread t1;
+ (void)t1;
+ }
+ // Create the stop flag.
+ atomic_uintptr_t flag;
+ __tsan_release(&flag);
+ atomic_store(&flag, 0, memory_order_release);
+ // Read it a lot.
+ for (int i = 0; i < kIters; i++) {
+ uptr v = atomic_load(&flag, memory_order_acquire);
+ __tsan_acquire(&flag);
+ CHECK_EQ(v, 0);
+ }
+}
+
+} // namespace __tsan
Added: compiler-rt/trunk/lib/tsan/rtl_tests/tsan_posix.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl_tests/tsan_posix.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl_tests/tsan_posix.cc (added)
+++ compiler-rt/trunk/lib/tsan/rtl_tests/tsan_posix.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,146 @@
+//===-- tsan_posix.cc -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_interface.h"
+#include "tsan_test_util.h"
+#include "gtest/gtest.h"
+#include <pthread.h>
+
+struct thread_key {
+ pthread_key_t key;
+ pthread_mutex_t *mtx;
+ int val;
+ int *cnt;
+ thread_key(pthread_key_t key, pthread_mutex_t *mtx, int val, int *cnt)
+ : key(key)
+ , mtx(mtx)
+ , val(val)
+ , cnt(cnt) {
+ }
+};
+
+static void thread_secific_dtor(void *v) {
+ thread_key *k = (thread_key *)v;
+ EXPECT_EQ(pthread_mutex_lock(k->mtx), 0);
+ (*k->cnt)++;
+ __tsan_write4(&k->cnt);
+ EXPECT_EQ(pthread_mutex_unlock(k->mtx), 0);
+ if (k->val == 42) {
+ delete k;
+ } else if (k->val == 43 || k->val == 44) {
+ k->val--;
+ EXPECT_EQ(pthread_setspecific(k->key, k), 0);
+ } else {
+ ASSERT_TRUE(false);
+ }
+}
+
+static void *dtors_thread(void *p) {
+ thread_key *k = (thread_key *)p;
+ EXPECT_EQ(pthread_setspecific(k->key, k), 0);
+ return 0;
+}
+
+TEST(Posix, ThreadSpecificDtors) {
+ int cnt = 0;
+ pthread_key_t key;
+ EXPECT_EQ(pthread_key_create(&key, thread_secific_dtor), 0);
+ pthread_mutex_t mtx;
+ EXPECT_EQ(pthread_mutex_init(&mtx, 0), 0);
+ pthread_t th[3];
+ thread_key *k[3];
+ k[0] = new thread_key(key, &mtx, 42, &cnt);
+ k[1] = new thread_key(key, &mtx, 43, &cnt);
+ k[2] = new thread_key(key, &mtx, 44, &cnt);
+ EXPECT_EQ(pthread_create(&th[0], 0, dtors_thread, k[0]), 0);
+ EXPECT_EQ(pthread_create(&th[1], 0, dtors_thread, k[1]), 0);
+ EXPECT_EQ(pthread_join(th[0], 0), 0);
+ EXPECT_EQ(pthread_create(&th[2], 0, dtors_thread, k[2]), 0);
+ EXPECT_EQ(pthread_join(th[1], 0), 0);
+ EXPECT_EQ(pthread_join(th[2], 0), 0);
+ EXPECT_EQ(pthread_key_delete(key), 0);
+ EXPECT_EQ(6, cnt);
+}
+
+static __thread int local_var;
+
+static void *local_thread(void *p) {
+ __tsan_write1(&local_var);
+ __tsan_write1(&p);
+ if (p == 0)
+ return 0;
+ const int kThreads = 4;
+ pthread_t th[kThreads];
+ for (int i = 0; i < kThreads; i++)
+ EXPECT_EQ(pthread_create(&th[i], 0, local_thread,
+ (void*)((long)p - 1)), 0); // NOLINT
+ for (int i = 0; i < kThreads; i++)
+ EXPECT_EQ(pthread_join(th[i], 0), 0);
+ return 0;
+}
+
+TEST(Posix, ThreadLocalAccesses) {
+ local_thread((void*)2);
+}
+
+struct CondContext {
+ pthread_mutex_t m;
+ pthread_cond_t c;
+ int data;
+};
+
+static void *cond_thread(void *p) {
+ CondContext &ctx = *static_cast<CondContext*>(p);
+
+ EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0);
+ EXPECT_EQ(ctx.data, 0);
+ ctx.data = 1;
+ EXPECT_EQ(pthread_cond_signal(&ctx.c), 0);
+ EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0);
+
+ EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0);
+ while (ctx.data != 2)
+ EXPECT_EQ(pthread_cond_wait(&ctx.c, &ctx.m), 0);
+ EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0);
+
+ EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0);
+ ctx.data = 3;
+ EXPECT_EQ(pthread_cond_broadcast(&ctx.c), 0);
+ EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0);
+
+ return 0;
+}
+
+TEST(Posix, CondBasic) {
+ CondContext ctx;
+ EXPECT_EQ(pthread_mutex_init(&ctx.m, 0), 0);
+ EXPECT_EQ(pthread_cond_init(&ctx.c, 0), 0);
+ ctx.data = 0;
+ pthread_t th;
+ EXPECT_EQ(pthread_create(&th, 0, cond_thread, &ctx), 0);
+
+ EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0);
+ while (ctx.data != 1)
+ EXPECT_EQ(pthread_cond_wait(&ctx.c, &ctx.m), 0);
+ ctx.data = 2;
+ EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0);
+ EXPECT_EQ(pthread_cond_broadcast(&ctx.c), 0);
+
+ EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0);
+ while (ctx.data != 3)
+ EXPECT_EQ(pthread_cond_wait(&ctx.c, &ctx.m), 0);
+ EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0);
+
+ EXPECT_EQ(pthread_join(th, 0), 0);
+ EXPECT_EQ(pthread_cond_destroy(&ctx.c), 0);
+ EXPECT_EQ(pthread_mutex_destroy(&ctx.m), 0);
+}
Added: compiler-rt/trunk/lib/tsan/rtl_tests/tsan_string.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl_tests/tsan_string.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl_tests/tsan_string.cc (added)
+++ compiler-rt/trunk/lib/tsan/rtl_tests/tsan_string.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,82 @@
+//===-- tsan_string.cc ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_test_util.h"
+#include "gtest/gtest.h"
+#include <string.h>
+
+namespace __tsan {
+
+TEST(ThreadSanitizer, Memcpy) {
+ char data0[7] = {1, 2, 3, 4, 5, 6, 7};
+ char data[7] = {42, 42, 42, 42, 42, 42, 42};
+ MainThread().Memcpy(data+1, data0+1, 5);
+ EXPECT_EQ(data[0], 42);
+ EXPECT_EQ(data[1], 2);
+ EXPECT_EQ(data[2], 3);
+ EXPECT_EQ(data[3], 4);
+ EXPECT_EQ(data[4], 5);
+ EXPECT_EQ(data[5], 6);
+ EXPECT_EQ(data[6], 42);
+ MainThread().Memset(data+1, 13, 5);
+ EXPECT_EQ(data[0], 42);
+ EXPECT_EQ(data[1], 13);
+ EXPECT_EQ(data[2], 13);
+ EXPECT_EQ(data[3], 13);
+ EXPECT_EQ(data[4], 13);
+ EXPECT_EQ(data[5], 13);
+ EXPECT_EQ(data[6], 42);
+}
+
+TEST(ThreadSanitizer, MemcpyRace1) {
+ char *data = new char[10];
+ char *data1 = new char[10];
+ char *data2 = new char[10];
+ ScopedThread t1, t2;
+ t1.Memcpy(data, data1, 10);
+ t2.Memcpy(data, data2, 10, true);
+}
+
+TEST(ThreadSanitizer, MemcpyRace2) {
+ char *data = new char[10];
+ char *data1 = new char[10];
+ char *data2 = new char[10];
+ ScopedThread t1, t2;
+ t1.Memcpy(data+5, data1, 1);
+ t2.Memcpy(data+3, data2, 4, true);
+}
+
+TEST(ThreadSanitizer, MemcpyRace3) {
+ char *data = new char[10];
+ char *data1 = new char[10];
+ char *data2 = new char[10];
+ ScopedThread t1, t2;
+ t1.Memcpy(data, data1, 10);
+ t2.Memcpy(data1, data2, 10, true);
+}
+
+TEST(ThreadSanitizer, MemcpyStack) {
+ char *data = new char[10];
+ char *data1 = new char[10];
+ ScopedThread t1, t2;
+ t1.Memcpy(data, data1, 10);
+ t2.Memcpy(data, data1, 10, true);
+}
+
+TEST(ThreadSanitizer, MemsetRace1) {
+ char *data = new char[10];
+ ScopedThread t1, t2;
+ t1.Memset(data, 1, 10);
+ t2.Memset(data, 2, 10, true);
+}
+
+} // namespace __tsan
Added: compiler-rt/trunk/lib/tsan/rtl_tests/tsan_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl_tests/tsan_test.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl_tests/tsan_test.cc (added)
+++ compiler-rt/trunk/lib/tsan/rtl_tests/tsan_test.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,43 @@
+//===-- tsan_test.cc --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_interface.h"
+#include "tsan_test_util.h"
+#include "gtest/gtest.h"
+
+static void foo() {}
+static void bar() {}
+
+TEST(ThreadSanitizer, FuncCall) {
+ ScopedThread t1, t2;
+ MemLoc l;
+ t1.Write1(l);
+ t2.Call(foo);
+ t2.Call(bar);
+ t2.Write1(l, true);
+ t2.Return();
+ t2.Return();
+}
+
+int main(int argc, char **argv) {
+ TestMutexBeforeInit(); // Mutexes must be usable before __tsan_init();
+ __tsan_init();
+ __tsan_func_entry(__builtin_return_address(0));
+ __tsan_func_entry((char*)&main + 1);
+
+ testing::InitGoogleTest(&argc, argv);
+ int res = RUN_ALL_TESTS();
+
+ __tsan_func_exit();
+ __tsan_func_exit();
+ return res;
+}
Added: compiler-rt/trunk/lib/tsan/rtl_tests/tsan_test_util.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl_tests/tsan_test_util.h?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl_tests/tsan_test_util.h (added)
+++ compiler-rt/trunk/lib/tsan/rtl_tests/tsan_test_util.h Thu May 10 09:18:22 2012
@@ -0,0 +1,122 @@
+//===-- tsan_test_util.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// Test utils.
+//===----------------------------------------------------------------------===//
+#ifndef TSAN_TEST_UTIL_H
+#define TSAN_TEST_UTIL_H
+
+void TestMutexBeforeInit();
+
+// A location of memory on which a race may be detected.
+class MemLoc {
+ public:
+ explicit MemLoc(int offset_from_aligned = 0);
+ explicit MemLoc(void *const real_addr) : loc_(real_addr) { }
+ ~MemLoc();
+ void *loc() const { return loc_; }
+ private:
+ void *const loc_;
+ MemLoc(const MemLoc&);
+ void operator = (const MemLoc&);
+};
+
+class Mutex {
+ public:
+ enum Type { Normal, Spin, RW };
+
+ explicit Mutex(Type type = Normal);
+ ~Mutex();
+
+ void Init();
+ void StaticInit(); // Emulates static initalization (tsan invisible).
+ void Destroy();
+ void Lock();
+ bool TryLock();
+ void Unlock();
+ void ReadLock();
+ bool TryReadLock();
+ void ReadUnlock();
+
+ private:
+ // Placeholder for pthread_mutex_t, CRITICAL_SECTION or whatever.
+ void *mtx_[128];
+ bool alive_;
+ const Type type_;
+
+ Mutex(const Mutex&);
+ void operator = (const Mutex&);
+};
+
+// A thread is started in CTOR and joined in DTOR.
+class ScopedThread {
+ public:
+ explicit ScopedThread(bool detached = false, bool main = false);
+ ~ScopedThread();
+ void Detach();
+
+ void Access(void *addr, bool is_write, int size, bool expect_race);
+ void Read(const MemLoc &ml, int size, bool expect_race = false) {
+ Access(ml.loc(), false, size, expect_race);
+ }
+ void Write(const MemLoc &ml, int size, bool expect_race = false) {
+ Access(ml.loc(), true, size, expect_race);
+ }
+ void Read1(const MemLoc &ml, bool expect_race = false) {
+ Read(ml, 1, expect_race); }
+ void Read2(const MemLoc &ml, bool expect_race = false) {
+ Read(ml, 2, expect_race); }
+ void Read4(const MemLoc &ml, bool expect_race = false) {
+ Read(ml, 4, expect_race); }
+ void Read8(const MemLoc &ml, bool expect_race = false) {
+ Read(ml, 8, expect_race); }
+ void Write1(const MemLoc &ml, bool expect_race = false) {
+ Write(ml, 1, expect_race); }
+ void Write2(const MemLoc &ml, bool expect_race = false) {
+ Write(ml, 2, expect_race); }
+ void Write4(const MemLoc &ml, bool expect_race = false) {
+ Write(ml, 4, expect_race); }
+ void Write8(const MemLoc &ml, bool expect_race = false) {
+ Write(ml, 8, expect_race); }
+
+ void VptrUpdate(const MemLoc &vptr, const MemLoc &new_val,
+ bool expect_race = false);
+
+ void Call(void(*pc)());
+ void Return();
+
+ void Create(const Mutex &m);
+ void Destroy(const Mutex &m);
+ void Lock(const Mutex &m);
+ bool TryLock(const Mutex &m);
+ void Unlock(const Mutex &m);
+ void ReadLock(const Mutex &m);
+ bool TryReadLock(const Mutex &m);
+ void ReadUnlock(const Mutex &m);
+
+ void Memcpy(void *dst, const void *src, int size, bool expect_race = false);
+ void Memset(void *dst, int val, int size, bool expect_race = false);
+
+ private:
+ struct Impl;
+ Impl *impl_;
+ ScopedThread(const ScopedThread&); // Not implemented.
+ void operator = (const ScopedThread&); // Not implemented.
+};
+
+class MainThread : public ScopedThread {
+ public:
+ MainThread()
+ : ScopedThread(false, true) {
+ }
+};
+
+#endif // #ifndef TSAN_TEST_UTIL_H
Added: compiler-rt/trunk/lib/tsan/rtl_tests/tsan_test_util_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl_tests/tsan_test_util_linux.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl_tests/tsan_test_util_linux.cc (added)
+++ compiler-rt/trunk/lib/tsan/rtl_tests/tsan_test_util_linux.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,460 @@
+//===-- tsan_test_util_linux.cc ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// Test utils, linux implementation.
+//===----------------------------------------------------------------------===//
+
+#include "tsan_interface.h"
+#include "tsan_test_util.h"
+#include "tsan_atomic.h"
+#include "tsan_report.h"
+
+#include "gtest/gtest.h"
+
+#include <assert.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+using namespace __tsan; // NOLINT
+
+static __thread bool expect_report;
+static __thread bool expect_report_reported;
+static __thread ReportType expect_report_type;
+
+static void *BeforeInitThread(void *param) {
+ (void)param;
+ return 0;
+}
+
+static void AtExit() {
+}
+
+void TestMutexBeforeInit() {
+ // Mutexes must be usable before __tsan_init();
+ pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
+ pthread_mutex_lock(&mtx);
+ pthread_mutex_unlock(&mtx);
+ pthread_mutex_destroy(&mtx);
+ pthread_t thr;
+ pthread_create(&thr, 0, BeforeInitThread, 0);
+ pthread_join(thr, 0);
+ atexit(AtExit);
+}
+
+namespace __tsan {
+bool OnReport(const ReportDesc *rep, bool suppressed) {
+ if (expect_report) {
+ if (rep->typ != expect_report_type) {
+ printf("Expected report of type %d, got type %d\n",
+ (int)expect_report_type, (int)rep->typ);
+ EXPECT_FALSE("Wrong report type");
+ return false;
+ }
+ } else {
+ EXPECT_FALSE("Unexpected report");
+ return false;
+ }
+ expect_report_reported = true;
+ return true;
+}
+}
+
+static void* allocate_addr(int size, int offset_from_aligned = 0) {
+ static uintptr_t foo;
+ static atomic_uintptr_t uniq = {(uintptr_t)&foo}; // Some real address.
+ const int kAlign = 16;
+ CHECK(offset_from_aligned < kAlign);
+ size = (size + 2 * kAlign) & ~(kAlign - 1);
+ uintptr_t addr = atomic_fetch_add(&uniq, size, memory_order_relaxed);
+ return (void*)(addr + offset_from_aligned);
+}
+
+MemLoc::MemLoc(int offset_from_aligned)
+ : loc_(allocate_addr(16, offset_from_aligned)) {
+}
+
+MemLoc::~MemLoc() {
+}
+
+Mutex::Mutex(Type type)
+ : alive_()
+ , type_(type) {
+}
+
+Mutex::~Mutex() {
+ CHECK(!alive_);
+}
+
+void Mutex::Init() {
+ CHECK(!alive_);
+ alive_ = true;
+ if (type_ == Normal)
+ CHECK_EQ(pthread_mutex_init((pthread_mutex_t*)mtx_, 0), 0);
+ else if (type_ == Spin)
+ CHECK_EQ(pthread_spin_init((pthread_spinlock_t*)mtx_, 0), 0);
+ else if (type_ == RW)
+ CHECK_EQ(pthread_rwlock_init((pthread_rwlock_t*)mtx_, 0), 0);
+ else
+ CHECK(0);
+}
+
+void Mutex::StaticInit() {
+ CHECK(!alive_);
+ CHECK(type_ == Normal);
+ alive_ = true;
+ pthread_mutex_t tmp = PTHREAD_MUTEX_INITIALIZER;
+ memcpy(mtx_, &tmp, sizeof(tmp));
+}
+
+void Mutex::Destroy() {
+ CHECK(alive_);
+ alive_ = false;
+ if (type_ == Normal)
+ CHECK_EQ(pthread_mutex_destroy((pthread_mutex_t*)mtx_), 0);
+ else if (type_ == Spin)
+ CHECK_EQ(pthread_spin_destroy((pthread_spinlock_t*)mtx_), 0);
+ else if (type_ == RW)
+ CHECK_EQ(pthread_rwlock_destroy((pthread_rwlock_t*)mtx_), 0);
+}
+
+void Mutex::Lock() {
+ CHECK(alive_);
+ if (type_ == Normal)
+ CHECK_EQ(pthread_mutex_lock((pthread_mutex_t*)mtx_), 0);
+ else if (type_ == Spin)
+ CHECK_EQ(pthread_spin_lock((pthread_spinlock_t*)mtx_), 0);
+ else if (type_ == RW)
+ CHECK_EQ(pthread_rwlock_wrlock((pthread_rwlock_t*)mtx_), 0);
+}
+
+bool Mutex::TryLock() {
+ CHECK(alive_);
+ if (type_ == Normal)
+ return pthread_mutex_trylock((pthread_mutex_t*)mtx_) == 0;
+ else if (type_ == Spin)
+ return pthread_spin_trylock((pthread_spinlock_t*)mtx_) == 0;
+ else if (type_ == RW)
+ return pthread_rwlock_trywrlock((pthread_rwlock_t*)mtx_) == 0;
+ return false;
+}
+
+void Mutex::Unlock() {
+ CHECK(alive_);
+ if (type_ == Normal)
+ CHECK_EQ(pthread_mutex_unlock((pthread_mutex_t*)mtx_), 0);
+ else if (type_ == Spin)
+ CHECK_EQ(pthread_spin_unlock((pthread_spinlock_t*)mtx_), 0);
+ else if (type_ == RW)
+ CHECK_EQ(pthread_rwlock_unlock((pthread_rwlock_t*)mtx_), 0);
+}
+
+void Mutex::ReadLock() {
+ CHECK(alive_);
+ CHECK(type_ == RW);
+ CHECK_EQ(pthread_rwlock_rdlock((pthread_rwlock_t*)mtx_), 0);
+}
+
+bool Mutex::TryReadLock() {
+ CHECK(alive_);
+ CHECK(type_ == RW);
+ return pthread_rwlock_tryrdlock((pthread_rwlock_t*)mtx_) == 0;
+}
+
+void Mutex::ReadUnlock() {
+ CHECK(alive_);
+ CHECK(type_ == RW);
+ CHECK_EQ(pthread_rwlock_unlock((pthread_rwlock_t*)mtx_), 0);
+}
+
+struct Event {
+ enum Type {
+ SHUTDOWN,
+ READ,
+ WRITE,
+ VPTR_UPDATE,
+ CALL,
+ RETURN,
+ MUTEX_CREATE,
+ MUTEX_DESTROY,
+ MUTEX_LOCK,
+ MUTEX_TRYLOCK,
+ MUTEX_UNLOCK,
+ MUTEX_READLOCK,
+ MUTEX_TRYREADLOCK,
+ MUTEX_READUNLOCK,
+ MEMCPY,
+ MEMSET
+ };
+ Type type;
+ void *ptr;
+ uptr arg;
+ uptr arg2;
+ bool res;
+ bool expect_report;
+ ReportType report_type;
+
+ Event(Type type, const void *ptr = 0, uptr arg = 0, uptr arg2 = 0)
+ : type(type)
+ , ptr(const_cast<void*>(ptr))
+ , arg(arg)
+ , arg2(arg2)
+ , res()
+ , expect_report()
+ , report_type() {
+ }
+
+ void ExpectReport(ReportType type) {
+ expect_report = true;
+ report_type = type;
+ }
+};
+
+struct ScopedThread::Impl {
+ pthread_t thread;
+ bool main;
+ bool detached;
+ atomic_uintptr_t event; // Event*
+
+ static void *ScopedThreadCallback(void *arg);
+ void send(Event *ev);
+ void HandleEvent(Event *ev);
+};
+
+void ScopedThread::Impl::HandleEvent(Event *ev) {
+ CHECK_EQ(expect_report, false);
+ expect_report = ev->expect_report;
+ expect_report_reported = false;
+ expect_report_type = ev->report_type;
+ switch (ev->type) {
+ case Event::READ:
+ case Event::WRITE: {
+ void (*tsan_mop)(void *addr) = 0;
+ if (ev->type == Event::READ) {
+ switch (ev->arg /*size*/) {
+ case 1: tsan_mop = __tsan_read1; break;
+ case 2: tsan_mop = __tsan_read2; break;
+ case 4: tsan_mop = __tsan_read4; break;
+ case 8: tsan_mop = __tsan_read8; break;
+ case 16: tsan_mop = __tsan_read16; break;
+ }
+ } else {
+ switch (ev->arg /*size*/) {
+ case 1: tsan_mop = __tsan_write1; break;
+ case 2: tsan_mop = __tsan_write2; break;
+ case 4: tsan_mop = __tsan_write4; break;
+ case 8: tsan_mop = __tsan_write8; break;
+ case 16: tsan_mop = __tsan_write16; break;
+ }
+ }
+ CHECK_NE(tsan_mop, 0);
+ errno = ECHRNG;
+ tsan_mop(ev->ptr);
+ CHECK_EQ(errno, ECHRNG); // In no case must errno be changed.
+ break;
+ }
+ case Event::VPTR_UPDATE:
+ __tsan_vptr_update((void**)ev->ptr, (void*)ev->arg);
+ break;
+ case Event::CALL:
+ __tsan_func_entry((void*)((uptr)ev->ptr));
+ break;
+ case Event::RETURN:
+ __tsan_func_exit();
+ break;
+ case Event::MUTEX_CREATE:
+ static_cast<Mutex*>(ev->ptr)->Init();
+ break;
+ case Event::MUTEX_DESTROY:
+ static_cast<Mutex*>(ev->ptr)->Destroy();
+ break;
+ case Event::MUTEX_LOCK:
+ static_cast<Mutex*>(ev->ptr)->Lock();
+ break;
+ case Event::MUTEX_TRYLOCK:
+ ev->res = static_cast<Mutex*>(ev->ptr)->TryLock();
+ break;
+ case Event::MUTEX_UNLOCK:
+ static_cast<Mutex*>(ev->ptr)->Unlock();
+ break;
+ case Event::MUTEX_READLOCK:
+ static_cast<Mutex*>(ev->ptr)->ReadLock();
+ break;
+ case Event::MUTEX_TRYREADLOCK:
+ ev->res = static_cast<Mutex*>(ev->ptr)->TryReadLock();
+ break;
+ case Event::MUTEX_READUNLOCK:
+ static_cast<Mutex*>(ev->ptr)->ReadUnlock();
+ break;
+ case Event::MEMCPY:
+ memcpy(ev->ptr, (void*)ev->arg, ev->arg2);
+ break;
+ case Event::MEMSET:
+ memset(ev->ptr, ev->arg, ev->arg2);
+ break;
+ default: CHECK(0);
+ }
+ if (expect_report && !expect_report_reported) {
+ printf("Missed expected report of type %d\n", (int)ev->report_type);
+ EXPECT_FALSE("Missed expected race");
+ }
+ expect_report = false;
+}
+
+void *ScopedThread::Impl::ScopedThreadCallback(void *arg) {
+ __tsan_func_entry(__builtin_return_address(0));
+ Impl *impl = (Impl*)arg;
+ for (;;) {
+ Event* ev = (Event*)atomic_load(&impl->event, memory_order_acquire);
+ if (ev == 0) {
+ pthread_yield();
+ continue;
+ }
+ if (ev->type == Event::SHUTDOWN) {
+ atomic_store(&impl->event, 0, memory_order_release);
+ break;
+ }
+ impl->HandleEvent(ev);
+ atomic_store(&impl->event, 0, memory_order_release);
+ }
+ __tsan_func_exit();
+ return 0;
+}
+
+void ScopedThread::Impl::send(Event *e) {
+ if (main) {
+ HandleEvent(e);
+ } else {
+ CHECK_EQ(atomic_load(&event, memory_order_relaxed), 0);
+ atomic_store(&event, (uintptr_t)e, memory_order_release);
+ while (atomic_load(&event, memory_order_acquire) != 0)
+ pthread_yield();
+ }
+}
+
+ScopedThread::ScopedThread(bool detached, bool main) {
+ impl_ = new Impl;
+ impl_->main = main;
+ impl_->detached = detached;
+ atomic_store(&impl_->event, 0, memory_order_relaxed);
+ if (!main) {
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, detached);
+ pthread_create(&impl_->thread, &attr,
+ ScopedThread::Impl::ScopedThreadCallback, impl_);
+ }
+}
+
+ScopedThread::~ScopedThread() {
+ if (!impl_->main) {
+ Event event(Event::SHUTDOWN);
+ impl_->send(&event);
+ if (!impl_->detached)
+ pthread_join(impl_->thread, 0);
+ }
+ delete impl_;
+}
+
+void ScopedThread::Detach() {
+ CHECK(!impl_->main);
+ CHECK(!impl_->detached);
+ impl_->detached = true;
+ pthread_detach(impl_->thread);
+}
+
+void ScopedThread::Access(void *addr, bool is_write,
+ int size, bool expect_race) {
+ Event event(is_write ? Event::WRITE : Event::READ, addr, size);
+ if (expect_race)
+ event.ExpectReport(ReportTypeRace);
+ impl_->send(&event);
+}
+
+void ScopedThread::VptrUpdate(const MemLoc &vptr,
+ const MemLoc &new_val,
+ bool expect_race) {
+ Event event(Event::VPTR_UPDATE, vptr.loc(), (uptr)new_val.loc());
+ if (expect_race)
+ event.ExpectReport(ReportTypeRace);
+ impl_->send(&event);
+}
+
+void ScopedThread::Call(void(*pc)()) {
+ Event event(Event::CALL, (void*)pc);
+ impl_->send(&event);
+}
+
+void ScopedThread::Return() {
+ Event event(Event::RETURN);
+ impl_->send(&event);
+}
+
+void ScopedThread::Create(const Mutex &m) {
+ Event event(Event::MUTEX_CREATE, &m);
+ impl_->send(&event);
+}
+
+void ScopedThread::Destroy(const Mutex &m) {
+ Event event(Event::MUTEX_DESTROY, &m);
+ impl_->send(&event);
+}
+
+void ScopedThread::Lock(const Mutex &m) {
+ Event event(Event::MUTEX_LOCK, &m);
+ impl_->send(&event);
+}
+
+bool ScopedThread::TryLock(const Mutex &m) {
+ Event event(Event::MUTEX_TRYLOCK, &m);
+ impl_->send(&event);
+ return event.res;
+}
+
+void ScopedThread::Unlock(const Mutex &m) {
+ Event event(Event::MUTEX_UNLOCK, &m);
+ impl_->send(&event);
+}
+
+void ScopedThread::ReadLock(const Mutex &m) {
+ Event event(Event::MUTEX_READLOCK, &m);
+ impl_->send(&event);
+}
+
+bool ScopedThread::TryReadLock(const Mutex &m) {
+ Event event(Event::MUTEX_TRYREADLOCK, &m);
+ impl_->send(&event);
+ return event.res;
+}
+
+void ScopedThread::ReadUnlock(const Mutex &m) {
+ Event event(Event::MUTEX_READUNLOCK, &m);
+ impl_->send(&event);
+}
+
+void ScopedThread::Memcpy(void *dst, const void *src, int size,
+ bool expect_race) {
+ Event event(Event::MEMCPY, dst, (uptr)src, size);
+ if (expect_race)
+ event.ExpectReport(ReportTypeRace);
+ impl_->send(&event);
+}
+
+void ScopedThread::Memset(void *dst, int val, int size,
+ bool expect_race) {
+ Event event(Event::MEMSET, dst, val, size);
+ if (expect_race)
+ event.ExpectReport(ReportTypeRace);
+ impl_->send(&event);
+}
Added: compiler-rt/trunk/lib/tsan/rtl_tests/tsan_thread.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl_tests/tsan_thread.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl_tests/tsan_thread.cc (added)
+++ compiler-rt/trunk/lib/tsan/rtl_tests/tsan_thread.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,59 @@
+//===-- tsan_thread.cc ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_test_util.h"
+#include "gtest/gtest.h"
+
+TEST(ThreadSanitizer, ThreadSync) {
+ MainThread t0;
+ MemLoc l;
+ t0.Write1(l);
+ {
+ ScopedThread t1;
+ t1.Write1(l);
+ }
+ t0.Write1(l);
+}
+
+TEST(ThreadSanitizer, ThreadDetach1) {
+ ScopedThread t1(true);
+ MemLoc l;
+ t1.Write1(l);
+}
+
+TEST(ThreadSanitizer, ThreadDetach2) {
+ ScopedThread t1;
+ MemLoc l;
+ t1.Write1(l);
+ t1.Detach();
+}
+
+static void *thread_alot_func(void *arg) {
+ (void)arg;
+ int usleep(unsigned);
+ usleep(50);
+ return 0;
+}
+
+TEST(DISABLED_SLOW_ThreadSanitizer, ThreadALot) {
+ const int kThreads = 70000;
+ const int kAlive = 1000;
+ pthread_t threads[kAlive] = {};
+ for (int i = 0; i < kThreads; i++) {
+ if (threads[i % kAlive])
+ pthread_join(threads[i % kAlive], 0);
+ pthread_create(&threads[i % kAlive], 0, thread_alot_func, 0);
+ }
+ for (int i = 0; i < kAlive; i++) {
+ pthread_join(threads[i], 0);
+ }
+}
Added: compiler-rt/trunk/lib/tsan/unit_tests/tsan_allocator_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/unit_tests/tsan_allocator_test.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/unit_tests/tsan_allocator_test.cc (added)
+++ compiler-rt/trunk/lib/tsan/unit_tests/tsan_allocator_test.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,56 @@
+//===-- tsan_allocator_test.c------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_allocator.h"
+#include "gtest/gtest.h"
+#include <stdlib.h>
+
+namespace __tsan {
+
+TEST(Allocator, Basic) {
+ char *p = (char*)Alloc(10);
+ EXPECT_NE(p, (char*)0);
+ char *p2 = (char*)Alloc(20);
+ EXPECT_NE(p2, (char*)0);
+ EXPECT_NE(p2, p);
+ for (int i = 0; i < 10; i++) {
+ p[i] = 42;
+ EXPECT_EQ(p, AllocBlock(p + i));
+ }
+ for (int i = 0; i < 20; i++) {
+ ((char*)p2)[i] = 42;
+ EXPECT_EQ(p2, AllocBlock(p2 + i));
+ }
+ Free(p);
+ Free(p2);
+}
+
+TEST(Allocator, Stress) {
+ const int kCount = 1000;
+ char *ptrs[kCount];
+ unsigned rnd = 42;
+ for (int i = 0; i < kCount; i++) {
+ uptr sz = rand_r(&rnd) % 1000;
+ char *p = (char*)Alloc(sz);
+ EXPECT_NE(p, (char*)0);
+ for (uptr j = 0; j < sz; j++) {
+ p[j] = 42;
+ EXPECT_EQ(p, AllocBlock(p + j));
+ }
+ ptrs[i] = p;
+ }
+ for (int i = 0; i < kCount; i++) {
+ Free(ptrs[i]);
+ }
+}
+
+} // namespace __tsan
Added: compiler-rt/trunk/lib/tsan/unit_tests/tsan_clock_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/unit_tests/tsan_clock_test.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/unit_tests/tsan_clock_test.cc (added)
+++ compiler-rt/trunk/lib/tsan/unit_tests/tsan_clock_test.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,123 @@
+//===-- tsan_clock_test.cc --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_clock.h"
+#include "tsan_rtl.h"
+#include "gtest/gtest.h"
+
+namespace __tsan {
+
+TEST(Clock, VectorBasic) {
+ ScopedInRtl in_rtl;
+ ThreadClock clk;
+ CHECK_EQ(clk.size(), 0);
+ clk.tick(0);
+ CHECK_EQ(clk.size(), 1);
+ CHECK_EQ(clk.get(0), 1);
+ clk.tick(3);
+ CHECK_EQ(clk.size(), 4);
+ CHECK_EQ(clk.get(0), 1);
+ CHECK_EQ(clk.get(1), 0);
+ CHECK_EQ(clk.get(2), 0);
+ CHECK_EQ(clk.get(3), 1);
+ clk.tick(3);
+ CHECK_EQ(clk.get(3), 2);
+}
+
+TEST(Clock, ChunkedBasic) {
+ ScopedInRtl in_rtl;
+ ThreadClock vector;
+ SyncClock chunked;
+ CHECK_EQ(vector.size(), 0);
+ CHECK_EQ(chunked.size(), 0);
+ vector.acquire(&chunked);
+ CHECK_EQ(vector.size(), 0);
+ CHECK_EQ(chunked.size(), 0);
+ vector.release(&chunked);
+ CHECK_EQ(vector.size(), 0);
+ CHECK_EQ(chunked.size(), 0);
+ vector.acq_rel(&chunked);
+ CHECK_EQ(vector.size(), 0);
+ CHECK_EQ(chunked.size(), 0);
+}
+
+TEST(Clock, AcquireRelease) {
+ ScopedInRtl in_rtl;
+ ThreadClock vector1;
+ vector1.tick(100);
+ SyncClock chunked;
+ vector1.release(&chunked);
+ CHECK_EQ(chunked.size(), 101);
+ ThreadClock vector2;
+ vector2.acquire(&chunked);
+ CHECK_EQ(vector2.size(), 101);
+ CHECK_EQ(vector2.get(0), 0);
+ CHECK_EQ(vector2.get(1), 0);
+ CHECK_EQ(vector2.get(99), 0);
+ CHECK_EQ(vector2.get(100), 1);
+}
+
+TEST(Clock, ManyThreads) {
+ ScopedInRtl in_rtl;
+ SyncClock chunked;
+ for (int i = 0; i < 100; i++) {
+ ThreadClock vector;
+ vector.tick(i);
+ vector.release(&chunked);
+ CHECK_EQ(chunked.size(), i + 1);
+ vector.acquire(&chunked);
+ CHECK_EQ(vector.size(), i + 1);
+ }
+ ThreadClock vector;
+ vector.acquire(&chunked);
+ CHECK_EQ(vector.size(), 100);
+ for (int i = 0; i < 100; i++)
+ CHECK_EQ(vector.get(i), 1);
+}
+
+TEST(Clock, DifferentSizes) {
+ ScopedInRtl in_rtl;
+ {
+ ThreadClock vector1;
+ vector1.tick(10);
+ ThreadClock vector2;
+ vector2.tick(20);
+ {
+ SyncClock chunked;
+ vector1.release(&chunked);
+ CHECK_EQ(chunked.size(), 11);
+ vector2.release(&chunked);
+ CHECK_EQ(chunked.size(), 21);
+ }
+ {
+ SyncClock chunked;
+ vector2.release(&chunked);
+ CHECK_EQ(chunked.size(), 21);
+ vector1.release(&chunked);
+ CHECK_EQ(chunked.size(), 21);
+ }
+ {
+ SyncClock chunked;
+ vector1.release(&chunked);
+ vector2.acquire(&chunked);
+ CHECK_EQ(vector2.size(), 21);
+ }
+ {
+ SyncClock chunked;
+ vector2.release(&chunked);
+ vector1.acquire(&chunked);
+ CHECK_EQ(vector1.size(), 21);
+ }
+ }
+}
+
+} // namespace __tsan
Added: compiler-rt/trunk/lib/tsan/unit_tests/tsan_flags_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/unit_tests/tsan_flags_test.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/unit_tests/tsan_flags_test.cc (added)
+++ compiler-rt/trunk/lib/tsan/unit_tests/tsan_flags_test.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,107 @@
+//===-- tsan_flags_test.cc --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_flags.h"
+#include "tsan_rtl.h"
+#include "gtest/gtest.h"
+
+namespace __tsan {
+
+TEST(Flags, Basic) {
+ ScopedInRtl in_rtl;
+ // At least should not crash.
+ Flags f = {};
+ InitializeFlags(&f, 0);
+ InitializeFlags(&f, "");
+}
+
+TEST(Flags, ParseBool) {
+ ScopedInRtl in_rtl;
+ Flags f = {};
+
+ f.enable_annotations = false;
+ InitializeFlags(&f, "enable_annotations");
+ EXPECT_EQ(f.enable_annotations, true);
+
+ f.enable_annotations = false;
+ InitializeFlags(&f, "--enable_annotations");
+ EXPECT_EQ(f.enable_annotations, true);
+
+ f.enable_annotations = false;
+ InitializeFlags(&f, "--enable_annotations=1");
+ EXPECT_EQ(f.enable_annotations, true);
+
+ // This flag is false by default.
+ f.force_seq_cst_atomics = false;
+ InitializeFlags(&f, "--force_seq_cst_atomics=1");
+ EXPECT_EQ(f.force_seq_cst_atomics, true);
+
+ f.enable_annotations = true;
+ InitializeFlags(&f, "asdas enable_annotations=0 asdasd");
+ EXPECT_EQ(f.enable_annotations, false);
+
+ f.enable_annotations = true;
+ InitializeFlags(&f, " --enable_annotations=0 ");
+ EXPECT_EQ(f.enable_annotations, false);
+}
+
+TEST(Flags, ParseInt) {
+ ScopedInRtl in_rtl;
+ Flags f = {};
+
+ f.exitcode = -11;
+ InitializeFlags(&f, "exitcode");
+ EXPECT_EQ(f.exitcode, 0);
+
+ f.exitcode = -11;
+ InitializeFlags(&f, "--exitcode=");
+ EXPECT_EQ(f.exitcode, 0);
+
+ f.exitcode = -11;
+ InitializeFlags(&f, "--exitcode=42");
+ EXPECT_EQ(f.exitcode, 42);
+
+ f.exitcode = -11;
+ InitializeFlags(&f, "--exitcode=-42");
+ EXPECT_EQ(f.exitcode, -42);
+}
+
+TEST(Flags, ParseStr) {
+ ScopedInRtl in_rtl;
+ Flags f = {};
+
+ InitializeFlags(&f, 0);
+ EXPECT_EQ(0, strcmp(f.strip_path_prefix, ""));
+ FinalizeFlags(&f);
+
+ InitializeFlags(&f, "strip_path_prefix");
+ EXPECT_EQ(0, strcmp(f.strip_path_prefix, ""));
+ FinalizeFlags(&f);
+
+ InitializeFlags(&f, "--strip_path_prefix=");
+ EXPECT_EQ(0, strcmp(f.strip_path_prefix, ""));
+ FinalizeFlags(&f);
+
+ InitializeFlags(&f, "--strip_path_prefix=abc");
+ EXPECT_EQ(0, strcmp(f.strip_path_prefix, "abc"));
+ FinalizeFlags(&f);
+
+ InitializeFlags(&f, "--strip_path_prefix='abc zxc'");
+ EXPECT_EQ(0, strcmp(f.strip_path_prefix, "abc zxc"));
+ FinalizeFlags(&f);
+
+ InitializeFlags(&f, "--strip_path_prefix=\"abc zxc\"");
+ EXPECT_EQ(0, strcmp(f.strip_path_prefix, "abc zxc"));
+ FinalizeFlags(&f);
+}
+
+} // namespace __tsan
Added: compiler-rt/trunk/lib/tsan/unit_tests/tsan_mman_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/unit_tests/tsan_mman_test.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/unit_tests/tsan_mman_test.cc (added)
+++ compiler-rt/trunk/lib/tsan/unit_tests/tsan_mman_test.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,109 @@
+//===-- tsan_mman_test.cc ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_mman.h"
+#include "tsan_rtl.h"
+#include "gtest/gtest.h"
+
+namespace __tsan {
+
+TEST(Mman, Internal) {
+ ScopedInRtl in_rtl;
+ char *p = (char*)internal_alloc(MBlockScopedBuf, 10);
+ EXPECT_NE(p, (char*)0);
+ char *p2 = (char*)internal_alloc(MBlockScopedBuf, 20);
+ EXPECT_NE(p2, (char*)0);
+ EXPECT_NE(p2, p);
+ for (int i = 0; i < 10; i++) {
+ p[i] = 42;
+ }
+ for (int i = 0; i < 20; i++) {
+ ((char*)p2)[i] = 42;
+ }
+ internal_free(p);
+ internal_free(p2);
+}
+
+TEST(Mman, User) {
+ ScopedInRtl in_rtl;
+ ThreadState *thr = cur_thread();
+ uptr pc = 0;
+ char *p = (char*)user_alloc(thr, pc, 10);
+ EXPECT_NE(p, (char*)0);
+ char *p2 = (char*)user_alloc(thr, pc, 20);
+ EXPECT_NE(p2, (char*)0);
+ EXPECT_NE(p2, p);
+ MBlock *b = user_mblock(thr, p);
+ EXPECT_NE(b, (MBlock*)0);
+ EXPECT_EQ(b->size, (uptr)10);
+ MBlock *b2 = user_mblock(thr, p2);
+ EXPECT_NE(b2, (MBlock*)0);
+ EXPECT_EQ(b2->size, (uptr)20);
+ for (int i = 0; i < 10; i++) {
+ p[i] = 42;
+ EXPECT_EQ(b, user_mblock(thr, p + i));
+ }
+ for (int i = 0; i < 20; i++) {
+ ((char*)p2)[i] = 42;
+ EXPECT_EQ(b2, user_mblock(thr, p2 + i));
+ }
+ user_free(thr, pc, p);
+ user_free(thr, pc, p2);
+}
+
+TEST(Mman, UserRealloc) {
+ ScopedInRtl in_rtl;
+ ThreadState *thr = cur_thread();
+ uptr pc = 0;
+ {
+ void *p = user_realloc(thr, pc, 0, 0);
+ // Strictly saying this is incorrect, realloc(NULL, N) is equivalent to
+ // malloc(N), thus must return non-NULL pointer.
+ EXPECT_EQ(p, (void*)0);
+ }
+ {
+ void *p = user_realloc(thr, pc, 0, 100);
+ EXPECT_NE(p, (void*)0);
+ memset(p, 0xde, 100);
+ user_free(thr, pc, p);
+ }
+ {
+ void *p = user_alloc(thr, pc, 100);
+ EXPECT_NE(p, (void*)0);
+ memset(p, 0xde, 100);
+ void *p2 = user_realloc(thr, pc, p, 0);
+ EXPECT_EQ(p2, (void*)0);
+ }
+ {
+ void *p = user_realloc(thr, pc, 0, 100);
+ EXPECT_NE(p, (void*)0);
+ memset(p, 0xde, 100);
+ void *p2 = user_realloc(thr, pc, p, 10000);
+ EXPECT_NE(p2, (void*)0);
+ for (int i = 0; i < 100; i++)
+ EXPECT_EQ(((char*)p2)[i], (char)0xde);
+ memset(p2, 0xde, 10000);
+ user_free(thr, pc, p2);
+ }
+ {
+ void *p = user_realloc(thr, pc, 0, 10000);
+ EXPECT_NE(p, (void*)0);
+ memset(p, 0xde, 10000);
+ void *p2 = user_realloc(thr, pc, p, 10);
+ EXPECT_NE(p2, (void*)0);
+ for (int i = 0; i < 10; i++)
+ EXPECT_EQ(((char*)p2)[i], (char)0xde);
+ user_free(thr, pc, p2);
+ }
+}
+
+} // namespace __tsan
Added: compiler-rt/trunk/lib/tsan/unit_tests/tsan_mutex_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/unit_tests/tsan_mutex_test.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/unit_tests/tsan_mutex_test.cc (added)
+++ compiler-rt/trunk/lib/tsan/unit_tests/tsan_mutex_test.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,101 @@
+//===-- tsan_mutex_test.cc --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_atomic.h"
+#include "tsan_mutex.h"
+#include "gtest/gtest.h"
+
+namespace __tsan {
+
+class TestData {
+ public:
+ TestData()
+ : mtx_(MutexTypeAnnotations, StatMtxAnnotations) {
+ for (int i = 0; i < kSize; i++)
+ data_[i] = 0;
+ }
+
+ void Write() {
+ Lock l(&mtx_);
+ T v0 = data_[0];
+ for (int i = 0; i < kSize; i++) {
+ CHECK_EQ(data_[i], v0);
+ data_[i]++;
+ }
+ }
+
+ void Read() {
+ ReadLock l(&mtx_);
+ T v0 = data_[0];
+ for (int i = 0; i < kSize; i++) {
+ CHECK_EQ(data_[i], v0);
+ }
+ }
+
+ private:
+ static const int kSize = 64;
+ typedef u64 T;
+ Mutex mtx_;
+ char pad_[kCacheLineSize];
+ T data_[kSize];
+};
+
+const int kThreads = 8;
+const int kWriteRate = 1024;
+#if TSAN_DEBUG
+const int kIters = 16*1024;
+#else
+const int kIters = 64*1024;
+#endif
+
+static void *write_mutex_thread(void *param) {
+ TestData *data = (TestData *)param;
+ TestData local;
+ for (int i = 0; i < kIters; i++) {
+ data->Write();
+ local.Write();
+ }
+ return 0;
+}
+
+static void *read_mutex_thread(void *param) {
+ TestData *data = (TestData *)param;
+ TestData local;
+ for (int i = 0; i < kIters; i++) {
+ if ((i % kWriteRate) == 0)
+ data->Write();
+ else
+ data->Read();
+ local.Write();
+ }
+ return 0;
+}
+
+TEST(Mutex, Write) {
+ TestData data;
+ pthread_t threads[kThreads];
+ for (int i = 0; i < kThreads; i++)
+ pthread_create(&threads[i], 0, write_mutex_thread, &data);
+ for (int i = 0; i < kThreads; i++)
+ pthread_join(threads[i], 0);
+}
+
+TEST(Mutex, ReadWrite) {
+ TestData data;
+ pthread_t threads[kThreads];
+ for (int i = 0; i < kThreads; i++)
+ pthread_create(&threads[i], 0, read_mutex_thread, &data);
+ for (int i = 0; i < kThreads; i++)
+ pthread_join(threads[i], 0);
+}
+
+} // namespace __tsan
Added: compiler-rt/trunk/lib/tsan/unit_tests/tsan_platform_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/unit_tests/tsan_platform_test.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/unit_tests/tsan_platform_test.cc (added)
+++ compiler-rt/trunk/lib/tsan/unit_tests/tsan_platform_test.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,83 @@
+//===-- tsan_platform_test.cc -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_platform.h"
+#include "gtest/gtest.h"
+
+namespace __tsan {
+
+static void *TestThreadInfo(void *arg) {
+ ScopedInRtl in_rtl;
+ uptr stk_addr = 0;
+ uptr stk_size = 0;
+ uptr tls_addr = 0;
+ uptr tls_size = 0;
+ GetThreadStackAndTls(&stk_addr, &stk_size, &tls_addr, &tls_size);
+ // Printf("stk=%lx-%lx(%lu)\n", stk_addr, stk_addr + stk_size, stk_size);
+ // Printf("tls=%lx-%lx(%lu)\n", tls_addr, tls_addr + tls_size, tls_size);
+
+ int stack_var;
+ EXPECT_NE(stk_addr, (uptr)0);
+ EXPECT_NE(stk_size, (uptr)0);
+ EXPECT_GT((uptr)&stack_var, stk_addr);
+ EXPECT_LT((uptr)&stack_var, stk_addr + stk_size);
+
+ static __thread int thread_var;
+ EXPECT_NE(tls_addr, (uptr)0);
+ EXPECT_NE(tls_size, (uptr)0);
+ EXPECT_GT((uptr)&thread_var, tls_addr);
+ EXPECT_LT((uptr)&thread_var, tls_addr + tls_size);
+
+ // Ensure that tls and stack do not intersect.
+ uptr tls_end = tls_addr + tls_size;
+ EXPECT_TRUE(tls_addr < stk_addr || tls_addr >= stk_addr + stk_size);
+ EXPECT_TRUE(tls_end < stk_addr || tls_end >= stk_addr + stk_size);
+ EXPECT_TRUE((tls_addr < stk_addr) == (tls_end < stk_addr));
+ return 0;
+}
+
+TEST(Platform, ThreadInfoMain) {
+ TestThreadInfo(0);
+}
+
+TEST(Platform, ThreadInfoWorker) {
+ pthread_t t;
+ pthread_create(&t, 0, TestThreadInfo, 0);
+ pthread_join(t, 0);
+}
+
+TEST(Platform, FileOps) {
+ const char *str1 = "qwerty";
+ uptr len1 = internal_strlen(str1);
+ const char *str2 = "zxcv";
+ uptr len2 = internal_strlen(str2);
+
+ fd_t fd = internal_open("./tsan_test.tmp", true);
+ EXPECT_NE(fd, kInvalidFd);
+ EXPECT_EQ(len1, internal_write(fd, str1, len1));
+ EXPECT_EQ(len2, internal_write(fd, str2, len2));
+ internal_close(fd);
+
+ fd = internal_open("./tsan_test.tmp", false);
+ EXPECT_NE(fd, kInvalidFd);
+ EXPECT_EQ(len1 + len2, internal_filesize(fd));
+ char buf[64] = {};
+ EXPECT_EQ(len1, internal_read(fd, buf, len1));
+ EXPECT_EQ(0, internal_memcmp(buf, str1, len1));
+ EXPECT_EQ((char)0, buf[len1 + 1]);
+ internal_memset(buf, 0, len1);
+ EXPECT_EQ(len2, internal_read(fd, buf, len2));
+ EXPECT_EQ(0, internal_memcmp(buf, str2, len2));
+ internal_close(fd);
+}
+
+} // namespace __tsan
Added: compiler-rt/trunk/lib/tsan/unit_tests/tsan_printf_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/unit_tests/tsan_printf_test.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/unit_tests/tsan_printf_test.cc (added)
+++ compiler-rt/trunk/lib/tsan/unit_tests/tsan_printf_test.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,109 @@
+//===-- tsan_printf_test.cc -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_rtl.h"
+#include "gtest/gtest.h"
+
+#include <string.h>
+#include <limits.h>
+
+namespace __tsan {
+
+TEST(Printf, Basic) {
+ char buf[1024];
+ uptr len = Snprintf(buf, sizeof(buf),
+ "a%db%ldc%lldd%ue%luf%llug%xh%lxq%llxw%pe%sr",
+ (int)-1, (long)-2, (long long)-3, // NOLINT
+ (unsigned)-4, (unsigned long)5, (unsigned long long)6, // NOLINT
+ (unsigned)10, (unsigned long)11, (unsigned long long)12, // NOLINT
+ (void*)0x123, "_string_");
+ EXPECT_EQ(len, strlen(buf));
+ EXPECT_EQ(0, strcmp(buf, "a-1b-2c-3d4294967292e5f6gahbqcw"
+ "0x000000000123e_string_r"));
+}
+
+TEST(Printf, OverflowStr) {
+ char buf[] = "123456789";
+ uptr len = Snprintf(buf, 4, "%s", "abcdef");
+ EXPECT_EQ(len, (uptr)6);
+ EXPECT_EQ(0, strcmp(buf, "abc"));
+ EXPECT_EQ(buf[3], 0);
+ EXPECT_EQ(buf[4], '5');
+ EXPECT_EQ(buf[5], '6');
+ EXPECT_EQ(buf[6], '7');
+ EXPECT_EQ(buf[7], '8');
+ EXPECT_EQ(buf[8], '9');
+ EXPECT_EQ(buf[9], 0);
+}
+
+TEST(Printf, OverflowInt) {
+ char buf[] = "123456789";
+ Snprintf(buf, 4, "%d", -123456789);
+ EXPECT_EQ(0, strcmp(buf, "-12"));
+ EXPECT_EQ(buf[3], 0);
+ EXPECT_EQ(buf[4], '5');
+ EXPECT_EQ(buf[5], '6');
+ EXPECT_EQ(buf[6], '7');
+ EXPECT_EQ(buf[7], '8');
+ EXPECT_EQ(buf[8], '9');
+ EXPECT_EQ(buf[9], 0);
+}
+
+TEST(Printf, OverflowUint) {
+ char buf[] = "123456789";
+ Snprintf(buf, 4, "a%llx", (long long)0x123456789); // NOLINT
+ EXPECT_EQ(0, strcmp(buf, "a12"));
+ EXPECT_EQ(buf[3], 0);
+ EXPECT_EQ(buf[4], '5');
+ EXPECT_EQ(buf[5], '6');
+ EXPECT_EQ(buf[6], '7');
+ EXPECT_EQ(buf[7], '8');
+ EXPECT_EQ(buf[8], '9');
+ EXPECT_EQ(buf[9], 0);
+}
+
+TEST(Printf, OverflowPtr) {
+ char buf[] = "123456789";
+ Snprintf(buf, 4, "%p", (void*)0x123456789);
+ EXPECT_EQ(0, strcmp(buf, "0x0"));
+ EXPECT_EQ(buf[3], 0);
+ EXPECT_EQ(buf[4], '5');
+ EXPECT_EQ(buf[5], '6');
+ EXPECT_EQ(buf[6], '7');
+ EXPECT_EQ(buf[7], '8');
+ EXPECT_EQ(buf[8], '9');
+ EXPECT_EQ(buf[9], 0);
+}
+
+template<typename T>
+static void TestMinMax(const char *fmt, T min, T max) {
+ char buf[1024];
+ uptr len = Snprintf(buf, sizeof(buf), fmt, min, max);
+ char buf2[1024];
+ snprintf(buf2, sizeof(buf2), fmt, min, max);
+ EXPECT_EQ(len, strlen(buf));
+ EXPECT_EQ(0, strcmp(buf, buf2));
+}
+
+TEST(Printf, MinMax) {
+ TestMinMax<int>("%d-%d", INT_MIN, INT_MAX); // NOLINT
+ TestMinMax<long>("%ld-%ld", LONG_MIN, LONG_MAX); // NOLINT
+ TestMinMax<long long>("%lld-%lld", LLONG_MIN, LLONG_MAX); // NOLINT
+ TestMinMax<unsigned>("%u-%u", 0, UINT_MAX); // NOLINT
+ TestMinMax<unsigned long>("%lu-%lu", 0, ULONG_MAX); // NOLINT
+ TestMinMax<unsigned long long>("%llu-%llu", 0, ULLONG_MAX); // NOLINT
+ TestMinMax<unsigned>("%x-%x", 0, UINT_MAX); // NOLINT
+ TestMinMax<unsigned long>("%lx-%lx", 0, ULONG_MAX); // NOLINT
+ TestMinMax<unsigned long long>("%llx-%llx", 0, ULLONG_MAX); // NOLINT
+}
+
+} // namespace __tsan
Added: compiler-rt/trunk/lib/tsan/unit_tests/tsan_shadow_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/unit_tests/tsan_shadow_test.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/unit_tests/tsan_shadow_test.cc (added)
+++ compiler-rt/trunk/lib/tsan/unit_tests/tsan_shadow_test.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,47 @@
+//===-- tsan_shadow_test.cc -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_platform.h"
+#include "gtest/gtest.h"
+
+namespace __tsan {
+
+TEST(Shadow, Mapping) {
+ static int global;
+ int stack;
+ void *heap = malloc(0);
+ free(heap);
+
+ CHECK(IsAppMem((uptr)&global));
+ CHECK(IsAppMem((uptr)&stack));
+ CHECK(IsAppMem((uptr)heap));
+
+ CHECK(IsShadowMem(MemToShadow((uptr)&global)));
+ CHECK(IsShadowMem(MemToShadow((uptr)&stack)));
+ CHECK(IsShadowMem(MemToShadow((uptr)heap)));
+}
+
+TEST(Shadow, Celling) {
+ u64 aligned_data[4];
+ char *data = (char*)aligned_data;
+ CHECK_EQ((uptr)data % kShadowSize, 0);
+ uptr s0 = MemToShadow((uptr)&data[0]);
+ CHECK_EQ(s0 % kShadowSize, 0);
+ for (unsigned i = 1; i < kShadowCell; i++)
+ CHECK_EQ(s0, MemToShadow((uptr)&data[i]));
+ for (unsigned i = kShadowCell; i < 2*kShadowCell; i++)
+ CHECK_EQ(s0 + kShadowSize*kShadowCnt, MemToShadow((uptr)&data[i]));
+ for (unsigned i = 2*kShadowCell; i < 3*kShadowCell; i++)
+ CHECK_EQ(s0 + 2*kShadowSize*kShadowCnt, MemToShadow((uptr)&data[i]));
+}
+
+} // namespace __tsan
Added: compiler-rt/trunk/lib/tsan/unit_tests/tsan_suppressions_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/unit_tests/tsan_suppressions_test.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/unit_tests/tsan_suppressions_test.cc (added)
+++ compiler-rt/trunk/lib/tsan/unit_tests/tsan_suppressions_test.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,132 @@
+//===-- tsan_suppressions_test.cc -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_suppressions.h"
+#include "tsan_rtl.h"
+#include "gtest/gtest.h"
+
+#include <string.h>
+
+namespace __tsan {
+
+TEST(Suppressions, Parse) {
+ ScopedInRtl in_rtl;
+ Suppression *supp0 = SuppressionParse(
+ "race:foo\n"
+ " race:bar\n" // NOLINT
+ "race:baz \n" // NOLINT
+ "# a comment\n"
+ "race:quz\n"
+ ); // NOLINT
+ Suppression *supp = supp0;
+ EXPECT_EQ(supp->type, SuppressionRace);
+ EXPECT_EQ(0, strcmp(supp->func, "quz"));
+ supp = supp->next;
+ EXPECT_EQ(supp->type, SuppressionRace);
+ EXPECT_EQ(0, strcmp(supp->func, "baz"));
+ supp = supp->next;
+ EXPECT_EQ(supp->type, SuppressionRace);
+ EXPECT_EQ(0, strcmp(supp->func, "bar"));
+ supp = supp->next;
+ EXPECT_EQ(supp->type, SuppressionRace);
+ EXPECT_EQ(0, strcmp(supp->func, "foo"));
+ supp = supp->next;
+ EXPECT_EQ((Suppression*)0, supp);
+ SuppressionFree(supp0);
+}
+
+TEST(Suppressions, Parse2) {
+ ScopedInRtl in_rtl;
+ Suppression *supp0 = SuppressionParse(
+ " # first line comment\n" // NOLINT
+ " race:bar \n" // NOLINT
+ "race:baz* *baz\n"
+ "# a comment\n"
+ "# last line comment\n"
+ ); // NOLINT
+ Suppression *supp = supp0;
+ EXPECT_EQ(supp->type, SuppressionRace);
+ EXPECT_EQ(0, strcmp(supp->func, "baz* *baz"));
+ supp = supp->next;
+ EXPECT_EQ(supp->type, SuppressionRace);
+ EXPECT_EQ(0, strcmp(supp->func, "bar"));
+ supp = supp->next;
+ EXPECT_EQ((Suppression*)0, supp);
+ SuppressionFree(supp0);
+}
+
+TEST(Suppressions, Parse3) {
+ ScopedInRtl in_rtl;
+ Suppression *supp0 = SuppressionParse(
+ "# last suppression w/o line-feed\n"
+ "race:foo\n"
+ "race:bar"
+ ); // NOLINT
+ Suppression *supp = supp0;
+ EXPECT_EQ(supp->type, SuppressionRace);
+ EXPECT_EQ(0, strcmp(supp->func, "bar"));
+ supp = supp->next;
+ EXPECT_EQ(supp->type, SuppressionRace);
+ EXPECT_EQ(0, strcmp(supp->func, "foo"));
+ supp = supp->next;
+ EXPECT_EQ((Suppression*)0, supp);
+ SuppressionFree(supp0);
+}
+
+TEST(Suppressions, ParseType) {
+ ScopedInRtl in_rtl;
+ Suppression *supp0 = SuppressionParse(
+ "race:foo\n"
+ "thread:bar\n"
+ "mutex:baz\n"
+ "signal:quz\n"
+ ); // NOLINT
+ Suppression *supp = supp0;
+ EXPECT_EQ(supp->type, SuppressionSignal);
+ EXPECT_EQ(0, strcmp(supp->func, "quz"));
+ supp = supp->next;
+ EXPECT_EQ(supp->type, SuppressionMutex);
+ EXPECT_EQ(0, strcmp(supp->func, "baz"));
+ supp = supp->next;
+ EXPECT_EQ(supp->type, SuppressionThread);
+ EXPECT_EQ(0, strcmp(supp->func, "bar"));
+ supp = supp->next;
+ EXPECT_EQ(supp->type, SuppressionRace);
+ EXPECT_EQ(0, strcmp(supp->func, "foo"));
+ supp = supp->next;
+ EXPECT_EQ((Suppression*)0, supp);
+ SuppressionFree(supp0);
+}
+
+static bool MyMatch(const char *templ, const char *func) {
+ char tmp[1024];
+ strcpy(tmp, templ); // NOLINT
+ return SuppressionMatch(tmp, func);
+}
+
+TEST(Suppressions, Match) {
+ EXPECT_TRUE(MyMatch("foobar", "foobar"));
+ EXPECT_TRUE(MyMatch("foobar", "prefix_foobar_postfix"));
+ EXPECT_TRUE(MyMatch("*foobar*", "prefix_foobar_postfix"));
+ EXPECT_TRUE(MyMatch("foo*bar", "foo_middle_bar"));
+ EXPECT_TRUE(MyMatch("foo*bar", "foobar"));
+ EXPECT_TRUE(MyMatch("foo*bar*baz", "foo_middle_bar_another_baz"));
+ EXPECT_TRUE(MyMatch("foo*bar*baz", "foo_middle_barbaz"));
+
+ EXPECT_FALSE(MyMatch("foo", "baz"));
+ EXPECT_FALSE(MyMatch("foobarbaz", "foobar"));
+ EXPECT_FALSE(MyMatch("foobarbaz", "barbaz"));
+ EXPECT_FALSE(MyMatch("foo*bar", "foobaz"));
+ EXPECT_FALSE(MyMatch("foo*bar", "foo_baz"));
+}
+
+} // namespace __tsan
Added: compiler-rt/trunk/lib/tsan/unit_tests/tsan_sync_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/unit_tests/tsan_sync_test.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/unit_tests/tsan_sync_test.cc (added)
+++ compiler-rt/trunk/lib/tsan/unit_tests/tsan_sync_test.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,65 @@
+//===-- tsan_sync_test.cc ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_sync.h"
+#include "tsan_rtl.h"
+#include "tsan_mman.h"
+#include "gtest/gtest.h"
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <map>
+
+namespace __tsan {
+
+TEST(Sync, Table) {
+ const uintptr_t kIters = 512*1024;
+ const uintptr_t kRange = 10000;
+
+ ScopedInRtl in_rtl;
+ ThreadState *thr = cur_thread();
+ uptr pc = 0;
+
+ SyncTab tab;
+ SyncVar *golden[kRange] = {};
+ unsigned seed = 0;
+ for (uintptr_t i = 0; i < kIters; i++) {
+ uintptr_t addr = rand_r(&seed) % (kRange - 1) + 1;
+ if (rand_r(&seed) % 2) {
+ // Get or add.
+ SyncVar *v = tab.GetAndLock(thr, pc, addr, true);
+ EXPECT_TRUE(golden[addr] == 0 || golden[addr] == v);
+ EXPECT_EQ(v->addr, addr);
+ golden[addr] = v;
+ v->mtx.Unlock();
+ } else {
+ // Remove.
+ SyncVar *v = tab.GetAndRemove(thr, pc, addr);
+ EXPECT_EQ(golden[addr], v);
+ if (v) {
+ EXPECT_EQ(v->addr, addr);
+ golden[addr] = 0;
+ DestroyAndFree(v);
+ }
+ }
+ }
+ for (uintptr_t addr = 0; addr < kRange; addr++) {
+ if (golden[addr] == 0)
+ continue;
+ SyncVar *v = tab.GetAndRemove(thr, pc, addr);
+ EXPECT_EQ(v, golden[addr]);
+ EXPECT_EQ(v->addr, addr);
+ DestroyAndFree(v);
+ }
+}
+
+} // namespace __tsan
Added: compiler-rt/trunk/lib/tsan/unit_tests/tsan_vector_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/unit_tests/tsan_vector_test.cc?rev=156545&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/unit_tests/tsan_vector_test.cc (added)
+++ compiler-rt/trunk/lib/tsan/unit_tests/tsan_vector_test.cc Thu May 10 09:18:22 2012
@@ -0,0 +1,45 @@
+//===-- tsan_vector_test.cc -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_vector.h"
+#include "tsan_rtl.h"
+#include "gtest/gtest.h"
+
+namespace __tsan {
+
+TEST(Vector, Basic) {
+ ScopedInRtl in_rtl;
+ Vector<int> v(MBlockScopedBuf);
+ EXPECT_EQ(v.Size(), (uptr)0);
+ v.PushBack(42);
+ EXPECT_EQ(v.Size(), (uptr)1);
+ EXPECT_EQ(v[0], 42);
+ v.PushBack(43);
+ EXPECT_EQ(v.Size(), (uptr)2);
+ EXPECT_EQ(v[0], 42);
+ EXPECT_EQ(v[1], 43);
+}
+
+TEST(Vector, Stride) {
+ ScopedInRtl in_rtl;
+ Vector<int> v(MBlockScopedBuf);
+ for (int i = 0; i < 1000; i++) {
+ v.PushBack(i);
+ EXPECT_EQ(v.Size(), (uptr)(i + 1));
+ EXPECT_EQ(v[i], i);
+ }
+ for (int i = 0; i < 1000; i++) {
+ EXPECT_EQ(v[i], i);
+ }
+}
+
+} // namespace __tsan
More information about the llvm-commits
mailing list