diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2012-08-06 19:57:59 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-02-16 05:12:26 +0100 |
commit | 634f82f1f1fda7983abf70b58e43c580b1f01df0 (patch) | |
tree | 0d3b67615c35f6c8938b0d40c2ab59097a4001ea /src/corelib/arch/qatomic_ia64.h | |
parent | fb30a3dd7c2e449235ac5896877bbc0ad41a3835 (diff) |
Add a testAndSet overload to the atomics that returns the current value
This is extremely useful, since the most common action after a failed
compare-and-swap is to loop around, trying again with the current
value as found in memory.
Code currently written as:
do {
Type value = atomic.load();
...
} while (!atomic.testAndSetRelaxed(value, desired));
Becomes:
Type value = atomic.load();
do {
...
} while (!atomic.testAndSetRelaxed(value, desired, value));
In most CPU architectures, the value that was found in memory is known
to the compare-and-swap code, so this is more efficient than the
previous code. In architectures where the value is not known, the new
code is no worse than before.
The implementation sometimes modified an existing function, sometimes
it added a new one, depending on whether more registers were needed in
the assembly (like ARMv6-7), the code became more complex (ARMv5), the
optimizer failed (C++11), or it was just plain equivalent (MIPS).
Change-Id: I7d6d200ea9746ec8978a0c1e1969dbc3580b9285
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com>
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/arch/qatomic_ia64.h')
-rw-r--r-- | src/corelib/arch/qatomic_ia64.h | 40 |
1 files changed, 28 insertions, 12 deletions
diff --git a/src/corelib/arch/qatomic_ia64.h b/src/corelib/arch/qatomic_ia64.h index 0075f32a42..e5e93ec2b7 100644 --- a/src/corelib/arch/qatomic_ia64.h +++ b/src/corelib/arch/qatomic_ia64.h @@ -150,10 +150,10 @@ template <int size> struct QBasicAtomicOps: QGenericAtomicOps<QBasicAtomicOps<si static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return true; } static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return true; } - template <typename T> static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW; - template <typename T> static bool testAndSetAcquire(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW; - template <typename T> static bool testAndSetRelease(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW; - template <typename T> static bool testAndSetOrdered(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW; + template <typename T> static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue = 0) Q_DECL_NOTHROW; + template <typename T> static bool testAndSetAcquire(T &_q_value, T expectedValue, T newValue, T *currentValue = 0) Q_DECL_NOTHROW; + template <typename T> static bool testAndSetRelease(T &_q_value, T expectedValue, T newValue, T *currentValue = 0) Q_DECL_NOTHROW; + template <typename T> static bool testAndSetOrdered(T &_q_value, T expectedValue, T newValue, T *currentValue = 0) Q_DECL_NOTHROW; static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return true; } static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return true; } @@ -373,7 +373,7 @@ bool QBasicAtomicOps<8>::deref(T &_q_value) Q_DECL_NOTHROW } template<> template <typename T> inline -bool QBasicAtomicOps<1>::testAndSetAcquire(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW +bool QBasicAtomicOps<1>::testAndSetAcquire(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW { T ret; asm volatile("mov ar.ccv=%2\n" @@ -382,11 +382,13 @@ bool QBasicAtomicOps<1>::testAndSetAcquire(T &_q_value, T expectedValue, T newVa : "=r" (ret), "+m" (_q_value) : "r" (expectedValue), "r" (newValue) : "memory"); + if (currentValue) + *currentValue = ret; return ret == expectedValue; } template<> template <typename T> inline -bool QBasicAtomicOps<1>::testAndSetRelease(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW +bool QBasicAtomicOps<1>::testAndSetRelease(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW { T ret; asm volatile("mov ar.ccv=%2\n" @@ -395,11 +397,13 @@ bool QBasicAtomicOps<1>::testAndSetRelease(T &_q_value, T expectedValue, T newVa : "=r" (ret), "+m" (_q_value) : "r" (expectedValue), "r" (newValue) : "memory"); + if (currentValue) + *currentValue = ret; return ret == expectedValue; } template<> template <typename T> inline -bool QBasicAtomicOps<2>::testAndSetAcquire(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW +bool QBasicAtomicOps<2>::testAndSetAcquire(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW { T ret; asm volatile("mov ar.ccv=%2\n" @@ -408,11 +412,13 @@ bool QBasicAtomicOps<2>::testAndSetAcquire(T &_q_value, T expectedValue, T newVa : "=r" (ret), "+m" (_q_value) : "r" (expectedValue), "r" (newValue) : "memory"); + if (currentValue) + *currentValue = ret; return ret == expectedValue; } template<> template <typename T> inline -bool QBasicAtomicOps<2>::testAndSetRelease(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW +bool QBasicAtomicOps<2>::testAndSetRelease(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW { T ret; asm volatile("mov ar.ccv=%2\n" @@ -421,11 +427,13 @@ bool QBasicAtomicOps<2>::testAndSetRelease(T &_q_value, T expectedValue, T newVa : "=r" (ret), "+m" (_q_value) : "r" (expectedValue), "r" (newValue) : "memory"); + if (currentValue) + *currentValue = ret; return ret == expectedValue; } template<> template <typename T> inline -bool QBasicAtomicOps<4>::testAndSetAcquire(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW +bool QBasicAtomicOps<4>::testAndSetAcquire(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW { T ret; asm volatile("mov ar.ccv=%2\n" @@ -434,11 +442,13 @@ bool QBasicAtomicOps<4>::testAndSetAcquire(T &_q_value, T expectedValue, T newVa : "=r" (ret), "+m" (_q_value) : "r" (expectedValue), "r" (newValue) : "memory"); + if (currentValue) + *currentValue = ret; return ret == expectedValue; } template<> template <typename T> inline -bool QBasicAtomicOps<4>::testAndSetRelease(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW +bool QBasicAtomicOps<4>::testAndSetRelease(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW { T ret; asm volatile("mov ar.ccv=%2\n" @@ -447,11 +457,13 @@ bool QBasicAtomicOps<4>::testAndSetRelease(T &_q_value, T expectedValue, T newVa : "=r" (ret), "+m" (_q_value) : "r" (expectedValue), "r" (newValue) : "memory"); + if (currentValue) + *currentValue = ret; return ret == expectedValue; } template<> template <typename T> inline -bool QBasicAtomicOps<8>::testAndSetAcquire(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW +bool QBasicAtomicOps<8>::testAndSetAcquire(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW { T ret; asm volatile("mov ar.ccv=%2\n" @@ -460,11 +472,13 @@ bool QBasicAtomicOps<8>::testAndSetAcquire(T &_q_value, T expectedValue, T newVa : "=r" (ret), "+m" (_q_value) : "r" (expectedValue), "r" (newValue) : "memory"); + if (currentValue) + *currentValue = ret; return ret == expectedValue; } template<> template <typename T> inline -bool QBasicAtomicOps<8>::testAndSetRelease(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW +bool QBasicAtomicOps<8>::testAndSetRelease(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW { T ret; asm volatile("mov ar.ccv=%2\n" @@ -473,6 +487,8 @@ bool QBasicAtomicOps<8>::testAndSetRelease(T &_q_value, T expectedValue, T newVa : "=r" (ret), "+m" (_q_value) : "r" (expectedValue), "r" (newValue) : "memory"); + if (currentValue) + *currentValue = ret; return ret == expectedValue; } |