On Thu, 19 Mar 2015, Jakub Jelinek wrote:

> 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?

Ok.

Thanks,
Richard.

> 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
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Jennifer Guild,
Dilip Upmanyu, Graham Norton HRB 21284 (AG Nuernberg)

Reply via email to