src/corelib/arch/symbian/qatomic_symbian.cpp
changeset 19 fcece45ef507
parent 18 2f34d5167611
--- a/src/corelib/arch/symbian/qatomic_symbian.cpp	Fri Apr 16 15:50:13 2010 +0300
+++ b/src/corelib/arch/symbian/qatomic_symbian.cpp	Mon May 03 13:17:34 2010 +0300
@@ -42,6 +42,10 @@
 #include <QtCore/qglobal.h>
 #include <QtCore/qatomic.h>
 
+#ifdef SYMBIAN_E32_ATOMIC_API
+#include <e32atomics.h>
+#endif
+
 #include <e32debug.h>
 
 QT_BEGIN_NAMESPACE
@@ -79,7 +83,7 @@
 
 Q_CORE_EXPORT bool QBasicAtomicInt::isReferenceCountingNative()
 {
-#ifdef QT_HAVE_ARMV6
+#if !defined(SYMBIAN_E32_ATOMIC_API) && defined(QT_HAVE_ARMV6)
     return true;
 #else
     return false;
@@ -88,7 +92,7 @@
 
 Q_CORE_EXPORT bool QBasicAtomicInt::isTestAndSetNative()
 {
-#ifdef QT_HAVE_ARMV6
+#if !defined(SYMBIAN_E32_ATOMIC_API) && defined(QT_HAVE_ARMV6)
     return true;
 #else
     return false;
@@ -97,7 +101,7 @@
 
 Q_CORE_EXPORT bool QBasicAtomicInt::isFetchAndStoreNative()
 {
-#ifdef QT_HAVE_ARMV6
+#if !defined(SYMBIAN_E32_ATOMIC_API) && defined(QT_HAVE_ARMV6)
     return true;
 #else
     return false;
@@ -106,7 +110,7 @@
 
 Q_CORE_EXPORT bool QBasicAtomicInt::isFetchAndAddNative()
 {
-#ifdef QT_HAVE_ARMV6
+#if !defined(SYMBIAN_E32_ATOMIC_API) && defined(QT_HAVE_ARMV6)
     return true;
 #else
     return false;
@@ -115,7 +119,7 @@
 
 Q_CORE_EXPORT bool QBasicAtomicPointer_isTestAndSetNative()
 {
-#ifdef QT_HAVE_ARMV6
+#if !defined(SYMBIAN_E32_ATOMIC_API) && defined(QT_HAVE_ARMV6)
     return true;
 #else
     return false;
@@ -124,7 +128,7 @@
 
 Q_CORE_EXPORT bool QBasicAtomicPointer_isFetchAndStoreNative()
 {
-#ifdef QT_HAVE_ARMV6
+#if !defined(SYMBIAN_E32_ATOMIC_API) && defined(QT_HAVE_ARMV6)
     return true;
 #else
     return false;
@@ -133,13 +137,187 @@
 
 Q_CORE_EXPORT bool QBasicAtomicPointer_isFetchAndAddNative()
 {
-#ifdef QT_HAVE_ARMV6
+#if !defined(SYMBIAN_E32_ATOMIC_API) && defined(QT_HAVE_ARMV6)
     return true;
 #else
     return false;
 #endif
 }
 
+#ifdef SYMBIAN_E32_ATOMIC_API
+//Symbian's API is SMP-safe when using SMP kernel, and cheap when using uniprocessor kernel
+
+//generate compiler error if casting assumptions are wrong (symbian64?)
+__ASSERT_COMPILE(sizeof(int) == sizeof(TUint32));
+__ASSERT_COMPILE(sizeof(void *) == sizeof(TUint32));
+
+Q_CORE_EXPORT
+bool QBasicAtomicInt_testAndSetOrdered(volatile int *_q_value, int expectedValue, int newValue)
+{
+    return static_cast<bool>(__e32_atomic_cas_ord32(_q_value,
+        reinterpret_cast<TUint32*>(&expectedValue), newValue));
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicInt_testAndSetRelaxed(volatile int *_q_value, int expectedValue, int newValue)
+{
+    return static_cast<bool>(__e32_atomic_cas_rlx32(_q_value,
+        reinterpret_cast<TUint32*>(&expectedValue), newValue));
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicInt_testAndSetAcquire(volatile int *_q_value, int expectedValue, int newValue)
+{
+    return static_cast<bool>(__e32_atomic_cas_acq32(_q_value,
+        reinterpret_cast<TUint32*>(&expectedValue), newValue));
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicInt_testAndSetRelease(volatile int *_q_value, int expectedValue, int newValue)
+{
+    return static_cast<bool>(__e32_atomic_cas_rel32(_q_value,
+        reinterpret_cast<TUint32*>(&expectedValue), newValue));
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndStoreOrdered(volatile int *_q_value, int newValue)
+{
+    return static_cast<int>(__e32_atomic_swp_ord32(_q_value, newValue));
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndStoreRelaxed(volatile int *_q_value, int newValue)
+{
+    return static_cast<int>(__e32_atomic_swp_rlx32(_q_value, newValue));
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndStoreAcquire(volatile int *_q_value, int newValue)
+{
+    return static_cast<int>(__e32_atomic_swp_acq32(_q_value, newValue));
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndStoreRelease(volatile int *_q_value, int newValue)
+{
+    return static_cast<int>(__e32_atomic_swp_rel32(_q_value, newValue));
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndAddOrdered(volatile int *_q_value, int valueToAdd)
+{
+    return static_cast<int>(__e32_atomic_add_ord32(_q_value, valueToAdd));
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndAddRelaxed(volatile int *_q_value, int valueToAdd)
+{
+    return static_cast<int>(__e32_atomic_add_rlx32(_q_value, valueToAdd));
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndAddAcquire(volatile int *_q_value, int valueToAdd)
+{
+    return static_cast<int>(__e32_atomic_add_acq32(_q_value, valueToAdd));
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndAddRelease(volatile int *_q_value, int valueToAdd)
+{
+    return static_cast<int>(__e32_atomic_add_rel32(_q_value, valueToAdd));
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicPointer_testAndSetOrdered(void * volatile *_q_value,
+                                           void *expectedValue,
+                                           void *newValue)
+{
+    return static_cast<bool>(__e32_atomic_cas_ord_ptr(_q_value,
+        &expectedValue,
+        newValue));
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicPointer_testAndSetRelaxed(void * volatile *_q_value,
+                                           void *expectedValue,
+                                           void *newValue)
+{
+    return static_cast<bool>(__e32_atomic_cas_rlx_ptr(_q_value,
+        &expectedValue,
+        newValue));
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicPointer_testAndSetAcquire(void * volatile *_q_value,
+                                           void *expectedValue,
+                                           void *newValue)
+{
+    return static_cast<bool>(__e32_atomic_cas_acq_ptr(_q_value,
+        &expectedValue,
+        newValue));
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicPointer_testAndSetRelease(void * volatile *_q_value,
+                                           void *expectedValue,
+                                           void *newValue)
+{
+    return static_cast<bool>(__e32_atomic_cas_rel_ptr(_q_value,
+        &expectedValue,
+        newValue));
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndStoreOrdered(void * volatile *_q_value, void *newValue)
+{
+    return __e32_atomic_swp_ord_ptr(_q_value, newValue);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndStoreRelaxed(void * volatile *_q_value, void *newValue)
+{
+    return __e32_atomic_swp_rlx_ptr(_q_value, newValue);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndStoreAcquire(void * volatile *_q_value, void *newValue)
+{
+    return __e32_atomic_swp_acq_ptr(_q_value, newValue);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndStoreRelease(void * volatile *_q_value, void *newValue)
+{
+    return __e32_atomic_swp_rel_ptr(_q_value, newValue);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndAddOrdered(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+    return __e32_atomic_add_ord_ptr(_q_value, valueToAdd);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndAddRelaxed(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+    return __e32_atomic_add_rlx_ptr(_q_value, valueToAdd);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndAddAcquire(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+    return __e32_atomic_add_acq_ptr(_q_value, valueToAdd);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndAddRelease(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+    return __e32_atomic_add_rel_ptr(_q_value, valueToAdd);
+}
+
+#else
+//Symbian kernels 9.4 and earlier don't expose a suitable API
+
 //For ARMv6, the generic atomics are machine coded
 #ifndef QT_HAVE_ARMV6
 
@@ -229,6 +407,121 @@
     return returnValue;
 }
 
+Q_CORE_EXPORT
+bool QBasicAtomicInt_testAndSetRelaxed(volatile int *_q_value, int expectedValue, int newValue)
+{
+    return QBasicAtomicInt_testAndSetOrdered(_q_value, expectedValue, newValue);
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicInt_testAndSetAcquire(volatile int *_q_value, int expectedValue, int newValue)
+{
+    return QBasicAtomicInt_testAndSetOrdered(_q_value, expectedValue, newValue);
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicInt_testAndSetRelease(volatile int *_q_value, int expectedValue, int newValue)
+{
+    return QBasicAtomicInt_testAndSetOrdered(_q_value, expectedValue, newValue);
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndStoreRelaxed(volatile int *_q_value, int newValue)
+{
+    return QBasicAtomicInt_fetchAndStoreOrdered(_q_value, newValue);
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndStoreAcquire(volatile int *_q_value, int newValue)
+{
+    return QBasicAtomicInt_fetchAndStoreOrdered(_q_value, newValue);
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndStoreRelease(volatile int *_q_value, int newValue)
+{
+    return QBasicAtomicInt_fetchAndStoreOrdered(_q_value, newValue);
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndAddRelaxed(volatile int *_q_value, int valueToAdd)
+{
+    return QBasicAtomicInt_fetchAndAddOrdered(_q_value, valueToAdd);
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndAddAcquire(volatile int *_q_value, int valueToAdd)
+{
+    return QBasicAtomicInt_fetchAndAddOrdered(_q_value, valueToAdd);
+}
+
+Q_CORE_EXPORT
+int QBasicAtomicInt_fetchAndAddRelease(volatile int *_q_value, int valueToAdd)
+{
+    return QBasicAtomicInt_fetchAndAddOrdered(_q_value, valueToAdd);
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicPointer_testAndSetRelaxed(void * volatile *_q_value,
+                                           void *expectedValue,
+                                           void *newValue)
+{
+    return QBasicAtomicPointer_testAndSetOrdered(_q_value, expectedValue, newValue);
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicPointer_testAndSetAcquire(void * volatile *_q_value,
+                                           void *expectedValue,
+                                           void *newValue)
+{
+    return QBasicAtomicPointer_testAndSetOrdered(_q_value, expectedValue, newValue);
+}
+
+Q_CORE_EXPORT
+bool QBasicAtomicPointer_testAndSetRelease(void * volatile *_q_value,
+                                           void *expectedValue,
+                                           void *newValue)
+{
+    return QBasicAtomicPointer_testAndSetOrdered(_q_value, expectedValue, newValue);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndStoreRelaxed(void * volatile *_q_value, void *newValue)
+{
+    return QBasicAtomicPointer_fetchAndStoreOrdered(_q_value, newValue);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndStoreAcquire(void * volatile *_q_value, void *newValue)
+{
+    return QBasicAtomicPointer_fetchAndStoreOrdered(_q_value, newValue);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndStoreRelease(void * volatile *_q_value, void *newValue)
+{
+    return QBasicAtomicPointer_fetchAndStoreOrdered(_q_value, newValue);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndAddRelaxed(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+    return QBasicAtomicPointer_fetchAndAddOrdered(_q_value, valueToAdd);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndAddAcquire(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+    return QBasicAtomicPointer_fetchAndAddOrdered(_q_value, valueToAdd);
+}
+
+Q_CORE_EXPORT
+void *QBasicAtomicPointer_fetchAndAddRelease(void * volatile *_q_value, qptrdiff valueToAdd)
+{
+    return QBasicAtomicPointer_fetchAndAddOrdered(_q_value, valueToAdd);
+}
+
 #endif // QT_HAVE_ARMV6
+#endif // SYMBIAN_E32_ATOMIC_API
 
 QT_END_NAMESPACE