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