Hi!

This patch fixes the other part of the PR.  On this testcase, ICF creates
a thunk and sets gimple_call_set_tail true on the call in there.  No
TSAN_FUNC_EXIT internal call is added, which isn't a big deal, tsan pass
has code to add it if there are none.  But, nothing was clearing the tail
call flag when this was done, and with -fsanitize=thread in sanitized
functions all functions that call other functions must start with the
__tsan_func_entry call and call __tsan_func_exit at the end (unless they are
noreturn).  Thus, we can only tail call __tsan_func_exit in instrumented
functions.  The patch clears the tail call flag on all calls but
TSAN_FUNC_EXIT (for which instrument_gimple isn't called at all).

Regtested on x86_64-linux, ok for trunk?

2015-03-19  Bernd Edlinger  <bernd.edlin...@hotmail.de>
            Jakub Jelinek  <ja...@redhat.com>

        PR sanitizer/65400
        * tsan.c (instrument_gimple): Clear tail call flag on
        calls.

        * c-c++-common/tsan/pr65400-3.c: New test.

--- gcc/tsan.c.jj       2015-01-19 09:31:24.000000000 +0100
+++ gcc/tsan.c  2015-03-19 09:51:39.086804965 +0100
@@ -680,6 +680,10 @@ instrument_gimple (gimple_stmt_iterator
       && (gimple_call_fndecl (stmt)
          != builtin_decl_implicit (BUILT_IN_TSAN_INIT)))
     {
+      /* All functions with function call will have exit instrumented,
+        therefore no function calls other than __tsan_func_exit
+        shall appear in the functions.  */
+      gimple_call_set_tail (as_a <gcall *> (stmt), false);
       if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
        instrument_builtin_call (gsi);
       return true;
--- gcc/testsuite/c-c++-common/tsan/pr65400-3.c.jj      2015-03-19 
10:07:15.453302478 +0100
+++ gcc/testsuite/c-c++-common/tsan/pr65400-3.c 2015-03-19 10:27:11.941515580 
+0100
@@ -0,0 +1,75 @@
+/* PR sanitizer/65400 */
+/* { dg-shouldfail "tsan" } */
+/* { dg-additional-options "-fno-omit-frame-pointer -ldl" } */
+
+#include <pthread.h>
+#include "tsan_barrier.h"
+
+static pthread_barrier_t barrier;
+int v;
+
+int
+fn1 (int a, int b, int c)
+{
+  int r = (a ^ b) % c;
+  r = r * a * b + c;
+  r = (r ^ b) % c;
+  return r;
+}
+
+int
+fn2 (int a, int b, int c)
+{
+  int r = (a ^ b) % c;
+  r = r * a * b + c;
+  r = (r ^ b) % c;
+  return r;
+}
+
+__attribute__((noinline, noclone)) void
+foo (void)
+{
+  barrier_wait (&barrier);
+  barrier_wait (&barrier);
+  v++;
+}
+
+__attribute__((noinline, noclone)) void
+bar (void)
+{
+  int (*fna) (int, int, int);
+  int (*fnb) (int, int, int);
+  int i;
+  asm ("" : "=g" (fna) : "0" (fn1));
+  asm ("" : "=g" (fnb) : "0" (fn2));
+  for (i = 0; i < 128; i++)
+    {
+      fna (0, 0, i + 1);
+      fnb (0, 0, i + 1);
+    }
+  foo ();
+}
+
+__attribute__((noinline, noclone)) void *
+tf (void *arg)
+{
+  (void) arg;
+  bar ();
+  return NULL;
+}
+
+int
+main ()
+{
+  pthread_t th;
+  barrier_init (&barrier, 2);
+  if (pthread_create (&th, NULL, tf, NULL))
+    return 0;
+  barrier_wait (&barrier);
+  v++;
+  barrier_wait (&barrier);
+  pthread_join (th, NULL);
+  return 0;
+}
+
+/* { dg-output "WARNING: ThreadSanitizer: data race.*#2 _?tf" } */

        Jakub

Reply via email to