lowlevellock.S 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  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. .align 5
  135. cfi_startproc
  136. __lll_lock_wait_private:
  137. mov.l r8, @-r15
  138. cfi_adjust_cfa_offset(4)
  139. cfi_rel_offset (r8, 0)
  140. mov r4, r6
  141. mov r5, r8
  142. mov #0, r7 /* No timeout. */
  143. LOAD_PRIVATE_FUTEX_WAIT (r5, r0, r1)
  144. mov #2, r4
  145. cmp/eq r4, r6
  146. bf 2f
  147. 1:
  148. mov r8, r4
  149. mov #SYS_futex, r3
  150. extu.b r3, r3
  151. trapa #0x14
  152. SYSCALL_INST_PAD
  153. 2:
  154. mov #2, r6
  155. XCHG (r6, @r8, r2)
  156. tst r2, r2
  157. bf 1b
  158. mov.l @r15+, r8
  159. rts
  160. mov r2, r0
  161. cfi_endproc
  162. .size __lll_lock_wait_private,.-__lll_lock_wait_private
  163. #ifdef NOT_IN_libc
  164. .globl __lll_lock_wait
  165. .type __lll_lock_wait,@function
  166. .hidden __lll_lock_wait
  167. .align 5
  168. cfi_startproc
  169. __lll_lock_wait:
  170. mov.l r9, @-r15
  171. cfi_adjust_cfa_offset(4)
  172. cfi_rel_offset (r9, 0)
  173. mov.l r8, @-r15
  174. cfi_adjust_cfa_offset(4)
  175. cfi_rel_offset (r8, 0)
  176. mov r6, r9
  177. mov r4, r6
  178. mov r5, r8
  179. mov #0, r7 /* No timeout. */
  180. mov r9, r5
  181. LOAD_FUTEX_WAIT (r5, r0, r1)
  182. mov #2, r4
  183. cmp/eq r4, r6
  184. bf 2f
  185. 1:
  186. mov r8, r4
  187. mov #SYS_futex, r3
  188. extu.b r3, r3
  189. trapa #0x14
  190. SYSCALL_INST_PAD
  191. 2:
  192. mov #2, r6
  193. XCHG (r6, @r8, r2)
  194. tst r2, r2
  195. bf 1b
  196. mov.l @r15+, r8
  197. mov.l @r15+, r9
  198. ret
  199. mov r2, r0
  200. cfi_endproc
  201. .size __lll_lock_wait,.-__lll_lock_wait
  202. /* r5 (r8): futex
  203. r7 (r11): flags
  204. r6 (r9): timeout
  205. r4 (r10): futex value
  206. */
  207. .globl __lll_timedlock_wait
  208. .type __lll_timedlock_wait,@function
  209. .hidden __lll_timedlock_wait
  210. .align 5
  211. cfi_startproc
  212. __lll_timedlock_wait:
  213. mov.l r12, @-r15
  214. cfi_adjust_cfa_offset(4)
  215. cfi_rel_offset (r12, 0)
  216. # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
  217. mov.l .Lhave, r1
  218. # ifdef __PIC__
  219. mova .Lgot, r0
  220. mov.l .Lgot, r12
  221. add r0, r12
  222. add r12, r1
  223. # endif
  224. mov.l @r1, r0
  225. tst r0, r0
  226. bt .Lreltmo
  227. # endif
  228. mov r4, r2
  229. mov r5, r4
  230. mov r7, r5
  231. mov r6, r7
  232. LOAD_FUTEX_WAIT_ABS (r5, r0, r1)
  233. mov #2, r6
  234. cmp/eq r6, r2
  235. bf/s 2f
  236. mov r6, r2
  237. 1:
  238. mov #2, r6
  239. mov #-1, r1
  240. mov #SYS_futex, r3
  241. extu.b r3, r3
  242. trapa #0x16
  243. SYSCALL_INST_PAD
  244. mov r0, r6
  245. 2:
  246. XCHG (r2, @r4, r3) /* NB: lock is implied */
  247. tst r3, r3
  248. bt/s 3f
  249. mov r6, r0
  250. cmp/eq #-ETIMEDOUT, r0
  251. bt 4f
  252. cmp/eq #-EINVAL, r0
  253. bf 1b
  254. 4:
  255. neg r0, r3
  256. 3:
  257. mov r3, r0
  258. rts
  259. mov.l @r15+, r12
  260. .align 2
  261. # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
  262. # ifdef __PIC__
  263. .Lgot:
  264. .long _GLOBAL_OFFSET_TABLE_
  265. .Lhave:
  266. .long __have_futex_clock_realtime@GOTOFF
  267. # else
  268. .Lhave:
  269. .long __have_futex_clock_realtime
  270. # endif
  271. .Lreltmo:
  272. /* Check for a valid timeout value. */
  273. mov.l @(4,r6), r1
  274. mov.l .L1g, r0
  275. cmp/hs r0, r1
  276. bt 3f
  277. mov.l r11, @-r15
  278. cfi_adjust_cfa_offset(4)
  279. cfi_rel_offset (r11, 0)
  280. mov.l r10, @-r15
  281. cfi_adjust_cfa_offset(4)
  282. cfi_rel_offset (r10, 0)
  283. mov.l r9, @-r15
  284. cfi_adjust_cfa_offset(4)
  285. cfi_rel_offset (r9, 0)
  286. mov.l r8, @-r15
  287. cfi_adjust_cfa_offset(4)
  288. cfi_rel_offset (r8, 0)
  289. mov r7, r11
  290. mov r4, r10
  291. mov r6, r9
  292. mov r5, r8
  293. /* Stack frame for the timespec and timeval structs. */
  294. add #-8, r15
  295. cfi_adjust_cfa_offset(8)
  296. mov #2, r2
  297. XCHG (r2, @r8, r3)
  298. tst r3, r3
  299. bt 6f
  300. 1:
  301. /* Get current time. */
  302. mov r15, r4
  303. mov #0, r5
  304. mov #__NR_gettimeofday, r3
  305. trapa #0x12
  306. SYSCALL_INST_PAD
  307. /* Compute relative timeout. */
  308. mov.l @(4,r15), r0
  309. mov.w .L1k, r1
  310. dmulu.l r0, r1 /* Micro seconds to nano seconds. */
  311. mov.l @r9, r2
  312. mov.l @(4,r9), r3
  313. mov.l @r15, r0
  314. sts macl, r1
  315. sub r0, r2
  316. clrt
  317. subc r1, r3
  318. bf 4f
  319. mov.l .L1g, r1
  320. add r1, r3
  321. add #-1, r2
  322. 4:
  323. cmp/pz r2
  324. bf 2f /* Time is already up. */
  325. mov.l r2, @r15 /* Store relative timeout. */
  326. mov.l r3, @(4,r15)
  327. mov r8, r4
  328. mov r11, r5
  329. LOAD_FUTEX_WAIT (r5, r0, r1)
  330. mov r10, r6
  331. mov r15, r7
  332. mov #SYS_futex, r3
  333. extu.b r3, r3
  334. trapa #0x14
  335. SYSCALL_INST_PAD
  336. mov r0, r5
  337. mov #2, r2
  338. XCHG (r2, @r8, r3)
  339. tst r3, r3
  340. bt/s 6f
  341. mov #-ETIMEDOUT, r1
  342. cmp/eq r5, r1
  343. bf 1b
  344. 2: mov #ETIMEDOUT, r3
  345. 6:
  346. mov r3, r0
  347. add #8, r15
  348. mov.l @r15+, r8
  349. mov.l @r15+, r9
  350. mov.l @r15+, r10
  351. mov.l @r15+, r11
  352. rts
  353. mov.l @r15+, r12
  354. 3:
  355. mov.l @r15+, r12
  356. rts
  357. mov #EINVAL, r0
  358. # endif
  359. cfi_endproc
  360. .L1k:
  361. .word 1000
  362. .align 2
  363. .L1g:
  364. .long 1000000000
  365. .size __lll_timedlock_wait,.-__lll_timedlock_wait
  366. #endif
  367. .globl __lll_unlock_wake_private
  368. .type __lll_unlock_wake_private,@function
  369. .hidden __lll_unlock_wake_private
  370. .align 5
  371. cfi_startproc
  372. __lll_unlock_wake_private:
  373. LOAD_PRIVATE_FUTEX_WAKE (r5, r0, r1)
  374. mov #1, r6 /* Wake one thread. */
  375. mov #0, r7
  376. mov.l r7, @r4 /* Stores 0. */
  377. mov #SYS_futex, r3
  378. extu.b r3, r3
  379. trapa #0x14
  380. SYSCALL_INST_PAD
  381. rts
  382. nop
  383. cfi_endproc
  384. .size __lll_unlock_wake_private,.-__lll_unlock_wake_private
  385. #ifdef NOT_IN_libc
  386. .globl __lll_unlock_wake
  387. .type __lll_unlock_wake,@function
  388. .hidden __lll_unlock_wake
  389. .align 5
  390. cfi_startproc
  391. __lll_unlock_wake:
  392. LOAD_FUTEX_WAKE (r5, r0, r1)
  393. mov #1, r6 /* Wake one thread. */
  394. mov #0, r7
  395. mov.l r7, @r4 /* Stores 0. */
  396. mov #SYS_futex, r3
  397. extu.b r3, r3
  398. trapa #0x14
  399. SYSCALL_INST_PAD
  400. rts
  401. nop
  402. cfi_endproc
  403. .size __lll_unlock_wake,.-__lll_unlock_wake
  404. .globl __lll_timedwait_tid
  405. .type __lll_timedwait_tid,@function
  406. .hidden __lll_timedwait_tid
  407. .align 5
  408. cfi_startproc
  409. __lll_timedwait_tid:
  410. mov.l r9, @-r15
  411. cfi_adjust_cfa_offset(4)
  412. cfi_rel_offset (r9, 0)
  413. mov.l r8, @-r15
  414. cfi_adjust_cfa_offset(4)
  415. cfi_rel_offset (r8, 0)
  416. mov r4, r8
  417. mov r5, r9
  418. /* Stack frame for the timespec and timeval structs. */
  419. add #-8, r15
  420. cfi_adjust_cfa_offset(8)
  421. 2:
  422. /* Get current time. */
  423. mov r15, r4
  424. mov #0, r5
  425. mov #__NR_gettimeofday, r3
  426. trapa #0x12
  427. SYSCALL_INST_PAD
  428. /* Compute relative timeout. */
  429. mov.l @(4,r15), r0
  430. mov.w .L1k2, r1
  431. dmulu.l r0, r1 /* Micro seconds to nano seconds. */
  432. mov.l @r9, r2
  433. mov.l @(4,r9), r3
  434. mov.l @r15, r0
  435. sts macl, r1
  436. sub r0, r2
  437. clrt
  438. subc r1, r3
  439. bf 5f
  440. mov.l .L1g2, r1
  441. add r1, r3
  442. add #-1, r2
  443. 5:
  444. cmp/pz r2
  445. bf 6f /* Time is already up. */
  446. mov.l r2, @r15 /* Store relative timeout. */
  447. mov.l r3, @(4,r15)
  448. mov.l @r8, r2
  449. tst r2, r2
  450. bt 4f
  451. mov r8, r4
  452. /* XXX The kernel so far uses global futex for the wakeup at
  453. all times. */
  454. mov #0, r5
  455. extu.b r5, r5
  456. mov r2, r6
  457. mov r15, r7
  458. mov #SYS_futex, r3
  459. extu.b r3, r3
  460. trapa #0x14
  461. SYSCALL_INST_PAD
  462. mov.l @r8, r2
  463. tst r2, r2
  464. bf 1f
  465. 4:
  466. mov #0, r0
  467. 3:
  468. add #8, r15
  469. mov.l @r15+, r8
  470. rts
  471. mov.l @r15+, r9
  472. 1:
  473. /* Check whether the time expired. */
  474. mov #-ETIMEDOUT, r1
  475. cmp/eq r0, r1
  476. bf 2b
  477. 6:
  478. bra 3b
  479. mov #ETIMEDOUT, r0
  480. cfi_endproc
  481. .L1k2:
  482. .word 1000
  483. .align 2
  484. .L1g2:
  485. .long 1000000000
  486. .size __lll_timedwait_tid,.-__lll_timedwait_tid
  487. #endif