00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }
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