.globl _thread_chkstk_darwin
_thread_chkstk_darwin:
.globl ____chkstk_darwin
-____chkstk_darwin: // %w9 == alloca size
+____chkstk_darwin: // %w9/x9 == alloca size
stp x10, x11, [sp, #-16]
// validate that the frame pointer is on our stack (no alt stack)
// (%sp - pthread_self()->stackaddr) > 0 ?
#if defined(__ARM64_ARCH_8_32__)
+ ubfx x9, x9, #0, #32
ldur w11, [x10, _PTHREAD_STRUCT_DIRECT_STACKADDR_OFFSET]
#else
ldur x11, [x10, _PTHREAD_STRUCT_DIRECT_STACKADDR_OFFSET]
cmp x10, x11
b.ls Lprobe
- // %sp - (uintptr_t)%w9 < pthread_self()->stackbottom ?
- subs x10, x10, w9, uxtw
+ // %sp - (uintptr_t)%x9 < pthread_self()->stackbottom ?
+ subs x10, x10, x9
b.lo Lcrash
cmp x10, x11
b.lo Lcrash
Lprobe:
mov x10, sp
- cmp w9, #0x1000
+ cmp x9, #0x1000
b.lo Lend
Lloop:
sub x10, x10, #0x1000
ldr x11, [x10]
- sub w9, w9, #0x1000
- cmp w9, #0x1000
+ sub x9, x9, #0x1000
+ cmp x9, #0x1000
b.hi Lloop
Lend:
sub x10, x10, x9
mutex_seq oldseq, newseq;
mutex_seq_load(seqaddr, &oldseq);
- if (os_unlikely(oldseq.lgenval & PTH_RWL_EBIT)) {
+ if (os_unlikely(!trylock && (oldseq.lgenval & PTH_RWL_EBIT))) {
return _pthread_mutex_firstfit_lock_slow(mutex, trylock);
}
gotlock = is_rwl_ebit_clear(oldseq.lgenval);
if (trylock && !gotlock) {
+#if __LP64__
+ // The sequence load is atomic, so we can bail here without writing
+ // it and avoid some unnecessary coherence traffic - rdar://57259033
+ os_atomic_thread_fence(acquire);
+ return EBUSY;
+#else
// A trylock on a held lock will fail immediately. But since
// we did not load the sequence words atomically, perform a
// no-op CAS64 to ensure that nobody has unlocked concurrently.
+#endif
} else if (os_likely(gotlock)) {
// In first-fit, getting the lock simply adds the E-bit
newseq.lgenval |= PTH_RWL_EBIT;
};
T_ASSERT_POSIX_SUCCESS(sigaction(SIGSEGV, &sa, NULL), "sigaction");
- call_chkstk(1 << 24);
+#if __LP64__
+ call_chkstk(1ul << 32);
+#else
+ call_chkstk(1ul << 24);
+#endif
T_FAIL("should have crashed");
#endif
}