qatomic_arm.h
上传用户:detong
上传日期:2022-06-22
资源大小:20675k
文件大小:9k
源码类别:

系统编程

开发平台:

Unix_Linux

  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
  4. ** Contact: Qt Software Information (qt-info@nokia.com)
  5. **
  6. ** This file is part of the QtCore module of the Qt Toolkit.
  7. **
  8. ** Commercial Usage
  9. ** Licensees holding valid Qt Commercial licenses may use this file in
  10. ** accordance with the Qt Commercial License Agreement provided with the
  11. ** Software or, alternatively, in accordance with the terms contained in
  12. ** a written agreement between you and Nokia.
  13. **
  14. **
  15. ** GNU General Public License Usage
  16. ** Alternatively, this file may be used under the terms of the GNU
  17. ** General Public License versions 2.0 or 3.0 as published by the Free
  18. ** Software Foundation and appearing in the file LICENSE.GPL included in
  19. ** the packaging of this file.  Please review the following information
  20. ** to ensure GNU General Public Licensing requirements will be met:
  21. ** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
  22. ** http://www.gnu.org/copyleft/gpl.html.  In addition, as a special
  23. ** exception, Nokia gives you certain additional rights. These rights
  24. ** are described in the Nokia Qt GPL Exception version 1.3, included in
  25. ** the file GPL_EXCEPTION.txt in this package.
  26. **
  27. ** Qt for Windows(R) Licensees
  28. ** As a special exception, Nokia, as the sole copyright holder for Qt
  29. ** Designer, grants users of the Qt/Eclipse Integration plug-in the
  30. ** right for the Qt/Eclipse Integration to link to functionality
  31. ** provided by Qt Designer and its related libraries.
  32. **
  33. ** If you are unsure which license is appropriate for your use, please
  34. ** contact the sales department at qt-sales@nokia.com.
  35. **
  36. ****************************************************************************/
  37. #ifndef QATOMIC_ARM_H
  38. #define QATOMIC_ARM_H
  39. QT_BEGIN_HEADER
  40. QT_BEGIN_NAMESPACE
  41. #define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE
  42. inline bool QBasicAtomicInt::isReferenceCountingNative()
  43. { return false; }
  44. inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
  45. { return false; }
  46. #define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE
  47. inline bool QBasicAtomicInt::isTestAndSetNative()
  48. { return false; }
  49. inline bool QBasicAtomicInt::isTestAndSetWaitFree()
  50. { return false; }
  51. #define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
  52. #define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE
  53. inline bool QBasicAtomicInt::isFetchAndStoreNative()
  54. { return true; }
  55. inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
  56. { return true; }
  57. #define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE
  58. inline bool QBasicAtomicInt::isFetchAndAddNative()
  59. { return false; }
  60. inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
  61. { return false; }
  62. #define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE
  63. template <typename T>
  64. Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
  65. { return false; }
  66. template <typename T>
  67. Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
  68. { return false; }
  69. #define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
  70. #define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE
  71. template <typename T>
  72. Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
  73. { return true; }
  74. template <typename T>
  75. Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
  76. { return true; }
  77. #define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE
  78. template <typename T>
  79. Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
  80. { return false; }
  81. template <typename T>
  82. Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
  83. { return false; }
  84. extern Q_CORE_EXPORT char q_atomic_lock;
  85. Q_CORE_EXPORT void qt_atomic_yield(int *);
  86. inline char q_atomic_swp(volatile char *ptr, char newval)
  87. {
  88.     register char ret;
  89.     asm volatile("swpb %0,%2,[%3]"
  90.                  : "=&r"(ret), "=m" (*ptr)
  91.                  : "r"(newval), "r"(ptr)
  92.                  : "cc", "memory");
  93.     return ret;
  94. }
  95. // Reference counting
  96. inline bool QBasicAtomicInt::ref()
  97. {
  98.     int count = 0;
  99.     while (q_atomic_swp(&q_atomic_lock, ~0) != 0)
  100.         qt_atomic_yield(&count);
  101.     int originalValue = _q_value++;
  102.     q_atomic_swp(&q_atomic_lock, 0);
  103.     return originalValue != -1;
  104. }
  105. inline bool QBasicAtomicInt::deref()
  106. {
  107.     int count = 0;
  108.     while (q_atomic_swp(&q_atomic_lock, ~0) != 0)
  109.         qt_atomic_yield(&count);
  110.     int originalValue = _q_value--;
  111.     q_atomic_swp(&q_atomic_lock, 0);
  112.     return originalValue != 1;
  113. }
  114. // Test and set for integers
  115. inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
  116. {
  117.     bool returnValue = false;
  118.     int count = 0;
  119.     while (q_atomic_swp(&q_atomic_lock, ~0) != 0)
  120.         qt_atomic_yield(&count);
  121.     if (_q_value == expectedValue) {
  122. _q_value = newValue;
  123. returnValue = true;
  124.     }
  125.     q_atomic_swp(&q_atomic_lock, 0);
  126.     return returnValue;
  127. }
  128. inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
  129. {
  130.     return testAndSetOrdered(expectedValue, newValue);
  131. }
  132. inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
  133. {
  134.     return testAndSetOrdered(expectedValue, newValue);
  135. }
  136. inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
  137. {
  138.     return testAndSetOrdered(expectedValue, newValue);
  139. }
  140. // Fetch and store for integers
  141. inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
  142. {
  143.     int originalValue;
  144.     asm volatile("swp %0,%2,[%3]"
  145.                  : "=&r"(originalValue), "=m" (_q_value)
  146.                  : "r"(newValue), "r"(&_q_value)
  147.                  : "cc", "memory");
  148.     return originalValue;
  149. }
  150. inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
  151. {
  152.     return fetchAndStoreOrdered(newValue);
  153. }
  154. inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
  155. {
  156.     return fetchAndStoreOrdered(newValue);
  157. }
  158. inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
  159. {
  160.     return fetchAndStoreOrdered(newValue);
  161. }
  162. // Fetch and add for integers
  163. inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
  164. {
  165.     int count = 0;
  166.     while (q_atomic_swp(&q_atomic_lock, ~0) != 0)
  167.         qt_atomic_yield(&count);
  168.     int originalValue = _q_value;
  169.     _q_value += valueToAdd;
  170.     q_atomic_swp(&q_atomic_lock, 0);
  171.     return originalValue;
  172. }
  173. inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
  174. {
  175.     return fetchAndAddOrdered(valueToAdd);
  176. }
  177. inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
  178. {
  179.     return fetchAndAddOrdered(valueToAdd);
  180. }
  181. inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
  182. {
  183.     return fetchAndAddOrdered(valueToAdd);
  184. }
  185. // Test and set for pointers
  186. template <typename T>
  187. Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
  188. {
  189.     bool returnValue = false;
  190.     int count = 0;
  191.     while (q_atomic_swp(&q_atomic_lock, ~0) != 0)
  192.         qt_atomic_yield(&count);
  193.     if (_q_value == expectedValue) {
  194. _q_value = newValue;
  195. returnValue = true;
  196.     }
  197.     q_atomic_swp(&q_atomic_lock, 0);
  198.     return returnValue;
  199. }
  200. template <typename T>
  201. Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
  202. {
  203.     return testAndSetOrdered(expectedValue, newValue);
  204. }
  205. template <typename T>
  206. Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
  207. {
  208.     return testAndSetOrdered(expectedValue, newValue);
  209. }
  210. template <typename T>
  211. Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
  212. {
  213.     return testAndSetOrdered(expectedValue, newValue);
  214. }
  215. // Fetch and store for pointers
  216. template <typename T>
  217. Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
  218. {
  219.     T *originalValue;
  220.     asm volatile("swp %0,%2,[%3]"
  221.                  : "=&r"(originalValue), "=m" (_q_value)
  222.                  : "r"(newValue), "r"(&_q_value)
  223.                  : "cc", "memory");
  224.     return originalValue;
  225. }
  226. template <typename T>
  227. Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
  228. {
  229.     return fetchAndStoreOrdered(newValue);
  230. }
  231. template <typename T>
  232. Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
  233. {
  234.     return fetchAndStoreOrdered(newValue);
  235. }
  236. template <typename T>
  237. Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
  238. {
  239.     return fetchAndStoreOrdered(newValue);
  240. }
  241. // Fetch and add for pointers
  242. template <typename T>
  243. Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
  244. {
  245.     int count = 0;
  246.     while (q_atomic_swp(&q_atomic_lock, ~0) != 0)
  247.         qt_atomic_yield(&count);
  248.     T *originalValue = (_q_value);
  249.     _q_value += valueToAdd;
  250.     q_atomic_swp(&q_atomic_lock, 0);
  251.     return originalValue;
  252. }
  253. template <typename T>
  254. Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
  255. {
  256.     return fetchAndAddOrdered(valueToAdd);
  257. }
  258. template <typename T>
  259. Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
  260. {
  261.     return fetchAndAddOrdered(valueToAdd);
  262. }
  263. template <typename T>
  264. Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
  265. {
  266.     return fetchAndAddOrdered(valueToAdd);
  267. }
  268. QT_END_NAMESPACE
  269. QT_END_HEADER
  270. #endif // QATOMIC_ARM_H