lowlevellock.S 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. /* Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009
  2. Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  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. #include "lowlevel-atomic.h"
  21. .text
  22. #ifdef __ASSUME_PRIVATE_FUTEX
  23. # define LOAD_PRIVATE_FUTEX_WAIT(reg,tmp,tmp2) \
  24. mov #(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg; \
  25. extu.b reg, reg
  26. # define LOAD_PRIVATE_FUTEX_WAKE(reg,tmp,tmp2) \
  27. mov #(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg; \
  28. extu.b reg, reg
  29. # define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \
  30. mov #(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), tmp; \
  31. extu.b tmp, tmp; \
  32. xor tmp, reg
  33. # define LOAD_FUTEX_WAIT_ABS(reg,tmp,tmp2) \
  34. mov #(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG), tmp; \
  35. extu.b tmp, tmp; \
  36. mov #(FUTEX_CLOCK_REALTIME >> 8), tmp2; \
  37. swap.b tmp2, tmp2; \
  38. or tmp2, tmp; \
  39. xor tmp, reg
  40. # define LOAD_FUTEX_WAKE(reg,tmp,tmp2) \
  41. mov #(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), tmp; \
  42. extu.b tmp, tmp; \
  43. xor tmp, reg
  44. #else
  45. # if FUTEX_WAIT == 0
  46. # define LOAD_PRIVATE_FUTEX_WAIT(reg,tmp,tmp2) \
  47. stc gbr, tmp ; \
  48. mov.w 99f, reg ; \
  49. add reg, tmp ; \
  50. bra 98f ; \
  51. mov.l @tmp, reg ; \
  52. 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
  53. 98:
  54. # else
  55. # define LOAD_PRIVATE_FUTEX_WAIT(reg,tmp,tmp2) \
  56. stc gbr, tmp ; \
  57. mov.w 99f, reg ; \
  58. add reg, tmp ; \
  59. mov.l @tmp, reg ; \
  60. bra 98f ; \
  61. mov #FUTEX_WAIT, tmp ; \
  62. 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
  63. 98: or tmp, reg
  64. # endif
  65. # define LOAD_PRIVATE_FUTEX_WAKE(reg,tmp,tmp2) \
  66. stc gbr, tmp ; \
  67. mov.w 99f, reg ; \
  68. add reg, tmp ; \
  69. mov.l @tmp, reg ; \
  70. bra 98f ; \
  71. mov #FUTEX_WAKE, tmp ; \
  72. 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
  73. 98: or tmp, reg
  74. # if FUTEX_WAIT == 0
  75. # define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \
  76. stc gbr, tmp ; \
  77. mov.w 99f, tmp2 ; \
  78. add tmp2, tmp ; \
  79. mov.l @tmp, tmp2 ; \
  80. bra 98f ; \
  81. mov #FUTEX_PRIVATE_FLAG, tmp ; \
  82. 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
  83. 98: extu.b tmp, tmp ; \
  84. xor tmp, reg ; \
  85. and tmp2, reg
  86. # else
  87. # define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \
  88. stc gbr, tmp ; \
  89. mov.w 99f, tmp2 ; \
  90. add tmp2, tmp ; \
  91. mov.l @tmp, tmp2 ; \
  92. bra 98f ; \
  93. mov #FUTEX_PRIVATE_FLAG, tmp ; \
  94. 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
  95. 98: extu.b tmp, tmp ; \
  96. xor tmp, reg ; \
  97. and tmp2, reg ; \
  98. mov #FUTEX_WAIT, tmp ; \
  99. or tmp, reg
  100. # endif
  101. # define LOAD_FUTEX_WAIT_ABS(reg,tmp,tmp2) \
  102. stc gbr, tmp ; \
  103. mov.w 99f, tmp2 ; \
  104. add tmp2, tmp ; \
  105. mov.l @tmp, tmp2 ; \
  106. bra 98f ; \
  107. mov #FUTEX_PRIVATE_FLAG, tmp ; \
  108. 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
  109. 98: extu.b tmp, tmp ; \
  110. xor tmp, reg ; \
  111. and tmp2, reg ; \
  112. mov #FUTEX_WAIT_BITSET, tmp ; \
  113. mov #(FUTEX_CLOCK_REALTIME >> 8), tmp2; \
  114. swap.b tmp2, tmp2; \
  115. or tmp2, tmp; \
  116. or tmp, reg
  117. # define LOAD_FUTEX_WAKE(reg,tmp,tmp2) \
  118. stc gbr, tmp ; \
  119. mov.w 99f, tmp2 ; \
  120. add tmp2, tmp ; \
  121. mov.l @tmp, tmp2 ; \
  122. bra 98f ; \
  123. mov #FUTEX_PRIVATE_FLAG, tmp ; \
  124. 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
  125. 98: extu.b tmp, tmp ; \
  126. xor tmp, reg ; \
  127. and tmp2, reg ; \
  128. mov #FUTEX_WAKE, tmp ; \
  129. or tmp, reg
  130. #endif
  131. .globl __lll_lock_wait_private
  132. .type __lll_lock_wait_private,@function
  133. .hidden __lll_lock_wait_private
  134. #ifndef IS_IN_libpthread
  135. .weak __lll_lock_wait_private
  136. #endif
  137. .align 5
  138. cfi_startproc
  139. __lll_lock_wait_private:
  140. mov.l r8, @-r15
  141. cfi_adjust_cfa_offset(4)
  142. cfi_rel_offset (r8, 0)
  143. mov r4, r6
  144. mov r5, r8
  145. mov #0, r7 /* No timeout. */
  146. LOAD_PRIVATE_FUTEX_WAIT (r5, r0, r1)
  147. mov #2, r4
  148. cmp/eq r4, r6
  149. bf 2f
  150. 1:
  151. mov r8, r4
  152. mov #SYS_futex, r3
  153. extu.b r3, r3
  154. trapa #0x14
  155. SYSCALL_INST_PAD
  156. 2:
  157. mov #2, r6
  158. XCHG (r6, @r8, r2)
  159. tst r2, r2
  160. bf 1b
  161. mov.l @r15+, r8
  162. rts
  163. mov r2, r0
  164. cfi_endproc
  165. .size __lll_lock_wait_private,.-__lll_lock_wait_private
  166. #ifdef NOT_IN_libc
  167. .globl __lll_lock_wait
  168. .type __lll_lock_wait,@function
  169. .hidden __lll_lock_wait
  170. .align 5
  171. cfi_startproc
  172. __lll_lock_wait:
  173. mov.l r9, @-r15
  174. cfi_adjust_cfa_offset(4)
  175. cfi_rel_offset (r9, 0)
  176. mov.l r8, @-r15
  177. cfi_adjust_cfa_offset(4)
  178. cfi_rel_offset (r8, 0)
  179. mov r6, r9
  180. mov r4, r6
  181. mov r5, r8
  182. mov #0, r7 /* No timeout. */
  183. mov r9, r5
  184. LOAD_FUTEX_WAIT (r5, r0, r1)
  185. mov #2, r4
  186. cmp/eq r4, r6
  187. bf 2f
  188. 1:
  189. mov r8, r4
  190. mov #SYS_futex, r3
  191. extu.b r3, r3
  192. trapa #0x14
  193. SYSCALL_INST_PAD
  194. 2:
  195. mov #2, r6
  196. XCHG (r6, @r8, r2)
  197. tst r2, r2
  198. bf 1b
  199. mov.l @r15+, r8
  200. mov.l @r15+, r9
  201. ret
  202. mov r2, r0
  203. cfi_endproc
  204. .size __lll_lock_wait,.-__lll_lock_wait
  205. /* r5 (r8): futex
  206. r7 (r11): flags
  207. r6 (r9): timeout
  208. r4 (r10): futex value
  209. */
  210. .globl __lll_timedlock_wait
  211. .type __lll_timedlock_wait,@function
  212. .hidden __lll_timedlock_wait
  213. .align 5
  214. cfi_startproc
  215. __lll_timedlock_wait:
  216. mov.l r12, @-r15
  217. cfi_adjust_cfa_offset(4)
  218. cfi_rel_offset (r12, 0)
  219. # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
  220. mov.l .Lhave, r1
  221. # ifdef __PIC__
  222. mova .Lgot, r0
  223. mov.l .Lgot, r12
  224. add r0, r12
  225. add r12, r1
  226. # endif
  227. mov.l @r1, r0
  228. tst r0, r0
  229. bt .Lreltmo
  230. # endif
  231. mov r4, r2
  232. mov r5, r4
  233. mov r7, r5
  234. mov r6, r7
  235. LOAD_FUTEX_WAIT_ABS (r5, r0, r1)
  236. mov #2, r6
  237. cmp/eq r6, r2
  238. bf/s 2f
  239. mov r6, r2
  240. 1:
  241. mov #2, r6
  242. mov #-1, r1
  243. mov #SYS_futex, r3
  244. extu.b r3, r3
  245. trapa #0x16
  246. SYSCALL_INST_PAD
  247. mov r0, r6
  248. 2:
  249. XCHG (r2, @r4, r3) /* NB: lock is implied */
  250. tst r3, r3
  251. bt/s 3f
  252. mov r6, r0
  253. cmp/eq #-ETIMEDOUT, r0
  254. bt 4f
  255. cmp/eq #-EINVAL, r0
  256. bf 1b
  257. 4:
  258. neg r0, r3
  259. 3:
  260. mov r3, r0
  261. rts
  262. mov.l @r15+, r12
  263. .align 2
  264. # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
  265. # ifdef __PIC__
  266. .Lgot:
  267. .long _GLOBAL_OFFSET_TABLE_
  268. .Lhave:
  269. .long __have_futex_clock_realtime@GOTOFF
  270. # else
  271. .Lhave:
  272. .long __have_futex_clock_realtime
  273. # endif
  274. .Lreltmo:
  275. /* Check for a valid timeout value. */
  276. mov.l @(4,r6), r1
  277. mov.l .L1g, r0
  278. cmp/hs r0, r1
  279. bt 3f
  280. mov.l r11, @-r15
  281. cfi_adjust_cfa_offset(4)
  282. cfi_rel_offset (r11, 0)
  283. mov.l r10, @-r15
  284. cfi_adjust_cfa_offset(4)
  285. cfi_rel_offset (r10, 0)
  286. mov.l r9, @-r15
  287. cfi_adjust_cfa_offset(4)
  288. cfi_rel_offset (r9, 0)
  289. mov.l r8, @-r15
  290. cfi_adjust_cfa_offset(4)
  291. cfi_rel_offset (r8, 0)
  292. mov r7, r11
  293. mov r4, r10
  294. mov r6, r9
  295. mov r5, r8
  296. /* Stack frame for the timespec and timeval structs. */
  297. add #-8, r15
  298. cfi_adjust_cfa_offset(8)
  299. mov #2, r2
  300. XCHG (r2, @r8, r3)
  301. tst r3, r3
  302. bt 6f
  303. 1:
  304. /* Get current time. */
  305. mov r15, r4
  306. mov #0, r5
  307. mov #__NR_gettimeofday, r3
  308. trapa #0x12
  309. SYSCALL_INST_PAD
  310. /* Compute relative timeout. */
  311. mov.l @(4,r15), r0
  312. mov.w .L1k, r1
  313. dmulu.l r0, r1 /* Micro seconds to nano seconds. */
  314. mov.l @r9, r2
  315. mov.l @(4,r9), r3
  316. mov.l @r15, r0
  317. sts macl, r1
  318. sub r0, r2
  319. clrt
  320. subc r1, r3
  321. bf 4f
  322. mov.l .L1g, r1
  323. add r1, r3
  324. add #-1, r2
  325. 4:
  326. cmp/pz r2
  327. bf 2f /* Time is already up. */
  328. mov.l r2, @r15 /* Store relative timeout. */
  329. mov.l r3, @(4,r15)
  330. mov r8, r4
  331. mov r11, r5
  332. LOAD_FUTEX_WAIT (r5, r0, r1)
  333. mov r10, r6
  334. mov r15, r7
  335. mov #SYS_futex, r3
  336. extu.b r3, r3
  337. trapa #0x14
  338. SYSCALL_INST_PAD
  339. mov r0, r5
  340. mov #2, r2
  341. XCHG (r2, @r8, r3)
  342. tst r3, r3
  343. bt/s 6f
  344. mov #-ETIMEDOUT, r1
  345. cmp/eq r5, r1
  346. bf 1b
  347. 2: mov #ETIMEDOUT, r3
  348. 6:
  349. mov r3, r0
  350. add #8, r15
  351. mov.l @r15+, r8
  352. mov.l @r15+, r9
  353. mov.l @r15+, r10
  354. mov.l @r15+, r11
  355. rts
  356. mov.l @r15+, r12
  357. 3:
  358. mov.l @r15+, r12
  359. rts
  360. mov #EINVAL, r0
  361. # endif
  362. cfi_endproc
  363. .L1k:
  364. .word 1000
  365. .align 2
  366. .L1g:
  367. .long 1000000000
  368. .size __lll_timedlock_wait,.-__lll_timedlock_wait
  369. #endif
  370. .globl __lll_unlock_wake_private
  371. .type __lll_unlock_wake_private,@function
  372. .hidden __lll_unlock_wake_private
  373. #ifndef IS_IN_libpthread
  374. .weak __lll_unlock_wake_private
  375. #endif
  376. .align 5
  377. cfi_startproc
  378. __lll_unlock_wake_private:
  379. LOAD_PRIVATE_FUTEX_WAKE (r5, r0, r1)
  380. mov #1, r6 /* Wake one thread. */
  381. mov #0, r7
  382. mov.l r7, @r4 /* Stores 0. */
  383. mov #SYS_futex, r3
  384. extu.b r3, r3
  385. trapa #0x14
  386. SYSCALL_INST_PAD
  387. rts
  388. nop
  389. cfi_endproc
  390. .size __lll_unlock_wake_private,.-__lll_unlock_wake_private
  391. #ifdef NOT_IN_libc
  392. .globl __lll_unlock_wake
  393. .type __lll_unlock_wake,@function
  394. .hidden __lll_unlock_wake
  395. .align 5
  396. cfi_startproc
  397. __lll_unlock_wake:
  398. LOAD_FUTEX_WAKE (r5, r0, r1)
  399. mov #1, r6 /* Wake one thread. */
  400. mov #0, r7
  401. mov.l r7, @r4 /* Stores 0. */
  402. mov #SYS_futex, r3
  403. extu.b r3, r3
  404. trapa #0x14
  405. SYSCALL_INST_PAD
  406. rts
  407. nop
  408. cfi_endproc
  409. .size __lll_unlock_wake,.-__lll_unlock_wake
  410. .globl __lll_timedwait_tid
  411. .type __lll_timedwait_tid,@function
  412. .hidden __lll_timedwait_tid
  413. .align 5
  414. cfi_startproc
  415. __lll_timedwait_tid:
  416. mov.l r9, @-r15
  417. cfi_adjust_cfa_offset(4)
  418. cfi_rel_offset (r9, 0)
  419. mov.l r8, @-r15
  420. cfi_adjust_cfa_offset(4)
  421. cfi_rel_offset (r8, 0)
  422. mov r4, r8
  423. mov r5, r9
  424. /* Stack frame for the timespec and timeval structs. */
  425. add #-8, r15
  426. cfi_adjust_cfa_offset(8)
  427. 2:
  428. /* Get current time. */
  429. mov r15, r4
  430. mov #0, r5
  431. mov #__NR_gettimeofday, r3
  432. trapa #0x12
  433. SYSCALL_INST_PAD
  434. /* Compute relative timeout. */
  435. mov.l @(4,r15), r0
  436. mov.w .L1k2, r1
  437. dmulu.l r0, r1 /* Micro seconds to nano seconds. */
  438. mov.l @r9, r2
  439. mov.l @(4,r9), r3
  440. mov.l @r15, r0
  441. sts macl, r1
  442. sub r0, r2
  443. clrt
  444. subc r1, r3
  445. bf 5f
  446. mov.l .L1g2, r1
  447. add r1, r3
  448. add #-1, r2
  449. 5:
  450. cmp/pz r2
  451. bf 6f /* Time is already up. */
  452. mov.l r2, @r15 /* Store relative timeout. */
  453. mov.l r3, @(4,r15)
  454. mov.l @r8, r2
  455. tst r2, r2
  456. bt 4f
  457. mov r8, r4
  458. /* XXX The kernel so far uses global futex for the wakeup at
  459. all times. */
  460. mov #0, r5
  461. extu.b r5, r5
  462. mov r2, r6
  463. mov r15, r7
  464. mov #SYS_futex, r3
  465. extu.b r3, r3
  466. trapa #0x14
  467. SYSCALL_INST_PAD
  468. mov.l @r8, r2
  469. tst r2, r2
  470. bf 1f
  471. 4:
  472. mov #0, r0
  473. 3:
  474. add #8, r15
  475. mov.l @r15+, r8
  476. rts
  477. mov.l @r15+, r9
  478. 1:
  479. /* Check whether the time expired. */
  480. mov #-ETIMEDOUT, r1
  481. cmp/eq r0, r1
  482. bf 2b
  483. 6:
  484. bra 3b
  485. mov #ETIMEDOUT, r0
  486. cfi_endproc
  487. .L1k2:
  488. .word 1000
  489. .align 2
  490. .L1g2:
  491. .long 1000000000
  492. .size __lll_timedwait_tid,.-__lll_timedwait_tid
  493. #endif