lowlevellock.S 10 KB

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