semaphore_32.S 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  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
  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. pushl_cfi %ecx
  71. CFI_REL_OFFSET ecx,0
  72. pushl_cfi %edx
  73. CFI_REL_OFFSET edx,0
  74. call rwsem_down_read_failed
  75. popl_cfi %edx
  76. popl_cfi %ecx
  77. ret
  78. CFI_ENDPROC
  79. ENDPROC(call_rwsem_down_read_failed)
  80. ENTRY(call_rwsem_down_write_failed)
  81. CFI_STARTPROC
  82. pushl_cfi %ecx
  83. CFI_REL_OFFSET ecx,0
  84. calll rwsem_down_write_failed
  85. popl_cfi %ecx
  86. ret
  87. CFI_ENDPROC
  88. ENDPROC(call_rwsem_down_write_failed)
  89. ENTRY(call_rwsem_wake)
  90. CFI_STARTPROC
  91. decw %dx /* do nothing if still outstanding active readers */
  92. jnz 1f
  93. pushl_cfi %ecx
  94. CFI_REL_OFFSET ecx,0
  95. call rwsem_wake
  96. popl_cfi %ecx
  97. 1: ret
  98. CFI_ENDPROC
  99. ENDPROC(call_rwsem_wake)
  100. /* Fix up special calling conventions */
  101. ENTRY(call_rwsem_downgrade_wake)
  102. CFI_STARTPROC
  103. pushl_cfi %ecx
  104. CFI_REL_OFFSET ecx,0
  105. pushl_cfi %edx
  106. CFI_REL_OFFSET edx,0
  107. call rwsem_downgrade_wake
  108. popl_cfi %edx
  109. popl_cfi %ecx
  110. ret
  111. CFI_ENDPROC
  112. ENDPROC(call_rwsem_downgrade_wake)
  113. #endif