1 | ThreadSanitizer |
2 | =============== |
3 | |
4 | Introduction |
5 | ------------ |
6 | |
7 | ThreadSanitizer is a tool that detects data races. It consists of a compiler |
8 | instrumentation module and a run-time library. Typical slowdown introduced by |
9 | ThreadSanitizer is about **5x-15x**. Typical memory overhead introduced by |
10 | ThreadSanitizer is about **5x-10x**. |
11 | |
12 | How to build |
13 | ------------ |
14 | |
15 | Build LLVM/Clang with `CMake <https://llvm.org/docs/CMake.html>`_. |
16 | |
17 | Supported Platforms |
18 | ------------------- |
19 | |
20 | ThreadSanitizer is supported on the following OS: |
21 | |
22 | * Android aarch64, x86_64 |
23 | * Darwin arm64, x86_64 |
24 | * FreeBSD |
25 | * Linux aarch64, x86_64, powerpc64, powerpc64le |
26 | * NetBSD |
27 | |
28 | Support for other 64-bit architectures is possible, contributions are welcome. |
29 | Support for 32-bit platforms is problematic and is not planned. |
30 | |
31 | Usage |
32 | ----- |
33 | |
34 | Simply compile and link your program with ``-fsanitize=thread``. To get a |
35 | reasonable performance add ``-O1`` or higher. Use ``-g`` to get file names |
36 | and line numbers in the warning messages. |
37 | |
38 | Example: |
39 | |
40 | .. code-block:: console |
41 | |
42 | % cat projects/compiler-rt/lib/tsan/lit_tests/tiny_race.c |
43 | #include <pthread.h> |
44 | int Global; |
45 | void *Thread1(void *x) { |
46 | Global = 42; |
47 | return x; |
48 | } |
49 | int main() { |
50 | pthread_t t; |
51 | pthread_create(&t, NULL, Thread1, NULL); |
52 | Global = 43; |
53 | pthread_join(t, NULL); |
54 | return Global; |
55 | } |
56 | |
57 | $ clang -fsanitize=thread -g -O1 tiny_race.c |
58 | |
59 | If a bug is detected, the program will print an error message to stderr. |
60 | Currently, ThreadSanitizer symbolizes its output using an external |
61 | ``addr2line`` process (this will be fixed in future). |
62 | |
63 | .. code-block:: bash |
64 | |
65 | % ./a.out |
66 | WARNING: ThreadSanitizer: data race (pid=19219) |
67 | Write of size 4 at 0x7fcf47b21bc0 by thread T1: |
68 | #0 Thread1 tiny_race.c:4 (exe+0x00000000a360) |
69 | |
70 | Previous write of size 4 at 0x7fcf47b21bc0 by main thread: |
71 | #0 main tiny_race.c:10 (exe+0x00000000a3b4) |
72 | |
73 | Thread T1 (running) created at: |
74 | #0 pthread_create tsan_interceptors.cc:705 (exe+0x00000000c790) |
75 | #1 main tiny_race.c:9 (exe+0x00000000a3a4) |
76 | |
77 | ``__has_feature(thread_sanitizer)`` |
78 | ------------------------------------ |
79 | |
80 | In some cases one may need to execute different code depending on whether |
81 | ThreadSanitizer is enabled. |
82 | :ref:`\_\_has\_feature <langext-__has_feature-__has_extension>` can be used for |
83 | this purpose. |
84 | |
85 | .. code-block:: c |
86 | |
87 | #if defined(__has_feature) |
88 | # if __has_feature(thread_sanitizer) |
89 | // code that builds only under ThreadSanitizer |
90 | # endif |
91 | #endif |
92 | |
93 | ``__attribute__((no_sanitize("thread")))`` |
94 | ----------------------------------------------- |
95 | |
96 | Some code should not be instrumented by ThreadSanitizer. One may use the |
97 | function attribute ``no_sanitize("thread")`` to disable instrumentation of plain |
98 | (non-atomic) loads/stores in a particular function. ThreadSanitizer still |
99 | instruments such functions to avoid false positives and provide meaningful stack |
100 | traces. This attribute may not be supported by other compilers, so we suggest |
101 | to use it together with ``__has_feature(thread_sanitizer)``. |
102 | |
103 | Blacklist |
104 | --------- |
105 | |
106 | ThreadSanitizer supports ``src`` and ``fun`` entity types in |
107 | :doc:`SanitizerSpecialCaseList`, that can be used to suppress data race reports |
108 | in the specified source files or functions. Unlike functions marked with |
109 | ``no_sanitize("thread")`` attribute, blacklisted functions are not instrumented |
110 | at all. This can lead to false positives due to missed synchronization via |
111 | atomic operations and missed stack frames in reports. |
112 | |
113 | Limitations |
114 | ----------- |
115 | |
116 | * ThreadSanitizer uses more real memory than a native run. At the default |
117 | settings the memory overhead is 5x plus 1Mb per each thread. Settings with 3x |
118 | (less accurate analysis) and 9x (more accurate analysis) overhead are also |
119 | available. |
120 | * ThreadSanitizer maps (but does not reserve) a lot of virtual address space. |
121 | This means that tools like ``ulimit`` may not work as usually expected. |
122 | * Libc/libstdc++ static linking is not supported. |
123 | * Non-position-independent executables are not supported. Therefore, the |
124 | ``fsanitize=thread`` flag will cause Clang to act as though the ``-fPIE`` |
125 | flag had been supplied if compiling without ``-fPIC``, and as though the |
126 | ``-pie`` flag had been supplied if linking an executable. |
127 | |
128 | Current Status |
129 | -------------- |
130 | |
131 | ThreadSanitizer is in beta stage. It is known to work on large C++ programs |
132 | using pthreads, but we do not promise anything (yet). C++11 threading is |
133 | supported with llvm libc++. The test suite is integrated into CMake build |
134 | and can be run with ``make check-tsan`` command. |
135 | |
136 | We are actively working on enhancing the tool --- stay tuned. Any help, |
137 | especially in the form of minimized standalone tests is more than welcome. |
138 | |
139 | More Information |
140 | ---------------- |
141 | `<https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual>`_ |
142 | |