locks.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * linux/include/asm-arm/proc-armo/locks.h
  3. *
  4. * Copyright (C) 2000 Russell King
  5. * Fixes for 26 bit machines, (C) 2000 Dave Gilbert
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. *
  11. * Interrupt safe locking assembler.
  12. */
  13. #ifndef __ASM_PROC_LOCKS_H
  14. #define __ASM_PROC_LOCKS_H
  15. /* Decrements by 1, fails if value < 0 */
  16. #define __down_op(ptr,fail) \
  17. ({ \
  18. __asm__ __volatile__ ( \
  19. "@ atomic down operation\n" \
  20. " mov ip, pc\n" \
  21. " orr lr, ip, #0x08000000\n" \
  22. " teqp lr, #0\n" \
  23. " ldr lr, [%0]\n" \
  24. " and ip, ip, #0x0c000003\n" \
  25. " subs lr, lr, #1\n" \
  26. " str lr, [%0]\n" \
  27. " orrmi ip, ip, #0x80000000 @ set N\n" \
  28. " teqp ip, #0\n" \
  29. " movmi ip, %0\n" \
  30. " blmi " #fail \
  31. : \
  32. : "r" (ptr) \
  33. : "ip", "lr", "cc"); \
  34. })
  35. #define __down_op_ret(ptr,fail) \
  36. ({ \
  37. unsigned int result; \
  38. __asm__ __volatile__ ( \
  39. " @ down_op_ret\n" \
  40. " mov ip, pc\n" \
  41. " orr lr, ip, #0x08000000\n" \
  42. " teqp lr, #0\n" \
  43. " ldr lr, [%1]\n" \
  44. " and ip, ip, #0x0c000003\n" \
  45. " subs lr, lr, #1\n" \
  46. " str lr, [%1]\n" \
  47. " orrmi ip, ip, #0x80000000 @ set N\n" \
  48. " teqp ip, #0\n" \
  49. " movmi ip, %1\n" \
  50. " movpl ip, #0\n" \
  51. " blmi " #fail "\n" \
  52. " mov %0, ip" \
  53. : "=&r" (result) \
  54. : "r" (ptr) \
  55. : "ip", "lr", "cc"); \
  56. result; \
  57. })
  58. #define __up_op(ptr,wake) \
  59. ({ \
  60. __asm__ __volatile__ ( \
  61. "@ up_op\n" \
  62. " mov ip, pc\n" \
  63. " orr lr, ip, #0x08000000\n" \
  64. " teqp lr, #0\n" \
  65. " ldr lr, [%0]\n" \
  66. " and ip, ip, #0x0c000003\n" \
  67. " adds lr, lr, #1\n" \
  68. " str lr, [%0]\n" \
  69. " orrle ip, ip, #0x80000000 @ set N - should this be mi ??? DAG ! \n" \
  70. " teqp ip, #0\n" \
  71. " movmi ip, %0\n" \
  72. " blmi " #wake \
  73. : \
  74. : "r" (ptr) \
  75. : "ip", "lr", "cc"); \
  76. })
  77. /*
  78. * The value 0x01000000 supports up to 128 processors and
  79. * lots of processes. BIAS must be chosen such that sub'ing
  80. * BIAS once per CPU will result in the long remaining
  81. * negative.
  82. */
  83. #define RW_LOCK_BIAS 0x01000000
  84. #define RW_LOCK_BIAS_STR "0x01000000"
  85. /* Decrements by RW_LOCK_BIAS rather than 1, fails if value != 0 */
  86. #define __down_op_write(ptr,fail) \
  87. ({ \
  88. __asm__ __volatile__( \
  89. "@ down_op_write\n" \
  90. " mov ip, pc\n" \
  91. " orr lr, ip, #0x08000000\n" \
  92. " teqp lr, #0\n" \
  93. " and ip, ip, #0x0c000003\n" \
  94. \
  95. " ldr lr, [%0]\n" \
  96. " subs lr, lr, %1\n" \
  97. " str lr, [%0]\n" \
  98. \
  99. " orreq ip, ip, #0x40000000 @ set Z \n"\
  100. " teqp ip, #0\n" \
  101. " movne ip, %0\n" \
  102. " blne " #fail \
  103. : \
  104. : "r" (ptr), "I" (RW_LOCK_BIAS) \
  105. : "ip", "lr", "cc"); \
  106. })
  107. /* Increments by RW_LOCK_BIAS, wakes if value >= 0 */
  108. #define __up_op_write(ptr,wake) \
  109. ({ \
  110. __asm__ __volatile__( \
  111. "@ up_op_read\n" \
  112. " mov ip, pc\n" \
  113. " orr lr, ip, #0x08000000\n" \
  114. " teqp lr, #0\n" \
  115. \
  116. " ldr lr, [%0]\n" \
  117. " and ip, ip, #0x0c000003\n" \
  118. " adds lr, lr, %1\n" \
  119. " str lr, [%0]\n" \
  120. \
  121. " orrcs ip, ip, #0x20000000 @ set C\n" \
  122. " teqp ip, #0\n" \
  123. " movcs ip, %0\n" \
  124. " blcs " #wake \
  125. : \
  126. : "r" (ptr), "I" (RW_LOCK_BIAS) \
  127. : "ip", "lr", "cc"); \
  128. })
  129. #define __down_op_read(ptr,fail) \
  130. __down_op(ptr, fail)
  131. #define __up_op_read(ptr,wake) \
  132. ({ \
  133. __asm__ __volatile__( \
  134. "@ up_op_read\n" \
  135. " mov ip, pc\n" \
  136. " orr lr, ip, #0x08000000\n" \
  137. " teqp lr, #0\n" \
  138. \
  139. " ldr lr, [%0]\n" \
  140. " and ip, ip, #0x0c000003\n" \
  141. " adds lr, lr, %1\n" \
  142. " str lr, [%0]\n" \
  143. \
  144. " orreq ip, ip, #0x40000000 @ Set Z \n" \
  145. " teqp ip, #0\n" \
  146. " moveq ip, %0\n" \
  147. " bleq " #wake \
  148. : \
  149. : "r" (ptr), "I" (1) \
  150. : "ip", "lr", "cc"); \
  151. })
  152. #endif