semaphore.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  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 <asm/semaphore.h>
  16. /*
  17. * The semaphore operations have a special calling sequence that
  18. * allow us to do a simpler in-line version of them. These routines
  19. * need to convert that sequence back into the C sequence when
  20. * there is contention on the semaphore.
  21. *
  22. * %eax contains the semaphore pointer on entry. Save the C-clobbered
  23. * registers (%eax, %edx and %ecx) except %eax whish is either a return
  24. * value or just clobbered..
  25. */
  26. asm(
  27. ".section .sched.text\n"
  28. ".align 4\n"
  29. ".globl __down_failed\n"
  30. "__down_failed:\n\t"
  31. #if defined(CONFIG_FRAME_POINTER)
  32. "pushl %ebp\n\t"
  33. "movl %esp,%ebp\n\t"
  34. #endif
  35. "pushl %edx\n\t"
  36. "pushl %ecx\n\t"
  37. "call __down\n\t"
  38. "popl %ecx\n\t"
  39. "popl %edx\n\t"
  40. #if defined(CONFIG_FRAME_POINTER)
  41. "movl %ebp,%esp\n\t"
  42. "popl %ebp\n\t"
  43. #endif
  44. "ret"
  45. );
  46. asm(
  47. ".section .sched.text\n"
  48. ".align 4\n"
  49. ".globl __down_failed_interruptible\n"
  50. "__down_failed_interruptible:\n\t"
  51. #if defined(CONFIG_FRAME_POINTER)
  52. "pushl %ebp\n\t"
  53. "movl %esp,%ebp\n\t"
  54. #endif
  55. "pushl %edx\n\t"
  56. "pushl %ecx\n\t"
  57. "call __down_interruptible\n\t"
  58. "popl %ecx\n\t"
  59. "popl %edx\n\t"
  60. #if defined(CONFIG_FRAME_POINTER)
  61. "movl %ebp,%esp\n\t"
  62. "popl %ebp\n\t"
  63. #endif
  64. "ret"
  65. );
  66. asm(
  67. ".section .sched.text\n"
  68. ".align 4\n"
  69. ".globl __down_failed_trylock\n"
  70. "__down_failed_trylock:\n\t"
  71. #if defined(CONFIG_FRAME_POINTER)
  72. "pushl %ebp\n\t"
  73. "movl %esp,%ebp\n\t"
  74. #endif
  75. "pushl %edx\n\t"
  76. "pushl %ecx\n\t"
  77. "call __down_trylock\n\t"
  78. "popl %ecx\n\t"
  79. "popl %edx\n\t"
  80. #if defined(CONFIG_FRAME_POINTER)
  81. "movl %ebp,%esp\n\t"
  82. "popl %ebp\n\t"
  83. #endif
  84. "ret"
  85. );
  86. asm(
  87. ".section .sched.text\n"
  88. ".align 4\n"
  89. ".globl __up_wakeup\n"
  90. "__up_wakeup:\n\t"
  91. "pushl %edx\n\t"
  92. "pushl %ecx\n\t"
  93. "call __up\n\t"
  94. "popl %ecx\n\t"
  95. "popl %edx\n\t"
  96. "ret"
  97. );
  98. /*
  99. * rw spinlock fallbacks
  100. */
  101. #if defined(CONFIG_SMP)
  102. asm(
  103. ".section .sched.text\n"
  104. ".align 4\n"
  105. ".globl __write_lock_failed\n"
  106. "__write_lock_failed:\n\t"
  107. LOCK_PREFIX "addl $" RW_LOCK_BIAS_STR ",(%eax)\n"
  108. "1: rep; nop\n\t"
  109. "cmpl $" RW_LOCK_BIAS_STR ",(%eax)\n\t"
  110. "jne 1b\n\t"
  111. LOCK_PREFIX "subl $" RW_LOCK_BIAS_STR ",(%eax)\n\t"
  112. "jnz __write_lock_failed\n\t"
  113. "ret"
  114. );
  115. asm(
  116. ".section .sched.text\n"
  117. ".align 4\n"
  118. ".globl __read_lock_failed\n"
  119. "__read_lock_failed:\n\t"
  120. LOCK_PREFIX "incl (%eax)\n"
  121. "1: rep; nop\n\t"
  122. "cmpl $1,(%eax)\n\t"
  123. "js 1b\n\t"
  124. LOCK_PREFIX "decl (%eax)\n\t"
  125. "js __read_lock_failed\n\t"
  126. "ret"
  127. );
  128. #endif