summaryrefslogtreecommitdiff
path: root/libc/ports/sysdeps/arm/dl-tlsdesc.S
diff options
context:
space:
mode:
authorWill Newton <will.newton@linaro.org>2014-05-23 15:24:30 +0100
committerWill Newton <will.newton@linaro.org>2014-07-03 14:59:35 +0100
commitfebf5a6a0b9aaf79b2dbdcf2dfe7f61d3ff938fc (patch)
tree628d8081995c458844b043c89ed11ecbe35e6034 /libc/ports/sysdeps/arm/dl-tlsdesc.S
parent5321828811bbfe277da5a4098fd960e41b23df3a (diff)
ARM: Fix handling of concurrent TLS descriptor resolution
The current code for handling concurrent resolution says that the ABI for _dl_tlsdesc_resolve_hold is the same as that of _dl_tlsdesc_lazy_resolver. However _dl_tlsdesc_resolve_hold is called from the trampoline directly rather than the lazy resolver stub so, for example, r2 has not been pushed so does not needed to be restored. This fixes an intermittent failure in nptl/tst-tls3 when building glibc for arm-linux-gnueabihf with -mtls-dialect=gnu2. ChangeLog: 2014-05-27 Will Newton <will.newton@linaro.org> [BZ #16990] * sysdeps/arm/dl-tlsdesc.S (_dl_tlsdesc_resolve_hold): Save and restore r2 rather than just restoring.
Diffstat (limited to 'libc/ports/sysdeps/arm/dl-tlsdesc.S')
-rw-r--r--libc/ports/sysdeps/arm/dl-tlsdesc.S31
1 files changed, 12 insertions, 19 deletions
diff --git a/libc/ports/sysdeps/arm/dl-tlsdesc.S b/libc/ports/sysdeps/arm/dl-tlsdesc.S
index 1644a3279..e87e7fb00 100644
--- a/libc/ports/sysdeps/arm/dl-tlsdesc.S
+++ b/libc/ports/sysdeps/arm/dl-tlsdesc.S
@@ -186,7 +186,9 @@ _dl_tlsdesc_lazy_resolver:
.size _dl_tlsdesc_lazy_resolver, .-_dl_tlsdesc_lazy_resolver
/* Holder for lazy tls descriptors being resolve in another thread.
- Same ABI as the lazy resolver itself. */
+
+ Our calling convention is to clobber r0, r1 and the processor
+ flags. All others that are modified must be saved */
.hidden _dl_tlsdesc_resolve_hold
.global _dl_tlsdesc_resolve_hold
.type _dl_tlsdesc_resolve_hold,#function
@@ -194,29 +196,20 @@ _dl_tlsdesc_lazy_resolver:
eabi_fnstart
.align 2
_dl_tlsdesc_resolve_hold:
- /* Tell the unwinder that r2 has already been pushed. */
- eabi_save ({r2})
- cfi_adjust_cfa_offset (4)
+ eabi_save ({r2,r3,ip,lr})
+ push {r2, r3, ip, lr}
+ cfi_adjust_cfa_offset (16)
cfi_rel_offset (r2, 0)
- eabi_save ({r0,r1,r3,ip,lr})
- push {r0, r1, r3, ip, lr}
- cfi_adjust_cfa_offset (20)
- cfi_rel_offset (r0, 0)
- cfi_rel_offset (r1, 4)
- cfi_rel_offset (r3, 8)
- cfi_rel_offset (ip, 12)
- cfi_rel_offset (lr, 16)
- adr r2, _dl_tlsdesc_resolve_hold
+ cfi_rel_offset (r3, 4)
+ cfi_rel_offset (ip, 8)
+ cfi_rel_offset (lr, 12)
+ adr r1, _dl_tlsdesc_resolve_hold
bl _dl_tlsdesc_resolve_hold_fixup
- pop {r0, r1, r3, ip, lr}
- cfi_adjust_cfa_offset (-20)
+ pop {r2, r3, ip, lr}
+ cfi_adjust_cfa_offset (-16)
cfi_restore (lr)
cfi_restore (ip)
cfi_restore (r3)
- cfi_restore (r1)
- cfi_restore (r0)
- pop {r2}
- cfi_adjust_cfa_offset (-4)
cfi_restore (r2)
sfi_breg r0, \
ldr r1, [\B, #4]