Improve cancellations, randomness, and time

- Exhaustively document cancellation points
- Rename SIGCANCEL to SIGTHR just like BSDs
- Further improve POSIX thread cancellations
- Ensure asynchronous cancellations work correctly
- Elevate the quality of getrandom() and getentropy()
- Make futexes cancel correctly on OpenBSD 6.x and 7.x
- Add reboot.com and shutdown.com to examples directory
- Remove underscore prefix from awesome timespec_*() APIs
- Create assertions that help verify our cancellation points
- Remove bad timespec APIs (cmp generalizes eq/ne/gt/gte/lt/lte)
This commit is contained in:
Justine Tunney 2022-11-05 19:49:41 -07:00
parent 0d7c265392
commit 3f0bcdc3ef
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
173 changed files with 1599 additions and 782 deletions

View file

@ -0,0 +1,2 @@
.include "o/libc/sysv/macros.internal.inc"
.scall __sys_openat_nc,0x1d41411f321d0101,globl,hidden

View file

@ -1,2 +1,2 @@
.include "o/libc/sysv/macros.internal.inc"
.scall sys_copy_file_range,0xffffff239ffff146,globl,hidden
.scall sys_copy_file_range,0xffffffa39ffff946,globl,hidden

View file

@ -1,2 +1,2 @@
.include "o/libc/sysv/macros.internal.inc"
.scall sys_getrandom,0xfff807a3329f493e,globl,hidden
.scall sys_getrandom,0x85b007a3321f493e,globl,hidden

View file

@ -1,2 +1,2 @@
.include "o/libc/sysv/macros.internal.inc"
.scall sys_tgkill,0xfffffffffffff0ea,globl,hidden
.scall sys_tgkill,0xffffff1e1ffff0ea,globl,hidden

View file

@ -168,10 +168,10 @@ syscon sig SIGPROF 27 27 27 27 27 27 # profiling timer expired;
syscon sig SIGWINCH 28 28 28 28 28 28 # terminal resized; unix consensus & faked on nt
syscon sig SIGIO 29 23 23 23 23 29 # bsd consensus
syscon sig SIGSYS 31 12 12 12 12 31 # wut; bsd consensus
syscon sig SIGINFO 0 29 29 29 29 0 # bsd consensus
syscon sig SIGEMT 0 7 7 7 7 0 # not implemented in most community editions of system five; consider doing this using SIGUSR1 or SIGUSR2 instead
syscon sig SIGINFO 63 29 29 29 29 63 # bsd consensus
syscon sig SIGEMT 64 7 7 7 7 64 # not implemented in most community editions of system five; consider doing this using SIGUSR1 or SIGUSR2 instead
syscon sig SIGPWR 30 30 30 30 32 30 # not implemented in most community editions of system five; consider doing this using SIGUSR1 or SIGUSR2 instead
syscon sig SIGCANCEL 32 7 65 7 33 32 # SIGRTMIN+0; faked as SIGEMT on XNU and OpenBSD
syscon sig SIGTHR 32 7 32 32 33 32 # used by pthread_cancel(); SIGRTMIN+0 on Linux/NetBSD; faked as SIGEMT on XNU (what is SIG32 on XNU anyway?)
syscon sig SIGRTMIN 32 0 65 0 33 32
syscon sig SIGRTMAX 64 0 126 0 63 64
syscon compat SIGPOLL 29 23 23 23 23 29 # same as SIGIO

View file

@ -1,2 +1,2 @@
.include "o/libc/sysv/consts/syscon.internal.inc"
.syscon sig,SIGEMT,0,7,7,7,7,0
.syscon sig,SIGEMT,64,7,7,7,7,64

View file

@ -1,2 +1,2 @@
.include "o/libc/sysv/consts/syscon.internal.inc"
.syscon sig,SIGINFO,0,29,29,29,29,0
.syscon sig,SIGINFO,63,29,29,29,29,63

View file

@ -1,2 +1,2 @@
.include "o/libc/sysv/consts/syscon.internal.inc"
.syscon sig,SIGCANCEL,32,7,65,7,33,32
.syscon sig,SIGTHR,32,7,32,32,33,32

View file

@ -7,7 +7,7 @@ COSMOPOLITAN_C_START_
extern const int SIGABRT;
extern const int SIGALRM;
extern const int SIGBUS;
extern const int SIGCANCEL;
extern const int SIGTHR;
extern const int SIGCHLD;
extern const int SIGCONT;
extern const int SIGEMT;
@ -73,7 +73,7 @@ COSMOPOLITAN_C_END_
#define SIGXFSZ LITERALLY(25)
#define SIGBUS SYMBOLIC(SIGBUS)
#define SIGCANCEL SYMBOLIC(SIGCANCEL)
#define SIGTHR SYMBOLIC(SIGTHR)
#define SIGCHLD SYMBOLIC(SIGCHLD)
#define SIGCONT SYMBOLIC(SIGCONT)
#define SIGEMT SYMBOLIC(SIGEMT)

View file

@ -100,7 +100,8 @@ scall __sys_wait4 0x9c180b807280783d globl hidden
scall sys_kill 0x02507a025202503e globl hidden # kill(pid, sig, 1) b/c xnu
scall sys_killpg 0x092fff092fffffff globl hidden
scall sys_clone 0x11fffffffffff038 globl hidden
scall sys_tkill 0x13e0771b121480c8 globl hidden # thr_kill() on freebsd; _lwp_kill() on netbsd; thrkill() on openbsd where arg3 should be 0; __pthread_kill() on XNU
scall sys_tkill 0x13e0771b121480c8 globl hidden # thr_kill() on FreeBSD; _lwp_kill() on NetBSD; thrkill() on OpenBSD where arg3 should be 0 or tcb; __pthread_kill() on XNU
scall sys_tgkill 0xffffff1e1ffff0ea globl hidden # thr_kill2() on FreeBSD
scall sys_futex 0x0a60531c6ffff0ca globl hidden # raises SIGSYS on NetBSD; _umtx_op() on FreeBSD
scall sys_futex_cp 0x8a68539c6ffff8ca globl hidden # intended for futex wait ops
scall sys_set_robust_list 0x0a7ffffffffff111 globl # no wrapper
@ -265,7 +266,6 @@ scall sys_ktimer_settime 0xffffff0edfffffff globl # no wrapper
scall sys_clock_settime 0x1ac0580e9ffff0e3 globl # no wrapper
scall sys_clock_gettime 0x1ab0570e8ffff0e4 globl hidden # Linux 2.6+ (c. 2003); XNU uses magic address
scall sys_clock_getres 0x1ad0590eaffff0e5 globl hidden
scall sys_tgkill 0xfffffffffffff0ea globl hidden
scall sys_mbind 0xfffffffffffff0ed globl # no wrapper; numa numa yeah
scall set_mempolicy 0xfffffffffffff0ee globl
scall get_mempolicy 0xfffffffffffff0ef globl
@ -286,6 +286,7 @@ scall sys_inotify_init 0xfffffffffffff0fd globl # wicked # no wrapper
scall sys_inotify_add_watch 0xfffffffffffff0fe globl # no wrapper
scall sys_inotify_rm_watch 0xfffffffffffff0ff globl # no wrapper
scall __sys_openat 0x9d49419f329cf901 globl hidden # Linux 2.6.16+ (c. 2007)
scall __sys_openat_nc 0x1d41411f321d0101 globl hidden # openat_nocancel() on xnu
scall sys_mkdirat 0x1cd13e1f021db102 globl hidden
scall sys_fchownat 0x1d013b1eb21d4104 globl hidden # @asyncsignalsafe
scall sys_utime 0xfffffffffffff084 globl hidden
@ -350,7 +351,7 @@ scall sys_sched_setattr 0xfffffffffffff13a globl # ├─ desktop replaced with
scall sys_sched_getattr 0xfffffffffffff13b globl # ├─ karen sandler requires systemd init and boot for tablet gui
scall sys_renameat2 0xfffffffffffff13c globl # └─ debian founder ian murdock found strangled with vacuum cord
#scall seccomp 0xfffffffffffff13d globl # wrapped manually
scall sys_getrandom 0xfff807a3329f493e globl hidden # Linux 3.17+ and getentropy() on XNU/OpenBSD, coming to NetBSD in 9.2
scall sys_getrandom 0x85b007a3321f493e globl hidden # Linux 3.17+; FreeBSD 12+; NetBSD v9.2+; getentropy() on XNU/OpenBSD
scall sys_memfd_create 0xfffffffffffff13f globl hidden
scall sys_kexec_file_load 0xfffffffffffff140 globl # no wrapper
scall sys_bpf 0xfffffffffffff141 globl # no wrapper
@ -358,7 +359,7 @@ scall sys_execveat 0xfffffffffffff142 globl # no wrapper
scall sys_userfaultfd 0xfffffffffffff143 globl # no wrapper; Linux 4.3+ (c. 2015)
scall sys_membarrier 0xfffffffffffff144 globl # no wrapper; Linux 4.3+ (c. 2015)
scall sys_mlock2 0xfffffffffffff145 globl # no wrapper; Linux 4.5+ (c. 2016)
scall sys_copy_file_range 0xffffff239ffff146 globl hidden # Linux 4.5+ (c. 2016), FreeBSD 13+
scall sys_copy_file_range 0xffffffa39ffff946 globl hidden # Linux 4.5+ (c. 2016), FreeBSD 13+
scall sys_preadv2 0xfffffffffffff147 globl # no wrapper
scall sys_pwritev2 0xfffffffffffff148 globl # no wrapper
scall sys_pkey_mprotect 0xfffffffffffff149 globl # no wrapper

View file

@ -110,7 +110,7 @@ __pid: .quad 0
systemfive_cp:
push %rbp
mov %rsp,%rbp
mov %rsp,%rbp # so backtraces work
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!
@ -120,21 +120,24 @@ systemfive_cancellable: # our pthread_cancel() miracle code
jz 1f # it's spawn() probably
testb $PT_NOCANCEL,0x00(%r10) # PosixThread::flags
jnz 1f # canceler no cancelling
#if IsModeDbg()
testb $PT_INCANCEL,0x00(%r10)
jz 5f
#endif
cmp $0,0x04(%r10) # PosixThread::cancelled
jne systemfive_cancel # tail call for masked mode
jne systemfive_cancel # we will tail call below
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!
1: cmp $-4095,%rax # but we still check again on eintr
jae 2f
jnc 2f
neg %rax # turns bsd errno to system v errno
2: cmp $-4095,%rax # but we still check again on eintr
jae 3f # branch because system call failed
ret # done if the system call succeeded
2: neg %eax # now examine the nature of failure
3: cmp EINTR(%rip),%eax # did SIGCANCEL cancel our i/o call
3: neg %eax # now examine the nature of failure
cmp EINTR(%rip),%eax # did the SIGTHR cancel our IO call
jne systemfive_errno # werent interrupted by OnSigCancel
cmpb $0,__tls_enabled(%rip) # make sure it's safe to grab %fs:0
je systemfive_errno # tls is disabled we can't continue
@ -146,11 +149,22 @@ 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 1f # now we are in fact cancelled
systemfive_cancel:
jmp 4f # now we are in fact cancelled
systemfive_cancel: # SIGTHR will jump here too
pop %rbp
1: jmp _pthread_cancel_sys # must be linked if we're cancelled
.weak _pthread_cancel_sys
4: jmp _pthread_cancel_sys # tail call
.weak _pthread_cancel_sys # must be linked if we're cancelled
#if IsModeDbg()
not_a_cancellation_point: # need BEGIN/END_CANCELLATION_POINT
nop
.weak report_cancellation_point
5: ezlea report_cancellation_point,cx
test %rcx,%rcx
jz 6f
call *%rcx
6: ud2
nop
#endif
.globl systemfive_cancellable_end
.globl systemfive_cancellable
.globl systemfive_cancel
@ -169,7 +183,7 @@ systemfive_linux:
mov %rsp,%rbp # having frame will help backtraces
syscall # this is known as a context switch
pop %rbp # next we check to see if it failed
0: cmp $-4095,%rax # system five nexgen32e abi § a.2.1
cmp $-4095,%rax # system five nexgen32e abi § a.2.1
jae systemfive_error # encodes errno as neg return value
ret
.endfn systemfive_linux,globl,hidden