diff options
author | A. Wilcox <AWilcox@Wilcox-Tech.com> | 2018-08-24 15:35:06 +0000 |
---|---|---|
committer | A. Wilcox <AWilcox@Wilcox-Tech.com> | 2018-08-24 15:35:06 +0000 |
commit | 409fe2a85188baaa8a737c1a4fe19fb0df47eb62 (patch) | |
tree | c59c9ba5ca00ed664fedc32b9a6557f4e3e41eb1 /system/musl/amalgamation.patch | |
parent | 23e639121014d2e94bcf768313a46a9df3d85d41 (diff) | |
download | packages-409fe2a85188baaa8a737c1a4fe19fb0df47eb62.tar.gz packages-409fe2a85188baaa8a737c1a4fe19fb0df47eb62.tar.bz2 packages-409fe2a85188baaa8a737c1a4fe19fb0df47eb62.tar.xz packages-409fe2a85188baaa8a737c1a4fe19fb0df47eb62.zip |
system/musl: package patch now even with tip of POSIX branch
Diffstat (limited to 'system/musl/amalgamation.patch')
-rw-r--r-- | system/musl/amalgamation.patch | 6417 |
1 files changed, 6417 insertions, 0 deletions
diff --git a/system/musl/amalgamation.patch b/system/musl/amalgamation.patch new file mode 100644 index 000000000..08228fb84 --- /dev/null +++ b/system/musl/amalgamation.patch @@ -0,0 +1,6417 @@ +diff --git a/Makefile b/Makefile +index 308ddaae..e23a8332 100644 +--- a/Makefile ++++ b/Makefile +@@ -116,17 +116,14 @@ obj/crt/Scrt1.o obj/crt/rcrt1.o: CFLAGS_ALL += -fPIC + OPTIMIZE_SRCS = $(wildcard $(OPTIMIZE_GLOBS:%=$(srcdir)/src/%)) + $(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.o) $(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.lo): CFLAGS += -O3 + +-MEMOPS_SRCS = src/string/memcpy.c src/string/memmove.c src/string/memcmp.c src/string/memset.c +-$(MEMOPS_SRCS:%.c=obj/%.o) $(MEMOPS_SRCS:%.c=obj/%.lo): CFLAGS_ALL += $(CFLAGS_MEMOPS) +- +-NOSSP_SRCS = $(wildcard crt/*.c) \ +- src/env/__libc_start_main.c src/env/__init_tls.c \ +- src/env/__stack_chk_fail.c \ +- src/thread/__set_thread_area.c src/thread/$(ARCH)/__set_thread_area.c \ +- src/string/memset.c src/string/$(ARCH)/memset.c \ +- src/string/memcpy.c src/string/$(ARCH)/memcpy.c \ +- ldso/dlstart.c ldso/dynlink.c +-$(NOSSP_SRCS:%.c=obj/%.o) $(NOSSP_SRCS:%.c=obj/%.lo): CFLAGS_ALL += $(CFLAGS_NOSSP) ++MEMOPS_OBJS = $(filter %/memcpy.o %/memmove.o %/memcmp.o %/memset.o, $(LIBC_OBJS)) ++$(MEMOPS_OBJS) $(MEMOPS_OBJS:%.o=%.lo): CFLAGS_ALL += $(CFLAGS_MEMOPS) ++ ++NOSSP_OBJS = $(CRT_OBJS) $(LDSO_OBJS) $(filter \ ++ %/__libc_start_main.o %/__init_tls.o %/__stack_chk_fail.o \ ++ %/__set_thread_area.o %/memset.o %/memcpy.o \ ++ , $(LIBC_OBJS)) ++$(NOSSP_OBJS) $(NOSSP_OBJS:%.o=%.lo): CFLAGS_ALL += $(CFLAGS_NOSSP) + + $(CRT_OBJS): CFLAGS_ALL += -DCRT + +diff --git a/arch/aarch64/bits/hwcap.h b/arch/aarch64/bits/hwcap.h +index 11396d31..8541e329 100644 +--- a/arch/aarch64/bits/hwcap.h ++++ b/arch/aarch64/bits/hwcap.h +@@ -14,3 +14,15 @@ + #define HWCAP_JSCVT (1 << 13) + #define HWCAP_FCMA (1 << 14) + #define HWCAP_LRCPC (1 << 15) ++#define HWCAP_DCPOP (1 << 16) ++#define HWCAP_SHA3 (1 << 17) ++#define HWCAP_SM3 (1 << 18) ++#define HWCAP_SM4 (1 << 19) ++#define HWCAP_ASIMDDP (1 << 20) ++#define HWCAP_SHA512 (1 << 21) ++#define HWCAP_SVE (1 << 22) ++#define HWCAP_ASIMDFHM (1 << 23) ++#define HWCAP_DIT (1 << 24) ++#define HWCAP_USCAT (1 << 25) ++#define HWCAP_ILRCPC (1 << 26) ++#define HWCAP_FLAGM (1 << 27) +diff --git a/arch/aarch64/bits/signal.h b/arch/aarch64/bits/signal.h +index 1c67313d..b71261f5 100644 +--- a/arch/aarch64/bits/signal.h ++++ b/arch/aarch64/bits/signal.h +@@ -25,6 +25,7 @@ typedef struct sigcontext { + #define FPSIMD_MAGIC 0x46508001 + #define ESR_MAGIC 0x45535201 + #define EXTRA_MAGIC 0x45585401 ++#define SVE_MAGIC 0x53564501 + struct _aarch64_ctx { + unsigned int magic; + unsigned int size; +@@ -45,6 +46,44 @@ struct extra_context { + unsigned int size; + unsigned int __reserved[3]; + }; ++struct sve_context { ++ struct _aarch64_ctx head; ++ unsigned short vl; ++ unsigned short __reserved[3]; ++}; ++#define SVE_VQ_BYTES 16 ++#define SVE_VQ_MIN 1 ++#define SVE_VQ_MAX 512 ++#define SVE_VL_MIN (SVE_VQ_MIN * SVE_VQ_BYTES) ++#define SVE_VL_MAX (SVE_VQ_MAX * SVE_VQ_BYTES) ++#define SVE_NUM_ZREGS 32 ++#define SVE_NUM_PREGS 16 ++#define sve_vl_valid(vl) \ ++ ((vl) % SVE_VQ_BYTES == 0 && (vl) >= SVE_VL_MIN && (vl) <= SVE_VL_MAX) ++#define sve_vq_from_vl(vl) ((vl) / SVE_VQ_BYTES) ++#define sve_vl_from_vq(vq) ((vq) * SVE_VQ_BYTES) ++#define SVE_SIG_ZREG_SIZE(vq) ((unsigned)(vq) * SVE_VQ_BYTES) ++#define SVE_SIG_PREG_SIZE(vq) ((unsigned)(vq) * (SVE_VQ_BYTES / 8)) ++#define SVE_SIG_FFR_SIZE(vq) SVE_SIG_PREG_SIZE(vq) ++#define SVE_SIG_REGS_OFFSET \ ++ ((sizeof(struct sve_context) + (SVE_VQ_BYTES - 1)) \ ++ / SVE_VQ_BYTES * SVE_VQ_BYTES) ++#define SVE_SIG_ZREGS_OFFSET SVE_SIG_REGS_OFFSET ++#define SVE_SIG_ZREG_OFFSET(vq, n) \ ++ (SVE_SIG_ZREGS_OFFSET + SVE_SIG_ZREG_SIZE(vq) * (n)) ++#define SVE_SIG_ZREGS_SIZE(vq) \ ++ (SVE_SIG_ZREG_OFFSET(vq, SVE_NUM_ZREGS) - SVE_SIG_ZREGS_OFFSET) ++#define SVE_SIG_PREGS_OFFSET(vq) \ ++ (SVE_SIG_ZREGS_OFFSET + SVE_SIG_ZREGS_SIZE(vq)) ++#define SVE_SIG_PREG_OFFSET(vq, n) \ ++ (SVE_SIG_PREGS_OFFSET(vq) + SVE_SIG_PREG_SIZE(vq) * (n)) ++#define SVE_SIG_PREGS_SIZE(vq) \ ++ (SVE_SIG_PREG_OFFSET(vq, SVE_NUM_PREGS) - SVE_SIG_PREGS_OFFSET(vq)) ++#define SVE_SIG_FFR_OFFSET(vq) \ ++ (SVE_SIG_PREGS_OFFSET(vq) + SVE_SIG_PREGS_SIZE(vq)) ++#define SVE_SIG_REGS_SIZE(vq) \ ++ (SVE_SIG_FFR_OFFSET(vq) + SVE_SIG_FFR_SIZE(vq) - SVE_SIG_REGS_OFFSET) ++#define SVE_SIG_CONTEXT_SIZE(vq) (SVE_SIG_REGS_OFFSET + SVE_SIG_REGS_SIZE(vq)) + #else + typedef struct { + long double __regs[18+256]; +diff --git a/arch/aarch64/pthread_arch.h b/arch/aarch64/pthread_arch.h +index b2e2d8f1..e8499d8e 100644 +--- a/arch/aarch64/pthread_arch.h ++++ b/arch/aarch64/pthread_arch.h +@@ -2,10 +2,11 @@ static inline struct pthread *__pthread_self() + { + char *self; + __asm__ __volatile__ ("mrs %0,tpidr_el0" : "=r"(self)); +- return (void*)(self + 16 - sizeof(struct pthread)); ++ return (void*)(self - sizeof(struct pthread)); + } + + #define TLS_ABOVE_TP +-#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) - 16) ++#define GAP_ABOVE_TP 16 ++#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread)) + + #define MC_PC pc +diff --git a/arch/aarch64/reloc.h b/arch/aarch64/reloc.h +index 51b66e23..40cf0b28 100644 +--- a/arch/aarch64/reloc.h ++++ b/arch/aarch64/reloc.h +@@ -10,7 +10,7 @@ + + #define NO_LEGACY_INITFINI + +-#define TPOFF_K 16 ++#define TPOFF_K 0 + + #define REL_SYMBOLIC R_AARCH64_ABS64 + #define REL_GOT R_AARCH64_GLOB_DAT +diff --git a/arch/arm/atomic_arch.h b/arch/arm/atomic_arch.h +index c5c56f81..62458b45 100644 +--- a/arch/arm/atomic_arch.h ++++ b/arch/arm/atomic_arch.h +@@ -7,8 +7,8 @@ + extern uintptr_t __attribute__((__visibility__("hidden"))) + __a_cas_ptr, __a_barrier_ptr; + +-#if ((__ARM_ARCH_6__ || __ARM_ARCH_6K__ || __ARM_ARCH_6ZK__) && !__thumb__) \ +- || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7 ++#if ((__ARM_ARCH_6__ || __ARM_ARCH_6K__ || __ARM_ARCH_6KZ__ || __ARM_ARCH_6ZK__) && !__thumb__) \ ++ || __ARM_ARCH_6T2__ || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7 + + #define a_ll a_ll + static inline int a_ll(volatile int *p) +@@ -91,4 +91,16 @@ static inline int a_clz_32(uint32_t x) + return x; + } + ++#if __ARM_ARCH_6T2__ || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7 ++ ++#define a_ctz_32 a_ctz_32 ++static inline int a_ctz_32(uint32_t x) ++{ ++ uint32_t xr; ++ __asm__ ("rbit %0, %1" : "=r"(xr) : "r"(x)); ++ return a_clz_32(xr); ++} ++ ++#endif ++ + #endif +diff --git a/arch/arm/bits/syscall.h.in b/arch/arm/bits/syscall.h.in +index c594152e..1920516a 100644 +--- a/arch/arm/bits/syscall.h.in ++++ b/arch/arm/bits/syscall.h.in +@@ -359,4 +359,5 @@ + #define __ARM_NR_usr26 0x0f0003 + #define __ARM_NR_usr32 0x0f0004 + #define __ARM_NR_set_tls 0x0f0005 ++#define __ARM_NR_get_tls 0x0f0006 + +diff --git a/arch/arm/pthread_arch.h b/arch/arm/pthread_arch.h +index 197752ef..8f2ae8f8 100644 +--- a/arch/arm/pthread_arch.h ++++ b/arch/arm/pthread_arch.h +@@ -1,11 +1,11 @@ +-#if ((__ARM_ARCH_6K__ || __ARM_ARCH_6ZK__) && !__thumb__) \ ++#if ((__ARM_ARCH_6K__ || __ARM_ARCH_6KZ__ || __ARM_ARCH_6ZK__) && !__thumb__) \ + || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7 + + static inline pthread_t __pthread_self() + { + char *p; + __asm__ __volatile__ ( "mrc p15,0,%0,c13,c0,3" : "=r"(p) ); +- return (void *)(p+8-sizeof(struct pthread)); ++ return (void *)(p-sizeof(struct pthread)); + } + + #else +@@ -21,12 +21,13 @@ static inline pthread_t __pthread_self() + extern uintptr_t __attribute__((__visibility__("hidden"))) __a_gettp_ptr; + register uintptr_t p __asm__("r0"); + __asm__ __volatile__ ( BLX " %1" : "=r"(p) : "r"(__a_gettp_ptr) : "cc", "lr" ); +- return (void *)(p+8-sizeof(struct pthread)); ++ return (void *)(p-sizeof(struct pthread)); + } + + #endif + + #define TLS_ABOVE_TP +-#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) - 8) ++#define GAP_ABOVE_TP 8 ++#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread)) + + #define MC_PC arm_pc +diff --git a/arch/arm/reloc.h b/arch/arm/reloc.h +index b175711d..4b00bf64 100644 +--- a/arch/arm/reloc.h ++++ b/arch/arm/reloc.h +@@ -16,7 +16,7 @@ + + #define NO_LEGACY_INITFINI + +-#define TPOFF_K 8 ++#define TPOFF_K 0 + + #define REL_SYMBOLIC R_ARM_ABS32 + #define REL_GOT R_ARM_GLOB_DAT +diff --git a/arch/arm/syscall_arch.h b/arch/arm/syscall_arch.h +index 6023303b..53fb155c 100644 +--- a/arch/arm/syscall_arch.h ++++ b/arch/arm/syscall_arch.h +@@ -3,74 +3,99 @@ + ((union { long long ll; long l[2]; }){ .ll = x }).l[1] + #define __SYSCALL_LL_O(x) 0, __SYSCALL_LL_E((x)) + ++#ifdef __thumb__ ++ ++/* Avoid use of r7 in asm constraints when producing thumb code, ++ * since it's reserved as frame pointer and might not be supported. */ ++#define __ASM____R7__ ++#define __asm_syscall(...) do { \ ++ __asm__ __volatile__ ( "mov %1,r7 ; mov r7,%2 ; svc 0 ; mov r7,%1" \ ++ : "=r"(r0), "=&r"((int){0}) : __VA_ARGS__ : "memory"); \ ++ return r0; \ ++ } while (0) ++ ++#else ++ ++#define __ASM____R7__ __asm__("r7") + #define __asm_syscall(...) do { \ + __asm__ __volatile__ ( "svc 0" \ + : "=r"(r0) : __VA_ARGS__ : "memory"); \ + return r0; \ + } while (0) ++#endif ++ ++/* For thumb2, we can allow 8-bit immediate syscall numbers, saving a ++ * register in the above dance around r7. Does not work for thumb1 where ++ * only movs, not mov, supports immediates, and we can't use movs because ++ * it doesn't support high regs. */ ++#ifdef __thumb2__ ++#define R7_OPERAND "rI"(r7) ++#else ++#define R7_OPERAND "r"(r7) ++#endif + + static inline long __syscall0(long n) + { +- register long r7 __asm__("r7") = n; ++ register long r7 __ASM____R7__ = n; + register long r0 __asm__("r0"); +- __asm_syscall("r"(r7)); ++ __asm_syscall(R7_OPERAND); + } + + static inline long __syscall1(long n, long a) + { +- register long r7 __asm__("r7") = n; ++ register long r7 __ASM____R7__ = n; + register long r0 __asm__("r0") = a; +- __asm_syscall("r"(r7), "0"(r0)); ++ __asm_syscall(R7_OPERAND, "0"(r0)); + } + + static inline long __syscall2(long n, long a, long b) + { +- register long r7 __asm__("r7") = n; ++ register long r7 __ASM____R7__ = n; + register long r0 __asm__("r0") = a; + register long r1 __asm__("r1") = b; +- __asm_syscall("r"(r7), "0"(r0), "r"(r1)); ++ __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1)); + } + + static inline long __syscall3(long n, long a, long b, long c) + { +- register long r7 __asm__("r7") = n; ++ register long r7 __ASM____R7__ = n; + register long r0 __asm__("r0") = a; + register long r1 __asm__("r1") = b; + register long r2 __asm__("r2") = c; +- __asm_syscall("r"(r7), "0"(r0), "r"(r1), "r"(r2)); ++ __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1), "r"(r2)); + } + + static inline long __syscall4(long n, long a, long b, long c, long d) + { +- register long r7 __asm__("r7") = n; ++ register long r7 __ASM____R7__ = n; + register long r0 __asm__("r0") = a; + register long r1 __asm__("r1") = b; + register long r2 __asm__("r2") = c; + register long r3 __asm__("r3") = d; +- __asm_syscall("r"(r7), "0"(r0), "r"(r1), "r"(r2), "r"(r3)); ++ __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1), "r"(r2), "r"(r3)); + } + + static inline long __syscall5(long n, long a, long b, long c, long d, long e) + { +- register long r7 __asm__("r7") = n; ++ register long r7 __ASM____R7__ = n; + register long r0 __asm__("r0") = a; + register long r1 __asm__("r1") = b; + register long r2 __asm__("r2") = c; + register long r3 __asm__("r3") = d; + register long r4 __asm__("r4") = e; +- __asm_syscall("r"(r7), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4)); ++ __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4)); + } + + static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) + { +- register long r7 __asm__("r7") = n; ++ register long r7 __ASM____R7__ = n; + register long r0 __asm__("r0") = a; + register long r1 __asm__("r1") = b; + register long r2 __asm__("r2") = c; + register long r3 __asm__("r3") = d; + register long r4 __asm__("r4") = e; + register long r5 __asm__("r5") = f; +- __asm_syscall("r"(r7), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5)); ++ __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5)); + } + + #define VDSO_USEFUL +@@ -78,3 +103,5 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo + #define VDSO_CGT_VER "LINUX_2.6" + + #define SYSCALL_FADVISE_6_ARG ++ ++#define SYSCALL_IPC_BROKEN_MODE +diff --git a/arch/generic/bits/kd.h b/arch/generic/bits/kd.h +new file mode 100644 +index 00000000..33b873f4 +--- /dev/null ++++ b/arch/generic/bits/kd.h +@@ -0,0 +1 @@ ++#include <linux/kd.h> +diff --git a/arch/generic/bits/ptrace.h b/arch/generic/bits/ptrace.h +new file mode 100644 +index 00000000..e69de29b +diff --git a/arch/generic/bits/soundcard.h b/arch/generic/bits/soundcard.h +new file mode 100644 +index 00000000..fade986f +--- /dev/null ++++ b/arch/generic/bits/soundcard.h +@@ -0,0 +1 @@ ++#include <linux/soundcard.h> +diff --git a/arch/generic/bits/termios.h b/arch/generic/bits/termios.h +index 434c02c8..124f71d2 100644 +--- a/arch/generic/bits/termios.h ++++ b/arch/generic/bits/termios.h +@@ -51,6 +51,7 @@ struct termios { + #define ONLRET 0000040 + #define OFILL 0000100 + #define OFDEL 0000200 ++#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE) + #define NLDLY 0000400 + #define NL0 0000000 + #define NL1 0000400 +@@ -70,6 +71,7 @@ struct termios { + #define FFDLY 0100000 + #define FF0 0000000 + #define FF1 0100000 ++#endif + + #define VTDLY 0040000 + #define VT0 0000000 +diff --git a/arch/generic/bits/vt.h b/arch/generic/bits/vt.h +new file mode 100644 +index 00000000..834abfbc +--- /dev/null ++++ b/arch/generic/bits/vt.h +@@ -0,0 +1 @@ ++#include <linux/vt.h> +diff --git a/arch/i386/atomic_arch.h b/arch/i386/atomic_arch.h +index 7d2a48a5..047fb68d 100644 +--- a/arch/i386/atomic_arch.h ++++ b/arch/i386/atomic_arch.h +@@ -92,10 +92,10 @@ static inline int a_ctz_64(uint64_t x) + return r; + } + +-#define a_ctz_l a_ctz_l +-static inline int a_ctz_l(unsigned long x) ++#define a_ctz_32 a_ctz_32 ++static inline int a_ctz_32(uint32_t x) + { +- long r; ++ int r; + __asm__( "bsf %1,%0" : "=r"(r) : "r"(x) ); + return r; + } +diff --git a/arch/i386/bits/limits.h b/arch/i386/bits/limits.h +index 65a3dd64..c340ceb2 100644 +--- a/arch/i386/bits/limits.h ++++ b/arch/i386/bits/limits.h +@@ -1,6 +1,6 @@ + #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +-#define PAGE_SIZE 4096 ++#define PAGESIZE 4096 + #define LONG_BIT 32 + #endif + +diff --git a/arch/i386/bits/ptrace.h b/arch/i386/bits/ptrace.h +new file mode 100644 +index 00000000..7d0efbf3 +--- /dev/null ++++ b/arch/i386/bits/ptrace.h +@@ -0,0 +1,11 @@ ++#define PTRACE_GET_THREAD_AREA 25 ++#define PTRACE_SET_THREAD_AREA 26 ++#define PTRACE_SYSEMU 31 ++#define PTRACE_SYSEMU_SINGLESTEP 32 ++#define PTRACE_SINGLEBLOCK 33 ++ ++#define PT_GET_THREAD_AREA PTRACE_GET_THREAD_AREA ++#define PT_SET_THREAD_AREA PTRACE_SET_THREAD_AREA ++#define PT_SYSEMU PTRACE_SYSEMU ++#define PT_SYSEMU_SINGLESTEP PTRACE_SYSEMU_SINGLESTEP ++#define PT_STEPBLOCK PTRACE_SINGLEBLOCK +diff --git a/arch/i386/bits/user.h b/arch/i386/bits/user.h +index 0e343930..33fea986 100644 +--- a/arch/i386/bits/user.h ++++ b/arch/i386/bits/user.h +@@ -37,8 +37,8 @@ struct user { + int u_debugreg[8]; + }; + +-#define PAGE_MASK (~(PAGE_SIZE-1)) +-#define NBPG PAGE_SIZE ++#define PAGE_MASK (~(PAGESIZE-1)) ++#define NBPG PAGESIZE + #define UPAGES 1 + #define HOST_TEXT_START_ADDR (u.start_code) + #define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) +diff --git a/arch/m68k/atomic_arch.h b/arch/m68k/atomic_arch.h +new file mode 100644 +index 00000000..b369649a +--- /dev/null ++++ b/arch/m68k/atomic_arch.h +@@ -0,0 +1,8 @@ ++#define a_cas a_cas ++static inline int a_cas(volatile int *p, int t, int s) ++{ ++ __asm__ __volatile__ ( ++ "cas.l %0, %2, (%1)" ++ : "+d"(t) : "a"(p), "d"(s) : "memory", "cc"); ++ return t; ++} +diff --git a/arch/m68k/bits/alltypes.h.in b/arch/m68k/bits/alltypes.h.in +new file mode 100644 +index 00000000..a4a8141f +--- /dev/null ++++ b/arch/m68k/bits/alltypes.h.in +@@ -0,0 +1,31 @@ ++#define _Addr int ++#define _Int64 long long ++#define _Reg int ++ ++TYPEDEF __builtin_va_list va_list; ++TYPEDEF __builtin_va_list __isoc_va_list; ++ ++#ifndef __cplusplus ++TYPEDEF long wchar_t; ++#endif ++ ++#if __mcffpu__ ++TYPEDEF float float_t; ++TYPEDEF double double_t; ++#else ++TYPEDEF long double float_t; ++TYPEDEF long double double_t; ++#endif ++ ++TYPEDEF struct { long long __ll; long double __ld; } max_align_t; ++ ++TYPEDEF long time_t; ++TYPEDEF long suseconds_t; ++ ++TYPEDEF struct { union { int __i[9]; volatile int __vi[9]; unsigned __s[9]; } __u; } pthread_attr_t; ++TYPEDEF struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t; ++TYPEDEF struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } mtx_t; ++TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } pthread_cond_t; ++TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } cnd_t; ++TYPEDEF struct { union { int __i[8]; volatile int __vi[8]; void *__p[8]; } __u; } pthread_rwlock_t; ++TYPEDEF struct { union { int __i[5]; volatile int __vi[5]; void *__p[5]; } __u; } pthread_barrier_t; +diff --git a/arch/m68k/bits/endian.h b/arch/m68k/bits/endian.h +new file mode 100644 +index 00000000..ef074b77 +--- /dev/null ++++ b/arch/m68k/bits/endian.h +@@ -0,0 +1 @@ ++#define __BYTE_ORDER __BIG_ENDIAN +diff --git a/arch/m68k/bits/fcntl.h b/arch/m68k/bits/fcntl.h +new file mode 100644 +index 00000000..f1c8400f +--- /dev/null ++++ b/arch/m68k/bits/fcntl.h +@@ -0,0 +1,40 @@ ++#define O_CREAT 0100 ++#define O_EXCL 0200 ++#define O_NOCTTY 0400 ++#define O_TRUNC 01000 ++#define O_APPEND 02000 ++#define O_NONBLOCK 04000 ++#define O_DSYNC 010000 ++#define O_SYNC 04010000 ++#define O_RSYNC 04010000 ++#define O_DIRECTORY 040000 ++#define O_NOFOLLOW 0100000 ++#define O_CLOEXEC 02000000 ++ ++#define O_ASYNC 020000 ++#define O_DIRECT 0200000 ++#define O_LARGEFILE 0400000 ++#define O_NOATIME 01000000 ++#define O_PATH 010000000 ++#define O_TMPFILE 020200000 ++#define O_NDELAY O_NONBLOCK ++ ++#define F_DUPFD 0 ++#define F_GETFD 1 ++#define F_SETFD 2 ++#define F_GETFL 3 ++#define F_SETFL 4 ++ ++#define F_SETOWN 8 ++#define F_GETOWN 9 ++#define F_SETSIG 10 ++#define F_GETSIG 11 ++ ++#define F_GETLK 12 ++#define F_SETLK 13 ++#define F_SETLKW 14 ++ ++#define F_SETOWN_EX 15 ++#define F_GETOWN_EX 16 ++ ++#define F_GETOWNER_UIDS 17 +diff --git a/arch/m68k/bits/fenv.h b/arch/m68k/bits/fenv.h +new file mode 100644 +index 00000000..c90a4a58 +--- /dev/null ++++ b/arch/m68k/bits/fenv.h +@@ -0,0 +1,29 @@ ++#if __HAVE_68881__ || __mcffpu__ ++ ++#define FE_INEXACT 8 ++#define FE_DIVBYZERO 16 ++#define FE_UNDERFLOW 32 ++#define FE_OVERFLOW 64 ++#define FE_INVALID 128 ++ ++#define FE_ALL_EXCEPT 0xf8 ++ ++#define FE_TONEAREST 0 ++#define FE_TOWARDZERO 16 ++#define FE_DOWNWARD 32 ++#define FE_UPWARD 48 ++ ++#else ++ ++#define FE_ALL_EXCEPT 0 ++#define FE_TONEAREST 0 ++ ++#endif ++ ++typedef unsigned fexcept_t; ++ ++typedef struct { ++ unsigned __control_register, __status_register, __instruction_address; ++} fenv_t; ++ ++#define FE_DFL_ENV ((const fenv_t *) -1) +diff --git a/arch/m68k/bits/float.h b/arch/m68k/bits/float.h +new file mode 100644 +index 00000000..0e6899d5 +--- /dev/null ++++ b/arch/m68k/bits/float.h +@@ -0,0 +1,39 @@ ++#if !__mcffpu__ ++ ++#define FLT_EVAL_METHOD 2 ++ ++#define LDBL_TRUE_MIN 3.6451995318824746025e-4951L ++#define LDBL_MIN 1.68105157155604675313e-4932L ++#define LDBL_MAX 1.1897314953572317650e+4932L ++#define LDBL_EPSILON 1.0842021724855044340e-19L ++ ++#define LDBL_MANT_DIG 64 ++#define LDBL_MIN_EXP (-16382) ++#define LDBL_MAX_EXP 16384 ++ ++#define LDBL_DIG 18 ++#define LDBL_MIN_10_EXP (-4931) ++#define LDBL_MAX_10_EXP 4932 ++ ++#define DECIMAL_DIG 21 ++ ++#else ++ ++#define FLT_EVAL_METHOD 0 ++ ++#define LDBL_TRUE_MIN 4.94065645841246544177e-324L ++#define LDBL_MIN 2.22507385850720138309e-308L ++#define LDBL_MAX 1.79769313486231570815e+308L ++#define LDBL_EPSILON 2.22044604925031308085e-16L ++ ++#define LDBL_MANT_DIG 53 ++#define LDBL_MIN_EXP (-1021) ++#define LDBL_MAX_EXP 1024 ++ ++#define LDBL_DIG 15 ++#define LDBL_MIN_10_EXP (-307) ++#define LDBL_MAX_10_EXP 308 ++ ++#define DECIMAL_DIG 17 ++ ++#endif +diff --git a/arch/m68k/bits/limits.h b/arch/m68k/bits/limits.h +new file mode 100644 +index 00000000..fbc6d238 +--- /dev/null ++++ b/arch/m68k/bits/limits.h +@@ -0,0 +1,7 @@ ++#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ ++ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) ++#define LONG_BIT 32 ++#endif ++ ++#define LONG_MAX 0x7fffffffL ++#define LLONG_MAX 0x7fffffffffffffffLL +diff --git a/arch/m68k/bits/posix.h b/arch/m68k/bits/posix.h +new file mode 100644 +index 00000000..30a38714 +--- /dev/null ++++ b/arch/m68k/bits/posix.h +@@ -0,0 +1,2 @@ ++#define _POSIX_V6_ILP32_OFFBIG 1 ++#define _POSIX_V7_ILP32_OFFBIG 1 +diff --git a/arch/m68k/bits/ptrace.h b/arch/m68k/bits/ptrace.h +new file mode 100644 +index 00000000..da93e7a7 +--- /dev/null ++++ b/arch/m68k/bits/ptrace.h +@@ -0,0 +1,2 @@ ++#define PTRACE_GET_THREAD_AREA 25 ++#define PTRACE_SINGLEBLOCK 33 +diff --git a/arch/m68k/bits/reg.h b/arch/m68k/bits/reg.h +new file mode 100644 +index 00000000..99201f70 +--- /dev/null ++++ b/arch/m68k/bits/reg.h +@@ -0,0 +1,45 @@ ++#undef __WORDSIZE ++#define __WORDSIZE 32 ++#define PT_D1 0 ++#define PT_D2 1 ++#define PT_D3 2 ++#define PT_D4 3 ++#define PT_D5 4 ++#define PT_D6 5 ++#define PT_D7 6 ++#define PT_A0 7 ++#define PT_A1 8 ++#define PT_A2 9 ++#define PT_A3 10 ++#define PT_A4 11 ++#define PT_A5 12 ++#define PT_A6 13 ++#define PT_D0 14 ++#define PT_USP 15 ++#define PT_ORIG_D0 16 ++#define PT_SR 17 ++#define PT_PC 18 ++ ++#if __mcffpu__ ++#define PT_FP0 21 ++#define PT_FP1 23 ++#define PT_FP2 25 ++#define PT_FP3 27 ++#define PT_FP4 29 ++#define PT_FP5 31 ++#define PT_FP6 33 ++#define PT_FP7 35 ++#else ++#define PT_FP0 21 ++#define PT_FP1 24 ++#define PT_FP2 27 ++#define PT_FP3 30 ++#define PT_FP4 33 ++#define PT_FP5 36 ++#define PT_FP6 39 ++#define PT_FP7 42 ++#endif ++ ++#define PT_FPCR 45 ++#define PT_FPSR 46 ++#define PT_FPIAR 47 +diff --git a/arch/m68k/bits/setjmp.h b/arch/m68k/bits/setjmp.h +new file mode 100644 +index 00000000..5e091fb4 +--- /dev/null ++++ b/arch/m68k/bits/setjmp.h +@@ -0,0 +1 @@ ++typedef unsigned long __jmp_buf[39]; +diff --git a/arch/m68k/bits/signal.h b/arch/m68k/bits/signal.h +new file mode 100644 +index 00000000..2c369ca3 +--- /dev/null ++++ b/arch/m68k/bits/signal.h +@@ -0,0 +1,140 @@ ++#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ ++ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) ++ ++#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) ++#define MINSIGSTKSZ 2048 ++#define SIGSTKSZ 8192 ++#endif ++ ++#ifdef _GNU_SOURCE ++enum { R_D0 = 0 }; ++#define R_D0 R_D0 ++enum { R_D1 = 1 }; ++#define R_D1 R_D1 ++enum { R_D2 = 2 }; ++#define R_D2 R_D2 ++enum { R_D3 = 3 }; ++#define R_D3 R_D3 ++enum { R_D4 = 4 }; ++#define R_D4 R_D4 ++enum { R_D5 = 5 }; ++#define R_D5 R_D5 ++enum { R_D6 = 6 }; ++#define R_D6 R_D6 ++enum { R_D7 = 7 }; ++#define R_D7 R_D7 ++enum { R_A0 = 8 }; ++#define R_A0 R_A0 ++enum { R_A1 = 9 }; ++#define R_A1 R_A1 ++enum { R_A2 = 10 }; ++#define R_A2 R_A2 ++enum { R_A3 = 11 }; ++#define R_A3 R_A3 ++enum { R_A4 = 12 }; ++#define R_A4 R_A4 ++enum { R_A5 = 13 }; ++#define R_A5 R_A5 ++enum { R_A6 = 14 }; ++#define R_A6 R_A6 ++enum { R_A7 = 15 }; ++#define R_A7 R_A7 ++enum { R_SP = 15 }; ++#define R_SP R_SP ++enum { R_PC = 16 }; ++#define R_PC R_PC ++enum { R_PS = 17 }; ++#define R_PS R_PS ++#endif ++ ++#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) ++ ++struct sigcontext { ++ unsigned long sc_mask, sc_usp, sc_d0, sc_d1, sc_a0, sc_a1; ++ unsigned short sc_sr; ++ unsigned long sc_pc; ++ unsigned short sc_formatvec; ++ unsigned long sc_fpregs[6], sc_fpcntl[3]; ++ unsigned char sc_fpstate[216]; ++}; ++ ++typedef int greg_t, gregset_t[18]; ++typedef struct { ++ int f_pcr, f_psr, f_fpiaddr, f_fpregs[8][3]; ++} fpregset_t; ++ ++typedef struct { ++ int version; ++ gregset_t gregs; ++ fpregset_t fpregs; ++} mcontext_t; ++#else ++typedef struct { ++ int __version; ++ int __gregs[18]; ++ int __fpregs[27]; ++} mcontext_t; ++#endif ++ ++struct sigaltstack { ++ void *ss_sp; ++ int ss_flags; ++ size_t ss_size; ++}; ++ ++typedef struct __ucontext { ++ unsigned long uc_flags; ++ struct __ucontext *uc_link; ++ stack_t uc_stack; ++ mcontext_t uc_mcontext; ++ long __reserved[80]; ++ sigset_t uc_sigmask; ++} ucontext_t; ++ ++#define SA_NOCLDSTOP 1 ++#define SA_NOCLDWAIT 2 ++#define SA_SIGINFO 4 ++#define SA_ONSTACK 0x08000000 ++#define SA_RESTART 0x10000000 ++#define SA_NODEFER 0x40000000 ++#define SA_RESETHAND 0x80000000 ++#define SA_RESTORER 0x04000000 ++ ++#endif ++ ++#define SIGHUP 1 ++#define SIGINT 2 ++#define SIGQUIT 3 ++#define SIGILL 4 ++#define SIGTRAP 5 ++#define SIGABRT 6 ++#define SIGIOT SIGABRT ++#define SIGBUS 7 ++#define SIGFPE 8 ++#define SIGKILL 9 ++#define SIGUSR1 10 ++#define SIGSEGV 11 ++#define SIGUSR2 12 ++#define SIGPIPE 13 ++#define SIGALRM 14 ++#define SIGTERM 15 ++#define SIGSTKFLT 16 ++#define SIGCHLD 17 ++#define SIGCONT 18 ++#define SIGSTOP 19 ++#define SIGTSTP 20 ++#define SIGTTIN 21 ++#define SIGTTOU 22 ++#define SIGURG 23 ++#define SIGXCPU 24 ++#define SIGXFSZ 25 ++#define SIGVTALRM 26 ++#define SIGPROF 27 ++#define SIGWINCH 28 ++#define SIGIO 29 ++#define SIGPOLL 29 ++#define SIGPWR 30 ++#define SIGSYS 31 ++#define SIGUNUSED SIGSYS ++ ++#define _NSIG 65 +diff --git a/arch/m68k/bits/stat.h b/arch/m68k/bits/stat.h +new file mode 100644 +index 00000000..0f7b66a1 +--- /dev/null ++++ b/arch/m68k/bits/stat.h +@@ -0,0 +1,21 @@ ++/* copied from kernel definition, but with padding replaced ++ * by the corresponding correctly-sized userspace types. */ ++ ++struct stat { ++ dev_t st_dev; ++ short __st_dev_padding; ++ long __st_ino_truncated; ++ mode_t st_mode; ++ nlink_t st_nlink; ++ uid_t st_uid; ++ gid_t st_gid; ++ dev_t st_rdev; ++ short __st_rdev_padding; ++ off_t st_size; ++ blksize_t st_blksize; ++ blkcnt_t st_blocks; ++ struct timespec st_atim; ++ struct timespec st_mtim; ++ struct timespec st_ctim; ++ ino_t st_ino; ++}; +diff --git a/arch/m68k/bits/stdint.h b/arch/m68k/bits/stdint.h +new file mode 100644 +index 00000000..d1b27121 +--- /dev/null ++++ b/arch/m68k/bits/stdint.h +@@ -0,0 +1,20 @@ ++typedef int32_t int_fast16_t; ++typedef int32_t int_fast32_t; ++typedef uint32_t uint_fast16_t; ++typedef uint32_t uint_fast32_t; ++ ++#define INT_FAST16_MIN INT32_MIN ++#define INT_FAST32_MIN INT32_MIN ++ ++#define INT_FAST16_MAX INT32_MAX ++#define INT_FAST32_MAX INT32_MAX ++ ++#define UINT_FAST16_MAX UINT32_MAX ++#define UINT_FAST32_MAX UINT32_MAX ++ ++#define INTPTR_MIN INT32_MIN ++#define INTPTR_MAX INT32_MAX ++#define UINTPTR_MAX UINT32_MAX ++#define PTRDIFF_MIN INT32_MIN ++#define PTRDIFF_MAX INT32_MAX ++#define SIZE_MAX UINT32_MAX +diff --git a/arch/m68k/bits/syscall.h.in b/arch/m68k/bits/syscall.h.in +new file mode 100644 +index 00000000..89cf114c +--- /dev/null ++++ b/arch/m68k/bits/syscall.h.in +@@ -0,0 +1,361 @@ ++#define __NR_restart_syscall 0 ++#define __NR_exit 1 ++#define __NR_fork 2 ++#define __NR_read 3 ++#define __NR_write 4 ++#define __NR_open 5 ++#define __NR_close 6 ++#define __NR_waitpid 7 ++#define __NR_creat 8 ++#define __NR_link 9 ++#define __NR_unlink 10 ++#define __NR_execve 11 ++#define __NR_chdir 12 ++#define __NR_time 13 ++#define __NR_mknod 14 ++#define __NR_chmod 15 ++#define __NR_chown 16 ++#define __NR_oldstat 18 ++#define __NR_lseek 19 ++#define __NR_getpid 20 ++#define __NR_mount 21 ++#define __NR_umount 22 ++#define __NR_setuid 23 ++#define __NR_getuid 24 ++#define __NR_stime 25 ++#define __NR_ptrace 26 ++#define __NR_alarm 27 ++#define __NR_oldfstat 28 ++#define __NR_pause 29 ++#define __NR_utime 30 ++#define __NR_access 33 ++#define __NR_nice 34 ++#define __NR_sync 36 ++#define __NR_kill 37 ++#define __NR_rename 38 ++#define __NR_mkdir 39 ++#define __NR_rmdir 40 ++#define __NR_dup 41 ++#define __NR_pipe 42 ++#define __NR_times 43 ++#define __NR_brk 45 ++#define __NR_setgid 46 ++#define __NR_getgid 47 ++#define __NR_signal 48 ++#define __NR_geteuid 49 ++#define __NR_getegid 50 ++#define __NR_acct 51 ++#define __NR_umount2 52 ++#define __NR_ioctl 54 ++#define __NR_fcntl 55 ++#define __NR_setpgid 57 ++#define __NR_umask 60 ++#define __NR_chroot 61 ++#define __NR_ustat 62 ++#define __NR_dup2 63 ++#define __NR_getppid 64 ++#define __NR_getpgrp 65 ++#define __NR_setsid 66 ++#define __NR_sigaction 67 ++#define __NR_sgetmask 68 ++#define __NR_ssetmask 69 ++#define __NR_setreuid 70 ++#define __NR_setregid 71 ++#define __NR_sigsuspend 72 ++#define __NR_sigpending 73 ++#define __NR_sethostname 74 ++#define __NR_setrlimit 75 ++#define __NR_getrlimit 76 ++#define __NR_getrusage 77 ++#define __NR_gettimeofday 78 ++#define __NR_settimeofday 79 ++#define __NR_getgroups 80 ++#define __NR_setgroups 81 ++#define __NR_select 82 ++#define __NR_symlink 83 ++#define __NR_oldlstat 84 ++#define __NR_readlink 85 ++#define __NR_uselib 86 ++#define __NR_swapon 87 ++#define __NR_reboot 88 ++#define __NR_readdir 89 ++#define __NR_mmap 90 ++#define __NR_munmap 91 ++#define __NR_truncate 92 ++#define __NR_ftruncate 93 ++#define __NR_fchmod 94 ++#define __NR_fchown 95 ++#define __NR_getpriority 96 ++#define __NR_setpriority 97 ++#define __NR_statfs 99 ++#define __NR_fstatfs 100 ++#define __NR_socketcall 102 ++#define __NR_syslog 103 ++#define __NR_setitimer 104 ++#define __NR_getitimer 105 ++#define __NR_stat 106 ++#define __NR_lstat 107 ++#define __NR_fstat 108 ++#define __NR_vhangup 111 ++#define __NR_wait4 114 ++#define __NR_swapoff 115 ++#define __NR_sysinfo 116 ++#define __NR_ipc 117 ++#define __NR_fsync 118 ++#define __NR_sigreturn 119 ++#define __NR_clone 120 ++#define __NR_setdomainname 121 ++#define __NR_uname 122 ++#define __NR_cacheflush 123 ++#define __NR_adjtimex 124 ++#define __NR_mprotect 125 ++#define __NR_sigprocmask 126 ++#define __NR_create_module 127 ++#define __NR_init_module 128 ++#define __NR_delete_module 129 ++#define __NR_get_kernel_syms 130 ++#define __NR_quotactl 131 ++#define __NR_getpgid 132 ++#define __NR_fchdir 133 ++#define __NR_bdflush 134 ++#define __NR_sysfs 135 ++#define __NR_personality 136 ++#define __NR_setfsuid 138 ++#define __NR_setfsgid 139 ++#define __NR__llseek 140 ++#define __NR_getdents 141 ++#define __NR__newselect 142 ++#define __NR_flock 143 ++#define __NR_msync 144 ++#define __NR_readv 145 ++#define __NR_writev 146 ++#define __NR_getsid 147 ++#define __NR_fdatasync 148 ++#define __NR__sysctl 149 ++#define __NR_mlock 150 ++#define __NR_munlock 151 ++#define __NR_mlockall 152 ++#define __NR_munlockall 153 ++#define __NR_sched_setparam 154 ++#define __NR_sched_getparam 155 ++#define __NR_sched_setscheduler 156 ++#define __NR_sched_getscheduler 157 ++#define __NR_sched_yield 158 ++#define __NR_sched_get_priority_max 159 ++#define __NR_sched_get_priority_min 160 ++#define __NR_sched_rr_get_interval 161 ++#define __NR_nanosleep 162 ++#define __NR_mremap 163 ++#define __NR_setresuid 164 ++#define __NR_getresuid 165 ++#define __NR_getpagesize 166 ++#define __NR_query_module 167 ++#define __NR_poll 168 ++#define __NR_nfsservctl 169 ++#define __NR_setresgid 170 ++#define __NR_getresgid 171 ++#define __NR_prctl 172 ++#define __NR_rt_sigreturn 173 ++#define __NR_rt_sigaction 174 ++#define __NR_rt_sigprocmask 175 ++#define __NR_rt_sigpending 176 ++#define __NR_rt_sigtimedwait 177 ++#define __NR_rt_sigqueueinfo 178 ++#define __NR_rt_sigsuspend 179 ++#define __NR_pread64 180 ++#define __NR_pwrite64 181 ++#define __NR_lchown 182 ++#define __NR_getcwd 183 ++#define __NR_capget 184 ++#define __NR_capset 185 ++#define __NR_sigaltstack 186 ++#define __NR_sendfile 187 ++#define __NR_getpmsg 188 ++#define __NR_putpmsg 189 ++#define __NR_vfork 190 ++#define __NR_ugetrlimit 191 ++#define __NR_mmap2 192 ++#define __NR_truncate64 193 ++#define __NR_ftruncate64 194 ++#define __NR_stat64 195 ++#define __NR_lstat64 196 ++#define __NR_fstat64 197 ++#define __NR_chown32 198 ++#define __NR_getuid32 199 ++#define __NR_getgid32 200 ++#define __NR_geteuid32 201 ++#define __NR_getegid32 202 ++#define __NR_setreuid32 203 ++#define __NR_setregid32 204 ++#define __NR_getgroups32 205 ++#define __NR_setgroups32 206 ++#define __NR_fchown32 207 ++#define __NR_setresuid32 208 ++#define __NR_getresuid32 209 ++#define __NR_setresgid32 210 ++#define __NR_getresgid32 211 ++#define __NR_lchown32 212 ++#define __NR_setuid32 213 ++#define __NR_setgid32 214 ++#define __NR_setfsuid32 215 ++#define __NR_setfsgid32 216 ++#define __NR_pivot_root 217 ++#define __NR_getdents64 220 ++#define __NR_gettid 221 ++#define __NR_tkill 222 ++#define __NR_setxattr 223 ++#define __NR_lsetxattr 224 ++#define __NR_fsetxattr 225 ++#define __NR_getxattr 226 ++#define __NR_lgetxattr 227 ++#define __NR_fgetxattr 228 ++#define __NR_listxattr 229 ++#define __NR_llistxattr 230 ++#define __NR_flistxattr 231 ++#define __NR_removexattr 232 ++#define __NR_lremovexattr 233 ++#define __NR_fremovexattr 234 ++#define __NR_futex 235 ++#define __NR_sendfile64 236 ++#define __NR_mincore 237 ++#define __NR_madvise 238 ++#define __NR_fcntl64 239 ++#define __NR_readahead 240 ++#define __NR_io_setup 241 ++#define __NR_io_destroy 242 ++#define __NR_io_getevents 243 ++#define __NR_io_submit 244 ++#define __NR_io_cancel 245 ++#define __NR_fadvise64 246 ++#define __NR_exit_group 247 ++#define __NR_lookup_dcookie 248 ++#define __NR_epoll_create 249 ++#define __NR_epoll_ctl 250 ++#define __NR_epoll_wait 251 ++#define __NR_remap_file_pages 252 ++#define __NR_set_tid_address 253 ++#define __NR_timer_create 254 ++#define __NR_timer_settime 255 ++#define __NR_timer_gettime 256 ++#define __NR_timer_getoverrun 257 ++#define __NR_timer_delete 258 ++#define __NR_clock_settime 259 ++#define __NR_clock_gettime 260 ++#define __NR_clock_getres 261 ++#define __NR_clock_nanosleep 262 ++#define __NR_statfs64 263 ++#define __NR_fstatfs64 264 ++#define __NR_tgkill 265 ++#define __NR_utimes 266 ++#define __NR_fadvise64_64 267 ++#define __NR_mbind 268 ++#define __NR_get_mempolicy 269 ++#define __NR_set_mempolicy 270 ++#define __NR_mq_open 271 ++#define __NR_mq_unlink 272 ++#define __NR_mq_timedsend 273 ++#define __NR_mq_timedreceive 274 ++#define __NR_mq_notify 275 ++#define __NR_mq_getsetattr 276 ++#define __NR_waitid 277 ++#define __NR_add_key 279 ++#define __NR_request_key 280 ++#define __NR_keyctl 281 ++#define __NR_ioprio_set 282 ++#define __NR_ioprio_get 283 ++#define __NR_inotify_init 284 ++#define __NR_inotify_add_watch 285 ++#define __NR_inotify_rm_watch 286 ++#define __NR_migrate_pages 287 ++#define __NR_openat 288 ++#define __NR_mkdirat 289 ++#define __NR_mknodat 290 ++#define __NR_fchownat 291 ++#define __NR_futimesat 292 ++#define __NR_fstatat64 293 ++#define __NR_unlinkat 294 ++#define __NR_renameat 295 ++#define __NR_linkat 296 ++#define __NR_symlinkat 297 ++#define __NR_readlinkat 298 ++#define __NR_fchmodat 299 ++#define __NR_faccessat 300 ++#define __NR_pselect6 301 ++#define __NR_ppoll 302 ++#define __NR_unshare 303 ++#define __NR_set_robust_list 304 ++#define __NR_get_robust_list 305 ++#define __NR_splice 306 ++#define __NR_sync_file_range 307 ++#define __NR_tee 308 ++#define __NR_vmsplice 309 ++#define __NR_move_pages 310 ++#define __NR_sched_setaffinity 311 ++#define __NR_sched_getaffinity 312 ++#define __NR_kexec_load 313 ++#define __NR_getcpu 314 ++#define __NR_epoll_pwait 315 ++#define __NR_utimensat 316 ++#define __NR_signalfd 317 ++#define __NR_timerfd_create 318 ++#define __NR_eventfd 319 ++#define __NR_fallocate 320 ++#define __NR_timerfd_settime 321 ++#define __NR_timerfd_gettime 322 ++#define __NR_signalfd4 323 ++#define __NR_eventfd2 324 ++#define __NR_epoll_create1 325 ++#define __NR_dup3 326 ++#define __NR_pipe2 327 ++#define __NR_inotify_init1 328 ++#define __NR_preadv 329 ++#define __NR_pwritev 330 ++#define __NR_rt_tgsigqueueinfo 331 ++#define __NR_perf_event_open 332 ++#define __NR_get_thread_area 333 ++#define __NR_set_thread_area 334 ++#define __NR_atomic_cmpxchg_32 335 ++#define __NR_atomic_barrier 336 ++#define __NR_fanotify_init 337 ++#define __NR_fanotify_mark 338 ++#define __NR_prlimit64 339 ++#define __NR_name_to_handle_at 340 ++#define __NR_open_by_handle_at 341 ++#define __NR_clock_adjtime 342 ++#define __NR_syncfs 343 ++#define __NR_setns 344 ++#define __NR_process_vm_readv 345 ++#define __NR_process_vm_writev 346 ++#define __NR_kcmp 347 ++#define __NR_finit_module 348 ++#define __NR_sched_setattr 349 ++#define __NR_sched_getattr 350 ++#define __NR_renameat2 351 ++#define __NR_getrandom 352 ++#define __NR_memfd_create 353 ++#define __NR_bpf 354 ++#define __NR_execveat 355 ++#define __NR_socket 356 ++#define __NR_socketpair 357 ++#define __NR_bind 358 ++#define __NR_connect 359 ++#define __NR_listen 360 ++#define __NR_accept4 361 ++#define __NR_getsockopt 362 ++#define __NR_setsockopt 363 ++#define __NR_getsockname 364 ++#define __NR_getpeername 365 ++#define __NR_sendto 366 ++#define __NR_sendmsg 367 ++#define __NR_recvfrom 368 ++#define __NR_recvmsg 369 ++#define __NR_shutdown 370 ++#define __NR_recvmmsg 371 ++#define __NR_sendmmsg 372 ++#define __NR_userfaultfd 373 ++#define __NR_membarrier 374 ++#define __NR_mlock2 375 ++#define __NR_copy_file_range 376 ++#define __NR_preadv2 377 ++#define __NR_pwritev2 378 ++#define __NR_statx 379 +diff --git a/arch/m68k/bits/user.h b/arch/m68k/bits/user.h +new file mode 100644 +index 00000000..9a4ca128 +--- /dev/null ++++ b/arch/m68k/bits/user.h +@@ -0,0 +1,33 @@ ++#undef __WORDSIZE ++#define __WORDSIZE 32 ++ ++struct user_m68kfp_struct { ++ unsigned long fpregs[24], fpcntl[3]; ++}; ++ ++struct user_regs_struct { ++ long d1, d2, d3, d4, d5, d6, d7; ++ long a0, a1, a2, a3, a4, a5, a6; ++ long d0, usp, orig_d0; ++ short stkadj, sr; ++ long pc; ++ short fmtvec, __pad; ++}; ++ ++struct user { ++ struct user_regs_struct regs; ++ int u_fpvalid; ++ struct user_m68kfp_struct m68kfp; ++ unsigned long u_tsize, u_dsize, u_ssize, start_code, start_stack; ++ long signal; ++ int reserved; ++ unsigned long u_ar0; ++ struct user_m68kfp_struct *u_fpstate; ++ unsigned long magic; ++ char u_comm[32]; ++}; ++ ++#define NBPG 4096 ++#define UPAGES 1 ++#define HOST_TEXT_START_ADDR (u.start_code) ++#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) +diff --git a/arch/m68k/crt_arch.h b/arch/m68k/crt_arch.h +new file mode 100644 +index 00000000..48a42f29 +--- /dev/null ++++ b/arch/m68k/crt_arch.h +@@ -0,0 +1,14 @@ ++__asm__( ++".text\n" ++".weak _DYNAMIC \n" ++".hidden _DYNAMIC \n" ++".global " START "\n" ++START ":\n" ++" suba.l %fp,%fp \n" ++" movea.l %sp,%a0 \n" ++" lea _DYNAMIC-.-8,%a1 \n" ++" pea (%pc,%a1) \n" ++" pea (%a0) \n" ++" lea " START "_c-.-8,%a1 \n" ++" jsr (%pc,%a1) \n" ++); +diff --git a/arch/m68k/pthread_arch.h b/arch/m68k/pthread_arch.h +new file mode 100644 +index 00000000..02d5b8a0 +--- /dev/null ++++ b/arch/m68k/pthread_arch.h +@@ -0,0 +1,13 @@ ++static inline struct pthread *__pthread_self() ++{ ++ uintptr_t tp = __syscall(SYS_get_thread_area); ++ return (pthread_t)(tp - 0x7000 - sizeof(struct pthread)); ++} ++ ++#define TLS_ABOVE_TP ++#define GAP_ABOVE_TP 0 ++#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000) ++ ++#define DTP_OFFSET 0x8000 ++ ++#define MC_PC gregs[R_PC] +diff --git a/arch/m68k/reloc.h b/arch/m68k/reloc.h +new file mode 100644 +index 00000000..f920b39e +--- /dev/null ++++ b/arch/m68k/reloc.h +@@ -0,0 +1,30 @@ ++#if __HAVE_68881__ ++#define FP_SUFFIX "" ++#elif __mcffpu__ ++#define FP_SUFFIX "-fp64" ++#else ++#define FP_SUFFIX "-sf" ++#endif ++ ++#define LDSO_ARCH "m68k" FP_SUFFIX ++ ++#define TPOFF_K (-0x7000) ++ ++#define REL_SYMBOLIC R_68K_32 ++#define REL_OFFSET R_68K_PC32 ++#define REL_GOT R_68K_GLOB_DAT ++#define REL_PLT R_68K_JMP_SLOT ++#define REL_RELATIVE R_68K_RELATIVE ++#define REL_COPY R_68K_COPY ++#define REL_DTPMOD R_68K_TLS_DTPMOD32 ++#define REL_DTPOFF R_68K_TLS_DTPREL32 ++#define REL_TPOFF R_68K_TLS_TPREL32 ++ ++#define CRTJMP(pc,sp) __asm__ __volatile__( \ ++ "move.l %1,%%sp ; jmp (%0)" : : "r"(pc), "r"(sp) : "memory" ) ++ ++#define GETFUNCSYM(fp, sym, got) __asm__ ( \ ++ ".hidden " #sym "\n" \ ++ "lea " #sym "-.-8,%0 \n" \ ++ "lea (%%pc,%0),%0 \n" \ ++ : "=a"(*fp) : : "memory" ) +diff --git a/arch/m68k/syscall_arch.h b/arch/m68k/syscall_arch.h +new file mode 100644 +index 00000000..af79c306 +--- /dev/null ++++ b/arch/m68k/syscall_arch.h +@@ -0,0 +1,91 @@ ++#define __SYSCALL_LL_E(x) \ ++((union { long long ll; long l[2]; }){ .ll = x }).l[0], \ ++((union { long long ll; long l[2]; }){ .ll = x }).l[1] ++#define __SYSCALL_LL_O(x) __SYSCALL_LL_E((x)) ++ ++static __inline long __syscall0(long n) ++{ ++ register unsigned long d0 __asm__("d0") = n; ++ __asm__ __volatile__ ("trap #0" : "+r"(d0) ++ : ++ : "memory"); ++ return d0; ++} ++ ++static inline long __syscall1(long n, long a) ++{ ++ register unsigned long d0 __asm__("d0") = n; ++ register unsigned long d1 __asm__("d1") = a; ++ __asm__ __volatile__ ("trap #0" : "+r"(d0) ++ : "r"(d1) ++ : "memory"); ++ return d0; ++} ++ ++static inline long __syscall2(long n, long a, long b) ++{ ++ register unsigned long d0 __asm__("d0") = n; ++ register unsigned long d1 __asm__("d1") = a; ++ register unsigned long d2 __asm__("d2") = b; ++ __asm__ __volatile__ ("trap #0" : "+r"(d0) ++ : "r"(d1), "r"(d2) ++ : "memory"); ++ return d0; ++} ++ ++static inline long __syscall3(long n, long a, long b, long c) ++{ ++ register unsigned long d0 __asm__("d0") = n; ++ register unsigned long d1 __asm__("d1") = a; ++ register unsigned long d2 __asm__("d2") = b; ++ register unsigned long d3 __asm__("d3") = c; ++ __asm__ __volatile__ ("trap #0" : "+r"(d0) ++ : "r"(d1), "r"(d2), "r"(d3) ++ : "memory"); ++ return d0; ++} ++ ++static inline long __syscall4(long n, long a, long b, long c, long d) ++{ ++ register unsigned long d0 __asm__("d0") = n; ++ register unsigned long d1 __asm__("d1") = a; ++ register unsigned long d2 __asm__("d2") = b; ++ register unsigned long d3 __asm__("d3") = c; ++ register unsigned long d4 __asm__("d4") = d; ++ __asm__ __volatile__ ("trap #0" : "+r"(d0) ++ : "r"(d1), "r"(d2), "r"(d3), "r"(d4) ++ : "memory"); ++ return d0; ++} ++ ++static inline long __syscall5(long n, long a, long b, long c, long d, long e) ++{ ++ register unsigned long d0 __asm__("d0") = n; ++ register unsigned long d1 __asm__("d1") = a; ++ register unsigned long d2 __asm__("d2") = b; ++ register unsigned long d3 __asm__("d3") = c; ++ register unsigned long d4 __asm__("d4") = d; ++ register unsigned long d5 __asm__("d5") = e; ++ __asm__ __volatile__ ("trap #0" : "+r"(d0) ++ : "r"(d1), "r"(d2), "r"(d3), "r"(d4), "r"(d5) ++ : "memory"); ++ return d0; ++} ++ ++static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) ++{ ++ register unsigned long d0 __asm__("d0") = n; ++ register unsigned long d1 __asm__("d1") = a; ++ register unsigned long d2 __asm__("d2") = b; ++ register unsigned long d3 __asm__("d3") = c; ++ register unsigned long d4 __asm__("d4") = d; ++ register unsigned long d5 __asm__("d5") = e; ++ register unsigned long a0 __asm__("a0") = f; ++ __asm__ __volatile__ ("trap #0" : "+r"(d0) ++ : "r"(d1), "r"(d2), "r"(d3), "r"(d4), "r"(d5), "r"(a0) ++ : "memory"); ++ return d0; ++} ++ ++#define SYSCALL_USE_SOCKETCALL ++#define SYSCALL_IPC_BROKEN_MODE +diff --git a/arch/microblaze/syscall_arch.h b/arch/microblaze/syscall_arch.h +index 8e2de7ea..6cf631ad 100644 +--- a/arch/microblaze/syscall_arch.h ++++ b/arch/microblaze/syscall_arch.h +@@ -102,3 +102,5 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo + #define SYSCALL_NO_INLINE + + #endif ++ ++#define SYSCALL_IPC_BROKEN_MODE +diff --git a/arch/mips/bits/hwcap.h b/arch/mips/bits/hwcap.h +index 05cffba4..13e86fe7 100644 +--- a/arch/mips/bits/hwcap.h ++++ b/arch/mips/bits/hwcap.h +@@ -1,2 +1,3 @@ + #define HWCAP_MIPS_R6 (1 << 0) + #define HWCAP_MIPS_MSA (1 << 1) ++#define HWCAP_MIPS_CRC32 (1 << 2) +diff --git a/arch/mips/bits/mman.h b/arch/mips/bits/mman.h +index c68aea88..9027bb63 100644 +--- a/arch/mips/bits/mman.h ++++ b/arch/mips/bits/mman.h +@@ -18,6 +18,7 @@ + #define MAP_STACK 0x40000 + #undef MAP_HUGETLB + #define MAP_HUGETLB 0x80000 ++#undef MAP_SYNC + + #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) + #undef MADV_SOFT_OFFLINE +diff --git a/arch/mips/bits/ptrace.h b/arch/mips/bits/ptrace.h +new file mode 100644 +index 00000000..77a01c06 +--- /dev/null ++++ b/arch/mips/bits/ptrace.h +@@ -0,0 +1,9 @@ ++#define PTRACE_GET_THREAD_AREA 25 ++#define PTRACE_SET_THREAD_AREA 26 ++#define PTRACE_PEEKTEXT_3264 0xc0 ++#define PTRACE_PEEKDATA_3264 0xc1 ++#define PTRACE_POKETEXT_3264 0xc2 ++#define PTRACE_POKEDATA_3264 0xc3 ++#define PTRACE_GET_THREAD_AREA_3264 0xc4 ++#define PTRACE_GET_WATCH_REGS 0xd0 ++#define PTRACE_SET_WATCH_REGS 0xd1 +diff --git a/arch/mips/bits/socket.h b/arch/mips/bits/socket.h +index 191ebdb5..b82c7d34 100644 +--- a/arch/mips/bits/socket.h ++++ b/arch/mips/bits/socket.h +@@ -45,6 +45,7 @@ struct cmsghdr { + #define SO_BSDCOMPAT 14 + #define SO_PASSCRED 17 + #define SO_PEERCRED 18 ++#define SO_PEERSEC 30 + #define SO_SNDBUFFORCE 31 + #define SO_RCVBUFFORCE 33 + +diff --git a/arch/mips/bits/termios.h b/arch/mips/bits/termios.h +index 6a1205d7..f7b9dd2e 100644 +--- a/arch/mips/bits/termios.h ++++ b/arch/mips/bits/termios.h +@@ -52,6 +52,7 @@ struct termios { + #define ONLRET 0000040 + #define OFILL 0000100 + #define OFDEL 0000200 ++#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE) + #define NLDLY 0000400 + #define NL0 0000000 + #define NL1 0000400 +@@ -71,6 +72,7 @@ struct termios { + #define FFDLY 0100000 + #define FF0 0000000 + #define FF1 0100000 ++#endif + + #define VTDLY 0040000 + #define VT0 0000000 +@@ -163,5 +165,5 @@ struct termios { + #define EXTPROC 0200000 + + #define XTABS 0014000 +-#define TIOCSER_TEMT 1 ++#define TIOCSER_TEMT 0x01 + #endif +diff --git a/arch/mips/pthread_arch.h b/arch/mips/pthread_arch.h +index e5812655..5fea15ad 100644 +--- a/arch/mips/pthread_arch.h ++++ b/arch/mips/pthread_arch.h +@@ -11,6 +11,7 @@ static inline struct pthread *__pthread_self() + } + + #define TLS_ABOVE_TP ++#define GAP_ABOVE_TP 0 + #define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000) + + #define DTP_OFFSET 0x8000 +diff --git a/arch/mips64/bits/hwcap.h b/arch/mips64/bits/hwcap.h +index 05cffba4..13e86fe7 100644 +--- a/arch/mips64/bits/hwcap.h ++++ b/arch/mips64/bits/hwcap.h +@@ -1,2 +1,3 @@ + #define HWCAP_MIPS_R6 (1 << 0) + #define HWCAP_MIPS_MSA (1 << 1) ++#define HWCAP_MIPS_CRC32 (1 << 2) +diff --git a/arch/mips64/bits/mman.h b/arch/mips64/bits/mman.h +index c68aea88..9027bb63 100644 +--- a/arch/mips64/bits/mman.h ++++ b/arch/mips64/bits/mman.h +@@ -18,6 +18,7 @@ + #define MAP_STACK 0x40000 + #undef MAP_HUGETLB + #define MAP_HUGETLB 0x80000 ++#undef MAP_SYNC + + #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) + #undef MADV_SOFT_OFFLINE +diff --git a/arch/mips64/bits/ptrace.h b/arch/mips64/bits/ptrace.h +new file mode 100644 +index 00000000..77a01c06 +--- /dev/null ++++ b/arch/mips64/bits/ptrace.h +@@ -0,0 +1,9 @@ ++#define PTRACE_GET_THREAD_AREA 25 ++#define PTRACE_SET_THREAD_AREA 26 ++#define PTRACE_PEEKTEXT_3264 0xc0 ++#define PTRACE_PEEKDATA_3264 0xc1 ++#define PTRACE_POKETEXT_3264 0xc2 ++#define PTRACE_POKEDATA_3264 0xc3 ++#define PTRACE_GET_THREAD_AREA_3264 0xc4 ++#define PTRACE_GET_WATCH_REGS 0xd0 ++#define PTRACE_SET_WATCH_REGS 0xd1 +diff --git a/arch/mips64/bits/socket.h b/arch/mips64/bits/socket.h +index cf801797..5aff0d91 100644 +--- a/arch/mips64/bits/socket.h ++++ b/arch/mips64/bits/socket.h +@@ -61,6 +61,7 @@ struct cmsghdr { + #define SO_BSDCOMPAT 14 + #define SO_PASSCRED 17 + #define SO_PEERCRED 18 ++#define SO_PEERSEC 30 + #define SO_SNDBUFFORCE 31 + #define SO_RCVBUFFORCE 33 + +diff --git a/arch/mips64/bits/termios.h b/arch/mips64/bits/termios.h +index 6a1205d7..f7b9dd2e 100644 +--- a/arch/mips64/bits/termios.h ++++ b/arch/mips64/bits/termios.h +@@ -52,6 +52,7 @@ struct termios { + #define ONLRET 0000040 + #define OFILL 0000100 + #define OFDEL 0000200 ++#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE) + #define NLDLY 0000400 + #define NL0 0000000 + #define NL1 0000400 +@@ -71,6 +72,7 @@ struct termios { + #define FFDLY 0100000 + #define FF0 0000000 + #define FF1 0100000 ++#endif + + #define VTDLY 0040000 + #define VT0 0000000 +@@ -163,5 +165,5 @@ struct termios { + #define EXTPROC 0200000 + + #define XTABS 0014000 +-#define TIOCSER_TEMT 1 ++#define TIOCSER_TEMT 0x01 + #endif +diff --git a/arch/mips64/pthread_arch.h b/arch/mips64/pthread_arch.h +index e5812655..5fea15ad 100644 +--- a/arch/mips64/pthread_arch.h ++++ b/arch/mips64/pthread_arch.h +@@ -11,6 +11,7 @@ static inline struct pthread *__pthread_self() + } + + #define TLS_ABOVE_TP ++#define GAP_ABOVE_TP 0 + #define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000) + + #define DTP_OFFSET 0x8000 +diff --git a/arch/mipsn32/bits/hwcap.h b/arch/mipsn32/bits/hwcap.h +index 05cffba4..13e86fe7 100644 +--- a/arch/mipsn32/bits/hwcap.h ++++ b/arch/mipsn32/bits/hwcap.h +@@ -1,2 +1,3 @@ + #define HWCAP_MIPS_R6 (1 << 0) + #define HWCAP_MIPS_MSA (1 << 1) ++#define HWCAP_MIPS_CRC32 (1 << 2) +diff --git a/arch/mipsn32/bits/mman.h b/arch/mipsn32/bits/mman.h +index c68aea88..9027bb63 100644 +--- a/arch/mipsn32/bits/mman.h ++++ b/arch/mipsn32/bits/mman.h +@@ -18,6 +18,7 @@ + #define MAP_STACK 0x40000 + #undef MAP_HUGETLB + #define MAP_HUGETLB 0x80000 ++#undef MAP_SYNC + + #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) + #undef MADV_SOFT_OFFLINE +diff --git a/arch/mipsn32/bits/ptrace.h b/arch/mipsn32/bits/ptrace.h +new file mode 100644 +index 00000000..77a01c06 +--- /dev/null ++++ b/arch/mipsn32/bits/ptrace.h +@@ -0,0 +1,9 @@ ++#define PTRACE_GET_THREAD_AREA 25 ++#define PTRACE_SET_THREAD_AREA 26 ++#define PTRACE_PEEKTEXT_3264 0xc0 ++#define PTRACE_PEEKDATA_3264 0xc1 ++#define PTRACE_POKETEXT_3264 0xc2 ++#define PTRACE_POKEDATA_3264 0xc3 ++#define PTRACE_GET_THREAD_AREA_3264 0xc4 ++#define PTRACE_GET_WATCH_REGS 0xd0 ++#define PTRACE_SET_WATCH_REGS 0xd1 +diff --git a/arch/mipsn32/bits/socket.h b/arch/mipsn32/bits/socket.h +index 191ebdb5..b82c7d34 100644 +--- a/arch/mipsn32/bits/socket.h ++++ b/arch/mipsn32/bits/socket.h +@@ -45,6 +45,7 @@ struct cmsghdr { + #define SO_BSDCOMPAT 14 + #define SO_PASSCRED 17 + #define SO_PEERCRED 18 ++#define SO_PEERSEC 30 + #define SO_SNDBUFFORCE 31 + #define SO_RCVBUFFORCE 33 + +diff --git a/arch/mipsn32/bits/termios.h b/arch/mipsn32/bits/termios.h +index 6a1205d7..f7b9dd2e 100644 +--- a/arch/mipsn32/bits/termios.h ++++ b/arch/mipsn32/bits/termios.h +@@ -52,6 +52,7 @@ struct termios { + #define ONLRET 0000040 + #define OFILL 0000100 + #define OFDEL 0000200 ++#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE) + #define NLDLY 0000400 + #define NL0 0000000 + #define NL1 0000400 +@@ -71,6 +72,7 @@ struct termios { + #define FFDLY 0100000 + #define FF0 0000000 + #define FF1 0100000 ++#endif + + #define VTDLY 0040000 + #define VT0 0000000 +@@ -163,5 +165,5 @@ struct termios { + #define EXTPROC 0200000 + + #define XTABS 0014000 +-#define TIOCSER_TEMT 1 ++#define TIOCSER_TEMT 0x01 + #endif +diff --git a/arch/mipsn32/pthread_arch.h b/arch/mipsn32/pthread_arch.h +index e5812655..5fea15ad 100644 +--- a/arch/mipsn32/pthread_arch.h ++++ b/arch/mipsn32/pthread_arch.h +@@ -11,6 +11,7 @@ static inline struct pthread *__pthread_self() + } + + #define TLS_ABOVE_TP ++#define GAP_ABOVE_TP 0 + #define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000) + + #define DTP_OFFSET 0x8000 +diff --git a/arch/or1k/bits/limits.h b/arch/or1k/bits/limits.h +index 483b6749..3a811c99 100644 +--- a/arch/or1k/bits/limits.h ++++ b/arch/or1k/bits/limits.h +@@ -1,6 +1,6 @@ + #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +-#define PAGE_SIZE 8192 ++#define PAGESIZE 8192 + #define LONG_BIT 32 + #endif + +diff --git a/arch/or1k/pthread_arch.h b/arch/or1k/pthread_arch.h +index 7decd769..521b9c53 100644 +--- a/arch/or1k/pthread_arch.h ++++ b/arch/or1k/pthread_arch.h +@@ -12,6 +12,7 @@ static inline struct pthread *__pthread_self() + } + + #define TLS_ABOVE_TP ++#define GAP_ABOVE_TP 0 + #define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread)) + + #define MC_PC regs.pc +diff --git a/arch/powerpc/bits/hwcap.h b/arch/powerpc/bits/hwcap.h +index 82c92a93..803de9b5 100644 +--- a/arch/powerpc/bits/hwcap.h ++++ b/arch/powerpc/bits/hwcap.h +@@ -38,3 +38,6 @@ + #define PPC_FEATURE2_HTM_NOSC 0x01000000 + #define PPC_FEATURE2_ARCH_3_00 0x00800000 + #define PPC_FEATURE2_HAS_IEEE128 0x00400000 ++#define PPC_FEATURE2_DARN 0x00200000 ++#define PPC_FEATURE2_SCV 0x00100000 ++#define PPC_FEATURE2_HTM_NO_SUSPEND 0x00080000 +diff --git a/arch/powerpc/bits/mman.h b/arch/powerpc/bits/mman.h +index 95ec4358..b3a675a8 100644 +--- a/arch/powerpc/bits/mman.h ++++ b/arch/powerpc/bits/mman.h +@@ -4,6 +4,7 @@ + #define MAP_NORESERVE 0x40 + #undef MAP_LOCKED + #define MAP_LOCKED 0x80 ++#undef MAP_SYNC + + #undef MCL_CURRENT + #define MCL_CURRENT 0x2000 +diff --git a/arch/powerpc/bits/ptrace.h b/arch/powerpc/bits/ptrace.h +new file mode 100644 +index 00000000..75086ca0 +--- /dev/null ++++ b/arch/powerpc/bits/ptrace.h +@@ -0,0 +1,23 @@ ++#define PTRACE_GETVRREGS 0x12 ++#define PTRACE_SETVRREGS 0x13 ++#define PTRACE_GETEVRREGS 0x14 ++#define PTRACE_SETEVRREGS 0x15 ++#define PTRACE_GETREGS64 0x16 ++#define PTRACE_SETREGS64 0x17 ++#define PTRACE_GET_DEBUGREG 0x19 ++#define PTRACE_SET_DEBUGREG 0x1a ++#define PTRACE_GETVSRREGS 0x1b ++#define PTRACE_SETVSRREGS 0x1c ++#define PTRACE_SINGLEBLOCK 0x100 ++ ++#define PT_GETVRREGS PTRACE_GETVRREGS ++#define PT_SETVRREGS PTRACE_SETVRREGS ++#define PT_GETEVRREGS PTRACE_GETEVRREGS ++#define PT_SETEVRREGS PTRACE_SETEVRREGS ++#define PT_GETREGS64 PTRACE_GETREGS64 ++#define PT_SETREGS64 PTRACE_SETREGS64 ++#define PT_GET_DEBUGREG PTRACE_GET_DEBUGREG ++#define PT_SET_DEBUGREG PTRACE_SET_DEBUGREG ++#define PT_GETVSRREGS PTRACE_GETVSRREGS ++#define PT_SETVSRREGS PTRACE_SETVSRREGS ++#define PT_STEPBLOCK PTRACE_SINGLEBLOCK +diff --git a/arch/powerpc/bits/socket.h b/arch/powerpc/bits/socket.h +index 2fee8777..a94b8bdb 100644 +--- a/arch/powerpc/bits/socket.h ++++ b/arch/powerpc/bits/socket.h +@@ -36,6 +36,7 @@ struct cmsghdr { + #define SO_PASSCRED 20 + #define SO_PEERCRED 21 + #define SO_ACCEPTCONN 30 ++#define SO_PEERSEC 31 + #define SO_SNDBUFFORCE 32 + #define SO_RCVBUFFORCE 33 + #define SO_PROTOCOL 38 +diff --git a/arch/powerpc/bits/syscall.h.in b/arch/powerpc/bits/syscall.h.in +index 20833915..7ce94bbd 100644 +--- a/arch/powerpc/bits/syscall.h.in ++++ b/arch/powerpc/bits/syscall.h.in +@@ -368,4 +368,7 @@ + #define __NR_pwritev2 381 + #define __NR_kexec_file_load 382 + #define __NR_statx 383 ++#define __NR_pkey_alloc 384 ++#define __NR_pkey_free 385 ++#define __NR_pkey_mprotect 386 + +diff --git a/arch/powerpc/bits/termios.h b/arch/powerpc/bits/termios.h +index 0b09630c..e3f22e86 100644 +--- a/arch/powerpc/bits/termios.h ++++ b/arch/powerpc/bits/termios.h +@@ -53,6 +53,7 @@ struct termios { + #define ONLRET 0000040 + #define OFILL 0000100 + #define OFDEL 0000200 ++#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE) + #define NLDLY 0001400 + #define NL0 0000000 + #define NL1 0000400 +@@ -74,6 +75,7 @@ struct termios { + #define BSDLY 0100000 + #define BS0 0000000 + #define BS1 0100000 ++#endif + + #define VTDLY 0200000 + #define VT0 0000000 +@@ -165,5 +167,5 @@ struct termios { + #define EXTPROC 0x10000000 + + #define XTABS 00006000 +-#define TIOCSER_TEMT 1 ++#define TIOCSER_TEMT 0x01 + #endif +diff --git a/arch/powerpc/pthread_arch.h b/arch/powerpc/pthread_arch.h +index 7c5c4fad..79e5a09f 100644 +--- a/arch/powerpc/pthread_arch.h ++++ b/arch/powerpc/pthread_arch.h +@@ -11,6 +11,7 @@ static inline struct pthread *__pthread_self() + } + + #define TLS_ABOVE_TP ++#define GAP_ABOVE_TP 0 + #define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000) + + #define DTP_OFFSET 0x8000 +diff --git a/arch/powerpc64/bits/hwcap.h b/arch/powerpc64/bits/hwcap.h +index 82c92a93..803de9b5 100644 +--- a/arch/powerpc64/bits/hwcap.h ++++ b/arch/powerpc64/bits/hwcap.h +@@ -38,3 +38,6 @@ + #define PPC_FEATURE2_HTM_NOSC 0x01000000 + #define PPC_FEATURE2_ARCH_3_00 0x00800000 + #define PPC_FEATURE2_HAS_IEEE128 0x00400000 ++#define PPC_FEATURE2_DARN 0x00200000 ++#define PPC_FEATURE2_SCV 0x00100000 ++#define PPC_FEATURE2_HTM_NO_SUSPEND 0x00080000 +diff --git a/arch/powerpc64/bits/mman.h b/arch/powerpc64/bits/mman.h +index 95ec4358..b3a675a8 100644 +--- a/arch/powerpc64/bits/mman.h ++++ b/arch/powerpc64/bits/mman.h +@@ -4,6 +4,7 @@ + #define MAP_NORESERVE 0x40 + #undef MAP_LOCKED + #define MAP_LOCKED 0x80 ++#undef MAP_SYNC + + #undef MCL_CURRENT + #define MCL_CURRENT 0x2000 +diff --git a/arch/powerpc64/bits/ptrace.h b/arch/powerpc64/bits/ptrace.h +new file mode 100644 +index 00000000..75086ca0 +--- /dev/null ++++ b/arch/powerpc64/bits/ptrace.h +@@ -0,0 +1,23 @@ ++#define PTRACE_GETVRREGS 0x12 ++#define PTRACE_SETVRREGS 0x13 ++#define PTRACE_GETEVRREGS 0x14 ++#define PTRACE_SETEVRREGS 0x15 ++#define PTRACE_GETREGS64 0x16 ++#define PTRACE_SETREGS64 0x17 ++#define PTRACE_GET_DEBUGREG 0x19 ++#define PTRACE_SET_DEBUGREG 0x1a ++#define PTRACE_GETVSRREGS 0x1b ++#define PTRACE_SETVSRREGS 0x1c ++#define PTRACE_SINGLEBLOCK 0x100 ++ ++#define PT_GETVRREGS PTRACE_GETVRREGS ++#define PT_SETVRREGS PTRACE_SETVRREGS ++#define PT_GETEVRREGS PTRACE_GETEVRREGS ++#define PT_SETEVRREGS PTRACE_SETEVRREGS ++#define PT_GETREGS64 PTRACE_GETREGS64 ++#define PT_SETREGS64 PTRACE_SETREGS64 ++#define PT_GET_DEBUGREG PTRACE_GET_DEBUGREG ++#define PT_SET_DEBUGREG PTRACE_SET_DEBUGREG ++#define PT_GETVSRREGS PTRACE_GETVSRREGS ++#define PT_SETVSRREGS PTRACE_SETVSRREGS ++#define PT_STEPBLOCK PTRACE_SINGLEBLOCK +diff --git a/arch/powerpc64/bits/socket.h b/arch/powerpc64/bits/socket.h +index 2f748ae8..0f3c9aac 100644 +--- a/arch/powerpc64/bits/socket.h ++++ b/arch/powerpc64/bits/socket.h +@@ -54,6 +54,7 @@ struct cmsghdr { + #define SO_PASSCRED 20 + #define SO_PEERCRED 21 + #define SO_ACCEPTCONN 30 ++#define SO_PEERSEC 31 + #define SO_SNDBUFFORCE 32 + #define SO_RCVBUFFORCE 33 + #define SO_PROTOCOL 38 +diff --git a/arch/powerpc64/bits/syscall.h.in b/arch/powerpc64/bits/syscall.h.in +index 936f43c0..1da1ecc0 100644 +--- a/arch/powerpc64/bits/syscall.h.in ++++ b/arch/powerpc64/bits/syscall.h.in +@@ -359,4 +359,7 @@ + #define __NR_pwritev2 381 + #define __NR_kexec_file_load 382 + #define __NR_statx 383 ++#define __NR_pkey_alloc 384 ++#define __NR_pkey_free 385 ++#define __NR_pkey_mprotect 386 + +diff --git a/arch/powerpc64/bits/termios.h b/arch/powerpc64/bits/termios.h +index 0b09630c..e3f22e86 100644 +--- a/arch/powerpc64/bits/termios.h ++++ b/arch/powerpc64/bits/termios.h +@@ -53,6 +53,7 @@ struct termios { + #define ONLRET 0000040 + #define OFILL 0000100 + #define OFDEL 0000200 ++#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE) + #define NLDLY 0001400 + #define NL0 0000000 + #define NL1 0000400 +@@ -74,6 +75,7 @@ struct termios { + #define BSDLY 0100000 + #define BS0 0000000 + #define BS1 0100000 ++#endif + + #define VTDLY 0200000 + #define VT0 0000000 +@@ -165,5 +167,5 @@ struct termios { + #define EXTPROC 0x10000000 + + #define XTABS 00006000 +-#define TIOCSER_TEMT 1 ++#define TIOCSER_TEMT 0x01 + #endif +diff --git a/arch/powerpc64/pthread_arch.h b/arch/powerpc64/pthread_arch.h +index 2f976fe2..37b75e29 100644 +--- a/arch/powerpc64/pthread_arch.h ++++ b/arch/powerpc64/pthread_arch.h +@@ -6,6 +6,7 @@ static inline struct pthread *__pthread_self() + } + + #define TLS_ABOVE_TP ++#define GAP_ABOVE_TP 0 + #define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000) + + #define DTP_OFFSET 0x8000 +diff --git a/arch/s390x/bits/limits.h b/arch/s390x/bits/limits.h +index 792a30b9..86ef7663 100644 +--- a/arch/s390x/bits/limits.h ++++ b/arch/s390x/bits/limits.h +@@ -1,6 +1,6 @@ + #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +-#define PAGE_SIZE 4096 ++#define PAGESIZE 4096 + #define LONG_BIT 64 + #endif + +diff --git a/arch/s390x/bits/ptrace.h b/arch/s390x/bits/ptrace.h +new file mode 100644 +index 00000000..d50e3262 +--- /dev/null ++++ b/arch/s390x/bits/ptrace.h +@@ -0,0 +1,9 @@ ++#define PTRACE_SINGLEBLOCK 12 ++#define PTRACE_PEEKUSR_AREA 0x5000 ++#define PTRACE_POKEUSR_AREA 0x5001 ++#define PTRACE_GET_LAST_BREAK 0x5006 ++#define PTRACE_ENABLE_TE 0x5009 ++#define PTRACE_DISABLE_TE 0x5010 ++#define PTRACE_TE_ABORT_RAND 0x5011 ++ ++#define PT_STEPBLOCK PTRACE_SINGLEBLOCK +diff --git a/arch/s390x/bits/syscall.h.in b/arch/s390x/bits/syscall.h.in +index 4fe1a64f..409e9155 100644 +--- a/arch/s390x/bits/syscall.h.in ++++ b/arch/s390x/bits/syscall.h.in +@@ -322,4 +322,6 @@ + #define __NR_pwritev2 377 + #define __NR_s390_guarded_storage 378 + #define __NR_statx 379 ++#define __NR_s390_sthyi 380 ++#define __NR_kexec_file_load 381 + +diff --git a/arch/s390x/bits/user.h b/arch/s390x/bits/user.h +index 17bce16f..ff3f0483 100644 +--- a/arch/s390x/bits/user.h ++++ b/arch/s390x/bits/user.h +@@ -54,8 +54,8 @@ struct user { + char u_comm[32]; + }; + +-#define PAGE_MASK (~(PAGE_SIZE-1)) +-#define NBPG PAGE_SIZE ++#define PAGE_MASK (~(PAGESIZE-1)) ++#define NBPG PAGESIZE + #define UPAGES 1 + #define HOST_TEXT_START_ADDR (u.start_code) + #define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) +diff --git a/arch/sh/bits/limits.h b/arch/sh/bits/limits.h +index 65a3dd64..c340ceb2 100644 +--- a/arch/sh/bits/limits.h ++++ b/arch/sh/bits/limits.h +@@ -1,6 +1,6 @@ + #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +-#define PAGE_SIZE 4096 ++#define PAGESIZE 4096 + #define LONG_BIT 32 + #endif + +diff --git a/arch/sh/pthread_arch.h b/arch/sh/pthread_arch.h +index 2756e7ec..41fefacf 100644 +--- a/arch/sh/pthread_arch.h ++++ b/arch/sh/pthread_arch.h +@@ -2,10 +2,11 @@ static inline struct pthread *__pthread_self() + { + char *self; + __asm__ __volatile__ ("stc gbr,%0" : "=r" (self) ); +- return (struct pthread *) (self + 8 - sizeof(struct pthread)); ++ return (struct pthread *) (self - sizeof(struct pthread)); + } + + #define TLS_ABOVE_TP +-#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) - 8) ++#define GAP_ABOVE_TP 8 ++#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread)) + + #define MC_PC sc_pc +diff --git a/arch/sh/reloc.h b/arch/sh/reloc.h +index 0238ce07..a1f16cb1 100644 +--- a/arch/sh/reloc.h ++++ b/arch/sh/reloc.h +@@ -20,7 +20,7 @@ + + #define LDSO_ARCH "sh" ENDIAN_SUFFIX FP_SUFFIX ABI_SUFFIX + +-#define TPOFF_K 8 ++#define TPOFF_K 0 + + #define REL_SYMBOLIC R_SH_DIR32 + #define REL_OFFSET R_SH_REL32 +diff --git a/arch/sh/syscall_arch.h b/arch/sh/syscall_arch.h +index 84758fe0..48f61d94 100644 +--- a/arch/sh/syscall_arch.h ++++ b/arch/sh/syscall_arch.h +@@ -86,3 +86,5 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo + register long r1 __asm__("r1") = f; + __asm_syscall(22, "r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7), "0"(r0), "r"(r1)); + } ++ ++#define SYSCALL_IPC_BROKEN_MODE +diff --git a/arch/x32/atomic_arch.h b/arch/x32/atomic_arch.h +index a744c299..918c2d4e 100644 +--- a/arch/x32/atomic_arch.h ++++ b/arch/x32/atomic_arch.h +@@ -106,8 +106,8 @@ static inline int a_ctz_64(uint64_t x) + return x; + } + +-#define a_ctz_l a_ctz_l +-static inline int a_ctz_l(unsigned long x) ++#define a_ctz_32 a_ctz_32 ++static inline int a_ctz_32(uint32_t x) + { + __asm__( "bsf %1,%0" : "=r"(x) : "r"(x) ); + return x; +diff --git a/arch/x32/bits/limits.h b/arch/x32/bits/limits.h +index 65a3dd64..c340ceb2 100644 +--- a/arch/x32/bits/limits.h ++++ b/arch/x32/bits/limits.h +@@ -1,6 +1,6 @@ + #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +-#define PAGE_SIZE 4096 ++#define PAGESIZE 4096 + #define LONG_BIT 32 + #endif + +diff --git a/arch/x32/bits/ptrace.h b/arch/x32/bits/ptrace.h +new file mode 100644 +index 00000000..7f8a09b5 +--- /dev/null ++++ b/arch/x32/bits/ptrace.h +@@ -0,0 +1,13 @@ ++#define PTRACE_GET_THREAD_AREA 25 ++#define PTRACE_SET_THREAD_AREA 26 ++#define PTRACE_ARCH_PRCTL 30 ++#define PTRACE_SYSEMU 31 ++#define PTRACE_SYSEMU_SINGLESTEP 32 ++#define PTRACE_SINGLEBLOCK 33 ++ ++#define PT_GET_THREAD_AREA PTRACE_GET_THREAD_AREA ++#define PT_SET_THREAD_AREA PTRACE_SET_THREAD_AREA ++#define PT_ARCH_PRCTL PTRACE_ARCH_PRCTL ++#define PT_SYSEMU PTRACE_SYSEMU ++#define PT_SYSEMU_SINGLESTEP PTRACE_SYSEMU_SINGLESTEP ++#define PT_STEPBLOCK PTRACE_SINGLEBLOCK +diff --git a/arch/x32/bits/user.h b/arch/x32/bits/user.h +index 471bb19d..4073cc06 100644 +--- a/arch/x32/bits/user.h ++++ b/arch/x32/bits/user.h +@@ -34,8 +34,8 @@ struct user { + unsigned long u_debugreg[8]; + }; + +-#define PAGE_MASK (~(PAGE_SIZE-1)) +-#define NBPG PAGE_SIZE ++#define PAGE_MASK (~(PAGESIZE-1)) ++#define NBPG PAGESIZE + #define UPAGES 1 + #define HOST_TEXT_START_ADDR (u.start_code) + #define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) +diff --git a/arch/x86_64/bits/limits.h b/arch/x86_64/bits/limits.h +index 792a30b9..86ef7663 100644 +--- a/arch/x86_64/bits/limits.h ++++ b/arch/x86_64/bits/limits.h +@@ -1,6 +1,6 @@ + #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +-#define PAGE_SIZE 4096 ++#define PAGESIZE 4096 + #define LONG_BIT 64 + #endif + +diff --git a/arch/x86_64/bits/ptrace.h b/arch/x86_64/bits/ptrace.h +new file mode 100644 +index 00000000..7f8a09b5 +--- /dev/null ++++ b/arch/x86_64/bits/ptrace.h +@@ -0,0 +1,13 @@ ++#define PTRACE_GET_THREAD_AREA 25 ++#define PTRACE_SET_THREAD_AREA 26 ++#define PTRACE_ARCH_PRCTL 30 ++#define PTRACE_SYSEMU 31 ++#define PTRACE_SYSEMU_SINGLESTEP 32 ++#define PTRACE_SINGLEBLOCK 33 ++ ++#define PT_GET_THREAD_AREA PTRACE_GET_THREAD_AREA ++#define PT_SET_THREAD_AREA PTRACE_SET_THREAD_AREA ++#define PT_ARCH_PRCTL PTRACE_ARCH_PRCTL ++#define PT_SYSEMU PTRACE_SYSEMU ++#define PT_SYSEMU_SINGLESTEP PTRACE_SYSEMU_SINGLESTEP ++#define PT_STEPBLOCK PTRACE_SINGLEBLOCK +diff --git a/arch/x86_64/bits/user.h b/arch/x86_64/bits/user.h +index 471bb19d..4073cc06 100644 +--- a/arch/x86_64/bits/user.h ++++ b/arch/x86_64/bits/user.h +@@ -34,8 +34,8 @@ struct user { + unsigned long u_debugreg[8]; + }; + +-#define PAGE_MASK (~(PAGE_SIZE-1)) +-#define NBPG PAGE_SIZE ++#define PAGE_MASK (~(PAGESIZE-1)) ++#define NBPG PAGESIZE + #define UPAGES 1 + #define HOST_TEXT_START_ADDR (u.start_code) + #define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) +diff --git a/configure b/configure +index 1e59c461..f940af9a 100755 +--- a/configure ++++ b/configure +@@ -320,6 +320,7 @@ i?86*) ARCH=i386 ;; + x86_64-x32*|x32*|x86_64*x32) ARCH=x32 ;; + x86_64-nt64*) ARCH=nt64 ;; + x86_64*) ARCH=x86_64 ;; ++m68k*) ARCH=m68k ;; + mips64*|mipsisa64*) ARCH=mips64 ;; + mips*) ARCH=mips ;; + microblaze*) ARCH=microblaze ;; +@@ -590,10 +591,12 @@ tryldflag LDFLAGS_AUTO -Wl,--no-undefined + # versions built without shared library support and pcc are broken. + tryldflag LDFLAGS_AUTO -Wl,--exclude-libs=ALL + +-# Linking with -Bsymbolic-functions is no longer mandatory for +-# the dynamic linker to work, but enable it if it works as +-# a linking optimization. +-tryldflag LDFLAGS_AUTO -Wl,-Bsymbolic-functions ++# Public data symbols must be interposable to allow for copy ++# relocations, but otherwise we want to bind symbols at libc link ++# time to eliminate startup relocations and PLT overhead. Use ++# --dynamic-list rather than -Bsymbolic-functions for greater ++# control over what symbols are left unbound. ++tryldflag LDFLAGS_AUTO -Wl,--dynamic-list="$srcdir/dynamic.list" + + # Find compiler runtime library + test -z "$LIBCC" && tryldflag LIBCC -lgcc && tryldflag LIBCC -lgcc_eh +@@ -639,6 +642,13 @@ if test "$ARCH" = "aarch64" ; then + trycppif __AARCH64EB__ "$t" && SUBARCH=${SUBARCH}_be + fi + ++if test "$ARCH" = "m68k" ; then ++if trycppif "__HAVE_68881__" ; then : ; ++elif trycppif "__mcffpu__" ; then SUBARCH="-fp64" ++else SUBARCH="-sf" ++fi ++fi ++ + if test "$ARCH" = "mips" ; then + trycppif "__mips_isa_rev >= 6" "$t" && SUBARCH=${SUBARCH}r6 + trycppif "_MIPSEL || __MIPSEL || __MIPSEL__" "$t" && SUBARCH=${SUBARCH}el +diff --git a/dynamic.list b/dynamic.list +new file mode 100644 +index 00000000..686f8eb4 +--- /dev/null ++++ b/dynamic.list +@@ -0,0 +1,44 @@ ++{ ++environ; ++__environ; ++ ++stdin; ++stdout; ++stderr; ++ ++malloc; ++calloc; ++realloc; ++free; ++memalign; ++posix_memalign; ++aligned_alloc; ++malloc_usable_size; ++ ++timezone; ++daylight; ++tzname; ++__timezone; ++__daylight; ++__tzname; ++ ++signgam; ++__signgam; ++ ++optarg; ++optind; ++opterr; ++optreset; ++__optreset; ++ ++getdate_err; ++ ++h_errno; ++ ++program_invocation_name; ++program_invocation_short_name; ++__progname; ++__progname_full; ++ ++__stack_chk_guard; ++}; +diff --git a/include/alltypes.h.in b/include/alltypes.h.in +index 6a9c105f..622ca01d 100644 +--- a/include/alltypes.h.in ++++ b/include/alltypes.h.in +@@ -7,10 +7,10 @@ TYPEDEF _Addr regoff_t; + TYPEDEF _Reg register_t; + + TYPEDEF signed char int8_t; +-TYPEDEF short int16_t; +-TYPEDEF int int32_t; +-TYPEDEF _Int64 int64_t; +-TYPEDEF _Int64 intmax_t; ++TYPEDEF signed short int16_t; ++TYPEDEF signed int int32_t; ++TYPEDEF signed _Int64 int64_t; ++TYPEDEF signed _Int64 intmax_t; + TYPEDEF unsigned char uint8_t; + TYPEDEF unsigned short uint16_t; + TYPEDEF unsigned int uint32_t; +diff --git a/include/elf.h b/include/elf.h +index e79915fe..c2297353 100644 +--- a/include/elf.h ++++ b/include/elf.h +@@ -623,6 +623,7 @@ typedef struct { + + + #define NT_PRSTATUS 1 ++#define NT_PRFPREG 2 + #define NT_FPREGSET 2 + #define NT_PRPSINFO 3 + #define NT_PRXREG 4 +@@ -644,6 +645,19 @@ typedef struct { + #define NT_PPC_VMX 0x100 + #define NT_PPC_SPE 0x101 + #define NT_PPC_VSX 0x102 ++#define NT_PPC_TAR 0x103 ++#define NT_PPC_PPR 0x104 ++#define NT_PPC_DSCR 0x105 ++#define NT_PPC_EBB 0x106 ++#define NT_PPC_PMU 0x107 ++#define NT_PPC_TM_CGPR 0x108 ++#define NT_PPC_TM_CFPR 0x109 ++#define NT_PPC_TM_CVMX 0x10a ++#define NT_PPC_TM_CVSX 0x10b ++#define NT_PPC_TM_SPR 0x10c ++#define NT_PPC_TM_CTAR 0x10d ++#define NT_PPC_TM_CPPR 0x10e ++#define NT_PPC_TM_CDSCR 0x10f + #define NT_386_TLS 0x200 + #define NT_386_IOPERM 0x201 + #define NT_X86_XSTATE 0x202 +@@ -656,14 +670,21 @@ typedef struct { + #define NT_S390_LAST_BREAK 0x306 + #define NT_S390_SYSTEM_CALL 0x307 + #define NT_S390_TDB 0x308 ++#define NT_S390_VXRS_LOW 0x309 ++#define NT_S390_VXRS_HIGH 0x30a ++#define NT_S390_GS_CB 0x30b ++#define NT_S390_GS_BC 0x30c ++#define NT_S390_RI_CB 0x30d + #define NT_ARM_VFP 0x400 + #define NT_ARM_TLS 0x401 + #define NT_ARM_HW_BREAK 0x402 + #define NT_ARM_HW_WATCH 0x403 + #define NT_ARM_SYSTEM_CALL 0x404 ++#define NT_ARM_SVE 0x405 + #define NT_METAG_CBUF 0x500 + #define NT_METAG_RPIPE 0x501 + #define NT_METAG_TLS 0x502 ++#define NT_ARC_V2 0x600 + #define NT_VERSION 1 + + +@@ -721,7 +742,8 @@ typedef struct { + #define DT_ENCODING 32 + #define DT_PREINIT_ARRAY 32 + #define DT_PREINIT_ARRAYSZ 33 +-#define DT_NUM 34 ++#define DT_SYMTAB_SHNDX 34 ++#define DT_NUM 35 + #define DT_LOOS 0x6000000d + #define DT_HIOS 0x6ffff000 + #define DT_LOPROC 0x70000000 +@@ -821,6 +843,8 @@ typedef struct { + #define DF_1_SYMINTPOSE 0x00800000 + #define DF_1_GLOBAUDIT 0x01000000 + #define DF_1_SINGLETON 0x02000000 ++#define DF_1_STUB 0x04000000 ++#define DF_1_PIE 0x08000000 + + #define DTF_1_PARINIT 0x00000001 + #define DTF_1_CONFEXP 0x00000002 +@@ -1002,6 +1026,14 @@ typedef struct { + #define AT_L2_CACHESHAPE 36 + #define AT_L3_CACHESHAPE 37 + ++#define AT_L1I_CACHESIZE 40 ++#define AT_L1I_CACHEGEOMETRY 41 ++#define AT_L1D_CACHESIZE 42 ++#define AT_L1D_CACHEGEOMETRY 43 ++#define AT_L2_CACHESIZE 44 ++#define AT_L2_CACHEGEOMETRY 45 ++#define AT_L3_CACHESIZE 46 ++#define AT_L3_CACHEGEOMETRY 47 + + + +@@ -1097,7 +1129,25 @@ typedef struct { + #define R_68K_GLOB_DAT 20 + #define R_68K_JMP_SLOT 21 + #define R_68K_RELATIVE 22 +-#define R_68K_NUM 23 ++#define R_68K_TLS_GD32 25 ++#define R_68K_TLS_GD16 26 ++#define R_68K_TLS_GD8 27 ++#define R_68K_TLS_LDM32 28 ++#define R_68K_TLS_LDM16 29 ++#define R_68K_TLS_LDM8 30 ++#define R_68K_TLS_LDO32 31 ++#define R_68K_TLS_LDO16 32 ++#define R_68K_TLS_LDO8 33 ++#define R_68K_TLS_IE32 34 ++#define R_68K_TLS_IE16 35 ++#define R_68K_TLS_IE8 36 ++#define R_68K_TLS_LE32 37 ++#define R_68K_TLS_LE16 38 ++#define R_68K_TLS_LE8 39 ++#define R_68K_TLS_DTPMOD32 40 ++#define R_68K_TLS_DTPREL32 41 ++#define R_68K_TLS_TPREL32 42 ++#define R_68K_NUM 43 + + #define R_386_NONE 0 + #define R_386_32 1 +@@ -2233,6 +2283,7 @@ enum + + #define PPC64_OPT_TLS 1 + #define PPC64_OPT_MULTI_TOC 2 ++#define PPC64_OPT_LOCALENTRY 4 + + #define STO_PPC64_LOCAL_BIT 5 + #define STO_PPC64_LOCAL_MASK 0xe0 +diff --git a/include/limits.h b/include/limits.h +index f9805a1e..ab163a22 100644 +--- a/include/limits.h ++++ b/include/limits.h +@@ -40,14 +40,9 @@ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) + + #define PIPE_BUF 4096 +-#ifdef PAGE_SIZE +-#define PAGESIZE PAGE_SIZE +-#endif + #define FILESIZEBITS 64 + #define NAME_MAX 255 +-#define SYMLINK_MAX 255 + #define PATH_MAX 4096 +-#define NZERO 20 + #define NGROUPS_MAX 32 + #define ARG_MAX 131072 + #define IOV_MAX 1024 +@@ -82,13 +77,22 @@ + #define RE_DUP_MAX 255 + + #define NL_ARGMAX 9 +-#define NL_LANGMAX 32 + #define NL_MSGMAX 32767 + #define NL_SETMAX 255 + #define NL_TEXTMAX 2048 + + #endif + ++#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE) ++ ++#ifdef PAGESIZE ++#define PAGE_SIZE PAGESIZE ++#endif ++#define NZERO 20 ++#define NL_LANGMAX 32 ++ ++#endif ++ + #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) \ + || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE+0 < 700) + +diff --git a/include/math.h b/include/math.h +index 6ac91da2..fea34686 100644 +--- a/include/math.h ++++ b/include/math.h +@@ -27,7 +27,7 @@ extern "C" { + #define MATH_ERREXCEPT 2 + #define math_errhandling 2 + +-#define FP_ILOGBNAN (-1-(int)(((unsigned)-1)>>1)) ++#define FP_ILOGBNAN (-1-0x7fffffff) + #define FP_ILOGB0 FP_ILOGBNAN + + #define FP_NAN 0 +diff --git a/include/net/if_arp.h b/include/net/if_arp.h +index c832ff95..27becc83 100644 +--- a/include/net/if_arp.h ++++ b/include/net/if_arp.h +@@ -59,6 +59,7 @@ struct arphdr { + #define ARPHRD_LAPB 516 + #define ARPHRD_DDCMP 517 + #define ARPHRD_RAWHDLC 518 ++#define ARPHRD_RAWIP 519 + + #define ARPHRD_TUNNEL 768 + #define ARPHRD_TUNNEL6 769 +diff --git a/include/netinet/if_ether.h b/include/netinet/if_ether.h +index 97134d75..ecd6c73c 100644 +--- a/include/netinet/if_ether.h ++++ b/include/netinet/if_ether.h +@@ -5,6 +5,7 @@ + #include <sys/types.h> + + #define ETH_ALEN 6 ++#define ETH_TLEN 2 + #define ETH_HLEN 14 + #define ETH_ZLEN 60 + #define ETH_DATA_LEN 1500 +@@ -17,6 +18,7 @@ + #define ETH_P_PUP 0x0200 + #define ETH_P_PUPAT 0x0201 + #define ETH_P_TSN 0x22F0 ++#define ETH_P_ERSPAN2 0x22EB + #define ETH_P_IP 0x0800 + #define ETH_P_X25 0x0805 + #define ETH_P_ARP 0x0806 +@@ -53,6 +55,8 @@ + #define ETH_P_AOE 0x88A2 + #define ETH_P_8021AD 0x88A8 + #define ETH_P_802_EX1 0x88B5 ++#define ETH_P_ERSPAN 0x88BE ++#define ETH_P_PREAUTH 0x88C7 + #define ETH_P_TIPC 0x88CA + #define ETH_P_MACSEC 0x88E5 + #define ETH_P_8021AH 0x88E7 +@@ -66,11 +70,13 @@ + #define ETH_P_IBOE 0x8915 + #define ETH_P_80221 0x8917 + #define ETH_P_HSR 0x892F ++#define ETH_P_NSH 0x894F + #define ETH_P_LOOPBACK 0x9000 + #define ETH_P_QINQ1 0x9100 + #define ETH_P_QINQ2 0x9200 + #define ETH_P_QINQ3 0x9300 + #define ETH_P_EDSA 0xDADA ++#define ETH_P_IFE 0xED3E + #define ETH_P_AF_IUCV 0xFBFB + + #define ETH_P_802_3_MIN 0x0600 +@@ -100,6 +106,7 @@ + #define ETH_P_IEEE802154 0x00F6 + #define ETH_P_CAIF 0x00F7 + #define ETH_P_XDSA 0x00F8 ++#define ETH_P_MAP 0x00F9 + + struct ethhdr { + uint8_t h_dest[ETH_ALEN]; +diff --git a/include/netinet/in.h b/include/netinet/in.h +index f18b478d..192679a6 100644 +--- a/include/netinet/in.h ++++ b/include/netinet/in.h +@@ -363,6 +363,7 @@ struct ip6_mtuinfo { + #define IPV6_TRANSPARENT 75 + #define IPV6_UNICAST_IF 76 + #define IPV6_RECVFRAGSIZE 77 ++#define IPV6_FREEBIND 78 + + #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP + #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP +diff --git a/include/netinet/tcp.h b/include/netinet/tcp.h +index 4d20936a..1e2acfbf 100644 +--- a/include/netinet/tcp.h ++++ b/include/netinet/tcp.h +@@ -34,6 +34,8 @@ + #define TCP_FASTOPEN_CONNECT 30 + #define TCP_ULP 31 + #define TCP_MD5SIG_EXT 32 ++#define TCP_FASTOPEN_KEY 33 ++#define TCP_FASTOPEN_NO_COOKIE 34 + + #define TCP_ESTABLISHED 1 + #define TCP_SYN_SENT 2 +@@ -54,6 +56,16 @@ enum { + TCP_NLA_SNDBUF_LIMITED, + TCP_NLA_DATA_SEGS_OUT, + TCP_NLA_TOTAL_RETRANS, ++ TCP_NLA_PACING_RATE, ++ TCP_NLA_DELIVERY_RATE, ++ TCP_NLA_SND_CWND, ++ TCP_NLA_REORDERING, ++ TCP_NLA_MIN_RTT, ++ TCP_NLA_RECUR_RETRANS, ++ TCP_NLA_DELIVERY_RATE_APP_LMT, ++ TCP_NLA_SNDQ_SIZE, ++ TCP_NLA_CA_STATE, ++ TCP_NLA_SND_SSTHRESH, + }; + + #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +@@ -220,6 +232,14 @@ struct tcp_md5sig { + uint8_t tcpm_key[TCP_MD5SIG_MAXKEYLEN]; + }; + ++struct tcp_diag_md5sig { ++ uint8_t tcpm_family; ++ uint8_t tcpm_prefixlen; ++ uint16_t tcpm_keylen; ++ uint32_t tcpm_addr[4]; ++ uint8_t tcpm_key[TCP_MD5SIG_MAXKEYLEN]; ++}; ++ + struct tcp_repair_window { + uint32_t snd_wl1; + uint32_t snd_wnd; +diff --git a/include/signal.h b/include/signal.h +index 2c8b3d55..a4f85cca 100644 +--- a/include/signal.h ++++ b/include/signal.h +@@ -210,7 +210,7 @@ int sigpending(sigset_t *); + int sigwait(const sigset_t *__restrict, int *__restrict); + int sigwaitinfo(const sigset_t *__restrict, siginfo_t *__restrict); + int sigtimedwait(const sigset_t *__restrict, siginfo_t *__restrict, const struct timespec *__restrict); +-int sigqueue(pid_t, int, const union sigval); ++int sigqueue(pid_t, int, union sigval); + + int pthread_sigmask(int, const sigset_t *__restrict, sigset_t *__restrict); + int pthread_kill(pthread_t, int); +@@ -231,6 +231,8 @@ int sigrelse(int); + void (*sigset(int, void (*)(int)))(int); + #define TRAP_BRKPT 1 + #define TRAP_TRACE 2 ++#define TRAP_BRANCH 3 ++#define TRAP_HWBKPT 4 + #define POLL_IN 1 + #define POLL_OUT 2 + #define POLL_MSG 3 +diff --git a/include/stdio.h b/include/stdio.h +index 7c4f9ee4..afadd912 100644 +--- a/include/stdio.h ++++ b/include/stdio.h +@@ -49,6 +49,7 @@ extern "C" { + + typedef union _G_fpos64_t { + char __opaque[16]; ++ long long __lldata; + double __align; + } fpos_t; + +diff --git a/include/stdlib.h b/include/stdlib.h +index 42ca8336..4bbaded0 100644 +--- a/include/stdlib.h ++++ b/include/stdlib.h +@@ -39,14 +39,18 @@ void *malloc (size_t); + void *calloc (size_t, size_t); + void *realloc (void *, size_t); + void free (void *); ++#if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L + void *aligned_alloc(size_t, size_t); ++#endif + + _Noreturn void abort (void); + int atexit (void (*) (void)); + _Noreturn void exit (int); + _Noreturn void _Exit (int); ++#if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L + int at_quick_exit (void (*) (void)); + _Noreturn void quick_exit (int); ++#endif + + char *getenv (const char *); + +@@ -100,7 +104,6 @@ int posix_memalign (void **, size_t, size_t); + int setenv (const char *, const char *, int); + int unsetenv (const char *); + int mkstemp (char *); +-int mkostemp (char *, int); + char *mkdtemp (char *); + int getsubopt (char **, char *const *, char **); + int rand_r (unsigned *); +@@ -138,6 +141,7 @@ void lcong48 (unsigned short [7]); + #include <alloca.h> + char *mktemp (char *); + int mkstemps (char *, int); ++int mkostemp (char *, int); + int mkostemps (char *, int, int); + void *valloc (size_t); + void *memalign(size_t, size_t); +diff --git a/include/string.h b/include/string.h +index ce1dc300..795a2abc 100644 +--- a/include/string.h ++++ b/include/string.h +@@ -82,6 +82,7 @@ void *memccpy (void *__restrict, const void *__restrict, int, size_t); + char *strsep(char **, const char *); + size_t strlcat (char *, const char *, size_t); + size_t strlcpy (char *, const char *, size_t); ++void explicit_bzero (void *, size_t); + #endif + + #ifdef _GNU_SOURCE +diff --git a/include/sys/epoll.h b/include/sys/epoll.h +index ffe2311f..ac81a841 100644 +--- a/include/sys/epoll.h ++++ b/include/sys/epoll.h +@@ -21,6 +21,7 @@ enum EPOLL_EVENTS { __EPOLL_DUMMY }; + #define EPOLLPRI 0x002 + #define EPOLLOUT 0x004 + #define EPOLLRDNORM 0x040 ++#define EPOLLNVAL 0x020 + #define EPOLLRDBAND 0x080 + #define EPOLLWRNORM 0x100 + #define EPOLLWRBAND 0x200 +diff --git a/include/sys/kd.h b/include/sys/kd.h +index 793fd59f..42122b9c 100644 +--- a/include/sys/kd.h ++++ b/include/sys/kd.h +@@ -1,8 +1 @@ +-#ifndef _SYS_KD_H +-#define _SYS_KD_H +- +-#define _LINUX_TYPES_H +-#include <linux/kd.h> +-#undef _LINUX_TYPES_H +- +-#endif ++#include <bits/kd.h> +diff --git a/include/sys/mman.h b/include/sys/mman.h +index 8a5149c9..99d02a2e 100644 +--- a/include/sys/mman.h ++++ b/include/sys/mman.h +@@ -20,6 +20,7 @@ extern "C" { + + #define MAP_SHARED 0x01 + #define MAP_PRIVATE 0x02 ++#define MAP_SHARED_VALIDATE 0x03 + #define MAP_TYPE 0x0f + #define MAP_FIXED 0x10 + #define MAP_ANON 0x20 +@@ -33,8 +34,23 @@ extern "C" { + #define MAP_NONBLOCK 0x10000 + #define MAP_STACK 0x20000 + #define MAP_HUGETLB 0x40000 ++#define MAP_SYNC 0x80000 ++#define MAP_FIXED_NOREPLACE 0x100000 + #define MAP_FILE 0 + ++#define MAP_HUGE_SHIFT 26 ++#define MAP_HUGE_MASK 0x3f ++#define MAP_HUGE_64KB (16 << 26) ++#define MAP_HUGE_512KB (19 << 26) ++#define MAP_HUGE_1MB (20 << 26) ++#define MAP_HUGE_2MB (21 << 26) ++#define MAP_HUGE_8MB (23 << 26) ++#define MAP_HUGE_16MB (24 << 26) ++#define MAP_HUGE_256MB (28 << 26) ++#define MAP_HUGE_1GB (30 << 26) ++#define MAP_HUGE_2GB (31 << 26) ++#define MAP_HUGE_16GB (34U << 26) ++ + #define PROT_NONE 0 + #define PROT_READ 1 + #define PROT_WRITE 2 +@@ -72,10 +88,23 @@ extern "C" { + #define MADV_NOHUGEPAGE 15 + #define MADV_DONTDUMP 16 + #define MADV_DODUMP 17 ++#define MADV_WIPEONFORK 18 ++#define MADV_KEEPONFORK 19 + #define MADV_HWPOISON 100 + #define MADV_SOFT_OFFLINE 101 + #endif + ++#ifdef _GNU_SOURCE ++#define MREMAP_MAYMOVE 1 ++#define MREMAP_FIXED 2 ++ ++#define MLOCK_ONFAULT 0x01 ++ ++#define MFD_CLOEXEC 0x0001U ++#define MFD_ALLOW_SEALING 0x0002U ++#define MFD_HUGETLB 0x0004U ++#endif ++ + #include <bits/mman.h> + + void *mmap (void *, size_t, int, int, int, off_t); +@@ -92,14 +121,13 @@ int mlockall (int); + int munlockall (void); + + #ifdef _GNU_SOURCE +-#define MREMAP_MAYMOVE 1 +-#define MREMAP_FIXED 2 + void *mremap (void *, size_t, size_t, int, ...); + int remap_file_pages (void *, size_t, int, size_t, int); ++int memfd_create (const char *, unsigned); ++int mlock2 (const void *, size_t, unsigned); + #endif + + #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +-#define MLOCK_ONFAULT 0x01 + int madvise (void *, size_t, int); + int mincore (void *, size_t, unsigned char *); + #endif +diff --git a/include/sys/msg.h b/include/sys/msg.h +index 139f22b7..be6afc34 100644 +--- a/include/sys/msg.h ++++ b/include/sys/msg.h +@@ -27,6 +27,7 @@ typedef unsigned long msglen_t; + + #define MSG_STAT 11 + #define MSG_INFO 12 ++#define MSG_STAT_ANY 13 + + struct msginfo { + int msgpool, msgmap, msgmax, msgmnb, msgmni, msgssz, msgtql; +diff --git a/include/sys/prctl.h b/include/sys/prctl.h +index 24f4f8bd..af76408c 100644 +--- a/include/sys/prctl.h ++++ b/include/sys/prctl.h +@@ -130,6 +130,21 @@ struct prctl_mm_map { + #define PR_CAP_AMBIENT_LOWER 3 + #define PR_CAP_AMBIENT_CLEAR_ALL 4 + ++#define PR_SVE_SET_VL 50 ++#define PR_SVE_SET_VL_ONEXEC (1 << 18) ++#define PR_SVE_GET_VL 51 ++#define PR_SVE_VL_LEN_MASK 0xffff ++#define PR_SVE_VL_INHERIT (1 << 17) ++ ++#define PR_GET_SPECULATION_CTRL 52 ++#define PR_SET_SPECULATION_CTRL 53 ++#define PR_SPEC_STORE_BYPASS 0 ++#define PR_SPEC_NOT_AFFECTED 0 ++#define PR_SPEC_PRCTL (1UL << 0) ++#define PR_SPEC_ENABLE (1UL << 1) ++#define PR_SPEC_DISABLE (1UL << 2) ++#define PR_SPEC_FORCE_DISABLE (1UL << 3) ++ + int prctl (int, ...); + + #ifdef __cplusplus +diff --git a/include/sys/ptrace.h b/include/sys/ptrace.h +index d9d45408..229e1f3d 100644 +--- a/include/sys/ptrace.h ++++ b/include/sys/ptrace.h +@@ -40,6 +40,7 @@ extern "C" { + #define PTRACE_GETSIGMASK 0x420a + #define PTRACE_SETSIGMASK 0x420b + #define PTRACE_SECCOMP_GET_FILTER 0x420c ++#define PTRACE_SECCOMP_GET_METADATA 0x420d + + #define PT_READ_I PTRACE_PEEKTEXT + #define PT_READ_D PTRACE_PEEKDATA +@@ -83,15 +84,23 @@ extern "C" { + #define PTRACE_EVENT_VFORK_DONE 5 + #define PTRACE_EVENT_EXIT 6 + #define PTRACE_EVENT_SECCOMP 7 ++#define PTRACE_EVENT_STOP 128 + + #define PTRACE_PEEKSIGINFO_SHARED 1 + +-struct ptrace_peeksiginfo_args { ++#include <bits/ptrace.h> ++ ++struct __ptrace_peeksiginfo_args { + uint64_t off; + uint32_t flags; + int32_t nr; + }; + ++struct __ptrace_seccomp_metadata { ++ uint64_t filter_off; ++ uint64_t flags; ++}; ++ + long ptrace(int, ...); + + #ifdef __cplusplus +diff --git a/include/sys/random.h b/include/sys/random.h +new file mode 100644 +index 00000000..4ee7bf2c +--- /dev/null ++++ b/include/sys/random.h +@@ -0,0 +1,19 @@ ++#ifndef _SYS_RANDOM_H ++#define _SYS_RANDOM_H ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define __NEED_size_t ++#define __NEED_ssize_t ++#include <bits/alltypes.h> ++ ++#define GRND_NONBLOCK 0x0001 ++#define GRND_RANDOM 0x0002 ++ ++ssize_t getrandom(void *, size_t, unsigned); ++ ++#ifdef __cplusplus ++} ++#endif ++#endif +diff --git a/include/sys/sem.h b/include/sys/sem.h +index e7c36980..61cdb83d 100644 +--- a/include/sys/sem.h ++++ b/include/sys/sem.h +@@ -33,6 +33,7 @@ extern "C" { + + #define SEM_STAT 18 + #define SEM_INFO 19 ++#define SEM_STAT_ANY 20 + + struct seminfo { + int semmap; +diff --git a/include/sys/shm.h b/include/sys/shm.h +index 67be822b..662fde59 100644 +--- a/include/sys/shm.h ++++ b/include/sys/shm.h +@@ -35,11 +35,25 @@ extern "C" { + #define SHM_UNLOCK 12 + #define SHM_STAT 13 + #define SHM_INFO 14 ++#define SHM_STAT_ANY 15 + #define SHM_DEST 01000 + #define SHM_LOCKED 02000 + #define SHM_HUGETLB 04000 + #define SHM_NORESERVE 010000 + ++#define SHM_HUGE_SHIFT 26 ++#define SHM_HUGE_MASK 0x3f ++#define SHM_HUGE_64KB (16 << 26) ++#define SHM_HUGE_512KB (19 << 26) ++#define SHM_HUGE_1MB (20 << 26) ++#define SHM_HUGE_2MB (21 << 26) ++#define SHM_HUGE_8MB (23 << 26) ++#define SHM_HUGE_16MB (24 << 26) ++#define SHM_HUGE_256MB (28 << 26) ++#define SHM_HUGE_1GB (30 << 26) ++#define SHM_HUGE_2GB (31 << 26) ++#define SHM_HUGE_16GB (34U << 26) ++ + typedef unsigned long shmatt_t; + + void *shmat(int, const void *, int); +diff --git a/include/sys/socket.h b/include/sys/socket.h +index 051d20e0..14be6e99 100644 +--- a/include/sys/socket.h ++++ b/include/sys/socket.h +@@ -108,7 +108,8 @@ struct linger { + #define PF_VSOCK 40 + #define PF_KCM 41 + #define PF_QIPCRTR 42 +-#define PF_MAX 43 ++#define PF_SMC 43 ++#define PF_MAX 44 + + #define AF_UNSPEC PF_UNSPEC + #define AF_LOCAL PF_LOCAL +@@ -156,6 +157,7 @@ struct linger { + #define AF_VSOCK PF_VSOCK + #define AF_KCM PF_KCM + #define AF_QIPCRTR PF_QIPCRTR ++#define AF_SMC PF_SMC + #define AF_MAX PF_MAX + + #ifndef SO_DEBUG +@@ -181,6 +183,7 @@ struct linger { + #define SO_RCVTIMEO 20 + #define SO_SNDTIMEO 21 + #define SO_ACCEPTCONN 30 ++#define SO_PEERSEC 31 + #define SO_SNDBUFFORCE 32 + #define SO_RCVBUFFORCE 33 + #define SO_PROTOCOL 38 +@@ -201,7 +204,6 @@ struct linger { + #define SO_TIMESTAMP 29 + #define SCM_TIMESTAMP SO_TIMESTAMP + +-#define SO_PEERSEC 31 + #define SO_PASSSEC 34 + #define SO_TIMESTAMPNS 35 + #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +@@ -230,6 +232,7 @@ struct linger { + #define SO_COOKIE 57 + #define SCM_TIMESTAMPING_PKTINFO 58 + #define SO_PEERGROUPS 59 ++#define SO_ZEROCOPY 60 + + #ifndef SOL_SOCKET + #define SOL_SOCKET 1 +@@ -261,6 +264,7 @@ struct linger { + #define SOL_ALG 279 + #define SOL_NFC 280 + #define SOL_KCM 281 ++#define SOL_TLS 282 + + #define SOMAXCONN 128 + +@@ -282,6 +286,7 @@ struct linger { + #define MSG_MORE 0x8000 + #define MSG_WAITFORONE 0x10000 + #define MSG_BATCH 0x40000 ++#define MSG_ZEROCOPY 0x4000000 + #define MSG_FASTOPEN 0x20000000 + #define MSG_CMSG_CLOEXEC 0x40000000 + +diff --git a/include/sys/soundcard.h b/include/sys/soundcard.h +index fade986f..5ca77646 100644 +--- a/include/sys/soundcard.h ++++ b/include/sys/soundcard.h +@@ -1 +1 @@ +-#include <linux/soundcard.h> ++#include <bits/soundcard.h> +diff --git a/include/sys/statvfs.h b/include/sys/statvfs.h +index e0839eca..ef07d684 100644 +--- a/include/sys/statvfs.h ++++ b/include/sys/statvfs.h +@@ -42,6 +42,7 @@ int fstatvfs (int, struct statvfs *); + #define ST_IMMUTABLE 512 + #define ST_NOATIME 1024 + #define ST_NODIRATIME 2048 ++#define ST_RELATIME 4096 + + #if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) + #define statvfs64 statvfs +diff --git a/include/sys/vt.h b/include/sys/vt.h +index 834abfbc..5000de49 100644 +--- a/include/sys/vt.h ++++ b/include/sys/vt.h +@@ -1 +1 @@ +-#include <linux/vt.h> ++#include <bits/vt.h> +diff --git a/include/tar.h b/include/tar.h +index be589842..2eba66ec 100644 +--- a/include/tar.h ++++ b/include/tar.h +@@ -1,9 +1,13 @@ + #ifndef _TAR_H + #define _TAR_H + ++#include <features.h> ++ + #define TSUID 04000 + #define TSGID 02000 ++#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE) + #define TSVTX 01000 ++#endif + #define TUREAD 00400 + #define TUWRITE 00200 + #define TUEXEC 00100 +diff --git a/include/time.h b/include/time.h +index 672b3fc3..c5946dd0 100644 +--- a/include/time.h ++++ b/include/time.h +@@ -58,11 +58,14 @@ struct tm *gmtime (const time_t *); + struct tm *localtime (const time_t *); + char *asctime (const struct tm *); + char *ctime (const time_t *); +-int timespec_get(struct timespec *, int); + +-#define CLOCKS_PER_SEC 1000000L ++#if __STDC_VERSION__ >= 201112L ++int timespec_get(struct timespec *, int); + + #define TIME_UTC 1 ++#endif ++ ++#define CLOCKS_PER_SEC 1000000L + + #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ +diff --git a/include/uchar.h b/include/uchar.h +index 8dabf1ed..7e5c4d40 100644 +--- a/include/uchar.h ++++ b/include/uchar.h +@@ -3,7 +3,9 @@ + + #ifdef __cplusplus + extern "C" { +-#else ++#endif ++ ++#if __cplusplus < 201103L + typedef unsigned short char16_t; + typedef unsigned char32_t; + #endif +diff --git a/include/unistd.h b/include/unistd.h +index 09190af4..1bdd3292 100644 +--- a/include/unistd.h ++++ b/include/unistd.h +@@ -128,12 +128,11 @@ long fpathconf(int, int); + long sysconf(int); + size_t confstr(int, char *, size_t); + ++#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) + #define F_ULOCK 0 + #define F_LOCK 1 + #define F_TLOCK 2 + #define F_TEST 3 +- +-#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) + int setreuid(uid_t, uid_t); + int setregid(gid_t, gid_t); + int lockf(int, int, off_t); +@@ -176,6 +175,7 @@ int acct(const char *); + long syscall(long, ...); + int execvpe(const char *, char *const [], char *const []); + int issetugid(void); ++int getentropy(void *, size_t); + #endif + + #ifdef _GNU_SOURCE +@@ -274,6 +274,7 @@ int eaccess(const char *, int); + #define _PC_ALLOC_SIZE_MIN 18 + #define _PC_SYMLINK_MAX 19 + #define _PC_2_SYMLINKS 20 ++#define _PC_TIMESTAMP_RESOLUTION 21 + + #define _SC_ARG_MAX 0 + #define _SC_CHILD_MAX 1 +@@ -417,6 +418,7 @@ int eaccess(const char *, int); + #define _SC_XOPEN_STREAMS 246 + #define _SC_THREAD_ROBUST_PRIO_INHERIT 247 + #define _SC_THREAD_ROBUST_PRIO_PROTECT 248 ++#define _SC_XOPEN_UUCP 249 + + #define _CS_PATH 0 + #define _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS 1 +@@ -459,6 +461,8 @@ int eaccess(const char *, int); + #define _CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS 1147 + #define _CS_V6_ENV 1148 + #define _CS_V7_ENV 1149 ++#define _CS_POSIX_V7_THREADS_CFLAGS 1150 ++#define _CS_POSIX_V7_THREADS_LDFLAGS 1151 + + #ifdef __cplusplus + } +diff --git a/ldso/dynlink.c b/ldso/dynlink.c +index 9bf6924b..87281ddb 100644 +--- a/ldso/dynlink.c ++++ b/ldso/dynlink.c +@@ -133,6 +133,9 @@ static struct dso *const nodeps_dummy; + + struct debug *_dl_debug_addr = &debug; + ++__attribute__((__visibility__("hidden"))) ++extern int __malloc_replaced; ++ + __attribute__((__visibility__("hidden"))) + void (*const __init_array_start)(void)=0, (*const __fini_array_start)(void)=0; + +@@ -158,10 +161,26 @@ static void *laddr(const struct dso *p, size_t v) + for (j=0; v-p->loadmap->segs[j].p_vaddr >= p->loadmap->segs[j].p_memsz; j++); + return (void *)(v - p->loadmap->segs[j].p_vaddr + p->loadmap->segs[j].addr); + } ++static void *laddr_pg(const struct dso *p, size_t v) ++{ ++ size_t j=0; ++ size_t pgsz = PAGE_SIZE; ++ if (!p->loadmap) return p->base + v; ++ for (j=0; ; j++) { ++ size_t a = p->loadmap->segs[j].p_vaddr; ++ size_t b = a + p->loadmap->segs[j].p_memsz; ++ a &= -pgsz; ++ b += pgsz-1; ++ b &= -pgsz; ++ if (v-a<b-a) break; ++ } ++ return (void *)(v - p->loadmap->segs[j].p_vaddr + p->loadmap->segs[j].addr); ++} + #define fpaddr(p, v) ((void (*)())&(struct funcdesc){ \ + laddr(p, v), (p)->got }) + #else + #define laddr(p, v) (void *)((p)->base + (v)) ++#define laddr_pg(p, v) laddr(p, v) + #define fpaddr(p, v) ((void (*)())laddr(p, v)) + #endif + +@@ -366,6 +385,14 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri + sym_val = def.sym ? (size_t)laddr(def.dso, def.sym->st_value) : 0; + tls_val = def.sym ? def.sym->st_value : 0; + ++ if ((type == REL_TPOFF || type == REL_TPOFF_NEG) ++ && runtime && def.dso->tls_id > static_tls_cnt) { ++ error("Error relocating %s: %s: initial-exec TLS " ++ "resolves to dynamic definition in %s", ++ dso->name, name, def.dso->name); ++ longjmp(*rtld_fail, 1); ++ } ++ + switch(type) { + case REL_NONE: + break; +@@ -419,7 +446,7 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri + #endif + case REL_TLSDESC: + if (stride<3) addend = reloc_addr[1]; +- if (runtime && def.dso->tls_id >= static_tls_cnt) { ++ if (runtime && def.dso->tls_id > static_tls_cnt) { + struct td_index *new = malloc(sizeof *new); + if (!new) { + error( +@@ -476,23 +503,16 @@ static void redo_lazy_relocs() + /* A huge hack: to make up for the wastefulness of shared libraries + * needing at least a page of dirty memory even if they have no global + * data, we reclaim the gaps at the beginning and end of writable maps +- * and "donate" them to the heap by setting up minimal malloc +- * structures and then freeing them. */ ++ * and "donate" them to the heap. */ + + static void reclaim(struct dso *dso, size_t start, size_t end) + { +- size_t *a, *z; ++ void __malloc_donate(char *, char *); + if (start >= dso->relro_start && start < dso->relro_end) start = dso->relro_end; + if (end >= dso->relro_start && end < dso->relro_end) end = dso->relro_start; +- start = start + 6*sizeof(size_t)-1 & -4*sizeof(size_t); +- end = (end & -4*sizeof(size_t)) - 2*sizeof(size_t); +- if (start>end || end-start < 4*sizeof(size_t)) return; +- a = laddr(dso, start); +- z = laddr(dso, end); +- a[-2] = 1; +- a[-1] = z[0] = end-start + 2*sizeof(size_t) | 1; +- z[1] = 1; +- free(a); ++ if (start >= end) return; ++ char *base = laddr_pg(dso, start); ++ __malloc_donate(base, base+(end-start)); + } + + static void reclaim_gaps(struct dso *dso) +@@ -500,7 +520,6 @@ static void reclaim_gaps(struct dso *dso) + Phdr *ph = dso->phdr; + size_t phcnt = dso->phnum; + +- if (DL_FDPIC) return; // FIXME + for (; phcnt--; ph=(void *)((char *)ph+dso->phentsize)) { + if (ph->p_type!=PT_LOAD) continue; + if ((ph->p_flags&(PF_R|PF_W))!=(PF_R|PF_W)) continue; +@@ -695,18 +714,17 @@ static void *map_library(int fd, struct dso *dso) + dso->phnum = eh->e_phnum; + dso->phentsize = eh->e_phentsize; + } +- /* Reuse the existing mapping for the lowest-address LOAD */ +- if ((ph->p_vaddr & -PAGE_SIZE) == addr_min && !DL_NOMMU_SUPPORT) +- continue; + this_min = ph->p_vaddr & -PAGE_SIZE; + this_max = ph->p_vaddr+ph->p_memsz+PAGE_SIZE-1 & -PAGE_SIZE; + off_start = ph->p_offset & -PAGE_SIZE; + prot = (((ph->p_flags&PF_R) ? PROT_READ : 0) | + ((ph->p_flags&PF_W) ? PROT_WRITE: 0) | + ((ph->p_flags&PF_X) ? PROT_EXEC : 0)); +- if (mmap_fixed(base+this_min, this_max-this_min, prot, MAP_PRIVATE|MAP_FIXED, fd, off_start) == MAP_FAILED) +- goto error; +- if (ph->p_memsz > ph->p_filesz) { ++ /* Reuse the existing mapping for the lowest-address LOAD */ ++ if ((ph->p_vaddr & -PAGE_SIZE) != addr_min || DL_NOMMU_SUPPORT) ++ if (mmap_fixed(base+this_min, this_max-this_min, prot, MAP_PRIVATE|MAP_FIXED, fd, off_start) == MAP_FAILED) ++ goto error; ++ if (ph->p_memsz > ph->p_filesz && (ph->p_flags&PF_W)) { + size_t brk = (size_t)base+ph->p_vaddr+ph->p_filesz; + size_t pgbrk = brk+PAGE_SIZE-1 & -PAGE_SIZE; + memset((void *)brk, 0, pgbrk-brk & PAGE_SIZE-1); +@@ -1583,8 +1601,9 @@ _Noreturn void __dls3(size_t *sp) + libc.tls_head = tls_tail = &app.tls; + app.tls_id = tls_cnt = 1; + #ifdef TLS_ABOVE_TP +- app.tls.offset = 0; +- tls_offset = app.tls.size ++ app.tls.offset = GAP_ABOVE_TP; ++ app.tls.offset += -GAP_ABOVE_TP & (app.tls.align-1); ++ tls_offset = app.tls.offset + app.tls.size + + ( -((uintptr_t)app.tls.image + app.tls.size) + & (app.tls.align-1) ); + #else +@@ -1683,6 +1702,12 @@ _Noreturn void __dls3(size_t *sp) + if (ldso_fail) _exit(127); + if (ldd_mode) _exit(0); + ++ /* Determine if malloc was interposed by a replacement implementation ++ * so that calloc and the memalign family can harden against the ++ * possibility of incomplete replacement. */ ++ if (find_sym(head, "malloc", 1).dso != &ldso) ++ __malloc_replaced = 1; ++ + /* Switch to runtime mode: any further failures in the dynamic + * linker are a reportable failure rather than a fatal startup + * error. */ +@@ -1861,8 +1886,17 @@ static void *addr2dso(size_t a) + return p; + } + } else { ++ Phdr *ph = p->phdr; ++ size_t phcnt = p->phnum; ++ size_t entsz = p->phentsize; ++ size_t base = (size_t)p->base; ++ for (; phcnt--; ph=(void *)((char *)ph+entsz)) { ++ if (ph->p_type != PT_LOAD) continue; ++ if (a-base-ph->p_vaddr < ph->p_memsz) ++ return p; ++ } + if (a-(size_t)p->map < p->map_len) +- return p; ++ return 0; + } + } + return 0; +@@ -1926,16 +1960,18 @@ failed: + return 0; + } + +-int dladdr(const void *addr, Dl_info *info) ++int dladdr(const void *addr_arg, Dl_info *info) + { ++ size_t addr = (size_t)addr_arg; + struct dso *p; + Sym *sym, *bestsym; + uint32_t nsym; + char *strings; +- void *best = 0; ++ size_t best = 0; ++ size_t besterr = -1; + + pthread_rwlock_rdlock(&lock); +- p = addr2dso((size_t)addr); ++ p = addr2dso(addr); + pthread_rwlock_unlock(&lock); + + if (!p) return 0; +@@ -1945,11 +1981,12 @@ int dladdr(const void *addr, Dl_info *info) + nsym = count_syms(p); + + if (DL_FDPIC) { +- size_t idx = ((size_t)addr-(size_t)p->funcdescs) ++ size_t idx = (addr-(size_t)p->funcdescs) + / sizeof(*p->funcdescs); + if (idx < nsym && (sym[idx].st_info&0xf) == STT_FUNC) { +- best = p->funcdescs + idx; ++ best = (size_t)(p->funcdescs + idx); + bestsym = sym + idx; ++ besterr = 0; + } + } + +@@ -1957,25 +1994,35 @@ int dladdr(const void *addr, Dl_info *info) + if (sym->st_value + && (1<<(sym->st_info&0xf) & OK_TYPES) + && (1<<(sym->st_info>>4) & OK_BINDS)) { +- void *symaddr = laddr(p, sym->st_value); +- if (symaddr > addr || symaddr < best) ++ size_t symaddr = (size_t)laddr(p, sym->st_value); ++ if (symaddr > addr || symaddr <= best) + continue; + best = symaddr; + bestsym = sym; ++ besterr = addr - symaddr; + if (addr == symaddr) + break; + } + } + +- if (!best) return 0; +- +- if (DL_FDPIC && (bestsym->st_info&0xf) == STT_FUNC) +- best = p->funcdescs + (bestsym - p->syms); ++ if (bestsym && besterr > bestsym->st_size-1) { ++ best = 0; ++ bestsym = 0; ++ } + + info->dli_fname = p->name; + info->dli_fbase = p->map; ++ ++ if (!best) { ++ info->dli_sname = 0; ++ info->dli_saddr = 0; ++ return 1; ++ } ++ ++ if (DL_FDPIC && (bestsym->st_info&0xf) == STT_FUNC) ++ best = (size_t)(p->funcdescs + (bestsym - p->syms)); + info->dli_sname = strings + bestsym->st_name; +- info->dli_saddr = best; ++ info->dli_saddr = (void *)best; + + return 1; + } +diff --git a/src/complex/casin.c b/src/complex/casin.c +index dfdda988..01ed6184 100644 +--- a/src/complex/casin.c ++++ b/src/complex/casin.c +@@ -12,5 +12,6 @@ double complex casin(double complex z) + x = creal(z); + y = cimag(z); + w = CMPLX(1.0 - (x - y)*(x + y), -2.0*x*y); +- return clog(CMPLX(-y, x) + csqrt(w)); ++ double complex r = clog(CMPLX(-y, x) + csqrt(w)); ++ return CMPLX(cimag(r), -creal(r)); + } +diff --git a/src/complex/casinf.c b/src/complex/casinf.c +index 93f0e335..4fcb76fc 100644 +--- a/src/complex/casinf.c ++++ b/src/complex/casinf.c +@@ -10,5 +10,6 @@ float complex casinf(float complex z) + x = crealf(z); + y = cimagf(z); + w = CMPLXF(1.0 - (x - y)*(x + y), -2.0*x*y); +- return clogf(CMPLXF(-y, x) + csqrtf(w)); ++ float complex r = clogf(CMPLXF(-y, x) + csqrtf(w)); ++ return CMPLXF(cimagf(r), -crealf(r)); + } +diff --git a/src/complex/casinl.c b/src/complex/casinl.c +index 0916c60f..3b7ceba7 100644 +--- a/src/complex/casinl.c ++++ b/src/complex/casinl.c +@@ -15,6 +15,7 @@ long double complex casinl(long double complex z) + x = creall(z); + y = cimagl(z); + w = CMPLXL(1.0 - (x - y)*(x + y), -2.0*x*y); +- return clogl(CMPLXL(-y, x) + csqrtl(w)); ++ long double complex r = clogl(CMPLXL(-y, x) + csqrtl(w)); ++ return CMPLXL(cimagl(r), -creall(r)); + } + #endif +diff --git a/src/complex/catan.c b/src/complex/catan.c +index 39ce6cf2..7dc2afeb 100644 +--- a/src/complex/catan.c ++++ b/src/complex/catan.c +@@ -91,29 +91,17 @@ double complex catan(double complex z) + x = creal(z); + y = cimag(z); + +- if (x == 0.0 && y > 1.0) +- goto ovrf; +- + x2 = x * x; + a = 1.0 - x2 - (y * y); +- if (a == 0.0) +- goto ovrf; + + t = 0.5 * atan2(2.0 * x, a); + w = _redupi(t); + + t = y - 1.0; + a = x2 + (t * t); +- if (a == 0.0) +- goto ovrf; + + t = y + 1.0; + a = (x2 + t * t)/a; +- w = w + (0.25 * log(a)) * I; +- return w; +- +-ovrf: +- // FIXME +- w = MAXNUM + MAXNUM * I; ++ w = CMPLX(w, 0.25 * log(a)); + return w; + } +diff --git a/src/conf/confstr.c b/src/conf/confstr.c +index 02cb1aa2..3d417284 100644 +--- a/src/conf/confstr.c ++++ b/src/conf/confstr.c +@@ -7,7 +7,7 @@ size_t confstr(int name, char *buf, size_t len) + const char *s = ""; + if (!name) { + s = "/bin:/usr/bin"; +- } else if ((name&~4U)!=1 && name-_CS_POSIX_V6_ILP32_OFF32_CFLAGS>33U) { ++ } else if ((name&~4U)!=1 && name-_CS_POSIX_V6_ILP32_OFF32_CFLAGS>35U) { + errno = EINVAL; + return 0; + } +diff --git a/src/conf/fpathconf.c b/src/conf/fpathconf.c +index 8eb037e6..7e4b8003 100644 +--- a/src/conf/fpathconf.c ++++ b/src/conf/fpathconf.c +@@ -24,8 +24,9 @@ long fpathconf(int fd, int name) + [_PC_REC_MIN_XFER_SIZE] = 4096, + [_PC_REC_XFER_ALIGN] = 4096, + [_PC_ALLOC_SIZE_MIN] = 4096, +- [_PC_SYMLINK_MAX] = SYMLINK_MAX, +- [_PC_2_SYMLINKS] = 1 ++ [_PC_SYMLINK_MAX] = -1, ++ [_PC_2_SYMLINKS] = 1, ++ [_PC_TIMESTAMP_RESOLUTION] = 1000000, + }; + if (name >= sizeof(values)/sizeof(values[0])) { + errno = EINVAL; +diff --git a/src/conf/sysconf.c b/src/conf/sysconf.c +index 9ce330a5..58830a09 100644 +--- a/src/conf/sysconf.c ++++ b/src/conf/sysconf.c +@@ -164,6 +164,7 @@ long sysconf(int name) + [_SC_XOPEN_STREAMS] = JT_ZERO, + [_SC_THREAD_ROBUST_PRIO_INHERIT] = -1, + [_SC_THREAD_ROBUST_PRIO_PROTECT] = -1, ++ [_SC_XOPEN_UUCP] = -1, + }; + + if (name >= sizeof(values)/sizeof(values[0]) || !values[name]) { +diff --git a/src/dirent/__dirent.h b/src/dirent/__dirent.h +index 101b0368..828a5f17 100644 +--- a/src/dirent/__dirent.h ++++ b/src/dirent/__dirent.h +@@ -1,9 +1,11 @@ + struct __dirstream + { +- int fd; + off_t tell; ++ int fd; + int buf_pos; + int buf_end; + volatile int lock[1]; ++ /* Any changes to this struct must preserve the property: ++ * offsetof(struct __dirent, buf) % sizeof(off_t) == 0 */ + char buf[2048]; + }; +diff --git a/src/dirent/readdir.c b/src/dirent/readdir.c +index 2cf0632c..eef92f79 100644 +--- a/src/dirent/readdir.c ++++ b/src/dirent/readdir.c +@@ -1,10 +1,12 @@ + #include <dirent.h> + #include <errno.h> ++#include <stddef.h> + #include "__dirent.h" + #include "syscall.h" + #include "libc.h" + +-int __getdents(int, struct dirent *, size_t); ++typedef char dirstream_buf_alignment_check[1-2*(int)( ++ offsetof(struct __dirstream, buf) % sizeof(off_t))]; + + struct dirent *readdir(DIR *dir) + { +diff --git a/src/env/__init_tls.c b/src/env/__init_tls.c +index b125eb1f..31d324a8 100644 +--- a/src/env/__init_tls.c ++++ b/src/env/__init_tls.c +@@ -15,7 +15,8 @@ int __init_tp(void *p) + int r = __set_thread_area(TP_ADJ(p)); + if (r < 0) return -1; + if (!r) libc.can_do_threads = 1; +- td->tid = __syscall(SYS_set_tid_address, &td->tid); ++ td->detach_state = DT_JOINABLE; ++ td->tid = __syscall(SYS_set_tid_address, &td->detach_state); + td->locale = &libc.global_locale; + td->robust_list.head = &td->robust_list.head; + return 0; +@@ -103,13 +104,19 @@ static void static_init_tls(size_t *aux) + + main_tls.size += (-main_tls.size - (uintptr_t)main_tls.image) + & (main_tls.align-1); +- if (main_tls.align < MIN_TLS_ALIGN) main_tls.align = MIN_TLS_ALIGN; +-#ifndef TLS_ABOVE_TP ++#ifdef TLS_ABOVE_TP ++ main_tls.offset = GAP_ABOVE_TP; ++ main_tls.offset += -GAP_ABOVE_TP & (main_tls.align-1); ++#else + main_tls.offset = main_tls.size; + #endif ++ if (main_tls.align < MIN_TLS_ALIGN) main_tls.align = MIN_TLS_ALIGN; + + libc.tls_align = main_tls.align; + libc.tls_size = 2*sizeof(void *) + sizeof(struct pthread) ++#ifdef TLS_ABOVE_TP ++ + main_tls.offset ++#endif + + main_tls.size + main_tls.align + + MIN_TLS_ALIGN-1 & -MIN_TLS_ALIGN; + +diff --git a/src/env/__libc_start_main.c b/src/env/__libc_start_main.c +index 2d758af7..0583f686 100644 +--- a/src/env/__libc_start_main.c ++++ b/src/env/__libc_start_main.c +@@ -42,11 +42,13 @@ void __init_libc(char **envp, char *pn) + && !aux[AT_SECURE]) return; + + struct pollfd pfd[3] = { {.fd=0}, {.fd=1}, {.fd=2} }; ++ int r = + #ifdef SYS_poll + __syscall(SYS_poll, pfd, 3, 0); + #else + __syscall(SYS_ppoll, pfd, 3, &(struct timespec){0}, 0, _NSIG/8); + #endif ++ if (r<0) a_crash(); + for (i=0; i<3; i++) if (pfd[i].revents&POLLNVAL) + if (__sys_open("/dev/null", O_RDWR)<0) + a_crash(); +diff --git a/src/errno/__errno_location.c b/src/errno/__errno_location.c +index 7172a1be..ad9f9241 100644 +--- a/src/errno/__errno_location.c ++++ b/src/errno/__errno_location.c +@@ -1,3 +1,4 @@ ++#include <errno.h> + #include "pthread_impl.h" + + int *__errno_location(void) +diff --git a/src/errno/__strerror.h b/src/errno/__strerror.h +index 915044b5..2f04d400 100644 +--- a/src/errno/__strerror.h ++++ b/src/errno/__strerror.h +@@ -100,5 +100,6 @@ E(EREMOTEIO, "Remote I/O error") + E(EDQUOT, "Quota exceeded") + E(ENOMEDIUM, "No medium found") + E(EMEDIUMTYPE, "Wrong medium type") ++E(EMULTIHOP, "Multihop attempted") + + E(0, "No error information") +diff --git a/src/exit/abort.c b/src/exit/abort.c +index ecc0f735..5e5a87c3 100644 +--- a/src/exit/abort.c ++++ b/src/exit/abort.c +@@ -1,13 +1,31 @@ + #include <stdlib.h> + #include <signal.h> ++#include <string.h> + #include "syscall.h" + #include "pthread_impl.h" + #include "atomic.h" + + _Noreturn void abort(void) + { ++ struct sigaction abrtaction; ++ sigset_t abrtset; ++ + raise(SIGABRT); + __block_all_sigs(0); ++ ++ /* Unblock just SIGABRT, and set default handler */ ++ sigemptyset(&abrtset); ++ sigaddset(&abrtset, SIGABRT); ++ sigprocmask(SIG_UNBLOCK, &abrtset, 0); ++ ++ memset(&abrtaction, 0, sizeof(struct sigaction)); ++ abrtaction.sa_handler = SIG_DFL; ++ ++ sigaction(SIGABRT, &abrtaction, NULL); ++ ++ raise(SIGABRT); ++ ++ /* Ok, give up. */ + a_crash(); + raise(SIGKILL); + _Exit(127); +diff --git a/src/fenv/m68k/fenv.c b/src/fenv/m68k/fenv.c +new file mode 100644 +index 00000000..e60949d1 +--- /dev/null ++++ b/src/fenv/m68k/fenv.c +@@ -0,0 +1,84 @@ ++#include <fenv.h> ++ ++#if __HAVE_68881__ || __mcffpu__ ++ ++static unsigned getsr() ++{ ++ unsigned v; ++ __asm__ __volatile__ ("fmove.l %%fpsr,%0" : "=dm"(v)); ++ return v; ++} ++ ++static void setsr(unsigned v) ++{ ++ __asm__ __volatile__ ("fmove.l %0,%%fpsr" : : "dm"(v)); ++} ++ ++static unsigned getcr() ++{ ++ unsigned v; ++ __asm__ __volatile__ ("fmove.l %%fpcr,%0" : "=dm"(v)); ++ return v; ++} ++ ++static void setcr(unsigned v) ++{ ++ __asm__ __volatile__ ("fmove.l %0,%%fpcr" : : "dm"(v)); ++} ++ ++int feclearexcept(int mask) ++{ ++ if (mask & ~FE_ALL_EXCEPT) return -1; ++ setsr(getsr() & ~mask); ++ return 0; ++} ++ ++int feraiseexcept(int mask) ++{ ++ if (mask & ~FE_ALL_EXCEPT) return -1; ++ setsr(getsr() | mask); ++ return 0; ++} ++ ++int fetestexcept(int mask) ++{ ++ return getsr() & mask; ++} ++ ++int fegetround(void) ++{ ++ return getcr() & FE_UPWARD; ++} ++ ++int __fesetround(int r) ++{ ++ setcr((getcr() & ~FE_UPWARD) | r); ++ return 0; ++} ++ ++int fegetenv(fenv_t *envp) ++{ ++ envp->__control_register = getcr(); ++ envp->__status_register = getsr(); ++ __asm__ __volatile__ ("fmove.l %%fpiar,%0" ++ : "=dm"(envp->__instruction_address)); ++ return 0; ++} ++ ++int fesetenv(const fenv_t *envp) ++{ ++ static const fenv_t default_env = { 0 }; ++ if (envp == FE_DFL_ENV) ++ envp = &default_env; ++ setcr(envp->__control_register); ++ setsr(envp->__status_register); ++ __asm__ __volatile__ ("fmove.l %0,%%fpiar" ++ : : "dm"(envp->__instruction_address)); ++ return 0; ++} ++ ++#else ++ ++#include "../fenv.c" ++ ++#endif +diff --git a/src/internal/atomic.h b/src/internal/atomic.h +index ab473dd7..f938879b 100644 +--- a/src/internal/atomic.h ++++ b/src/internal/atomic.h +@@ -251,6 +251,22 @@ static inline void a_crash() + } + #endif + ++#ifndef a_ctz_32 ++#define a_ctz_32 a_ctz_32 ++static inline int a_ctz_32(uint32_t x) ++{ ++#ifdef a_clz_32 ++ return 31-a_clz_32(x&-x); ++#else ++ static const char debruijn32[32] = { ++ 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13, ++ 31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14 ++ }; ++ return debruijn32[(x&-x)*0x076be629 >> 27]; ++#endif ++} ++#endif ++ + #ifndef a_ctz_64 + #define a_ctz_64 a_ctz_64 + static inline int a_ctz_64(uint64_t x) +@@ -261,22 +277,23 @@ static inline int a_ctz_64(uint64_t x) + 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10, + 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12 + }; +- static const char debruijn32[32] = { +- 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13, +- 31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14 +- }; + if (sizeof(long) < 8) { + uint32_t y = x; + if (!y) { + y = x>>32; +- return 32 + debruijn32[(y&-y)*0x076be629 >> 27]; ++ return 32 + a_ctz_32(y); + } +- return debruijn32[(y&-y)*0x076be629 >> 27]; ++ return a_ctz_32(y); + } + return debruijn64[(x&-x)*0x022fdd63cc95386dull >> 58]; + } + #endif + ++static inline int a_ctz_l(unsigned long x) ++{ ++ return (sizeof(long) < 8) ? a_ctz_32(x) : a_ctz_64(x); ++} ++ + #ifndef a_clz_64 + #define a_clz_64 a_clz_64 + static inline int a_clz_64(uint64_t x) +@@ -298,17 +315,4 @@ static inline int a_clz_64(uint64_t x) + } + #endif + +-#ifndef a_ctz_l +-#define a_ctz_l a_ctz_l +-static inline int a_ctz_l(unsigned long x) +-{ +- static const char debruijn32[32] = { +- 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13, +- 31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14 +- }; +- if (sizeof(long) == 8) return a_ctz_64(x); +- return debruijn32[(x&-x)*0x076be629 >> 27]; +-} +-#endif +- + #endif +diff --git a/src/internal/libm.h b/src/internal/libm.h +index df864111..a2505f7e 100644 +--- a/src/internal/libm.h ++++ b/src/internal/libm.h +@@ -28,6 +28,17 @@ union ldshape { + uint16_t se; + } i; + }; ++#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __BIG_ENDIAN ++/* This is the m68k variant of 80-bit long double, and this definition only works ++ * on archs where the alignment requirement of uint64_t is <= 4. */ ++union ldshape { ++ long double f; ++ struct { ++ uint16_t se; ++ uint16_t pad; ++ uint64_t m; ++ } i; ++}; + #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN + union ldshape { + long double f; +diff --git a/src/internal/m68k/syscall.s b/src/internal/m68k/syscall.s +new file mode 100644 +index 00000000..9972a34d +--- /dev/null ++++ b/src/internal/m68k/syscall.s +@@ -0,0 +1,9 @@ ++.global __syscall ++.hidden __syscall ++.type __syscall,%function ++__syscall: ++ movem.l %d2-%d5,-(%sp) ++ movem.l 20(%sp),%d0-%d5/%a0 ++ trap #0 ++ movem.l (%sp)+,%d2-%d5 ++ rts +diff --git a/src/internal/malloc_impl.h b/src/internal/malloc_impl.h +new file mode 100644 +index 00000000..5d025b06 +--- /dev/null ++++ b/src/internal/malloc_impl.h +@@ -0,0 +1,45 @@ ++#ifndef MALLOC_IMPL_H ++#define MALLOC_IMPL_H ++ ++void *__mmap(void *, size_t, int, int, int, off_t); ++int __munmap(void *, size_t); ++void *__mremap(void *, size_t, size_t, int, ...); ++int __madvise(void *, size_t, int); ++ ++struct chunk { ++ size_t psize, csize; ++ struct chunk *next, *prev; ++}; ++ ++struct bin { ++ volatile int lock[2]; ++ struct chunk *head; ++ struct chunk *tail; ++}; ++ ++#define SIZE_ALIGN (4*sizeof(size_t)) ++#define SIZE_MASK (-SIZE_ALIGN) ++#define OVERHEAD (2*sizeof(size_t)) ++#define MMAP_THRESHOLD (0x1c00*SIZE_ALIGN) ++#define DONTCARE 16 ++#define RECLAIM 163840 ++ ++#define CHUNK_SIZE(c) ((c)->csize & -2) ++#define CHUNK_PSIZE(c) ((c)->psize & -2) ++#define PREV_CHUNK(c) ((struct chunk *)((char *)(c) - CHUNK_PSIZE(c))) ++#define NEXT_CHUNK(c) ((struct chunk *)((char *)(c) + CHUNK_SIZE(c))) ++#define MEM_TO_CHUNK(p) (struct chunk *)((char *)(p) - OVERHEAD) ++#define CHUNK_TO_MEM(c) (void *)((char *)(c) + OVERHEAD) ++#define BIN_TO_CHUNK(i) (MEM_TO_CHUNK(&mal.bins[i].head)) ++ ++#define C_INUSE ((size_t)1) ++ ++#define IS_MMAPPED(c) !((c)->csize & (C_INUSE)) ++ ++__attribute__((__visibility__("hidden"))) ++void __bin_chunk(struct chunk *); ++ ++__attribute__((__visibility__("hidden"))) ++extern int __malloc_replaced; ++ ++#endif +diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h +index f6a4f2c2..3826bd8e 100644 +--- a/src/internal/pthread_impl.h ++++ b/src/internal/pthread_impl.h +@@ -19,38 +19,36 @@ struct pthread { + void **dtv, *unused1, *unused2; + uintptr_t sysinfo; + uintptr_t canary, canary2; +- pid_t tid, pid; + + /* Part 2 -- implementation details, non-ABI. */ +- int tsd_used, errno_val; +- volatile int cancel, canceldisable, cancelasync; +- int detached; ++ int tid; ++ int errno_val; ++ volatile int detach_state; ++ volatile int cancel; ++ volatile unsigned char canceldisable, cancelasync; ++ unsigned char tsd_used:1; ++ unsigned char unblock_cancel:1; ++ unsigned char dlerror_flag:1; + unsigned char *map_base; + size_t map_size; + void *stack; + size_t stack_size; ++ size_t guard_size; + void *start_arg; + void *(*start)(void *); + void *result; + struct __ptcb *cancelbuf; + void **tsd; +- volatile int dead; + struct { + volatile void *volatile head; + long off; + volatile void *volatile pending; + } robust_list; +- int unblock_cancel; + volatile int timer_id; + locale_t locale; + volatile int killlock[1]; +- volatile int exitlock[1]; +- volatile int startlock[2]; +- unsigned long sigmask[_NSIG/8/sizeof(long)]; + char *dlerror_buf; +- int dlerror_flag; + void *stdio_locks; +- size_t guard_size; + + /* Part 3 -- the positions of these fields relative to + * the end of the structure is external and internal ABI. */ +@@ -58,6 +56,22 @@ struct pthread { + void **dtv_copy; + }; + ++struct start_sched_args { ++ void *start_arg; ++ void *(*start_fn)(void *); ++ sigset_t mask; ++ pthread_attr_t *attr; ++ volatile int futex; ++}; ++ ++enum { ++ DT_EXITED = 0, ++ DT_EXITING, ++ DT_JOINABLE, ++ DT_DETACHED, ++ DT_DYNAMIC, ++}; ++ + struct __timer { + int timerid; + pthread_t thread; +@@ -147,8 +161,8 @@ static inline void __wake(volatile void *addr, int cnt, int priv) + static inline void __futexwait(volatile void *addr, int val, int priv) + { + if (priv) priv = FUTEX_PRIVATE; +- __syscall(SYS_futex, addr, FUTEX_WAIT|priv, val) != -ENOSYS || +- __syscall(SYS_futex, addr, FUTEX_WAIT, val); ++ __syscall(SYS_futex, addr, FUTEX_WAIT|priv, val, 0) != -ENOSYS || ++ __syscall(SYS_futex, addr, FUTEX_WAIT, val, 0); + } + + void __acquire_ptc(void); +diff --git a/src/internal/stdio_impl.h b/src/internal/stdio_impl.h +index 7cdf729d..1127a492 100644 +--- a/src/internal/stdio_impl.h ++++ b/src/internal/stdio_impl.h +@@ -9,7 +9,7 @@ + + #define FFINALLOCK(f) ((f)->lock>=0 ? __lockfile((f)) : 0) + #define FLOCK(f) int __need_unlock = ((f)->lock>=0 ? __lockfile((f)) : 0) +-#define FUNLOCK(f) if (__need_unlock) __unlockfile((f)); else ++#define FUNLOCK(f) do { if (__need_unlock) __unlockfile((f)); } while (0) + + #define F_PERM 1 + #define F_NORD 4 +diff --git a/src/ipc/msgctl.c b/src/ipc/msgctl.c +index 4372c719..ea9b2337 100644 +--- a/src/ipc/msgctl.c ++++ b/src/ipc/msgctl.c +@@ -1,12 +1,34 @@ + #include <sys/msg.h> ++#include <endian.h> + #include "syscall.h" + #include "ipc.h" + ++#if __BYTE_ORDER != __BIG_ENDIAN ++#undef SYSCALL_IPC_BROKEN_MODE ++#endif ++ + int msgctl(int q, int cmd, struct msqid_ds *buf) + { ++#ifdef SYSCALL_IPC_BROKEN_MODE ++ struct msqid_ds tmp; ++ if (cmd == IPC_SET) { ++ tmp = *buf; ++ tmp.msg_perm.mode *= 0x10000U; ++ buf = &tmp; ++ } ++#endif + #ifdef SYS_msgctl +- return syscall(SYS_msgctl, q, cmd | IPC_64, buf); ++ int r = __syscall(SYS_msgctl, q, cmd | IPC_64, buf); + #else +- return syscall(SYS_ipc, IPCOP_msgctl, q, cmd | IPC_64, 0, buf, 0); ++ int r = __syscall(SYS_ipc, IPCOP_msgctl, q, cmd | IPC_64, 0, buf, 0); ++#endif ++#ifdef SYSCALL_IPC_BROKEN_MODE ++ if (r >= 0) switch (cmd) { ++ case IPC_STAT: ++ case MSG_STAT: ++ case MSG_STAT_ANY: ++ buf->msg_perm.mode >>= 16; ++ } + #endif ++ return __syscall_ret(r); + } +diff --git a/src/ipc/semctl.c b/src/ipc/semctl.c +index 673a9a8c..941e2813 100644 +--- a/src/ipc/semctl.c ++++ b/src/ipc/semctl.c +@@ -1,8 +1,13 @@ + #include <sys/sem.h> + #include <stdarg.h> ++#include <endian.h> + #include "syscall.h" + #include "ipc.h" + ++#if __BYTE_ORDER != __BIG_ENDIAN ++#undef SYSCALL_IPC_BROKEN_MODE ++#endif ++ + union semun { + int val; + struct semid_ds *buf; +@@ -20,9 +25,26 @@ int semctl(int id, int num, int cmd, ...) + arg = va_arg(ap, union semun); + va_end(ap); + } ++#ifdef SYSCALL_IPC_BROKEN_MODE ++ struct semid_ds tmp; ++ if (cmd == IPC_SET) { ++ tmp = *arg.buf; ++ tmp.sem_perm.mode *= 0x10000U; ++ arg.buf = &tmp; ++ } ++#endif + #ifdef SYS_semctl +- return syscall(SYS_semctl, id, num, cmd | IPC_64, arg.buf); ++ int r = __syscall(SYS_semctl, id, num, cmd | IPC_64, arg.buf); + #else +- return syscall(SYS_ipc, IPCOP_semctl, id, num, cmd | IPC_64, &arg.buf); ++ int r = __syscall(SYS_ipc, IPCOP_semctl, id, num, cmd | IPC_64, &arg.buf); ++#endif ++#ifdef SYSCALL_IPC_BROKEN_MODE ++ if (r >= 0) switch (cmd) { ++ case IPC_STAT: ++ case SEM_STAT: ++ case SEM_STAT_ANY: ++ arg.buf->sem_perm.mode >>= 16; ++ } + #endif ++ return __syscall_ret(r); + } +diff --git a/src/ipc/shmctl.c b/src/ipc/shmctl.c +index e2879f20..c951a581 100644 +--- a/src/ipc/shmctl.c ++++ b/src/ipc/shmctl.c +@@ -1,12 +1,34 @@ + #include <sys/shm.h> ++#include <endian.h> + #include "syscall.h" + #include "ipc.h" + ++#if __BYTE_ORDER != __BIG_ENDIAN ++#undef SYSCALL_IPC_BROKEN_MODE ++#endif ++ + int shmctl(int id, int cmd, struct shmid_ds *buf) + { ++#ifdef SYSCALL_IPC_BROKEN_MODE ++ struct shmid_ds tmp; ++ if (cmd == IPC_SET) { ++ tmp = *buf; ++ tmp.shm_perm.mode *= 0x10000U; ++ buf = &tmp; ++ } ++#endif + #ifdef SYS_shmctl +- return syscall(SYS_shmctl, id, cmd | IPC_64, buf); ++ int r = __syscall(SYS_shmctl, id, cmd | IPC_64, buf); + #else +- return syscall(SYS_ipc, IPCOP_shmctl, id, cmd | IPC_64, 0, buf, 0); ++ int r = __syscall(SYS_ipc, IPCOP_shmctl, id, cmd | IPC_64, 0, buf, 0); ++#endif ++#ifdef SYSCALL_IPC_BROKEN_MODE ++ if (r >= 0) switch (cmd) { ++ case IPC_STAT: ++ case SHM_STAT: ++ case SHM_STAT_ANY: ++ buf->shm_perm.mode >>= 16; ++ } + #endif ++ return __syscall_ret(r); + } +diff --git a/src/ldso/aarch64/tlsdesc.s b/src/ldso/aarch64/tlsdesc.s +index 8ed5c267..8e4004d7 100644 +--- a/src/ldso/aarch64/tlsdesc.s ++++ b/src/ldso/aarch64/tlsdesc.s +@@ -14,7 +14,7 @@ __tlsdesc_static: + // size_t __tlsdesc_dynamic(size_t *a) + // { + // struct {size_t modidx,off;} *p = (void*)a[1]; +-// size_t *dtv = *(size_t**)(tp + 16 - 8); ++// size_t *dtv = *(size_t**)(tp - 8); + // if (p->modidx <= dtv[0]) + // return dtv[p->modidx] + p->off - tp; + // return __tls_get_new(p) - tp; +@@ -28,8 +28,7 @@ __tlsdesc_dynamic: + mrs x1,tpidr_el0 // tp + ldr x0,[x0,#8] // p + ldr x2,[x0] // p->modidx +- add x3,x1,#8 +- ldr x3,[x3] // dtv ++ ldr x3,[x1,#-8] // dtv + ldr x4,[x3] // dtv[0] + cmp x2,x4 + b.hi 1f +diff --git a/src/ldso/m68k/dlsym.s b/src/ldso/m68k/dlsym.s +new file mode 100644 +index 00000000..5209ae1b +--- /dev/null ++++ b/src/ldso/m68k/dlsym.s +@@ -0,0 +1,12 @@ ++.text ++.global dlsym ++.hidden __dlsym ++.type dlsym,@function ++dlsym: ++ move.l (%sp),-(%sp) ++ move.l 12(%sp),-(%sp) ++ move.l 12(%sp),-(%sp) ++ lea __dlsym-.-8,%a1 ++ jsr (%pc,%a1) ++ add.l #12,%sp ++ rts +diff --git a/src/linux/getrandom.c b/src/linux/getrandom.c +new file mode 100644 +index 00000000..6cc6f6b0 +--- /dev/null ++++ b/src/linux/getrandom.c +@@ -0,0 +1,7 @@ ++#include <sys/random.h> ++#include "syscall.h" ++ ++ssize_t getrandom(void *buf, size_t buflen, unsigned flags) ++{ ++ return syscall_cp(SYS_getrandom, buf, buflen, flags); ++} +diff --git a/src/linux/memfd_create.c b/src/linux/memfd_create.c +new file mode 100644 +index 00000000..1649fe55 +--- /dev/null ++++ b/src/linux/memfd_create.c +@@ -0,0 +1,8 @@ ++#define _GNU_SOURCE 1 ++#include <sys/mman.h> ++#include "syscall.h" ++ ++int memfd_create(const char *name, unsigned flags) ++{ ++ return syscall(SYS_memfd_create, name, flags); ++} +diff --git a/src/linux/mlock2.c b/src/linux/mlock2.c +new file mode 100644 +index 00000000..10132742 +--- /dev/null ++++ b/src/linux/mlock2.c +@@ -0,0 +1,10 @@ ++#define _GNU_SOURCE 1 ++#include <sys/mman.h> ++#include "syscall.h" ++ ++int mlock2(const void *addr, size_t len, unsigned flags) ++{ ++ if (flags == 0) ++ return mlock(addr, len); ++ return syscall(SYS_mlock2, addr, len, flags); ++} +diff --git a/src/locale/iconv.c b/src/locale/iconv.c +index d469856c..3047c27b 100644 +--- a/src/locale/iconv.c ++++ b/src/locale/iconv.c +@@ -458,16 +458,24 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri + * range in the hkscs table then hard-coded + * here. Ugly, yes. */ + if (c/256 == 0xdc) { +- if (totype-0300U > 8) k = 2; +- else k = "\10\4\4\10\4\4\10\2\4"[totype-0300]; +- if (k > *outb) goto toobig; +- x += iconv(combine_to_from(to, 0), ++ union { ++ char c[8]; ++ wchar_t wc[2]; ++ } tmp; ++ char *ptmp = tmp.c; ++ size_t tmpx = iconv(combine_to_from(to, find_charmap("utf8")), + &(char *){"\303\212\314\204" + "\303\212\314\214" + "\303\252\314\204" + "\303\252\314\214" + +c%256}, &(size_t){4}, +- out, outb); ++ &ptmp, &(size_t){sizeof tmp}); ++ size_t tmplen = ptmp - tmp.c; ++ if (tmplen > *outb) goto toobig; ++ if (tmpx) x++; ++ memcpy(*out, &tmp, tmplen); ++ *out += tmplen; ++ *outb -= tmplen; + continue; + } + if (!c) goto ilseq; +@@ -539,6 +547,7 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri + if (*outb < 1) goto toobig; + if (c<256 && c==legacy_map(tomap, c)) { + revout: ++ if (*outb < 1) goto toobig; + *(*out)++ = c; + *outb -= 1; + break; +@@ -645,6 +654,8 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri + *out += 4; + *outb -= 4; + break; ++ case UTF_32: ++ totype = UTF_32BE; + case UTF_32BE: + case UTF_32LE: + if (*outb < 4) goto toobig; +diff --git a/src/locale/langinfo.c b/src/locale/langinfo.c +index b16caf44..83be6433 100644 +--- a/src/locale/langinfo.c ++++ b/src/locale/langinfo.c +@@ -33,7 +33,7 @@ char *__nl_langinfo_l(nl_item item, locale_t loc) + int idx = item & 65535; + const char *str; + +- if (item == CODESET) return MB_CUR_MAX==1 ? "ASCII" : "UTF-8"; ++ if (item == CODESET) return loc->cat[LC_CTYPE] ? "UTF-8" : "ASCII"; + + /* _NL_LOCALE_NAME extension */ + if (idx == 65535 && cat < LC_ALL) +diff --git a/src/locale/setlocale.c b/src/locale/setlocale.c +index 40bc7ece..4d51cdfe 100644 +--- a/src/locale/setlocale.c ++++ b/src/locale/setlocale.c +@@ -25,6 +25,8 @@ char *setlocale(int cat, const char *name) + + if ((unsigned)cat > LC_ALL) return 0; + ++ if (name && (!strncmp(name, "VSX4L", 5))) return 0; ++ + LOCK(lock); + + /* For LC_ALL, setlocale is required to return a string which +diff --git a/src/malloc/__brk.c b/src/malloc/__brk.c +deleted file mode 100644 +index 4c9119b4..00000000 +--- a/src/malloc/__brk.c ++++ /dev/null +@@ -1,7 +0,0 @@ +-#include <stdint.h> +-#include "syscall.h" +- +-uintptr_t __brk(uintptr_t newbrk) +-{ +- return __syscall(SYS_brk, newbrk); +-} +diff --git a/src/malloc/calloc.c b/src/malloc/calloc.c +deleted file mode 100644 +index 436c0b03..00000000 +--- a/src/malloc/calloc.c ++++ /dev/null +@@ -1,13 +0,0 @@ +-#include <stdlib.h> +-#include <errno.h> +- +-void *__malloc0(size_t); +- +-void *calloc(size_t m, size_t n) +-{ +- if (n && m > (size_t)-1/n) { +- errno = ENOMEM; +- return 0; +- } +- return __malloc0(n * m); +-} +diff --git a/src/malloc/lite_malloc.c b/src/malloc/lite_malloc.c +index 701f60b4..96c4feac 100644 +--- a/src/malloc/lite_malloc.c ++++ b/src/malloc/lite_malloc.c +@@ -47,4 +47,14 @@ static void *__simple_malloc(size_t n) + } + + weak_alias(__simple_malloc, malloc); +-weak_alias(__simple_malloc, __malloc0); ++ ++static void *__simple_calloc(size_t m, size_t n) ++{ ++ if (n && m > (size_t)-1/n) { ++ errno = ENOMEM; ++ return 0; ++ } ++ return __simple_malloc(n * m); ++} ++ ++weak_alias(__simple_calloc, calloc); +diff --git a/src/malloc/malloc.c b/src/malloc/malloc.c +index 9e05e1d6..d72883e1 100644 +--- a/src/malloc/malloc.c ++++ b/src/malloc/malloc.c +@@ -8,53 +8,19 @@ + #include "libc.h" + #include "atomic.h" + #include "pthread_impl.h" ++#include "malloc_impl.h" + + #if defined(__GNUC__) && defined(__PIC__) + #define inline inline __attribute__((always_inline)) + #endif + +-void *__mmap(void *, size_t, int, int, int, off_t); +-int __munmap(void *, size_t); +-void *__mremap(void *, size_t, size_t, int, ...); +-int __madvise(void *, size_t, int); +- +-struct chunk { +- size_t psize, csize; +- struct chunk *next, *prev; +-}; +- +-struct bin { +- volatile int lock[2]; +- struct chunk *head; +- struct chunk *tail; +-}; +- + static struct { + volatile uint64_t binmap; + struct bin bins[64]; + volatile int free_lock[2]; + } mal; + +- +-#define SIZE_ALIGN (4*sizeof(size_t)) +-#define SIZE_MASK (-SIZE_ALIGN) +-#define OVERHEAD (2*sizeof(size_t)) +-#define MMAP_THRESHOLD (0x1c00*SIZE_ALIGN) +-#define DONTCARE 16 +-#define RECLAIM 163840 +- +-#define CHUNK_SIZE(c) ((c)->csize & -2) +-#define CHUNK_PSIZE(c) ((c)->psize & -2) +-#define PREV_CHUNK(c) ((struct chunk *)((char *)(c) - CHUNK_PSIZE(c))) +-#define NEXT_CHUNK(c) ((struct chunk *)((char *)(c) + CHUNK_SIZE(c))) +-#define MEM_TO_CHUNK(p) (struct chunk *)((char *)(p) - OVERHEAD) +-#define CHUNK_TO_MEM(c) (void *)((char *)(c) + OVERHEAD) +-#define BIN_TO_CHUNK(i) (MEM_TO_CHUNK(&mal.bins[i].head)) +- +-#define C_INUSE ((size_t)1) +- +-#define IS_MMAPPED(c) !((c)->csize & (C_INUSE)) +- ++int __malloc_replaced; + + /* Synchronization tools */ + +@@ -314,7 +280,7 @@ static void trim(struct chunk *self, size_t n) + next->psize = n1-n | C_INUSE; + self->csize = n | C_INUSE; + +- free(CHUNK_TO_MEM(split)); ++ __bin_chunk(split); + } + + void *malloc(size_t n) +@@ -366,15 +332,40 @@ void *malloc(size_t n) + return CHUNK_TO_MEM(c); + } + +-void *__malloc0(size_t n) ++static size_t mal0_clear(char *p, size_t pagesz, size_t n) + { ++#ifdef __GNUC__ ++ typedef uint64_t __attribute__((__may_alias__)) T; ++#else ++ typedef unsigned char T; ++#endif ++ char *pp = p + n; ++ size_t i = (uintptr_t)pp & (pagesz - 1); ++ for (;;) { ++ pp = memset(pp - i, 0, i); ++ if (pp - p < pagesz) return pp - p; ++ for (i = pagesz; i; i -= 2*sizeof(T), pp -= 2*sizeof(T)) ++ if (((T *)pp)[-1] | ((T *)pp)[-2]) ++ break; ++ } ++} ++ ++void *calloc(size_t m, size_t n) ++{ ++ if (n && m > (size_t)-1/n) { ++ errno = ENOMEM; ++ return 0; ++ } ++ n *= m; + void *p = malloc(n); +- if (p && !IS_MMAPPED(MEM_TO_CHUNK(p))) { +- size_t *z; +- n = (n + sizeof *z - 1)/sizeof *z; +- for (z=p; n; n--, z++) if (*z) *z=0; ++ if (!p) return p; ++ if (!__malloc_replaced) { ++ if (IS_MMAPPED(MEM_TO_CHUNK(p))) ++ return p; ++ if (n >= PAGE_SIZE) ++ n = mal0_clear(p, PAGE_SIZE, n); + } +- return p; ++ return memset(p, 0, n); + } + + void *realloc(void *p, size_t n) +@@ -397,10 +388,9 @@ void *realloc(void *p, size_t n) + size_t newlen = n + extra; + /* Crash on realloc of freed chunk */ + if (extra & 1) a_crash(); +- if (newlen < PAGE_SIZE && (new = malloc(n))) { +- memcpy(new, p, n-OVERHEAD); +- free(p); +- return new; ++ if (newlen < PAGE_SIZE && (new = malloc(n-OVERHEAD))) { ++ n0 = n; ++ goto copy_free_ret; + } + newlen = (newlen + PAGE_SIZE-1) & -PAGE_SIZE; + if (oldlen == newlen) return p; +@@ -443,34 +433,20 @@ copy_realloc: + /* As a last resort, allocate a new chunk and copy to it. */ + new = malloc(n-OVERHEAD); + if (!new) return 0; ++copy_free_ret: + memcpy(new, p, n0-OVERHEAD); + free(CHUNK_TO_MEM(self)); + return new; + } + +-void free(void *p) ++void __bin_chunk(struct chunk *self) + { +- struct chunk *self, *next; ++ struct chunk *next = NEXT_CHUNK(self); + size_t final_size, new_size, size; + int reclaim=0; + int i; + +- if (!p) return; +- +- self = MEM_TO_CHUNK(p); +- +- if (IS_MMAPPED(self)) { +- size_t extra = self->psize; +- char *base = (char *)self - extra; +- size_t len = CHUNK_SIZE(self) + extra; +- /* Crash on double free */ +- if (extra & 1) a_crash(); +- __munmap(base, len); +- return; +- } +- + final_size = new_size = CHUNK_SIZE(self); +- next = NEXT_CHUNK(self); + + /* Crash on corrupted footer (likely from buffer overflow) */ + if (next->psize != self->csize) a_crash(); +@@ -531,3 +507,44 @@ void free(void *p) + + unlock_bin(i); + } ++ ++static void unmap_chunk(struct chunk *self) ++{ ++ size_t extra = self->psize; ++ char *base = (char *)self - extra; ++ size_t len = CHUNK_SIZE(self) + extra; ++ /* Crash on double free */ ++ if (extra & 1) a_crash(); ++ __munmap(base, len); ++} ++ ++void free(void *p) ++{ ++ if (!p) return; ++ ++ struct chunk *self = MEM_TO_CHUNK(p); ++ ++ if (IS_MMAPPED(self)) ++ unmap_chunk(self); ++ else ++ __bin_chunk(self); ++} ++ ++void __malloc_donate(char *start, char *end) ++{ ++ size_t align_start_up = (SIZE_ALIGN-1) & (-(uintptr_t)start - OVERHEAD); ++ size_t align_end_down = (SIZE_ALIGN-1) & (uintptr_t)end; ++ ++ /* Getting past this condition ensures that the padding for alignment ++ * and header overhead will not overflow and will leave a nonzero ++ * multiple of SIZE_ALIGN bytes between start and end. */ ++ if (end - start <= OVERHEAD + align_start_up + align_end_down) ++ return; ++ start += align_start_up + OVERHEAD; ++ end -= align_end_down; ++ ++ struct chunk *c = MEM_TO_CHUNK(start), *n = MEM_TO_CHUNK(end); ++ c->psize = n->csize = C_INUSE; ++ c->csize = n->psize = C_INUSE | (end-start); ++ __bin_chunk(c); ++} +diff --git a/src/malloc/memalign.c b/src/malloc/memalign.c +index 006bd21c..8a6152f4 100644 +--- a/src/malloc/memalign.c ++++ b/src/malloc/memalign.c +@@ -2,55 +2,53 @@ + #include <stdint.h> + #include <errno.h> + #include "libc.h" +- +-/* This function should work with most dlmalloc-like chunk bookkeeping +- * systems, but it's only guaranteed to work with the native implementation +- * used in this library. */ ++#include "malloc_impl.h" + + void *__memalign(size_t align, size_t len) + { +- unsigned char *mem, *new, *end; +- size_t header, footer; ++ unsigned char *mem, *new; + + if ((align & -align) != align) { + errno = EINVAL; +- return NULL; ++ return 0; + } + +- if (len > SIZE_MAX - align) { ++ if (len > SIZE_MAX - align || __malloc_replaced) { + errno = ENOMEM; +- return NULL; ++ return 0; + } + +- if (align <= 4*sizeof(size_t)) { +- if (!(mem = malloc(len))) +- return NULL; +- return mem; +- } ++ if (align <= SIZE_ALIGN) ++ return malloc(len); + + if (!(mem = malloc(len + align-1))) +- return NULL; ++ return 0; + + new = (void *)((uintptr_t)mem + align-1 & -align); + if (new == mem) return mem; + +- header = ((size_t *)mem)[-1]; ++ struct chunk *c = MEM_TO_CHUNK(mem); ++ struct chunk *n = MEM_TO_CHUNK(new); + +- if (!(header & 7)) { +- ((size_t *)new)[-2] = ((size_t *)mem)[-2] + (new-mem); +- ((size_t *)new)[-1] = ((size_t *)mem)[-1] - (new-mem); ++ if (IS_MMAPPED(c)) { ++ /* Apply difference between aligned and original ++ * address to the "extra" field of mmapped chunk. */ ++ n->psize = c->psize + (new-mem); ++ n->csize = c->csize - (new-mem); + return new; + } + +- end = mem + (header & -8); +- footer = ((size_t *)end)[-2]; ++ struct chunk *t = NEXT_CHUNK(c); + +- ((size_t *)mem)[-1] = header&7 | new-mem; +- ((size_t *)new)[-2] = footer&7 | new-mem; +- ((size_t *)new)[-1] = header&7 | end-new; +- ((size_t *)end)[-2] = footer&7 | end-new; ++ /* Split the allocated chunk into two chunks. The aligned part ++ * that will be used has the size in its footer reduced by the ++ * difference between the aligned and original addresses, and ++ * the resulting size copied to its header. A new header and ++ * footer are written for the split-off part to be freed. */ ++ n->psize = c->csize = C_INUSE | (new-mem); ++ n->csize = t->psize -= new-mem; + +- free(mem); ++ __bin_chunk(c); + return new; + } + +diff --git a/src/math/__fpclassifyl.c b/src/math/__fpclassifyl.c +index 481c0b94..e41781b6 100644 +--- a/src/math/__fpclassifyl.c ++++ b/src/math/__fpclassifyl.c +@@ -13,10 +13,18 @@ int __fpclassifyl(long double x) + int msb = u.i.m>>63; + if (!e && !msb) + return u.i.m ? FP_SUBNORMAL : FP_ZERO; ++ if (e == 0x7fff) { ++ /* The x86 variant of 80-bit extended precision only admits ++ * one representation of each infinity, with the mantissa msb ++ * necessarily set. The version with it clear is invalid/nan. ++ * The m68k variant, however, allows either, and tooling uses ++ * the version with it clear. */ ++ if (__BYTE_ORDER == __LITTLE_ENDIAN && !msb) ++ return FP_NAN; ++ return u.i.m << 1 ? FP_NAN : FP_INFINITE; ++ } + if (!msb) + return FP_NAN; +- if (e == 0x7fff) +- return u.i.m << 1 ? FP_NAN : FP_INFINITE; + return FP_NORMAL; + } + #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 +diff --git a/src/math/fmaf.c b/src/math/fmaf.c +index aa57feb6..80f5cd8a 100644 +--- a/src/math/fmaf.c ++++ b/src/math/fmaf.c +@@ -50,7 +50,7 @@ float fmaf(float x, float y, float z) + /* Common case: The double precision result is fine. */ + if ((u.i & 0x1fffffff) != 0x10000000 || /* not a halfway case */ + e == 0x7ff || /* NaN */ +- result - xy == z || /* exact */ ++ (result - xy == z && result - z == xy) || /* exact */ + fegetround() != FE_TONEAREST) /* not round-to-nearest */ + { + /* +diff --git a/src/misc/getentropy.c b/src/misc/getentropy.c +new file mode 100644 +index 00000000..4c61ae26 +--- /dev/null ++++ b/src/misc/getentropy.c +@@ -0,0 +1,31 @@ ++#include <sys/random.h> ++#include <pthread.h> ++#include <errno.h> ++ ++int getentropy(void *buffer, size_t len) ++{ ++ int cs, ret; ++ char *pos = buffer; ++ ++ if (len > 256) { ++ errno = EIO; ++ return -1; ++ } ++ ++ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); ++ ++ while (len) { ++ ret = getrandom(pos, len, 0); ++ if (ret < 0) { ++ if (errno == EINTR) continue; ++ else break; ++ } ++ pos += ret; ++ len -= ret; ++ ret = 0; ++ } ++ ++ pthread_setcancelstate(cs, 0); ++ ++ return ret; ++} +diff --git a/src/misc/gethostid.c b/src/misc/gethostid.c +index ea65611a..25bb35db 100644 +--- a/src/misc/gethostid.c ++++ b/src/misc/gethostid.c +@@ -1,3 +1,5 @@ ++#include <unistd.h> ++ + long gethostid() + { + return 0; +diff --git a/src/misc/getopt.c b/src/misc/getopt.c +index e9bab41c..e921a60e 100644 +--- a/src/misc/getopt.c ++++ b/src/misc/getopt.c +@@ -77,7 +77,7 @@ int getopt(int argc, char * const argv[], const char *optstring) + if (l>0) i+=l; else i++; + } while (l && d != c); + +- if (d != c) { ++ if (d != c || c == ':') { + optopt = c; + if (optstring[0] != ':' && opterr) + __getopt_msg(argv[0], ": unrecognized option: ", optchar, k); +diff --git a/src/misc/getopt_long.c b/src/misc/getopt_long.c +index 008b747c..ddcef949 100644 +--- a/src/misc/getopt_long.c ++++ b/src/misc/getopt_long.c +@@ -1,5 +1,7 @@ + #define _GNU_SOURCE + #include <stddef.h> ++#include <stdlib.h> ++#include <limits.h> + #include <getopt.h> + #include <stdio.h> + #include <string.h> +@@ -58,10 +60,10 @@ static int __getopt_long_core(int argc, char *const *argv, const char *optstring + { + int colon = optstring[optstring[0]=='+'||optstring[0]=='-']==':'; + int i, cnt, match; +- char *arg, *opt; ++ char *arg, *opt, *start = argv[optind]+1; + for (cnt=i=0; longopts[i].name; i++) { + const char *name = longopts[i].name; +- opt = argv[optind]+1; ++ opt = start; + if (*opt == '-') opt++; + while (*opt && *opt != '=' && *opt == *name) + name++, opt++; +@@ -74,6 +76,17 @@ static int __getopt_long_core(int argc, char *const *argv, const char *optstring + } + cnt++; + } ++ if (cnt==1 && longonly && arg-start == mblen(start, MB_LEN_MAX)) { ++ int l = arg-start; ++ for (i=0; optstring[i]; i++) { ++ int j; ++ for (j=0; j<l && start[j]==optstring[i+j]; j++); ++ if (j==l) { ++ cnt++; ++ break; ++ } ++ } ++ } + if (cnt==1) { + i = match; + opt = arg; +diff --git a/src/network/getaddrinfo.c b/src/network/getaddrinfo.c +index b9439f77..ba26847a 100644 +--- a/src/network/getaddrinfo.c ++++ b/src/network/getaddrinfo.c +@@ -3,6 +3,10 @@ + #include <netinet/in.h> + #include <netdb.h> + #include <string.h> ++#include <pthread.h> ++#include <unistd.h> ++#include <endian.h> ++#include <errno.h> + #include "lookup.h" + + int getaddrinfo(const char *restrict host, const char *restrict serv, const struct addrinfo *restrict hint, struct addrinfo **restrict res) +@@ -43,6 +47,41 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru + } + } + ++ if (flags & AI_ADDRCONFIG) { ++ /* Define the "an address is configured" condition for address ++ * families via ability to create a socket for the family plus ++ * routability of the loopback address for the family. */ ++ static const struct sockaddr_in lo4 = { ++ .sin_family = AF_INET, .sin_port = 65535, ++ .sin_addr.s_addr = __BYTE_ORDER == __BIG_ENDIAN ++ ? 0x7f000001 : 0x0100007f ++ }; ++ static const struct sockaddr_in6 lo6 = { ++ .sin6_family = AF_INET6, .sin6_port = 65535, ++ .sin6_addr = IN6ADDR_LOOPBACK_INIT ++ }; ++ int tf[2] = { AF_INET, AF_INET6 }; ++ const void *ta[2] = { &lo4, &lo6 }; ++ socklen_t tl[2] = { sizeof lo4, sizeof lo6 }; ++ for (i=0; i<2; i++) { ++ if (family==tf[1-i]) continue; ++ int s = socket(tf[i], SOCK_CLOEXEC|SOCK_DGRAM, ++ IPPROTO_UDP); ++ if (s>=0) { ++ int cs; ++ pthread_setcancelstate( ++ PTHREAD_CANCEL_DISABLE, &cs); ++ int r = connect(s, ta[i], tl[i]); ++ pthread_setcancelstate(cs, 0); ++ close(s); ++ if (!r) continue; ++ } ++ if (errno != EAFNOSUPPORT) return EAI_SYSTEM; ++ if (family == tf[i]) return EAI_NONAME; ++ family = tf[1-i]; ++ } ++ } ++ + nservs = __lookup_serv(ports, serv, proto, socktype, flags); + if (nservs < 0) return nservs; + +diff --git a/src/network/inet_ntop.c b/src/network/inet_ntop.c +index 14f9f4c4..4bfef2c5 100644 +--- a/src/network/inet_ntop.c ++++ b/src/network/inet_ntop.c +@@ -36,7 +36,7 @@ const char *inet_ntop(int af, const void *restrict a0, char *restrict s, socklen + j = strspn(buf+i, ":0"); + if (j>max) best=i, max=j; + } +- if (max>2) { ++ if (max>3) { + buf[best] = buf[best+1] = ':'; + memmove(buf+best+2, buf+best+max, i-best-max+1); + } +diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c +index 209c20f0..0e6db9ef 100644 +--- a/src/network/lookup_name.c ++++ b/src/network/lookup_name.c +@@ -184,6 +184,10 @@ static int name_from_dns_search(struct address buf[static MAXADDRS], char canon[ + for (dots=l=0; name[l]; l++) if (name[l]=='.') dots++; + if (dots >= conf.ndots || name[l-1]=='.') *search = 0; + ++ /* Strip final dot for canon, fail if multiple trailing dots. */ ++ if (name[l-1]=='.') l--; ++ if (!l || name[l-1]=='.') return EAI_NONAME; ++ + /* This can never happen; the caller already checked length. */ + if (l >= 256) return EAI_NONAME; + +@@ -351,36 +355,53 @@ int __lookup_name(struct address buf[static MAXADDRS], char canon[static 256], c + * excessive runtime and code size cost and dubious benefit. + * So far the label/precedence table cannot be customized. */ + for (i=0; i<cnt; i++) { ++ int family = buf[i].family; + int key = 0; +- struct sockaddr_in6 sa, da = { ++ struct sockaddr_in6 sa6 = { 0 }, da6 = { + .sin6_family = AF_INET6, + .sin6_scope_id = buf[i].scopeid, + .sin6_port = 65535 + }; +- if (buf[i].family == AF_INET6) { +- memcpy(da.sin6_addr.s6_addr, buf[i].addr, 16); ++ struct sockaddr_in sa4 = { 0 }, da4 = { ++ .sin_family = AF_INET, ++ .sin_port = 65535 ++ }; ++ void *sa, *da; ++ socklen_t salen, dalen; ++ if (family == AF_INET6) { ++ memcpy(da6.sin6_addr.s6_addr, buf[i].addr, 16); ++ da = &da6; dalen = sizeof da6; ++ sa = &sa6; salen = sizeof sa6; + } else { +- memcpy(da.sin6_addr.s6_addr, ++ memcpy(sa6.sin6_addr.s6_addr, ++ "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12); ++ memcpy(da6.sin6_addr.s6_addr+12, buf[i].addr, 4); ++ memcpy(da6.sin6_addr.s6_addr, + "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12); +- memcpy(da.sin6_addr.s6_addr+12, buf[i].addr, 4); ++ memcpy(da6.sin6_addr.s6_addr+12, buf[i].addr, 4); ++ memcpy(&da4.sin_addr, buf[i].addr, 4); ++ da = &da4; dalen = sizeof da4; ++ sa = &sa4; salen = sizeof sa4; + } +- const struct policy *dpolicy = policyof(&da.sin6_addr); +- int dscope = scopeof(&da.sin6_addr); ++ const struct policy *dpolicy = policyof(&da6.sin6_addr); ++ int dscope = scopeof(&da6.sin6_addr); + int dlabel = dpolicy->label; + int dprec = dpolicy->prec; + int prefixlen = 0; +- int fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_UDP); ++ int fd = socket(family, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_UDP); + if (fd >= 0) { +- if (!connect(fd, (void *)&da, sizeof da)) { ++ if (!connect(fd, da, dalen)) { + key |= DAS_USABLE; +- if (!getsockname(fd, (void *)&sa, +- &(socklen_t){sizeof sa})) { +- if (dscope == scopeof(&sa.sin6_addr)) ++ if (!getsockname(fd, sa, &salen)) { ++ if (family == AF_INET) memcpy( ++ &sa6.sin6_addr.s6_addr+12, ++ &sa4.sin_addr, 4); ++ if (dscope == scopeof(&sa6.sin6_addr)) + key |= DAS_MATCHINGSCOPE; +- if (dlabel == labelof(&sa.sin6_addr)) ++ if (dlabel == labelof(&sa6.sin6_addr)) + key |= DAS_MATCHINGLABEL; +- prefixlen = prefixmatch(&sa.sin6_addr, +- &da.sin6_addr); ++ prefixlen = prefixmatch(&sa6.sin6_addr, ++ &da6.sin6_addr); + } + } + close(fd); +diff --git a/src/process/execlp.c b/src/process/execlp.c +index 5eed886e..f6da398b 100644 +--- a/src/process/execlp.c ++++ b/src/process/execlp.c +@@ -1,6 +1,9 @@ + #include <unistd.h> ++#include <errno.h> + #include <stdarg.h> + ++extern int __execsh(const char *, char *const []); ++ + int execlp(const char *file, const char *argv0, ...) + { + int argc; +@@ -17,6 +20,11 @@ int execlp(const char *file, const char *argv0, ...) + argv[i] = va_arg(ap, char *); + argv[i] = NULL; + va_end(ap); +- return execvp(file, argv); ++ execvp(file, argv); ++ if (errno == ENOEXEC) { ++ errno = 0; ++ return __execsh(file, argv); ++ } ++ return -1; + } + } +diff --git a/src/process/execsh.c b/src/process/execsh.c +new file mode 100644 +index 00000000..180bb2aa +--- /dev/null ++++ b/src/process/execsh.c +@@ -0,0 +1,18 @@ ++#include <unistd.h> ++#include <errno.h> ++#include "libc.h" ++ ++int ++__execsh(const char *file, char *const argv[]) ++{ ++ int i, argc; ++ char **p; ++ ++ for (argc=1, p=(char **)argv; *p; ++argc, ++p); ++ ++ char *nargv[argc+1]; ++ nargv[0] = (char *)file; ++ for (i=0; i<argc; ++i) ++ nargv[i+1] = argv[i]; ++ return execv("/bin/sh", nargv); ++} +diff --git a/src/process/execvp.c b/src/process/execvp.c +index 2dddeddb..fdd0ca48 100644 +--- a/src/process/execvp.c ++++ b/src/process/execvp.c +@@ -6,6 +6,7 @@ + #include "libc.h" + + extern char **__environ; ++extern int __execsh(const char *, char *const []); + + int __execvpe(const char *file, char *const argv[], char *const envp[]) + { +@@ -56,7 +57,12 @@ int __execvpe(const char *file, char *const argv[], char *const envp[]) + + int execvp(const char *file, char *const argv[]) + { +- return __execvpe(file, argv, __environ); ++ __execvpe(file, argv, __environ); ++ if (errno == ENOEXEC) { ++ errno = 0; ++ return __execsh(file, argv); ++ } ++ return -1; + } + + weak_alias(__execvpe, execvpe); +diff --git a/src/process/system.c b/src/process/system.c +index 8cbdda06..0569461c 100644 +--- a/src/process/system.c ++++ b/src/process/system.c +@@ -19,7 +19,9 @@ int system(const char *cmd) + + pthread_testcancel(); + +- if (!cmd) return 1; ++ if (!cmd) { ++ return (access("/bin/sh", X_OK) == 0); ++ } + + sigaction(SIGINT, &sa, &oldint); + sigaction(SIGQUIT, &sa, &oldquit); +diff --git a/src/setjmp/m68k/longjmp.s b/src/setjmp/m68k/longjmp.s +new file mode 100644 +index 00000000..cdb05fb5 +--- /dev/null ++++ b/src/setjmp/m68k/longjmp.s +@@ -0,0 +1,14 @@ ++.global _longjmp ++.global longjmp ++.type _longjmp,@function ++.type longjmp,@function ++_longjmp: ++longjmp: ++ movea.l 4(%sp),%a0 ++ move.l 8(%sp),%d0 ++ bne 1f ++ move.l #1,%d0 ++1: movem.l (%a0),%d2-%d7/%a2-%a7 ++ fmovem.x 52(%a0),%fp2-%fp7 ++ move.l 48(%a0),(%sp) ++ rts +diff --git a/src/setjmp/m68k/setjmp.s b/src/setjmp/m68k/setjmp.s +new file mode 100644 +index 00000000..15e549b0 +--- /dev/null ++++ b/src/setjmp/m68k/setjmp.s +@@ -0,0 +1,18 @@ ++.global ___setjmp ++.hidden ___setjmp ++.global __setjmp ++.global _setjmp ++.global setjmp ++.type __setjmp,@function ++.type _setjmp,@function ++.type setjmp,@function ++___setjmp: ++__setjmp: ++_setjmp: ++setjmp: ++ movea.l 4(%sp),%a0 ++ movem.l %d2-%d7/%a2-%a7,(%a0) ++ move.l (%sp),48(%a0) ++ fmovem.x %fp2-%fp7,52(%a0) ++ clr.l %d0 ++ rts +diff --git a/src/signal/m68k/sigsetjmp.s b/src/signal/m68k/sigsetjmp.s +new file mode 100644 +index 00000000..09bfa646 +--- /dev/null ++++ b/src/signal/m68k/sigsetjmp.s +@@ -0,0 +1,29 @@ ++.global sigsetjmp ++.global __sigsetjmp ++.type sigsetjmp,@function ++.type __sigsetjmp,@function ++sigsetjmp: ++__sigsetjmp: ++ move.l 8(%sp),%d0 ++ beq 1f ++ ++ movea.l 4(%sp),%a1 ++ move.l (%sp)+,156(%a1) ++ move.l %a2,156+4+8(%a1) ++ movea.l %a1,%a2 ++ ++.hidden ___setjmp ++ lea ___setjmp-.-8,%a1 ++ jsr (%pc,%a1) ++ ++ move.l 156(%a2),-(%sp) ++ move.l %a2,4(%sp) ++ move.l %d0,8(%sp) ++ movea.l 156+4+8(%a2),%a2 ++ ++.hidden __sigsetjmp_tail ++ lea __sigsetjmp_tail-.-8,%a1 ++ jmp (%pc,%a1) ++ ++1: lea ___setjmp-.-8,%a1 ++ jmp (%pc,%a1) +diff --git a/src/signal/sigisemptyset.c b/src/signal/sigisemptyset.c +index 312c66cf..68b86624 100644 +--- a/src/signal/sigisemptyset.c ++++ b/src/signal/sigisemptyset.c +@@ -4,6 +4,7 @@ + + int sigisemptyset(const sigset_t *set) + { +- static const unsigned long zeroset[_NSIG/8/sizeof(long)]; +- return !memcmp(set, &zeroset, _NSIG/8); ++ for (size_t i=0; i<_NSIG/8/sizeof *set->__bits; i++) ++ if (set->__bits[i]) return 0; ++ return 1; + } +diff --git a/src/signal/sigrtmin.c b/src/signal/sigrtmin.c +index d0e769bb..c5a1fd92 100644 +--- a/src/signal/sigrtmin.c ++++ b/src/signal/sigrtmin.c +@@ -1,3 +1,5 @@ ++#include <signal.h> ++ + int __libc_current_sigrtmin() + { + return 35; +diff --git a/src/stdio/__lockfile.c b/src/stdio/__lockfile.c +index 9d967d6e..2ff75d8a 100644 +--- a/src/stdio/__lockfile.c ++++ b/src/stdio/__lockfile.c +@@ -1,28 +1,25 @@ + #include "stdio_impl.h" + #include "pthread_impl.h" + ++#define MAYBE_WAITERS 0x40000000 ++ + int __lockfile(FILE *f) + { +- int owner, tid = __pthread_self()->tid; +- if (f->lock == tid) ++ int owner = f->lock, tid = __pthread_self()->tid; ++ if ((owner & ~MAYBE_WAITERS) == tid) + return 0; +- while ((owner = a_cas(&f->lock, 0, tid))) +- __wait(&f->lock, &f->waiters, owner, 1); ++ for (;;) { ++ owner = a_cas(&f->lock, 0, tid); ++ if (!owner) return 1; ++ if (a_cas(&f->lock, owner, owner|MAYBE_WAITERS)==owner) break; ++ } ++ while ((owner = a_cas(&f->lock, 0, tid|MAYBE_WAITERS))) ++ __futexwait(&f->lock, owner, 1); + return 1; + } + + void __unlockfile(FILE *f) + { +- a_store(&f->lock, 0); +- +- /* The following read is technically invalid under situations +- * of self-synchronized destruction. Another thread may have +- * called fclose as soon as the above store has completed. +- * Nonetheless, since FILE objects always live in memory +- * obtained by malloc from the heap, it's safe to assume +- * the dereferences below will not fault. In the worst case, +- * a spurious syscall will be made. If the implementation of +- * malloc changes, this assumption needs revisiting. */ +- +- if (f->waiters) __wake(&f->lock, 1, 1); ++ if (a_swap(&f->lock, 0) & MAYBE_WAITERS) ++ __wake(&f->lock, 1, 1); + } +diff --git a/src/stdio/__stdio_read.c b/src/stdio/__stdio_read.c +index f8fa6d3b..ea675da3 100644 +--- a/src/stdio/__stdio_read.c ++++ b/src/stdio/__stdio_read.c +@@ -9,10 +9,11 @@ size_t __stdio_read(FILE *f, unsigned char *buf, size_t len) + }; + ssize_t cnt; + +- cnt = syscall(SYS_readv, f->fd, iov, 2); ++ cnt = iov[0].iov_len ? syscall(SYS_readv, f->fd, iov, 2) ++ : syscall(SYS_read, f->fd, iov[1].iov_base, iov[1].iov_len); + if (cnt <= 0) { +- f->flags |= F_EOF ^ ((F_ERR^F_EOF) & cnt); +- return cnt; ++ f->flags |= cnt ? F_ERR : F_EOF; ++ return 0; + } + if (cnt <= iov[0].iov_len) return cnt; + cnt -= iov[0].iov_len; +diff --git a/src/stdio/__towrite.c b/src/stdio/__towrite.c +index 0a69d926..b022cbca 100644 +--- a/src/stdio/__towrite.c ++++ b/src/stdio/__towrite.c +@@ -3,7 +3,7 @@ + int __towrite(FILE *f) + { + f->mode |= f->mode-1; +- if (f->flags & (F_NOWR)) { ++ if (f->flags & F_NOWR) { + f->flags |= F_ERR; + return EOF; + } +diff --git a/src/stdio/fclose.c b/src/stdio/fclose.c +index d687a877..c675413d 100644 +--- a/src/stdio/fclose.c ++++ b/src/stdio/fclose.c +@@ -24,7 +24,7 @@ int fclose(FILE *f) + r = fflush(f); + r |= f->close(f); + +- if (f->getln_buf) free(f->getln_buf); ++ free(f->getln_buf); + if (!perm) free(f); + else FUNLOCK(f); + +diff --git a/src/stdio/fgetpos.c b/src/stdio/fgetpos.c +index c3fa0eb0..6eb361e1 100644 +--- a/src/stdio/fgetpos.c ++++ b/src/stdio/fgetpos.c +@@ -4,7 +4,7 @@ int fgetpos(FILE *restrict f, fpos_t *restrict pos) + { + off_t off = __ftello(f); + if (off < 0) return -1; +- *(off_t *)pos = off; ++ *(long long *)pos = off; + return 0; + } + +diff --git a/src/stdio/flockfile.c b/src/stdio/flockfile.c +index a196c1ef..6806cf8b 100644 +--- a/src/stdio/flockfile.c ++++ b/src/stdio/flockfile.c +@@ -1,10 +1,11 @@ + #include "stdio_impl.h" + #include "pthread_impl.h" + ++void __register_locked_file(FILE *, pthread_t); ++ + void flockfile(FILE *f) + { +- while (ftrylockfile(f)) { +- int owner = f->lock; +- if (owner) __wait(&f->lock, &f->waiters, owner, 1); +- } ++ if (!ftrylockfile(f)) return; ++ __lockfile(f); ++ __register_locked_file(f, __pthread_self()); + } +diff --git a/src/stdio/fmemopen.c b/src/stdio/fmemopen.c +index 2ce43d32..fb2656e3 100644 +--- a/src/stdio/fmemopen.c ++++ b/src/stdio/fmemopen.c +@@ -9,6 +9,12 @@ struct cookie { + int mode; + }; + ++struct mem_FILE { ++ FILE f; ++ struct cookie c; ++ unsigned char buf[UNGET+BUFSIZ], buf2[]; ++}; ++ + static off_t mseek(FILE *f, off_t off, int whence) + { + ssize_t base; +@@ -72,8 +78,7 @@ static int mclose(FILE *m) + + FILE *fmemopen(void *restrict buf, size_t size, const char *restrict mode) + { +- FILE *f; +- struct cookie *c; ++ struct mem_FILE *f; + int plus = !!strchr(mode, '+'); + + if (!size || !strchr("rwa", *mode)) { +@@ -86,29 +91,34 @@ FILE *fmemopen(void *restrict buf, size_t size, const char *restrict mode) + return 0; + } + +- f = calloc(sizeof *f + sizeof *c + UNGET + BUFSIZ + (buf?0:size), 1); ++ f = malloc(sizeof *f + (buf?0:size)); + if (!f) return 0; +- f->cookie = c = (void *)(f+1); +- f->fd = -1; +- f->lbf = EOF; +- f->buf = (unsigned char *)(c+1) + UNGET; +- f->buf_size = BUFSIZ; +- if (!buf) buf = f->buf + BUFSIZ; ++ memset(&f->f, 0, sizeof f->f); ++ f->f.cookie = &f->c; ++ f->f.fd = -1; ++ f->f.lbf = EOF; ++ f->f.buf = f->buf + UNGET; ++ f->f.buf_size = sizeof f->buf - UNGET; ++ if (!buf) { ++ buf = f->buf2;; ++ memset(buf, 0, size); ++ } + +- c->buf = buf; +- c->size = size; +- c->mode = *mode; ++ memset(&f->c, 0, sizeof f->c); ++ f->c.buf = buf; ++ f->c.size = size; ++ f->c.mode = *mode; + +- if (!plus) f->flags = (*mode == 'r') ? F_NOWR : F_NORD; +- if (*mode == 'r') c->len = size; +- else if (*mode == 'a') c->len = c->pos = strnlen(buf, size); ++ if (!plus) f->f.flags = (*mode == 'r') ? F_NOWR : F_NORD; ++ if (*mode == 'r') f->c.len = size; ++ else if (*mode == 'a') f->c.len = f->c.pos = strnlen(buf, size); + +- f->read = mread; +- f->write = mwrite; +- f->seek = mseek; +- f->close = mclose; ++ f->f.read = mread; ++ f->f.write = mwrite; ++ f->f.seek = mseek; ++ f->f.close = mclose; + +- if (!libc.threaded) f->lock = -1; ++ if (!libc.threaded) f->f.lock = -1; + +- return __ofl_add(f); ++ return __ofl_add(&f->f); + } +diff --git a/src/stdio/fopencookie.c b/src/stdio/fopencookie.c +index 2f46dd53..da042fe8 100644 +--- a/src/stdio/fopencookie.c ++++ b/src/stdio/fopencookie.c +@@ -116,15 +116,12 @@ FILE *fopencookie(void *cookie, const char *mode, cookie_io_functions_t iofuncs) + + /* Set up our fcookie */ + f->fc.cookie = cookie; +- f->fc.iofuncs.read = iofuncs.read; +- f->fc.iofuncs.write = iofuncs.write; +- f->fc.iofuncs.seek = iofuncs.seek; +- f->fc.iofuncs.close = iofuncs.close; ++ f->fc.iofuncs = iofuncs; + + f->f.fd = -1; + f->f.cookie = &f->fc; + f->f.buf = f->buf + UNGET; +- f->f.buf_size = BUFSIZ; ++ f->f.buf_size = sizeof f->buf - UNGET; + f->f.lbf = EOF; + + /* Initialize op ptrs. No problem if some are unneeded. */ +diff --git a/src/stdio/fread.c b/src/stdio/fread.c +index aef75f73..733d3716 100644 +--- a/src/stdio/fread.c ++++ b/src/stdio/fread.c +@@ -25,7 +25,7 @@ size_t fread(void *restrict destv, size_t size, size_t nmemb, FILE *restrict f) + /* Read the remainder directly */ + for (; l; l-=k, dest+=k) { + k = __toread(f) ? 0 : f->read(f, dest, l); +- if (k+1<=1) { ++ if (!k) { + FUNLOCK(f); + return (len-l)/size; + } +diff --git a/src/stdio/fsetpos.c b/src/stdio/fsetpos.c +index 5d76c8cd..6310424e 100644 +--- a/src/stdio/fsetpos.c ++++ b/src/stdio/fsetpos.c +@@ -2,7 +2,7 @@ + + int fsetpos(FILE *f, const fpos_t *pos) + { +- return __fseeko(f, *(const off_t *)pos, SEEK_SET); ++ return __fseeko(f, *(const long long *)pos, SEEK_SET); + } + + LFS64(fsetpos); +diff --git a/src/stdio/ftrylockfile.c b/src/stdio/ftrylockfile.c +index eb13c839..3b97807a 100644 +--- a/src/stdio/ftrylockfile.c ++++ b/src/stdio/ftrylockfile.c +@@ -2,6 +2,8 @@ + #include "pthread_impl.h" + #include <limits.h> + ++#define MAYBE_WAITERS 0x40000000 ++ + void __do_orphaned_stdio_locks() + { + FILE *f; +@@ -18,23 +20,29 @@ void __unlist_locked_file(FILE *f) + } + } + ++void __register_locked_file(FILE *f, pthread_t self) ++{ ++ f->lockcount = 1; ++ f->prev_locked = 0; ++ f->next_locked = self->stdio_locks; ++ if (f->next_locked) f->next_locked->prev_locked = f; ++ self->stdio_locks = f; ++} ++ + int ftrylockfile(FILE *f) + { + pthread_t self = __pthread_self(); + int tid = self->tid; +- if (f->lock == tid) { ++ int owner = f->lock; ++ if ((owner & ~MAYBE_WAITERS) == tid) { + if (f->lockcount == LONG_MAX) + return -1; + f->lockcount++; + return 0; + } +- if (f->lock < 0) f->lock = 0; +- if (f->lock || a_cas(&f->lock, 0, tid)) ++ if (owner < 0) f->lock = owner = 0; ++ if (owner || a_cas(&f->lock, 0, tid)) + return -1; +- f->lockcount = 1; +- f->prev_locked = 0; +- f->next_locked = self->stdio_locks; +- if (f->next_locked) f->next_locked->prev_locked = f; +- self->stdio_locks = f; ++ __register_locked_file(f, self); + return 0; + } +diff --git a/src/stdio/getdelim.c b/src/stdio/getdelim.c +index 1ccd8029..d4b23882 100644 +--- a/src/stdio/getdelim.c ++++ b/src/stdio/getdelim.c +@@ -3,8 +3,6 @@ + #include <inttypes.h> + #include <errno.h> + +-#define MIN(a,b) ((a)<(b) ? (a) : (b)) +- + ssize_t getdelim(char **restrict s, size_t *restrict n, int delim, FILE *restrict f) + { + char *tmp; +diff --git a/src/stdio/open_memstream.c b/src/stdio/open_memstream.c +index eab024da..ee834234 100644 +--- a/src/stdio/open_memstream.c ++++ b/src/stdio/open_memstream.c +@@ -12,6 +12,12 @@ struct cookie { + size_t space; + }; + ++struct ms_FILE { ++ FILE f; ++ struct cookie c; ++ unsigned char buf[BUFSIZ]; ++}; ++ + static off_t ms_seek(FILE *f, off_t off, int whence) + { + ssize_t base; +@@ -57,34 +63,34 @@ static int ms_close(FILE *f) + + FILE *open_memstream(char **bufp, size_t *sizep) + { +- FILE *f; +- struct cookie *c; ++ struct ms_FILE *f; + char *buf; + +- if (!(f=malloc(sizeof *f + sizeof *c + BUFSIZ))) return 0; ++ if (!(f=malloc(sizeof *f))) return 0; + if (!(buf=malloc(sizeof *buf))) { + free(f); + return 0; + } +- memset(f, 0, sizeof *f + sizeof *c); +- f->cookie = c = (void *)(f+1); ++ memset(&f->f, 0, sizeof f->f); ++ memset(&f->c, 0, sizeof f->c); ++ f->f.cookie = &f->c; + +- c->bufp = bufp; +- c->sizep = sizep; +- c->pos = c->len = c->space = *sizep = 0; +- c->buf = *bufp = buf; ++ f->c.bufp = bufp; ++ f->c.sizep = sizep; ++ f->c.pos = f->c.len = f->c.space = *sizep = 0; ++ f->c.buf = *bufp = buf; + *buf = 0; + +- f->flags = F_NORD; +- f->fd = -1; +- f->buf = (void *)(c+1); +- f->buf_size = BUFSIZ; +- f->lbf = EOF; +- f->write = ms_write; +- f->seek = ms_seek; +- f->close = ms_close; ++ f->f.flags = F_NORD; ++ f->f.fd = -1; ++ f->f.buf = f->buf; ++ f->f.buf_size = sizeof f->buf; ++ f->f.lbf = EOF; ++ f->f.write = ms_write; ++ f->f.seek = ms_seek; ++ f->f.close = ms_close; + +- if (!libc.threaded) f->lock = -1; ++ if (!libc.threaded) f->f.lock = -1; + +- return __ofl_add(f); ++ return __ofl_add(&f->f); + } +diff --git a/src/stdio/open_wmemstream.c b/src/stdio/open_wmemstream.c +index 4d90cd97..cb693ea7 100644 +--- a/src/stdio/open_wmemstream.c ++++ b/src/stdio/open_wmemstream.c +@@ -14,6 +14,12 @@ struct cookie { + mbstate_t mbs; + }; + ++struct wms_FILE { ++ FILE f; ++ struct cookie c; ++ unsigned char buf[1]; ++}; ++ + static off_t wms_seek(FILE *f, off_t off, int whence) + { + ssize_t base; +@@ -59,34 +65,34 @@ static int wms_close(FILE *f) + + FILE *open_wmemstream(wchar_t **bufp, size_t *sizep) + { +- FILE *f; +- struct cookie *c; ++ struct wms_FILE *f; + wchar_t *buf; + +- if (!(f=malloc(sizeof *f + sizeof *c))) return 0; ++ if (!(f=malloc(sizeof *f))) return 0; + if (!(buf=malloc(sizeof *buf))) { + free(f); + return 0; + } +- memset(f, 0, sizeof *f + sizeof *c); +- f->cookie = c = (void *)(f+1); ++ memset(&f->f, 0, sizeof f->f); ++ memset(&f->c, 0, sizeof f->c); ++ f->f.cookie = &f->c; + +- c->bufp = bufp; +- c->sizep = sizep; +- c->pos = c->len = c->space = *sizep = 0; +- c->buf = *bufp = buf; ++ f->c.bufp = bufp; ++ f->c.sizep = sizep; ++ f->c.pos = f->c.len = f->c.space = *sizep = 0; ++ f->c.buf = *bufp = buf; + *buf = 0; + +- f->flags = F_NORD; +- f->fd = -1; +- f->buf = (void *)(c+1); +- f->buf_size = 0; +- f->lbf = EOF; +- f->write = wms_write; +- f->seek = wms_seek; +- f->close = wms_close; ++ f->f.flags = F_NORD; ++ f->f.fd = -1; ++ f->f.buf = f->buf; ++ f->f.buf_size = 0; ++ f->f.lbf = EOF; ++ f->f.write = wms_write; ++ f->f.seek = wms_seek; ++ f->f.close = wms_close; + +- if (!libc.threaded) f->lock = -1; ++ if (!libc.threaded) f->f.lock = -1; + +- return __ofl_add(f); ++ return __ofl_add(&f->f); + } +diff --git a/src/stdio/setvbuf.c b/src/stdio/setvbuf.c +index 541a125f..06ea296c 100644 +--- a/src/stdio/setvbuf.c ++++ b/src/stdio/setvbuf.c +@@ -1,22 +1,25 @@ + #include "stdio_impl.h" + +-/* This function makes no attempt to protect the user from his/her own +- * stupidity. If called any time but when then ISO C standard specifically +- * allows it, all hell can and will break loose, especially with threads! +- * +- * This implementation ignores all arguments except the buffering type, +- * and uses the existing buffer allocated alongside the FILE object. +- * In the case of stderr where the preexisting buffer is length 1, it +- * is not possible to set line buffering or full buffering. */ ++/* The behavior of this function is undefined except when it is the first ++ * operation on the stream, so the presence or absence of locking is not ++ * observable in a program whose behavior is defined. Thus no locking is ++ * performed here. No allocation of buffers is performed, but a buffer ++ * provided by the caller is used as long as it is suitably sized. */ + + int setvbuf(FILE *restrict f, char *restrict buf, int type, size_t size) + { + f->lbf = EOF; + +- if (type == _IONBF) ++ if (type == _IONBF) { + f->buf_size = 0; +- else if (type == _IOLBF) +- f->lbf = '\n'; ++ } else { ++ if (buf && size >= UNGET) { ++ f->buf = (void *)(buf + UNGET); ++ f->buf_size = size - UNGET; ++ } ++ if (type == _IOLBF && f->buf_size) ++ f->lbf = '\n'; ++ } + + f->flags |= F_SVB; + +diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c +index 50fb55c1..5e7be717 100644 +--- a/src/stdio/vfprintf.c ++++ b/src/stdio/vfprintf.c +@@ -220,6 +220,7 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t) + else re=LDBL_MANT_DIG/4-1-p; + + if (re) { ++ round *= 1<<(LDBL_MANT_DIG%4); + while (re--) round*=16; + if (*prefix=='-') { + y=-y; +diff --git a/src/stdio/vfwprintf.c b/src/stdio/vfwprintf.c +index e87ad42a..9d774fcc 100644 +--- a/src/stdio/vfwprintf.c ++++ b/src/stdio/vfwprintf.c +@@ -255,8 +255,11 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_ + } + continue; + case 'c': ++ if (w<1) w=1; ++ if (w>1 && !(fl&LEFT_ADJ)) fprintf(f, "%*s", w-1, ""); + fputwc(btowc(arg.i), f); +- l = 1; ++ if (w>1 && (fl&LEFT_ADJ)) fprintf(f, "%*s", w-1, ""); ++ l = w; + continue; + case 'C': + fputwc(arg.i, f); +diff --git a/src/stdio/vswprintf.c b/src/stdio/vswprintf.c +index 6eb2f6ac..38efed65 100644 +--- a/src/stdio/vswprintf.c ++++ b/src/stdio/vswprintf.c +@@ -1,6 +1,5 @@ + #include "stdio_impl.h" + #include <limits.h> +-#include <string.h> + #include <errno.h> + #include <stdint.h> + #include <wchar.h> +@@ -37,17 +36,17 @@ static size_t sw_write(FILE *f, const unsigned char *s, size_t l) + int vswprintf(wchar_t *restrict s, size_t n, const wchar_t *restrict fmt, va_list ap) + { + int r; +- FILE f; + unsigned char buf[256]; + struct cookie c = { s, n-1 }; ++ FILE f = { ++ .lbf = EOF, ++ .write = sw_write, ++ .lock = -1, ++ .buf = buf, ++ .buf_size = sizeof buf, ++ .cookie = &c, ++ }; + +- memset(&f, 0, sizeof(FILE)); +- f.lbf = EOF; +- f.write = sw_write; +- f.buf_size = sizeof buf; +- f.buf = buf; +- f.lock = -1; +- f.cookie = &c; + if (!n) { + return -1; + } else if (n > INT_MAX) { +diff --git a/src/stdlib/abs.c b/src/stdlib/abs.c +index 4806d629..e721fdc2 100644 +--- a/src/stdlib/abs.c ++++ b/src/stdlib/abs.c +@@ -1,3 +1,5 @@ ++#include <stdlib.h> ++ + int abs(int a) + { + return a>0 ? a : -a; +diff --git a/src/stdlib/bsearch.c b/src/stdlib/bsearch.c +index 61d89367..fe050ea3 100644 +--- a/src/stdlib/bsearch.c ++++ b/src/stdlib/bsearch.c +@@ -7,13 +7,13 @@ void *bsearch(const void *key, const void *base, size_t nel, size_t width, int ( + while (nel > 0) { + try = (char *)base + width*(nel/2); + sign = cmp(key, try); +- if (!sign) return try; +- else if (nel == 1) break; +- else if (sign < 0) ++ if (sign < 0) { + nel /= 2; +- else { +- base = try; +- nel -= nel/2; ++ } else if (sign > 0) { ++ base = (char *)try + width; ++ nel -= nel/2+1; ++ } else { ++ return try; + } + } + return NULL; +diff --git a/src/stdlib/labs.c b/src/stdlib/labs.c +index 675b95b8..83ddb147 100644 +--- a/src/stdlib/labs.c ++++ b/src/stdlib/labs.c +@@ -1,3 +1,5 @@ ++#include <stdlib.h> ++ + long labs(long a) + { + return a>0 ? a : -a; +diff --git a/src/stdlib/llabs.c b/src/stdlib/llabs.c +index bec4a03d..9dfaf5cf 100644 +--- a/src/stdlib/llabs.c ++++ b/src/stdlib/llabs.c +@@ -1,3 +1,5 @@ ++#include <stdlib.h> ++ + long long llabs(long long a) + { + return a>0 ? a : -a; +diff --git a/src/string/explicit_bzero.c b/src/string/explicit_bzero.c +new file mode 100644 +index 00000000..f2e12f23 +--- /dev/null ++++ b/src/string/explicit_bzero.c +@@ -0,0 +1,8 @@ ++#define _BSD_SOURCE ++#include <string.h> ++ ++void explicit_bzero(void *d, size_t n) ++{ ++ d = memset(d, 0, n); ++ __asm__ __volatile__ ("" : : "r"(d) : "memory"); ++} +diff --git a/src/thread/default_attr.c b/src/thread/default_attr.c +new file mode 100644 +index 00000000..46fe98ee +--- /dev/null ++++ b/src/thread/default_attr.c +@@ -0,0 +1,4 @@ ++#include "pthread_impl.h" ++ ++size_t __default_stacksize = DEFAULT_STACK_SIZE; ++size_t __default_guardsize = DEFAULT_GUARD_SIZE; +diff --git a/src/thread/m68k/__m68k_read_tp.s b/src/thread/m68k/__m68k_read_tp.s +new file mode 100644 +index 00000000..86886da8 +--- /dev/null ++++ b/src/thread/m68k/__m68k_read_tp.s +@@ -0,0 +1,8 @@ ++.text ++.global __m68k_read_tp ++.type __m68k_read_tp,@function ++__m68k_read_tp: ++ move.l #333,%d0 ++ trap #0 ++ move.l %d0,%a0 ++ rts +diff --git a/src/thread/m68k/clone.s b/src/thread/m68k/clone.s +new file mode 100644 +index 00000000..5b61b6fa +--- /dev/null ++++ b/src/thread/m68k/clone.s +@@ -0,0 +1,24 @@ ++.text ++.global __clone ++.type __clone,@function ++__clone: ++ movem.l %d2-%d5,-(%sp) ++ move.l #120,%d0 ++ move.l 28(%sp),%d1 ++ move.l 24(%sp),%d2 ++ and.l #-16,%d2 ++ move.l 36(%sp),%d3 ++ move.l 44(%sp),%d4 ++ move.l 40(%sp),%d5 ++ move.l 20(%sp),%a0 ++ move.l 32(%sp),%a1 ++ trap #0 ++ tst.l %d0 ++ beq 1f ++ movem.l (%sp)+,%d2-%d5 ++ rts ++1: move.l %a1,-(%sp) ++ jsr (%a0) ++ move.l #1,%d0 ++ trap #0 ++ clr.b 0 +diff --git a/src/thread/m68k/syscall_cp.s b/src/thread/m68k/syscall_cp.s +new file mode 100644 +index 00000000..5628a896 +--- /dev/null ++++ b/src/thread/m68k/syscall_cp.s +@@ -0,0 +1,26 @@ ++.text ++.global __cp_begin ++.hidden __cp_begin ++.global __cp_end ++.hidden __cp_end ++.global __cp_cancel ++.hidden __cp_cancel ++.hidden __cancel ++.global __syscall_cp_asm ++.hidden __syscall_cp_asm ++.type __syscall_cp_asm,@function ++__syscall_cp_asm: ++ movem.l %d2-%d5,-(%sp) ++ movea.l 20(%sp),%a0 ++__cp_begin: ++ move.l (%a0),%d0 ++ bne __cp_cancel ++ movem.l 24(%sp),%d0-%d5/%a0 ++ trap #0 ++__cp_end: ++ movem.l (%sp)+,%d2-%d5 ++ rts ++__cp_cancel: ++ movem.l (%sp)+,%d2-%d5 ++ move.l __cancel-.-8,%a1 ++ jmp (%pc,%a1) +diff --git a/src/thread/mips/clone.s b/src/thread/mips/clone.s +index 37dddf57..30a0146b 100644 +--- a/src/thread/mips/clone.s ++++ b/src/thread/mips/clone.s +@@ -28,5 +28,8 @@ __clone: + nop + 1: lw $25, 0($sp) + lw $4, 4($sp) +- jr $25 ++ jalr $25 + nop ++ move $4, $2 ++ li $2, 4001 ++ syscall +diff --git a/src/thread/mips64/clone.s b/src/thread/mips64/clone.s +index 229d2677..1b71e07c 100644 +--- a/src/thread/mips64/clone.s ++++ b/src/thread/mips64/clone.s +@@ -26,5 +26,8 @@ __clone: + nop + 1: ld $25, 0($sp) # function pointer + ld $4, 8($sp) # argument pointer +- jr $25 # call the user's function ++ jalr $25 # call the user's function + nop ++ move $4, $2 ++ li $2, 5058 ++ syscall +diff --git a/src/thread/mipsn32/clone.s b/src/thread/mipsn32/clone.s +index 51035852..ebf5dbea 100644 +--- a/src/thread/mipsn32/clone.s ++++ b/src/thread/mipsn32/clone.s +@@ -26,5 +26,8 @@ __clone: + nop + 1: lw $25, 0($sp) # function pointer + lw $4, 4($sp) # argument pointer +- jr $25 # call the user's function ++ jalr $25 # call the user's function + nop ++ move $4, $2 ++ li $2, 6058 ++ syscall +diff --git a/src/thread/pthread_attr_init.c b/src/thread/pthread_attr_init.c +index 8f6e3374..a962b460 100644 +--- a/src/thread/pthread_attr_init.c ++++ b/src/thread/pthread_attr_init.c +@@ -1,9 +1,12 @@ + #include "pthread_impl.h" + ++extern size_t __default_stacksize; ++extern size_t __default_guardsize; ++ + int pthread_attr_init(pthread_attr_t *a) + { + *a = (pthread_attr_t){0}; +- a->_a_stacksize = DEFAULT_STACK_SIZE; +- a->_a_guardsize = DEFAULT_GUARD_SIZE; ++ a->_a_stacksize = __default_stacksize; ++ a->_a_guardsize = __default_guardsize; + return 0; + } +diff --git a/src/thread/pthread_attr_setinheritsched.c b/src/thread/pthread_attr_setinheritsched.c +index c91d8f83..e540e846 100644 +--- a/src/thread/pthread_attr_setinheritsched.c ++++ b/src/thread/pthread_attr_setinheritsched.c +@@ -1,4 +1,25 @@ + #include "pthread_impl.h" ++#include "syscall.h" ++ ++__attribute__((__visibility__("hidden"))) ++void *__start_sched(void *p) ++{ ++ struct start_sched_args *ssa = p; ++ void *start_arg = ssa->start_arg; ++ void *(*start_fn)(void *) = ssa->start_fn; ++ pthread_t self = __pthread_self(); ++ ++ int ret = -__syscall(SYS_sched_setscheduler, self->tid, ++ ssa->attr->_a_policy, &ssa->attr->_a_prio); ++ if (!ret) __restore_sigs(&ssa->mask); ++ a_store(&ssa->futex, ret); ++ __wake(&ssa->futex, 1, 1); ++ if (ret) { ++ self->detach_state = DT_DYNAMIC; ++ return 0; ++ } ++ return start_fn(start_arg); ++} + + int pthread_attr_setinheritsched(pthread_attr_t *a, int inherit) + { +diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c +index 439ee363..27ace2c6 100644 +--- a/src/thread/pthread_create.c ++++ b/src/thread/pthread_create.c +@@ -19,6 +19,12 @@ weak_alias(dummy_0, __pthread_tsd_run_dtors); + weak_alias(dummy_0, __do_orphaned_stdio_locks); + weak_alias(dummy_0, __dl_thread_cleanup); + ++static void *dummy_1(void *p) ++{ ++ return 0; ++} ++weak_alias(dummy_1, __start_sched); ++ + _Noreturn void __pthread_exit(void *result) + { + pthread_t self = __pthread_self(); +@@ -37,11 +43,11 @@ _Noreturn void __pthread_exit(void *result) + + __pthread_tsd_run_dtors(); + +- LOCK(self->exitlock); +- +- /* Mark this thread dead before decrementing count */ ++ /* Access to target the exiting thread with syscalls that use ++ * its kernel tid is controlled by killlock. For detached threads, ++ * any use past this point would have undefined behavior, but for ++ * joinable threads it's a valid usage that must be handled. */ + LOCK(self->killlock); +- self->dead = 1; + + /* Block all signals before decrementing the live thread count. + * This is important to ensure that dynamically allocated TLS +@@ -49,20 +55,14 @@ _Noreturn void __pthread_exit(void *result) + * reasons as well. */ + __block_all_sigs(&set); + +- /* Wait to unlock the kill lock, which governs functions like +- * pthread_kill which target a thread id, until signals have +- * been blocked. This precludes observation of the thread id +- * as a live thread (with application code running in it) after +- * the thread was reported dead by ESRCH being returned. */ +- UNLOCK(self->killlock); +- + /* It's impossible to determine whether this is "the last thread" + * until performing the atomic decrement, since multiple threads + * could exit at the same time. For the last thread, revert the +- * decrement and unblock signals to give the atexit handlers and +- * stdio cleanup code a consistent state. */ ++ * decrement, restore the tid, and unblock signals to give the ++ * atexit handlers and stdio cleanup code a consistent state. */ + if (a_fetch_add(&libc.threads_minus_1, -1)==0) { + libc.threads_minus_1 = 0; ++ UNLOCK(self->killlock); + __restore_sigs(&set); + exit(0); + } +@@ -89,15 +89,19 @@ _Noreturn void __pthread_exit(void *result) + __do_orphaned_stdio_locks(); + __dl_thread_cleanup(); + +- if (self->detached && self->map_base) { ++ /* This atomic potentially competes with a concurrent pthread_detach ++ * call; the loser is responsible for freeing thread resources. */ ++ int state = a_cas(&self->detach_state, DT_JOINABLE, DT_EXITING); ++ ++ if (state>=DT_DETACHED && self->map_base) { + /* Detached threads must avoid the kernel clear_child_tid + * feature, since the virtual address will have been + * unmapped and possibly already reused by a new mapping + * at the time the kernel would perform the write. In + * the case of threads that started out detached, the + * initial clone flags are correct, but if the thread was +- * detached later (== 2), we need to clear it here. */ +- if (self->detached == 2) __syscall(SYS_set_tid_address, 0); ++ * detached later, we need to clear it here. */ ++ if (state == DT_DYNAMIC) __syscall(SYS_set_tid_address, 0); + + /* Robust list will no longer be valid, and was already + * processed above, so unregister it with the kernel. */ +@@ -113,6 +117,12 @@ _Noreturn void __pthread_exit(void *result) + __unmapself(self->map_base, self->map_size); + } + ++ /* After the kernel thread exits, its tid may be reused. Clear it ++ * to prevent inadvertent use and inform functions that would use ++ * it that it's no longer available. */ ++ self->tid = 0; ++ UNLOCK(self->killlock); ++ + for (;;) __syscall(SYS_exit, 0); + } + +@@ -131,19 +141,6 @@ void __do_cleanup_pop(struct __ptcb *cb) + static int start(void *p) + { + pthread_t self = p; +- /* States for startlock: +- * 0 = no need for start sync +- * 1 = waiting for parent to do work +- * 2 = failure in parent, child must abort +- * 3 = success in parent, child must restore sigmask */ +- if (self->startlock[0]) { +- __wait(self->startlock, 0, 1, 1); +- if (self->startlock[0] == 2) { +- self->detached = 2; +- pthread_exit(0); +- } +- __restore_sigs(self->sigmask); +- } + if (self->unblock_cancel) + __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, + SIGPT_SET, 0, _NSIG/8); +@@ -168,8 +165,8 @@ static void *dummy_tsd[1] = { 0 }; + weak_alias(dummy_tsd, __pthread_tsd_main); + + volatile int __block_new_threads = 0; +-size_t __default_stacksize = DEFAULT_STACK_SIZE; +-size_t __default_guardsize = DEFAULT_GUARD_SIZE; ++extern size_t __default_stacksize; ++extern size_t __default_guardsize; + + static FILE *volatile dummy_file = 0; + weak_alias(dummy_file, __stdin_used); +@@ -194,6 +191,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att + | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_DETACHED; + int do_sched = 0; + pthread_attr_t attr = { 0 }; ++ struct start_sched_args ssa; + + if (!libc.can_do_threads) return ENOSYS; + self = __pthread_self(); +@@ -272,24 +270,32 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att + new->tsd = (void *)tsd; + new->locale = &libc.global_locale; + if (attr._a_detach) { +- new->detached = 1; ++ new->detach_state = DT_DETACHED; + flags -= CLONE_CHILD_CLEARTID; ++ } else { ++ new->detach_state = DT_JOINABLE; + } + if (attr._a_sched) { +- do_sched = new->startlock[0] = 1; +- __block_app_sigs(new->sigmask); ++ do_sched = 1; ++ ssa.futex = -1; ++ ssa.start_fn = new->start; ++ ssa.start_arg = new->start_arg; ++ ssa.attr = &attr; ++ new->start = __start_sched; ++ new->start_arg = &ssa; ++ __block_app_sigs(&ssa.mask); + } + new->robust_list.head = &new->robust_list.head; + new->unblock_cancel = self->cancel; + new->CANARY = self->CANARY; + + a_inc(&libc.threads_minus_1); +- ret = __clone((c11 ? start_c11 : start), stack, flags, new, &new->tid, TP_ADJ(new), &new->tid); ++ ret = __clone((c11 ? start_c11 : start), stack, flags, new, &new->tid, TP_ADJ(new), &new->detach_state); + + __release_ptc(); + + if (do_sched) { +- __restore_sigs(new->sigmask); ++ __restore_sigs(&ssa.mask); + } + + if (ret < 0) { +@@ -299,11 +305,9 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att + } + + if (do_sched) { +- ret = __syscall(SYS_sched_setscheduler, new->tid, +- attr._a_policy, &attr._a_prio); +- a_store(new->startlock, ret<0 ? 2 : 3); +- __wake(new->startlock, 1, 1); +- if (ret < 0) return -ret; ++ __futexwait(&ssa.futex, -1, 1); ++ ret = ssa.futex; ++ if (ret) return ret; + } + + *res = new; +diff --git a/src/thread/pthread_detach.c b/src/thread/pthread_detach.c +index 692bbaf9..9cee7a89 100644 +--- a/src/thread/pthread_detach.c ++++ b/src/thread/pthread_detach.c +@@ -5,11 +5,10 @@ int __pthread_join(pthread_t, void **); + + static int __pthread_detach(pthread_t t) + { +- /* Cannot detach a thread that's already exiting */ +- if (a_cas(t->exitlock, 0, INT_MIN + 1)) ++ /* If the cas fails, detach state is either already-detached ++ * or exiting/exited, and pthread_join will trap or cleanup. */ ++ if (a_cas(&t->detach_state, DT_JOINABLE, DT_DYNAMIC) != DT_JOINABLE) + return __pthread_join(t, 0); +- t->detached = 2; +- UNLOCK(t->exitlock); + return 0; + } + +diff --git a/src/thread/pthread_getattr_np.c b/src/thread/pthread_getattr_np.c +index 29a209bd..2881831f 100644 +--- a/src/thread/pthread_getattr_np.c ++++ b/src/thread/pthread_getattr_np.c +@@ -6,7 +6,7 @@ + int pthread_getattr_np(pthread_t t, pthread_attr_t *a) + { + *a = (pthread_attr_t){0}; +- a->_a_detach = !!t->detached; ++ a->_a_detach = t->detach_state>=DT_DETACHED; + a->_a_guardsize = t->guard_size; + if (t->stack) { + a->_a_stackaddr = (uintptr_t)t->stack; +diff --git a/src/thread/pthread_getschedparam.c b/src/thread/pthread_getschedparam.c +index a994b637..05be4242 100644 +--- a/src/thread/pthread_getschedparam.c ++++ b/src/thread/pthread_getschedparam.c +@@ -4,7 +4,7 @@ int pthread_getschedparam(pthread_t t, int *restrict policy, struct sched_param + { + int r; + LOCK(t->killlock); +- if (t->dead) { ++ if (!t->tid) { + r = ESRCH; + } else { + r = -__syscall(SYS_sched_getparam, t->tid, param); +diff --git a/src/thread/pthread_join.c b/src/thread/pthread_join.c +index b7175c09..18264da6 100644 +--- a/src/thread/pthread_join.c ++++ b/src/thread/pthread_join.c +@@ -7,13 +7,14 @@ int __pthread_setcancelstate(int, int *); + + int __pthread_timedjoin_np(pthread_t t, void **res, const struct timespec *at) + { +- int tmp, cs, r = 0; ++ int state, cs, r = 0; + __pthread_testcancel(); + __pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + if (cs == PTHREAD_CANCEL_ENABLE) __pthread_setcancelstate(cs, 0); +- if (t->detached) a_crash(); +- while ((tmp = t->tid) && r != ETIMEDOUT && r != EINVAL) +- r = __timedwait_cp(&t->tid, tmp, CLOCK_REALTIME, at, 0); ++ while ((state = t->detach_state) && r != ETIMEDOUT && r != EINVAL) { ++ if (state >= DT_DETACHED) a_crash(); ++ r = __timedwait_cp(&t->detach_state, state, CLOCK_REALTIME, at, 0); ++ } + __pthread_setcancelstate(cs, 0); + if (r == ETIMEDOUT || r == EINVAL) return r; + a_barrier(); +@@ -29,7 +30,7 @@ int __pthread_join(pthread_t t, void **res) + + int __pthread_tryjoin_np(pthread_t t, void **res) + { +- return t->tid ? EBUSY : __pthread_join(t, res); ++ return t->detach_state==DT_JOINABLE ? EBUSY : __pthread_join(t, res); + } + + weak_alias(__pthread_tryjoin_np, pthread_tryjoin_np); +diff --git a/src/thread/pthread_kill.c b/src/thread/pthread_kill.c +index f0903420..6d70e626 100644 +--- a/src/thread/pthread_kill.c ++++ b/src/thread/pthread_kill.c +@@ -4,7 +4,8 @@ int pthread_kill(pthread_t t, int sig) + { + int r; + LOCK(t->killlock); +- r = t->dead ? ESRCH : -__syscall(SYS_tkill, t->tid, sig); ++ r = t->tid ? -__syscall(SYS_tkill, t->tid, sig) ++ : (sig+0U >= _NSIG ? EINVAL : 0); + UNLOCK(t->killlock); + return r; + } +diff --git a/src/thread/pthread_setschedparam.c b/src/thread/pthread_setschedparam.c +index 9e2fa456..ab45f2ff 100644 +--- a/src/thread/pthread_setschedparam.c ++++ b/src/thread/pthread_setschedparam.c +@@ -4,7 +4,7 @@ int pthread_setschedparam(pthread_t t, int policy, const struct sched_param *par + { + int r; + LOCK(t->killlock); +- r = t->dead ? ESRCH : -__syscall(SYS_sched_setscheduler, t->tid, policy, param); ++ r = !t->tid ? ESRCH : -__syscall(SYS_sched_setscheduler, t->tid, policy, param); + UNLOCK(t->killlock); + return r; + } +diff --git a/src/thread/pthread_setschedprio.c b/src/thread/pthread_setschedprio.c +index dc745b42..c353f6b5 100644 +--- a/src/thread/pthread_setschedprio.c ++++ b/src/thread/pthread_setschedprio.c +@@ -4,7 +4,7 @@ int pthread_setschedprio(pthread_t t, int prio) + { + int r; + LOCK(t->killlock); +- r = t->dead ? ESRCH : -__syscall(SYS_sched_setparam, t->tid, &prio); ++ r = !t->tid ? ESRCH : -__syscall(SYS_sched_setparam, t->tid, &prio); + UNLOCK(t->killlock); + return r; + } +diff --git a/src/time/strftime.c b/src/time/strftime.c +index 708875ee..d3f2add9 100644 +--- a/src/time/strftime.c ++++ b/src/time/strftime.c +@@ -181,9 +181,8 @@ const char *__strftime_fmt_1(char (*s)[100], size_t *l, int f, const struct tm * + *l = 0; + return ""; + } +- *l = snprintf(*s, sizeof *s, "%+.2d%.2d", +- (tm->__tm_gmtoff)/3600, +- abs(tm->__tm_gmtoff%3600)/60); ++ *l = snprintf(*s, sizeof *s, "%+.4ld", ++ tm->__tm_gmtoff/3600*100 + tm->__tm_gmtoff%3600/60); + return *s; + case 'Z': + if (tm->tm_isdst < 0) { +diff --git a/src/time/timespec_get.c b/src/time/timespec_get.c +index 03c5a77b..c423b825 100644 +--- a/src/time/timespec_get.c ++++ b/src/time/timespec_get.c +@@ -6,7 +6,7 @@ int __clock_gettime(clockid_t, struct timespec *); + * are considered erroneous. */ + int timespec_get(struct timespec * ts, int base) + { +- if (base != TIME_UTC) return 0; ++ if (base != 1) return 0; + int ret = __clock_gettime(CLOCK_REALTIME, ts); + return ret < 0 ? 0 : base; + } +diff --git a/src/time/wcsftime.c b/src/time/wcsftime.c +index 638e64f6..23500cc8 100644 +--- a/src/time/wcsftime.c ++++ b/src/time/wcsftime.c +@@ -4,7 +4,7 @@ + #include "locale_impl.h" + #include "libc.h" + +-const char *__strftime_fmt_1(char (*s)[100], size_t *l, int f, const struct tm *tm, locale_t loc); ++const char *__strftime_fmt_1(char (*s)[100], size_t *l, int f, const struct tm *tm, locale_t loc, int pad); + + size_t __wcsftime_l(wchar_t *restrict s, size_t n, const wchar_t *restrict f, const struct tm *restrict tm, locale_t loc) + { +@@ -14,7 +14,7 @@ size_t __wcsftime_l(wchar_t *restrict s, size_t n, const wchar_t *restrict f, co + wchar_t *p; + const char *t_mb; + const wchar_t *t; +- int plus; ++ int pad, plus; + unsigned long width; + for (l=0; l<n; f++) { + if (!*f) { +@@ -26,6 +26,8 @@ size_t __wcsftime_l(wchar_t *restrict s, size_t n, const wchar_t *restrict f, co + continue; + } + f++; ++ pad = 0; ++ if (*f == '-' || *f == '_' || *f == '0') pad = *f++; + if ((plus = (*f == '+'))) f++; + width = wcstoul(f, &p, 10); + if (*p == 'C' || *p == 'F' || *p == 'G' || *p == 'Y') { +@@ -35,7 +37,7 @@ size_t __wcsftime_l(wchar_t *restrict s, size_t n, const wchar_t *restrict f, co + } + f = p; + if (*f == 'E' || *f == 'O') f++; +- t_mb = __strftime_fmt_1(&buf, &k, *f, tm, loc); ++ t_mb = __strftime_fmt_1(&buf, &k, *f, tm, loc, pad); + if (!t_mb) break; + k = mbstowcs(wbuf, t_mb, sizeof wbuf / sizeof *wbuf); + if (k == (size_t)-1) return 0; +diff --git a/src/unistd/getcwd.c b/src/unistd/getcwd.c +index 103fbbb5..f407ffe0 100644 +--- a/src/unistd/getcwd.c ++++ b/src/unistd/getcwd.c +@@ -6,10 +6,10 @@ + + char *getcwd(char *buf, size_t size) + { +- char tmp[PATH_MAX]; ++ char tmp[buf ? 1 : PATH_MAX]; + if (!buf) { + buf = tmp; +- size = PATH_MAX; ++ size = sizeof tmp; + } else if (!size) { + errno = EINVAL; + return 0; +diff --git a/src/unistd/gethostname.c b/src/unistd/gethostname.c +index f984b7dd..633ef571 100644 +--- a/src/unistd/gethostname.c ++++ b/src/unistd/gethostname.c +@@ -8,6 +8,6 @@ int gethostname(char *name, size_t len) + if (uname(&uts)) return -1; + if (len > sizeof uts.nodename) len = sizeof uts.nodename; + for (i=0; i<len && (name[i] = uts.nodename[i]); i++); +- if (i==len) name[i-1] = 0; ++ if (i && i==len) name[i-1] = 0; + return 0; + } +diff --git a/src/unistd/nice.c b/src/unistd/nice.c +index da569967..6c25c8c3 100644 +--- a/src/unistd/nice.c ++++ b/src/unistd/nice.c +@@ -1,12 +1,16 @@ + #include <unistd.h> + #include <sys/resource.h> ++#include <limits.h> + #include "syscall.h" + + int nice(int inc) + { +-#ifdef SYS_nice +- return syscall(SYS_nice, inc); +-#else +- return setpriority(PRIO_PROCESS, 0, getpriority(PRIO_PROCESS, 0)+inc); +-#endif ++ int prio = inc; ++ // Only query old priority if it can affect the result. ++ // This also avoids issues with integer overflow. ++ if (inc > -2*NZERO && inc < 2*NZERO) ++ prio += getpriority(PRIO_PROCESS, 0); ++ if (prio > NZERO-1) prio = NZERO-1; ++ if (prio < -NZERO) prio = -NZERO; ++ return setpriority(PRIO_PROCESS, 0, prio) ? -1 : prio; + } +diff --git a/tools/musl-gcc.specs.sh b/tools/musl-gcc.specs.sh +index 294e24f7..30492574 100644 +--- a/tools/musl-gcc.specs.sh ++++ b/tools/musl-gcc.specs.sh +@@ -17,10 +17,10 @@ cat <<EOF + libgcc.a%s %:if-exists(libgcc_eh.a%s) + + *startfile: +-%{!shared: $libdir/%{pie:S}crt1.o} $libdir/crti.o %{shared|pie:crtbeginS.o%s;:crtbegin.o%s} ++%{!shared: $libdir/Scrt1.o} $libdir/crti.o crtbeginS.o%s + + *endfile: +-%{shared|pie:crtendS.o%s;:crtend.o%s} $libdir/crtn.o ++crtendS.o%s $libdir/crtn.o + + *link: + -dynamic-linker $ldso -nostdlib %{shared:-shared} %{static:-static} %{rdynamic:-export-dynamic} |