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

- File List
- File Members

# qatomic_ia64.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_IA64_H
    00043 #define QATOMIC_IA64_H
    00044
    00045 QT_BEGIN_HEADER
    00046
    00047 QT_BEGIN_NAMESPACE
    00048
    00049 #define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
    00050 #define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE
    00051
    00052 inline bool QBasicAtomicInt::isReferenceCountingNative()
    00053 { return true; }
    00054 inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
    00055 { return true; }
    00056
    00057 #define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
    00058 #define Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE
    00059
    00060 inline bool QBasicAtomicInt::isTestAndSetNative()
    00061 { return true; }
    00062 inline bool QBasicAtomicInt::isTestAndSetWaitFree()
    00063 { return true; }
    00064
    00065 #define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
    00066 #define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE
    00067
    00068 inline bool QBasicAtomicInt::isFetchAndStoreNative()
    00069 { return true; }
    00070 inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
    00071 { return true; }
    00072
    00073 #define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
    00074
    00075 inline bool QBasicAtomicInt::isFetchAndAddNative()
    00076 { return true; }
    00077 inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
    00078 { return false; }
    00079
    00080 #define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
    00081 #define Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE
    00082
    00083 template <typename T>
    00084 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
    00085 { return true; }
    00086 template <typename T>
    00087 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
    00088 { return true; }
    00089
    00090 #define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
    00091 #define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE
    00092
    00093 template <typename T>
    00094 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
    00095 { return true; }
    00096 template <typename T>
    00097 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
    00098 { return true; }
    00099
    00100 #define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
    00101
    00102 template <typename T>
    00103 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
    00104 { return true; }
    00105 template <typename T>
    00106 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
    00107 { return false; }
    00108
    00109 inline bool _q_ia64_fetchadd_immediate(register int value)
    00110 {
    00111     return value == 1 || value == -1
    00112         || value == 4 || value == -4
    00113         || value == 8 || value == -8
    00114         || value == 16 || value == -16;
    00115 }
    00116
    00117 #if defined(Q_CC_INTEL)
    00118
    00119 // intrinsics provided by the Intel C++ Compiler
    00120 #include <ia64intrin.h>
    00121
    00122 inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
    00123 {
    00124     return static_cast<int>(_InterlockedExchange(&_q_value, newValue));
    00125 }
    00126
    00127 inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
    00128 {
    00129     __memory_barrier();
    00130     return static_cast<int>(_InterlockedExchange(&_q_value, newValue));
    00131 }
    00132
    00133 inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
    00134 {
    00135     register int expectedValueCopy = expectedValue;
    00136     return (static_cast<int>(_InterlockedCompareExchange(&_q_value,
    00137                              newValue,
    00138                              expectedValueCopy))
    00139         == expectedValue);
    00140 }
    00141
    00142 inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
    00143 {
    00144     register int expectedValueCopy = expectedValue;
    00145     return (static_cast<int>(_InterlockedCompareExchange_acq(reinterpret_cast<volatile uint *>(&_q_value),
    00146                                  newValue,
    00147                                  expectedValueCopy))
    00148         == expectedValue);
    00149 }
    00150
    00151 inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
    00152 {
    00153     register int expectedValueCopy = expectedValue;
    00154     return (static_cast<int>(_InterlockedCompareExchange_rel(reinterpret_cast<volatile uint *>(&_q_value),
    00155                                  newValue,
    00156                                  expectedValueCopy))
    00157         == expectedValue);
    00158 }
    00159
    00160 inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
    00161 {
    00162     __memory_barrier();
    00163     return testAndSetAcquire(expectedValue, newValue);
    00164 }
    00165
    00166 inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
    00167 {
    00168     if (__builtin_constant_p(valueToAdd)) {
    00169         if (valueToAdd == 1)
    00170             return __fetchadd4_acq((unsigned int *)&_q_value, 1);
    00171         if (valueToAdd == -1)
    00172             return __fetchadd4_acq((unsigned int *)&_q_value, -1);
    00173     }
    00174     return _InterlockedExchangeAdd(&_q_value, valueToAdd);
    00175 }
    00176
    00177 inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
    00178 {
    00179     if (__builtin_constant_p(valueToAdd)) {
    00180         if (valueToAdd == 1)
    00181             return __fetchadd4_rel((unsigned int *)&_q_value, 1);
    00182         if (valueToAdd == -1)
    00183             return __fetchadd4_rel((unsigned int *)&_q_value, -1);
    00184     }
    00185     __memory_barrier();
    00186     return _InterlockedExchangeAdd(&_q_value, valueToAdd);
    00187 }
    00188
    00189 inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
    00190 {
    00191     __memory_barrier();
    00192     return fetchAndAddAcquire(valueToAdd);
    00193 }
    00194
    00195 inline bool QBasicAtomicInt::ref()
    00196 {
    00197     return _InterlockedIncrement(&_q_value) != 0;
    00198 }
    00199
    00200 inline bool QBasicAtomicInt::deref()
    00201 {
    00202     return _InterlockedDecrement(&_q_value) != 0;
    00203 }
    00204
    00205 template <typename T>
    00206 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
    00207 {
    00208     return (T *)_InterlockedExchangePointer(reinterpret_cast<void * volatile*>(&_q_value), newValue);
    00209 }
    00210
    00211 template <typename T>
    00212 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
    00213 {
    00214     __memory_barrier();
    00215     return fetchAndStoreAcquire(newValue);
    00216 }
    00217
    00218 template <typename T>
    00219 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
    00220 {
    00221     register T *expectedValueCopy = expectedValue;
    00222     return (_InterlockedCompareExchangePointer(reinterpret_cast<void * volatile*>(&_q_value),
    00223                            newValue,
    00224                            expectedValueCopy)
    00225         == expectedValue);
    00226 }
    00227
    00228 template <typename T>
    00229 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
    00230 {
    00231     union {
    00232         volatile void *x;
    00233         volatile unsigned long *p;
    00234     };
    00235     x = &_q_value;
    00236     register T *expectedValueCopy = expectedValue;
    00237     return (_InterlockedCompareExchange64_acq(p, quintptr(newValue), quintptr(expectedValueCopy))
    00238         == quintptr(expectedValue));
    00239 }
    00240
    00241 template <typename T>
    00242 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
    00243 {
    00244     union {
    00245         volatile void *x;
    00246         volatile unsigned long *p;
    00247     };
    00248     x = &_q_value;
    00249     register T *expectedValueCopy = expectedValue;
    00250     return (_InterlockedCompareExchange64_rel(p, quintptr(newValue), quintptr(expectedValueCopy))
    00251         == quintptr(expectedValue));
    00252 }
    00253
    00254 template <typename T>
    00255 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
    00256 {
    00257     __memory_barrier();
    00258     return testAndSetAcquire(expectedValue, newValue);
    00259 }
    00260
    00261 template <typename T>
    00262 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
    00263 {
    00264     return (T *)_InterlockedExchangeAdd64((volatile long *)&_q_value,
    00265                                           valueToAdd * sizeof(T));
    00266 }
    00267
    00268 template <typename T>
    00269 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
    00270 {
    00271     __memory_barrier();
    00272     return (T *)_InterlockedExchangeAdd64((volatile long *)&_q_value,
    00273                                           valueToAdd * sizeof(T));
    00274 }
    00275
    00276 template <typename T>
    00277 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
    00278 {
    00279     __memory_barrier();
    00280     return fetchAndAddAcquire(valueToAdd);
    00281 }
    00282
    00283 #else // !Q_CC_INTEL
    00284
    00285 #  if defined(Q_CC_GNU)
    00286
    00287 inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
    00288 {
    00289     int ret;
    00290     asm volatile("xchg4 %0=%1,%2\n"
    00291                  : "=r" (ret), "+m" (_q_value)
    00292                  : "r" (newValue)
    00293                  : "memory");
    00294     return ret;
    00295 }
    00296
    00297 inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
    00298 {
    00299     int ret;
    00300     asm volatile("mf\n"
    00301                  "xchg4 %0=%1,%2\n"
    00302                  : "=r" (ret), "+m" (_q_value)
    00303                  : "r" (newValue)
    00304                  : "memory");
    00305     return ret;
    00306 }
    00307
    00308 inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
    00309 {
    00310     int ret;
    00311     asm volatile("mov ar.ccv=%2\n"
    00312                  ";;\n"
    00313                  "cmpxchg4.acq %0=%1,%3,ar.ccv\n"
    00314                  : "=r" (ret), "+m" (_q_value)
    00315                  : "r" (expectedValue), "r" (newValue)
    00316                  : "memory");
    00317     return ret == expectedValue;
    00318 }
    00319
    00320 inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
    00321 {
    00322     int ret;
    00323     asm volatile("mov ar.ccv=%2\n"
    00324                  ";;\n"
    00325                  "cmpxchg4.rel %0=%1,%3,ar.ccv\n"
    00326                  : "=r" (ret), "+m" (_q_value)
    00327                  : "r" (expectedValue), "r" (newValue)
    00328                  : "memory");
    00329     return ret == expectedValue;
    00330 }
    00331
    00332 inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
    00333 {
    00334     int ret;
    00335
    00336 #if (__GNUC__ >= 4)
    00337     // We implement a fast fetch-and-add when we can
    00338     if (__builtin_constant_p(valueToAdd) && _q_ia64_fetchadd_immediate(valueToAdd)) {
    00339         asm volatile("fetchadd4.acq  %0=%1,%2\n"
    00340                      : "=r" (ret), "+m" (_q_value)
    00341                      : "i" (valueToAdd)
    00342                      : "memory");
    00343         return ret;
    00344     }
    00345 #endif
    00346
    00347     // otherwise, use a loop around test-and-set
    00348     ret = _q_value;
    00349     asm volatile("0:\n"
    00350                  "      mov           r9=%0\n"
    00351                  "      mov           ar.ccv=%0\n"
    00352                  "      add           %0=%0, %2\n"
    00353                  "      ;;\n"
    00354                  "      cmpxchg4.acq %0=%1,%0,ar.ccv\n"
    00355                  "      ;;\n"
    00356                  "      cmp.ne       p6,p0 = %0, r9\n"
    00357                  "(p6)  br.dptk      0b\n"
    00358                  "1:\n"
    00359                  : "+r" (ret), "+m" (_q_value)
    00360                  : "r" (valueToAdd)
    00361                  : "r9", "p6", "memory");
    00362     return ret;
    00363 }
    00364
    00365 inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
    00366 {
    00367     int ret;
    00368
    00369 #if (__GNUC__ >= 4)
    00370     // We implement a fast fetch-and-add when we can
    00371     if (__builtin_constant_p(valueToAdd) && _q_ia64_fetchadd_immediate(valueToAdd)) {
    00372         asm volatile("fetchadd4.rel  %0=%1,%2\n"
    00373                      : "=r" (ret), "+m" (_q_value)
    00374                      : "i" (valueToAdd)
    00375                      : "memory");
    00376         return ret;
    00377     }
    00378 #endif
    00379
    00380     // otherwise, use a loop around test-and-set
    00381     ret = _q_value;
    00382     asm volatile("0:\n"
    00383                  "      mov           r9=%0\n"
    00384                  "      mov           ar.ccv=%0\n"
    00385                  "      add           %0=%0, %2\n"
    00386                  "      ;;\n"
    00387                  "      cmpxchg4.rel %0=%1,%0,ar.ccv\n"
    00388                  "      ;;\n"
    00389                  "      cmp.ne       p6,p0 = %0, r9\n"
    00390                  "(p6)  br.dptk      0b\n"
    00391                  "1:\n"
    00392                  : "+r" (ret), "+m" (_q_value)
    00393                  : "r" (valueToAdd)
    00394                  : "r9", "p6", "memory");
    00395     return ret;
    00396 }
    00397
    00398 inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
    00399 {
    00400     asm volatile("mf" ::: "memory");
    00401     return fetchAndAddRelease(valueToAdd);
    00402 }
    00403
    00404 inline bool QBasicAtomicInt::ref()
    00405 {
    00406     int ret;
    00407     asm volatile("fetchadd4.acq %0=%1,1\n"
    00408                  : "=r" (ret), "+m" (_q_value)
    00409                  :
    00410                  : "memory");
    00411     return ret != -1;
    00412 }
    00413
    00414 inline bool QBasicAtomicInt::deref()
    00415 {
    00416     int ret;
    00417     asm volatile("fetchadd4.rel %0=%1,-1\n"
    00418                  : "=r" (ret), "+m" (_q_value)
    00419                  :
    00420                  : "memory");
    00421     return ret != 1;
    00422 }
    00423
    00424 template <typename T>
    00425 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
    00426 {
    00427     T *ret;
    00428     asm volatile("xchg8 %0=%1,%2\n"
    00429                  : "=r" (ret), "+m" (_q_value)
    00430                  : "r" (newValue)
    00431                  : "memory");
    00432     return ret;
    00433 }
    00434
    00435 template <typename T>
    00436 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
    00437 {
    00438     T *ret;
    00439     asm volatile("mf\n"
    00440                  "xchg8 %0=%1,%2\n"
    00441                  : "=r" (ret), "+m" (_q_value)
    00442                  : "r" (newValue)
    00443                  : "memory");
    00444     return ret;
    00445 }
    00446
    00447 template <typename T>
    00448 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
    00449 {
    00450     T *ret;
    00451     asm volatile("mov ar.ccv=%2\n"
    00452                  ";;\n"
    00453                  "cmpxchg8.acq %0=%1,%3,ar.ccv\n"
    00454                  : "=r" (ret), "+m" (_q_value)
    00455                  : "r" (expectedValue), "r" (newValue)
    00456                  : "memory");
    00457     return ret == expectedValue;
    00458 }
    00459
    00460 template <typename T>
    00461 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
    00462 {
    00463     T *ret;
    00464     asm volatile("mov ar.ccv=%2\n"
    00465                  ";;\n"
    00466                  "cmpxchg8.rel %0=%1,%3,ar.ccv\n"
    00467                  : "=r" (ret), "+m" (_q_value)
    00468                  : "r" (expectedValue), "r" (newValue)
    00469                  : "memory");
    00470     return ret == expectedValue;
    00471 }
    00472
    00473 template <typename T>
    00474 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
    00475 {
    00476     T *ret;
    00477
    00478 #if (__GNUC__ >= 4)
    00479     // We implement a fast fetch-and-add when we can
    00480     if (__builtin_constant_p(valueToAdd) && _q_ia64_fetchadd_immediate(valueToAdd * sizeof(T))) {
    00481         asm volatile("fetchadd8.acq  %0=%1,%2\n"
    00482                      : "=r" (ret), "+m" (_q_value)
    00483                      : "i" (valueToAdd * sizeof(T))
    00484                      : "memory");
    00485         return ret;
    00486     }
    00487 #endif
    00488
    00489     // otherwise, use a loop around test-and-set
    00490     ret = _q_value;
    00491     asm volatile("0:\n"
    00492                  "      mov           r9=%0\n"
    00493                  "      mov           ar.ccv=%0\n"
    00494                  "      add           %0=%0, %2\n"
    00495                  "      ;;\n"
    00496                  "      cmpxchg8.acq %0=%1,%0,ar.ccv\n"
    00497                  "      ;;\n"
    00498                  "      cmp.ne       p6,p0 = %0, r9\n"
    00499                  "(p6)  br.dptk      0b\n"
    00500                  "1:\n"
    00501                  : "+r" (ret), "+m" (_q_value)
    00502                  : "r" (valueToAdd * sizeof(T))
    00503                  : "r9", "p6", "memory");
    00504     return ret;
    00505 }
    00506
    00507 template <typename T>
    00508 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
    00509 {
    00510     T *ret;
    00511
    00512 #if (__GNUC__ >= 4)
    00513     // We implement a fast fetch-and-add when we can
    00514     if (__builtin_constant_p(valueToAdd) && _q_ia64_fetchadd_immediate(valueToAdd * sizeof(T))) {
    00515         asm volatile("fetchadd8.rel  %0=%1,%2\n"
    00516                      : "=r" (ret), "+m" (_q_value)
    00517                      : "i" (valueToAdd * sizeof(T))
    00518                      : "memory");
    00519         return ret;
    00520     }
    00521 #endif
    00522
    00523     // otherwise, use a loop around test-and-set
    00524     ret = _q_value;
    00525     asm volatile("0:\n"
    00526                  "      mov           r9=%0\n"
    00527                  "      mov           ar.ccv=%0\n"
    00528                  "      add           %0=%0, %2\n"
    00529                  "      ;;\n"
    00530                  "      cmpxchg8.rel %0=%1,%0,ar.ccv\n"
    00531                  "      ;;\n"
    00532                  "      cmp.ne       p6,p0 = %0, r9\n"
    00533                  "(p6)  br.dptk      0b\n"
    00534                  "1:\n"
    00535                  : "+r" (ret), "+m" (_q_value)
    00536                  : "r" (valueToAdd * sizeof(T))
    00537                  : "r9", "p6", "memory");
    00538     return ret;
    00539 }
    00540
    00541 template <typename T>
    00542 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
    00543 {
    00544     asm volatile("mf" ::: "memory");
    00545     return fetchAndAddRelease(valueToAdd);
    00546 }
    00547
    00548 #elif defined Q_CC_HPACC
    00549
    00550 QT_BEGIN_INCLUDE_NAMESPACE
    00551 #include <ia64/sys/inline.h>
    00552 QT_END_INCLUDE_NAMESPACE
    00553
    00554 #define FENCE (_Asm_fence)(_UP_CALL_FENCE | _UP_SYS_FENCE | _DOWN_CALL_FENCE | _DOWN_SYS_FENCE)
    00555
    00556 inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
    00557 {
    00558     return _Asm_xchg((_Asm_sz)_SZ_W, &_q_value, (unsigned)newValue,
    00559                      (_Asm_ldhint)_LDHINT_NONE, FENCE);
    00560 }
    00561
    00562 inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
    00563 {
    00564     _Asm_mf(FENCE);
    00565     return _Asm_xchg((_Asm_sz)_SZ_W, &_q_value, (unsigned)newValue,
    00566                      (_Asm_ldhint)_LDHINT_NONE, FENCE);
    00567 }
    00568
    00569 inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
    00570 {
    00571     _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (unsigned)expectedValue, FENCE);
    00572     int ret = _Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_ACQ,
    00573                            &_q_value, (unsigned)newValue, (_Asm_ldhint)_LDHINT_NONE);
    00574     return ret == expectedValue;
    00575 }
    00576
    00577 inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
    00578 {
    00579     _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (unsigned)expectedValue, FENCE);
    00580     int ret = _Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_REL,
    00581                            &_q_value, newValue, (_Asm_ldhint)_LDHINT_NONE);
    00582     return ret == expectedValue;
    00583 }
    00584
    00585 inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
    00586 {
    00587     if (valueToAdd == 1)
    00588         return _Asm_fetchadd((_Asm_fasz)_FASZ_W, (_Asm_sem)_SEM_ACQ,
    00589                              &_q_value, 1, (_Asm_ldhint)_LDHINT_NONE, FENCE);
    00590     else if (valueToAdd == -1)
    00591         return _Asm_fetchadd((_Asm_fasz)_FASZ_W, (_Asm_sem)_SEM_ACQ,
    00592                              &_q_value, -1, (_Asm_ldhint)_LDHINT_NONE, FENCE);
    00593
    00594     // implement the test-and-set loop
    00595     register int old, ret;
    00596     do {
    00597         old = _q_value;
    00598         _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (unsigned)old, FENCE);
    00599         ret = _Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_ACQ,
    00600                            &_q_value, old + valueToAdd, (_Asm_ldhint)_LDHINT_NONE);
    00601     } while (ret != old);
    00602     return old;
    00603 }
    00604
    00605 inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
    00606 {
    00607     if (valueToAdd == 1)
    00608         return _Asm_fetchadd((_Asm_fasz)_FASZ_W, (_Asm_sem)_SEM_REL,
    00609                              &_q_value, 1, (_Asm_ldhint)_LDHINT_NONE, FENCE);
    00610     else if (valueToAdd == -1)
    00611         return _Asm_fetchadd((_Asm_fasz)_FASZ_W, (_Asm_sem)_SEM_REL,
    00612                              &_q_value, -1, (_Asm_ldhint)_LDHINT_NONE, FENCE);
    00613
    00614     // implement the test-and-set loop
    00615     register int old, ret;
    00616     do {
    00617         old = _q_value;
    00618         _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (unsigned)old, FENCE);
    00619         ret = _Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_REL,
    00620                            &_q_value, old + valueToAdd, (_Asm_ldhint)_LDHINT_NONE);
    00621     } while (ret != old);
    00622     return old;
    00623 }
    00624
    00625 inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
    00626 {
    00627     _Asm_mf(FENCE);
    00628     return fetchAndAddAcquire(valueToAdd);
    00629 }
    00630
    00631 inline bool QBasicAtomicInt::ref()
    00632 {
    00633     return (int)_Asm_fetchadd((_Asm_fasz)_FASZ_W, (_Asm_sem)_SEM_ACQ,
    00634                               &_q_value, 1, (_Asm_ldhint)_LDHINT_NONE, FENCE) != -1;
    00635 }
    00636
    00637 inline bool QBasicAtomicInt::deref()
    00638 {
    00639     return (int)_Asm_fetchadd((_Asm_fasz)_FASZ_W, (_Asm_sem)_SEM_REL,
    00640                               &_q_value, -1, (_Asm_ldhint)_LDHINT_NONE, FENCE) != 1;
    00641 }
    00642
    00643 template <typename T>
    00644 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
    00645 {
    00646 #ifdef __LP64__
    00647     return (T *)_Asm_xchg((_Asm_sz)_SZ_D, &_q_value, (quint64)newValue,
    00648                           (_Asm_ldhint)_LDHINT_NONE, FENCE);
    00649 #else
    00650     return (T *)_Asm_xchg((_Asm_sz)_SZ_W, &_q_value, (quint32)newValue,
    00651                           (_Asm_ldhint)_LDHINT_NONE, FENCE);
    00652 #endif
    00653 }
    00654
    00655 template <typename T>
    00656 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
    00657 {
    00658     _Asm_mf(FENCE);
    00659     return fetchAndStoreAcquire(newValue);
    00660 }
    00661
    00662 template <typename T>
    00663 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
    00664 {
    00665 #ifdef __LP64__
    00666     _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint64)expectedValue, FENCE);
    00667     T *ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_D, (_Asm_sem)_SEM_ACQ,
    00668                                &_q_value, (quint64)newValue, (_Asm_ldhint)_LDHINT_NONE);
    00669 #else
    00670     _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint32)expectedValue, FENCE);
    00671     T *ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_ACQ,
    00672                                &_q_value, (quint32)newValue, (_Asm_ldhint)_LDHINT_NONE);
    00673 #endif
    00674     return ret == expectedValue;
    00675 }
    00676
    00677 template <typename T>
    00678 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
    00679 {
    00680 #ifdef __LP64__
    00681     _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint64)expectedValue, FENCE);
    00682     T *ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_D, (_Asm_sem)_SEM_REL,
    00683                                &_q_value, (quint64)newValue, (_Asm_ldhint)_LDHINT_NONE);
    00684 #else
    00685     _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint32)expectedValue, FENCE);
    00686     T *ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_REL,
    00687                                &_q_value, (quint32)newValue, (_Asm_ldhint)_LDHINT_NONE);
    00688 #endif
    00689     return ret == expectedValue;
    00690 }
    00691
    00692 template <typename T>
    00693 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
    00694 {
    00695     // implement the test-and-set loop
    00696     register T *old, *ret;
    00697     do {
    00698         old = _q_value;
    00699 #ifdef __LP64__
    00700         _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint64)old, FENCE);
    00701         ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_D, (_Asm_sem)_SEM_ACQ,
    00702                                 &_q_value, (quint64)(old + valueToAdd),
    00703                                 (_Asm_ldhint)_LDHINT_NONE);
    00704 #else
    00705         _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint32)old, FENCE);
    00706         ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_ACQ,
    00707                                 &_q_value, (quint32)(old + valueToAdd),
    00708                                 (_Asm_ldhint)_LDHINT_NONE);
    00709 #endif
    00710     } while (old != ret);
    00711     return old;
    00712 }
    00713
    00714 template <typename T>
    00715 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
    00716 {
    00717     // implement the test-and-set loop
    00718     register T *old, *ret;
    00719     do {
    00720         old = _q_value;
    00721 #ifdef __LP64__
    00722         _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint64)old, FENCE);
    00723         ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_D, (_Asm_sem)_SEM_REL,
    00724                                 &_q_value, (quint64)(old + valueToAdd),
    00725                                 (_Asm_ldhint)_LDHINT_NONE);
    00726 #else
    00727         _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint32)old, FENCE);
    00728         ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_REL,
    00729                                 &_q_value, (quint32)(old + valueToAdd),
    00730                                 (_Asm_ldhint)_LDHINT_NONE);
    00731 #endif
    00732     } while (old != ret);
    00733     return old;
    00734 }
    00735
    00736 template <typename T>
    00737 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
    00738 {
    00739     _Asm_mf(FENCE);
    00740     return fetchAndAddAcquire(valueToAdd);
    00741 }
    00742
    00743 #else
    00744
    00745 extern "C" {
    00746     Q_CORE_EXPORT int q_atomic_test_and_set_int(volatile int *ptr, int expected, int newval);
    00747     Q_CORE_EXPORT int q_atomic_test_and_set_ptr(volatile void *ptr, void *expected, void *newval);
    00748 } // extern "C"
    00749
    00750 #endif
    00751
    00752 inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
    00753 {
    00754     return testAndSetAcquire(expectedValue, newValue);
    00755 }
    00756
    00757 inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
    00758 {
    00759     return testAndSetAcquire(expectedValue, newValue);
    00760 }
    00761
    00762 template <typename T>
    00763 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
    00764 {
    00765     return testAndSetAcquire(expectedValue, newValue);
    00766 }
    00767
    00768 template <typename T>
    00769 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
    00770 {
    00771     return testAndSetAcquire(expectedValue, newValue);
    00772 }
    00773
    00774 #endif // Q_CC_INTEL
    00775
    00776 inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
    00777 {
    00778     return fetchAndStoreAcquire(newValue);
    00779 }
    00780
    00781 inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
    00782 {
    00783     return fetchAndStoreRelease(newValue);
    00784 }
    00785
    00786 inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
    00787 {
    00788     return fetchAndAddAcquire(valueToAdd);
    00789 }
    00790
    00791 template <typename T>
    00792 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
    00793 {
    00794     return fetchAndStoreAcquire(newValue);
    00795 }
    00796
    00797 template <typename T>
    00798 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
    00799 {
    00800     return fetchAndStoreRelaxed(newValue);
    00801 }
    00802
    00803 template <typename T>
    00804 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
    00805 {
    00806     return fetchAndAddAcquire(valueToAdd);
    00807 }
    00808
    00809 QT_END_NAMESPACE
    00810
    00811 QT_END_HEADER
    00812
    00813 #endif // QATOMIC_IA64_H