lowlevellock.S 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. /* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, write to the Free
  14. Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  15. 02111-1307 USA. */
  16. #include <sysdep.h>
  17. #include <pthread-errnos.h>
  18. .text
  19. #ifndef LOCK
  20. # ifdef UP
  21. # define LOCK
  22. # else
  23. # define LOCK lock
  24. # endif
  25. #endif
  26. #define FUTEX_WAIT 0
  27. #define FUTEX_WAKE 1
  28. .globl __lll_mutex_lock_wait
  29. .type __lll_mutex_lock_wait,@function
  30. .hidden __lll_mutex_lock_wait
  31. .align 16
  32. __lll_mutex_lock_wait:
  33. pushl %edx
  34. pushl %ebx
  35. pushl %esi
  36. movl $2, %edx
  37. movl %ecx, %ebx
  38. xorl %esi, %esi /* No timeout. */
  39. xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
  40. cmpl %edx, %eax /* NB: %edx == 2 */
  41. jne 2f
  42. 1: movl $SYS_futex, %eax
  43. ENTER_KERNEL
  44. 2: movl %edx, %eax
  45. xchgl %eax, (%ebx) /* NB: lock is implied */
  46. testl %eax, %eax
  47. jnz,pn 1b
  48. popl %esi
  49. popl %ebx
  50. popl %edx
  51. ret
  52. .size __lll_mutex_lock_wait,.-__lll_mutex_lock_wait
  53. #ifdef NOT_IN_libc
  54. .globl __lll_mutex_timedlock_wait
  55. .type __lll_mutex_timedlock_wait,@function
  56. .hidden __lll_mutex_timedlock_wait
  57. .align 16
  58. __lll_mutex_timedlock_wait:
  59. /* Check for a valid timeout value. */
  60. cmpl $1000000000, 4(%edx)
  61. jae 3f
  62. pushl %edi
  63. pushl %esi
  64. pushl %ebx
  65. pushl %ebp
  66. /* Stack frame for the timespec and timeval structs. */
  67. subl $8, %esp
  68. movl %ecx, %ebp
  69. movl %edx, %edi
  70. 1:
  71. /* Get current time. */
  72. movl %esp, %ebx
  73. xorl %ecx, %ecx
  74. movl $SYS_gettimeofday, %eax
  75. ENTER_KERNEL
  76. /* Compute relative timeout. */
  77. movl 4(%esp), %eax
  78. movl $1000, %edx
  79. mul %edx /* Milli seconds to nano seconds. */
  80. movl (%edi), %ecx
  81. movl 4(%edi), %edx
  82. subl (%esp), %ecx
  83. subl %eax, %edx
  84. jns 4f
  85. addl $1000000000, %edx
  86. subl $1, %ecx
  87. 4: testl %ecx, %ecx
  88. js 5f /* Time is already up. */
  89. /* Store relative timeout. */
  90. movl %ecx, (%esp)
  91. movl %edx, 4(%esp)
  92. movl %ebp, %ebx
  93. movl $1, %eax
  94. movl $2, %edx
  95. LOCK
  96. cmpxchgl %edx, (%ebx)
  97. testl %eax, %eax
  98. je 8f
  99. /* Futex call. */
  100. movl %esp, %esi
  101. xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
  102. movl $SYS_futex, %eax
  103. ENTER_KERNEL
  104. movl %eax, %ecx
  105. 8: /* NB: %edx == 2 */
  106. xorl %eax, %eax
  107. LOCK
  108. cmpxchgl %edx, (%ebx)
  109. jnz 7f
  110. 6: addl $8, %esp
  111. popl %ebp
  112. popl %ebx
  113. popl %esi
  114. popl %edi
  115. ret
  116. /* Check whether the time expired. */
  117. 7: cmpl $-ETIMEDOUT, %ecx
  118. je 5f
  119. /* Make sure the current holder knows we are going to sleep. */
  120. movl %edx, %eax
  121. xchgl %eax, (%ebx)
  122. testl %eax, %eax
  123. jz 6b
  124. jmp 1b
  125. 3: movl $EINVAL, %eax
  126. ret
  127. 5: movl $ETIMEDOUT, %eax
  128. jmp 6b
  129. .size __lll_mutex_timedlock_wait,.-__lll_mutex_timedlock_wait
  130. #endif
  131. #ifdef NOT_IN_libc
  132. .globl lll_unlock_wake_cb
  133. .type lll_unlock_wake_cb,@function
  134. .hidden lll_unlock_wake_cb
  135. .align 16
  136. lll_unlock_wake_cb:
  137. pushl %ebx
  138. pushl %ecx
  139. pushl %edx
  140. movl 20(%esp), %ebx
  141. LOCK
  142. subl $1, (%ebx)
  143. je 1f
  144. movl $FUTEX_WAKE, %ecx
  145. movl $1, %edx /* Wake one thread. */
  146. movl $SYS_futex, %eax
  147. movl $0, (%ebx)
  148. ENTER_KERNEL
  149. 1: popl %edx
  150. popl %ecx
  151. popl %ebx
  152. ret
  153. .size lll_unlock_wake_cb,.-lll_unlock_wake_cb
  154. #endif
  155. .globl __lll_mutex_unlock_wake
  156. .type __lll_mutex_unlock_wake,@function
  157. .hidden __lll_mutex_unlock_wake
  158. .align 16
  159. __lll_mutex_unlock_wake:
  160. pushl %ebx
  161. pushl %ecx
  162. pushl %edx
  163. movl %eax, %ebx
  164. movl $0, (%eax)
  165. movl $FUTEX_WAKE, %ecx
  166. movl $1, %edx /* Wake one thread. */
  167. movl $SYS_futex, %eax
  168. ENTER_KERNEL
  169. popl %edx
  170. popl %ecx
  171. popl %ebx
  172. ret
  173. .size __lll_mutex_unlock_wake,.-__lll_mutex_unlock_wake
  174. #ifdef NOT_IN_libc
  175. .globl __lll_timedwait_tid
  176. .type __lll_timedwait_tid,@function
  177. .hidden __lll_timedwait_tid
  178. .align 16
  179. __lll_timedwait_tid:
  180. pushl %edi
  181. pushl %esi
  182. pushl %ebx
  183. pushl %ebp
  184. movl %eax, %ebp
  185. movl %edx, %edi
  186. subl $8, %esp
  187. /* Get current time. */
  188. 2: movl %esp, %ebx
  189. xorl %ecx, %ecx
  190. movl $SYS_gettimeofday, %eax
  191. ENTER_KERNEL
  192. /* Compute relative timeout. */
  193. movl 4(%esp), %eax
  194. movl $1000, %edx
  195. mul %edx /* Milli seconds to nano seconds. */
  196. movl (%edi), %ecx
  197. movl 4(%edi), %edx
  198. subl (%esp), %ecx
  199. subl %eax, %edx
  200. jns 5f
  201. addl $1000000000, %edx
  202. subl $1, %ecx
  203. 5: testl %ecx, %ecx
  204. js 6f /* Time is already up. */
  205. movl %ecx, (%esp) /* Store relative timeout. */
  206. movl %edx, 4(%esp)
  207. movl (%ebp), %edx
  208. testl %edx, %edx
  209. jz 4f
  210. movl %esp, %esi
  211. xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
  212. movl %ebp, %ebx
  213. movl $SYS_futex, %eax
  214. ENTER_KERNEL
  215. cmpl $0, (%ebx)
  216. jne 1f
  217. 4: xorl %eax, %eax
  218. 3: addl $8, %esp
  219. popl %ebp
  220. popl %ebx
  221. popl %esi
  222. popl %edi
  223. ret
  224. 1: cmpl $-ETIMEDOUT, %eax
  225. jne 2b
  226. 6: movl $ETIMEDOUT, %eax
  227. jmp 3b
  228. .size __lll_timedwait_tid,.-__lll_timedwait_tid
  229. #endif