Commit 5ba4a08c by Jakub Jelinek Committed by Jakub Jelinek

re PR sanitizer/68260 (false positive with tsan)

	PR sanitizer/68260
	* tsan.c: Include target.h.
	(enum tsan_atomic_action): Add bool_clear and bool_test_and_set.
	(BOOL_CLEAR, BOOL_TEST_AND_SET): Define.
	(tsan_atomic_table): Add BUILT_IN_ATOMIC_CLEAR and
	BUILT_IN_ATOMIC_TEST_AND_SET entries.
	(instrument_builtin_call): Handle bool_clear and bool_test_and_set.

	* c-c++-common/tsan/pr68260.c: New test.

From-SVN: r240129
parent 130ffea0
2016-09-14 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/68260
* tsan.c: Include target.h.
(enum tsan_atomic_action): Add bool_clear and bool_test_and_set.
(BOOL_CLEAR, BOOL_TEST_AND_SET): Define.
(tsan_atomic_table): Add BUILT_IN_ATOMIC_CLEAR and
BUILT_IN_ATOMIC_TEST_AND_SET entries.
(instrument_builtin_call): Handle bool_clear and bool_test_and_set.
2016-09-14 Bernd Edlinger <bernd.edlinger@hotmail.de> 2016-09-14 Bernd Edlinger <bernd.edlinger@hotmail.de>
Martin Liska <mliska@suse.cz> Martin Liska <mliska@suse.cz>
......
2016-09-14 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/68260
* c-c++-common/tsan/pr68260.c: New test.
2016-09-13 Joe Seymour <joe.s@somniumtech.com> 2016-09-13 Joe Seymour <joe.s@somniumtech.com>
PR target/70713 PR target/70713
......
/* PR sanitizer/68260 */
#include <pthread.h>
#include <stdbool.h>
bool lock;
int counter;
void *
tf (void *arg)
{
(void) arg;
while (__atomic_test_and_set (&lock, __ATOMIC_ACQUIRE))
;
++counter;
__atomic_clear (&lock, __ATOMIC_RELEASE);
return (void *) 0;
}
int
main ()
{
pthread_t thr;
pthread_create (&thr, 0, tf, 0);
tf ((void *) 0);
pthread_join (thr, 0);
return 0;
}
...@@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see
#include "tsan.h" #include "tsan.h"
#include "asan.h" #include "asan.h"
#include "builtins.h" #include "builtins.h"
#include "target.h"
/* Number of instrumented memory accesses in the current function. */ /* Number of instrumented memory accesses in the current function. */
...@@ -240,7 +241,8 @@ instrument_expr (gimple_stmt_iterator gsi, tree expr, bool is_write) ...@@ -240,7 +241,8 @@ instrument_expr (gimple_stmt_iterator gsi, tree expr, bool is_write)
enum tsan_atomic_action enum tsan_atomic_action
{ {
check_last, add_seq_cst, add_acquire, weak_cas, strong_cas, check_last, add_seq_cst, add_acquire, weak_cas, strong_cas,
bool_cas, val_cas, lock_release, fetch_op, fetch_op_seq_cst bool_cas, val_cas, lock_release, fetch_op, fetch_op_seq_cst,
bool_clear, bool_test_and_set
}; };
/* Table how to map sync/atomic builtins to their corresponding /* Table how to map sync/atomic builtins to their corresponding
...@@ -274,6 +276,10 @@ static const struct tsan_map_atomic ...@@ -274,6 +276,10 @@ static const struct tsan_map_atomic
TRANSFORM (fcode, tsan_fcode, fetch_op, code) TRANSFORM (fcode, tsan_fcode, fetch_op, code)
#define FETCH_OPS(fcode, tsan_fcode, code) \ #define FETCH_OPS(fcode, tsan_fcode, code) \
TRANSFORM (fcode, tsan_fcode, fetch_op_seq_cst, code) TRANSFORM (fcode, tsan_fcode, fetch_op_seq_cst, code)
#define BOOL_CLEAR(fcode, tsan_fcode) \
TRANSFORM (fcode, tsan_fcode, bool_clear, ERROR_MARK)
#define BOOL_TEST_AND_SET(fcode, tsan_fcode) \
TRANSFORM (fcode, tsan_fcode, bool_test_and_set, ERROR_MARK)
CHECK_LAST (ATOMIC_LOAD_1, TSAN_ATOMIC8_LOAD), CHECK_LAST (ATOMIC_LOAD_1, TSAN_ATOMIC8_LOAD),
CHECK_LAST (ATOMIC_LOAD_2, TSAN_ATOMIC16_LOAD), CHECK_LAST (ATOMIC_LOAD_2, TSAN_ATOMIC16_LOAD),
...@@ -463,7 +469,11 @@ static const struct tsan_map_atomic ...@@ -463,7 +469,11 @@ static const struct tsan_map_atomic
LOCK_RELEASE (SYNC_LOCK_RELEASE_2, TSAN_ATOMIC16_STORE), LOCK_RELEASE (SYNC_LOCK_RELEASE_2, TSAN_ATOMIC16_STORE),
LOCK_RELEASE (SYNC_LOCK_RELEASE_4, TSAN_ATOMIC32_STORE), LOCK_RELEASE (SYNC_LOCK_RELEASE_4, TSAN_ATOMIC32_STORE),
LOCK_RELEASE (SYNC_LOCK_RELEASE_8, TSAN_ATOMIC64_STORE), LOCK_RELEASE (SYNC_LOCK_RELEASE_8, TSAN_ATOMIC64_STORE),
LOCK_RELEASE (SYNC_LOCK_RELEASE_16, TSAN_ATOMIC128_STORE) LOCK_RELEASE (SYNC_LOCK_RELEASE_16, TSAN_ATOMIC128_STORE),
BOOL_CLEAR (ATOMIC_CLEAR, TSAN_ATOMIC8_STORE),
BOOL_TEST_AND_SET (ATOMIC_TEST_AND_SET, TSAN_ATOMIC8_EXCHANGE)
}; };
/* Instrument an atomic builtin. */ /* Instrument an atomic builtin. */
...@@ -615,6 +625,57 @@ instrument_builtin_call (gimple_stmt_iterator *gsi) ...@@ -615,6 +625,57 @@ instrument_builtin_call (gimple_stmt_iterator *gsi)
build_int_cst (NULL_TREE, build_int_cst (NULL_TREE,
MEMMODEL_RELEASE)); MEMMODEL_RELEASE));
return; return;
case bool_clear:
case bool_test_and_set:
if (BOOL_TYPE_SIZE != 8)
{
decl = NULL_TREE;
for (j = 1; j < 5; j++)
if (BOOL_TYPE_SIZE == (8 << j))
{
enum built_in_function tsan_fcode
= (enum built_in_function)
(tsan_atomic_table[i].tsan_fcode + j);
decl = builtin_decl_implicit (tsan_fcode);
break;
}
if (decl == NULL_TREE)
return;
}
last_arg = gimple_call_arg (stmt, num - 1);
if (!tree_fits_uhwi_p (last_arg)
|| memmodel_base (tree_to_uhwi (last_arg)) >= MEMMODEL_LAST)
return;
t = TYPE_ARG_TYPES (TREE_TYPE (decl));
t = TREE_VALUE (TREE_CHAIN (t));
if (tsan_atomic_table[i].action == bool_clear)
{
update_gimple_call (gsi, decl, 3, gimple_call_arg (stmt, 0),
build_int_cst (t, 0), last_arg);
return;
}
t = build_int_cst (t, targetm.atomic_test_and_set_trueval);
update_gimple_call (gsi, decl, 3, gimple_call_arg (stmt, 0),
t, last_arg);
stmt = gsi_stmt (*gsi);
lhs = gimple_call_lhs (stmt);
if (lhs == NULL_TREE)
return;
if (targetm.atomic_test_and_set_trueval != 1
|| !useless_type_conversion_p (TREE_TYPE (lhs),
TREE_TYPE (t)))
{
tree new_lhs = make_ssa_name (TREE_TYPE (t));
gimple_call_set_lhs (stmt, new_lhs);
if (targetm.atomic_test_and_set_trueval != 1)
g = gimple_build_assign (lhs, NE_EXPR, new_lhs,
build_int_cst (TREE_TYPE (t), 0));
else
g = gimple_build_assign (lhs, NOP_EXPR, new_lhs);
gsi_insert_after (gsi, g, GSI_NEW_STMT);
update_stmt (stmt);
}
return;
default: default:
continue; continue;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment