diff options
author | torvald <torvald@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-12-24 01:42:35 +0000 |
---|---|---|
committer | torvald <torvald@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-12-24 01:42:35 +0000 |
commit | c4c0a912745588307c7be984615a825edd421bbd (patch) | |
tree | fd0ffc4afe2a926dc6676559d466c9ae7fad9c2b /libitm/config | |
parent | 813b307549daffa9a654d62e98a71ea8a11f932d (diff) | |
download | gcc-c4c0a912745588307c7be984615a825edd421bbd.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@182675 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libitm/config')
-rw-r--r-- | libitm/config/linux/rwlock.cc | 20 | ||||
-rw-r--r-- | libitm/config/linux/rwlock.h | 1 | ||||
-rw-r--r-- | libitm/config/posix/rwlock.cc | 18 | ||||
-rw-r--r-- | libitm/config/posix/rwlock.h | 1 |
4 files changed, 30 insertions, 10 deletions
diff --git a/libitm/config/linux/rwlock.cc b/libitm/config/linux/rwlock.cc index f87be2e880a..24e7042ff10 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 e5a53c054f6..987e5801409 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 7ef39982ccf..f93baf2e100 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 359991ab45b..a1a6042e562 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); |