semaphore.S 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. * i386 semaphore implementation.
  3. *
  4. * (C) Copyright 1999 Linus Torvalds
  5. *
  6. * Portions Copyright 1999 Red Hat, Inc.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version
  11. * 2 of the License, or (at your option) any later version.
  12. *
  13. * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@kvack.org>
  14. */
  15. #include <linux/linkage.h>
  16. #include <asm/rwlock.h>
  17. #include <asm/alternative-asm.i>
  18. #include <asm/frame.i>
  19. #include <asm/dwarf2.h>
  20. /*
  21. * The semaphore operations have a special calling sequence that
  22. * allow us to do a simpler in-line version of them. These routines
  23. * need to convert that sequence back into the C sequence when
  24. * there is contention on the semaphore.
  25. *
  26. * %eax contains the semaphore pointer on entry. Save the C-clobbered
  27. * registers (%eax, %edx and %ecx) except %eax whish is either a return
  28. * value or just clobbered..
  29. */
  30. .section .sched.text
  31. ENTRY(__down_failed)
  32. CFI_STARTPROC
  33. FRAME
  34. pushl %edx
  35. CFI_ADJUST_CFA_OFFSET 4
  36. CFI_REL_OFFSET edx,0
  37. pushl %ecx
  38. CFI_ADJUST_CFA_OFFSET 4
  39. CFI_REL_OFFSET ecx,0
  40. call __down
  41. popl %ecx
  42. CFI_ADJUST_CFA_OFFSET -4
  43. CFI_RESTORE ecx
  44. popl %edx
  45. CFI_ADJUST_CFA_OFFSET -4
  46. CFI_RESTORE edx
  47. ENDFRAME
  48. ret
  49. CFI_ENDPROC
  50. END(__down_failed)
  51. ENTRY(__down_failed_interruptible)
  52. CFI_STARTPROC
  53. FRAME
  54. pushl %edx
  55. CFI_ADJUST_CFA_OFFSET 4
  56. CFI_REL_OFFSET edx,0
  57. pushl %ecx
  58. CFI_ADJUST_CFA_OFFSET 4
  59. CFI_REL_OFFSET ecx,0
  60. call __down_interruptible
  61. popl %ecx
  62. CFI_ADJUST_CFA_OFFSET -4
  63. CFI_RESTORE ecx
  64. popl %edx
  65. CFI_ADJUST_CFA_OFFSET -4
  66. CFI_RESTORE edx
  67. ENDFRAME
  68. ret
  69. CFI_ENDPROC
  70. END(__down_failed_interruptible)
  71. ENTRY(__down_failed_trylock)
  72. CFI_STARTPROC
  73. FRAME
  74. pushl %edx
  75. CFI_ADJUST_CFA_OFFSET 4
  76. CFI_REL_OFFSET edx,0
  77. pushl %ecx
  78. CFI_ADJUST_CFA_OFFSET 4
  79. CFI_REL_OFFSET ecx,0
  80. call __down_trylock
  81. popl %ecx
  82. CFI_ADJUST_CFA_OFFSET -4
  83. CFI_RESTORE ecx
  84. popl %edx
  85. CFI_ADJUST_CFA_OFFSET -4
  86. CFI_RESTORE edx
  87. ENDFRAME
  88. ret
  89. CFI_ENDPROC
  90. END(__down_failed_trylock)
  91. ENTRY(__up_wakeup)
  92. CFI_STARTPROC
  93. FRAME
  94. pushl %edx
  95. CFI_ADJUST_CFA_OFFSET 4
  96. CFI_REL_OFFSET edx,0
  97. pushl %ecx
  98. CFI_ADJUST_CFA_OFFSET 4
  99. CFI_REL_OFFSET ecx,0
  100. call __up
  101. popl %ecx
  102. CFI_ADJUST_CFA_OFFSET -4
  103. CFI_RESTORE ecx
  104. popl %edx
  105. CFI_ADJUST_CFA_OFFSET -4
  106. CFI_RESTORE edx
  107. ENDFRAME
  108. ret
  109. CFI_ENDPROC
  110. END(__up_wakeup)
  111. /*
  112. * rw spinlock fallbacks
  113. */
  114. #ifdef CONFIG_SMP
  115. ENTRY(__write_lock_failed)
  116. CFI_STARTPROC simple
  117. FRAME
  118. 2: LOCK_PREFIX
  119. addl $ RW_LOCK_BIAS,(%eax)
  120. 1: rep; nop
  121. cmpl $ RW_LOCK_BIAS,(%eax)
  122. jne 1b
  123. LOCK_PREFIX
  124. subl $ RW_LOCK_BIAS,(%eax)
  125. jnz 2b
  126. ENDFRAME
  127. ret
  128. CFI_ENDPROC
  129. END(__write_lock_failed)
  130. ENTRY(__read_lock_failed)
  131. CFI_STARTPROC
  132. FRAME
  133. 2: LOCK_PREFIX
  134. incl (%eax)
  135. 1: rep; nop
  136. cmpl $1,(%eax)
  137. js 1b
  138. LOCK_PREFIX
  139. decl (%eax)
  140. js 2b
  141. ENDFRAME
  142. ret
  143. CFI_ENDPROC
  144. END(__read_lock_failed)
  145. #endif
  146. /* Fix up special calling conventions */
  147. ENTRY(call_rwsem_down_read_failed)
  148. CFI_STARTPROC
  149. push %ecx
  150. CFI_ADJUST_CFA_OFFSET 4
  151. CFI_REL_OFFSET ecx,0
  152. push %edx
  153. CFI_ADJUST_CFA_OFFSET 4
  154. CFI_REL_OFFSET edx,0
  155. call rwsem_down_read_failed
  156. pop %edx
  157. CFI_ADJUST_CFA_OFFSET -4
  158. pop %ecx
  159. CFI_ADJUST_CFA_OFFSET -4
  160. ret
  161. CFI_ENDPROC
  162. END(call_rwsem_down_read_failed)
  163. ENTRY(call_rwsem_down_write_failed)
  164. CFI_STARTPROC
  165. push %ecx
  166. CFI_ADJUST_CFA_OFFSET 4
  167. CFI_REL_OFFSET ecx,0
  168. calll rwsem_down_write_failed
  169. pop %ecx
  170. CFI_ADJUST_CFA_OFFSET -4
  171. ret
  172. CFI_ENDPROC
  173. END(call_rwsem_down_write_failed)
  174. ENTRY(call_rwsem_wake)
  175. CFI_STARTPROC
  176. decw %dx /* do nothing if still outstanding active readers */
  177. jnz 1f
  178. push %ecx
  179. CFI_ADJUST_CFA_OFFSET 4
  180. CFI_REL_OFFSET ecx,0
  181. call rwsem_wake
  182. pop %ecx
  183. CFI_ADJUST_CFA_OFFSET -4
  184. 1: ret
  185. CFI_ENDPROC
  186. END(call_rwsem_wake)
  187. /* Fix up special calling conventions */
  188. ENTRY(call_rwsem_downgrade_wake)
  189. CFI_STARTPROC
  190. push %ecx
  191. CFI_ADJUST_CFA_OFFSET 4
  192. CFI_REL_OFFSET ecx,0
  193. push %edx
  194. CFI_ADJUST_CFA_OFFSET 4
  195. CFI_REL_OFFSET edx,0
  196. call rwsem_downgrade_wake
  197. pop %edx
  198. CFI_ADJUST_CFA_OFFSET -4
  199. pop %ecx
  200. CFI_ADJUST_CFA_OFFSET -4
  201. ret
  202. CFI_ENDPROC
  203. END(call_rwsem_downgrade_wake)