diff options
author | Richard Henderson <rth@redhat.com> | 2014-02-20 09:43:53 -0800 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2014-02-20 09:43:53 -0800 |
commit | 672ce9397b78c077e21d785a2ddf9fffd51a1952 (patch) | |
tree | 8ec4b08823b9b5486cecde9c93f376b7f59cf42e /gcc/builtins.c | |
parent | 95ce7613d537f5a3e9e36da0ca6aa752f60da8e0 (diff) | |
download | gcc-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.c | 19 |
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; } |