summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorShane Kearns <shane.kearns@sosco.com>2009-11-04 21:26:00 (GMT)
committerShane Kearns <shane.kearns@sosco.com>2009-11-06 12:55:23 (GMT)
commit7442be794787c710812d46052b74d73042795aac (patch)
treec3c21b0715f7d906cb8f6a762693b1b09bf6d20c /src
parentd3ecece1432a3b0a2cb579270d7b3f5a2afaa674 (diff)
downloadQt-7442be794787c710812d46052b74d73042795aac.zip
Qt-7442be794787c710812d46052b74d73042795aac.tar.gz
Qt-7442be794787c710812d46052b74d73042795aac.tar.bz2
Binary compatibility of Symbian ARMv5 and ARMv6 builds
Use ARMv6 atomics where available Use OS atomics otherwise Integrate ARMV6 atomics to Symbian builds Use compiler defined macros to detect if ARMv6 instructions are available This defines the QT_HAVE_ARMV6 macro, replacing the way it was defined by the Symbian build system previously in qpainting.pri. qatomic_symbian now uses qatomic_arm or qatomic_armv6 automatically Port armv6 atomics to implement generic atomics interface The inline atomics are not inlined when we build for thumb using RVCT. So there is no performance improvement of using the "inline" versions vs a shared version called through a function call. The generic atomics interface is good for binary compatibility, as the same symbols are exported in all versions now. Changed the fallback generic atomics implementation from the unix one to a symbian specific one using RFastLock (identical code to the windows generic atomics, except for RFastLock replaces Win32 CRITICAL_SECTION) Note: GCCE atomics still need porting Tell git to ignore .lst listing files (produced by sbs/abld listing) ARMv6 support for GCCE compiler and fallback implementation using OS When building corelib with GCCE and -march=armv6, QT_HAVE_ARMV6 will be defined. This patch adds copies of the asm functions in GCC syntax. When building for the Symbian emulator, or ARMv5, then Symbian OS atomic functions are used as a fallback - these are more efficient than the unix atomics, and don't require data import (which the ARMv5 atomics use, but the OS loader doesn't support fully) Symbian OS functions are always used for QBasicAtomicInt::ref / deref, because these are faster than the generic function in all cases. They are machine coded for ARMv6, and are used internally by RFastLock. Reviewed-By: axis Reviewed-By: Brad
Diffstat (limited to 'src')
-rw-r--r--src/corelib/arch/armv6/qatomic_generic_armv6.cpp260
-rw-r--r--src/corelib/arch/qatomic_armv6.h3
-rw-r--r--src/corelib/arch/qatomic_symbian.h240
-rw-r--r--src/corelib/arch/symbian/arch.pri2
-rw-r--r--src/corelib/arch/symbian/qatomic_symbian.cpp104
-rw-r--r--src/corelib/global/qglobal.h7
-rw-r--r--src/gui/painting/painting.pri1
-rw-r--r--src/s60installs/eabi/QtCoreu.def8
8 files changed, 586 insertions, 39 deletions
diff --git a/src/corelib/arch/armv6/qatomic_generic_armv6.cpp b/src/corelib/arch/armv6/qatomic_generic_armv6.cpp
new file mode 100644
index 0000000..3078662
--- /dev/null
+++ b/src/corelib/arch/armv6/qatomic_generic_armv6.cpp
@@ -0,0 +1,260 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+** This file implements the generic atomics interface using ARMv6 assembly
+** instructions. It is more efficent than the inline versions when Qt is
+** built for the THUMB instruction set, as the required instructions are
+** only available in ARM state.
+****************************************************************************/
+
+#include <QtCore/qglobal.h>
+
+#ifdef QT_HAVE_ARMV6
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+#ifdef Q_CC_RVCT
+#pragma push
+#pragma arm
+Q_CORE_EXPORT asm
+bool QBasicAtomicInt_testAndSetOrdered(volatile int *_q_value, int expectedValue, int newValue)
+{
+ CODE32
+ //R0 = _q_value
+ //R1 = expectedValue
+ //R2 = newValue
+retry_testAndSetOrdered
+ LDREX r3,[r0] //r3 = *_q_value
+ EORS r3,r3,r1 //if (r3 == expectedValue) {
+ STREXEQ r3,r2,[r0] //*_q_value = newvalue, r3 = error
+ TEQEQ r3,#1 //if error
+ BEQ retry_testAndSetOrdered //then goto retry }
+ RSBS r0,r3,#1 //return (r3 == 0)
+ MOVCC r0,#0
+ BX r14
+}
+
+Q_CORE_EXPORT asm
+int QBasicAtomicInt_fetchAndStoreOrdered(volatile int *_q_value, int newValue)
+{
+ CODE32
+//R0 = _q_value
+//R1 = newValue
+retry_fetchAndStoreOrdered
+ LDREX r3,[r0] //r3 = *_q_value
+ STREX r2,r1,[r0] //*_q_value = newValue, r2 = error
+ TEQ r2,#0 //if error
+ BNE retry_fetchAndStoreOrdered //then goto retry
+ MOV r0,r3 //return r3
+ BX r14
+}
+
+Q_CORE_EXPORT asm
+int QBasicAtomicInt_fetchAndAddOrdered(volatile int *_q_value, int valueToAdd)
+{
+ CODE32
+ //R0 = _q_value
+ //R1 = valueToAdd
+ STMDB sp!,{r12,lr}
+retry_fetchAndAddOrdered
+ LDREX r2,[r0] //r2 = *_q_value
+ ADD r3,r2,r1 //r3 = r2 + r1
+ STREX r12,r3,[r0] //*_q_value = r3, r12 = error
+ TEQ r12,#0 //if error
+ BNE retry_fetchAndAddOrdered //then retry
+ MOV r0,r2 //return r2
+ LDMIA sp!,{r12,pc}
+}
+
+Q_CORE_EXPORT asm
+bool QBasicAtomicPointer_testAndSetOrdered(void * volatile *_q_value,
+ void *expectedValue,
+ void *newValue)
+{
+ CODE32
+ //R0 = _q_value
+ //R1 = expectedValue
+ //R2 = newValue
+retryPointer_testAndSetOrdered
+ LDREX r3,[r0] //r3 = *_q_value
+ EORS r3,r3,r1 //if (r3 == expectedValue) {
+ STREXEQ r3,r2,[r0] //*_q_value = newvalue, r3 = error
+ TEQEQ r3,#1 //if error
+ BEQ retryPointer_testAndSetOrdered //then goto retry }
+ RSBS r0,r3,#1 //return (r3 == 0)
+ MOVCC r0,#0
+ BX r14
+}
+
+Q_CORE_EXPORT asm
+void *QBasicAtomicPointer_fetchAndStoreOrdered(void * volatile *_q_value, void *newValue)
+{
+ CODE32
+ //R0 = _q_value
+ //R1 = newValue
+retryPointer_fetchAndStoreOrdered
+ LDREX r3,[r0] //r3 = *_q_value
+ STREX r2,r1,[r0] //*_q_value = newValue, r2 = error
+ TEQ r2,#0 //if error
+ BNE retryPointer_fetchAndStoreOrdered //then goto retry
+ MOV r0,r3 //return r3
+ BX r14
+}
+
+Q_CORE_EXPORT asm
+void *QBasicAtomicPointer_fetchAndAddOrdered(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+ CODE32
+ //R0 = _q_value
+ //R1 = valueToAdd
+ STMDB sp!,{r12,lr}
+retryPointer_fetchAndAddOrdered
+ LDREX r2,[r0] //r2 = *_q_value
+ ADD r3,r2,r1 //r3 = r2 + r1
+ STREX r12,r3,[r0] //*_q_value = r3, r12 = error
+ TEQ r12,#0 //if error
+ BNE retryPointer_fetchAndAddOrdered //then retry
+ MOV r0,r2 //return r2
+ LDMIA sp!,{r12,pc}
+}
+
+#pragma pop
+#elif defined (Q_CC_GCCE)
+Q_CORE_EXPORT __declspec( naked )
+bool QBasicAtomicInt_testAndSetOrdered(volatile int *_q_value, int expectedValue, int newValue)
+{
+ //R0 = _q_value
+ //R1 = expectedValue
+ //R2 = newValue
+ asm("retry_testAndSetOrdered:");
+ asm(" LDREX r3,[r0]"); //r3 = *_q_value
+ asm(" EORS r3,r3,r1"); //if (r3 == expectedValue) {
+ asm(" STREXEQ r3,r2,[r0]"); //*_q_value = newvalue, r3 = error
+ asm(" TEQEQ r3,#1"); //if error
+ asm(" BEQ retry_testAndSetOrdered"); //then goto retry }
+ asm(" RSBS r0,r3,#1"); //return (r3 == 0)
+ asm(" MOVCC r0,#0");
+ asm(" BX r14");
+}
+
+Q_CORE_EXPORT __declspec( naked )
+int QBasicAtomicInt_fetchAndStoreOrdered(volatile int *_q_value, int newValue)
+{
+//R0 = _q_value
+//R1 = newValue
+ asm("retry_fetchAndStoreOrdered:");
+ asm(" LDREX r3,[r0]"); //r3 = *_q_value
+ asm(" STREX r2,r1,[r0]"); //*_q_value = newValue, r2 = error
+ asm(" TEQ r2,#0"); //if error
+ asm(" BNE retry_fetchAndStoreOrdered"); //then goto retry
+ asm(" MOV r0,r3"); //return r3
+ asm(" BX r14");
+}
+
+Q_CORE_EXPORT __declspec( naked )
+int QBasicAtomicInt_fetchAndAddOrdered(volatile int *_q_value, int valueToAdd)
+{
+ //R0 = _q_value
+ //R1 = valueToAdd
+ asm(" STMDB sp!,{r12,lr}");
+ asm("retry_fetchAndAddOrdered:");
+ asm(" LDREX r2,[r0]"); //r2 = *_q_value
+ asm(" ADD r3,r2,r1 "); //r3 = r2 + r1
+ asm(" STREX r12,r3,[r0]"); //*_q_value = r3, r12 = error
+ asm(" TEQ r12,#0"); //if error
+ asm(" BNE retry_fetchAndAddOrdered"); //then retry
+ asm(" MOV r0,r2"); //return r2
+ asm(" LDMIA sp!,{r12,pc}");
+}
+
+Q_CORE_EXPORT __declspec( naked )
+bool QBasicAtomicPointer_testAndSetOrdered(void * volatile *_q_value,
+ void *expectedValue,
+ void *newValue)
+{
+ //R0 = _q_value
+ //R1 = expectedValue
+ //R2 = newValue
+ asm("retryPointer_testAndSetOrdered:");
+ asm(" LDREX r3,[r0]"); //r3 = *_q_value
+ asm(" EORS r3,r3,r1"); //if (r3 == expectedValue) {
+ asm(" STREXEQ r3,r2,[r0]"); //*_q_value = newvalue, r3 = error
+ asm(" TEQEQ r3,#1"); //if error
+ asm(" BEQ retryPointer_testAndSetOrdered"); //then goto retry }
+ asm(" RSBS r0,r3,#1"); //return (r3 == 0)
+ asm(" MOVCC r0,#0");
+ asm(" BX r14");
+}
+
+Q_CORE_EXPORT __declspec( naked )
+void *QBasicAtomicPointer_fetchAndStoreOrdered(void * volatile *_q_value, void *newValue)
+{
+ //R0 = _q_value
+ //R1 = newValue
+ asm("retryPointer_fetchAndStoreOrdered:");
+ asm(" LDREX r3,[r0]"); //r3 = *_q_value
+ asm(" STREX r2,r1,[r0]"); //*_q_value = newValue, r2 = error
+ asm(" TEQ r2,#0"); //if error
+ asm(" BNE retryPointer_fetchAndStoreOrdered"); //then goto retry
+ asm(" MOV r0,r3"); //return r3
+ asm(" BX r14");
+}
+
+Q_CORE_EXPORT __declspec( naked )
+void *QBasicAtomicPointer_fetchAndAddOrdered(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+ //R0 = _q_value
+ //R1 = valueToAdd
+ asm(" STMDB sp!,{r12,lr}");
+ asm("retryPointer_fetchAndAddOrdered:");
+ asm(" LDREX r2,[r0]"); //r2 = *_q_value
+ asm(" ADD r3,r2,r1"); //r3 = r2 + r1
+ asm(" STREX r12,r3,[r0]"); //*_q_value = r3, r12 = error
+ asm(" TEQ r12,#0"); //if error
+ asm(" BNE retryPointer_fetchAndAddOrdered"); //then retry
+ asm(" MOV r0,r2"); //return r2
+ asm(" LDMIA sp!,{r12,pc}");
+}
+#else
+#error unknown arm compiler
+#endif
+QT_END_NAMESPACE
+#endif
diff --git a/src/corelib/arch/qatomic_armv6.h b/src/corelib/arch/qatomic_armv6.h
index 28655df..1e9f0c4 100644
--- a/src/corelib/arch/qatomic_armv6.h
+++ b/src/corelib/arch/qatomic_armv6.h
@@ -45,7 +45,6 @@
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
-
#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
inline bool QBasicAtomicInt::isReferenceCountingNative()
@@ -101,7 +100,7 @@ template <typename T>
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
{ return false; }
-#ifdef !Q_CC_RVCT
+#ifndef Q_CC_RVCT
inline bool QBasicAtomicInt::ref()
{
diff --git a/src/corelib/arch/qatomic_symbian.h b/src/corelib/arch/qatomic_symbian.h
index 3721aca..571f628 100644
--- a/src/corelib/arch/qatomic_symbian.h
+++ b/src/corelib/arch/qatomic_symbian.h
@@ -42,12 +42,8 @@
#ifndef QATOMIC_SYMBIAN_H
#define QATOMIC_SYMBIAN_H
-#if defined(Q_CC_RVCT)
-# define QT_NO_ARM_EABI
-# include <QtCore/qatomic_arm.h>
-#elif defined(Q_CC_NOKIAX86) || defined(Q_CC_GCCE)
-# include <QtCore/qatomic_generic.h>
-#endif
+#include <qglobal.h>
+#include <e32std.h>
QT_BEGIN_HEADER
@@ -55,7 +51,237 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Core)
-// Empty, but needed to avoid warnings
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isReferenceCountingNative()
+{ return false; }
+inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isTestAndSetNative()
+{ return false; }
+inline bool QBasicAtomicInt::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndStoreNative()
+{ return false; }
+inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE
+
+inline bool QBasicAtomicInt::isFetchAndAddNative()
+{ return false; }
+inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
+{ return false; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
+{ return false; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
+{ return false; }
+
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
+{ return false; }
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
+{ return false; }
+
+Q_CORE_EXPORT bool QBasicAtomicInt_testAndSetOrdered(volatile int *, int, int);
+Q_CORE_EXPORT int QBasicAtomicInt_fetchAndStoreOrdered(volatile int *, int);
+Q_CORE_EXPORT int QBasicAtomicInt_fetchAndAddOrdered(volatile int *, int);
+
+Q_CORE_EXPORT bool QBasicAtomicPointer_testAndSetOrdered(void * volatile *, void *, void *);
+Q_CORE_EXPORT void *QBasicAtomicPointer_fetchAndStoreOrdered(void * volatile *, void *);
+Q_CORE_EXPORT void *QBasicAtomicPointer_fetchAndAddOrdered(void * volatile *, qptrdiff);
+
+// Reference counting
+
+//LockedInc and LockedDec are machine coded for ARMv6 (and future proof)
+inline bool QBasicAtomicInt::ref()
+{
+ int original = User::LockedInc((TInt&)_q_value);
+ return original != -1;
+}
+
+inline bool QBasicAtomicInt::deref()
+{
+ int original = User::LockedDec((TInt&)_q_value);
+ return original != 1;
+}
+
+// Test and set for integers
+
+inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+{
+ return QBasicAtomicInt_testAndSetOrdered(&_q_value, expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+// Fetch and store for integers
+
+inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+{
+ return QBasicAtomicInt_fetchAndStoreOrdered(&_q_value, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+// Fetch and add for integers
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
+{
+ return QBasicAtomicInt_fetchAndAddOrdered(&_q_value, valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+// Test and set for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+{
+ union { T * volatile * typed; void * volatile * voidp; } pointer;
+ pointer.typed = &_q_value;
+ return QBasicAtomicPointer_testAndSetOrdered(pointer.voidp, expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+// Fetch and store for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+{
+ union { T * volatile * typed; void * volatile * voidp; } pointer;
+ union { T *typed; void *voidp; } returnValue;
+ pointer.typed = &_q_value;
+ returnValue.voidp = QBasicAtomicPointer_fetchAndStoreOrdered(pointer.voidp, newValue);
+ return returnValue.typed;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+{
+ return fetchAndStoreOrdered(newValue);
+}
+
+// Fetch and add for pointers
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+{
+ union { T * volatile *typed; void * volatile *voidp; } pointer;
+ union { T *typed; void *voidp; } returnValue;
+ pointer.typed = &_q_value;
+ returnValue.voidp = QBasicAtomicPointer_fetchAndAddOrdered(pointer.voidp, valueToAdd * sizeof(T));
+ return returnValue.typed;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
QT_END_NAMESPACE
diff --git a/src/corelib/arch/symbian/arch.pri b/src/corelib/arch/symbian/arch.pri
index deb94b1..3ef1c9e 100644
--- a/src/corelib/arch/symbian/arch.pri
+++ b/src/corelib/arch/symbian/arch.pri
@@ -2,4 +2,4 @@
# Symbian architecture
#
SOURCES += $$QT_ARCH_CPP/qatomic_symbian.cpp \
- $$QT_ARCH_CPP/../generic/qatomic_generic_unix.cpp
+ $$QT_ARCH_CPP/../armv6/qatomic_generic_armv6.cpp
diff --git a/src/corelib/arch/symbian/qatomic_symbian.cpp b/src/corelib/arch/symbian/qatomic_symbian.cpp
index 8f02155..2ab5ae9 100644
--- a/src/corelib/arch/symbian/qatomic_symbian.cpp
+++ b/src/corelib/arch/symbian/qatomic_symbian.cpp
@@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE
// This way we can report on heap cells and handles that are really not owned by anything which still exists.
// This information can be used to detect whether memory leaks are happening, particularly if these numbers grow as the app is used more.
// This code is placed here as it happens to make it the very last static to be destroyed in a Qt app. The
-// reason assumed is that this file appears before any other file declaring static data in the generated
+// reason assumed is that this file appears before any other file declaring static data in the generated
// Symbian MMP file. This particular file was chosen as it is the earliest symbian specific file.
struct QSymbianPrintExitInfo
{
@@ -77,37 +77,95 @@ struct QSymbianPrintExitInfo
TInt initThreadHandleCount;
} symbian_printExitInfo;
-QT_END_NAMESPACE
+//For ARMv6, the generic atomics are machine coded
+#ifndef QT_HAVE_ARMV6
+class QCriticalSection
+{
+public:
+ QCriticalSection() { fastlock.CreateLocal(); }
+ ~QCriticalSection() { fastlock.Close(); }
+ void lock() { fastlock.Wait(); }
+ void unlock() { fastlock.Signal(); }
-#if defined(Q_CC_RVCT)
+private:
+ RFastLock fastlock;
+};
-#include "../arm/qatomic_arm.cpp"
+QCriticalSection qAtomicCriticalSection;
-QT_BEGIN_NAMESPACE
+Q_CORE_EXPORT
+bool QBasicAtomicInt_testAndSetOrdered(volatile int *_q_value, int expectedValue, int newValue)
+{
+ bool returnValue = false;
+ qAtomicCriticalSection.lock();
+ if (*_q_value == expectedValue) {
+ *_q_value = newValue;
+ returnValue = true;
+ }
+ qAtomicCriticalSection.unlock();
+ return returnValue;
+}
-Q_CORE_EXPORT __asm char q_atomic_swp(volatile char *ptr, char newval)
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndStoreOrdered(volatile int *_q_value, int newValue)
{
- add r2, pc, #0
- bx r2
- arm
- swpb r2,r1,[r0]
- mov r0, r2
- bx lr
- thumb
+ int returnValue;
+ qAtomicCriticalSection.lock();
+ returnValue = *_q_value;
+ *_q_value = newValue;
+ qAtomicCriticalSection.unlock();
+ return returnValue;
}
-Q_CORE_EXPORT __asm int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndAddOrdered(volatile int *_q_value, int valueToAdd)
{
- add r2, pc, #0
- bx r2
- arm
- swp r2,r1,[r0]
- mov r0, r2
- bx lr
- thumb
+ int returnValue;
+ qAtomicCriticalSection.lock();
+ returnValue = *_q_value;
+ *_q_value += valueToAdd;
+ qAtomicCriticalSection.unlock();
+ return returnValue;
}
-QT_END_NAMESPACE
+Q_CORE_EXPORT
+bool QBasicAtomicPointer_testAndSetOrdered(void * volatile *_q_value,
+ void *expectedValue,
+ void *newValue)
+{
+ bool returnValue = false;
+ qAtomicCriticalSection.lock();
+ if (*_q_value == expectedValue) {
+ *_q_value = newValue;
+ returnValue = true;
+ }
+ qAtomicCriticalSection.unlock();
+ return returnValue;
+}
-#endif // Q_CC_RVCT
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndStoreOrdered(void * volatile *_q_value, void *newValue)
+{
+ void *returnValue;
+ qAtomicCriticalSection.lock();
+ returnValue = *_q_value;
+ *_q_value = newValue;
+ qAtomicCriticalSection.unlock();
+ return returnValue;
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndAddOrdered(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+ void *returnValue;
+ qAtomicCriticalSection.lock();
+ returnValue = *_q_value;
+ *_q_value = reinterpret_cast<char *>(returnValue) + valueToAdd;
+ qAtomicCriticalSection.unlock();
+ return returnValue;
+}
+
+#endif // QT_HAVE_ARMV6
+
+QT_END_NAMESPACE
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index d113e02..9558256 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -437,13 +437,18 @@ namespace QT_NAMESPACE {}
#elif defined(__GCCE__)
# define Q_CC_GCCE
# define QT_VISIBILITY_AVAILABLE
+# if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__)
+# define QT_HAVE_ARMV6
+# endif
/* ARM Realview Compiler Suite
RVCT compiler also defines __EDG__ and __GNUC__ (if --gnu flag is given),
so check for it before that */
#elif defined(__ARMCC__) || defined(__CC_ARM)
# define Q_CC_RVCT
-
+# if __TARGET_ARCH_ARM >= 6
+# define QT_HAVE_ARMV6
+# endif
#elif defined(__GNUC__)
# define Q_CC_GNU
# define Q_C_CALLBACKS
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index c35c33a..628a109 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -370,7 +370,6 @@ symbian {
SOURCES += painting/qwindowsurface_s60.cpp
armccIfdefBlock = \
"$${LITERAL_HASH}if defined(ARMV6)" \
- "MACRO QT_HAVE_ARMV6" \
"SOURCEPATH painting" \
"SOURCE qblendfunctions_armv6_rvct.s" \
"SOURCE qdrawhelper_armv6_rvct.s" \
diff --git a/src/s60installs/eabi/QtCoreu.def b/src/s60installs/eabi/QtCoreu.def
index 487d989..e6345cb 100644
--- a/src/s60installs/eabi/QtCoreu.def
+++ b/src/s60installs/eabi/QtCoreu.def
@@ -13,7 +13,7 @@ EXPORTS
_Z11qt_int_sqrtj @ 12 NONAME
_Z12noforcepointR11QTextStream @ 13 NONAME
_Z12qSharedBuildv @ 14 NONAME
- _Z12q_atomic_swpPVcc @ 15 NONAME
+ _Z12q_atomic_swpPVcc @ 15 NONAME ABSENT
_Z12qt_s60GetRFsv @ 16 NONAME
_Z13lowercasebaseR11QTextStream @ 17 NONAME
_Z13qErrnoWarningPKcz @ 18 NONAME
@@ -24,7 +24,7 @@ EXPORTS
_Z15lowercasedigitsR11QTextStream @ 23 NONAME
_Z15qAddPostRoutinePFvvE @ 24 NONAME
_Z15qInitResourceIOv @ 25 NONAME
- _Z15qt_atomic_yieldPi @ 26 NONAME
+ _Z15qt_atomic_yieldPi @ 26 NONAME ABSENT
_Z15qt_error_stringi @ 27 NONAME
_Z15uppercasedigitsR11QTextStream @ 28 NONAME
_Z16qt_QString2HBufCRK7QString @ 29 NONAME
@@ -706,7 +706,7 @@ EXPORTS
_ZN15QAnimationGroupD0Ev @ 705 NONAME
_ZN15QAnimationGroupD1Ev @ 706 NONAME
_ZN15QAnimationGroupD2Ev @ 707 NONAME
- _ZN15QBasicAtomicInt20fetchAndStoreOrderedEi @ 708 NONAME
+ _ZN15QBasicAtomicInt20fetchAndStoreOrderedEi @ 708 NONAME ABSENT
_ZN15QDateTimeParser11parseFormatERK7QString @ 709 NONAME
_ZN15QLinkedListData11shared_nullE @ 710 NONAME DATA 20
_ZN15QObjectUserDataD0Ev @ 711 NONAME
@@ -3566,7 +3566,7 @@ EXPORTS
inflateSync @ 3565 NONAME
inflateSyncPoint @ 3566 NONAME
qMetaTypeGuiHelper @ 3567 NONAME DATA 4
- q_atomic_lock @ 3568 NONAME DATA 1
+ q_atomic_lock @ 3568 NONAME DATA 1 ABSENT
qt_addObject @ 3569 NONAME
qt_global_mutexpool @ 3570 NONAME DATA 4
qt_locale_initialized @ 3571 NONAME DATA 1