[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