pthread_cond_wait.S 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  1. /* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library; if not, write to the Free
  13. Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  14. 02111-1307 USA. */
  15. #include <sysdep.h>
  16. #include <lowlevelcond.h>
  17. #include "lowlevel-atomic.h"
  18. #define FUTEX_WAIT 0
  19. #define FUTEX_WAKE 1
  20. .text
  21. /* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) */
  22. .globl __pthread_cond_wait
  23. .type __pthread_cond_wait, @function
  24. .align 5
  25. __pthread_cond_wait:
  26. .LSTARTCODE:
  27. mov.l r8, @-r15
  28. .Lpush_r8:
  29. mov.l r9, @-r15
  30. .Lpush_r9:
  31. mov.l r10, @-r15
  32. .Lpush_r10:
  33. mov.l r11, @-r15
  34. .Lpush_r11:
  35. mov.l r12, @-r15
  36. .Lpush_r12:
  37. sts.l pr, @-r15
  38. .Lpush_pr:
  39. add #-48, r15
  40. .Lalloc:
  41. mov r4, r8
  42. mov r5, r9
  43. #ifdef __PIC__
  44. mova .Lgot0, r0
  45. mov.l .Lgot0, r12
  46. add r0, r12
  47. #endif
  48. /* Get internal lock. */
  49. mov #0, r3
  50. mov #1, r4
  51. #if cond_lock != 0
  52. CMPXCHG (r3, @(cond_lock,r8), r4, r2)
  53. #else
  54. CMPXCHG (r3, @r8, r4, r2)
  55. #endif
  56. bt 2f
  57. bra 1f
  58. nop
  59. #ifdef __PIC__
  60. .align 2
  61. .Lgot0:
  62. .long _GLOBAL_OFFSET_TABLE_
  63. #endif
  64. 2:
  65. /* Store the reference to the mutex. If there is already a
  66. different value in there this is a bad user bug. */
  67. mov.l @(dep_mutex,r8),r0
  68. cmp/eq #-1, r0
  69. bt 15f
  70. mov.l r9, @(dep_mutex,r8)
  71. 15:
  72. /* Unlock the mutex. */
  73. mov.l .Lmunlock0, r1
  74. mov #0, r5
  75. bsrf r1
  76. mov r9, r4
  77. .Lmunlock0b:
  78. tst r0, r0
  79. bt 0f
  80. bra 12f
  81. nop
  82. 0:
  83. mov #1, r2
  84. mov #0, r3
  85. clrt
  86. mov.l @(total_seq,r8),r0
  87. mov.l @(total_seq+4,r8),r1
  88. addc r2, r0
  89. addc r3, r1
  90. mov.l r0,@(total_seq,r8)
  91. mov.l r1,@(total_seq+4,r8)
  92. mov.l @(cond_futex,r8),r0
  93. add r2, r0
  94. mov.l r0,@(cond_futex,r8)
  95. mov #(1 << clock_bits), r2
  96. mov.l @(cond_nwaiters,r8), r0
  97. add r2, r0
  98. mov.l r0, @(cond_nwaiters,r8)
  99. /* Get and store current wakeup_seq value. */
  100. mov.l @(wakeup_seq,r8), r10
  101. mov.l @(wakeup_seq+4,r8), r11
  102. mov.l @(broadcast_seq,r8), r0
  103. mov.l r0, @(4,r15)
  104. 8:
  105. mov.l @(cond_futex,r8),r0
  106. mov.l r0, @(8,r15)
  107. /* Unlock. */
  108. #if cond_lock != 0
  109. DEC (@(cond_lock,r8), r2)
  110. #else
  111. DEC (@r8, r2)
  112. #endif
  113. tst r2, r2
  114. bf 3f
  115. 4:
  116. .LcleanupSTART:
  117. mov.l .Lenable0, r1
  118. bsrf r1
  119. nop
  120. .Lenable0b:
  121. mov.l r0, @r15
  122. mov #0, r7
  123. mov #FUTEX_WAIT, r5
  124. mov.l @(8,r15), r6
  125. mov r8, r4
  126. add #cond_futex, r4
  127. mov #SYS_futex, r3
  128. extu.b r3, r3
  129. trapa #0x14
  130. SYSCALL_INST_PAD
  131. mov.l .Ldisable0, r1
  132. bsrf r1
  133. mov.l @r15, r4
  134. .Ldisable0b:
  135. .LcleanupEND:
  136. /* Lock. */
  137. mov #0, r3
  138. mov #1, r4
  139. #if cond_lock != 0
  140. CMPXCHG (r3, @(cond_lock,r8), r4, r2)
  141. #else
  142. CMPXCHG (r3, @r8, r4, r2)
  143. #endif
  144. bf 5f
  145. 6:
  146. mov.l @(broadcast_seq,r8), r0
  147. mov.l @(4,r15), r1
  148. cmp/eq r0, r1
  149. bf 16f
  150. mov.l @(woken_seq,r8), r0
  151. mov.l @(woken_seq+4,r8), r1
  152. mov.l @(wakeup_seq,r8), r2
  153. mov.l @(wakeup_seq+4,r8), r3
  154. cmp/eq r3, r11
  155. bf 7f
  156. cmp/eq r2, r10
  157. bt 8b
  158. 7:
  159. cmp/eq r1, r3
  160. bf 9f
  161. cmp/eq r0, r2
  162. bt 8b
  163. 9:
  164. mov #1, r2
  165. mov #0, r3
  166. clrt
  167. mov.l @(woken_seq,r8),r0
  168. mov.l @(woken_seq+4,r8),r1
  169. addc r2, r0
  170. addc r3, r1
  171. mov.l r0,@(woken_seq,r8)
  172. mov.l r1,@(woken_seq+4,r8)
  173. 16:
  174. mov #(1 << clock_bits), r2
  175. mov.l @(cond_nwaiters,r8),r0
  176. sub r2, r0
  177. mov.l r0,@(cond_nwaiters,r8)
  178. /* Wake up a thread which wants to destroy the condvar object. */
  179. mov.l @(total_seq,r8),r0
  180. mov.l @(total_seq+4,r8),r1
  181. and r1, r0
  182. not r0, r0
  183. cmp/eq #0, r0
  184. bf/s 17f
  185. mov #((1 << clock_bits) - 1), r1
  186. not r1, r1
  187. mov.l @(cond_nwaiters,r8),r0
  188. tst r1, r0
  189. bf 17f
  190. mov r8, r4
  191. add #cond_nwaiters, r4
  192. mov #FUTEX_WAKE, r5
  193. mov #1, r6
  194. mov #0, r7
  195. mov #SYS_futex, r3
  196. extu.b r3, r3
  197. trapa #0x14
  198. SYSCALL_INST_PAD
  199. 17:
  200. #if cond_lock != 0
  201. DEC (@(cond_lock,r8), r2)
  202. #else
  203. DEC (@r8, r2)
  204. #endif
  205. tst r2, r2
  206. bf 10f
  207. 11:
  208. mov.l .Lmlocki0, r1
  209. bsrf r1
  210. mov r9, r4
  211. .Lmlocki0b:
  212. /* We return the result of the mutex_lock operation. */
  213. 14:
  214. add #48, r15
  215. lds.l @r15+, pr
  216. mov.l @r15+, r12
  217. mov.l @r15+, r11
  218. mov.l @r15+, r10
  219. mov.l @r15+, r9
  220. rts
  221. mov.l @r15+, r8
  222. .align 2
  223. .Lmunlock0:
  224. .long __pthread_mutex_unlock_usercnt-.Lmunlock0b
  225. .Lenable0:
  226. .long __pthread_enable_asynccancel-.Lenable0b
  227. .Ldisable0:
  228. .long __pthread_disable_asynccancel-.Ldisable0b
  229. .Lmlocki0:
  230. .long __pthread_mutex_cond_lock-.Lmlocki0b
  231. 1:
  232. /* Initial locking failed. */
  233. mov r8, r5
  234. #if cond_lock != 0
  235. add #cond_lock, r5
  236. #endif
  237. mov.l .Lmwait0, r1
  238. bsrf r1
  239. mov r2, r4
  240. .Lmwait0b:
  241. bra 2b
  242. nop
  243. 3:
  244. /* Unlock in loop requires waekup. */
  245. mov r8, r4
  246. #if cond_lock != 0
  247. add #cond_lock, r4
  248. #endif
  249. mov.l .Lmwake0, r1
  250. bsrf r1
  251. nop
  252. .Lmwake0b:
  253. bra 4b
  254. nop
  255. 5:
  256. /* Locking in loop failed. */
  257. mov r8, r5
  258. #if cond_lock != 0
  259. add #cond_lock, r5
  260. #endif
  261. mov.l .Lmwait1, r1
  262. bsrf r1
  263. mov r2, r4
  264. .Lmwait1b:
  265. bra 6b
  266. nop
  267. 10:
  268. /* Unlock after loop requires wakeup. */
  269. mov r8, r4
  270. #if cond_lock != 0
  271. add #cond_lock, r4
  272. #endif
  273. mov.l .Lmwake1, r1
  274. bsrf r1
  275. nop
  276. .Lmwake1b:
  277. bra 11b
  278. nop
  279. 12:
  280. /* The initial unlocking of the mutex failed. */
  281. mov.l r0, @(12,r15)
  282. #if cond_lock != 0
  283. DEC (@(cond_lock,r8), r2)
  284. #else
  285. DEC (@r8, r2)
  286. #endif
  287. tst r2, r2
  288. bf 13f
  289. mov r8, r4
  290. #if cond_lock != 0
  291. add #cond_lock, r4
  292. #endif
  293. mov.l .Lmwake2, r1
  294. bsrf r1
  295. nop
  296. .Lmwake2b:
  297. 13:
  298. bra 14b
  299. mov.l @(12,r15), r0
  300. .align 2
  301. .Lmwait0:
  302. .long __lll_mutex_lock_wait-.Lmwait0b
  303. .Lmwake0:
  304. .long __lll_mutex_unlock_wake-.Lmwake0b
  305. .Lmwait1:
  306. .long __lll_mutex_lock_wait-.Lmwait1b
  307. .Lmwake1:
  308. .long __lll_mutex_unlock_wake-.Lmwake1b
  309. .Lmwake2:
  310. .long __lll_mutex_unlock_wake-.Lmwake2b
  311. .size __pthread_cond_wait, .-__pthread_cond_wait
  312. weak_alias (__pthread_cond_wait, pthread_cond_wait)
  313. .type __condvar_w_cleanup, @function
  314. __condvar_w_cleanup:
  315. mov r4, r11
  316. /* Get internal lock. */
  317. mov #0, r3
  318. mov #1, r4
  319. #if cond_lock != 0
  320. CMPXCHG (r3, @(cond_lock,r8), r4, r2)
  321. #else
  322. CMPXCHG (r3, @r8, r4, r2)
  323. #endif
  324. bt 1f
  325. nop
  326. mov r8, r5
  327. #if cond_lock != 0
  328. add #cond_lock, r5
  329. #endif
  330. mov.l .Lmwait3, r1
  331. bsrf r1
  332. mov r2, r4
  333. .Lmwait3b:
  334. 1:
  335. mov.l @(broadcast_seq,r8), r0
  336. mov.l @(4,r15), r1
  337. cmp/eq r0, r1
  338. bf 3f
  339. mov #1, r2
  340. mov #0, r3
  341. clrt
  342. mov.l @(wakeup_seq,r8),r0
  343. mov.l @(wakeup_seq+4,r8),r1
  344. addc r2, r0
  345. addc r3, r1
  346. mov.l r0,@(wakeup_seq,r8)
  347. mov.l r1,@(wakeup_seq+4,r8)
  348. mov.l @(cond_futex,r8),r0
  349. add r2, r0
  350. mov.l r0,@(cond_futex,r8)
  351. clrt
  352. mov.l @(woken_seq,r8),r0
  353. mov.l @(woken_seq+4,r8),r1
  354. addc r2, r0
  355. addc r3, r1
  356. mov.l r0,@(woken_seq,r8)
  357. mov.l r1,@(woken_seq+4,r8)
  358. 3:
  359. mov #(1 << clock_bits), r2
  360. mov.l @(cond_nwaiters,r8),r0
  361. sub r2, r0
  362. mov.l r0,@(cond_nwaiters,r8)
  363. /* Wake up a thread which wants to destroy the condvar object. */
  364. mov #0, r10
  365. mov.l @(total_seq,r8),r0
  366. mov.l @(total_seq+4,r8),r1
  367. and r1, r0
  368. not r0, r0
  369. cmp/eq #0, r0
  370. bf/s 4f
  371. mov #((1 << clock_bits) - 1), r1
  372. not r1, r1
  373. mov.l @(cond_nwaiters,r8),r0
  374. tst r1, r0
  375. bf 4f
  376. mov r8, r4
  377. add #cond_nwaiters, r4
  378. mov #FUTEX_WAKE, r5
  379. mov #1, r6
  380. mov #0, r7
  381. mov #SYS_futex, r3
  382. extu.b r3, r3
  383. trapa #0x14
  384. SYSCALL_INST_PAD
  385. mov #1, r10
  386. 4:
  387. #if cond_lock != 0
  388. DEC (@(cond_lock,r8), r2)
  389. #else
  390. DEC (@r8, r2)
  391. #endif
  392. tst r2, r2
  393. bt 2f
  394. mov r8, r4
  395. #if cond_lock != 0
  396. add #cond_lock, r4
  397. #endif
  398. mov.l .Lmwake3, r1
  399. bsrf r1
  400. nop
  401. .Lmwake3b:
  402. 2:
  403. /* Wake up all waiters to make sure no signal gets lost. */
  404. tst r10, r10
  405. bf/s 5f
  406. mov r8, r4
  407. add #cond_futex, r4
  408. mov #FUTEX_WAKE, r5
  409. mov #-1, r6
  410. shlr r6 /* r6 = 0x7fffffff */
  411. mov #0, r7
  412. mov #SYS_futex, r3
  413. extu.b r3, r3
  414. trapa #0x14
  415. SYSCALL_INST_PAD
  416. 5:
  417. mov.l .Lmlocki3, r1
  418. bsrf r1
  419. mov r9, r4
  420. .Lmlocki3b:
  421. .LcallUR:
  422. mov.l .Lresume, r1
  423. #ifdef __PIC__
  424. add r12, r1
  425. #endif
  426. jsr @r1
  427. mov r11, r4
  428. sleep
  429. .align 2
  430. .Lmwait3:
  431. .long __lll_mutex_lock_wait-.Lmwait3b
  432. .Lmwake3:
  433. .long __lll_mutex_unlock_wake-.Lmwake3b
  434. .Lmlocki3:
  435. .long __pthread_mutex_cond_lock-.Lmlocki3b
  436. .Lresume:
  437. #ifdef __PIC__
  438. .long _Unwind_Resume@GOTOFF
  439. #else
  440. .long _Unwind_Resume
  441. #endif
  442. .LENDCODE:
  443. .size __condvar_w_cleanup, .-__condvar_w_cleanup
  444. .section .gcc_except_table,"a",@progbits
  445. .LexceptSTART:
  446. .byte 0xff ! @LPStart format (omit)
  447. .byte 0xff ! @TType format (omit)
  448. .byte 0x0b ! call-site format
  449. ! DW_EH_PE_sdata4
  450. .uleb128 .Lcstend-.Lcstbegin
  451. .Lcstbegin:
  452. .ualong .LcleanupSTART-.LSTARTCODE
  453. .ualong .LcleanupEND-.LcleanupSTART
  454. .ualong __condvar_w_cleanup-.LSTARTCODE
  455. .uleb128 0
  456. .ualong .LcallUR-.LSTARTCODE
  457. .ualong .LENDCODE-.LcallUR
  458. .ualong 0
  459. .uleb128 0
  460. .Lcstend:
  461. .section .eh_frame,"a",@progbits
  462. .LSTARTFRAME:
  463. .ualong .LENDCIE-.LSTARTCIE ! Length of the CIE.
  464. .LSTARTCIE:
  465. .ualong 0 ! CIE ID.
  466. .byte 1 ! Version number.
  467. #ifdef SHARED
  468. .string "zPLR" ! NUL-terminated augmentation
  469. ! string.
  470. #else
  471. .string "zPL" ! NUL-terminated augmentation
  472. ! string.
  473. #endif
  474. .uleb128 1 ! Code alignment factor.
  475. .sleb128 -4 ! Data alignment factor.
  476. .byte 0x11 ! Return address register
  477. ! column.
  478. #ifdef SHARED
  479. .uleb128 7 ! Augmentation value length.
  480. .byte 0x9b ! Personality: DW_EH_PE_pcrel
  481. ! + DW_EH_PE_sdata4
  482. ! + DW_EH_PE_indirect
  483. .ualong DW.ref.__gcc_personality_v0-.
  484. .byte 0x1b ! LSDA Encoding: DW_EH_PE_pcrel
  485. ! + DW_EH_PE_sdata4.
  486. .byte 0x1b ! FDE Encoding: DW_EH_PE_pcrel
  487. ! + DW_EH_PE_sdata4.
  488. #else
  489. .uleb128 6 ! Augmentation value length.
  490. .byte 0x0 ! Personality: absolute
  491. .ualong __gcc_personality_v0
  492. .byte 0x0 ! LSDA Encoding: absolute
  493. #endif
  494. .byte 0x0c ! DW_CFA_def_cfa
  495. .uleb128 0xf
  496. .uleb128 0
  497. .align 2
  498. .LENDCIE:
  499. .ualong .LENDFDE-.LSTARTFDE ! Length of the FDE.
  500. .LSTARTFDE:
  501. .ualong .LSTARTFDE-.LSTARTFRAME ! CIE pointer.
  502. #ifdef SHARED
  503. .ualong .LSTARTCODE-. ! PC-relative start address
  504. ! of the code.
  505. #else
  506. .ualong .LSTARTCODE ! Start address of the code.
  507. #endif
  508. .ualong .LENDCODE-.LSTARTCODE ! Length of the code.
  509. .uleb128 4 ! Augmentation size
  510. #ifdef SHARED
  511. .ualong .LexceptSTART-.
  512. #else
  513. .ualong .LexceptSTART
  514. #endif
  515. .byte 0x4
  516. .ualong .Lpush_r8-.LSTARTCODE
  517. .byte 0xe
  518. .uleb128 4
  519. .byte 0x88
  520. .uleb128 1
  521. .byte 0x4
  522. .ualong .Lpush_r9-.Lpush_r8
  523. .byte 0xe
  524. .uleb128 8
  525. .byte 0x89
  526. .uleb128 2
  527. .byte 0x4
  528. .ualong .Lpush_r10-.Lpush_r9
  529. .byte 0xe
  530. .uleb128 12
  531. .byte 0x8a
  532. .uleb128 3
  533. .byte 0x4
  534. .ualong .Lpush_r11-.Lpush_r10
  535. .byte 0xe
  536. .uleb128 16
  537. .byte 0x8b
  538. .uleb128 4
  539. .byte 0x4
  540. .ualong .Lpush_r12-.Lpush_r11
  541. .byte 0xe
  542. .uleb128 20
  543. .byte 0x8c
  544. .uleb128 5
  545. .byte 0x4
  546. .ualong .Lpush_pr-.Lpush_r12
  547. .byte 0xe
  548. .uleb128 24
  549. .byte 0x91
  550. .uleb128 6
  551. .byte 0x4
  552. .ualong .Lalloc-.Lpush_pr
  553. .byte 0xe
  554. .uleb128 72
  555. .align 2
  556. .LENDFDE:
  557. #ifdef SHARED
  558. .hidden DW.ref.__gcc_personality_v0
  559. .weak DW.ref.__gcc_personality_v0
  560. .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
  561. .align 4
  562. .type DW.ref.__gcc_personality_v0, @object
  563. .size DW.ref.__gcc_personality_v0, 4
  564. DW.ref.__gcc_personality_v0:
  565. .long __gcc_personality_v0
  566. #endif