aboutsummaryrefslogtreecommitdiff
path: root/libitm/beginend.cc
diff options
context:
space:
mode:
authorTorvald Riegel <triegel@redhat.com>2016-01-13 12:40:34 +0000
committerTorvald Riegel <torvald@gcc.gnu.org>2016-01-13 12:40:34 +0000
commit629e47295b44d9adf01b66061dd891a25e567474 (patch)
tree0f4bfc83fa01d0a035d86c869e199905d89075cb /libitm/beginend.cc
parent8bc47ae2a784685f79dca8d7d04135c939a49452 (diff)
downloadgcc-629e47295b44d9adf01b66061dd891a25e567474.zip
gcc-629e47295b44d9adf01b66061dd891a25e567474.tar.gz
gcc-629e47295b44d9adf01b66061dd891a25e567474.tar.bz2
libitm: Fix privatization safety interaction with serial mode.
From-SVN: r232322
Diffstat (limited to 'libitm/beginend.cc')
-rw-r--r--libitm/beginend.cc34
1 files changed, 29 insertions, 5 deletions
diff --git a/libitm/beginend.cc b/libitm/beginend.cc
index c801dab..85fb4f1 100644
--- a/libitm/beginend.cc
+++ b/libitm/beginend.cc
@@ -568,8 +568,9 @@ GTM::gtm_thread::trycommit ()
gtm_word priv_time = 0;
if (abi_disp()->trycommit (priv_time))
{
- // The transaction is now inactive. Everything that we still have to do
- // will not synchronize with other transactions anymore.
+ // The transaction is now finished but we will still access some shared
+ // data if we have to ensure privatization safety.
+ bool do_read_unlock = false;
if (state & gtm_thread::STATE_SERIAL)
{
gtm_thread::serial_lock.write_unlock ();
@@ -578,7 +579,27 @@ GTM::gtm_thread::trycommit ()
priv_time = 0;
}
else
- gtm_thread::serial_lock.read_unlock (this);
+ {
+ // If we have to ensure privatization safety, we must not yet
+ // release the read lock and become inactive because (1) we still
+ // have to go through the list of all transactions, which can be
+ // modified by serial mode threads, and (2) we interpret each
+ // transactions' shared_state in the context of what we believe to
+ // be the current method group (and serial mode transactions can
+ // change the method group). Therefore, if we have to ensure
+ // privatization safety, delay becoming inactive but set a maximum
+ // snapshot time (we have committed and thus have an empty snapshot,
+ // so it will always be most recent). Use release MO so that this
+ // synchronizes with other threads observing our snapshot time.
+ if (priv_time)
+ {
+ do_read_unlock = true;
+ shared_state.store((~(typeof gtm_thread::shared_state)0) - 1,
+ memory_order_release);
+ }
+ else
+ gtm_thread::serial_lock.read_unlock (this);
+ }
state = 0;
// We can commit the undo log after dispatch-specific commit and after
@@ -618,8 +639,11 @@ GTM::gtm_thread::trycommit ()
}
}
- // After ensuring privatization safety, we execute potentially
- // privatizing actions (e.g., calling free()). User actions are first.
+ // After ensuring privatization safety, we are now truly inactive and
+ // thus can release the read lock. We will also execute potentially
+ // privatizing actions (e.g., calling free()). User actions are first.
+ if (do_read_unlock)
+ gtm_thread::serial_lock.read_unlock (this);
commit_user_actions ();
commit_allocations (false, 0);