- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files
- Directories
- Examples

- File List
- File Members

# qatomic_armv6.h

Go to the documentation of this file.

    00001 /****************************************************************************
    00002 **
    00003 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
    00004 ** All rights reserved.
    00005 ** Contact: Nokia Corporation (qt-info@nokia.com)
    00006 **
    00007 ** This file is part of the QtCore module of the Qt Toolkit.
    00008 **
    00009 ** $QT_BEGIN_LICENSE:LGPL$
    00010 ** Commercial Usage
    00011 ** Licensees holding valid Qt Commercial licenses may use this file in
    00012 ** accordance with the Qt Commercial License Agreement provided with the
    00013 ** Software or, alternatively, in accordance with the terms contained in
    00014 ** a written agreement between you and Nokia.
    00015 **
    00016 ** GNU Lesser General Public License Usage
    00017 ** Alternatively, this file may be used under the terms of the GNU Lesser
    00018 ** General Public License version 2.1 as published by the Free Software
    00019 ** Foundation and appearing in the file LICENSE.LGPL included in the
    00020 ** packaging of this file.  Please review the following information to
    00021 ** ensure the GNU Lesser General Public License version 2.1 requirements
    00022 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    00023 **
    00024 ** In addition, as a special exception, Nokia gives you certain additional
    00025 ** rights.  These rights are described in the Nokia Qt LGPL Exception
    00026 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this module.
    00027 **
    00028 ** GNU General Public License Usage
    00029 ** Alternatively, this file may be used under the terms of the GNU
    00030 ** General Public License version 3.0 as published by the Free Software
    00031 ** Foundation and appearing in the file LICENSE.GPL included in the
    00032 ** packaging of this file.  Please review the following information to
    00033 ** ensure the GNU General Public License version 3.0 requirements will be
    00034 ** met: http://www.gnu.org/copyleft/gpl.html.
    00035 **
    00036 ** If you have questions regarding the use of this file, please contact
    00037 ** Nokia at qt-info@nokia.com.
    00038 ** $QT_END_LICENSE$
    00039 **
    00040 ****************************************************************************/
    00041
    00042 #ifndef QATOMIC_ARMV6_H
    00043 #define QATOMIC_ARMV6_H
    00044
    00045 QT_BEGIN_HEADER
    00046
    00047 QT_BEGIN_NAMESPACE
    00048 #define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
    00049
    00050 inline bool QBasicAtomicInt::isReferenceCountingNative()
    00051 { return true; }
    00052 inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
    00053 { return false; }
    00054
    00055 #define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
    00056
    00057 inline bool QBasicAtomicInt::isTestAndSetNative()
    00058 { return true; }
    00059 inline bool QBasicAtomicInt::isTestAndSetWaitFree()
    00060 { return false; }
    00061
    00062 #define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
    00063
    00064 inline bool QBasicAtomicInt::isFetchAndStoreNative()
    00065 { return true; }
    00066 inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
    00067 { return false; }
    00068
    00069 #define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
    00070
    00071 inline bool QBasicAtomicInt::isFetchAndAddNative()
    00072 { return true; }
    00073 inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
    00074 { return false; }
    00075
    00076 #define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
    00077
    00078 template <typename T>
    00079 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
    00080 { return true; }
    00081 template <typename T>
    00082 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
    00083 { return false; }
    00084
    00085 #define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
    00086
    00087 template <typename T>
    00088 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
    00089 { return true; }
    00090 template <typename T>
    00091 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
    00092 { return false; }
    00093
    00094 #define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
    00095
    00096 template <typename T>
    00097 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
    00098 { return true; }
    00099 template <typename T>
    00100 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
    00101 { return false; }
    00102
    00103 #ifndef Q_CC_RVCT
    00104
    00105 inline bool QBasicAtomicInt::ref()
    00106 {
    00107     register int newValue;
    00108     register int result;
    00109     asm volatile("0:\n"
    00110                  "ldrex %[newValue], [%[_q_value]]\n"
    00111                  "add %[newValue], %[newValue], #1\n"
    00112                  "strex %[result], %[newValue], [%[_q_value]]\n"
    00113                  "teq %[result], #0\n"
    00114                  "bne 0b\n"
    00115                  : [newValue] "=&r" (newValue),
    00116                    [result] "=&r" (result),
    00117                    "+m" (_q_value)
    00118                  : [_q_value] "r" (&_q_value)
    00119                  : "cc", "memory");
    00120     return newValue != 0;
    00121 }
    00122
    00123 inline bool QBasicAtomicInt::deref()
    00124 {
    00125     register int newValue;
    00126     register int result;
    00127     asm volatile("0:\n"
    00128                  "ldrex %[newValue], [%[_q_value]]\n"
    00129                  "sub %[newValue], %[newValue], #1\n"
    00130                  "strex %[result], %[newValue], [%[_q_value]]\n"
    00131                  "teq %[result], #0\n"
    00132                  "bne 0b\n"
    00133                  : [newValue] "=&r" (newValue),
    00134                    [result] "=&r" (result),
    00135                    "+m" (_q_value)
    00136                  : [_q_value] "r" (&_q_value)
    00137                  : "cc", "memory");
    00138     return newValue != 0;
    00139 }
    00140
    00141 inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
    00142 {
    00143     register int result;
    00144     asm volatile("0:\n"
    00145                  "ldrex %[result], [%[_q_value]]\n"
    00146                  "eors %[result], %[result], %[expectedValue]\n"
    00147                  "strexeq %[result], %[newValue], [%[_q_value]]\n"
    00148                  "teqeq %[result], #1\n"
    00149                  "beq 0b\n"
    00150                  : [result] "=&r" (result),
    00151                    "+m" (_q_value)
    00152                  : [expectedValue] "r" (expectedValue),
    00153                    [newValue] "r" (newValue),
    00154                    [_q_value] "r" (&_q_value)
    00155                  : "cc", "memory");
    00156     return result == 0;
    00157 }
    00158
    00159 inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
    00160 {
    00161     register int originalValue;
    00162     register int result;
    00163     asm volatile("0:\n"
    00164                  "ldrex %[originalValue], [%[_q_value]]\n"
    00165                  "strex %[result], %[newValue], [%[_q_value]]\n"
    00166                  "teq %[result], #0\n"
    00167                  "bne 0b\n"
    00168                  : [originalValue] "=&r" (originalValue),
    00169                    [result] "=&r" (result),
    00170                    "+m" (_q_value)
    00171                  : [newValue] "r" (newValue),
    00172                    [_q_value] "r" (&_q_value)
    00173                  : "cc", "memory");
    00174     return originalValue;
    00175 }
    00176
    00177 inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
    00178 {
    00179     register int originalValue;
    00180     register int newValue;
    00181     register int result;
    00182     asm volatile("0:\n"
    00183                  "ldrex %[originalValue], [%[_q_value]]\n"
    00184                  "add %[newValue], %[originalValue], %[valueToAdd]\n"
    00185                  "strex %[result], %[newValue], [%[_q_value]]\n"
    00186                  "teq %[result], #0\n"
    00187                  "bne 0b\n"
    00188                  : [originalValue] "=&r" (originalValue),
    00189                    [newValue] "=&r" (newValue),
    00190                    [result] "=&r" (result),
    00191                    "+m" (_q_value)
    00192                  : [valueToAdd] "r" (valueToAdd),
    00193                    [_q_value] "r" (&_q_value)
    00194                  : "cc", "memory");
    00195     return originalValue;
    00196 }
    00197
    00198 template <typename T>
    00199 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
    00200 {
    00201     register T *result;
    00202     asm volatile("0:\n"
    00203                  "ldrex %[result], [%[_q_value]]\n"
    00204                  "eors %[result], %[result], %[expectedValue]\n"
    00205                  "strexeq %[result], %[newValue], [%[_q_value]]\n"
    00206                  "teqeq %[result], #1\n"
    00207                  "beq 0b\n"
    00208                  : [result] "=&r" (result),
    00209                    "+m" (_q_value)
    00210                  : [expectedValue] "r" (expectedValue),
    00211                    [newValue] "r" (newValue),
    00212                    [_q_value] "r" (&_q_value)
    00213                  : "cc", "memory");
    00214     return result == 0;
    00215 }
    00216
    00217 template <typename T>
    00218 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
    00219 {
    00220     register T *originalValue;
    00221     register int result;
    00222     asm volatile("0:\n"
    00223                  "ldrex %[originalValue], [%[_q_value]]\n"
    00224                  "strex %[result], %[newValue], [%[_q_value]]\n"
    00225                  "teq %[result], #0\n"
    00226                  "bne 0b\n"
    00227                  : [originalValue] "=&r" (originalValue),
    00228                    [result] "=&r" (result),
    00229                    "+m" (_q_value)
    00230                  : [newValue] "r" (newValue),
    00231                    [_q_value] "r" (&_q_value)
    00232                  : "cc", "memory");
    00233     return originalValue;
    00234 }
    00235
    00236 template <typename T>
    00237 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
    00238 {
    00239     register T *originalValue;
    00240     register T *newValue;
    00241     register int result;
    00242     asm volatile("0:\n"
    00243                  "ldrex %[originalValue], [%[_q_value]]\n"
    00244                  "add %[newValue], %[originalValue], %[valueToAdd]\n"
    00245                  "strex %[result], %[newValue], [%[_q_value]]\n"
    00246                  "teq %[result], #0\n"
    00247                  "bne 0b\n"
    00248                  : [originalValue] "=&r" (originalValue),
    00249                    [newValue] "=&r" (newValue),
    00250                    [result] "=&r" (result),
    00251                    "+m" (_q_value)
    00252                  : [valueToAdd] "r" (valueToAdd * sizeof(T)),
    00253                    [_q_value] "r" (&_q_value)
    00254                  : "cc", "memory");
    00255     return originalValue;
    00256 }
    00257
    00258 #else
    00259 // This is Q_CC_RVCT
    00260
    00261 // RVCT inline assembly documentation:
    00262 // http://www.keil.com/support/man/docs/armcc/armcc_chdcffdb.htm
    00263 // RVCT embedded assembly documentation:
    00264 // http://www.keil.com/support/man/docs/armcc/armcc_chddbeib.htm
    00265
    00266 // save our pragma state and switch to ARM mode
    00267 #pragma push
    00268 #pragma arm
    00269
    00270 inline bool QBasicAtomicInt::ref()
    00271 {
    00272     register int newValue;
    00273     register int result;
    00274     retry:
    00275     __asm {
    00276         ldrex   newValue, [&_q_value]
    00277         add     newValue, newValue, #1
    00278         strex   result, newValue, [&_q_value]
    00279         teq     result, #0
    00280         bne     retry
    00281     }
    00282     return newValue != 0;
    00283 }
    00284
    00285 inline bool QBasicAtomicInt::deref()
    00286 {
    00287     register int newValue;
    00288     register int result;
    00289     retry:
    00290     __asm {
    00291         ldrex   newValue, [&_q_value]
    00292         sub     newValue, newValue, #1
    00293         strex   result, newValue, [&_q_value]
    00294         teq     result, #0
    00295         bne     retry
    00296     }
    00297     return newValue != 0;
    00298 }
    00299
    00300 inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
    00301 {
    00302     register int result;
    00303     retry:
    00304     __asm {
    00305         ldrex   result, [&_q_value]
    00306         eors    result, result, expectedValue
    00307         strexeq result, newValue, [&_q_value]
    00308         teqeq   result, #1
    00309         beq     retry
    00310     }
    00311     return result == 0;
    00312 }
    00313
    00314 inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
    00315 {
    00316     register int originalValue;
    00317     register int result;
    00318     retry:
    00319     __asm {
    00320         ldrex   originalValue, [&_q_value]
    00321         strex   result, newValue, [&_q_value]
    00322         teq     result, #0
    00323         bne     retry
    00324     }
    00325     return originalValue;
    00326 }
    00327
    00328 inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
    00329 {
    00330     register int originalValue;
    00331     register int newValue;
    00332     register int result;
    00333     retry:
    00334     __asm {
    00335         ldrex   originalValue, [&_q_value]
    00336         add     newValue, originalValue, valueToAdd
    00337         strex   result, newValue, [&_q_value]
    00338         teq     result, #0
    00339         bne     retry
    00340     }
    00341     return originalValue;
    00342 }
    00343
    00344 template <typename T>
    00345 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
    00346 {
    00347     register T *result;
    00348     retry:
    00349     __asm {
    00350         ldrex   result, [&_q_value]
    00351         eors    result, result, expectedValue
    00352         strexeq result, newValue, [&_q_value]
    00353         teqeq   result, #1
    00354         beq     retry
    00355     }
    00356     return result == 0;
    00357 }
    00358
    00359 template <typename T>
    00360 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
    00361 {
    00362     register T *originalValue;
    00363     register int result;
    00364     retry:
    00365     __asm {
    00366         ldrex   originalValue, [&_q_value]
    00367         strex   result, newValue, [&_q_value]
    00368         teq     result, #0
    00369         bne     retry
    00370     }
    00371     return originalValue;
    00372 }
    00373
    00374 template <typename T>
    00375 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
    00376 {
    00377     register T *originalValue;
    00378     register T *newValue;
    00379     register int result;
    00380     retry:
    00381     __asm {
    00382         ldrex   originalValue, [&_q_value]
    00383         add     newValue, originalValue, valueToAdd * sizeof(T)
    00384         strex   result, newValue, [&_q_value]
    00385         teq     result, #0
    00386         bne     retry
    00387     }
    00388     return originalValue;
    00389 }
    00390
    00391 // go back to the previous pragma state (probably Thumb mode)
    00392 #pragma pop
    00393 #endif
    00394
    00395 // common code
    00396
    00397 inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
    00398 {
    00399     return testAndSetOrdered(expectedValue, newValue);
    00400 }
    00401
    00402 inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
    00403 {
    00404     return testAndSetOrdered(expectedValue, newValue);
    00405 }
    00406
    00407 inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
    00408 {
    00409     return testAndSetOrdered(expectedValue, newValue);
    00410 }
    00411
    00412 inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
    00413 {
    00414     return fetchAndStoreOrdered(newValue);
    00415 }
    00416
    00417 inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
    00418 {
    00419     return fetchAndStoreOrdered(newValue);
    00420 }
    00421
    00422 inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
    00423 {
    00424     return fetchAndStoreOrdered(newValue);
    00425 }
    00426
    00427 inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
    00428 {
    00429     return fetchAndAddOrdered(valueToAdd);
    00430 }
    00431
    00432 inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
    00433 {
    00434     return fetchAndAddOrdered(valueToAdd);
    00435 }
    00436
    00437 inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
    00438 {
    00439     return fetchAndAddOrdered(valueToAdd);
    00440 }
    00441
    00442 template <typename T>
    00443 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
    00444 {
    00445     return testAndSetOrdered(expectedValue, newValue);
    00446 }
    00447
    00448 template <typename T>
    00449 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
    00450 {
    00451     return testAndSetOrdered(expectedValue, newValue);
    00452 }
    00453
    00454 template <typename T>
    00455 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
    00456 {
    00457     return testAndSetOrdered(expectedValue, newValue);
    00458 }
    00459
    00460 template <typename T>
    00461 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
    00462 {
    00463     return fetchAndStoreOrdered(newValue);
    00464 }
    00465
    00466 template <typename T>
    00467 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
    00468 {
    00469     return fetchAndStoreOrdered(newValue);
    00470 }
    00471
    00472 template <typename T>
    00473 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
    00474 {
    00475     return fetchAndStoreOrdered(newValue);
    00476 }
    00477
    00478 template <typename T>
    00479 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
    00480 {
    00481     return fetchAndAddOrdered(valueToAdd);
    00482 }
    00483
    00484 template <typename T>
    00485 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
    00486 {
    00487     return fetchAndAddOrdered(valueToAdd);
    00488 }
    00489
    00490 template <typename T>
    00491 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
    00492 {
    00493     return fetchAndAddOrdered(valueToAdd);
    00494 }
    00495
    00496 QT_END_NAMESPACE
    00497
    00498 QT_END_HEADER
    00499
    00500 #endif // QATOMIC_ARMV6_H