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_ARM_H
00043 #define QATOMIC_ARM_H
00044
00045 QT_BEGIN_HEADER
00046
00047 QT_BEGIN_NAMESPACE
00048
00049 #define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE
00050
00051 inline bool QBasicAtomicInt::isReferenceCountingNative()
00052 { return false; }
00053 inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
00054 { return false; }
00055
00056 #define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE
00057
00058 inline bool QBasicAtomicInt::isTestAndSetNative()
00059 { return false; }
00060 inline bool QBasicAtomicInt::isTestAndSetWaitFree()
00061 { return false; }
00062
00063 #define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
00064 #define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE
00065
00066 inline bool QBasicAtomicInt::isFetchAndStoreNative()
00067 { return true; }
00068 inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
00069 { return true; }
00070
00071 #define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE
00072
00073 inline bool QBasicAtomicInt::isFetchAndAddNative()
00074 { return false; }
00075 inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
00076 { return false; }
00077
00078 #define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE
00079
00080 template <typename T>
00081 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
00082 { return false; }
00083 template <typename T>
00084 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
00085 { return false; }
00086
00087 #define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
00088 #define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE
00089
00090 template <typename T>
00091 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
00092 { return true; }
00093 template <typename T>
00094 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
00095 { return true; }
00096
00097 #define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE
00098
00099 template <typename T>
00100 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
00101 { return false; }
00102 template <typename T>
00103 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
00104 { return false; }
00105
00106 #ifndef QT_NO_ARM_EABI
00107
00108
00109 extern "C" typedef int (qt_atomic_eabi_cmpxchg_int_t)(int oldval, int newval, volatile int *ptr);
00110 extern "C" typedef int (qt_atomic_eabi_cmpxchg_ptr_t)(void *oldval, void *newval, volatile void *ptr);
00111 #define qt_atomic_eabi_cmpxchg_int (*reinterpret_cast<qt_atomic_eabi_cmpxchg_int_t *>(0xffff0fc0))
00112 #define qt_atomic_eabi_cmpxchg_ptr (*reinterpret_cast<qt_atomic_eabi_cmpxchg_ptr_t *>(0xffff0fc0))
00113
00114 #else
00115
00116 extern Q_CORE_EXPORT char q_atomic_lock;
00117 Q_CORE_EXPORT void qt_atomic_yield(int *);
00118
00119 #ifdef Q_CC_RVCT
00120
00121 Q_CORE_EXPORT __asm char q_atomic_swp(volatile char *ptr, char newval);
00122
00123 #else
00124
00125 inline char q_atomic_swp(volatile char *ptr, char newval)
00126 {
00127 register char ret;
00128 asm volatile("swpb %0,%2,[%3]"
00129 : "=&r"(ret), "=m" (*ptr)
00130 : "r"(newval), "r"(ptr)
00131 : "cc", "memory");
00132 return ret;
00133 }
00134
00135 #endif // Q_CC_RVCT
00136
00137 #endif // QT_NO_ARM_EABI
00138
00139
00140
00141 inline bool QBasicAtomicInt::ref()
00142 {
00143 #ifndef QT_NO_ARM_EABI
00144 register int originalValue;
00145 register int newValue;
00146 do {
00147 originalValue = _q_value;
00148 newValue = originalValue + 1;
00149 } while (qt_atomic_eabi_cmpxchg_int(originalValue, newValue, &_q_value) != 0);
00150 return newValue != 0;
00151 #else
00152 int count = 0;
00153 while (q_atomic_swp(&q_atomic_lock, ~0) != 0)
00154 qt_atomic_yield(&count);
00155 int originalValue = _q_value++;
00156 q_atomic_swp(&q_atomic_lock, 0);
00157 return originalValue != -1;
00158 #endif
00159 }
00160
00161 inline bool QBasicAtomicInt::deref()
00162 {
00163 #ifndef QT_NO_ARM_EABI
00164 register int originalValue;
00165 register int newValue;
00166 do {
00167 originalValue = _q_value;
00168 newValue = originalValue - 1;
00169 } while (qt_atomic_eabi_cmpxchg_int(originalValue, newValue, &_q_value) != 0);
00170 return newValue != 0;
00171 #else
00172 int count = 0;
00173 while (q_atomic_swp(&q_atomic_lock, ~0) != 0)
00174 qt_atomic_yield(&count);
00175 int originalValue = _q_value--;
00176 q_atomic_swp(&q_atomic_lock, 0);
00177 return originalValue != 1;
00178 #endif
00179 }
00180
00181
00182
00183 inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
00184 {
00185 #ifndef QT_NO_ARM_EABI
00186 register int originalValue;
00187 do {
00188 originalValue = _q_value;
00189 if (originalValue != expectedValue)
00190 return false;
00191 } while (qt_atomic_eabi_cmpxchg_int(expectedValue, newValue, &_q_value) != 0);
00192 return true;
00193 #else
00194 bool returnValue = false;
00195 int count = 0;
00196 while (q_atomic_swp(&q_atomic_lock, ~0) != 0)
00197 qt_atomic_yield(&count);
00198 if (_q_value == expectedValue) {
00199 _q_value = newValue;
00200 returnValue = true;
00201 }
00202 q_atomic_swp(&q_atomic_lock, 0);
00203 return returnValue;
00204 #endif
00205 }
00206
00207 inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
00208 {
00209 return testAndSetOrdered(expectedValue, newValue);
00210 }
00211
00212 inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
00213 {
00214 return testAndSetOrdered(expectedValue, newValue);
00215 }
00216
00217 inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
00218 {
00219 return testAndSetOrdered(expectedValue, newValue);
00220 }
00221
00222
00223
00224 #ifndef Q_CC_RVCT
00225
00226 inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
00227 {
00228 int originalValue;
00229 asm volatile("swp %0,%2,[%3]"
00230 : "=&r"(originalValue), "=m" (_q_value)
00231 : "r"(newValue), "r"(&_q_value)
00232 : "cc", "memory");
00233 return originalValue;
00234 }
00235
00236 #endif
00237
00238 inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
00239 {
00240 return fetchAndStoreOrdered(newValue);
00241 }
00242
00243 inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
00244 {
00245 return fetchAndStoreOrdered(newValue);
00246 }
00247
00248 inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
00249 {
00250 return fetchAndStoreOrdered(newValue);
00251 }
00252
00253
00254
00255 inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
00256 {
00257 #ifndef QT_NO_ARM_EABI
00258 register int originalValue;
00259 register int newValue;
00260 do {
00261 originalValue = _q_value;
00262 newValue = originalValue + valueToAdd;
00263 } while (qt_atomic_eabi_cmpxchg_int(originalValue, newValue, &_q_value) != 0);
00264 return originalValue;
00265 #else
00266 int count = 0;
00267 while (q_atomic_swp(&q_atomic_lock, ~0) != 0)
00268 qt_atomic_yield(&count);
00269 int originalValue = _q_value;
00270 _q_value += valueToAdd;
00271 q_atomic_swp(&q_atomic_lock, 0);
00272 return originalValue;
00273 #endif
00274 }
00275
00276 inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
00277 {
00278 return fetchAndAddOrdered(valueToAdd);
00279 }
00280
00281 inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
00282 {
00283 return fetchAndAddOrdered(valueToAdd);
00284 }
00285
00286 inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
00287 {
00288 return fetchAndAddOrdered(valueToAdd);
00289 }
00290
00291
00292
00293 template <typename T>
00294 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
00295 {
00296 #ifndef QT_NO_ARM_EABI
00297 register T *originalValue;
00298 do {
00299 originalValue = _q_value;
00300 if (originalValue != expectedValue)
00301 return false;
00302 } while (qt_atomic_eabi_cmpxchg_ptr(expectedValue, newValue, &_q_value) != 0);
00303 return true;
00304 #else
00305 bool returnValue = false;
00306 int count = 0;
00307 while (q_atomic_swp(&q_atomic_lock, ~0) != 0)
00308 qt_atomic_yield(&count);
00309 if (_q_value == expectedValue) {
00310 _q_value = newValue;
00311 returnValue = true;
00312 }
00313 q_atomic_swp(&q_atomic_lock, 0);
00314 return returnValue;
00315 #endif
00316 }
00317
00318 template <typename T>
00319 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
00320 {
00321 return testAndSetOrdered(expectedValue, newValue);
00322 }
00323
00324 template <typename T>
00325 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
00326 {
00327 return testAndSetOrdered(expectedValue, newValue);
00328 }
00329
00330 template <typename T>
00331 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
00332 {
00333 return testAndSetOrdered(expectedValue, newValue);
00334 }
00335
00336
00337
00338 #ifdef Q_CC_RVCT
00339
00340 template <typename T>
00341 __asm T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
00342 {
00343 add r2, pc, #0
00344 bx r2
00345 arm
00346 swp r2,r1,[r0]
00347 mov r0, r2
00348 bx lr
00349 thumb
00350 }
00351
00352 #else
00353
00354 template <typename T>
00355 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
00356 {
00357 T *originalValue;
00358 asm volatile("swp %0,%2,[%3]"
00359 : "=&r"(originalValue), "=m" (_q_value)
00360 : "r"(newValue), "r"(&_q_value)
00361 : "cc", "memory");
00362 return originalValue;
00363 }
00364
00365 #endif // Q_CC_RVCT
00366
00367 template <typename T>
00368 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
00369 {
00370 return fetchAndStoreOrdered(newValue);
00371 }
00372
00373 template <typename T>
00374 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
00375 {
00376 return fetchAndStoreOrdered(newValue);
00377 }
00378
00379 template <typename T>
00380 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
00381 {
00382 return fetchAndStoreOrdered(newValue);
00383 }
00384
00385
00386
00387 template <typename T>
00388 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
00389 {
00390 #ifndef QT_NO_ARM_EABI
00391 register T *originalValue;
00392 register T *newValue;
00393 do {
00394 originalValue = _q_value;
00395 newValue = originalValue + valueToAdd;
00396 } while (qt_atomic_eabi_cmpxchg_ptr(originalValue, newValue, &_q_value) != 0);
00397 return originalValue;
00398 #else
00399 int count = 0;
00400 while (q_atomic_swp(&q_atomic_lock, ~0) != 0)
00401 qt_atomic_yield(&count);
00402 T *originalValue = (_q_value);
00403 _q_value += valueToAdd;
00404 q_atomic_swp(&q_atomic_lock, 0);
00405 return originalValue;
00406 #endif
00407 }
00408
00409 template <typename T>
00410 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
00411 {
00412 return fetchAndAddOrdered(valueToAdd);
00413 }
00414
00415 template <typename T>
00416 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
00417 {
00418 return fetchAndAddOrdered(valueToAdd);
00419 }
00420
00421 template <typename T>
00422 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
00423 {
00424 return fetchAndAddOrdered(valueToAdd);
00425 }
00426
00427 QT_END_NAMESPACE
00428
00429 QT_END_HEADER
00430
00431 #endif // QATOMIC_ARM_H