diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-02-20 17:43:53 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-02-20 17:43:53 +0000 |
commit | d86e37524da30190b22017cc46a278c3ebfceb5c (patch) | |
tree | 8ec4b08823b9b5486cecde9c93f376b7f59cf42e | |
parent | 73e15dfcff00049654d5f5eba0889e2a7d3d80cf (diff) | |
download | gcc-d86e37524da30190b22017cc46a278c3ebfceb5c.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@207966 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/builtins.c | 19 | ||||
-rw-r--r-- | libatomic/ChangeLog | 6 | ||||
-rw-r--r-- | libatomic/cas_n.c | 25 |
4 files changed, 38 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9333fb6804c..7161754b2b3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2014-02-20 Richard Henderson <rth@redhat.com> + + PR c++/60272 + * builtins.c (expand_builtin_atomic_compare_exchange): Conditionalize + on failure the store back into EXPECT. + 2014-02-20 Chung-Lin Tang <cltang@codesourcery.com> Sandra Loosemore <sandra@codesourcery.com> diff --git a/gcc/builtins.c b/gcc/builtins.c index f5f55bf0e2e..09fefe50a8d 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; } diff --git a/libatomic/ChangeLog b/libatomic/ChangeLog index 2d1c9bd18ae..1bd3c2178aa 100644 --- a/libatomic/ChangeLog +++ b/libatomic/ChangeLog @@ -1,3 +1,9 @@ +2014-02-20 Richard Henderson <rth@redhat.com> + + PR c++/60272 + * cas_n.c (libat_compare_exchange): Conditionalize on failure + the store back to EPTR. + 2014-01-02 Richard Sandiford <rdsandiford@googlemail.com> Update copyright years diff --git a/libatomic/cas_n.c b/libatomic/cas_n.c index 39c78332423..801262d551c 100644 --- a/libatomic/cas_n.c +++ b/libatomic/cas_n.c @@ -51,10 +51,9 @@ SIZE(libat_compare_exchange) (UTYPE *mptr, UTYPE *eptr, UTYPE newval, #if !DONE && N <= WORDSIZE && defined(atomic_compare_exchange_w) bool SIZE(libat_compare_exchange) (UTYPE *mptr, UTYPE *eptr, UTYPE newval, - int smodel, int fmodel UNUSED) + int smodel, int fmodel) { UWORD mask, shift, weval, woldval, wnewval, t, *wptr; - bool ret = false; pre_barrier (smodel); @@ -82,12 +81,13 @@ SIZE(libat_compare_exchange) (UTYPE *mptr, UTYPE *eptr, UTYPE newval, } while (!atomic_compare_exchange_w (wptr, &woldval, t, true, __ATOMIC_RELAXED, __ATOMIC_RELAXED)); - ret = true; + post_barrier (smodel); + return true; + failure: *eptr = woldval >> shift; - - post_barrier (smodel); - return ret; + post_barrier (fmodel); + return false; } #define DONE 1 @@ -102,18 +102,17 @@ SIZE(libat_compare_exchange) (UTYPE *mptr, UTYPE *eptr, UTYPE newval, { UTYPE oldval; UWORD magic; - bool ret = false; + bool ret; pre_seq_barrier (smodel); magic = protect_start (mptr); oldval = *mptr; - if (oldval == *eptr) - { - *mptr = newval; - ret = true; - } - *eptr = oldval; + ret = (oldval == *eptr); + if (ret) + *mptr = newval; + else + *eptr = oldval; protect_end (mptr, magic); post_seq_barrier (smodel); |