Patchwork [tsan] ThreadSanitizer instrumentation part

login
register
mail settings
Submitter Wei Mi
Date Nov. 22, 2012, 7:22 a.m.
Message ID <CA+4CFy7H13c9DOJVJvtETe1VqAv60-1MeKQ=X0VQvjjpPBeB5g@mail.gmail.com>
Download mbox | patch
Permalink /patch/201023/
State New
Headers show

Comments

Wei Mi - Nov. 22, 2012, 7:22 a.m.
Hi,

I update the tsan patch against trunk, and create libtsan patch.
Please see if it is ok.

gcc/ChangeLog:
2012-11-22  Dmitry Vyukov  <dvyukov@google.com>
            Wei Mi  <wmi@google.com>

        * builtins.def (DEF_SANITIZER_BUILTIN): Define tsan builtins.
        * sanitizer.def: Ditto.
        * Makefile.in (tsan.o): Add tsan.o target.
        (BUILTINS_DEF): Add sanitizer.def.
        * passes.c (init_optimization_passes): Add tsan passes.
        * tree-pass.h (register_pass_info): Ditto.
        * toplev.c (compile_file): Ditto.
        * doc/invoke.texi: Document tsan related options.
        * gcc.c (LINK_COMMAND_SPEC): Add LIBTSAN_SPEC in link command
if -fsanitize=thread.
        * tsan.c: New file about tsan.
        * tsan.h: Ditto.
        * common.opt: Add -fsanitize=thread.

libsanitizer/ChangeLog:
2012-11-22  Wei Mi  <wmi@google.com>

        * tsan: New directory. Import tsan runtime from llvm.
        * configure.ac: Add 64 bits tsan build.
        * Makefile.am: Likewise.
        * configure: Regenerated.
        * Makefile.in: Likewise.

Thanks,
Wei.

On Sun, Nov 18, 2012 at 10:52 AM, Konstantin Serebryany
<konstantin.s.serebryany@gmail.com> wrote:
> Just a comment about tsan.
> Today, tsan works *only* on x86_64 linux (no 32-bits, no non-linux).
> Other 64-bit platforms may be doable, but not as easy as for asan.
> Non-linux is harder than non-x86_64 (need to support tons of libc interceptors).
> 32-bit platforms are very hard to port to, I would not bother for now.
> (this probably includes x32, which has cheap atomic 64-bit
> loads/stores, but has too small address space for tsan)
>
> Conclusion: when committing tsan code, please make sure it is enable
> only on x86_64
>
> --kcc
>
> On Sat, Nov 17, 2012 at 3:13 AM, Wei Mi <wmi@google.com> wrote:
>> Hi,
>>
>> Is it ok for the trunk?
>>
>> Thanks,
>> Wei.
>>
>> On Tue, Nov 13, 2012 at 5:06 PM, Wei Mi <wmi@google.com> wrote:
>>> Thanks for catching this. I update the patch.
>>>
>>> Regards,
>>> Wei.
>>>
>>> On Tue, Nov 13, 2012 at 4:54 PM, Richard Henderson <rth@redhat.com> wrote:
>>>> On 11/13/2012 04:08 PM, Wei Mi wrote:
>>>>> +extern void tsan_finish_file (void);
>>>>> +
>>>>> +#endif /* TREE_TSAN */
>>>>> +/* ThreadSanitizer, a data race detector.
>>>>> +   Copyright (C) 2011 Free Software Foundation, Inc.
>>>>> +   Contributed by Dmitry Vyukov <dvyukov@google.com>
>>>>
>>>> Careful, you've got double applied patches there.
>>>>
>>>>
>>>> r~
Xinliang David Li - Nov. 22, 2012, 7:45 a.m.
On Wed, Nov 21, 2012 at 11:35 PM, Dmitry Vyukov <dvyukov@google.com> wrote:
> What percent of the memory accesses the following can skip?
>
> I just don't know what exactly they mean. ADDR_EXPR/COMPONENT_REF look like
> it can skip a lot.
>

It does not skip a lot.

>
> +  /* TODO: handle other cases
> +     (FIELD_DECL, ARRAY_RANGE_REF, TARGET_MEM_REF, ADDR_EXPR).  */

The comment is not correct.  The analysis should not care about
FIELD_DECL (covered by COMPONENT_REF), nor ADDR_EXPR.  Due to the pass
ordering, target mem-ref is not seen either.


> +  if (tcode != ARRAY_REF
> +      && tcode != VAR_DECL
> +      && tcode != COMPONENT_REF
> +      && tcode != INDIRECT_REF
> +      && tcode != MEM_REF)
> +    return false;
>

The listed cases are handled.

David

>
>
> On Thu, Nov 22, 2012 at 11:29 AM, Dmitry Vyukov <dvyukov@google.com> wrote:
>>
>> +static bool
>> +tsan_gate (void)
>> +{
>> +  return flag_tsan != 0
>> + && builtin_decl_implicit_p (BUILT_IN_TSAN_INIT);
>>
>>
>> What does it mean? Why builtin_decl_implicit_p (BUILT_IN_TSAN_INIT)?
>>
>> +}
>>
>>
>>
>> On Thu, Nov 22, 2012 at 11:22 AM, Wei Mi <wmi@google.com> wrote:
>>>
>>> Hi,
>>>
>>> I update the tsan patch against trunk, and create libtsan patch.
>>> Please see if it is ok.
>>>
>>> gcc/ChangeLog:
>>> 2012-11-22  Dmitry Vyukov  <dvyukov@google.com>
>>>             Wei Mi  <wmi@google.com>
>>>
>>>         * builtins.def (DEF_SANITIZER_BUILTIN): Define tsan builtins.
>>>         * sanitizer.def: Ditto.
>>>         * Makefile.in (tsan.o): Add tsan.o target.
>>>         (BUILTINS_DEF): Add sanitizer.def.
>>>         * passes.c (init_optimization_passes): Add tsan passes.
>>>         * tree-pass.h (register_pass_info): Ditto.
>>>         * toplev.c (compile_file): Ditto.
>>>         * doc/invoke.texi: Document tsan related options.
>>>         * gcc.c (LINK_COMMAND_SPEC): Add LIBTSAN_SPEC in link command
>>> if -fsanitize=thread.
>>>         * tsan.c: New file about tsan.
>>>         * tsan.h: Ditto.
>>>         * common.opt: Add -fsanitize=thread.
>>>
>>> libsanitizer/ChangeLog:
>>> 2012-11-22  Wei Mi  <wmi@google.com>
>>>
>>>         * tsan: New directory. Import tsan runtime from llvm.
>>>         * configure.ac: Add 64 bits tsan build.
>>>         * Makefile.am: Likewise.
>>>         * configure: Regenerated.
>>>         * Makefile.in: Likewise.
>>>
>>> Thanks,
>>> Wei.
>>>
>>> On Sun, Nov 18, 2012 at 10:52 AM, Konstantin Serebryany
>>> <konstantin.s.serebryany@gmail.com> wrote:
>>> > Just a comment about tsan.
>>> > Today, tsan works *only* on x86_64 linux (no 32-bits, no non-linux).
>>> > Other 64-bit platforms may be doable, but not as easy as for asan.
>>> > Non-linux is harder than non-x86_64 (need to support tons of libc
>>> > interceptors).
>>> > 32-bit platforms are very hard to port to, I would not bother for now.
>>> > (this probably includes x32, which has cheap atomic 64-bit
>>> > loads/stores, but has too small address space for tsan)
>>> >
>>> > Conclusion: when committing tsan code, please make sure it is enable
>>> > only on x86_64
>>> >
>>> > --kcc
>>> >
>>> > On Sat, Nov 17, 2012 at 3:13 AM, Wei Mi <wmi@google.com> wrote:
>>> >> Hi,
>>> >>
>>> >> Is it ok for the trunk?
>>> >>
>>> >> Thanks,
>>> >> Wei.
>>> >>
>>> >> On Tue, Nov 13, 2012 at 5:06 PM, Wei Mi <wmi@google.com> wrote:
>>> >>> Thanks for catching this. I update the patch.
>>> >>>
>>> >>> Regards,
>>> >>> Wei.
>>> >>>
>>> >>> On Tue, Nov 13, 2012 at 4:54 PM, Richard Henderson <rth@redhat.com>
>>> >>> wrote:
>>> >>>> On 11/13/2012 04:08 PM, Wei Mi wrote:
>>> >>>>> +extern void tsan_finish_file (void);
>>> >>>>> +
>>> >>>>> +#endif /* TREE_TSAN */
>>> >>>>> +/* ThreadSanitizer, a data race detector.
>>> >>>>> +   Copyright (C) 2011 Free Software Foundation, Inc.
>>> >>>>> +   Contributed by Dmitry Vyukov <dvyukov@google.com>
>>> >>>>
>>> >>>> Careful, you've got double applied patches there.
>>> >>>>
>>> >>>>
>>> >>>> r~
>>
>>
>
Jakub Jelinek - Nov. 22, 2012, 8:08 a.m.
On Thu, Nov 22, 2012 at 11:29:05AM +0400, Dmitry Vyukov wrote:
> +static bool
> +tsan_gate (void)
> +{
> +  return flag_tsan != 0
> +	 && builtin_decl_implicit_p (BUILT_IN_TSAN_INIT);
> 
> 
> What does it mean? Why builtin_decl_implicit_p (BUILT_IN_TSAN_INIT)?

It is a temporary workaround, I'll handle it when the patch goes in.
The thing is that while the C/C++ family of FEs will create all the builtins
just because they are included in builtins.def, other FEs won't.
So we need some routine that will build the builtins if the FEs didn't
initialize them.

	Jakub
Jakub Jelinek - Nov. 22, 2012, 9:54 a.m.
On Wed, Nov 21, 2012 at 11:22:51PM -0800, Wei Mi wrote:
> I update the tsan patch against trunk, and create libtsan patch.
> Please see if it is ok.
> 
> gcc/ChangeLog:
> 2012-11-22  Dmitry Vyukov  <dvyukov@google.com>
>             Wei Mi  <wmi@google.com>
> 
>         * builtins.def (DEF_SANITIZER_BUILTIN): Define tsan builtins.
>         * sanitizer.def: Ditto.
>         * Makefile.in (tsan.o): Add tsan.o target.
>         (BUILTINS_DEF): Add sanitizer.def.
>         * passes.c (init_optimization_passes): Add tsan passes.
>         * tree-pass.h (register_pass_info): Ditto.
>         * toplev.c (compile_file): Ditto.
>         * doc/invoke.texi: Document tsan related options.
>         * gcc.c (LINK_COMMAND_SPEC): Add LIBTSAN_SPEC in link command
> if -fsanitize=thread.
>         * tsan.c: New file about tsan.
>         * tsan.h: Ditto.
>         * common.opt: Add -fsanitize=thread.
> 
> libsanitizer/ChangeLog:
> 2012-11-22  Wei Mi  <wmi@google.com>
> 
>         * tsan: New directory. Import tsan runtime from llvm.
>         * configure.ac: Add 64 bits tsan build.
>         * Makefile.am: Likewise.
>         * configure: Regenerated.
>         * Makefile.in: Likewise.

Ok, thanks.  The comments can be fixed up incrementally.

	Jakub
Wei Mi - Nov. 22, 2012, 10:06 p.m.
Thanks, Fixed.

Wei.

On Wed, Nov 21, 2012 at 11:48 PM, Dmitry Vyukov <dvyukov@google.com> wrote:
> On Thu, Nov 22, 2012 at 11:45 AM, Xinliang David Li <davidxl@google.com>
> wrote:
>>
>> On Wed, Nov 21, 2012 at 11:35 PM, Dmitry Vyukov <dvyukov@google.com>
>> wrote:
>> > What percent of the memory accesses the following can skip?
>> >
>> > I just don't know what exactly they mean. ADDR_EXPR/COMPONENT_REF look
>> > like
>> > it can skip a lot.
>> >
>>
>> It does not skip a lot.
>>
>> >
>> > +  /* TODO: handle other cases
>> > +     (FIELD_DECL, ARRAY_RANGE_REF, TARGET_MEM_REF, ADDR_EXPR).  */
>>
>> The comment is not correct.  The analysis should not care about
>> FIELD_DECL (covered by COMPONENT_REF), nor ADDR_EXPR.  Due to the pass
>> ordering, target mem-ref is not seen either.
>
>
>
>
> Wei, please update the comment that only ARRAY_RANGE_REF is not handled.
>
>
>> > +  if (tcode != ARRAY_REF
>> > +      && tcode != VAR_DECL
>> > +      && tcode != COMPONENT_REF
>> > +      && tcode != INDIRECT_REF
>> > +      && tcode != MEM_REF)
>> > +    return false;
>> >
>>
>> The listed cases are handled.
>>
>> David
>>
>> >
>> >
>> > On Thu, Nov 22, 2012 at 11:29 AM, Dmitry Vyukov <dvyukov@google.com>
>> > wrote:
>> >>
>> >> +static bool
>> >> +tsan_gate (void)
>> >> +{
>> >> +  return flag_tsan != 0
>> >> + && builtin_decl_implicit_p (BUILT_IN_TSAN_INIT);
>> >>
>> >>
>> >> What does it mean? Why builtin_decl_implicit_p (BUILT_IN_TSAN_INIT)?
>> >>
>> >> +}
>> >>
>> >>
>> >>
>> >> On Thu, Nov 22, 2012 at 11:22 AM, Wei Mi <wmi@google.com> wrote:
>> >>>
>> >>> Hi,
>> >>>
>> >>> I update the tsan patch against trunk, and create libtsan patch.
>> >>> Please see if it is ok.
>> >>>
>> >>> gcc/ChangeLog:
>> >>> 2012-11-22  Dmitry Vyukov  <dvyukov@google.com>
>> >>>             Wei Mi  <wmi@google.com>
>> >>>
>> >>>         * builtins.def (DEF_SANITIZER_BUILTIN): Define tsan builtins.
>> >>>         * sanitizer.def: Ditto.
>> >>>         * Makefile.in (tsan.o): Add tsan.o target.
>> >>>         (BUILTINS_DEF): Add sanitizer.def.
>> >>>         * passes.c (init_optimization_passes): Add tsan passes.
>> >>>         * tree-pass.h (register_pass_info): Ditto.
>> >>>         * toplev.c (compile_file): Ditto.
>> >>>         * doc/invoke.texi: Document tsan related options.
>> >>>         * gcc.c (LINK_COMMAND_SPEC): Add LIBTSAN_SPEC in link command
>> >>> if -fsanitize=thread.
>> >>>         * tsan.c: New file about tsan.
>> >>>         * tsan.h: Ditto.
>> >>>         * common.opt: Add -fsanitize=thread.
>> >>>
>> >>> libsanitizer/ChangeLog:
>> >>> 2012-11-22  Wei Mi  <wmi@google.com>
>> >>>
>> >>>         * tsan: New directory. Import tsan runtime from llvm.
>> >>>         * configure.ac: Add 64 bits tsan build.
>> >>>         * Makefile.am: Likewise.
>> >>>         * configure: Regenerated.
>> >>>         * Makefile.in: Likewise.
>> >>>
>> >>> Thanks,
>> >>> Wei.
>> >>>
>> >>> On Sun, Nov 18, 2012 at 10:52 AM, Konstantin Serebryany
>> >>> <konstantin.s.serebryany@gmail.com> wrote:
>> >>> > Just a comment about tsan.
>> >>> > Today, tsan works *only* on x86_64 linux (no 32-bits, no non-linux).
>> >>> > Other 64-bit platforms may be doable, but not as easy as for asan.
>> >>> > Non-linux is harder than non-x86_64 (need to support tons of libc
>> >>> > interceptors).
>> >>> > 32-bit platforms are very hard to port to, I would not bother for
>> >>> > now.
>> >>> > (this probably includes x32, which has cheap atomic 64-bit
>> >>> > loads/stores, but has too small address space for tsan)
>> >>> >
>> >>> > Conclusion: when committing tsan code, please make sure it is enable
>> >>> > only on x86_64
>> >>> >
>> >>> > --kcc
>> >>> >
>> >>> > On Sat, Nov 17, 2012 at 3:13 AM, Wei Mi <wmi@google.com> wrote:
>> >>> >> Hi,
>> >>> >>
>> >>> >> Is it ok for the trunk?
>> >>> >>
>> >>> >> Thanks,
>> >>> >> Wei.
>> >>> >>
>> >>> >> On Tue, Nov 13, 2012 at 5:06 PM, Wei Mi <wmi@google.com> wrote:
>> >>> >>> Thanks for catching this. I update the patch.
>> >>> >>>
>> >>> >>> Regards,
>> >>> >>> Wei.
>> >>> >>>
>> >>> >>> On Tue, Nov 13, 2012 at 4:54 PM, Richard Henderson
>> >>> >>> <rth@redhat.com>
>> >>> >>> wrote:
>> >>> >>>> On 11/13/2012 04:08 PM, Wei Mi wrote:
>> >>> >>>>> +extern void tsan_finish_file (void);
>> >>> >>>>> +
>> >>> >>>>> +#endif /* TREE_TSAN */
>> >>> >>>>> +/* ThreadSanitizer, a data race detector.
>> >>> >>>>> +   Copyright (C) 2011 Free Software Foundation, Inc.
>> >>> >>>>> +   Contributed by Dmitry Vyukov <dvyukov@google.com>
>> >>> >>>>
>> >>> >>>> Careful, you've got double applied patches there.
>> >>> >>>>
>> >>> >>>>
>> >>> >>>> r~
>> >>
>> >>
>> >
>
>
Wei Mi - Nov. 22, 2012, 10:08 p.m.
Thanks. I checked in the code.
Committed revision 193736.
Committed revision 193737.

Wei.

On Thu, Nov 22, 2012 at 1:54 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Wed, Nov 21, 2012 at 11:22:51PM -0800, Wei Mi wrote:
>> I update the tsan patch against trunk, and create libtsan patch.
>> Please see if it is ok.
>>
>> gcc/ChangeLog:
>> 2012-11-22  Dmitry Vyukov  <dvyukov@google.com>
>>             Wei Mi  <wmi@google.com>
>>
>>         * builtins.def (DEF_SANITIZER_BUILTIN): Define tsan builtins.
>>         * sanitizer.def: Ditto.
>>         * Makefile.in (tsan.o): Add tsan.o target.
>>         (BUILTINS_DEF): Add sanitizer.def.
>>         * passes.c (init_optimization_passes): Add tsan passes.
>>         * tree-pass.h (register_pass_info): Ditto.
>>         * toplev.c (compile_file): Ditto.
>>         * doc/invoke.texi: Document tsan related options.
>>         * gcc.c (LINK_COMMAND_SPEC): Add LIBTSAN_SPEC in link command
>> if -fsanitize=thread.
>>         * tsan.c: New file about tsan.
>>         * tsan.h: Ditto.
>>         * common.opt: Add -fsanitize=thread.
>>
>> libsanitizer/ChangeLog:
>> 2012-11-22  Wei Mi  <wmi@google.com>
>>
>>         * tsan: New directory. Import tsan runtime from llvm.
>>         * configure.ac: Add 64 bits tsan build.
>>         * Makefile.am: Likewise.
>>         * configure: Regenerated.
>>         * Makefile.in: Likewise.
>
> Ok, thanks.  The comments can be fixed up incrementally.
>
>         Jakub
H.J. Lu - Nov. 22, 2012, 11:04 p.m.
On Thu, Nov 22, 2012 at 2:08 PM, Wei Mi <wmi@google.com> wrote:
> Thanks. I checked in the code.
> Committed revision 193736.
> Committed revision 193737.
>
> Wei.
>
> On Thu, Nov 22, 2012 at 1:54 AM, Jakub Jelinek <jakub@redhat.com> wrote:
>> On Wed, Nov 21, 2012 at 11:22:51PM -0800, Wei Mi wrote:
>>> I update the tsan patch against trunk, and create libtsan patch.
>>> Please see if it is ok.
>>>
>>> gcc/ChangeLog:
>>> 2012-11-22  Dmitry Vyukov  <dvyukov@google.com>
>>>             Wei Mi  <wmi@google.com>
>>>
>>>         * builtins.def (DEF_SANITIZER_BUILTIN): Define tsan builtins.
>>>         * sanitizer.def: Ditto.
>>>         * Makefile.in (tsan.o): Add tsan.o target.
>>>         (BUILTINS_DEF): Add sanitizer.def.
>>>         * passes.c (init_optimization_passes): Add tsan passes.
>>>         * tree-pass.h (register_pass_info): Ditto.
>>>         * toplev.c (compile_file): Ditto.
>>>         * doc/invoke.texi: Document tsan related options.
>>>         * gcc.c (LINK_COMMAND_SPEC): Add LIBTSAN_SPEC in link command
>>> if -fsanitize=thread.
>>>         * tsan.c: New file about tsan.
>>>         * tsan.h: Ditto.
>>>         * common.opt: Add -fsanitize=thread.
>>>
>>> libsanitizer/ChangeLog:
>>> 2012-11-22  Wei Mi  <wmi@google.com>
>>>
>>>         * tsan: New directory. Import tsan runtime from llvm.
>>>         * configure.ac: Add 64 bits tsan build.
>>>         * Makefile.am: Likewise.
>>>         * configure: Regenerated.
>>>         * Makefile.in: Likewise.
>>
>> Ok, thanks.  The comments can be fixed up incrementally.
>>
>>         Jakub

It failed to bootstrap on Linux/i686:

http://gcc.gnu.org/ml/gcc-regression/2012-11/msg00409.html

It tried to build tsan on Linux/i686.
Jakub Jelinek - Nov. 22, 2012, 11:06 p.m.
On Thu, Nov 22, 2012 at 03:04:23PM -0800, H.J. Lu wrote:
> It failed to bootstrap on Linux/i686:
> 
> http://gcc.gnu.org/ml/gcc-regression/2012-11/msg00409.html
> 
> It tried to build tsan on Linux/i686.

I'd hope http://gcc.gnu.org/ml/gcc-patches/2012-11/msg01866.html ought to
fix that.

	Jakub
Jack Howarth - Nov. 22, 2012, 11:18 p.m.
On Thu, Nov 22, 2012 at 02:08:07PM -0800, Wei Mi wrote:
> Thanks. I checked in the code.
> Committed revision 193736.
> Committed revision 193737.
> 
> Wei.

Wei,
   Unlike libasan, we seem to have issues building libtsan on darwin using the currently proposed
patch...

http://gcc.gnu.org/ml/gcc-patches/2012-11/msg01817.html

The build fails at...

libtool: compile:  /sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/./gcc/g++ -B/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/./gcc/ -nostdinc++ -nostdinc++ -I/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc++-v3/include/x86_64-apple-darwin12.2.0 -I/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc++-v3/include -I/sw/src/fink.build/gcc48-4.8.0-1000/gcc-4.8-20121122/libstdc++-v3/libsupc++ -I/sw/src/fink.build/gcc48-4.8.0-1000/gcc-4.8-20121122/libstdc++-v3/include/backward -I/sw/src/fink.build/gcc48-4.8.0-1000/gcc-4.8-20121122/libstdc++-v3/testsuite/util -L/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc++-v3/src -L/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc++-v3/src/.libs -B/sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/bin/ -B/sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/lib/ -isystem /sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/include -isystem /sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/sys-include -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I. -I../../../../gcc-4.8-20121122/libsanitizer/tsan -I ../../../../gcc-4.8-20121122/libsanitizer -I ../../../../gcc-4.8-20121122/libsanitizer/include -Wall -W -Wno-unused-parameter -Wwrite-strings -pedantic -Wno-long-long -fPIC -fno-builtin -fno-exceptions -fomit-frame-pointer -funwind-tables -fvisibility=hidden -Wno-variadic-macros -Wno-c99-extensions -g -O2 -MT tsan_interceptors.lo -MD -MP -MF .deps/tsan_interceptors.Tpo -c ../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc  -fno-common -DPIC -o .libs/tsan_interceptors.o
../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc: In function ‘unsigned int wrap_sleep(unsigned int)’:
../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc:164:27: error: ‘sleep’ was not declared in this scope
   unsigned res = sleep(sec);
                           ^
../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc: In function ‘int wrap_usleep(long_t)’:
../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc:171:24: error: ‘usleep’ was not declared in this scope
   int res = usleep(usec);
                        ^
../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc: In function ‘int wrap_nanosleep(void*, void*)’:
../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc:178:31: error: ‘nanosleep’ was not declared in this scope
   int res = nanosleep(req, rem);
                               ^
../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc: In function ‘void (* wrap_signal(int, sighandler_t))(int)’:
../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc:1270:38: error: ‘sigaction’ was not declared in this scope
   int res = sigaction(sig, &act, &old);
                                      ^
In file included from ../../../../gcc-4.8-20121122/libsanitizer/interception/interception.h:184:0,
                 from ../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.h:15,
                 from ../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc:16:
../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc: In function ‘void __tsan::InitializeInterceptors()’:
../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc:1377:18: error: ‘longjmp’ was not declared in this scope
   TSAN_INTERCEPT(longjmp);
                  ^
../../../../gcc-4.8-20121122/libsanitizer/interception/interception_mac.h:41:35: note: in definition of macro ‘OVERRIDE_FUNCTION_MAC’
           (::__interception::uptr)old_func, \
                                   ^
../../../../gcc-4.8-20121122/libsanitizer/interception/interception.h:187:35: note: in expansion of macro ‘INTERCEPT_FUNCTION_MAC’
 # define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_MAC(func)
                                   ^
../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.h:48:30: note: in expansion of macro ‘INTERCEPT_FUNCTION’
 #define TSAN_INTERCEPT(func) INTERCEPT_FUNCTION(func)
                              ^
etc. Current llvm svn seems to be broken elsewhere (in compiler-rt/lib/ubsan) so I can't test tsan support there as well.
              Jack

> 
> On Thu, Nov 22, 2012 at 1:54 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> > On Wed, Nov 21, 2012 at 11:22:51PM -0800, Wei Mi wrote:
> >> I update the tsan patch against trunk, and create libtsan patch.
> >> Please see if it is ok.
> >>
> >> gcc/ChangeLog:
> >> 2012-11-22  Dmitry Vyukov  <dvyukov@google.com>
> >>             Wei Mi  <wmi@google.com>
> >>
> >>         * builtins.def (DEF_SANITIZER_BUILTIN): Define tsan builtins.
> >>         * sanitizer.def: Ditto.
> >>         * Makefile.in (tsan.o): Add tsan.o target.
> >>         (BUILTINS_DEF): Add sanitizer.def.
> >>         * passes.c (init_optimization_passes): Add tsan passes.
> >>         * tree-pass.h (register_pass_info): Ditto.
> >>         * toplev.c (compile_file): Ditto.
> >>         * doc/invoke.texi: Document tsan related options.
> >>         * gcc.c (LINK_COMMAND_SPEC): Add LIBTSAN_SPEC in link command
> >> if -fsanitize=thread.
> >>         * tsan.c: New file about tsan.
> >>         * tsan.h: Ditto.
> >>         * common.opt: Add -fsanitize=thread.
> >>
> >> libsanitizer/ChangeLog:
> >> 2012-11-22  Wei Mi  <wmi@google.com>
> >>
> >>         * tsan: New directory. Import tsan runtime from llvm.
> >>         * configure.ac: Add 64 bits tsan build.
> >>         * Makefile.am: Likewise.
> >>         * configure: Regenerated.
> >>         * Makefile.in: Likewise.
> >
> > Ok, thanks.  The comments can be fixed up incrementally.
> >
> >         Jakub
Wei Mi - Nov. 23, 2012, 12:53 a.m.
Hi Jack,

Koysta mentioned in a previous mail that tsan is only supported on
x86_64 linux (no 32-bits, no non-linux) for now. tsan building should
be disabled on the platforms other than x86-64-linux. Thanks to Jakub
who will provide another patch including this fix soon.

Thanks,
Wei.

On Thu, Nov 22, 2012 at 3:18 PM, Jack Howarth <howarth@bromo.med.uc.edu> wrote:
> On Thu, Nov 22, 2012 at 02:08:07PM -0800, Wei Mi wrote:
>> Thanks. I checked in the code.
>> Committed revision 193736.
>> Committed revision 193737.
>>
>> Wei.
>
> Wei,
>    Unlike libasan, we seem to have issues building libtsan on darwin using the currently proposed
> patch...
>
> http://gcc.gnu.org/ml/gcc-patches/2012-11/msg01817.html
>
> The build fails at...
>
> libtool: compile:  /sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/./gcc/g++ -B/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/./gcc/ -nostdinc++ -nostdinc++ -I/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc++-v3/include/x86_64-apple-darwin12.2.0 -I/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc++-v3/include -I/sw/src/fink.build/gcc48-4.8.0-1000/gcc-4.8-20121122/libstdc++-v3/libsupc++ -I/sw/src/fink.build/gcc48-4.8.0-1000/gcc-4.8-20121122/libstdc++-v3/include/backward -I/sw/src/fink.build/gcc48-4.8.0-1000/gcc-4.8-20121122/libstdc++-v3/testsuite/util -L/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc++-v3/src -L/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc++-v3/src/.libs -B/sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/bin/ -B/sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/lib/ -isystem /sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/include -isystem /sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/sys-include -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I. -I../../../../gcc-4.8-20121122/libsanitizer/tsan -I ../../../../gcc-4.8-20121122/libsanitizer -I ../../../../gcc-4.8-20121122/libsanitizer/include -Wall -W -Wno-unused-parameter -Wwrite-strings -pedantic -Wno-long-long -fPIC -fno-builtin -fno-exceptions -fomit-frame-pointer -funwind-tables -fvisibility=hidden -Wno-variadic-macros -Wno-c99-extensions -g -O2 -MT tsan_interceptors.lo -MD -MP -MF .deps/tsan_interceptors.Tpo -c ../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc  -fno-common -DPIC -o .libs/tsan_interceptors.o
> ../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc: In function ‘unsigned int wrap_sleep(unsigned int)’:
> ../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc:164:27: error: ‘sleep’ was not declared in this scope
>    unsigned res = sleep(sec);
>                            ^
> ../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc: In function ‘int wrap_usleep(long_t)’:
> ../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc:171:24: error: ‘usleep’ was not declared in this scope
>    int res = usleep(usec);
>                         ^
> ../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc: In function ‘int wrap_nanosleep(void*, void*)’:
> ../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc:178:31: error: ‘nanosleep’ was not declared in this scope
>    int res = nanosleep(req, rem);
>                                ^
> ../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc: In function ‘void (* wrap_signal(int, sighandler_t))(int)’:
> ../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc:1270:38: error: ‘sigaction’ was not declared in this scope
>    int res = sigaction(sig, &act, &old);
>                                       ^
> In file included from ../../../../gcc-4.8-20121122/libsanitizer/interception/interception.h:184:0,
>                  from ../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.h:15,
>                  from ../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc:16:
> ../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc: In function ‘void __tsan::InitializeInterceptors()’:
> ../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.cc:1377:18: error: ‘longjmp’ was not declared in this scope
>    TSAN_INTERCEPT(longjmp);
>                   ^
> ../../../../gcc-4.8-20121122/libsanitizer/interception/interception_mac.h:41:35: note: in definition of macro ‘OVERRIDE_FUNCTION_MAC’
>            (::__interception::uptr)old_func, \
>                                    ^
> ../../../../gcc-4.8-20121122/libsanitizer/interception/interception.h:187:35: note: in expansion of macro ‘INTERCEPT_FUNCTION_MAC’
>  # define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_MAC(func)
>                                    ^
> ../../../../gcc-4.8-20121122/libsanitizer/tsan/tsan_interceptors.h:48:30: note: in expansion of macro ‘INTERCEPT_FUNCTION’
>  #define TSAN_INTERCEPT(func) INTERCEPT_FUNCTION(func)
>                               ^
> etc. Current llvm svn seems to be broken elsewhere (in compiler-rt/lib/ubsan) so I can't test tsan support there as well.
>               Jack
>
>>
>> On Thu, Nov 22, 2012 at 1:54 AM, Jakub Jelinek <jakub@redhat.com> wrote:
>> > On Wed, Nov 21, 2012 at 11:22:51PM -0800, Wei Mi wrote:
>> >> I update the tsan patch against trunk, and create libtsan patch.
>> >> Please see if it is ok.
>> >>
>> >> gcc/ChangeLog:
>> >> 2012-11-22  Dmitry Vyukov  <dvyukov@google.com>
>> >>             Wei Mi  <wmi@google.com>
>> >>
>> >>         * builtins.def (DEF_SANITIZER_BUILTIN): Define tsan builtins.
>> >>         * sanitizer.def: Ditto.
>> >>         * Makefile.in (tsan.o): Add tsan.o target.
>> >>         (BUILTINS_DEF): Add sanitizer.def.
>> >>         * passes.c (init_optimization_passes): Add tsan passes.
>> >>         * tree-pass.h (register_pass_info): Ditto.
>> >>         * toplev.c (compile_file): Ditto.
>> >>         * doc/invoke.texi: Document tsan related options.
>> >>         * gcc.c (LINK_COMMAND_SPEC): Add LIBTSAN_SPEC in link command
>> >> if -fsanitize=thread.
>> >>         * tsan.c: New file about tsan.
>> >>         * tsan.h: Ditto.
>> >>         * common.opt: Add -fsanitize=thread.
>> >>
>> >> libsanitizer/ChangeLog:
>> >> 2012-11-22  Wei Mi  <wmi@google.com>
>> >>
>> >>         * tsan: New directory. Import tsan runtime from llvm.
>> >>         * configure.ac: Add 64 bits tsan build.
>> >>         * Makefile.am: Likewise.
>> >>         * configure: Regenerated.
>> >>         * Makefile.in: Likewise.
>> >
>> > Ok, thanks.  The comments can be fixed up incrementally.
>> >
>> >         Jakub

Patch

Index: gcc/gcc.c
===================================================================
--- gcc/gcc.c	(revision 193702)
+++ gcc/gcc.c	(working copy)
@@ -553,6 +553,15 @@  proper position among the other output f
 #endif
 #endif
 
+#ifndef LIBTSAN_SPEC
+#ifdef HAVE_LD_STATIC_DYNAMIC
+#define LIBTSAN_SPEC "%{static-libtsan:" LD_STATIC_OPTION \
+		     "} -ltsan %{static-libtsan:" LD_DYNAMIC_OPTION "}"
+#else
+#define LIBTSAN_SPEC "-ltsan"
+#endif
+#endif
+
 /* config.h can define LIBGCC_SPEC to override how and when libgcc.a is
    included.  */
 #ifndef LIBGCC_SPEC
@@ -697,6 +706,7 @@  proper position among the other output f
     %(mflib) " STACK_SPLIT_SPEC "\
     %{fprofile-arcs|fprofile-generate*|coverage:-lgcov}\
     %{fsanitize=address:" LIBASAN_SPEC "}\
+    %{fsanitize=thread:" LIBTSAN_SPEC "}\
     %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
     %{!nostdlib:%{!nostartfiles:%E}} %{T*} }}}}}}"
 #endif
Index: gcc/sanitizer.def
===================================================================
--- gcc/sanitizer.def	(revision 0)
+++ gcc/sanitizer.def	(revision 0)
@@ -0,0 +1,28 @@ 
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_INIT, "__tsan_init", 
+		      BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_FUNC_ENTRY, "__tsan_func_entry",
+		      BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_FUNC_EXIT, "__tsan_func_exit",
+		      BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_VPTR_UPDATE, "__tsan_vptr_update",
+		      BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_READ_1, "__tsan_read1",
+		      BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_READ_2, "__tsan_read2",
+		      BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_READ_4, "__tsan_read4",
+		      BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_READ_8, "__tsan_read8",
+		      BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_READ_16, "__tsan_read16",
+		      BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE_1, "__tsan_write1",
+		      BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE_2, "__tsan_write2",
+		      BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE_4, "__tsan_write4",
+		      BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE_8, "__tsan_write8",
+		      BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE_16, "__tsan_write16",
+		      BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 193702)
+++ gcc/Makefile.in	(working copy)
@@ -863,7 +863,7 @@  RTL_ERROR_H = rtl-error.h $(RTL_H) $(DIA
 READ_MD_H = $(OBSTACK_H) $(HASHTAB_H) read-md.h
 PARAMS_H = params.h params.def
 BUILTINS_DEF = builtins.def sync-builtins.def omp-builtins.def \
-	gtm-builtins.def
+	gtm-builtins.def sanitizer.def
 INTERNAL_FN_DEF = internal-fn.def
 INTERNAL_FN_H = internal-fn.h $(INTERNAL_FN_DEF)
 TREE_H = coretypes.h tree.h all-tree.def tree.def c-family/c-common.def \
@@ -1365,6 +1365,7 @@  OBJS = \
 	trans-mem.o \
 	tree-affine.o \
 	asan.o \
+	tsan.o \
 	tree-call-cdce.o \
 	tree-cfg.o \
 	tree-cfgcleanup.o \
@@ -2228,6 +2229,12 @@  asan.o : asan.c asan.h $(CONFIG_H) $(SYS
    output.h coretypes.h $(GIMPLE_PRETTY_PRINT_H) \
    tree-iterator.h $(TREE_FLOW_H) $(TREE_PASS_H) \
    $(TARGET_H) $(EXPR_H) $(OPTABS_H) $(TM_P_H)
+tsan.o : $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TREE_INLINE_H) \
+   $(GIMPLE_H) $(DIAGNOSTIC_H) langhooks.h \
+   $(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_PASS_H) $(CGRAPH_H) $(GGC_H) \
+   $(BASIC_BLOCK_H) $(FLAGS_H) $(FUNCTION_H) \
+   $(TM_P_H) $(TREE_FLOW_H) $(DIAGNOSTIC_CORE_H) $(GIMPLE_H) tree-iterator.h \
+   intl.h cfghooks.h output.h options.h c-family/c-common.h tsan.h
 tree-ssa-tail-merge.o: tree-ssa-tail-merge.c \
    $(SYSTEM_H) $(CONFIG_H) coretypes.h $(TM_H) $(BITMAP_H) \
    $(FLAGS_H) $(TM_P_H) $(BASIC_BLOCK_H) \
@@ -2689,7 +2696,8 @@  toplev.o : toplev.c $(CONFIG_H) $(SYSTEM
    $(CGRAPH_H) $(COVERAGE_H) alloc-pool.h $(GGC_H) \
    $(OPTS_H) params.def tree-mudflap.h $(TREE_PASS_H) $(GIMPLE_H) \
    tree-ssa-alias.h $(PLUGIN_H) realmpfr.h tree-diagnostic.h \
-   $(TREE_PRETTY_PRINT_H) opts-diagnostic.h $(COMMON_TARGET_H)
+   $(TREE_PRETTY_PRINT_H) opts-diagnostic.h $(COMMON_TARGET_H) \
+   tsan.h
 
 hwint.o : hwint.c $(CONFIG_H) $(SYSTEM_H) $(DIAGNOSTIC_CORE_H)
 
@@ -3740,6 +3748,7 @@  GTFILES = $(CPP_ID_DATA_H) $(srcdir)/inp
   $(srcdir)/target-globals.h \
   $(srcdir)/ipa-inline.h \
   $(srcdir)/asan.c \
+  $(srcdir)/tsan.c \
   @all_gtfiles@
 
 # Compute the list of GT header files from the corresponding C sources,
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 193702)
+++ gcc/doc/invoke.texi	(working copy)
@@ -453,7 +453,8 @@  Objective-C and Objective-C++ Dialects}.
 @xref{Link Options,,Options for Linking}.
 @gccoptlist{@var{object-file-name}  -l@var{library} @gol
 -nostartfiles  -nodefaultlibs  -nostdlib -pie -rdynamic @gol
--s  -static -static-libgcc -static-libasan -static-libstdc++ @gol
+-s  -static -static-libgcc -static-libstdc++ @gol
+-static-libasan -static-libtsan @gol
 -shared -shared-libgcc  -symbolic @gol
 -T @var{script}  -Wl,@var{option}  -Xlinker @var{option} @gol
 -u @var{symbol}}
@@ -6862,6 +6863,12 @@  Memory access instructions will be instr
 out-of-bounds and use-after-free bugs. So far only heap bugs will be detected.
 See @uref{http://code.google.com/p/address-sanitizer/} for more details.
 
+@item -fsanitize=thread
+Enable ThreadSanitizer, a fast data race detector.
+Memory access instructions will be instrumented to detect
+data race bugs. 
+See @uref{http://code.google.com/p/data-race-test/wiki/ThreadSanitizer} for more details.
+
 @item -fmudflap -fmudflapth -fmudflapir
 @opindex fmudflap
 @opindex fmudflapth
@@ -9947,6 +9954,15 @@  option is not used, then this links agai
 driver to link @file{libasan} statically, without necessarily linking
 other libraries statically.
 
+@item -static-libtsan
+When the @option{-fsanitize=thread} option is used to link a program,
+the GCC driver automatically links against @option{libtsan}.  If
+@file{libtsan} is available as a shared library, and the @option{-static}
+option is not used, then this links against the shared version of
+@file{libtsan}.  The @option{-static-libtsan} option directs the GCC
+driver to link @file{libtsan} statically, without necessarily linking
+other libraries statically.
+
 @item -static-libstdc++
 When the @command{g++} program is used to link a C++ program, it
 normally automatically links against @option{libstdc++}.  If
Index: gcc/passes.c
===================================================================
--- gcc/passes.c	(revision 193702)
+++ gcc/passes.c	(working copy)
@@ -1450,6 +1450,7 @@  init_optimization_passes (void)
       NEXT_PASS (pass_pre);
       NEXT_PASS (pass_sink_code);
       NEXT_PASS (pass_asan);
+      NEXT_PASS (pass_tsan);
       NEXT_PASS (pass_tree_loop);
 	{
 	  struct opt_pass **p = &pass_tree_loop.pass.sub;
@@ -1556,6 +1557,7 @@  init_optimization_passes (void)
     }
   NEXT_PASS (pass_lower_complex_O0);
   NEXT_PASS (pass_asan_O0);
+  NEXT_PASS (pass_tsan_O0);
   NEXT_PASS (pass_cleanup_eh);
   NEXT_PASS (pass_lower_resx);
   NEXT_PASS (pass_nrv);
Index: gcc/tree-pass.h
===================================================================
--- gcc/tree-pass.h	(revision 193702)
+++ gcc/tree-pass.h	(working copy)
@@ -261,6 +261,8 @@  extern struct gimple_opt_pass pass_mudfl
 extern struct gimple_opt_pass pass_mudflap_2;
 extern struct gimple_opt_pass pass_asan;
 extern struct gimple_opt_pass pass_asan_O0;
+extern struct gimple_opt_pass pass_tsan;
+extern struct gimple_opt_pass pass_tsan_O0;
 extern struct gimple_opt_pass pass_lower_cf;
 extern struct gimple_opt_pass pass_refactor_eh;
 extern struct gimple_opt_pass pass_lower_eh;
Index: gcc/tsan.c
===================================================================
--- gcc/tsan.c	(revision 0)
+++ gcc/tsan.c	(revision 0)
@@ -0,0 +1,406 @@ 
+/* GCC instrumentation plugin for ThreadSanitizer.
+   Copyright (C) 2011, 2012 Free Software Foundation, Inc.
+   Contributed by Dmitry Vyukov <dvyukov@google.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "intl.h"
+#include "tm.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "function.h"
+#include "tree-flow.h"
+#include "tree-pass.h"
+#include "tree-iterator.h"
+#include "langhooks.h"
+#include "output.h"
+#include "options.h"
+#include "target.h"
+#include "cgraph.h"
+#include "diagnostic.h"
+
+/* Number of instrumented memory accesses in the current function.  */
+
+/* Builds the following decl
+   void __tsan_read/writeX (void *addr);  */
+
+static tree
+get_memory_access_decl (bool is_write, unsigned size)
+{
+  enum built_in_function fcode;
+
+  if (size <= 1)
+    fcode = is_write ? BUILT_IN_TSAN_WRITE_1
+		     : BUILT_IN_TSAN_READ_1;
+  else if (size <= 3)
+    fcode = is_write ? BUILT_IN_TSAN_WRITE_2
+		     : BUILT_IN_TSAN_READ_2;
+  else if (size <= 7)
+    fcode = is_write ? BUILT_IN_TSAN_WRITE_4
+		     : BUILT_IN_TSAN_READ_4;
+  else if (size <= 15)
+    fcode = is_write ? BUILT_IN_TSAN_WRITE_8
+		     : BUILT_IN_TSAN_READ_8;
+  else
+    fcode = is_write ? BUILT_IN_TSAN_WRITE_16
+		     : BUILT_IN_TSAN_READ_16;
+
+  return builtin_decl_implicit (fcode);
+}
+
+/* Check as to whether EXPR refers to a store to vptr.  */
+
+static tree
+is_vptr_store (gimple stmt, tree expr, bool is_write)
+{
+  if (is_write == true
+      && gimple_assign_single_p (stmt)
+      && TREE_CODE (expr) == COMPONENT_REF)
+    {
+      tree field = TREE_OPERAND (expr, 1);
+      if (TREE_CODE (field) == FIELD_DECL
+	  && DECL_VIRTUAL_P (field))
+	return gimple_assign_rhs1 (stmt);
+    }
+  return NULL;
+}
+
+/* Checks as to whether EXPR refers to constant var/field/param.
+   Don't bother to instrument them.  */
+
+static bool
+is_load_of_const_p (tree expr, bool is_write)
+{
+  if (is_write)
+    return false;
+  if (TREE_CODE (expr) == COMPONENT_REF)
+    expr = TREE_OPERAND (expr, 1);
+  if (TREE_CODE (expr) == VAR_DECL
+      || TREE_CODE (expr) == PARM_DECL
+      || TREE_CODE (expr) == FIELD_DECL)
+    {
+      if (TREE_READONLY (expr))
+	return true;
+    }
+  return false;
+}
+
+/* Instruments EXPR if needed. If any instrumentation is inserted,
+ * return true. */
+
+static bool
+instrument_expr (gimple_stmt_iterator gsi, tree expr, bool is_write)
+{
+  enum tree_code tcode;
+  tree base, rhs, expr_type, expr_ptr, builtin_decl;
+  basic_block bb;
+  HOST_WIDE_INT size;
+  gimple stmt, g;
+  location_t loc;
+
+  base = get_base_address (expr);
+  if (base == NULL_TREE
+      || TREE_CODE (base) == SSA_NAME
+      || TREE_CODE (base) == STRING_CST)
+    return false;
+
+  tcode = TREE_CODE (expr);
+
+  /* Below are things we do not instrument
+     (no possibility of races or not implemented yet).  */
+  if (/* Compiler-emitted artificial variables.  */
+      (DECL_P (expr) && DECL_ARTIFICIAL (expr))
+      /* The var does not live in memory -> no possibility of races.  */
+      || (tcode == VAR_DECL
+	  && !TREE_ADDRESSABLE (expr)
+	  && TREE_STATIC (expr) == 0)
+      /* Not implemented.  */
+      || TREE_CODE (TREE_TYPE (expr)) == RECORD_TYPE
+      /* Not implemented.  */
+      || tcode == CONSTRUCTOR
+      /* Not implemented.  */
+      || tcode == PARM_DECL
+      /* Load of a const variable/parameter/field.  */
+      || is_load_of_const_p (expr, is_write))
+    return false;
+
+  size = int_size_in_bytes (TREE_TYPE (expr));
+  if (size == -1)
+    return false;
+
+  /* For now just avoid instrumenting bit field acceses.
+     TODO: handle bit-fields as if touching the whole field.  */
+  HOST_WIDE_INT bitsize, bitpos;
+  tree offset;
+  enum machine_mode mode;
+  int volatilep = 0, unsignedp = 0;
+  get_inner_reference (expr, &bitsize, &bitpos, &offset,
+		       &mode, &unsignedp, &volatilep, false);
+  if (bitpos % (size * BITS_PER_UNIT)
+      || bitsize != size * BITS_PER_UNIT)
+    return false;
+
+  /* TODO: handle other cases
+     (FIELD_DECL, ARRAY_RANGE_REF, TARGET_MEM_REF, ADDR_EXPR).  */
+  if (tcode != ARRAY_REF
+      && tcode != VAR_DECL
+      && tcode != COMPONENT_REF
+      && tcode != INDIRECT_REF
+      && tcode != MEM_REF)
+    return false;
+
+  stmt = gsi_stmt (gsi);
+  loc = gimple_location (stmt);
+  rhs = is_vptr_store (stmt, expr, is_write);
+  gcc_checking_assert (rhs != NULL || is_gimple_addressable (expr));
+  expr_ptr = build_fold_addr_expr (unshare_expr (expr));
+  if (rhs == NULL)
+    {
+      expr_type = TREE_TYPE (expr);
+      while (TREE_CODE (expr_type) == ARRAY_TYPE)
+	expr_type = TREE_TYPE (expr_type);
+      size = int_size_in_bytes (expr_type);
+      g = gimple_build_call (get_memory_access_decl (is_write, size),
+			     1, expr_ptr);
+    }
+  else
+    {
+      builtin_decl = builtin_decl_implicit (BUILT_IN_TSAN_VPTR_UPDATE);
+      g = gimple_build_call (builtin_decl, 1, expr_ptr);
+    }
+  gimple_set_location (g, loc);
+  /* Instrumentation for assignment of a function result
+     must be inserted after the call.  Instrumentation for
+     reads of function arguments must be inserted before the call.
+     That's because the call can contain synchronization.  */
+  if (is_gimple_call (stmt) && is_write)
+    {
+      /* If the call can throw, it must be the last stmt in
+	 a basic block, so the instrumented stmts need to be
+	 inserted in successor bbs. */
+      if (is_ctrl_altering_stmt (stmt))
+	{
+	  edge e;
+
+	  bb = gsi_bb (gsi);
+	  e = find_fallthru_edge (bb->succs);
+	  if (e)
+	    gsi_insert_seq_on_edge_immediate (e, g);
+	}
+      else
+	gsi_insert_after (&gsi, g, GSI_NEW_STMT);
+    }
+  else
+    gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+
+  return true;
+}
+
+/* Instruments the gimple pointed to by GSI. Return
+ * true if func entry/exit should be instrumented. */
+
+static bool
+instrument_gimple (gimple_stmt_iterator gsi)
+{
+  gimple stmt;
+  tree rhs, lhs;
+  bool instrumented = false;
+
+  stmt = gsi_stmt (gsi);
+  if (is_gimple_call (stmt)
+      && (gimple_call_fndecl (stmt)
+	  != builtin_decl_implicit (BUILT_IN_TSAN_INIT)))
+    return true;
+  else if (is_gimple_assign (stmt))
+    {
+      if (gimple_store_p (stmt))
+	{
+	  lhs = gimple_assign_lhs (stmt);
+	  instrumented = instrument_expr (gsi, lhs, true);
+	}
+      if (gimple_assign_load_p (stmt))
+	{
+	  rhs = gimple_assign_rhs1 (stmt);
+	  instrumented = instrument_expr (gsi, rhs, false);
+	}
+    }
+  return instrumented;
+}
+
+/* Instruments all interesting memory accesses in the current function.
+ * Return true if func entry/exit should be instrumented. */
+
+static bool
+instrument_memory_accesses (void)
+{
+  basic_block bb;
+  gimple_stmt_iterator gsi;
+  bool fentry_exit_instrument = false;
+
+  FOR_EACH_BB (bb)
+    for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+      fentry_exit_instrument |= instrument_gimple (gsi);
+  return fentry_exit_instrument;
+}
+
+/* Instruments function entry.  */
+
+static void
+instrument_func_entry (void)
+{
+  basic_block succ_bb;
+  gimple_stmt_iterator gsi;
+  tree ret_addr, builtin_decl;
+  gimple g;
+
+  succ_bb = single_succ (ENTRY_BLOCK_PTR);
+  gsi = gsi_after_labels (succ_bb);
+
+  builtin_decl = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
+  g = gimple_build_call (builtin_decl, 1, integer_zero_node);
+  ret_addr = make_ssa_name (ptr_type_node, NULL);
+  gimple_call_set_lhs (g, ret_addr);
+  gimple_set_location (g, cfun->function_start_locus);
+  gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+
+  builtin_decl =  builtin_decl_implicit (BUILT_IN_TSAN_FUNC_ENTRY);
+  g = gimple_build_call (builtin_decl, 1, ret_addr);
+  gimple_set_location (g, cfun->function_start_locus);
+  gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+}
+
+/* Instruments function exits.  */
+
+static void
+instrument_func_exit (void)
+{
+  location_t loc;
+  basic_block exit_bb;
+  gimple_stmt_iterator gsi;
+  gimple stmt, g;
+  tree builtin_decl;
+  edge e;
+  edge_iterator ei;
+
+  /* Find all function exits.  */
+  exit_bb = EXIT_BLOCK_PTR;
+  FOR_EACH_EDGE (e, ei, exit_bb->preds)
+    {
+      gsi = gsi_last_bb (e->src);
+      stmt = gsi_stmt (gsi);
+      gcc_assert (gimple_code (stmt) == GIMPLE_RETURN);
+      loc = gimple_location (stmt);
+      builtin_decl = builtin_decl_implicit (BUILT_IN_TSAN_FUNC_EXIT);
+      g = gimple_build_call (builtin_decl, 0);
+      gimple_set_location (g, loc);
+      gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+    }
+}
+
+/* ThreadSanitizer instrumentation pass.  */
+
+static unsigned
+tsan_pass (void)
+{
+  if (instrument_memory_accesses ())
+    {
+      instrument_func_entry ();
+      instrument_func_exit ();
+    }
+  return 0;
+}
+
+/* The pass's gate.  */
+
+static bool
+tsan_gate (void)
+{
+  return flag_tsan != 0
+	 && builtin_decl_implicit_p (BUILT_IN_TSAN_INIT);
+}
+
+/* Inserts __tsan_init () into the list of CTORs.  */
+
+void
+tsan_finish_file (void)
+{
+  tree ctor_statements;
+  tree init_decl;
+
+  ctor_statements = NULL_TREE;
+  init_decl = builtin_decl_implicit (BUILT_IN_TSAN_INIT);
+  append_to_statement_list (build_call_expr (init_decl, 0),
+			    &ctor_statements);
+  cgraph_build_static_cdtor ('I', ctor_statements,
+			     MAX_RESERVED_INIT_PRIORITY - 1);
+}
+
+/* The pass descriptor.  */
+
+struct gimple_opt_pass pass_tsan =
+{
+ {
+  GIMPLE_PASS,
+  "tsan",				/* name  */
+  OPTGROUP_NONE,			/* optinfo_flags */
+  tsan_gate,				/* gate  */
+  tsan_pass,				/* execute  */
+  NULL,					/* sub  */
+  NULL,					/* next  */
+  0,					/* static_pass_number  */
+  TV_NONE,				/* tv_id  */
+  PROP_ssa | PROP_cfg,			/* properties_required  */
+  0,					/* properties_provided  */
+  0,					/* properties_destroyed  */
+  0,					/* todo_flags_start  */
+  TODO_verify_all | TODO_update_ssa
+  | TODO_update_address_taken		/* todo_flags_finish  */
+ }
+};
+
+static bool
+tsan_gate_O0 (void)
+{
+  return flag_tsan != 0 && !optimize
+	 && builtin_decl_implicit_p (BUILT_IN_TSAN_INIT);
+}
+
+struct gimple_opt_pass pass_tsan_O0 =
+{
+ {
+  GIMPLE_PASS,
+  "tsan0",				/* name  */
+  OPTGROUP_NONE,			/* optinfo_flags */
+  tsan_gate_O0,				/* gate  */
+  tsan_pass,				/* execute  */
+  NULL,					/* sub  */
+  NULL,					/* next  */
+  0,					/* static_pass_number  */
+  TV_NONE,				/* tv_id  */
+  PROP_ssa | PROP_cfg,			/* properties_required  */
+  0,					/* properties_provided  */
+  0,					/* properties_destroyed  */
+  0,					/* todo_flags_start  */
+  TODO_verify_all | TODO_update_ssa
+  | TODO_update_address_taken		/* todo_flags_finish  */
+ }
+};
Index: gcc/tsan.h
===================================================================
--- gcc/tsan.h	(revision 0)
+++ gcc/tsan.h	(revision 0)
@@ -0,0 +1,26 @@ 
+/* ThreadSanitizer, a data race detector.
+   Copyright (C) 2011, 2012 Free Software Foundation, Inc.
+   Contributed by Dmitry Vyukov <dvyukov@google.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef TREE_TSAN
+#define TREE_TSAN
+
+extern void tsan_finish_file (void);
+
+#endif /* TREE_TSAN */
Index: gcc/common.opt
===================================================================
--- gcc/common.opt	(revision 193702)
+++ gcc/common.opt	(working copy)
@@ -844,6 +844,10 @@  fsanitize=address
 Common Report Var(flag_asan)
 Enable AddressSanitizer, a memory error detector
 
+fsanitize=thread
+Common Report Var(flag_tsan)
+Enable ThreadSanitizer, a data race detector
+
 fasynchronous-unwind-tables
 Common Report Var(flag_asynchronous_unwind_tables) Optimization
 Generate unwind tables that are exact at each instruction boundary
@@ -2519,6 +2523,9 @@  Driver
 static-libasan
 Driver
 
+static-libtsan
+Driver
+
 symbolic
 Driver
 
Index: gcc/toplev.c
===================================================================
--- gcc/toplev.c	(revision 193702)
+++ gcc/toplev.c	(working copy)
@@ -73,6 +73,7 @@  along with GCC; see the file COPYING3.
 #include "alloc-pool.h"
 #include "tree-mudflap.h"
 #include "asan.h"
+#include "tsan.h"
 #include "gimple.h"
 #include "tree-ssa-alias.h"
 #include "plugin.h"
@@ -575,6 +576,9 @@  compile_file (void)
       if (flag_asan)
         asan_finish_file ();
 
+      if (flag_tsan)
+	tsan_finish_file ();
+
       output_shared_constant_pool ();
       output_object_blocks ();
       finish_tm_clone_pairs ();
Index: gcc/builtins.def
===================================================================
--- gcc/builtins.def	(revision 193702)
+++ gcc/builtins.def	(working copy)
@@ -149,6 +149,15 @@  along with GCC; see the file COPYING3.
   DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE,    \
 	       true, true, true, ATTRS, false, flag_tm)
 
+/* Builtin used by the implementation of libsanitizer. These
+   functions are mapped to the actual implementation of the 
+   libtsan library. */
+#undef DEF_SANITIZER_BUILTIN
+#define DEF_SANITIZER_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
+  DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE,    \
+	       true, true, true, ATTRS, true, \
+	       flag_tsan)
+
 /* Define an attribute list for math functions that are normally
    "impure" because some of them may write into global memory for
    `errno'.  If !flag_errno_math they are instead "const".  */
@@ -825,3 +834,7 @@  DEF_GCC_BUILTIN (BUILT_IN_LINE, "LINE",
 
 /* GTM builtins. */
 #include "gtm-builtins.def"
+
+/* Sanitizer builtins. */
+#include "sanitizer.def"
+