semaphore.S 4.1 KB

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