semaphore_32.S 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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.h>
  18. #include <asm/frame.h>
  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, "ax"
  31. /*
  32. * rw spinlock fallbacks
  33. */
  34. #ifdef CONFIG_SMP
  35. ENTRY(__write_lock_failed)
  36. CFI_STARTPROC simple
  37. FRAME
  38. 2: LOCK_PREFIX
  39. addl $ RW_LOCK_BIAS,(%eax)
  40. 1: rep; nop
  41. cmpl $ RW_LOCK_BIAS,(%eax)
  42. jne 1b
  43. LOCK_PREFIX
  44. subl $ RW_LOCK_BIAS,(%eax)
  45. jnz 2b
  46. ENDFRAME
  47. ret
  48. CFI_ENDPROC
  49. ENDPROC(__write_lock_failed)
  50. ENTRY(__read_lock_failed)
  51. CFI_STARTPROC
  52. FRAME
  53. 2: LOCK_PREFIX
  54. incl (%eax)
  55. 1: rep; nop
  56. cmpl $1,(%eax)
  57. js 1b
  58. LOCK_PREFIX
  59. decl (%eax)
  60. js 2b
  61. ENDFRAME
  62. ret
  63. CFI_ENDPROC
  64. ENDPROC(__read_lock_failed)
  65. #endif
  66. #ifdef CONFIG_RWSEM_XCHGADD_ALGORITHM
  67. /* Fix up special calling conventions */
  68. ENTRY(call_rwsem_down_read_failed)
  69. CFI_STARTPROC
  70. push %ecx
  71. CFI_ADJUST_CFA_OFFSET 4
  72. CFI_REL_OFFSET ecx,0
  73. push %edx
  74. CFI_ADJUST_CFA_OFFSET 4
  75. CFI_REL_OFFSET edx,0
  76. call rwsem_down_read_failed
  77. pop %edx
  78. CFI_ADJUST_CFA_OFFSET -4
  79. pop %ecx
  80. CFI_ADJUST_CFA_OFFSET -4
  81. ret
  82. CFI_ENDPROC
  83. ENDPROC(call_rwsem_down_read_failed)
  84. ENTRY(call_rwsem_down_write_failed)
  85. CFI_STARTPROC
  86. push %ecx
  87. CFI_ADJUST_CFA_OFFSET 4
  88. CFI_REL_OFFSET ecx,0
  89. calll rwsem_down_write_failed
  90. pop %ecx
  91. CFI_ADJUST_CFA_OFFSET -4
  92. ret
  93. CFI_ENDPROC
  94. ENDPROC(call_rwsem_down_write_failed)
  95. ENTRY(call_rwsem_wake)
  96. CFI_STARTPROC
  97. decw %dx /* do nothing if still outstanding active readers */
  98. jnz 1f
  99. push %ecx
  100. CFI_ADJUST_CFA_OFFSET 4
  101. CFI_REL_OFFSET ecx,0
  102. call rwsem_wake
  103. pop %ecx
  104. CFI_ADJUST_CFA_OFFSET -4
  105. 1: ret
  106. CFI_ENDPROC
  107. ENDPROC(call_rwsem_wake)
  108. /* Fix up special calling conventions */
  109. ENTRY(call_rwsem_downgrade_wake)
  110. CFI_STARTPROC
  111. push %ecx
  112. CFI_ADJUST_CFA_OFFSET 4
  113. CFI_REL_OFFSET ecx,0
  114. push %edx
  115. CFI_ADJUST_CFA_OFFSET 4
  116. CFI_REL_OFFSET edx,0
  117. call rwsem_downgrade_wake
  118. pop %edx
  119. CFI_ADJUST_CFA_OFFSET -4
  120. pop %ecx
  121. CFI_ADJUST_CFA_OFFSET -4
  122. ret
  123. CFI_ENDPROC
  124. ENDPROC(call_rwsem_downgrade_wake)
  125. #endif