tsan: Add param to disable func-entry-exit instrumentation

Adds param tsan-instrument-func-entry-exit, which controls if
__tsan_func_{entry,exit} calls should be emitted or not. The default
behaviour is to emit the calls.

This may be required by alternative race detection runtimes. One such
runtime is the Kernel Concurrency Sanitizer (KCSAN):

	https://github.com/google/ktsan/wiki/KCSAN

After this change, GCC should satisfy all requirements for KCSAN:

	https://lore.kernel.org/lkml/20200515150338.190344-7-elver@google.com/

gcc/ChangeLog:

	* gimplify.c (gimplify_function_tree): Optimize and do not emit
	IFN_TSAN_FUNC_EXIT in a finally block if we do not need it.
	* params.opt: Add --param=tsan-instrument-func-entry-exit=.
	* tsan.c (instrument_memory_accesses): Make
	fentry_exit_instrument bool depend on new param.

gcc/testsuite/ChangeLog:

	* c-c++-common/tsan/func_entry_exit.c: New test.
	* c-c++-common/tsan/func_entry_exit_disabled.c: New test.
This commit is contained in:
Marco Elver 2020-06-10 16:21:21 +02:00
parent 1432bc3681
commit 06712fc68d
5 changed files with 67 additions and 2 deletions

View file

@ -15011,7 +15011,8 @@ gimplify_function_tree (tree fndecl)
bind = new_bind;
}
if (sanitize_flags_p (SANITIZE_THREAD))
if (sanitize_flags_p (SANITIZE_THREAD)
&& param_tsan_instrument_func_entry_exit)
{
gcall *call = gimple_build_call_internal (IFN_TSAN_FUNC_EXIT, 0);
gimple *tf = gimple_build_try (seq, call, GIMPLE_TRY_FINALLY);

View file

@ -912,6 +912,10 @@ Set the maximum number of instructions executed in parallel in reassociated tree
Common Joined UInteger Var(param_tsan_distinguish_volatile) IntegerRange(0, 1) Param
Emit special instrumentation for accesses to volatiles.
-param=tsan-instrument-func-entry-exit=
Common Joined UInteger Var(param_tsan_instrument_func_entry_exit) Init(1) IntegerRange(0, 1) Param
Emit instrumentation calls to __tsan_func_entry() and __tsan_func_exit().
-param=uninit-control-dep-attempts=
Common Joined UInteger Var(param_uninit_control_dep_attempts) Init(1000) IntegerRange(1, 65536) Param Optimization
Maximum number of nested calls to search for control dependencies during uninitialized variable analysis.

View file

@ -0,0 +1,29 @@
/* { dg-do compile } */
/* { dg-options "-fdump-tree-gimple -fdump-tree-optimized" } */
int x;
__attribute__((noinline))
void fn1(void)
{
x++;
}
__attribute__((noinline))
void fn2(void)
{
fn1();
}
__attribute__((noinline))
int main(int argc, char *argv[])
{
fn1();
fn2();
return 0;
}
// { dg-final { scan-tree-dump "TSAN_FUNC_EXIT" "gimple" } }
// { dg-final { scan-tree-dump-times "__tsan_func_entry" 3 "optimized" } }
// { dg-final { scan-tree-dump-times "__tsan_func_exit" 3 "optimized" } }
// { dg-final { scan-tree-dump "__tsan_write" "optimized" } }

View file

@ -0,0 +1,29 @@
/* { dg-do compile } */
/* { dg-options "--param=tsan-instrument-func-entry-exit=0 -fdump-tree-gimple -fdump-tree-optimized" } */
int x;
__attribute__((noinline))
void fn1(void)
{
x++;
}
__attribute__((noinline))
void fn2(void)
{
fn1();
}
__attribute__((noinline))
int main(int argc, char *argv[])
{
fn1();
fn2();
return 0;
}
// { dg-final { scan-tree-dump-not "TSAN_FUNC_EXIT" "gimple" } }
// { dg-final { scan-tree-dump-not "__tsan_func_entry" "optimized" } }
// { dg-final { scan-tree-dump-not "__tsan_func_exit" "optimized" } }
// { dg-final { scan-tree-dump "__tsan_write" "optimized" } }

View file

@ -804,7 +804,9 @@ instrument_memory_accesses (bool *cfg_changed)
func_exit_seen = true;
}
else
fentry_exit_instrument |= instrument_gimple (&gsi);
fentry_exit_instrument
|= (instrument_gimple (&gsi)
&& param_tsan_instrument_func_entry_exit);
}
if (gimple_purge_dead_eh_edges (bb))
*cfg_changed = true;