diff options
author | Marco Elver <elver@google.com> | 2020-06-09 15:15:39 +0200 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2020-06-09 21:22:24 +0200 |
commit | ab2789ec507a94f1a75a6534bca51c7b39037ce0 (patch) | |
tree | 7b9e508583db3280549c554e3cbb51ceb877ccdb /gcc/tsan.c | |
parent | 6e52b2297ecce1243c00d76b3f079b71016b8ffa (diff) | |
download | gcc-ab2789ec507a94f1a75a6534bca51c7b39037ce0.zip gcc-ab2789ec507a94f1a75a6534bca51c7b39037ce0.tar.gz gcc-ab2789ec507a94f1a75a6534bca51c7b39037ce0.tar.bz2 |
tsan: Add optional support for distinguishing volatiles
Add support to optionally emit different instrumentation for accesses to
volatile variables. While the default TSAN runtime likely will never
require this feature, other runtimes for different environments that
have subtly different memory models or assumptions may require
distinguishing volatiles.
One such environment are OS kernels, where volatile is still used in
various places, and often declare volatile to be appropriate even in
multi-threaded contexts. One such example is the Linux kernel, which
implements various synchronization primitives using volatile
(READ_ONCE(), WRITE_ONCE()).
Here the Kernel Concurrency Sanitizer (KCSAN), is a runtime that uses
TSAN instrumentation but otherwise implements a very different approach
to race detection from TSAN:
https://github.com/google/ktsan/wiki/KCSAN
Due to recent changes in requirements by the Linux kernel, KCSAN
requires that the compiler supports tsan-distinguish-volatile (among
several new requirements):
https://lore.kernel.org/lkml/20200521142047.169334-7-elver@google.com/
gcc/
* params.opt: Define --param=tsan-distinguish-volatile=[0,1].
* sanitizer.def (BUILT_IN_TSAN_VOLATILE_READ1): Define new
builtin for volatile instrumentation of reads/writes.
(BUILT_IN_TSAN_VOLATILE_READ2): Likewise.
(BUILT_IN_TSAN_VOLATILE_READ4): Likewise.
(BUILT_IN_TSAN_VOLATILE_READ8): Likewise.
(BUILT_IN_TSAN_VOLATILE_READ16): Likewise.
(BUILT_IN_TSAN_VOLATILE_WRITE1): Likewise.
(BUILT_IN_TSAN_VOLATILE_WRITE2): Likewise.
(BUILT_IN_TSAN_VOLATILE_WRITE4): Likewise.
(BUILT_IN_TSAN_VOLATILE_WRITE8): Likewise.
(BUILT_IN_TSAN_VOLATILE_WRITE16): Likewise.
* tsan.c (get_memory_access_decl): Argument if access is
volatile. If param tsan-distinguish-volatile is non-zero, and
access if volatile, return volatile instrumentation decl.
(instrument_expr): Check if access is volatile.
gcc/testsuite/
* c-c++-common/tsan/volatile.c: New test.
Diffstat (limited to 'gcc/tsan.c')
-rw-r--r-- | gcc/tsan.c | 29 |
1 files changed, 17 insertions, 12 deletions
@@ -52,25 +52,29 @@ along with GCC; see the file COPYING3. If not see void __tsan_read/writeX (void *addr); */ static tree -get_memory_access_decl (bool is_write, unsigned size) +get_memory_access_decl (bool is_write, unsigned size, bool volatilep) { enum built_in_function fcode; + int pos; if (size <= 1) - fcode = is_write ? BUILT_IN_TSAN_WRITE1 - : BUILT_IN_TSAN_READ1; + pos = 0; else if (size <= 3) - fcode = is_write ? BUILT_IN_TSAN_WRITE2 - : BUILT_IN_TSAN_READ2; + pos = 1; else if (size <= 7) - fcode = is_write ? BUILT_IN_TSAN_WRITE4 - : BUILT_IN_TSAN_READ4; + pos = 2; else if (size <= 15) - fcode = is_write ? BUILT_IN_TSAN_WRITE8 - : BUILT_IN_TSAN_READ8; + pos = 3; + else + pos = 4; + + if (param_tsan_distinguish_volatile && volatilep) + fcode = is_write ? BUILT_IN_TSAN_VOLATILE_WRITE1 + : BUILT_IN_TSAN_VOLATILE_READ1; else - fcode = is_write ? BUILT_IN_TSAN_WRITE16 - : BUILT_IN_TSAN_READ16; + fcode = is_write ? BUILT_IN_TSAN_WRITE1 + : BUILT_IN_TSAN_READ1; + fcode = (built_in_function)(fcode + pos); return builtin_decl_implicit (fcode); } @@ -204,7 +208,8 @@ instrument_expr (gimple_stmt_iterator gsi, tree expr, bool is_write) g = gimple_build_call (builtin_decl, 2, expr_ptr, size_int (size)); } else if (rhs == NULL) - g = gimple_build_call (get_memory_access_decl (is_write, size), + g = gimple_build_call (get_memory_access_decl (is_write, size, + TREE_THIS_VOLATILE (expr)), 1, expr_ptr); else { |