This page is about ThreadSanitizer version 1. For the new (and better supported) version go to http://code.google.com/p/thread-sanitizer
ThreadSanitizer paper was presented at WBIA'09: PDF
Introduction
ThreadSanitizer (aka tsan, not "Thread Sanitizer") is a data race detector for C/C++ programs.
The Linux and Mac versions are based on Valgrind.
The Windows version is based on PIN.
ThreadSanitizer is similar to Helgrind in many ways, but it also has several differences.
The instrumentation code is partially taken from Helgrind; but the race detection machinery is absolutely new (the code is written in C++).
The source code is published under BSD-like licence (except for valgrind-related modules which are GPLv2+).
ThreadSanitizer is being actively developed and used at Google.
See also:
Contacts: data-race-test(#)googlegroups.com
How to get
You may download the pre-built binaries from the ThreadSanitizerBuildBot
If you want to build ThreadSanitizer youself, refer to BuildingThreadSanitizer.
ThreadSanitizer is supported on the following platforms:
- Linux x86_64 and x86. Tested on Ubuntu 8.04 and 9.10.
- Darwin i386 (MacOS X 10.5).
- Windows i386 (Tested on 7, Vista and XP)
- In progress:
Using ThreadSanitizer
on Linux and Mac
Just like any other valgrind-based tool:
valgrind [valgrind options] --tool=tsan [--tsan-options] your/program [program options]
or (if you are using the self-contained binary):
tsan.sh [--tsan-options] your/program [program options]
on Windows
Run ThreadSanitizer like this (assuming you unpacked it in C:\):
C:\tsan-x86-windows\tsan.bat [--tsan-options] -- your\program.exe [program options]
Command line flags
| Flag name | default | description |
| Analysis sensitivity flags: | | ThreadSanitizer can work in different modes that affect accuracy (number of detected bugs, number of false reports) and speed. |
| --keep-history=0|1 | 1 | Keep the history of the previous accesses. By default, the stack traces of concurrent accesses are almost precise. Setting this option to zero will make the tool run 10%-30% faster, but the concurrent accesses will not be printed. Use --keep-history=0 in continuous builds, and --keep-history=1 when analyzing reports. |
| --hybrid=yes|no | no | Act as a hybrid detector (PureHappensBeforeVsHybrid) |
| --free-is-write=yes|no | no | Treat free()/delete/... as a memory access (write), thus reporting races between free() and other memory accesses. On by default since r2273 |
| Interface flags: | | Flags that affect the generated output. |
| --log-file=filename | "" | Dump the output to filename; if empty dump to stderr |
| --color | no | Add colors to the output using ANSI escape codes. |
| --show-pc | no | Show pc (program counter) in the stack traces. |
| --announce-threads | no | Show the stack traces of thread creation . |
| --fullpath-after=file_prefix | | Remove "^.*file_prefix" from the printed file names. You may pass this flag several times. |
| Resource usage | | |
| --max-sid | 8388608 (2^23) | This number of unique Segment IDs. This reflects the amount of memory allocated by ThreadSanitizer at startup. One Segment ID requires ~100 bytes of memory, so by default approximately 800M of memory is allocated. The higher this number the better. This number can not be very small (<100000). The upper bound depends on the amount of available memory. |
| --num-callers | 12 | The size of the stack trace printed for the current access. Increasing this number does not affect performance. |
| --num-callers-in-history | 10 | The size of the stack trace stored for the concurrent accesses. Increasing this number improves the reports but increases the memory footprint and slows down the execution. |
| Profiling | | |
| --sample-events=N | 0 | If non zero, ThreadSanitizer will sample one of 2^N events and at the end print the event profile. This options could be used together with ThreadSanitizerIgnores. |
Screenshot
ThreadSanitizer's output viewed in vim with syntax highlightning and the source code in the second window:
Ok you can do this in emacs too. Just insert the following snippet in your .emacs file
(setq tsan-log '((tsan-log "^==[0-9]+== +\\#[0-9]+ +[^ ]+ \\([^:]+\\):\\([0-9]+\\)$" 1 2 nil nil))) (setq orig-compilation-error-regexp-alist (copy-alist compilation-error-regexp-alist)) (setq orig-compilation-error-regexp-alist-alist (copy-alist compilation-error-regexp-alist-alist)) (setq compilation-error-regexp-alist (append '(tsan-log) compilation-error-regexp-alist)) (setq compilation-error-regexp-alist-alist (append (copy-alist tsan-log) compilation-error-regexp-alist-alist))file:///home/jaonwkim/Desktop/p1.png
Next,
that should do it!
(require 'compile) (setq tsan-log '((tsan-log "^==[0-9]+== +\\#[0-9]+ +[^ ]+ \\([^:]+\\):\\([0-9]+\\)$" 1 2 nil nil))) (setq orig-compilation-error-regexp-alist (copy-alist compilation-error-regexp-alist)) (setq orig-compilation-error-regexp-alist-alist (copy-alist compilation-error-regexp-alist-alist)) (setq compilation-error-regexp-alist (append '(tsan-log) compilation-error-regexp-alist)) (setq compilation-error-regexp-alist-alist (append (copy-alist tsan-log) compilation-error-regexp-alist-alist))