summaryrefslogtreecommitdiff
path: root/gcc48-rh1491395.patch
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2024-08-01 14:23:42 +0000
committerCoprDistGit <infra@openeuler.org>2024-08-01 14:23:42 +0000
commit82711f6567ef069eebb942e382e2c3fa61fbf538 (patch)
tree22200b7326b32ca672ffb6e4ce6d19a09dc476e5 /gcc48-rh1491395.patch
parent5d624aa0d36abe76a344f0593eae5cf36d083b15 (diff)
automatic import of compat-libgfortran-48openeuler24.03_LTSopeneuler23.09
Diffstat (limited to 'gcc48-rh1491395.patch')
-rw-r--r--gcc48-rh1491395.patch177
1 files changed, 177 insertions, 0 deletions
diff --git a/gcc48-rh1491395.patch b/gcc48-rh1491395.patch
new file mode 100644
index 0000000..f0a8bb4
--- /dev/null
+++ b/gcc48-rh1491395.patch
@@ -0,0 +1,177 @@
+2016-01-16 Torvald Riegel <triegel@redhat.com>
+
+ * method-gl.cc (gl_wt_dispatch::trycommit): Ensure proxy privatization
+ safety.
+ * method-ml.cc (ml_wt_dispatch::trycommit): Likewise.
+ * libitm/testsuite/libitm.c/priv-1.c: New.
+
+--- libitm/method-gl.cc
++++ libitm/method-gl.cc
+@@ -291,12 +291,18 @@ public:
+ // See begin_or_restart() for why we need release memory order here.
+ v = gl_mg::clear_locked(v) + 1;
+ o_gl_mg.orec.store(v, memory_order_release);
+-
+- // Need to ensure privatization safety. Every other transaction must
+- // have a snapshot time that is at least as high as our commit time
+- // (i.e., our commit must be visible to them).
+- priv_time = v;
+ }
++
++ // Need to ensure privatization safety. Every other transaction must have
++ // a snapshot time that is at least as high as our commit time (i.e., our
++ // commit must be visible to them). Because of proxy privatization, we
++ // must ensure that even if we are a read-only transaction. See
++ // ml_wt_dispatch::trycommit() for details: We can't get quite the same
++ // set of problems because we just use one orec and thus, for example,
++ // there cannot be concurrent writers -- but we can still get pending
++ // loads to privatized data when not ensuring privatization safety, which
++ // is problematic if the program unmaps the privatized memory.
++ priv_time = v;
+ return true;
+ }
+
+--- libitm/method-ml.cc
++++ libitm/method-ml.cc
+@@ -513,6 +513,21 @@ public:
+ if (!tx->writelog.size())
+ {
+ tx->readlog.clear();
++ // We still need to ensure privatization safety, unfortunately. While
++ // we cannot have privatized anything by ourselves (because we are not
++ // an update transaction), we can have observed the commits of
++ // another update transaction that privatized something. Because any
++ // commit happens before ensuring privatization, our snapshot and
++ // commit can thus have happened before ensuring privatization safety
++ // for this commit/snapshot time. Therefore, before we can return to
++ // nontransactional code that might use the privatized data, we must
++ // ensure privatization safety for our snapshot time.
++ // This still seems to be better than not allowing use of the
++ // snapshot time before privatization safety has been ensured because
++ // we at least can run transactions such as this one, and in the
++ // meantime the transaction producing this commit time might have
++ // finished ensuring privatization safety for it.
++ priv_time = tx->shared_state.load(memory_order_relaxed);
+ return true;
+ }
+
+--- /dev/null
++++ libitm/testsuite/libitm.c/priv-1.c
+@@ -0,0 +1,117 @@
++/* Quick stress test for proxy privatization. */
++
++/* We need to use a TM method that has to enforce privatization safety
++ explicitly. */
++/* { dg-set-target-env-var ITM_DEFAULT_METHOD "ml_wt" } */
++/* { dg-options "-std=gnu11" } */
++
++#include <stdlib.h>
++#include <stdio.h>
++#include <pthread.h>
++
++/* Make them likely to be mapped to different orecs. */
++#define ALIGN __attribute__((aligned (256)))
++/* Don't make these static to work around PR 68591. */
++int x ALIGN;
++int *ptr ALIGN;
++int *priv_ptr ALIGN;
++int priv_value ALIGN;
++int barrier ALIGN = 0;
++const int iters = 100;
++
++static void arrive_and_wait (int expected_value)
++{
++ int now = __atomic_add_fetch (&barrier, 1, __ATOMIC_ACQ_REL);
++ while (now < expected_value)
++ __atomic_load (&barrier, &now, __ATOMIC_ACQUIRE);
++}
++
++static void __attribute__((transaction_pure,noinline)) delay (int i)
++{
++ for (volatile int v = 0; v < i; v++);
++}
++
++/* This tries to catch a case in which proxy privatization safety is not
++ ensured by privatization_user. Specifically, it's access to the value
++ of it's transactional snapshot of ptr must read from an uncommitted write
++ by writer; thus, writer must still be active but must have read ptr before
++ proxy can privatize *ptr by assigning to ptr.
++ We try to make this interleaving more likely by delaying the commit of
++ writer and the start of proxy. */
++static void *writer (void *dummy __attribute__((unused)))
++{
++ for (int i = 0; i < iters; i++)
++ {
++ /* Initialize state in each round. */
++ x = 0;
++ ptr = &x;
++ priv_ptr = NULL;
++ int wrote = 1;
++ arrive_and_wait (i * 6 + 3);
++ /* Interference by another writer. Has a conflict with the proxy
++ privatizer. */
++ __transaction_atomic
++ {
++ if (ptr != NULL)
++ *ptr = 1;
++ else
++ wrote = 0;
++ delay (2000000);
++ }
++ arrive_and_wait (i * 6 + 6);
++ /* If the previous transaction committed first, wrote == 1 and x == 1;
++ otherwise, if the proxy came first, wrote == 0 and priv_value == 0.
++ */
++ if (wrote != priv_value)
++ abort ();
++ }
++ return NULL;
++}
++
++static void *proxy (void *dummy __attribute__((unused)))
++{
++ for (int i = 0; i < iters; i++)
++ {
++ arrive_and_wait (i * 6 + 3);
++ delay(1000000);
++ __transaction_atomic
++ {
++ /* Hand-off to privatization-user and its read-only transaction and
++ subsequent use of privatization. */
++ priv_ptr = ptr;
++ ptr = NULL;
++ }
++ arrive_and_wait (i * 6 + 6);
++ }
++ return NULL;
++}
++
++static void *privatization_user (void *dummy __attribute__((unused)))
++{
++ for (int i = 0; i < iters; i++)
++ {
++ arrive_and_wait (i * 6 + 3);
++ /* Spin until we have gotten a pointer from the proxy. Then access
++ the value pointed to nontransactionally. */
++ int *p = NULL;
++ while (p == NULL)
++ __transaction_atomic { p = priv_ptr; }
++ priv_value = *p;
++ arrive_and_wait (i * 6 + 6);
++ }
++ return NULL;
++}
++
++int main()
++{
++ pthread_t p[3];
++
++ pthread_create (p+0, NULL, writer, NULL);
++ pthread_create (p+1, NULL, proxy, NULL);
++ pthread_create (p+2, NULL, privatization_user, NULL);
++
++ for (int i = 0; i < 3; ++i)
++ pthread_join (p[i], NULL);
++
++ return 0;
++}