diff options
author | Fathi Boudra <fabo@debian.org> | 2011-06-12 14:01:21 +0300 |
---|---|---|
committer | Fathi Boudra <fabo@debian.org> | 2011-06-12 14:01:21 +0300 |
commit | 0dcde90564d897dbef49c0df701605e803f9abb2 (patch) | |
tree | 2493f142787509140e783d27967f1d5e3e6137cc | |
parent | 04707289b2230eb8945c9d6dd8903ab054a67a36 (diff) | |
download | qt4-x11-0dcde90564d897dbef49c0df701605e803f9abb2.tar.gz |
Add patches:
- armv6_Include_explicitly_IT_instructions.patch
- armv6_Add_support_for_ARMv7_atomic_operations.patch, instead of GCC intrinsics patch for armhf.
-rw-r--r-- | debian/changelog | 7 | ||||
-rw-r--r-- | debian/patches/armv6_Add_support_for_ARMv7_atomic_operations.patch | 399 | ||||
-rw-r--r-- | debian/patches/armv6_Include_explicitly_IT_instructions.patch | 26 | ||||
-rw-r--r-- | debian/patches/series | 3 | ||||
-rw-r--r-- | debian/patches/x-0003-Use-GCC-intrinsics-for-armv6-atomic-operations.patch | 195 |
5 files changed, 432 insertions, 198 deletions
diff --git a/debian/changelog b/debian/changelog index e2d5b7f..eb8f20c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,11 +1,14 @@ qt4-x11 (4:4.7.3-2) UNRELEASED; urgency=low - * Add patch cherry-picked upstream: + * Add patches: - Fixed_bug_in_X11_backend_when_creating_translucent_windows.patch - Fix_builds_with_compilers_without_--with-fpu_neon_as_default.patch NEON_SOURCES would be (incorrectly) compiled without -mfpu=neon, resulting in build failure. This also moves -mfpu=neon after CXXFLAGS, - as CXXFLAGS may contain -mfpu=vfpv3-d16 + as CXXFLAGS may contain -mfpu=vfpv3-d16. + - armv6_Include_explicitly_IT_instructions.patch + - armv6_Add_support_for_ARMv7_atomic_operations.patch, instead of GCC + intrinsics patch for armhf. * Build Qt with GL ES 2 on armel and armhf architectures: - debian/control: add libgles2-mesa-dev | libgles2-dev build-dependencies. - debian/rules: pass -opengl es2 configure option. diff --git a/debian/patches/armv6_Add_support_for_ARMv7_atomic_operations.patch b/debian/patches/armv6_Add_support_for_ARMv7_atomic_operations.patch new file mode 100644 index 0000000..a311c78 --- /dev/null +++ b/debian/patches/armv6_Add_support_for_ARMv7_atomic_operations.patch @@ -0,0 +1,399 @@ +Description: Add support for ARMv7 atomic operations + + ARMv7 adds the DMB (data memory barrier) instruction which we can use to + enforce memory barriers in QAtomicInt and QAtomicPointer. Other than + that, ARMv7 is identical to ARMv6. + + Adjust the ARMv6 code to relax the compiler memory barriers on the + *Relaxed() operations, and use *Relaxed() functions together the + appropriate compiler barriers in the *Acquire(), *Release(), and + *Ordered() functions. For "pure" ARMv6 code, the barriers are only + compiler barriers, but for ARMv7, we also emit the DMB instruction. + + Fixed in Qt 4.8. See patchset: + f293b98 Silence preprocessor warnings about __TARGET_ARCH_ARM not being + defined + c7bf2d7 Fixed compile for symbian + dc8d096 Compile when detecting ARMv5 + 2c73f55 Compile when detecting ARMv5 + 82b4fff Add support for ARMv7 atomic operations + 7be2c58 Merge the armv6 and arm architectures + 1c0b3237 Copy src/corelib/arch/qatomic_arm.h to + src/corelib/arch/qatomic_armv5.h + a0f69c0 Move symbian specific qatomic_generic_armv6.cpp + +Author: Bradley T. Hughes <bradley.hughes@nokia.com> +Bug-Ubuntu: https://launchpad.net/bugs/490371 +--- + src/corelib/arch/qatomic_armv6.h | 162 ++++++++++++++++++++++++++------------- + 1 file changed, 111 insertions(+), 51 deletions(-) + +--- a/src/corelib/arch/qatomic_armv6.h ++++ b/src/corelib/arch/qatomic_armv6.h +@@ -102,6 +102,15 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPoint + + #ifndef Q_CC_RVCT + ++// use the DMB instruction when compiling for ARMv7 ++#ifndef Q_DATA_MEMORY_BARRIER ++# define Q_DATA_MEMORY_BARRIER asm volatile("dmb\n":::"memory") ++#endif ++#ifndef Q_COMPILER_MEMORY_BARRIER ++# define Q_COMPILER_MEMORY_BARRIER asm volatile("":::"memory") ++#endif ++ ++// ... but the implementation is otherwise identical to that for ARMv6 + inline bool QBasicAtomicInt::ref() + { + register int newValue; +@@ -138,7 +147,7 @@ inline bool QBasicAtomicInt::deref() + return newValue != 0; + } + +-inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) ++inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) + { + register int result; + asm volatile("0:\n" +@@ -153,11 +162,11 @@ inline bool QBasicAtomicInt::testAndSetO + : [expectedValue] "r" (expectedValue), + [newValue] "r" (newValue), + [_q_value] "r" (&_q_value) +- : "cc", "memory"); ++ : "cc"); + return result == 0; + } + +-inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) ++inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) + { + register int originalValue; + register int result; +@@ -171,11 +180,11 @@ inline int QBasicAtomicInt::fetchAndStor + "+m" (_q_value) + : [newValue] "r" (newValue), + [_q_value] "r" (&_q_value) +- : "cc", "memory"); ++ : "cc"); + return originalValue; + } + +-inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) ++inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) + { + register int originalValue; + register int newValue; +@@ -192,12 +201,12 @@ inline int QBasicAtomicInt::fetchAndAddO + "+m" (_q_value) + : [valueToAdd] "r" (valueToAdd), + [_q_value] "r" (&_q_value) +- : "cc", "memory"); ++ : "cc"); + return originalValue; + } + + template <typename T> +-Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) ++Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) + { + register T *result; + asm volatile("0:\n" +@@ -212,12 +221,12 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPoint + : [expectedValue] "r" (expectedValue), + [newValue] "r" (newValue), + [_q_value] "r" (&_q_value) +- : "cc", "memory"); ++ : "cc"); + return result == 0; + } + + template <typename T> +-Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) ++Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) + { + register T *originalValue; + register int result; +@@ -231,12 +240,12 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer + "+m" (_q_value) + : [newValue] "r" (newValue), + [_q_value] "r" (&_q_value) +- : "cc", "memory"); ++ : "cc"); + return originalValue; + } + + template <typename T> +-Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) ++Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) + { + register T *originalValue; + register T *newValue; +@@ -253,7 +262,7 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer + "+m" (_q_value) + : [valueToAdd] "r" (valueToAdd * sizeof(T)), + [_q_value] "r" (&_q_value) +- : "cc", "memory"); ++ : "cc"); + return originalValue; + } + +@@ -265,9 +274,18 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer + // RVCT embedded assembly documentation: + // http://www.keil.com/support/man/docs/armcc/armcc_chddbeib.htm + +-// save our pragma state and switch to ARM mode +-#pragma push +-#pragma arm ++#if __TARGET_ARCH_THUMB-0 < 4 ++// save our pragma state and switch to ARM mode (unless using Thumb2) ++# pragma push ++# pragma arm ++#endif ++ ++#ifndef Q_DATA_MEMORY_BARRIER ++# define Q_DATA_MEMORY_BARRIER __schedule_barrier() ++#endif ++#ifndef Q_COMPILER_MEMORY_BARRIER ++# define Q_COMPILER_MEMORY_BARRIER __schedule_barrier() ++#endif + + inline bool QBasicAtomicInt::ref() + { +@@ -299,7 +317,7 @@ inline bool QBasicAtomicInt::deref() + return newValue != 0; + } + +-inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) ++inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) + { + register int result; + retry: +@@ -313,7 +331,7 @@ inline bool QBasicAtomicInt::testAndSetO + return result == 0; + } + +-inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) ++inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) + { + register int originalValue; + register int result; +@@ -327,7 +345,7 @@ inline int QBasicAtomicInt::fetchAndStor + return originalValue; + } + +-inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) ++inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) + { + register int originalValue; + register int newValue; +@@ -344,7 +362,7 @@ inline int QBasicAtomicInt::fetchAndAddO + } + + template <typename T> +-Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) ++Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) + { + register T *result; + retry: +@@ -359,7 +377,7 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPoint + } + + template <typename T> +-Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) ++Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) + { + register T *originalValue; + register int result; +@@ -374,7 +392,7 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer + } + + template <typename T> +-Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) ++Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) + { + register T *originalValue; + register T *newValue; +@@ -390,111 +408,153 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer + return originalValue; + } + +-// go back to the previous pragma state (probably Thumb mode) +-#pragma pop ++#if __TARGET_ARCH_THUMB-0 < 4 ++# pragma pop + #endif + +-// common code ++#endif + +-inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +-{ +- return testAndSetOrdered(expectedValue, newValue); +-} ++// common code + + inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) + { +- return testAndSetOrdered(expectedValue, newValue); ++ bool returnValue = testAndSetRelaxed(expectedValue, newValue); ++ Q_DATA_MEMORY_BARRIER; ++ return returnValue; + } + + inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) + { +- return testAndSetOrdered(expectedValue, newValue); ++ Q_DATA_MEMORY_BARRIER; ++ return testAndSetRelaxed(expectedValue, newValue); + } + +-inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) ++inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) + { +- return fetchAndStoreOrdered(newValue); ++ Q_DATA_MEMORY_BARRIER; ++ bool returnValue = testAndSetRelaxed(expectedValue, newValue); ++ Q_COMPILER_MEMORY_BARRIER; ++ return returnValue; + } + + inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) + { +- return fetchAndStoreOrdered(newValue); ++ int returnValue = fetchAndStoreRelaxed(newValue); ++ Q_DATA_MEMORY_BARRIER; ++ return returnValue; + } + + inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) + { +- return fetchAndStoreOrdered(newValue); ++ Q_DATA_MEMORY_BARRIER; ++ return fetchAndStoreRelaxed(newValue); + } + +-inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) ++inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) + { +- return fetchAndAddOrdered(valueToAdd); ++ Q_DATA_MEMORY_BARRIER; ++ int returnValue = fetchAndStoreRelaxed(newValue); ++ Q_COMPILER_MEMORY_BARRIER; ++ return returnValue; + } + ++ + inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) + { +- return fetchAndAddOrdered(valueToAdd); ++ int returnValue = fetchAndAddRelaxed(valueToAdd); ++ Q_DATA_MEMORY_BARRIER; ++ return returnValue; + } + + inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) + { +- return fetchAndAddOrdered(valueToAdd); ++ Q_DATA_MEMORY_BARRIER; ++ return fetchAndAddRelaxed(valueToAdd); + } + +-template <typename T> +-Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) ++inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) + { +- return testAndSetOrdered(expectedValue, newValue); ++ Q_DATA_MEMORY_BARRIER; ++ int returnValue = fetchAndAddRelaxed(valueToAdd); ++ Q_COMPILER_MEMORY_BARRIER; ++ return returnValue; + } + + template <typename T> + Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) + { +- return testAndSetOrdered(expectedValue, newValue); ++ bool returnValue = testAndSetRelaxed(expectedValue, newValue); ++ Q_DATA_MEMORY_BARRIER; ++ return returnValue; + } + + template <typename T> + Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) + { +- return testAndSetOrdered(expectedValue, newValue); ++ Q_DATA_MEMORY_BARRIER; ++ return testAndSetRelaxed(expectedValue, newValue); + } + + template <typename T> +-Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) ++Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) + { +- return fetchAndStoreOrdered(newValue); ++ Q_DATA_MEMORY_BARRIER; ++ bool returnValue = testAndSetAcquire(expectedValue, newValue); ++ Q_COMPILER_MEMORY_BARRIER; ++ return returnValue; + } + + template <typename T> + Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) + { +- return fetchAndStoreOrdered(newValue); ++ T *returnValue = fetchAndStoreRelaxed(newValue); ++ Q_DATA_MEMORY_BARRIER; ++ return returnValue; + } + + template <typename T> + Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) + { +- return fetchAndStoreOrdered(newValue); ++ Q_DATA_MEMORY_BARRIER; ++ return fetchAndStoreRelaxed(newValue); + } + + template <typename T> +-Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) ++Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) + { +- return fetchAndAddOrdered(valueToAdd); ++ Q_DATA_MEMORY_BARRIER; ++ T *returnValue = fetchAndStoreRelaxed(newValue); ++ Q_COMPILER_MEMORY_BARRIER; ++ return returnValue; + } + + template <typename T> + Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) + { +- return fetchAndAddOrdered(valueToAdd); ++ T *returnValue = fetchAndAddRelaxed(valueToAdd); ++ Q_DATA_MEMORY_BARRIER; ++ return returnValue; + } + + template <typename T> + Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) + { +- return fetchAndAddOrdered(valueToAdd); ++ Q_DATA_MEMORY_BARRIER; ++ return fetchAndAddRelaxed(valueToAdd); + } + ++template <typename T> ++Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) ++{ ++ Q_DATA_MEMORY_BARRIER; ++ T *returnValue = fetchAndAddRelaxed(valueToAdd); ++ Q_COMPILER_MEMORY_BARRIER; ++ return returnValue; ++} ++ ++#undef Q_DATA_MEMORY_BARRIER ++#undef Q_COMPILER_MEMORY_BARRIER ++ + QT_END_NAMESPACE + + QT_END_HEADER diff --git a/debian/patches/armv6_Include_explicitly_IT_instructions.patch b/debian/patches/armv6_Include_explicitly_IT_instructions.patch new file mode 100644 index 0000000..22ab9d2 --- /dev/null +++ b/debian/patches/armv6_Include_explicitly_IT_instructions.patch @@ -0,0 +1,26 @@ +Description: include explicitly IT instructions to fix build failure without +implicit-it=thumb +Author: Michael Hope <michael.hope@linaro.org> +Bug-Ubuntu: https://launchpad.net/bugs/673085 +--- + src/corelib/arch/qatomic_armv6.h | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/src/corelib/arch/qatomic_armv6.h ++++ b/src/corelib/arch/qatomic_armv6.h +@@ -144,6 +144,7 @@ inline bool QBasicAtomicInt::testAndSetO + asm volatile("0:\n" + "ldrex %[result], [%[_q_value]]\n" + "eors %[result], %[result], %[expectedValue]\n" ++ "itt eq\n" + "strexeq %[result], %[newValue], [%[_q_value]]\n" + "teqeq %[result], #1\n" + "beq 0b\n" +@@ -202,6 +203,7 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPoint + asm volatile("0:\n" + "ldrex %[result], [%[_q_value]]\n" + "eors %[result], %[result], %[expectedValue]\n" ++ "itt eq\n" + "strexeq %[result], %[newValue], [%[_q_value]]\n" + "teqeq %[result], #1\n" + "beq 0b\n" diff --git a/debian/patches/series b/debian/patches/series index 8826850..e6e53fa 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -41,7 +41,6 @@ buildable_appchooser_states_demos.patch 71_hppa_unaligned_access_fix_458133.diff 80_hurd_max_path.diff 92_armel_gcc43_valist_compat.diff -x-0003-Use-GCC-intrinsics-for-armv6-atomic-operations.patch 94_armv6_uname_entry.diff 96_webkit_no_gc_sections.diff 99_hppa_bug561203_decrease_failure_rate.diff @@ -49,3 +48,5 @@ powerpcspe.diff sh.diff kfreebsd_monotonic_clock.diff powerpc_designer_gstabs.diff +armv6_Include_explicitly_IT_instructions.patch +armv6_Add_support_for_ARMv7_atomic_operations.patch diff --git a/debian/patches/x-0003-Use-GCC-intrinsics-for-armv6-atomic-operations.patch b/debian/patches/x-0003-Use-GCC-intrinsics-for-armv6-atomic-operations.patch deleted file mode 100644 index e5ca14d..0000000 --- a/debian/patches/x-0003-Use-GCC-intrinsics-for-armv6-atomic-operations.patch +++ /dev/null @@ -1,195 +0,0 @@ -From 7aaf387cdb578327017169a9c97bcf6c0581a780 Mon Sep 17 00:00:00 2001 -From: michaedw in build chroot <build@ctbu-bld5.cisco.com> -Date: Mon, 14 Mar 2011 01:52:46 +0000 -Subject: [PATCH] Use GCC intrinsics for armv6 atomic operations - ---- - src/corelib/arch/qatomic_armv6.h | 146 +++++++------------------------------ - 1 files changed, 28 insertions(+), 118 deletions(-) - ---- a/src/corelib/arch/qatomic_armv6.h -+++ b/src/corelib/arch/qatomic_armv6.h -@@ -104,155 +104,65 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPoint - - inline bool QBasicAtomicInt::ref() - { -- register int newValue; -- register int result; -- asm volatile("0:\n" -- "ldrex %[newValue], [%[_q_value]]\n" -- "add %[newValue], %[newValue], #1\n" -- "strex %[result], %[newValue], [%[_q_value]]\n" -- "teq %[result], #0\n" -- "bne 0b\n" -- : [newValue] "=&r" (newValue), -- [result] "=&r" (result), -- "+m" (_q_value) -- : [_q_value] "r" (&_q_value) -- : "cc", "memory"); -- return newValue != 0; -+ return __sync_add_and_fetch(&_q_value, 1) != 0; - } - - inline bool QBasicAtomicInt::deref() - { -- register int newValue; -- register int result; -- asm volatile("0:\n" -- "ldrex %[newValue], [%[_q_value]]\n" -- "sub %[newValue], %[newValue], #1\n" -- "strex %[result], %[newValue], [%[_q_value]]\n" -- "teq %[result], #0\n" -- "bne 0b\n" -- : [newValue] "=&r" (newValue), -- [result] "=&r" (result), -- "+m" (_q_value) -- : [_q_value] "r" (&_q_value) -- : "cc", "memory"); -- return newValue != 0; -+ return __sync_sub_and_fetch(&_q_value, 1) != 0; - } - - inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) - { -- register int result; -- asm volatile("0:\n" -- "ldrex %[result], [%[_q_value]]\n" -- "eors %[result], %[result], %[expectedValue]\n" -- "strexeq %[result], %[newValue], [%[_q_value]]\n" -- "teqeq %[result], #1\n" -- "beq 0b\n" -- : [result] "=&r" (result), -- "+m" (_q_value) -- : [expectedValue] "r" (expectedValue), -- [newValue] "r" (newValue), -- [_q_value] "r" (&_q_value) -- : "cc", "memory"); -- return result == 0; -+ return __sync_bool_compare_and_swap(&_q_value, expectedValue, newValue); - } - - inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) - { -- register int originalValue; -- register int result; -- asm volatile("0:\n" -- "ldrex %[originalValue], [%[_q_value]]\n" -- "strex %[result], %[newValue], [%[_q_value]]\n" -- "teq %[result], #0\n" -- "bne 0b\n" -- : [originalValue] "=&r" (originalValue), -- [result] "=&r" (result), -- "+m" (_q_value) -- : [newValue] "r" (newValue), -- [_q_value] "r" (&_q_value) -- : "cc", "memory"); -- return originalValue; -+ if (!newValue) -+ return __sync_fetch_and_and(&_q_value, 0); -+ else -+ { -+ int expectedValue = 0; -+ int oldValue; -+ do { -+ oldValue = __sync_val_compare_and_swap(&_q_value, expectedValue, newValue); -+ } while (oldValue != expectedValue); -+ return oldValue; -+ } - } - - inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) - { -- register int originalValue; -- register int newValue; -- register int result; -- asm volatile("0:\n" -- "ldrex %[originalValue], [%[_q_value]]\n" -- "add %[newValue], %[originalValue], %[valueToAdd]\n" -- "strex %[result], %[newValue], [%[_q_value]]\n" -- "teq %[result], #0\n" -- "bne 0b\n" -- : [originalValue] "=&r" (originalValue), -- [newValue] "=&r" (newValue), -- [result] "=&r" (result), -- "+m" (_q_value) -- : [valueToAdd] "r" (valueToAdd), -- [_q_value] "r" (&_q_value) -- : "cc", "memory"); -- return originalValue; -+ return __sync_fetch_and_add(&_q_value, valueToAdd); - } - - template <typename T> - Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) - { -- register T *result; -- asm volatile("0:\n" -- "ldrex %[result], [%[_q_value]]\n" -- "eors %[result], %[result], %[expectedValue]\n" -- "strexeq %[result], %[newValue], [%[_q_value]]\n" -- "teqeq %[result], #1\n" -- "beq 0b\n" -- : [result] "=&r" (result), -- "+m" (_q_value) -- : [expectedValue] "r" (expectedValue), -- [newValue] "r" (newValue), -- [_q_value] "r" (&_q_value) -- : "cc", "memory"); -- return result == 0; -+ return __sync_bool_compare_and_swap(&_q_value, expectedValue, newValue); - } - - template <typename T> - Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) - { -- register T *originalValue; -- register int result; -- asm volatile("0:\n" -- "ldrex %[originalValue], [%[_q_value]]\n" -- "strex %[result], %[newValue], [%[_q_value]]\n" -- "teq %[result], #0\n" -- "bne 0b\n" -- : [originalValue] "=&r" (originalValue), -- [result] "=&r" (result), -- "+m" (_q_value) -- : [newValue] "r" (newValue), -- [_q_value] "r" (&_q_value) -- : "cc", "memory"); -- return originalValue; -+ if (!newValue) -+ return __sync_fetch_and_and(&_q_value, 0); -+ else -+ { -+ T* expectedValue = 0; -+ T* oldValue; -+ do { -+ oldValue = __sync_val_compare_and_swap(&_q_value, expectedValue, newValue); -+ } while (oldValue != expectedValue); -+ return oldValue; -+ } - } - - template <typename T> - Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) - { -- register T *originalValue; -- register T *newValue; -- register int result; -- asm volatile("0:\n" -- "ldrex %[originalValue], [%[_q_value]]\n" -- "add %[newValue], %[originalValue], %[valueToAdd]\n" -- "strex %[result], %[newValue], [%[_q_value]]\n" -- "teq %[result], #0\n" -- "bne 0b\n" -- : [originalValue] "=&r" (originalValue), -- [newValue] "=&r" (newValue), -- [result] "=&r" (result), -- "+m" (_q_value) -- : [valueToAdd] "r" (valueToAdd * sizeof(T)), -- [_q_value] "r" (&_q_value) -- : "cc", "memory"); -- return originalValue; -+ return (T*) __sync_fetch_and_add((volatile int*) &_q_value, valueToAdd); - } - - #else |