[llvm-commits] [compiler-rt] r169493 - in /compiler-rt/trunk/lib/tsan: lit_tests/ rtl/ tests/unit/
Dmitry Vyukov
dvyukov at google.com
Thu Dec 6 04:16:16 PST 2012
Author: dvyukov
Date: Thu Dec 6 06:16:15 2012
New Revision: 169493
URL: http://llvm.org/viewvc/llvm-project?rev=169493&view=rev
Log:
tsan: add mutexsets to reports
With this change reports say what mutexes the threads hold around the racy memory accesses.
Added:
compiler-rt/trunk/lib/tsan/lit_tests/ignore_race.cc
compiler-rt/trunk/lib/tsan/lit_tests/mutexset1.cc
compiler-rt/trunk/lib/tsan/lit_tests/mutexset2.cc
compiler-rt/trunk/lib/tsan/lit_tests/mutexset3.cc
compiler-rt/trunk/lib/tsan/lit_tests/mutexset4.cc
compiler-rt/trunk/lib/tsan/lit_tests/mutexset5.cc
compiler-rt/trunk/lib/tsan/lit_tests/mutexset6.cc
compiler-rt/trunk/lib/tsan/lit_tests/mutexset7.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_mutexset.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_mutexset.h
compiler-rt/trunk/lib/tsan/tests/unit/tsan_mutexset_test.cc
Modified:
compiler-rt/trunk/lib/tsan/lit_tests/free_race.c
compiler-rt/trunk/lib/tsan/lit_tests/memcpy_race.cc
compiler-rt/trunk/lib/tsan/lit_tests/mop_with_offset.cc
compiler-rt/trunk/lib/tsan/lit_tests/mop_with_offset2.cc
compiler-rt/trunk/lib/tsan/lit_tests/race_on_heap.cc
compiler-rt/trunk/lib/tsan/lit_tests/race_on_mutex.c
compiler-rt/trunk/lib/tsan/lit_tests/race_with_finished_thread.cc
compiler-rt/trunk/lib/tsan/lit_tests/simple_stack.c
compiler-rt/trunk/lib/tsan/lit_tests/simple_stack2.cc
compiler-rt/trunk/lib/tsan/lit_tests/thread_name.cc
compiler-rt/trunk/lib/tsan/lit_tests/write_in_reader_lock.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_defs.h
compiler-rt/trunk/lib/tsan/rtl/tsan_interface_atomic.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_mman.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.h
compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_report.h
compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h
compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h
compiler-rt/trunk/lib/tsan/rtl/tsan_sync.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_sync.h
compiler-rt/trunk/lib/tsan/rtl/tsan_trace.h
compiler-rt/trunk/lib/tsan/tests/unit/tsan_sync_test.cc
Modified: compiler-rt/trunk/lib/tsan/lit_tests/free_race.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/free_race.c?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/free_race.c (original)
+++ compiler-rt/trunk/lib/tsan/lit_tests/free_race.c Thu Dec 6 06:16:15 2012
@@ -35,9 +35,9 @@
}
// CHECK: WARNING: ThreadSanitizer: heap-use-after-free
-// CHECK: Write of size 4 at {{.*}} by main thread:
+// CHECK: Write of size 4 at {{.*}} by main thread{{.*}}:
// CHECK: #0 Thread2
// CHECK: #1 main
-// CHECK: Previous write of size 8 at {{.*}} by thread 1:
+// CHECK: Previous write of size 8 at {{.*}} by thread T1{{.*}}:
// CHECK: #0 free
// CHECK: #1 Thread1
Added: compiler-rt/trunk/lib/tsan/lit_tests/ignore_race.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/ignore_race.cc?rev=169493&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/ignore_race.cc (added)
+++ compiler-rt/trunk/lib/tsan/lit_tests/ignore_race.cc Thu Dec 6 06:16:15 2012
@@ -0,0 +1,31 @@
+// RUN: %clang_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int Global;
+
+extern "C" void AnnotateIgnoreWritesBegin(const char *f, int l);
+extern "C" void AnnotateIgnoreWritesEnd(const char *f, int l);
+extern "C" void AnnotateIgnoreReadsBegin(const char *f, int l);
+extern "C" void AnnotateIgnoreReadsEnd(const char *f, int l);
+
+void *Thread(void *x) {
+ AnnotateIgnoreWritesBegin(__FILE__, __LINE__);
+ AnnotateIgnoreReadsBegin(__FILE__, __LINE__);
+ Global = 42;
+ AnnotateIgnoreReadsEnd(__FILE__, __LINE__);
+ AnnotateIgnoreWritesEnd(__FILE__, __LINE__);
+ return 0;
+}
+
+int main() {
+ pthread_t t;
+ pthread_create(&t, 0, Thread, 0);
+ usleep(100000);
+ Global = 43;
+ pthread_join(t, 0);
+ return 0;
+}
+
+// CHECK-NOT: ThreadSanitizer
Modified: compiler-rt/trunk/lib/tsan/lit_tests/memcpy_race.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/memcpy_race.cc?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/memcpy_race.cc (original)
+++ compiler-rt/trunk/lib/tsan/lit_tests/memcpy_race.cc Thu Dec 6 06:16:15 2012
@@ -32,9 +32,9 @@
// CHECK: addr=[[ADDR:0x[0-9,a-f]+]]
// CHECK: WARNING: ThreadSanitizer: data race
-// CHECK: Write of size 1 at [[ADDR]] by thread 2:
+// CHECK: Write of size 1 at [[ADDR]] by thread T2:
// CHECK: #0 memcpy
// CHECK: #1 Thread2
-// CHECK: Previous write of size 1 at [[ADDR]] by thread 1:
+// CHECK: Previous write of size 1 at [[ADDR]] by thread T1:
// CHECK: #0 memcpy
// CHECK: #1 Thread1
Modified: compiler-rt/trunk/lib/tsan/lit_tests/mop_with_offset.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/mop_with_offset.cc?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/mop_with_offset.cc (original)
+++ compiler-rt/trunk/lib/tsan/lit_tests/mop_with_offset.cc Thu Dec 6 06:16:15 2012
@@ -32,5 +32,5 @@
// 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:
+// CHECK: Write of size 1 at [[PTR2]] by thread T2:
+// CHECK: Previous write of size 4 at [[PTR1]] by thread T1:
Modified: compiler-rt/trunk/lib/tsan/lit_tests/mop_with_offset2.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/mop_with_offset2.cc?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/mop_with_offset2.cc (original)
+++ compiler-rt/trunk/lib/tsan/lit_tests/mop_with_offset2.cc Thu Dec 6 06:16:15 2012
@@ -32,5 +32,5 @@
// 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:
+// CHECK: Write of size 4 at [[PTR1]] by thread T1:
+// CHECK: Previous write of size 1 at [[PTR2]] by thread T2:
Added: compiler-rt/trunk/lib/tsan/lit_tests/mutexset1.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/mutexset1.cc?rev=169493&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/mutexset1.cc (added)
+++ compiler-rt/trunk/lib/tsan/lit_tests/mutexset1.cc Thu Dec 6 06:16:15 2012
@@ -0,0 +1,38 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int Global;
+pthread_mutex_t mtx;
+
+void *Thread1(void *x) {
+ usleep(100*1000);
+ pthread_mutex_lock(&mtx);
+ Global++;
+ pthread_mutex_unlock(&mtx);
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ Global--;
+ return NULL;
+}
+
+int main() {
+ pthread_mutex_init(&mtx, 0);
+ 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);
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: Write of size 4 at {{.*}} by thread T1 (mutexes: write M1):
+// CHECK: Previous write of size 4 at {{.*}} by thread T2:
+// CHECK: Mutex M1 created at:
+// CHECK: #0 pthread_mutex_init
+// CHECK: #1 main {{.*}}/mutexset1.cc:23
+
Added: compiler-rt/trunk/lib/tsan/lit_tests/mutexset2.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/mutexset2.cc?rev=169493&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/mutexset2.cc (added)
+++ compiler-rt/trunk/lib/tsan/lit_tests/mutexset2.cc Thu Dec 6 06:16:15 2012
@@ -0,0 +1,38 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int Global;
+pthread_mutex_t mtx;
+
+void *Thread1(void *x) {
+ pthread_mutex_lock(&mtx);
+ Global++;
+ pthread_mutex_unlock(&mtx);
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ usleep(100*1000);
+ Global--;
+ return NULL;
+}
+
+int main() {
+ pthread_mutex_init(&mtx, 0);
+ 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);
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: Write of size 4 at {{.*}} by thread T2:
+// CHECK: Previous write of size 4 at {{.*}} by thread T1 (mutexes: write M1):
+// CHECK: Mutex M1 created at:
+// CHECK: #0 pthread_mutex_init
+// CHECK: #1 main {{.*}}/mutexset2.cc:23
+
Added: compiler-rt/trunk/lib/tsan/lit_tests/mutexset3.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/mutexset3.cc?rev=169493&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/mutexset3.cc (added)
+++ compiler-rt/trunk/lib/tsan/lit_tests/mutexset3.cc Thu Dec 6 06:16:15 2012
@@ -0,0 +1,46 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int Global;
+pthread_mutex_t mtx1;
+pthread_mutex_t mtx2;
+
+void *Thread1(void *x) {
+ usleep(100*1000);
+ pthread_mutex_lock(&mtx1);
+ pthread_mutex_lock(&mtx2);
+ Global++;
+ pthread_mutex_unlock(&mtx2);
+ pthread_mutex_unlock(&mtx1);
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ Global--;
+ return NULL;
+}
+
+int main() {
+ pthread_mutex_init(&mtx1, 0);
+ pthread_mutex_init(&mtx2, 0);
+ 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(&mtx1);
+ pthread_mutex_destroy(&mtx2);
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: Write of size 4 at {{.*}} by thread T1 (mutexes: write M1, write M2):
+// CHECK: Previous write of size 4 at {{.*}} by thread T2:
+// CHECK: Mutex M1 created at:
+// CHECK: #0 pthread_mutex_init
+// CHECK: #1 main {{.*}}/mutexset3.cc:26
+// CHECK: Mutex M2 created at:
+// CHECK: #0 pthread_mutex_init
+// CHECK: #1 main {{.*}}/mutexset3.cc:27
+
Added: compiler-rt/trunk/lib/tsan/lit_tests/mutexset4.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/mutexset4.cc?rev=169493&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/mutexset4.cc (added)
+++ compiler-rt/trunk/lib/tsan/lit_tests/mutexset4.cc Thu Dec 6 06:16:15 2012
@@ -0,0 +1,47 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int Global;
+pthread_mutex_t mtx1;
+pthread_mutex_t mtx2;
+
+void *Thread1(void *x) {
+ pthread_mutex_lock(&mtx1);
+ pthread_mutex_lock(&mtx2);
+ Global++;
+ pthread_mutex_unlock(&mtx2);
+ pthread_mutex_unlock(&mtx1);
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ usleep(100*1000);
+ Global--;
+ return NULL;
+}
+
+int main() {
+ pthread_mutex_init(&mtx1, 0);
+ pthread_mutex_init(&mtx2, 0);
+ 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(&mtx1);
+ pthread_mutex_destroy(&mtx2);
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: Write of size 4 at {{.*}} by thread T2:
+// CHECK: Previous write of size 4 at {{.*}} by thread T1
+// CHECK: (mutexes: write M1, write M2):
+// CHECK: Mutex M1 created at:
+// CHECK: #0 pthread_mutex_init
+// CHECK: #1 main {{.*}}/mutexset4.cc:26
+// CHECK: Mutex M2 created at:
+// CHECK: #0 pthread_mutex_init
+// CHECK: #1 main {{.*}}/mutexset4.cc:27
+
Added: compiler-rt/trunk/lib/tsan/lit_tests/mutexset5.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/mutexset5.cc?rev=169493&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/mutexset5.cc (added)
+++ compiler-rt/trunk/lib/tsan/lit_tests/mutexset5.cc Thu Dec 6 06:16:15 2012
@@ -0,0 +1,46 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int Global;
+pthread_mutex_t mtx1;
+pthread_mutex_t mtx2;
+
+void *Thread1(void *x) {
+ usleep(100*1000);
+ pthread_mutex_lock(&mtx1);
+ Global++;
+ pthread_mutex_unlock(&mtx1);
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ pthread_mutex_lock(&mtx2);
+ Global--;
+ pthread_mutex_unlock(&mtx2);
+ return NULL;
+}
+
+int main() {
+ pthread_mutex_init(&mtx1, 0);
+ pthread_mutex_init(&mtx2, 0);
+ 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(&mtx1);
+ pthread_mutex_destroy(&mtx2);
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: Write of size 4 at {{.*}} by thread T1 (mutexes: write M1):
+// CHECK: Previous write of size 4 at {{.*}} by thread T2 (mutexes: write M2):
+// CHECK: Mutex M1 created at:
+// CHECK: #0 pthread_mutex_init
+// CHECK: #1 main {{.*}}/mutexset5.cc:26
+// CHECK: Mutex M2 created at:
+// CHECK: #0 pthread_mutex_init
+// CHECK: #1 main {{.*}}/mutexset5.cc:27
+
Added: compiler-rt/trunk/lib/tsan/lit_tests/mutexset6.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/mutexset6.cc?rev=169493&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/mutexset6.cc (added)
+++ compiler-rt/trunk/lib/tsan/lit_tests/mutexset6.cc Thu Dec 6 06:16:15 2012
@@ -0,0 +1,54 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int Global;
+pthread_mutex_t mtx1;
+pthread_spinlock_t mtx2;
+pthread_rwlock_t mtx3;
+
+void *Thread1(void *x) {
+ usleep(100*1000);
+ pthread_mutex_lock(&mtx1);
+ Global++;
+ pthread_mutex_unlock(&mtx1);
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ pthread_mutex_lock(&mtx1);
+ pthread_mutex_unlock(&mtx1);
+ pthread_spin_lock(&mtx2);
+ pthread_rwlock_rdlock(&mtx3);
+ Global--;
+ pthread_spin_unlock(&mtx2);
+ pthread_rwlock_unlock(&mtx3);
+ return NULL;
+}
+
+int main() {
+ pthread_mutex_init(&mtx1, 0);
+ pthread_spin_init(&mtx2, 0);
+ pthread_rwlock_init(&mtx3, 0);
+ 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(&mtx1);
+ pthread_spin_destroy(&mtx2);
+ pthread_rwlock_destroy(&mtx3);
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: Write of size 4 at {{.*}} by thread T1 (mutexes: write M1):
+// CHECK: Previous write of size 4 at {{.*}} by thread T2
+// CHECK: (mutexes: write M2, read M3):
+// CHECK: Mutex M1 created at:
+// CHECK: #1 main {{.*}}/mutexset6.cc:31
+// CHECK: Mutex M2 created at:
+// CHECK: #1 main {{.*}}/mutexset6.cc:32
+// CHECK: Mutex M3 created at:
+// CHECK: #1 main {{.*}}/mutexset6.cc:33
+
Added: compiler-rt/trunk/lib/tsan/lit_tests/mutexset7.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/mutexset7.cc?rev=169493&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/mutexset7.cc (added)
+++ compiler-rt/trunk/lib/tsan/lit_tests/mutexset7.cc Thu Dec 6 06:16:15 2012
@@ -0,0 +1,38 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int Global;
+
+void *Thread1(void *x) {
+ usleep(100*1000);
+ Global++;
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ pthread_mutex_t mtx;
+ pthread_mutex_init(&mtx, 0);
+ pthread_mutex_lock(&mtx);
+ Global--;
+ pthread_mutex_unlock(&mtx);
+ pthread_mutex_destroy(&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);
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: Write of size 4 at {{.*}} by thread T1:
+// CHECK: Previous write of size 4 at {{.*}} by thread T2
+// CHECK: (mutexes: write M{{[0-9]+}}):
+// CHECK: Mutex M{{[0-9]+}} is already destroyed
+// CHECK-NOT: Mutex {{.*}} created at
+
Modified: compiler-rt/trunk/lib/tsan/lit_tests/race_on_heap.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/race_on_heap.cc?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/race_on_heap.cc (original)
+++ compiler-rt/trunk/lib/tsan/lit_tests/race_on_heap.cc Thu Dec 6 06:16:15 2012
@@ -37,11 +37,11 @@
// CHECK: addr=[[ADDR:0x[0-9,a-f]+]]
// CHECK: WARNING: ThreadSanitizer: data race
// ...
-// CHECK: Location is heap block of size 99 at [[ADDR]] allocated by thread 1:
+// CHECK: Location is heap block of size 99 at [[ADDR]] allocated by thread T1:
// CHCEKL #0 malloc
// CHECK: #1 alloc
// CHECK: #2 AllocThread
// ...
-// CHECK: Thread 1 (tid={{.*}}, finished) created at:
+// CHECK: Thread T1 (tid={{.*}}, finished) created at:
// CHECK: #0 pthread_create
// CHECK: #1 main
Modified: compiler-rt/trunk/lib/tsan/lit_tests/race_on_mutex.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/race_on_mutex.c?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/race_on_mutex.c (original)
+++ compiler-rt/trunk/lib/tsan/lit_tests/race_on_mutex.c Thu Dec 6 06:16:15 2012
@@ -34,9 +34,9 @@
}
// CHECK: WARNING: ThreadSanitizer: data race
-// CHECK-NEXT: Read of size 1 at {{.*}} by thread 2:
+// CHECK-NEXT: Read of size 1 at {{.*}} by thread T2:
// CHECK-NEXT: #0 pthread_mutex_lock
// CHECK-NEXT: #1 Thread2{{.*}} {{.*}}race_on_mutex.c:20{{(:3)?}} ({{.*}})
-// CHECK: Previous write of size 1 at {{.*}} by thread 1:
+// CHECK: Previous write of size 1 at {{.*}} by thread T1:
// CHECK-NEXT: #0 pthread_mutex_init {{.*}} ({{.*}})
// CHECK-NEXT: #1 Thread1{{.*}} {{.*}}race_on_mutex.c:11{{(:3)?}} ({{.*}})
Modified: compiler-rt/trunk/lib/tsan/lit_tests/race_with_finished_thread.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/race_with_finished_thread.cc?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/race_with_finished_thread.cc (original)
+++ compiler-rt/trunk/lib/tsan/lit_tests/race_with_finished_thread.cc Thu Dec 6 06:16:15 2012
@@ -34,10 +34,10 @@
}
// 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: Write of size 4 at {{.*}} by thread T2:
+// CHECK: Previous write of size 4 at {{.*}} by thread T1:
// CHECK: #0 foobar
// CHECK: #1 Thread1
-// CHECK: Thread 1 (tid={{.*}}, finished) created at:
+// CHECK: Thread T1 (tid={{.*}}, finished) created at:
// CHECK: #0 pthread_create
// CHECK: #1 main
Modified: compiler-rt/trunk/lib/tsan/lit_tests/simple_stack.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/simple_stack.c?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/simple_stack.c (original)
+++ compiler-rt/trunk/lib/tsan/lit_tests/simple_stack.c Thu Dec 6 06:16:15 2012
@@ -48,19 +48,19 @@
}
// CHECK: WARNING: ThreadSanitizer: data race
-// CHECK-NEXT: Write of size 4 at {{.*}} by thread 1:
+// CHECK-NEXT: Write of size 4 at {{.*}} by thread T1:
// CHECK-NEXT: #0 foo1{{.*}} {{.*}}simple_stack.c:9{{(:3)?}} ({{.*}})
// CHECK-NEXT: #1 bar1{{.*}} {{.*}}simple_stack.c:14{{(:3)?}} ({{.*}})
// CHECK-NEXT: #2 Thread1{{.*}} {{.*}}simple_stack.c:28{{(:3)?}} ({{.*}})
-// CHECK: Previous read of size 4 at {{.*}} by thread 2:
+// CHECK: Previous read of size 4 at {{.*}} by thread T2:
// CHECK-NEXT: #0 foo2{{.*}} {{.*}}simple_stack.c:18{{(:26)?}} ({{.*}})
// CHECK-NEXT: #1 bar2{{.*}} {{.*}}simple_stack.c:23{{(:3)?}} ({{.*}})
// CHECK-NEXT: #2 Thread2{{.*}} {{.*}}simple_stack.c:33{{(:3)?}} ({{.*}})
-// CHECK: Thread 1 (tid={{.*}}, running) created at:
+// CHECK: Thread T1 (tid={{.*}}, running) created at:
// CHECK-NEXT: #0 pthread_create {{.*}} ({{.*}})
// CHECK-NEXT: #1 StartThread{{.*}} {{.*}}simple_stack.c:38{{(:3)?}} ({{.*}})
// CHECK-NEXT: #2 main{{.*}} {{.*}}simple_stack.c:43{{(:3)?}} ({{.*}})
-// CHECK: Thread 2 ({{.*}}) created at:
+// CHECK: Thread T2 ({{.*}}) created at:
// CHECK-NEXT: #0 pthread_create {{.*}} ({{.*}})
// CHECK-NEXT: #1 StartThread{{.*}} {{.*}}simple_stack.c:38{{(:3)?}} ({{.*}})
// CHECK-NEXT: #2 main{{.*}} {{.*}}simple_stack.c:44{{(:3)?}} ({{.*}})
Modified: compiler-rt/trunk/lib/tsan/lit_tests/simple_stack2.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/simple_stack2.cc?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/simple_stack2.cc (original)
+++ compiler-rt/trunk/lib/tsan/lit_tests/simple_stack2.cc Thu Dec 6 06:16:15 2012
@@ -43,7 +43,7 @@
}
// CHECK: WARNING: ThreadSanitizer: data race
-// CHECK-NEXT: Write of size 4 at {{.*}} by thread 1:
+// CHECK-NEXT: Write of size 4 at {{.*}} by thread T1:
// CHECK-NEXT: #0 foo1{{.*}} {{.*}}simple_stack2.cc:9{{(:3)?}} ({{.*}})
// CHECK-NEXT: #1 bar1{{.*}} {{.*}}simple_stack2.cc:16{{(:3)?}} ({{.*}})
// CHECK-NEXT: #2 Thread1{{.*}} {{.*}}simple_stack2.cc:34{{(:3)?}} ({{.*}})
Modified: compiler-rt/trunk/lib/tsan/lit_tests/thread_name.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/thread_name.cc?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/thread_name.cc (original)
+++ compiler-rt/trunk/lib/tsan/lit_tests/thread_name.cc Thu Dec 6 06:16:15 2012
@@ -29,6 +29,6 @@
}
// CHECK: WARNING: ThreadSanitizer: data race
-// CHECK: Thread 1 'Thread1'
-// CHECK: Thread 2 'Thread2'
+// CHECK: Thread T1 'Thread1'
+// CHECK: Thread T2 'Thread2'
Modified: compiler-rt/trunk/lib/tsan/lit_tests/write_in_reader_lock.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/write_in_reader_lock.cc?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/write_in_reader_lock.cc (original)
+++ compiler-rt/trunk/lib/tsan/lit_tests/write_in_reader_lock.cc Thu Dec 6 06:16:15 2012
@@ -29,7 +29,7 @@
}
// CHECK: WARNING: ThreadSanitizer: data race
-// CHECK: Write of size 4 at {{.*}} by thread 1:
+// CHECK: Write of size 4 at {{.*}} by thread T1{{.*}}:
// CHECK: #0 Thread1(void*) {{.*}}write_in_reader_lock.cc:13
-// CHECK: Previous read of size 4 at {{.*}} by main thread:
+// CHECK: Previous read of size 4 at {{.*}} by main thread{{.*}}:
// CHECK: #0 main {{.*}}write_in_reader_lock.cc:23
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_defs.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_defs.h?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_defs.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_defs.h Thu Dec 6 06:16:15 2012
@@ -139,6 +139,12 @@
return (T)((u64)p & ~(align - 1));
}
+// Zeroizes high part, returns 'bits' lsb bits.
+template<typename T>
+T GetLsb(T v, int bits) {
+ return (T)((u64)v & ((1ull << bits) - 1));
+}
+
struct MD5Hash {
u64 hash[2];
bool operator==(const MD5Hash &other) const;
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interface_atomic.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interface_atomic.cc?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interface_atomic.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interface_atomic.cc Thu Dec 6 06:16:15 2012
@@ -231,7 +231,7 @@
// Assume the access is atomic.
if (!IsAcquireOrder(mo) && sizeof(T) <= sizeof(a))
return *a;
- SyncVar *s = CTX()->synctab.GetAndLock(thr, pc, (uptr)a, false);
+ SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, (uptr)a, false);
thr->clock.set(thr->tid, thr->fast_state.epoch());
thr->clock.acquire(&s->clock);
T v = *a;
@@ -253,7 +253,7 @@
return;
}
__sync_synchronize();
- SyncVar *s = CTX()->synctab.GetAndLock(thr, pc, (uptr)a, true);
+ SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, (uptr)a, true);
thr->clock.set(thr->tid, thr->fast_state.epoch());
thr->clock.ReleaseStore(&s->clock);
*a = v;
@@ -265,7 +265,7 @@
template<typename T, T (*F)(volatile T *v, T op)>
static T AtomicRMW(ThreadState *thr, uptr pc, volatile T *a, T v, morder mo) {
- SyncVar *s = CTX()->synctab.GetAndLock(thr, pc, (uptr)a, true);
+ SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, (uptr)a, true);
thr->clock.set(thr->tid, thr->fast_state.epoch());
if (IsAcqRelOrder(mo))
thr->clock.acq_rel(&s->clock);
@@ -324,7 +324,7 @@
static bool AtomicCAS(ThreadState *thr, uptr pc,
volatile T *a, T *c, T v, morder mo, morder fmo) {
(void)fmo; // Unused because llvm does not pass it yet.
- SyncVar *s = CTX()->synctab.GetAndLock(thr, pc, (uptr)a, true);
+ SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, (uptr)a, true);
thr->clock.set(thr->tid, thr->fast_state.epoch());
if (IsAcqRelOrder(mo))
thr->clock.acq_rel(&s->clock);
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_mman.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_mman.cc?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_mman.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_mman.cc Thu Dec 6 06:16:15 2012
@@ -60,8 +60,9 @@
void *p = allocator()->Allocate(&thr->alloc_cache, sz, align);
if (p == 0)
return 0;
- MBlock *b = (MBlock*)allocator()->GetMetaData(p);
+ MBlock *b = new(allocator()->GetMetaData(p)) MBlock;
b->size = sz;
+ b->head = 0;
b->alloc_tid = thr->unique_id;
b->alloc_stack_id = CurrentStackId(thr, pc);
if (CTX() && CTX()->initialized) {
@@ -92,6 +93,7 @@
if (CTX() && CTX()->initialized && thr->in_rtl == 1) {
MemoryRangeFreed(thr, pc, (uptr)p, b->size);
}
+ b->~MBlock();
allocator()->Deallocate(&thr->alloc_cache, p);
SignalUnsafeCall(thr, pc);
}
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.cc?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.cc Thu Dec 6 06:16:15 2012
@@ -30,12 +30,13 @@
/*0 MutexTypeInvalid*/ {},
/*1 MutexTypeTrace*/ {MutexTypeLeaf},
/*2 MutexTypeThreads*/ {MutexTypeReport},
- /*3 MutexTypeReport*/ {},
+ /*3 MutexTypeReport*/ {MutexTypeSyncTab, MutexTypeMBlock},
/*4 MutexTypeSyncVar*/ {},
/*5 MutexTypeSyncTab*/ {MutexTypeSyncVar},
/*6 MutexTypeSlab*/ {MutexTypeLeaf},
/*7 MutexTypeAnnotations*/ {},
/*8 MutexTypeAtExit*/ {MutexTypeSyncTab},
+ /*9 MutexTypeMBlock*/ {MutexTypeSyncVar},
};
static bool CanLockAdj[MutexTypeCount][MutexTypeCount];
@@ -122,6 +123,8 @@
void DeadlockDetector::Lock(MutexType t) {
// Printf("LOCK %d @%zu\n", t, seq_ + 1);
+ CHECK_GT(t, MutexTypeInvalid);
+ CHECK_LT(t, MutexTypeCount);
u64 max_seq = 0;
u64 max_idx = MutexTypeInvalid;
for (int i = 0; i != MutexTypeCount; i++) {
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.h?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.h Thu Dec 6 06:16:15 2012
@@ -29,6 +29,7 @@
MutexTypeSlab,
MutexTypeAnnotations,
MutexTypeAtExit,
+ MutexTypeMBlock,
// This must be the last.
MutexTypeCount
Added: compiler-rt/trunk/lib/tsan/rtl/tsan_mutexset.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_mutexset.cc?rev=169493&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_mutexset.cc (added)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_mutexset.cc Thu Dec 6 06:16:15 2012
@@ -0,0 +1,89 @@
+//===-- tsan_mutexset.cc --------------------------------------------------===//
+//
+// 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_mutexset.h"
+#include "tsan_rtl.h"
+
+namespace __tsan {
+
+const uptr MutexSet::kMaxSize;
+
+MutexSet::MutexSet() {
+ size_ = 0;
+ internal_memset(&descs_, 0, sizeof(descs_));
+}
+
+void MutexSet::Add(u64 id, bool write, u64 epoch) {
+ // Look up existing mutex with the same id.
+ for (uptr i = 0; i < size_; i++) {
+ if (descs_[i].id == id) {
+ descs_[i].count++;
+ descs_[i].epoch = epoch;
+ return;
+ }
+ }
+ // On overflow, find the oldest mutex and drop it.
+ if (size_ == kMaxSize) {
+ u64 minepoch = (u64)-1;
+ u64 mini = (u64)-1;
+ for (uptr i = 0; i < size_; i++) {
+ if (descs_[i].epoch < minepoch) {
+ minepoch = descs_[i].epoch;
+ mini = i;
+ }
+ }
+ RemovePos(mini);
+ CHECK_EQ(size_, kMaxSize - 1);
+ }
+ // Add new mutex descriptor.
+ descs_[size_].id = id;
+ descs_[size_].write = write;
+ descs_[size_].epoch = epoch;
+ descs_[size_].count = 1;
+ size_++;
+}
+
+void MutexSet::Del(u64 id, bool write) {
+ for (uptr i = 0; i < size_; i++) {
+ if (descs_[i].id == id) {
+ if (--descs_[i].count == 0)
+ RemovePos(i);
+ return;
+ }
+ }
+}
+
+void MutexSet::Remove(u64 id) {
+ for (uptr i = 0; i < size_; i++) {
+ if (descs_[i].id == id) {
+ RemovePos(i);
+ return;
+ }
+ }
+}
+
+void MutexSet::RemovePos(uptr i) {
+ CHECK_LT(i, size_);
+ descs_[i] = descs_[size_ - 1];
+ size_--;
+}
+
+uptr MutexSet::Size() const {
+ return size_;
+}
+
+MutexSet::Desc MutexSet::Get(uptr i) const {
+ CHECK_LT(i, size_);
+ return descs_[i];
+}
+
+} // namespace __tsan
Added: compiler-rt/trunk/lib/tsan/rtl/tsan_mutexset.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_mutexset.h?rev=169493&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_mutexset.h (added)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_mutexset.h Thu Dec 6 06:16:15 2012
@@ -0,0 +1,65 @@
+//===-- tsan_mutexset.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.
+//
+// MutexSet holds the set of mutexes currently held by a thread.
+//===----------------------------------------------------------------------===//
+#ifndef TSAN_MUTEXSET_H
+#define TSAN_MUTEXSET_H
+
+#include "tsan_defs.h"
+
+namespace __tsan {
+
+class MutexSet {
+ public:
+ // Holds limited number of mutexes.
+ // The oldest mutexes are discarded on overflow.
+ static const uptr kMaxSize = 64;
+ struct Desc {
+ u64 id;
+ u64 epoch;
+ int count;
+ bool write;
+ };
+
+ MutexSet();
+ // The 'id' is obtained from SyncVar::GetId().
+ void Add(u64 id, bool write, u64 epoch);
+ void Del(u64 id, bool write);
+ void Remove(u64 id); // Removes the mutex completely (if it's destroyed).
+ uptr Size() const;
+ Desc Get(uptr i) const;
+
+ private:
+#ifndef TSAN_GO
+ uptr size_;
+ Desc descs_[kMaxSize];
+#endif
+
+ void RemovePos(uptr i);
+};
+
+// Go does not have mutexes, so do not spend memory and time.
+// (Go sync.Mutex is actually a semaphore -- can be unlocked
+// in different goroutine).
+#ifdef TSAN_GO
+MutexSet::MutexSet() {}
+void MutexSet::Add(u64 id, bool write, u64 epoch) {}
+void MutexSet::Del(u64 id, bool write) {}
+void MutexSet::Remove(u64 id) {}
+void MutexSet::RemovePos(uptr i) {}
+uptr MutexSet::Size() const { return 0; }
+MutexSet::Desc MutexSet::Get(uptr i) const { return Desc(); }
+#endif
+
+} // namespace __tsan
+
+#endif // TSAN_REPORT_H
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc Thu Dec 6 06:16:15 2012
@@ -25,6 +25,10 @@
, sleep() {
}
+ReportMop::ReportMop()
+ : mset(MBlockReportMutex) {
+}
+
ReportDesc::~ReportDesc() {
// FIXME(dvyukov): it must be leaking a lot of memory.
}
@@ -67,15 +71,27 @@
Printf("\n");
}
+static void PrintMutexSet(Vector<ReportMopMutex> const& mset) {
+ for (uptr i = 0; i < mset.Size(); i++) {
+ if (i == 0)
+ Printf(" (mutexes:");
+ const ReportMopMutex m = mset[i];
+ Printf(" %s M%llu", m.write ? "write" : "read", m.id);
+ Printf(i == mset.Size() - 1 ? ")" : ",");
+ }
+}
+
static void PrintMop(const ReportMop *mop, bool first) {
Printf(" %s of size %d at %p",
(first ? (mop->write ? "Write" : "Read")
: (mop->write ? "Previous write" : "Previous read")),
mop->size, (void*)mop->addr);
if (mop->tid == 0)
- Printf(" by main thread:\n");
+ Printf(" by main thread");
else
- Printf(" by thread %d:\n", mop->tid);
+ Printf(" by thread T%d", mop->tid);
+ PrintMutexSet(mop->mset);
+ Printf(":\n");
PrintStack(mop->stack);
}
@@ -90,24 +106,26 @@
if (loc->tid == 0)
Printf(" by main thread:\n");
else
- Printf(" by thread %d:\n", loc->tid);
+ Printf(" by thread T%d:\n", loc->tid);
PrintStack(loc->stack);
} else if (loc->type == ReportLocationStack) {
- Printf(" Location is stack of thread %d:\n\n", loc->tid);
+ Printf(" Location is stack of thread T%d:\n\n", loc->tid);
}
}
static void PrintMutex(const ReportMutex *rm) {
- if (rm->stack == 0)
- return;
- Printf(" Mutex %d created at:\n", rm->id);
- PrintStack(rm->stack);
+ if (rm->destroyed) {
+ Printf(" Mutex M%llu is already destroyed.\n\n", rm->id);
+ } else {
+ Printf(" Mutex M%llu created at:\n", rm->id);
+ PrintStack(rm->stack);
+ }
}
static void PrintThread(const ReportThread *rt) {
if (rt->id == 0) // Little sense in describing the main thread.
return;
- Printf(" Thread %d", rt->id);
+ Printf(" Thread T%d", rt->id);
if (rt->name)
Printf(" '%s'", rt->name);
Printf(" (tid=%zu, %s)", rt->pid, rt->running ? "running" : "finished");
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_report.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_report.h?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_report.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_report.h Thu Dec 6 06:16:15 2012
@@ -38,14 +38,20 @@
int col;
};
+struct ReportMopMutex {
+ u64 id;
+ bool write;
+};
+
struct ReportMop {
int tid;
uptr addr;
int size;
bool write;
- int nmutex;
- int *mutex;
+ Vector<ReportMopMutex> mset;
ReportStack *stack;
+
+ ReportMop();
};
enum ReportLocationType {
@@ -76,7 +82,8 @@
};
struct ReportMutex {
- int id;
+ u64 id;
+ bool destroyed;
ReportStack *stack;
};
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc Thu Dec 6 06:16:15 2012
@@ -291,6 +291,7 @@
TraceHeader *hdr = &thr->trace.headers[trace];
hdr->epoch0 = thr->fast_state.epoch();
hdr->stack0.ObtainCurrent(thr, 0);
+ hdr->mset0 = thr->mset;
thr->nomalloc--;
}
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h Thu Dec 6 06:16:15 2012
@@ -36,6 +36,7 @@
#include "tsan_vector.h"
#include "tsan_report.h"
#include "tsan_platform.h"
+#include "tsan_mutexset.h"
#if SANITIZER_WORDSIZE != 64
# error "ThreadSanitizer is supported only on 64-bit platforms"
@@ -50,6 +51,10 @@
u32 alloc_tid;
u32 alloc_stack_id;
SyncVar *head;
+
+ MBlock()
+ : mtx(MutexTypeMBlock, StatMtxMBlock) {
+ }
};
#ifndef TSAN_GO
@@ -300,6 +305,7 @@
uptr *shadow_stack;
uptr *shadow_stack_end;
#endif
+ MutexSet mset;
ThreadClock clock;
#ifndef TSAN_GO
AllocatorCache alloc_cache;
@@ -447,7 +453,8 @@
~ScopedReport();
void AddStack(const StackTrace *stack);
- void AddMemoryAccess(uptr addr, Shadow s, const StackTrace *stack);
+ void AddMemoryAccess(uptr addr, Shadow s, const StackTrace *stack,
+ const MutexSet *mset);
void AddThread(const ThreadContext *tctx);
void AddMutex(const SyncVar *s);
void AddLocation(uptr addr, uptr size);
@@ -459,11 +466,13 @@
Context *ctx_;
ReportDesc *rep_;
+ void AddMutex(u64 id);
+
ScopedReport(const ScopedReport&);
void operator = (const ScopedReport&);
};
-void RestoreStack(int tid, const u64 epoch, StackTrace *stk);
+void RestoreStack(int tid, const u64 epoch, StackTrace *stk, MutexSet *mset);
void StatAggregate(u64 *dst, u64 *src);
void StatOutput(u64 *stat);
@@ -577,7 +586,10 @@
extern "C" void __tsan_trace_switch();
void ALWAYS_INLINE INLINE TraceAddEvent(ThreadState *thr, FastState fs,
- EventType typ, uptr addr) {
+ EventType typ, u64 addr) {
+ DCHECK_GE((int)typ, 0);
+ DCHECK_LE((int)typ, 7);
+ DCHECK_EQ(GetLsb(addr, 61), addr);
StatInc(thr, StatEvents);
u64 pos = fs.GetTracePos();
if (UNLIKELY((pos % kTracePartSize) == 0)) {
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc Thu Dec 6 06:16:15 2012
@@ -28,7 +28,7 @@
StatInc(thr, StatMutexCreate);
if (!linker_init && IsAppMem(addr))
MemoryWrite1Byte(thr, pc, addr);
- SyncVar *s = ctx->synctab.GetAndLock(thr, pc, addr, true);
+ SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, addr, true);
s->is_rw = rw;
s->is_recursive = recursive;
s->is_linker_init = linker_init;
@@ -61,11 +61,12 @@
trace.ObtainCurrent(thr, pc);
rep.AddStack(&trace);
FastState last(s->last_lock);
- RestoreStack(last.tid(), last.epoch(), &trace);
+ RestoreStack(last.tid(), last.epoch(), &trace, 0);
rep.AddStack(&trace);
rep.AddLocation(s->addr, 1);
OutputReport(ctx, rep);
}
+ thr->mset.Remove(s->GetId());
DestroyAndFree(s);
}
@@ -74,9 +75,9 @@
DPrintf("#%d: MutexLock %zx\n", thr->tid, addr);
if (IsAppMem(addr))
MemoryRead1Byte(thr, pc, addr);
+ SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
thr->fast_state.IncrementEpoch();
- TraceAddEvent(thr, thr->fast_state, EventTypeLock, addr);
- SyncVar *s = CTX()->synctab.GetAndLock(thr, pc, addr, true);
+ TraceAddEvent(thr, thr->fast_state, EventTypeLock, s->GetId());
if (s->owner_tid == SyncVar::kInvalidTid) {
CHECK_EQ(s->recursion, 0);
s->owner_tid = thr->tid;
@@ -98,6 +99,7 @@
StatInc(thr, StatMutexRecLock);
}
s->recursion++;
+ thr->mset.Add(s->GetId(), true, thr->fast_state.epoch());
s->mtx.Unlock();
}
@@ -106,9 +108,9 @@
DPrintf("#%d: MutexUnlock %zx\n", thr->tid, addr);
if (IsAppMem(addr))
MemoryRead1Byte(thr, pc, addr);
+ SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
thr->fast_state.IncrementEpoch();
- TraceAddEvent(thr, thr->fast_state, EventTypeUnlock, addr);
- SyncVar *s = CTX()->synctab.GetAndLock(thr, pc, addr, true);
+ TraceAddEvent(thr, thr->fast_state, EventTypeUnlock, s->GetId());
if (s->recursion == 0) {
if (!s->is_broken) {
s->is_broken = true;
@@ -134,6 +136,7 @@
StatInc(thr, StatMutexRecUnlock);
}
}
+ thr->mset.Del(s->GetId(), true);
s->mtx.Unlock();
}
@@ -143,9 +146,9 @@
StatInc(thr, StatMutexReadLock);
if (IsAppMem(addr))
MemoryRead1Byte(thr, pc, addr);
+ SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, false);
thr->fast_state.IncrementEpoch();
- TraceAddEvent(thr, thr->fast_state, EventTypeRLock, addr);
- SyncVar *s = CTX()->synctab.GetAndLock(thr, pc, addr, false);
+ TraceAddEvent(thr, thr->fast_state, EventTypeRLock, s->GetId());
if (s->owner_tid != SyncVar::kInvalidTid) {
Printf("ThreadSanitizer WARNING: read lock of a write locked mutex\n");
PrintCurrentStack(thr, pc);
@@ -154,6 +157,7 @@
thr->clock.acquire(&s->clock);
s->last_lock = thr->fast_state.raw();
StatInc(thr, StatSyncAcquire);
+ thr->mset.Add(s->GetId(), false, thr->fast_state.epoch());
s->mtx.ReadUnlock();
}
@@ -163,9 +167,9 @@
StatInc(thr, StatMutexReadUnlock);
if (IsAppMem(addr))
MemoryRead1Byte(thr, pc, addr);
+ SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
thr->fast_state.IncrementEpoch();
- TraceAddEvent(thr, thr->fast_state, EventTypeRUnlock, addr);
- SyncVar *s = CTX()->synctab.GetAndLock(thr, pc, addr, true);
+ TraceAddEvent(thr, thr->fast_state, EventTypeRUnlock, s->GetId());
if (s->owner_tid != SyncVar::kInvalidTid) {
Printf("ThreadSanitizer WARNING: read unlock of a write "
"locked mutex\n");
@@ -176,6 +180,7 @@
thr->clock.release(&s->read_clock);
StatInc(thr, StatSyncRelease);
s->mtx.Unlock();
+ thr->mset.Del(s->GetId(), false);
}
void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) {
@@ -183,18 +188,22 @@
DPrintf("#%d: MutexReadOrWriteUnlock %zx\n", thr->tid, addr);
if (IsAppMem(addr))
MemoryRead1Byte(thr, pc, addr);
- SyncVar *s = CTX()->synctab.GetAndLock(thr, pc, addr, true);
+ SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
+ bool write = true;
if (s->owner_tid == SyncVar::kInvalidTid) {
// Seems to be read unlock.
+ write = false;
StatInc(thr, StatMutexReadUnlock);
thr->fast_state.IncrementEpoch();
- TraceAddEvent(thr, thr->fast_state, EventTypeRUnlock, addr);
+ TraceAddEvent(thr, thr->fast_state, EventTypeRUnlock, s->GetId());
thr->clock.set(thr->tid, thr->fast_state.epoch());
thr->fast_synch_epoch = thr->fast_state.epoch();
thr->clock.release(&s->read_clock);
StatInc(thr, StatSyncRelease);
} else if (s->owner_tid == thr->tid) {
// Seems to be write unlock.
+ thr->fast_state.IncrementEpoch();
+ TraceAddEvent(thr, thr->fast_state, EventTypeUnlock, s->GetId());
CHECK_GT(s->recursion, 0);
s->recursion--;
if (s->recursion == 0) {
@@ -204,8 +213,6 @@
// The sequence of events is quite tricky and doubled in several places.
// First, it's a bug to increment the epoch w/o writing to the trace.
// Then, the acquire/release logic can be factored out as well.
- thr->fast_state.IncrementEpoch();
- TraceAddEvent(thr, thr->fast_state, EventTypeUnlock, addr);
thr->clock.set(thr->tid, thr->fast_state.epoch());
thr->fast_synch_epoch = thr->fast_state.epoch();
thr->clock.ReleaseStore(&s->clock);
@@ -218,13 +225,14 @@
Printf("ThreadSanitizer WARNING: mutex unlock by another thread\n");
PrintCurrentStack(thr, pc);
}
+ thr->mset.Del(s->GetId(), write);
s->mtx.Unlock();
}
void Acquire(ThreadState *thr, uptr pc, uptr addr) {
CHECK_GT(thr->in_rtl, 0);
DPrintf("#%d: Acquire %zx\n", thr->tid, addr);
- SyncVar *s = CTX()->synctab.GetAndLock(thr, pc, addr, false);
+ SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, false);
thr->clock.set(thr->tid, thr->fast_state.epoch());
thr->clock.acquire(&s->clock);
StatInc(thr, StatSyncAcquire);
@@ -248,7 +256,7 @@
void Release(ThreadState *thr, uptr pc, uptr addr) {
CHECK_GT(thr->in_rtl, 0);
DPrintf("#%d: Release %zx\n", thr->tid, addr);
- SyncVar *s = CTX()->synctab.GetAndLock(thr, pc, addr, true);
+ SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
thr->clock.set(thr->tid, thr->fast_state.epoch());
thr->clock.release(&s->clock);
StatInc(thr, StatSyncRelease);
@@ -258,7 +266,7 @@
void ReleaseStore(ThreadState *thr, uptr pc, uptr addr) {
CHECK_GT(thr->in_rtl, 0);
DPrintf("#%d: ReleaseStore %zx\n", thr->tid, addr);
- SyncVar *s = CTX()->synctab.GetAndLock(thr, pc, addr, true);
+ SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
thr->clock.set(thr->tid, thr->fast_state.epoch());
thr->clock.ReleaseStore(&s->clock);
StatInc(thr, StatSyncRelease);
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc Thu Dec 6 06:16:15 2012
@@ -14,6 +14,7 @@
#include "sanitizer_common/sanitizer_libc.h"
#include "sanitizer_common/sanitizer_placement_new.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "sanitizer_common/sanitizer_common.h"
#include "tsan_platform.h"
#include "tsan_rtl.h"
#include "tsan_suppressions.h"
@@ -25,6 +26,8 @@
namespace __tsan {
+using namespace __sanitizer; // NOLINT
+
void TsanCheckFailed(const char *file, int line, const char *cond,
u64 v1, u64 v2) {
ScopedInRtl in_rtl;
@@ -134,7 +137,7 @@
}
void ScopedReport::AddMemoryAccess(uptr addr, Shadow s,
- const StackTrace *stack) {
+ const StackTrace *stack, const MutexSet *mset) {
void *mem = internal_alloc(MBlockReportMop, sizeof(ReportMop));
ReportMop *mop = new(mem) ReportMop;
rep_->mops.PushBack(mop);
@@ -142,8 +145,27 @@
mop->addr = addr + s.addr0();
mop->size = s.size();
mop->write = s.is_write();
- mop->nmutex = 0;
mop->stack = SymbolizeStack(*stack);
+ for (uptr i = 0; i < mset->Size(); i++) {
+ MutexSet::Desc d = mset->Get(i);
+ u64 uid = 0;
+ uptr addr = SyncVar::SplitId(d.id, &uid);
+ SyncVar *s = ctx_->synctab.GetIfExistsAndLock(addr, false);
+ // Check that the mutex is still alive.
+ // Another mutex can be created at the same address,
+ // so check uid as well.
+ if (s && s->CheckId(uid)) {
+ ReportMopMutex mtx = {s->uid, d.write};
+ mop->mset.PushBack(mtx);
+ AddMutex(s);
+ } else {
+ ReportMopMutex mtx = {d.id, d.write};
+ mop->mset.PushBack(mtx);
+ AddMutex(d.id);
+ }
+ if (s)
+ s->mtx.ReadUnlock();
+ }
}
void ScopedReport::AddThread(const ThreadContext *tctx) {
@@ -175,13 +197,31 @@
#endif
void ScopedReport::AddMutex(const SyncVar *s) {
+ for (uptr i = 0; i < rep_->mutexes.Size(); i++) {
+ if (rep_->mutexes[i]->id == s->uid)
+ return;
+ }
void *mem = internal_alloc(MBlockReportMutex, sizeof(ReportMutex));
ReportMutex *rm = new(mem) ReportMutex();
rep_->mutexes.PushBack(rm);
- rm->id = 42;
+ rm->id = s->uid;
+ rm->destroyed = false;
rm->stack = SymbolizeStack(s->creation_stack);
}
+void ScopedReport::AddMutex(u64 id) {
+ for (uptr i = 0; i < rep_->mutexes.Size(); i++) {
+ if (rep_->mutexes[i]->id == id)
+ return;
+ }
+ void *mem = internal_alloc(MBlockReportMutex, sizeof(ReportMutex));
+ ReportMutex *rm = new(mem) ReportMutex();
+ rep_->mutexes.PushBack(rm);
+ rm->id = id;
+ rm->destroyed = true;
+ rm->stack = 0;
+}
+
void ScopedReport::AddLocation(uptr addr, uptr size) {
if (addr == 0)
return;
@@ -248,7 +288,10 @@
return rep_;
}
-void RestoreStack(int tid, const u64 epoch, StackTrace *stk) {
+void RestoreStack(int tid, const u64 epoch, StackTrace *stk, MutexSet *mset) {
+ // This function restores stack trace and mutex set for the thread/epoch.
+ // It does so by getting stack trace and mutex set at the beginning of
+ // trace part, and then replaying the trace till the given epoch.
ThreadContext *tctx = CTX()->threads[tid];
if (tctx == 0)
return;
@@ -269,6 +312,7 @@
TraceHeader* hdr = &trace->headers[partidx];
if (epoch < hdr->epoch0)
return;
+ const u64 epoch0 = RoundDown(epoch, TraceSize());
const u64 eend = epoch % TraceSize();
const u64 ebegin = RoundDown(eend, kTracePartSize);
DPrintf("#%d: RestoreStack epoch=%zu ebegin=%zu eend=%zu partidx=%d\n",
@@ -278,12 +322,14 @@
stack[i] = hdr->stack0.Get(i);
DPrintf2(" #%02lu: pc=%zx\n", i, stack[i]);
}
+ if (mset)
+ *mset = hdr->mset0;
uptr pos = hdr->stack0.Size();
Event *events = (Event*)GetThreadTrace(tid);
for (uptr i = ebegin; i <= eend; i++) {
Event ev = events[i];
EventType typ = (EventType)(ev >> 61);
- uptr pc = (uptr)(ev & 0xffffffffffffull);
+ uptr pc = (uptr)(ev & ((1ull << 61) - 1));
DPrintf2(" %zu typ=%d pc=%zx\n", i, typ, pc);
if (typ == EventTypeMop) {
stack[pos] = pc;
@@ -293,6 +339,17 @@
if (pos > 0)
pos--;
}
+ if (mset) {
+ if (typ == EventTypeLock) {
+ mset->Add(pc, true, epoch0 + i);
+ } else if (typ == EventTypeUnlock) {
+ mset->Del(pc, true);
+ } else if (typ == EventTypeRLock) {
+ mset->Add(pc, false, epoch0 + i);
+ } else if (typ == EventTypeRUnlock) {
+ mset->Del(pc, false);
+ }
+ }
for (uptr j = 0; j <= pos; j++)
DPrintf2(" #%zu: %zx\n", j, stack[j]);
}
@@ -456,15 +513,18 @@
traces[0].ObtainCurrent(thr, toppc);
if (IsFiredSuppression(ctx, rep, traces[0]))
return;
+ InternalScopedBuffer<MutexSet> mset2(1);
+ new(mset2.data()) MutexSet();
Shadow s2(thr->racy_state[1]);
- RestoreStack(s2.tid(), s2.epoch(), &traces[1]);
+ RestoreStack(s2.tid(), s2.epoch(), &traces[1], mset2.data());
if (HandleRacyStacks(thr, traces, addr_min, addr_max))
return;
for (uptr i = 0; i < kMop; i++) {
Shadow s(thr->racy_state[i]);
- rep.AddMemoryAccess(addr, s, &traces[i]);
+ rep.AddMemoryAccess(addr, s, &traces[i],
+ i == 0 ? &thr->mset : mset2.data());
}
if (flags()->suppress_java && IsJavaNonsense(rep.GetReport()))
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc Thu Dec 6 06:16:15 2012
@@ -305,6 +305,7 @@
Printf("ThreadSanitizer: join of non-existent thread\n");
return;
}
+ // FIXME(dvyukov): print message and continue (it's user error).
CHECK_EQ(tctx->detached, false);
CHECK_EQ(tctx->status, ThreadStatusFinished);
thr->clock.acquire(&tctx->sync);
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc Thu Dec 6 06:16:15 2012
@@ -253,6 +253,7 @@
name[StatMtxSlab] = " Slab ";
name[StatMtxAtExit] = " Atexit ";
name[StatMtxAnnotations] = " Annotations ";
+ name[StatMtxMBlock] = " MBlock ";
Printf("Statistics:\n");
for (int i = 0; i < StatCnt; i++)
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h Thu Dec 6 06:16:15 2012
@@ -255,6 +255,7 @@
StatMtxSlab,
StatMtxAnnotations,
StatMtxAtExit,
+ StatMtxMBlock,
// This must be the last.
StatCnt
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_sync.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_sync.cc?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_sync.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_sync.cc Thu Dec 6 06:16:15 2012
@@ -17,9 +17,10 @@
namespace __tsan {
-SyncVar::SyncVar(uptr addr)
+SyncVar::SyncVar(uptr addr, u64 uid)
: mtx(MutexTypeSyncVar, StatMtxSyncVar)
, addr(addr)
+ , uid(uid)
, owner_tid(kInvalidTid)
, last_lock()
, recursion()
@@ -47,8 +48,17 @@
}
}
+SyncVar* SyncTab::GetOrCreateAndLock(ThreadState *thr, uptr pc,
+ uptr addr, bool write_lock) {
+ return GetAndLock(thr, pc, addr, write_lock, true);
+}
+
+SyncVar* SyncTab::GetIfExistsAndLock(uptr addr, bool write_lock) {
+ return GetAndLock(0, 0, addr, write_lock, false);
+}
+
SyncVar* SyncTab::GetAndLock(ThreadState *thr, uptr pc,
- uptr addr, bool write_lock) {
+ uptr addr, bool write_lock, bool create) {
#ifndef TSAN_GO
if (PrimaryAllocator::PointerIsMine((void*)addr)) {
MBlock *b = user_mblock(thr, (void*)addr);
@@ -59,9 +69,12 @@
break;
}
if (res == 0) {
+ if (!create)
+ return 0;
StatInc(thr, StatSyncCreated);
void *mem = internal_alloc(MBlockSync, sizeof(SyncVar));
- res = new(mem) SyncVar(addr);
+ const u64 uid = atomic_fetch_add(&uid_gen_, 1, memory_order_relaxed);
+ res = new(mem) SyncVar(addr, uid);
res->creation_stack.ObtainCurrent(thr, pc);
res->next = b->head;
b->head = res;
@@ -87,6 +100,8 @@
}
}
}
+ if (!create)
+ return 0;
{
Lock l(&p->mtx);
SyncVar *res = p->val;
@@ -97,7 +112,8 @@
if (res == 0) {
StatInc(thr, StatSyncCreated);
void *mem = internal_alloc(MBlockSync, sizeof(SyncVar));
- res = new(mem) SyncVar(addr);
+ const u64 uid = atomic_fetch_add(&uid_gen_, 1, memory_order_relaxed);
+ res = new(mem) SyncVar(addr, uid);
#ifndef TSAN_GO
res->creation_stack.ObtainCurrent(thr, pc);
#endif
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_sync.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_sync.h?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_sync.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_sync.h Thu Dec 6 06:16:15 2012
@@ -50,12 +50,13 @@
};
struct SyncVar {
- explicit SyncVar(uptr addr);
+ explicit SyncVar(uptr addr, u64 uid);
static const int kInvalidTid = -1;
Mutex mtx;
const uptr addr;
+ const u64 uid; // Globally unique id.
SyncClock clock;
SyncClock read_clock; // Used for rw mutexes only.
StackTrace creation_stack;
@@ -69,6 +70,18 @@
SyncVar *next; // In SyncTab hashtable.
uptr GetMemoryConsumption();
+ u64 GetId() const {
+ // 47 lsb is addr, then 14 bits is low part of uid, then 3 zero bits.
+ return GetLsb((u64)addr | (uid << 47), 61);
+ }
+ bool CheckId(u64 uid) const {
+ CHECK_EQ(uid, GetLsb(uid, 14));
+ return GetLsb(this->uid, 14) == uid;
+ }
+ static uptr SplitId(u64 id, u64 *uid) {
+ *uid = id >> 47;
+ return (uptr)GetLsb(id, 47);
+ }
};
class SyncTab {
@@ -76,9 +89,9 @@
SyncTab();
~SyncTab();
- // If the SyncVar does not exist yet, it is created.
- SyncVar* GetAndLock(ThreadState *thr, uptr pc,
- uptr addr, bool write_lock);
+ SyncVar* GetOrCreateAndLock(ThreadState *thr, uptr pc,
+ uptr addr, bool write_lock);
+ SyncVar* GetIfExistsAndLock(uptr addr, bool write_lock);
// If the SyncVar does not exist, returns 0.
SyncVar* GetAndRemove(ThreadState *thr, uptr pc, uptr addr);
@@ -96,9 +109,13 @@
// FIXME: Implement something more sane.
static const int kPartCount = 1009;
Part tab_[kPartCount];
+ atomic_uint64_t uid_gen_;
int PartIdx(uptr addr);
+ SyncVar* GetAndLock(ThreadState *thr, uptr pc,
+ uptr addr, bool write_lock, bool create);
+
SyncTab(const SyncTab&); // Not implemented.
void operator = (const SyncTab&); // Not implemented.
};
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_trace.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_trace.h?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_trace.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_trace.h Thu Dec 6 06:16:15 2012
@@ -16,6 +16,7 @@
#include "tsan_defs.h"
#include "tsan_mutex.h"
#include "tsan_sync.h"
+#include "tsan_mutexset.h"
namespace __tsan {
@@ -43,6 +44,7 @@
struct TraceHeader {
StackTrace stack0; // Start stack for the trace.
u64 epoch0; // Start epoch for the trace.
+ MutexSet mset0;
#ifndef TSAN_GO
uptr stack0buf[kTraceStackSize];
#endif
Added: compiler-rt/trunk/lib/tsan/tests/unit/tsan_mutexset_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/tests/unit/tsan_mutexset_test.cc?rev=169493&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/tests/unit/tsan_mutexset_test.cc (added)
+++ compiler-rt/trunk/lib/tsan/tests/unit/tsan_mutexset_test.cc Thu Dec 6 06:16:15 2012
@@ -0,0 +1,126 @@
+//===-- tsan_mutexset_test.cc ---------------------------------------------===//
+//
+// 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_mutexset.h"
+#include "gtest/gtest.h"
+
+namespace __tsan {
+
+static void Expect(const MutexSet &mset, uptr i, u64 id, bool write, u64 epoch,
+ int count) {
+ MutexSet::Desc d = mset.Get(i);
+ EXPECT_EQ(id, d.id);
+ EXPECT_EQ(write, d.write);
+ EXPECT_EQ(epoch, d.epoch);
+ EXPECT_EQ(count, d.count);
+}
+
+TEST(MutexSet, Basic) {
+ MutexSet mset;
+ EXPECT_EQ(mset.Size(), (uptr)0);
+
+ mset.Add(1, true, 2);
+ EXPECT_EQ(mset.Size(), (uptr)1);
+ Expect(mset, 0, 1, true, 2, 1);
+ mset.Del(1, true);
+ EXPECT_EQ(mset.Size(), (uptr)0);
+
+ mset.Add(3, true, 4);
+ mset.Add(5, false, 6);
+ EXPECT_EQ(mset.Size(), (uptr)2);
+ Expect(mset, 0, 3, true, 4, 1);
+ Expect(mset, 1, 5, false, 6, 1);
+ mset.Del(3, true);
+ EXPECT_EQ(mset.Size(), (uptr)1);
+ mset.Del(5, false);
+ EXPECT_EQ(mset.Size(), (uptr)0);
+}
+
+TEST(MutexSet, DoubleAdd) {
+ MutexSet mset;
+ mset.Add(1, true, 2);
+ EXPECT_EQ(mset.Size(), (uptr)1);
+ Expect(mset, 0, 1, true, 2, 1);
+
+ mset.Add(1, true, 2);
+ EXPECT_EQ(mset.Size(), (uptr)1);
+ Expect(mset, 0, 1, true, 2, 2);
+
+ mset.Del(1, true);
+ EXPECT_EQ(mset.Size(), (uptr)1);
+ Expect(mset, 0, 1, true, 2, 1);
+
+ mset.Del(1, true);
+ EXPECT_EQ(mset.Size(), (uptr)0);
+}
+
+TEST(MutexSet, DoubleDel) {
+ MutexSet mset;
+ mset.Add(1, true, 2);
+ EXPECT_EQ(mset.Size(), (uptr)1);
+ mset.Del(1, true);
+ EXPECT_EQ(mset.Size(), (uptr)0);
+ mset.Del(1, true);
+ EXPECT_EQ(mset.Size(), (uptr)0);
+}
+
+TEST(MutexSet, Remove) {
+ MutexSet mset;
+ mset.Add(1, true, 2);
+ mset.Add(1, true, 2);
+ mset.Add(3, true, 4);
+ mset.Add(3, true, 4);
+ EXPECT_EQ(mset.Size(), (uptr)2);
+
+ mset.Remove(1);
+ EXPECT_EQ(mset.Size(), (uptr)1);
+ Expect(mset, 0, 3, true, 4, 2);
+}
+
+TEST(MutexSet, Full) {
+ MutexSet mset;
+ for (uptr i = 0; i < MutexSet::kMaxSize; i++) {
+ mset.Add(i, true, i + 1);
+ }
+ EXPECT_EQ(mset.Size(), MutexSet::kMaxSize);
+ for (uptr i = 0; i < MutexSet::kMaxSize; i++) {
+ Expect(mset, i, i, true, i + 1, 1);
+ }
+
+ for (uptr i = 0; i < MutexSet::kMaxSize; i++) {
+ mset.Add(i, true, i + 1);
+ }
+ EXPECT_EQ(mset.Size(), MutexSet::kMaxSize);
+ for (uptr i = 0; i < MutexSet::kMaxSize; i++) {
+ Expect(mset, i, i, true, i + 1, 2);
+ }
+}
+
+TEST(MutexSet, Overflow) {
+ MutexSet mset;
+ for (uptr i = 0; i < MutexSet::kMaxSize; i++) {
+ mset.Add(i, true, i + 1);
+ mset.Add(i, true, i + 1);
+ }
+ mset.Add(100, true, 200);
+ EXPECT_EQ(mset.Size(), MutexSet::kMaxSize);
+ for (uptr i = 0; i < MutexSet::kMaxSize; i++) {
+ if (i == 0)
+ Expect(mset, i, 63, true, 64, 2);
+ else if (i == MutexSet::kMaxSize - 1)
+ Expect(mset, i, 100, true, 200, 1);
+ else
+ Expect(mset, i, i, true, i + 1, 2);
+ }
+}
+
+} // namespace __tsan
Modified: compiler-rt/trunk/lib/tsan/tests/unit/tsan_sync_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/tests/unit/tsan_sync_test.cc?rev=169493&r1=169492&r2=169493&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/tests/unit/tsan_sync_test.cc (original)
+++ compiler-rt/trunk/lib/tsan/tests/unit/tsan_sync_test.cc Thu Dec 6 06:16:15 2012
@@ -36,7 +36,7 @@
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);
+ SyncVar *v = tab.GetOrCreateAndLock(thr, pc, addr, true);
EXPECT_TRUE(golden[addr] == 0 || golden[addr] == v);
EXPECT_EQ(v->addr, addr);
golden[addr] = v;
More information about the llvm-commits
mailing list