lowlevellock.S 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. /* Copyright (C) 2002-2004, 2006, 2007, 2009 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. #include <bits/kernel-features.h>
  19. #include <lowlevellock.h>
  20. #include <tcb-offsets.h>
  21. .text
  22. #ifdef __ASSUME_PRIVATE_FUTEX
  23. # define LOAD_PRIVATE_FUTEX_WAIT(reg) \
  24. movl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg
  25. # define LOAD_PRIVATE_FUTEX_WAKE(reg) \
  26. movl $(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg
  27. # define LOAD_FUTEX_WAIT(reg) \
  28. xorl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg
  29. # define LOAD_FUTEX_WAIT_ABS(reg) \
  30. xorl $(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME), reg
  31. # define LOAD_FUTEX_WAKE(reg) \
  32. xorl $(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg
  33. #else
  34. # if FUTEX_WAIT == 0
  35. # define LOAD_PRIVATE_FUTEX_WAIT(reg) \
  36. movl %gs:PRIVATE_FUTEX, reg
  37. # else
  38. # define LOAD_PRIVATE_FUTEX_WAIT(reg) \
  39. movl %gs:PRIVATE_FUTEX, reg ; \
  40. orl $FUTEX_WAIT, reg
  41. # endif
  42. # define LOAD_PRIVATE_FUTEX_WAKE(reg) \
  43. movl %gs:PRIVATE_FUTEX, reg ; \
  44. orl $FUTEX_WAKE, reg
  45. # if FUTEX_WAIT == 0
  46. # define LOAD_FUTEX_WAIT(reg) \
  47. xorl $FUTEX_PRIVATE_FLAG, reg ; \
  48. andl %gs:PRIVATE_FUTEX, reg
  49. # else
  50. # define LOAD_FUTEX_WAIT(reg) \
  51. xorl $FUTEX_PRIVATE_FLAG, reg ; \
  52. andl %gs:PRIVATE_FUTEX, reg ; \
  53. orl $FUTEX_WAIT, reg
  54. # endif
  55. # define LOAD_FUTEX_WAIT_ABS(reg) \
  56. xorl $FUTEX_PRIVATE_FLAG, reg ; \
  57. andl %gs:PRIVATE_FUTEX, reg ; \
  58. orl $FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME, reg
  59. # define LOAD_FUTEX_WAKE(reg) \
  60. xorl $FUTEX_PRIVATE_FLAG, reg ; \
  61. andl %gs:PRIVATE_FUTEX, reg ; \
  62. orl $FUTEX_WAKE, reg
  63. #endif
  64. .globl __lll_lock_wait_private
  65. .type __lll_lock_wait_private,@function
  66. .hidden __lll_lock_wait_private
  67. .align 16
  68. __lll_lock_wait_private:
  69. cfi_startproc
  70. pushl %edx
  71. cfi_adjust_cfa_offset(4)
  72. pushl %ebx
  73. cfi_adjust_cfa_offset(4)
  74. pushl %esi
  75. cfi_adjust_cfa_offset(4)
  76. cfi_offset(%edx, -8)
  77. cfi_offset(%ebx, -12)
  78. cfi_offset(%esi, -16)
  79. movl $2, %edx
  80. movl %ecx, %ebx
  81. xorl %esi, %esi /* No timeout. */
  82. LOAD_PRIVATE_FUTEX_WAIT (%ecx)
  83. cmpl %edx, %eax /* NB: %edx == 2 */
  84. jne 2f
  85. 1: movl $SYS_futex, %eax
  86. ENTER_KERNEL
  87. 2: movl %edx, %eax
  88. xchgl %eax, (%ebx) /* NB: lock is implied */
  89. testl %eax, %eax
  90. jnz 1b
  91. popl %esi
  92. cfi_adjust_cfa_offset(-4)
  93. cfi_restore(%esi)
  94. popl %ebx
  95. cfi_adjust_cfa_offset(-4)
  96. cfi_restore(%ebx)
  97. popl %edx
  98. cfi_adjust_cfa_offset(-4)
  99. cfi_restore(%edx)
  100. ret
  101. cfi_endproc
  102. .size __lll_lock_wait_private,.-__lll_lock_wait_private
  103. #ifdef NOT_IN_libc
  104. .globl __lll_lock_wait
  105. .type __lll_lock_wait,@function
  106. .hidden __lll_lock_wait
  107. .align 16
  108. __lll_lock_wait:
  109. cfi_startproc
  110. pushl %edx
  111. cfi_adjust_cfa_offset(4)
  112. pushl %ebx
  113. cfi_adjust_cfa_offset(4)
  114. pushl %esi
  115. cfi_adjust_cfa_offset(4)
  116. cfi_offset(%edx, -8)
  117. cfi_offset(%ebx, -12)
  118. cfi_offset(%esi, -16)
  119. movl %edx, %ebx
  120. movl $2, %edx
  121. xorl %esi, %esi /* No timeout. */
  122. LOAD_FUTEX_WAIT (%ecx)
  123. cmpl %edx, %eax /* NB: %edx == 2 */
  124. jne 2f
  125. 1: movl $SYS_futex, %eax
  126. ENTER_KERNEL
  127. 2: movl %edx, %eax
  128. xchgl %eax, (%ebx) /* NB: lock is implied */
  129. testl %eax, %eax
  130. jnz 1b
  131. popl %esi
  132. cfi_adjust_cfa_offset(-4)
  133. cfi_restore(%esi)
  134. popl %ebx
  135. cfi_adjust_cfa_offset(-4)
  136. cfi_restore(%ebx)
  137. popl %edx
  138. cfi_adjust_cfa_offset(-4)
  139. cfi_restore(%edx)
  140. ret
  141. cfi_endproc
  142. .size __lll_lock_wait,.-__lll_lock_wait
  143. /* %ecx: futex
  144. %esi: flags
  145. %edx: timeout
  146. %eax: futex value
  147. */
  148. .globl __lll_timedlock_wait
  149. .type __lll_timedlock_wait,@function
  150. .hidden __lll_timedlock_wait
  151. .align 16
  152. __lll_timedlock_wait:
  153. cfi_startproc
  154. pushl %ebp
  155. cfi_adjust_cfa_offset(4)
  156. cfi_rel_offset(%ebp, 0)
  157. pushl %ebx
  158. cfi_adjust_cfa_offset(4)
  159. cfi_rel_offset(%ebx, 0)
  160. # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
  161. # ifdef __PIC__
  162. LOAD_PIC_REG (bx)
  163. cmpl $0, __have_futex_clock_realtime@GOTOFF(%ebx)
  164. # else
  165. cmpl $0, __have_futex_clock_realtime
  166. # endif
  167. je .Lreltmo
  168. # endif
  169. movl %ecx, %ebx
  170. movl %esi, %ecx
  171. movl %edx, %esi
  172. movl $0xffffffff, %ebp
  173. LOAD_FUTEX_WAIT_ABS (%ecx)
  174. movl $2, %edx
  175. cmpl %edx, %eax
  176. jne 2f
  177. 1: movl $SYS_futex, %eax
  178. movl $2, %edx
  179. ENTER_KERNEL
  180. 2: xchgl %edx, (%ebx) /* NB: lock is implied */
  181. testl %edx, %edx
  182. jz 3f
  183. cmpl $-ETIMEDOUT, %eax
  184. je 4f
  185. cmpl $-EINVAL, %eax
  186. jne 1b
  187. 4: movl %eax, %edx
  188. negl %edx
  189. 3: movl %edx, %eax
  190. 7: popl %ebx
  191. cfi_adjust_cfa_offset(-4)
  192. cfi_restore(%ebx)
  193. popl %ebp
  194. cfi_adjust_cfa_offset(-4)
  195. cfi_restore(%ebp)
  196. ret
  197. # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
  198. .Lreltmo:
  199. /* Check for a valid timeout value. */
  200. cmpl $1000000000, 4(%edx)
  201. jae 3f
  202. pushl %esi
  203. cfi_adjust_cfa_offset(4)
  204. cfi_rel_offset(%esi, 0)
  205. pushl %edi
  206. cfi_adjust_cfa_offset(4)
  207. cfi_rel_offset(%edi, 0)
  208. /* Stack frame for the timespec and timeval structs. */
  209. subl $8, %esp
  210. cfi_adjust_cfa_offset(8)
  211. movl %ecx, %ebp
  212. movl %edx, %edi
  213. movl $2, %edx
  214. xchgl %edx, (%ebp)
  215. test %edx, %edx
  216. je 6f
  217. 1:
  218. /* Get current time. */
  219. movl %esp, %ebx
  220. xorl %ecx, %ecx
  221. movl $__NR_gettimeofday, %eax
  222. ENTER_KERNEL
  223. /* Compute relative timeout. */
  224. movl 4(%esp), %eax
  225. movl $1000, %edx
  226. mul %edx /* Milli seconds to nano seconds. */
  227. movl (%edi), %ecx
  228. movl 4(%edi), %edx
  229. subl (%esp), %ecx
  230. subl %eax, %edx
  231. jns 4f
  232. addl $1000000000, %edx
  233. subl $1, %ecx
  234. 4: testl %ecx, %ecx
  235. js 2f /* Time is already up. */
  236. /* Store relative timeout. */
  237. movl %ecx, (%esp)
  238. movl %edx, 4(%esp)
  239. /* Futex call. */
  240. movl %ebp, %ebx
  241. movl $2, %edx
  242. movl %esp, %esi
  243. movl 16(%esp), %ecx
  244. LOAD_FUTEX_WAIT (%ecx)
  245. movl $SYS_futex, %eax
  246. ENTER_KERNEL
  247. /* NB: %edx == 2 */
  248. xchgl %edx, (%ebp)
  249. testl %edx, %edx
  250. je 6f
  251. cmpl $-ETIMEDOUT, %eax
  252. jne 1b
  253. 2: movl $ETIMEDOUT, %edx
  254. 6: addl $8, %esp
  255. cfi_adjust_cfa_offset(-8)
  256. popl %edi
  257. cfi_adjust_cfa_offset(-4)
  258. cfi_restore(%edi)
  259. popl %esi
  260. cfi_adjust_cfa_offset(-4)
  261. cfi_restore(%esi)
  262. 7: popl %ebx
  263. cfi_adjust_cfa_offset(-4)
  264. cfi_restore(%ebx)
  265. popl %ebp
  266. cfi_adjust_cfa_offset(-4)
  267. cfi_restore(%ebp)
  268. movl %edx, %eax
  269. ret
  270. 3: movl $EINVAL, %edx
  271. jmp 7b
  272. # endif
  273. cfi_endproc
  274. .size __lll_timedlock_wait,.-__lll_timedlock_wait
  275. #endif
  276. .globl __lll_unlock_wake_private
  277. .type __lll_unlock_wake_private,@function
  278. .hidden __lll_unlock_wake_private
  279. .align 16
  280. __lll_unlock_wake_private:
  281. cfi_startproc
  282. pushl %ebx
  283. cfi_adjust_cfa_offset(4)
  284. pushl %ecx
  285. cfi_adjust_cfa_offset(4)
  286. pushl %edx
  287. cfi_adjust_cfa_offset(4)
  288. cfi_offset(%ebx, -8)
  289. cfi_offset(%ecx, -12)
  290. cfi_offset(%edx, -16)
  291. movl %eax, %ebx
  292. movl $0, (%eax)
  293. LOAD_PRIVATE_FUTEX_WAKE (%ecx)
  294. movl $1, %edx /* Wake one thread. */
  295. movl $SYS_futex, %eax
  296. ENTER_KERNEL
  297. popl %edx
  298. cfi_adjust_cfa_offset(-4)
  299. cfi_restore(%edx)
  300. popl %ecx
  301. cfi_adjust_cfa_offset(-4)
  302. cfi_restore(%ecx)
  303. popl %ebx
  304. cfi_adjust_cfa_offset(-4)
  305. cfi_restore(%ebx)
  306. ret
  307. cfi_endproc
  308. .size __lll_unlock_wake_private,.-__lll_unlock_wake_private
  309. #ifdef NOT_IN_libc
  310. .globl __lll_unlock_wake
  311. .type __lll_unlock_wake,@function
  312. .hidden __lll_unlock_wake
  313. .align 16
  314. __lll_unlock_wake:
  315. cfi_startproc
  316. pushl %ebx
  317. cfi_adjust_cfa_offset(4)
  318. pushl %ecx
  319. cfi_adjust_cfa_offset(4)
  320. pushl %edx
  321. cfi_adjust_cfa_offset(4)
  322. cfi_offset(%ebx, -8)
  323. cfi_offset(%ecx, -12)
  324. cfi_offset(%edx, -16)
  325. movl %eax, %ebx
  326. movl $0, (%eax)
  327. LOAD_FUTEX_WAKE (%ecx)
  328. movl $1, %edx /* Wake one thread. */
  329. movl $SYS_futex, %eax
  330. ENTER_KERNEL
  331. popl %edx
  332. cfi_adjust_cfa_offset(-4)
  333. cfi_restore(%edx)
  334. popl %ecx
  335. cfi_adjust_cfa_offset(-4)
  336. cfi_restore(%ecx)
  337. popl %ebx
  338. cfi_adjust_cfa_offset(-4)
  339. cfi_restore(%ebx)
  340. ret
  341. cfi_endproc
  342. .size __lll_unlock_wake,.-__lll_unlock_wake
  343. .globl __lll_timedwait_tid
  344. .type __lll_timedwait_tid,@function
  345. .hidden __lll_timedwait_tid
  346. .align 16
  347. __lll_timedwait_tid:
  348. pushl %edi
  349. pushl %esi
  350. pushl %ebx
  351. pushl %ebp
  352. movl %eax, %ebp
  353. movl %edx, %edi
  354. subl $8, %esp
  355. /* Get current time. */
  356. 2: movl %esp, %ebx
  357. xorl %ecx, %ecx
  358. movl $__NR_gettimeofday, %eax
  359. ENTER_KERNEL
  360. /* Compute relative timeout. */
  361. movl 4(%esp), %eax
  362. movl $1000, %edx
  363. mul %edx /* Milli seconds to nano seconds. */
  364. movl (%edi), %ecx
  365. movl 4(%edi), %edx
  366. subl (%esp), %ecx
  367. subl %eax, %edx
  368. jns 5f
  369. addl $1000000000, %edx
  370. subl $1, %ecx
  371. 5: testl %ecx, %ecx
  372. js 6f /* Time is already up. */
  373. movl %ecx, (%esp) /* Store relative timeout. */
  374. movl %edx, 4(%esp)
  375. movl (%ebp), %edx
  376. testl %edx, %edx
  377. jz 4f
  378. movl %esp, %esi
  379. /* XXX The kernel so far uses global futex for the wakeup at
  380. all times. */
  381. xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
  382. movl %ebp, %ebx
  383. movl $SYS_futex, %eax
  384. ENTER_KERNEL
  385. cmpl $0, (%ebx)
  386. jne 1f
  387. 4: xorl %eax, %eax
  388. 3: addl $8, %esp
  389. popl %ebp
  390. popl %ebx
  391. popl %esi
  392. popl %edi
  393. ret
  394. 1: cmpl $-ETIMEDOUT, %eax
  395. jne 2b
  396. 6: movl $ETIMEDOUT, %eax
  397. jmp 3b
  398. .size __lll_timedwait_tid,.-__lll_timedwait_tid
  399. #endif