diff --git a/libc/intrin/asan.c b/libc/intrin/asan.c index bcfc9cf1f..0e8a14f7c 100644 --- a/libc/intrin/asan.c +++ b/libc/intrin/asan.c @@ -948,9 +948,9 @@ static dontdiscard __asan_die_f *__asan_report_memory_fault( static void *__asan_morgue_add(void *p) { return atomic_exchange_explicit( __asan_morgue.p + (atomic_fetch_add_explicit(&__asan_morgue.i, 1, - memory_order_acquire) & + memory_order_acq_rel) & (ARRAYLEN(__asan_morgue.p) - 1)), - p, memory_order_release); + p, memory_order_acq_rel); } static void __asan_morgue_flush(void) { diff --git a/libc/stdio/getrandom.c b/libc/stdio/getrandom.c index 6050cde77..7d8ae5d64 100644 --- a/libc/stdio/getrandom.c +++ b/libc/stdio/getrandom.c @@ -53,7 +53,6 @@ static ssize_t GetDevRandom(char *p, size_t n) { pthread_cleanup_push((void *)sys_close, (void *)(intptr_t)fd); rc = sys_read(fd, p, n); pthread_cleanup_pop(1); - close(fd); return rc; } diff --git a/libc/sysv/systemfive.S b/libc/sysv/systemfive.S index 08b0e4b38..0efda018e 100644 --- a/libc/sysv/systemfive.S +++ b/libc/sysv/systemfive.S @@ -108,6 +108,9 @@ __pid: .quad 0 .endobj __pid,globl,hidden .previous +systemfive_cp: + push %rbp + mov %rsp,%rbp systemfive_cancellable: # our pthread_cancel() miracle code cmpb $0,__tls_enabled(%rip) # inspired by the musl libc design! je 1f # we handle linux and bsd together! @@ -118,12 +121,12 @@ systemfive_cancellable: # our pthread_cancel() miracle code testb $PT_NOCANCEL,0x00(%r10) # PosixThread::flags jnz 1f # canceler no cancelling cmp $0,0x04(%r10) # PosixThread::cancelled - jne _pthread_cancel_sys # tail call for masked mode - .weak _pthread_cancel_sys # must be linked if we're cancelled + jne systemfive_cancel # tail call for masked mode 1: mov %rcx,%r10 # move the fourth argument clc # no cancellable system calls exist syscall # that have 7+ args on the bsd OSes systemfive_cancellable_end: # i/o calls park here for long time + pop %rbp jc systemfive_errno jmp 0f jc 3f # we're now out of the limbo state! @@ -143,10 +146,15 @@ systemfive_cancellable_end: # i/o calls park here for long time jnz systemfive_errno # cancellation is disabled cmp $0,0x04(%rcx) # PosixThread::cancelled je systemfive_errno # we aren't actually cancelled - jmp _pthread_cancel_sys # now we are in fact cancelled - .endfn systemfive_cancellable,globl,hidden + jmp 1f # now we are in fact cancelled +systemfive_cancel: + pop %rbp +1: jmp _pthread_cancel_sys # must be linked if we're cancelled + .weak _pthread_cancel_sys .globl systemfive_cancellable_end - .hidden systemfive_cancellable_end + .globl systemfive_cancellable + .globl systemfive_cancel + .endfn systemfive_cp .Lanchorpoint: #if SupportsLinux() || SupportsMetal() @@ -155,7 +163,7 @@ systemfive_linux: cmp $0xfff,%eax # checks if unsupported by platform je systemfive_enosys # never taken branches cost nothing btr $11,%eax # 0x800 means a call is cancellable - jc systemfive_cancellable # it is handled by the holiest code + jc systemfive_cp # it is handled by the holiest code mov %rcx,%r10 # syscall instruction clobbers %rcx push %rbp # linux never reads args from stack mov %rsp,%rbp # having frame will help backtraces @@ -210,7 +218,7 @@ systemfive_bsd: cmp $0xfff,%ax je systemfive_enosys btr $11,%eax # checks/reset the 800 cancellable bit - jc systemfive_cancellable + jc systemfive_cp mov %rcx,%r10 syscall # bsd will need arg on stack sometimes jc systemfive_errno # bsd sets carry flag if %rax is errno diff --git a/libc/thread/pthread_cancel.c b/libc/thread/pthread_cancel.c index 4bd51ff2a..389a29028 100644 --- a/libc/thread/pthread_cancel.c +++ b/libc/thread/pthread_cancel.c @@ -34,8 +34,10 @@ #include "libc/thread/thread.h" #include "libc/thread/tls.h" -extern const char systemfive_cancellable[] hidden; -extern const char systemfive_cancellable_end[] hidden; +int systemfive_cancel(void); + +extern const char systemfive_cancellable[]; +extern const char systemfive_cancellable_end[]; int _pthread_cancel_sys(void) { struct PosixThread *pt; @@ -57,7 +59,7 @@ static void OnSigCancel(int sig, siginfo_t *si, void *ctx) { if ((pt->flags & PT_ASYNC) || (systemfive_cancellable <= (char *)uc->uc_mcontext.rip && (char *)uc->uc_mcontext.rip < systemfive_cancellable_end)) { - uc->uc_mcontext.rip = (intptr_t)_pthread_cancel_sys; + uc->uc_mcontext.rip = (intptr_t)systemfive_cancel; } else { tkill(atomic_load_explicit(&tib->tib_tid, memory_order_relaxed), sig); }