aboutsummaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2014-02-20 09:43:53 -0800
committerRichard Henderson <rth@gcc.gnu.org>2014-02-20 09:43:53 -0800
commit672ce9397b78c077e21d785a2ddf9fffd51a1952 (patch)
tree8ec4b08823b9b5486cecde9c93f376b7f59cf42e /gcc/builtins.c
parent95ce7613d537f5a3e9e36da0ca6aa752f60da8e0 (diff)
downloadgcc-672ce9397b78c077e21d785a2ddf9fffd51a1952.zip
gcc-672ce9397b78c077e21d785a2ddf9fffd51a1952.tar.gz
gcc-672ce9397b78c077e21d785a2ddf9fffd51a1952.tar.bz2
re PR c++/60272 (atomic<>::compare_exchange_weak has spurious store and can cause race conditions)
PR c++/60272 gcc/ * builtins.c (expand_builtin_atomic_compare_exchange): Conditionalize on failure the store back into EXPECT. libatomic/ * cas_n.c (libat_compare_exchange): Conditionalize on failure the store back to EPTR. From-SVN: r207966
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r--gcc/builtins.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index f5f55bf..09fefe50 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -5292,7 +5292,7 @@ static rtx
expand_builtin_atomic_compare_exchange (enum machine_mode mode, tree exp,
rtx target)
{
- rtx expect, desired, mem, oldval;
+ rtx expect, desired, mem, oldval, label;
enum memmodel success, failure;
tree weak;
bool is_weak;
@@ -5330,14 +5330,23 @@ expand_builtin_atomic_compare_exchange (enum machine_mode mode, tree exp,
if (tree_fits_shwi_p (weak) && tree_to_shwi (weak) != 0)
is_weak = true;
+ if (target == const0_rtx)
+ target = NULL;
oldval = expect;
- if (!expand_atomic_compare_and_swap ((target == const0_rtx ? NULL : &target),
- &oldval, mem, oldval, desired,
+
+ if (!expand_atomic_compare_and_swap (&target, &oldval, mem, oldval, desired,
is_weak, success, failure))
return NULL_RTX;
- if (oldval != expect)
- emit_move_insn (expect, oldval);
+ /* Conditionally store back to EXPECT, lest we create a race condition
+ with an improper store to memory. */
+ /* ??? With a rearrangement of atomics at the gimple level, we can handle
+ the normal case where EXPECT is totally private, i.e. a register. At
+ which point the store can be unconditional. */
+ label = gen_label_rtx ();
+ emit_cmp_and_jump_insns (target, const0_rtx, NE, NULL, VOIDmode, 1, label);
+ emit_move_insn (expect, oldval);
+ emit_label (label);
return target;
}