PageRenderTime 25ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/uClibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S

https://bitbucket.org/pizzafactory/blackfin-toolchain
Assembly | 595 lines | 525 code | 70 blank | 0 comment | 27 complexity | ae0297e8cfdbfc8c35a3072f19f3ad85 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, GPL-3.0, AGPL-1.0, LGPL-2.1
  1. /* Copyright (C) 2002-2004,2006-2007,2009,2010 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 <lowlevellock.h>
  18. #include <lowlevelcond.h>
  19. #include <tcb-offsets.h>
  20. #include <pthread-errnos.h>
  21. #include <pthread-pi-defines.h>
  22. #include <bits/kernel-features.h>
  23. .text
  24. /* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) */
  25. .globl __pthread_cond_wait
  26. .type __pthread_cond_wait, @function
  27. .protected __pthread_cond_wait
  28. .align 16
  29. __pthread_cond_wait:
  30. .LSTARTCODE:
  31. cfi_startproc
  32. #ifdef SHARED
  33. cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect,
  34. DW.ref.__gcc_personality_v0)
  35. cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART)
  36. #else
  37. cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0)
  38. cfi_lsda(DW_EH_PE_udata4, .LexceptSTART)
  39. #endif
  40. pushl %ebp
  41. cfi_adjust_cfa_offset(4)
  42. cfi_rel_offset(%ebp, 0)
  43. pushl %edi
  44. cfi_adjust_cfa_offset(4)
  45. cfi_rel_offset(%edi, 0)
  46. pushl %esi
  47. cfi_adjust_cfa_offset(4)
  48. cfi_rel_offset(%esi, 0)
  49. pushl %ebx
  50. cfi_adjust_cfa_offset(4)
  51. cfi_rel_offset(%ebx, 0)
  52. xorl %esi, %esi
  53. movl 20(%esp), %ebx
  54. /* Get internal lock. */
  55. movl $1, %edx
  56. xorl %eax, %eax
  57. LOCK
  58. #if cond_lock == 0
  59. cmpxchgl %edx, (%ebx)
  60. #else
  61. cmpxchgl %edx, cond_lock(%ebx)
  62. #endif
  63. jnz 1f
  64. /* Store the reference to the mutex. If there is already a
  65. different value in there this is a bad user bug. */
  66. 2: cmpl $-1, dep_mutex(%ebx)
  67. movl 24(%esp), %eax
  68. je 15f
  69. movl %eax, dep_mutex(%ebx)
  70. /* Unlock the mutex. */
  71. 15: xorl %edx, %edx
  72. call __pthread_mutex_unlock_usercnt
  73. testl %eax, %eax
  74. jne 12f
  75. addl $1, total_seq(%ebx)
  76. adcl $0, total_seq+4(%ebx)
  77. addl $1, cond_futex(%ebx)
  78. addl $(1 << nwaiters_shift), cond_nwaiters(%ebx)
  79. #define FRAME_SIZE 20
  80. subl $FRAME_SIZE, %esp
  81. cfi_adjust_cfa_offset(FRAME_SIZE)
  82. cfi_remember_state
  83. /* Get and store current wakeup_seq value. */
  84. movl wakeup_seq(%ebx), %edi
  85. movl wakeup_seq+4(%ebx), %edx
  86. movl broadcast_seq(%ebx), %eax
  87. movl %edi, 4(%esp)
  88. movl %edx, 8(%esp)
  89. movl %eax, 12(%esp)
  90. /* Reset the pi-requeued flag. */
  91. 8: movl $0, 16(%esp)
  92. movl cond_futex(%ebx), %ebp
  93. /* Unlock. */
  94. LOCK
  95. #if cond_lock == 0
  96. subl $1, (%ebx)
  97. #else
  98. subl $1, cond_lock(%ebx)
  99. #endif
  100. jne 3f
  101. .LcleanupSTART:
  102. 4: call __pthread_enable_asynccancel
  103. movl %eax, (%esp)
  104. xorl %ecx, %ecx
  105. cmpl $-1, dep_mutex(%ebx)
  106. sete %cl
  107. je 18f
  108. movl dep_mutex(%ebx), %edi
  109. /* Requeue to a non-robust PI mutex if the PI bit is set and
  110. the robust bit is not set. */
  111. movl MUTEX_KIND(%edi), %eax
  112. andl $(ROBUST_BIT|PI_BIT), %eax
  113. cmpl $PI_BIT, %eax
  114. jne 18f
  115. movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx
  116. movl %ebp, %edx
  117. xorl %esi, %esi
  118. addl $cond_futex, %ebx
  119. movl $SYS_futex, %eax
  120. ENTER_KERNEL
  121. subl $cond_futex, %ebx
  122. /* Set the pi-requeued flag only if the kernel has returned 0. The
  123. kernel does not hold the mutex on error. */
  124. cmpl $0, %eax
  125. sete 16(%esp)
  126. je 19f
  127. /* Normal and PI futexes dont mix. Use normal futex functions only
  128. if the kernel does not support the PI futex functions. */
  129. cmpl $-ENOSYS, %eax
  130. jne 19f
  131. xorl %ecx, %ecx
  132. 18: subl $1, %ecx
  133. #ifdef __ASSUME_PRIVATE_FUTEX
  134. andl $FUTEX_PRIVATE_FLAG, %ecx
  135. #else
  136. andl %gs:PRIVATE_FUTEX, %ecx
  137. #endif
  138. #if FUTEX_WAIT != 0
  139. addl $FUTEX_WAIT, %ecx
  140. #endif
  141. movl %ebp, %edx
  142. addl $cond_futex, %ebx
  143. .Ladd_cond_futex:
  144. movl $SYS_futex, %eax
  145. ENTER_KERNEL
  146. subl $cond_futex, %ebx
  147. .Lsub_cond_futex:
  148. 19: movl (%esp), %eax
  149. call __pthread_disable_asynccancel
  150. .LcleanupEND:
  151. /* Lock. */
  152. movl $1, %edx
  153. xorl %eax, %eax
  154. LOCK
  155. #if cond_lock == 0
  156. cmpxchgl %edx, (%ebx)
  157. #else
  158. cmpxchgl %edx, cond_lock(%ebx)
  159. #endif
  160. jnz 5f
  161. 6: movl broadcast_seq(%ebx), %eax
  162. cmpl 12(%esp), %eax
  163. jne 16f
  164. movl woken_seq(%ebx), %eax
  165. movl woken_seq+4(%ebx), %ecx
  166. movl wakeup_seq(%ebx), %edi
  167. movl wakeup_seq+4(%ebx), %edx
  168. cmpl 8(%esp), %edx
  169. jne 7f
  170. cmpl 4(%esp), %edi
  171. je 8b
  172. 7: cmpl %ecx, %edx
  173. jne 9f
  174. cmp %eax, %edi
  175. je 8b
  176. 9: addl $1, woken_seq(%ebx)
  177. adcl $0, woken_seq+4(%ebx)
  178. /* Unlock */
  179. 16: subl $(1 << nwaiters_shift), cond_nwaiters(%ebx)
  180. /* Wake up a thread which wants to destroy the condvar object. */
  181. movl total_seq(%ebx), %eax
  182. andl total_seq+4(%ebx), %eax
  183. cmpl $0xffffffff, %eax
  184. jne 17f
  185. movl cond_nwaiters(%ebx), %eax
  186. andl $~((1 << nwaiters_shift) - 1), %eax
  187. jne 17f
  188. addl $cond_nwaiters, %ebx
  189. movl $SYS_futex, %eax
  190. #if FUTEX_PRIVATE_FLAG > 255
  191. xorl %ecx, %ecx
  192. #endif
  193. cmpl $-1, dep_mutex-cond_nwaiters(%ebx)
  194. sete %cl
  195. subl $1, %ecx
  196. #ifdef __ASSUME_PRIVATE_FUTEX
  197. andl $FUTEX_PRIVATE_FLAG, %ecx
  198. #else
  199. andl %gs:PRIVATE_FUTEX, %ecx
  200. #endif
  201. addl $FUTEX_WAKE, %ecx
  202. movl $1, %edx
  203. ENTER_KERNEL
  204. subl $cond_nwaiters, %ebx
  205. 17: LOCK
  206. #if cond_lock == 0
  207. subl $1, (%ebx)
  208. #else
  209. subl $1, cond_lock(%ebx)
  210. #endif
  211. jne 10f
  212. /* With requeue_pi, the mutex lock is held in the kernel. */
  213. 11: movl 24+FRAME_SIZE(%esp), %eax
  214. movl 16(%esp), %ecx
  215. testl %ecx, %ecx
  216. jnz 21f
  217. call __pthread_mutex_cond_lock
  218. 20: addl $FRAME_SIZE, %esp
  219. cfi_adjust_cfa_offset(-FRAME_SIZE);
  220. 14: popl %ebx
  221. cfi_adjust_cfa_offset(-4)
  222. cfi_restore(%ebx)
  223. popl %esi
  224. cfi_adjust_cfa_offset(-4)
  225. cfi_restore(%esi)
  226. popl %edi
  227. cfi_adjust_cfa_offset(-4)
  228. cfi_restore(%edi)
  229. popl %ebp
  230. cfi_adjust_cfa_offset(-4)
  231. cfi_restore(%ebp)
  232. /* We return the result of the mutex_lock operation. */
  233. ret
  234. cfi_restore_state
  235. 21: call __pthread_mutex_cond_lock_adjust
  236. xorl %eax, %eax
  237. jmp 20b
  238. cfi_adjust_cfa_offset(-FRAME_SIZE);
  239. /* Initial locking failed. */
  240. 1:
  241. #if cond_lock == 0
  242. movl %ebx, %edx
  243. #else
  244. leal cond_lock(%ebx), %edx
  245. #endif
  246. #if (LLL_SHARED-LLL_PRIVATE) > 255
  247. xorl %ecx, %ecx
  248. #endif
  249. cmpl $-1, dep_mutex(%ebx)
  250. setne %cl
  251. subl $1, %ecx
  252. andl $(LLL_SHARED-LLL_PRIVATE), %ecx
  253. #if LLL_PRIVATE != 0
  254. addl $LLL_PRIVATE, %ecx
  255. #endif
  256. call __lll_lock_wait
  257. jmp 2b
  258. /* The initial unlocking of the mutex failed. */
  259. 12:
  260. LOCK
  261. #if cond_lock == 0
  262. subl $1, (%ebx)
  263. #else
  264. subl $1, cond_lock(%ebx)
  265. #endif
  266. jne 14b
  267. movl %eax, %esi
  268. #if cond_lock == 0
  269. movl %ebx, %eax
  270. #else
  271. leal cond_lock(%ebx), %eax
  272. #endif
  273. #if (LLL_SHARED-LLL_PRIVATE) > 255
  274. xorl %ecx, %ecx
  275. #endif
  276. cmpl $-1, dep_mutex(%ebx)
  277. setne %cl
  278. subl $1, %ecx
  279. andl $(LLL_SHARED-LLL_PRIVATE), %ecx
  280. #if LLL_PRIVATE != 0
  281. addl $LLL_PRIVATE, %ecx
  282. #endif
  283. call __lll_unlock_wake
  284. movl %esi, %eax
  285. jmp 14b
  286. cfi_adjust_cfa_offset(FRAME_SIZE)
  287. /* Unlock in loop requires wakeup. */
  288. 3:
  289. #if cond_lock == 0
  290. movl %ebx, %eax
  291. #else
  292. leal cond_lock(%ebx), %eax
  293. #endif
  294. #if (LLL_SHARED-LLL_PRIVATE) > 255
  295. xorl %ecx, %ecx
  296. #endif
  297. cmpl $-1, dep_mutex(%ebx)
  298. setne %cl
  299. subl $1, %ecx
  300. andl $(LLL_SHARED-LLL_PRIVATE), %ecx
  301. #if LLL_PRIVATE != 0
  302. addl $LLL_PRIVATE, %ecx
  303. #endif
  304. call __lll_unlock_wake
  305. jmp 4b
  306. /* Locking in loop failed. */
  307. 5:
  308. #if cond_lock == 0
  309. movl %ebx, %edx
  310. #else
  311. leal cond_lock(%ebx), %edx
  312. #endif
  313. #if (LLL_SHARED-LLL_PRIVATE) > 255
  314. xorl %ecx, %ecx
  315. #endif
  316. cmpl $-1, dep_mutex(%ebx)
  317. setne %cl
  318. subl $1, %ecx
  319. andl $(LLL_SHARED-LLL_PRIVATE), %ecx
  320. #if LLL_PRIVATE != 0
  321. addl $LLL_PRIVATE, %ecx
  322. #endif
  323. call __lll_lock_wait
  324. jmp 6b
  325. /* Unlock after loop requires wakeup. */
  326. 10:
  327. #if cond_lock == 0
  328. movl %ebx, %eax
  329. #else
  330. leal cond_lock(%ebx), %eax
  331. #endif
  332. #if (LLL_SHARED-LLL_PRIVATE) > 255
  333. xorl %ecx, %ecx
  334. #endif
  335. cmpl $-1, dep_mutex(%ebx)
  336. setne %cl
  337. subl $1, %ecx
  338. andl $(LLL_SHARED-LLL_PRIVATE), %ecx
  339. #if LLL_PRIVATE != 0
  340. addl $LLL_PRIVATE, %ecx
  341. #endif
  342. call __lll_unlock_wake
  343. jmp 11b
  344. .size __pthread_cond_wait, .-__pthread_cond_wait
  345. weak_alias(__pthread_cond_wait, pthread_cond_wait)
  346. .type __condvar_w_cleanup2, @function
  347. __condvar_w_cleanup2:
  348. subl $cond_futex, %ebx
  349. .size __condvar_w_cleanup2, .-__condvar_w_cleanup2
  350. .LSbl4:
  351. .type __condvar_w_cleanup, @function
  352. __condvar_w_cleanup:
  353. movl %eax, %esi
  354. /* Get internal lock. */
  355. movl $1, %edx
  356. xorl %eax, %eax
  357. LOCK
  358. #if cond_lock == 0
  359. cmpxchgl %edx, (%ebx)
  360. #else
  361. cmpxchgl %edx, cond_lock(%ebx)
  362. #endif
  363. jz 1f
  364. #if cond_lock == 0
  365. movl %ebx, %edx
  366. #else
  367. leal cond_lock(%ebx), %edx
  368. #endif
  369. #if (LLL_SHARED-LLL_PRIVATE) > 255
  370. xorl %ecx, %ecx
  371. #endif
  372. cmpl $-1, dep_mutex(%ebx)
  373. setne %cl
  374. subl $1, %ecx
  375. andl $(LLL_SHARED-LLL_PRIVATE), %ecx
  376. #if LLL_PRIVATE != 0
  377. addl $LLL_PRIVATE, %ecx
  378. #endif
  379. call __lll_lock_wait
  380. 1: movl broadcast_seq(%ebx), %eax
  381. cmpl 12(%esp), %eax
  382. jne 3f
  383. /* We increment the wakeup_seq counter only if it is lower than
  384. total_seq. If this is not the case the thread was woken and
  385. then canceled. In this case we ignore the signal. */
  386. movl total_seq(%ebx), %eax
  387. movl total_seq+4(%ebx), %edi
  388. cmpl wakeup_seq+4(%ebx), %edi
  389. jb 6f
  390. ja 7f
  391. cmpl wakeup_seq(%ebx), %eax
  392. jbe 7f
  393. 6: addl $1, wakeup_seq(%ebx)
  394. adcl $0, wakeup_seq+4(%ebx)
  395. addl $1, cond_futex(%ebx)
  396. 7: addl $1, woken_seq(%ebx)
  397. adcl $0, woken_seq+4(%ebx)
  398. 3: subl $(1 << nwaiters_shift), cond_nwaiters(%ebx)
  399. /* Wake up a thread which wants to destroy the condvar object. */
  400. xorl %edi, %edi
  401. movl total_seq(%ebx), %eax
  402. andl total_seq+4(%ebx), %eax
  403. cmpl $0xffffffff, %eax
  404. jne 4f
  405. movl cond_nwaiters(%ebx), %eax
  406. andl $~((1 << nwaiters_shift) - 1), %eax
  407. jne 4f
  408. addl $cond_nwaiters, %ebx
  409. movl $SYS_futex, %eax
  410. #if FUTEX_PRIVATE_FLAG > 255
  411. xorl %ecx, %ecx
  412. #endif
  413. cmpl $-1, dep_mutex-cond_nwaiters(%ebx)
  414. sete %cl
  415. subl $1, %ecx
  416. #ifdef __ASSUME_PRIVATE_FUTEX
  417. andl $FUTEX_PRIVATE_FLAG, %ecx
  418. #else
  419. andl %gs:PRIVATE_FUTEX, %ecx
  420. #endif
  421. addl $FUTEX_WAKE, %ecx
  422. movl $1, %edx
  423. ENTER_KERNEL
  424. subl $cond_nwaiters, %ebx
  425. movl $1, %edi
  426. 4: LOCK
  427. #if cond_lock == 0
  428. subl $1, (%ebx)
  429. #else
  430. subl $1, cond_lock(%ebx)
  431. #endif
  432. je 2f
  433. #if cond_lock == 0
  434. movl %ebx, %eax
  435. #else
  436. leal cond_lock(%ebx), %eax
  437. #endif
  438. #if (LLL_SHARED-LLL_PRIVATE) > 255
  439. xorl %ecx, %ecx
  440. #endif
  441. cmpl $-1, dep_mutex(%ebx)
  442. setne %cl
  443. subl $1, %ecx
  444. andl $(LLL_SHARED-LLL_PRIVATE), %ecx
  445. #if LLL_PRIVATE != 0
  446. addl $LLL_PRIVATE, %ecx
  447. #endif
  448. call __lll_unlock_wake
  449. /* Wake up all waiters to make sure no signal gets lost. */
  450. 2: testl %edi, %edi
  451. jnz 5f
  452. addl $cond_futex, %ebx
  453. #if FUTEX_PRIVATE_FLAG > 255
  454. xorl %ecx, %ecx
  455. #endif
  456. cmpl $-1, dep_mutex-cond_futex(%ebx)
  457. sete %cl
  458. subl $1, %ecx
  459. #ifdef __ASSUME_PRIVATE_FUTEX
  460. andl $FUTEX_PRIVATE_FLAG, %ecx
  461. #else
  462. andl %gs:PRIVATE_FUTEX, %ecx
  463. #endif
  464. addl $FUTEX_WAKE, %ecx
  465. movl $SYS_futex, %eax
  466. movl $0x7fffffff, %edx
  467. ENTER_KERNEL
  468. 5: movl 24+FRAME_SIZE(%esp), %eax
  469. call __pthread_mutex_cond_lock
  470. movl %esi, (%esp)
  471. .LcallUR:
  472. #ifdef __PIC__
  473. call __i686.get_pc_thunk.bx
  474. addl $_GLOBAL_OFFSET_TABLE_, %ebx
  475. #endif
  476. call _Unwind_Resume@PLT
  477. hlt
  478. .LENDCODE:
  479. cfi_endproc
  480. .size __condvar_w_cleanup, .-__condvar_w_cleanup
  481. .section .gcc_except_table,"a",@progbits
  482. .LexceptSTART:
  483. .byte DW_EH_PE_omit # @LPStart format (omit)
  484. .byte DW_EH_PE_omit # @TType format (omit)
  485. .byte DW_EH_PE_sdata4 # call-site format
  486. # DW_EH_PE_sdata4
  487. .uleb128 .Lcstend-.Lcstbegin
  488. .Lcstbegin:
  489. .long .LcleanupSTART-.LSTARTCODE
  490. .long .Ladd_cond_futex-.LcleanupSTART
  491. .long __condvar_w_cleanup-.LSTARTCODE
  492. .uleb128 0
  493. .long .Ladd_cond_futex-.LSTARTCODE
  494. .long .Lsub_cond_futex-.Ladd_cond_futex
  495. .long __condvar_w_cleanup2-.LSTARTCODE
  496. .uleb128 0
  497. .long .Lsub_cond_futex-.LSTARTCODE
  498. .long .LcleanupEND-.Lsub_cond_futex
  499. .long __condvar_w_cleanup-.LSTARTCODE
  500. .uleb128 0
  501. .long .LcallUR-.LSTARTCODE
  502. .long .LENDCODE-.LcallUR
  503. .long 0
  504. .uleb128 0
  505. .Lcstend:
  506. #ifdef __PIC__
  507. .section .gnu.linkonce.t.__i686.get_pc_thunk.bx,"ax",@progbits
  508. .globl __i686.get_pc_thunk.bx
  509. .hidden __i686.get_pc_thunk.bx
  510. .type __i686.get_pc_thunk.bx,@function
  511. __i686.get_pc_thunk.bx:
  512. movl (%esp), %ebx;
  513. ret
  514. .size __i686.get_pc_thunk.bx,.-__i686.get_pc_thunk.bx
  515. #endif
  516. #ifdef SHARED
  517. .hidden DW.ref.__gcc_personality_v0
  518. .weak DW.ref.__gcc_personality_v0
  519. .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
  520. .align 4
  521. .type DW.ref.__gcc_personality_v0, @object
  522. .size DW.ref.__gcc_personality_v0, 4
  523. DW.ref.__gcc_personality_v0:
  524. .long __gcc_personality_v0
  525. #endif