lowlevellock.S 9.2 KB

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