tsan: Add param to disable func-entry-exit instrumentation
authorMarco Elver <elver@google.com>
Wed, 10 Jun 2020 14:21:21 +0000 (16:21 +0200)
committerMarco Elver <elver@google.com>
Fri, 12 Jun 2020 15:29:45 +0000 (17:29 +0200)
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.

gcc/gimplify.c
gcc/params.opt
gcc/testsuite/c-c++-common/tsan/func_entry_exit.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/tsan/func_entry_exit_disabled.c [new file with mode: 0644]
gcc/tsan.c

index e14932fafaf8e7a39e1069cf15b0ab4b66783a54..416fb609b940c2fd5c283228b8f348ea0429584a 100644 (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);
index 9b564bb046c5d129e0dce0a769382f8b6e4b0569..e29a44e7712b824a44ab04deddd09b1e8c7d1546 100644 (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.
diff --git a/gcc/testsuite/c-c++-common/tsan/func_entry_exit.c b/gcc/testsuite/c-c++-common/tsan/func_entry_exit.c
new file mode 100644 (file)
index 0000000..9c1b697
--- /dev/null
@@ -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" } }
diff --git a/gcc/testsuite/c-c++-common/tsan/func_entry_exit_disabled.c b/gcc/testsuite/c-c++-common/tsan/func_entry_exit_disabled.c
new file mode 100644 (file)
index 0000000..63cc73b
--- /dev/null
@@ -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" } }
index 447acccfafdce75c06f6b5e51b5e2334921c7edd..4d6223454b576eb0706b514a2493e48c20c94a15 100644 (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;