aboutsummaryrefslogtreecommitdiff
path: root/libitm/config
diff options
context:
space:
mode:
authorTorvald Riegel <triegel@redhat.com>2011-12-24 01:42:35 +0000
committerTorvald Riegel <torvald@gcc.gnu.org>2011-12-24 01:42:35 +0000
commit610e39013598f4f3bc66c117c3402c07b517cfa0 (patch)
treefd0ffc4afe2a926dc6676559d466c9ae7fad9c2b /libitm/config
parent799142bf743cb04f3a86df85c69481a3c44c1ad9 (diff)
downloadgcc-610e39013598f4f3bc66c117c3402c07b517cfa0.zip
gcc-610e39013598f4f3bc66c117c3402c07b517cfa0.tar.gz
gcc-610e39013598f4f3bc66c117c3402c07b517cfa0.tar.bz2
libitm: Fix privatization safety during upgrades to serial mode.
libitm/ * beginend.cc (GTM::gtm_thread::restart): Add and handle finish_serial_upgrade parameter. * libitm.h (GTM::gtm_thread::restart): Adapt declaration. * config/linux/rwlock.cc (GTM::gtm_rwlock::write_lock_generic): Don't unset reader flag. (GTM::gtm_rwlock::write_upgrade_finish): New. * config/posix/rwlock.cc: Same. * config/linux/rwlock.h (GTM::gtm_rwlock::write_upgrade_finish): Declare. * config/posix/rwlock.h: Same. * method-serial.cc (GTM::gtm_thread::serialirr_mode): Unset reader flag after commit or after rollback when restarting. From-SVN: r182675
Diffstat (limited to 'libitm/config')
-rw-r--r--libitm/config/linux/rwlock.cc20
-rw-r--r--libitm/config/linux/rwlock.h1
-rw-r--r--libitm/config/posix/rwlock.cc18
-rw-r--r--libitm/config/posix/rwlock.h1
4 files changed, 30 insertions, 10 deletions
diff --git a/libitm/config/linux/rwlock.cc b/libitm/config/linux/rwlock.cc
index f87be2e..24e7042 100644
--- a/libitm/config/linux/rwlock.cc
+++ b/libitm/config/linux/rwlock.cc
@@ -121,17 +121,13 @@ gtm_rwlock::write_lock_generic (gtm_thread *tx)
// readers that might still be active.
// We don't need an extra barrier here because the CAS and the xchg
// operations have full barrier semantics already.
-
- // If this is an upgrade, we are not a reader anymore. This is only safe to
- // do after we have acquired the writer lock.
// TODO In the worst case, this requires one wait/wake pair for each
// active reader. Reduce this!
- if (tx != 0)
- tx->shared_state.store (-1, memory_order_relaxed);
-
for (gtm_thread *it = gtm_thread::list_of_threads; it != 0;
it = it->next_thread)
{
+ if (it == tx)
+ continue;
// Use a loop here to check reader flags again after waiting.
while (it->shared_state.load (memory_order_relaxed)
!= ~(typeof it->shared_state)0)
@@ -175,6 +171,18 @@ gtm_rwlock::write_upgrade (gtm_thread *tx)
}
+// Has to be called iff the previous upgrade was successful and after it is
+// safe for the transaction to not be marked as a reader anymore.
+
+void
+gtm_rwlock::write_upgrade_finish (gtm_thread *tx)
+{
+ // We are not a reader anymore. This is only safe to do after we have
+ // acquired the writer lock.
+ tx->shared_state.store (-1, memory_order_release);
+}
+
+
// Release a RW lock from reading.
void
diff --git a/libitm/config/linux/rwlock.h b/libitm/config/linux/rwlock.h
index e5a53c0..987e580 100644
--- a/libitm/config/linux/rwlock.h
+++ b/libitm/config/linux/rwlock.h
@@ -57,6 +57,7 @@ class gtm_rwlock
void write_unlock ();
bool write_upgrade (gtm_thread *tx);
+ void write_upgrade_finish (gtm_thread *tx);
protected:
bool write_lock_generic (gtm_thread *tx);
diff --git a/libitm/config/posix/rwlock.cc b/libitm/config/posix/rwlock.cc
index 7ef3998..f93baf2 100644
--- a/libitm/config/posix/rwlock.cc
+++ b/libitm/config/posix/rwlock.cc
@@ -155,10 +155,6 @@ gtm_rwlock::write_lock_generic (gtm_thread *tx)
// path of read_lock()).
atomic_thread_fence(memory_order_seq_cst);
- // If this is an upgrade, we are not a reader anymore.
- if (tx != 0)
- tx->shared_state.store(-1, memory_order_relaxed);
-
// Count the number of active readers to be able to decrease the number of
// wake-ups and wait calls that are necessary.
//
@@ -194,6 +190,8 @@ gtm_rwlock::write_lock_generic (gtm_thread *tx)
it = it->next_thread)
{
// Don't count ourself if this is an upgrade.
+ if (it == tx)
+ continue;
if (it->shared_state.load(memory_order_relaxed) != (gtm_word)-1)
readers++;
}
@@ -231,6 +229,18 @@ gtm_rwlock::write_upgrade (gtm_thread *tx)
}
+// Has to be called iff the previous upgrade was successful and after it is
+// safe for the transaction to not be marked as a reader anymore.
+
+void
+gtm_rwlock::write_upgrade_finish (gtm_thread *tx)
+{
+ // We are not a reader anymore. This is only safe to do after we have
+ // acquired the writer lock.
+ tx->shared_state.store (-1, memory_order_release);
+}
+
+
// Release a RW lock from reading.
void
diff --git a/libitm/config/posix/rwlock.h b/libitm/config/posix/rwlock.h
index 359991a..a1a6042 100644
--- a/libitm/config/posix/rwlock.h
+++ b/libitm/config/posix/rwlock.h
@@ -72,6 +72,7 @@ class gtm_rwlock
void write_unlock ();
bool write_upgrade (gtm_thread *tx);
+ void write_upgrade_finish (gtm_thread *tx);
protected:
bool write_lock_generic (gtm_thread *tx);