locks.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. /*
  2. * linux/include/asm-arm/locks.h
  3. *
  4. * Copyright (C) 2000 Russell King
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. *
  10. * Interrupt safe locking assembler.
  11. */
  12. #ifndef __ASM_PROC_LOCKS_H
  13. #define __ASM_PROC_LOCKS_H
  14. #if __LINUX_ARM_ARCH__ >= 6
  15. #define __down_op(ptr,fail) \
  16. ({ \
  17. __asm__ __volatile__( \
  18. "@ down_op\n" \
  19. "1: ldrex lr, [%0]\n" \
  20. " sub lr, lr, %1\n" \
  21. " strex ip, lr, [%0]\n" \
  22. " teq ip, #0\n" \
  23. " bne 1b\n" \
  24. " teq lr, #0\n" \
  25. " movmi ip, %0\n" \
  26. " blmi " #fail \
  27. : \
  28. : "r" (ptr), "I" (1) \
  29. : "ip", "lr", "cc"); \
  30. smp_mb(); \
  31. })
  32. #define __down_op_ret(ptr,fail) \
  33. ({ \
  34. unsigned int ret; \
  35. __asm__ __volatile__( \
  36. "@ down_op_ret\n" \
  37. "1: ldrex lr, [%1]\n" \
  38. " sub lr, lr, %2\n" \
  39. " strex ip, lr, [%1]\n" \
  40. " teq ip, #0\n" \
  41. " bne 1b\n" \
  42. " teq lr, #0\n" \
  43. " movmi ip, %1\n" \
  44. " movpl ip, #0\n" \
  45. " blmi " #fail "\n" \
  46. " mov %0, ip" \
  47. : "=&r" (ret) \
  48. : "r" (ptr), "I" (1) \
  49. : "ip", "lr", "cc"); \
  50. smp_mb(); \
  51. ret; \
  52. })
  53. #define __up_op(ptr,wake) \
  54. ({ \
  55. smp_mb(); \
  56. __asm__ __volatile__( \
  57. "@ up_op\n" \
  58. "1: ldrex lr, [%0]\n" \
  59. " add lr, lr, %1\n" \
  60. " strex ip, lr, [%0]\n" \
  61. " teq ip, #0\n" \
  62. " bne 1b\n" \
  63. " cmp lr, #0\n" \
  64. " movle ip, %0\n" \
  65. " blle " #wake \
  66. : \
  67. : "r" (ptr), "I" (1) \
  68. : "ip", "lr", "cc"); \
  69. })
  70. /*
  71. * The value 0x01000000 supports up to 128 processors and
  72. * lots of processes. BIAS must be chosen such that sub'ing
  73. * BIAS once per CPU will result in the long remaining
  74. * negative.
  75. */
  76. #define RW_LOCK_BIAS 0x01000000
  77. #define RW_LOCK_BIAS_STR "0x01000000"
  78. #define __down_op_write(ptr,fail) \
  79. ({ \
  80. __asm__ __volatile__( \
  81. "@ down_op_write\n" \
  82. "1: ldrex lr, [%0]\n" \
  83. " sub lr, lr, %1\n" \
  84. " strex ip, lr, [%0]\n" \
  85. " teq ip, #0\n" \
  86. " bne 1b\n" \
  87. " teq lr, #0\n" \
  88. " movne ip, %0\n" \
  89. " blne " #fail \
  90. : \
  91. : "r" (ptr), "I" (RW_LOCK_BIAS) \
  92. : "ip", "lr", "cc"); \
  93. smp_mb(); \
  94. })
  95. #define __up_op_write(ptr,wake) \
  96. ({ \
  97. smp_mb(); \
  98. __asm__ __volatile__( \
  99. "@ up_op_write\n" \
  100. "1: ldrex lr, [%0]\n" \
  101. " adds lr, lr, %1\n" \
  102. " strex ip, lr, [%0]\n" \
  103. " teq ip, #0\n" \
  104. " bne 1b\n" \
  105. " movcs ip, %0\n" \
  106. " blcs " #wake \
  107. : \
  108. : "r" (ptr), "I" (RW_LOCK_BIAS) \
  109. : "ip", "lr", "cc"); \
  110. })
  111. #define __down_op_read(ptr,fail) \
  112. __down_op(ptr, fail)
  113. #define __up_op_read(ptr,wake) \
  114. ({ \
  115. smp_mb(); \
  116. __asm__ __volatile__( \
  117. "@ up_op_read\n" \
  118. "1: ldrex lr, [%0]\n" \
  119. " add lr, lr, %1\n" \
  120. " strex ip, lr, [%0]\n" \
  121. " teq ip, #0\n" \
  122. " bne 1b\n" \
  123. " teq lr, #0\n" \
  124. " moveq ip, %0\n" \
  125. " bleq " #wake \
  126. : \
  127. : "r" (ptr), "I" (1) \
  128. : "ip", "lr", "cc"); \
  129. })
  130. #else
  131. #define __down_op(ptr,fail) \
  132. ({ \
  133. __asm__ __volatile__( \
  134. "@ down_op\n" \
  135. " mrs ip, cpsr\n" \
  136. " orr lr, ip, #128\n" \
  137. " msr cpsr_c, lr\n" \
  138. " ldr lr, [%0]\n" \
  139. " subs lr, lr, %1\n" \
  140. " str lr, [%0]\n" \
  141. " msr cpsr_c, ip\n" \
  142. " movmi ip, %0\n" \
  143. " blmi " #fail \
  144. : \
  145. : "r" (ptr), "I" (1) \
  146. : "ip", "lr", "cc"); \
  147. smp_mb(); \
  148. })
  149. #define __down_op_ret(ptr,fail) \
  150. ({ \
  151. unsigned int ret; \
  152. __asm__ __volatile__( \
  153. "@ down_op_ret\n" \
  154. " mrs ip, cpsr\n" \
  155. " orr lr, ip, #128\n" \
  156. " msr cpsr_c, lr\n" \
  157. " ldr lr, [%1]\n" \
  158. " subs lr, lr, %2\n" \
  159. " str lr, [%1]\n" \
  160. " msr cpsr_c, ip\n" \
  161. " movmi ip, %1\n" \
  162. " movpl ip, #0\n" \
  163. " blmi " #fail "\n" \
  164. " mov %0, ip" \
  165. : "=&r" (ret) \
  166. : "r" (ptr), "I" (1) \
  167. : "ip", "lr", "cc"); \
  168. smp_mb(); \
  169. ret; \
  170. })
  171. #define __up_op(ptr,wake) \
  172. ({ \
  173. smp_mb(); \
  174. __asm__ __volatile__( \
  175. "@ up_op\n" \
  176. " mrs ip, cpsr\n" \
  177. " orr lr, ip, #128\n" \
  178. " msr cpsr_c, lr\n" \
  179. " ldr lr, [%0]\n" \
  180. " adds lr, lr, %1\n" \
  181. " str lr, [%0]\n" \
  182. " msr cpsr_c, ip\n" \
  183. " movle ip, %0\n" \
  184. " blle " #wake \
  185. : \
  186. : "r" (ptr), "I" (1) \
  187. : "ip", "lr", "cc"); \
  188. })
  189. /*
  190. * The value 0x01000000 supports up to 128 processors and
  191. * lots of processes. BIAS must be chosen such that sub'ing
  192. * BIAS once per CPU will result in the long remaining
  193. * negative.
  194. */
  195. #define RW_LOCK_BIAS 0x01000000
  196. #define RW_LOCK_BIAS_STR "0x01000000"
  197. #define __down_op_write(ptr,fail) \
  198. ({ \
  199. __asm__ __volatile__( \
  200. "@ down_op_write\n" \
  201. " mrs ip, cpsr\n" \
  202. " orr lr, ip, #128\n" \
  203. " msr cpsr_c, lr\n" \
  204. " ldr lr, [%0]\n" \
  205. " subs lr, lr, %1\n" \
  206. " str lr, [%0]\n" \
  207. " msr cpsr_c, ip\n" \
  208. " movne ip, %0\n" \
  209. " blne " #fail \
  210. : \
  211. : "r" (ptr), "I" (RW_LOCK_BIAS) \
  212. : "ip", "lr", "cc"); \
  213. smp_mb(); \
  214. })
  215. #define __up_op_write(ptr,wake) \
  216. ({ \
  217. __asm__ __volatile__( \
  218. "@ up_op_write\n" \
  219. " mrs ip, cpsr\n" \
  220. " orr lr, ip, #128\n" \
  221. " msr cpsr_c, lr\n" \
  222. " ldr lr, [%0]\n" \
  223. " adds lr, lr, %1\n" \
  224. " str lr, [%0]\n" \
  225. " msr cpsr_c, ip\n" \
  226. " movcs ip, %0\n" \
  227. " blcs " #wake \
  228. : \
  229. : "r" (ptr), "I" (RW_LOCK_BIAS) \
  230. : "ip", "lr", "cc"); \
  231. smp_mb(); \
  232. })
  233. #define __down_op_read(ptr,fail) \
  234. __down_op(ptr, fail)
  235. #define __up_op_read(ptr,wake) \
  236. ({ \
  237. smp_mb(); \
  238. __asm__ __volatile__( \
  239. "@ up_op_read\n" \
  240. " mrs ip, cpsr\n" \
  241. " orr lr, ip, #128\n" \
  242. " msr cpsr_c, lr\n" \
  243. " ldr lr, [%0]\n" \
  244. " adds lr, lr, %1\n" \
  245. " str lr, [%0]\n" \
  246. " msr cpsr_c, ip\n" \
  247. " moveq ip, %0\n" \
  248. " bleq " #wake \
  249. : \
  250. : "r" (ptr), "I" (1) \
  251. : "ip", "lr", "cc"); \
  252. })
  253. #endif
  254. #endif