aboutsummaryrefslogtreecommitdiff
path: root/libatomic
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 /libatomic
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 'libatomic')
-rw-r--r--libatomic/ChangeLog6
-rw-r--r--libatomic/cas_n.c25
2 files changed, 18 insertions, 13 deletions
diff --git a/libatomic/ChangeLog b/libatomic/ChangeLog
index 2d1c9bd..1bd3c21 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 39c7833..801262d 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);