[llvm-commits] [compiler-rt] r169493 - in /compiler-rt/trunk/lib/tsan: lit_tests/ rtl/ tests/unit/
David Blaikie
dblaikie at gmail.com
Thu Dec 13 11:38:47 PST 2012
On Thu, Dec 6, 2012 at 4:16 AM, Dmitry Vyukov <dvyukov at google.com> wrote:
> 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
I don't know whether this is related to the flaking you were fixing in
later commits, but I've been seeing several test failing consistently
on linux for a while now. Failures look like:
FAIL: ThreadSanitizer :: ignore_race.cc (12890 of 13034)
******************** TEST 'ThreadSanitizer :: ignore_race.cc' FAILED
********************
Script:
--
/home/blaikie/local/Development/llvm/build/clang/x86-64/Debug/llvm/bin/clang
-fsanitize=thread -fPIE -fno-builtin -g -Wall -pie -lpthread -ldl -O1
/usr/local/google/home/blaikie/Development/llvm/src/projects/compiler-rt/lib/tsan/lit_tests/ignore_race.cc
-o /usr/local/google/home/blaikie/Development/llvm/build/clang/x86-64/Debug/llvm/projects/compiler-rt/lib/tsan/lit_tests/Output/ignore_race.cc.tmp
&& /usr/local/google/home/blaikie/Development/llvm/build/clang/x86-64/Debug/llvm/projects/compiler-rt/lib/tsan/lit_tests/Output/ignore_race.cc.tmp
2>&1 | FileCheck
/usr/local/google/home/blaikie/Development/llvm/src/projects/compiler-rt/lib/tsan/lit_tests/ignore_race.cc
--
Exit Code: 2
Command Output (stderr):
--
FileCheck error: '-' is empty.
--
********************
& the tests that are failing are:
ThreadSanitizer :: fd_close_norace.cc
ThreadSanitizer :: fd_dup_norace.cc
ThreadSanitizer :: fd_pipe_norace.cc
ThreadSanitizer :: fd_socket_norace.cc
ThreadSanitizer :: 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;
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list