]> git.proxmox.com Git - wasi-libc.git/commitdiff
Update to musl 1.2.2.
authorDan Gohman <dev@sunfishcode.online>
Thu, 18 Mar 2021 16:47:06 +0000 (09:47 -0700)
committerDan Gohman <dev@sunfishcode.online>
Thu, 18 Mar 2021 18:18:41 +0000 (11:18 -0700)
See the WHATSNEW file for details.

167 files changed:
dlmalloc/src/dlmalloc.c
expected/wasm32-wasi/defined-symbols.txt
expected/wasm32-wasi/predefined-macros.txt
libc-top-half/musl/INSTALL
libc-top-half/musl/VERSION
libc-top-half/musl/WHATSNEW
libc-top-half/musl/arch/aarch64/bits/hwcap.h
libc-top-half/musl/arch/aarch64/bits/signal.h
libc-top-half/musl/arch/aarch64/bits/syscall.h.in
libc-top-half/musl/arch/aarch64/bits/user.h
libc-top-half/musl/arch/aarch64/pthread_arch.h
libc-top-half/musl/arch/arm/bits/syscall.h.in
libc-top-half/musl/arch/arm/pthread_arch.h
libc-top-half/musl/arch/generic/bits/fcntl.h
libc-top-half/musl/arch/i386/bits/syscall.h.in
libc-top-half/musl/arch/i386/pthread_arch.h
libc-top-half/musl/arch/i386/syscall_arch.h
libc-top-half/musl/arch/m68k/bits/syscall.h.in
libc-top-half/musl/arch/m68k/pthread_arch.h
libc-top-half/musl/arch/m68k/syscall_arch.h
libc-top-half/musl/arch/microblaze/bits/syscall.h.in
libc-top-half/musl/arch/microblaze/pthread_arch.h
libc-top-half/musl/arch/microblaze/syscall_arch.h
libc-top-half/musl/arch/mips/bits/syscall.h.in
libc-top-half/musl/arch/mips/pthread_arch.h
libc-top-half/musl/arch/mips/syscall_arch.h
libc-top-half/musl/arch/mips64/bits/fcntl.h
libc-top-half/musl/arch/mips64/bits/syscall.h.in
libc-top-half/musl/arch/mips64/pthread_arch.h
libc-top-half/musl/arch/mipsn32/bits/syscall.h.in
libc-top-half/musl/arch/mipsn32/pthread_arch.h
libc-top-half/musl/arch/or1k/bits/syscall.h.in
libc-top-half/musl/arch/or1k/pthread_arch.h
libc-top-half/musl/arch/powerpc/bits/syscall.h.in
libc-top-half/musl/arch/powerpc/pthread_arch.h
libc-top-half/musl/arch/powerpc64/bits/syscall.h.in
libc-top-half/musl/arch/powerpc64/pthread_arch.h
libc-top-half/musl/arch/riscv64/bits/fcntl.h [deleted file]
libc-top-half/musl/arch/riscv64/bits/signal.h
libc-top-half/musl/arch/riscv64/bits/syscall.h.in
libc-top-half/musl/arch/riscv64/pthread_arch.h
libc-top-half/musl/arch/s390x/bits/alltypes.h.in
libc-top-half/musl/arch/s390x/bits/float.h
libc-top-half/musl/arch/s390x/bits/syscall.h.in
libc-top-half/musl/arch/s390x/pthread_arch.h
libc-top-half/musl/arch/s390x/syscall_arch.h
libc-top-half/musl/arch/sh/bits/signal.h
libc-top-half/musl/arch/sh/bits/syscall.h.in
libc-top-half/musl/arch/sh/pthread_arch.h
libc-top-half/musl/arch/x32/bits/fcntl.h
libc-top-half/musl/arch/x32/bits/syscall.h.in
libc-top-half/musl/arch/x32/pthread_arch.h
libc-top-half/musl/arch/x86_64/bits/fcntl.h [deleted file]
libc-top-half/musl/arch/x86_64/bits/syscall.h.in
libc-top-half/musl/arch/x86_64/pthread_arch.h
libc-top-half/musl/configure
libc-top-half/musl/include/alltypes.h.in
libc-top-half/musl/include/elf.h
libc-top-half/musl/include/netinet/if_ether.h
libc-top-half/musl/include/netinet/in.h
libc-top-half/musl/include/netinet/tcp.h
libc-top-half/musl/include/netinet/udp.h
libc-top-half/musl/include/sched.h
libc-top-half/musl/include/signal.h
libc-top-half/musl/include/stdlib.h
libc-top-half/musl/include/sys/fanotify.h
libc-top-half/musl/include/sys/ioctl.h
libc-top-half/musl/include/sys/mman.h
libc-top-half/musl/include/sys/personality.h
libc-top-half/musl/include/sys/prctl.h
libc-top-half/musl/include/sys/random.h
libc-top-half/musl/include/termios.h
libc-top-half/musl/include/unistd.h
libc-top-half/musl/ldso/dynlink.c
libc-top-half/musl/src/aio/aio.c
libc-top-half/musl/src/aio/aio_suspend.c
libc-top-half/musl/src/conf/sysconf.c
libc-top-half/musl/src/crypt/crypt_blowfish.c
libc-top-half/musl/src/env/__init_tls.c
libc-top-half/musl/src/env/__stack_chk_fail.c
libc-top-half/musl/src/exit/abort.c
libc-top-half/musl/src/exit/abort_lock.c [new file with mode: 0644]
libc-top-half/musl/src/exit/assert.c
libc-top-half/musl/src/exit/at_quick_exit.c
libc-top-half/musl/src/exit/atexit.c
libc-top-half/musl/src/include/stdlib.h
libc-top-half/musl/src/include/unistd.h
libc-top-half/musl/src/internal/aio_impl.h [new file with mode: 0644]
libc-top-half/musl/src/internal/fork_impl.h [new file with mode: 0644]
libc-top-half/musl/src/internal/libm.h
libc-top-half/musl/src/internal/locale_impl.h
libc-top-half/musl/src/internal/lock.h
libc-top-half/musl/src/internal/pthread_impl.h
libc-top-half/musl/src/internal/stdio_impl.h
libc-top-half/musl/src/internal/syscall.h
libc-top-half/musl/src/ldso/dlerror.c
libc-top-half/musl/src/legacy/lutimes.c
libc-top-half/musl/src/linux/gettid.c [new file with mode: 0644]
libc-top-half/musl/src/linux/membarrier.c
libc-top-half/musl/src/linux/setgroups.c
libc-top-half/musl/src/locale/dcngettext.c
libc-top-half/musl/src/locale/freelocale.c
libc-top-half/musl/src/locale/locale_map.c
libc-top-half/musl/src/locale/newlocale.c
libc-top-half/musl/src/locale/setlocale.c
libc-top-half/musl/src/malloc/free.c [new file with mode: 0644]
libc-top-half/musl/src/malloc/libc_calloc.c [new file with mode: 0644]
libc-top-half/musl/src/malloc/lite_malloc.c
libc-top-half/musl/src/malloc/mallocng/glue.h
libc-top-half/musl/src/malloc/mallocng/malloc_usable_size.c
libc-top-half/musl/src/malloc/oldmalloc/malloc.c
libc-top-half/musl/src/malloc/realloc.c [new file with mode: 0644]
libc-top-half/musl/src/malloc/reallocarray.c [new file with mode: 0644]
libc-top-half/musl/src/math/__math_invalidl.c [new file with mode: 0644]
libc-top-half/musl/src/math/arm/fabs.c
libc-top-half/musl/src/math/arm/sqrt.c
libc-top-half/musl/src/math/sqrt.c
libc-top-half/musl/src/math/sqrt_data.c [new file with mode: 0644]
libc-top-half/musl/src/math/sqrt_data.h [new file with mode: 0644]
libc-top-half/musl/src/math/sqrtf.c
libc-top-half/musl/src/math/sqrtl.c
libc-top-half/musl/src/misc/ioctl.c
libc-top-half/musl/src/misc/realpath.c
libc-top-half/musl/src/misc/setrlimit.c
libc-top-half/musl/src/misc/syslog.c
libc-top-half/musl/src/misc/uname.c
libc-top-half/musl/src/multibyte/wcsnrtombs.c
libc-top-half/musl/src/network/h_errno.c
libc-top-half/musl/src/network/herror.c
libc-top-half/musl/src/network/lookup_name.c
libc-top-half/musl/src/network/res_query.c
libc-top-half/musl/src/passwd/getgrouplist.c
libc-top-half/musl/src/prng/random.c
libc-top-half/musl/src/process/_Fork.c [new file with mode: 0644]
libc-top-half/musl/src/process/fork.c
libc-top-half/musl/src/process/posix_spawn.c
libc-top-half/musl/src/setjmp/aarch64/longjmp.s
libc-top-half/musl/src/setjmp/i386/longjmp.s
libc-top-half/musl/src/setjmp/x32/longjmp.s
libc-top-half/musl/src/setjmp/x32/setjmp.s
libc-top-half/musl/src/setjmp/x86_64/longjmp.s
libc-top-half/musl/src/setjmp/x86_64/setjmp.s
libc-top-half/musl/src/signal/sigaction.c
libc-top-half/musl/src/stdio/__stdio_close.c
libc-top-half/musl/src/stdio/ofl.c
libc-top-half/musl/src/string/strstr.c
libc-top-half/musl/src/termios/tcgetwinsize.c [new file with mode: 0644]
libc-top-half/musl/src/termios/tcsetwinsize.c [new file with mode: 0644]
libc-top-half/musl/src/thread/i386/__set_thread_area.s
libc-top-half/musl/src/thread/pthread_attr_get.c
libc-top-half/musl/src/thread/pthread_cond_timedwait.c
libc-top-half/musl/src/thread/pthread_create.c
libc-top-half/musl/src/thread/pthread_mutex_destroy.c
libc-top-half/musl/src/thread/pthread_mutexattr_setprotocol.c
libc-top-half/musl/src/thread/pthread_mutexattr_setrobust.c
libc-top-half/musl/src/thread/s390x/clone.s
libc-top-half/musl/src/thread/s390x/syscall_cp.s
libc-top-half/musl/src/thread/sem_open.c
libc-top-half/musl/src/thread/synccall.c
libc-top-half/musl/src/thread/vmlock.c
libc-top-half/musl/src/time/__tz.c
libc-top-half/musl/src/time/timer_create.c
libc-top-half/musl/src/unistd/close.c
libc-top-half/musl/src/unistd/faccessat.c
libc-top-half/musl/src/unistd/readlink.c
libc-top-half/musl/src/unistd/readlinkat.c
libc-top-half/musl/src/unistd/setxid.c

index dab8df5f2f622df95d5d77abf848013e8ae686ce..331536b44fef0c9285369f2df9126ce95136d10d 100644 (file)
@@ -91,3 +91,8 @@ void* aligned_alloc(size_t alignment, size_t bytes) {
 size_t malloc_usable_size(void *ptr) {
     return dlmalloc_usable_size(ptr);
 }
+
+// Define these to satisfy musl references.
+void *__libc_malloc(size_t) __attribute__((alias("malloc")));
+void __libc_free(void *) __attribute__((alias("free")));
+void *__libc_calloc(size_t nmemb, size_t size) __attribute__((alias("calloc")));
index eb33f4b971cb15b42b23c4e0abe046bb5fed95b6..480ad10664c0e1a0720ee0c6b2fa8e30ce3e8e82 100644 (file)
@@ -132,6 +132,9 @@ __lgamma_r
 __lgammaf_r
 __lgammal_r
 __libc
+__libc_calloc
+__libc_free
+__libc_malloc
 __loc_is_allocated
 __localtime_r
 __log2_data
@@ -145,6 +148,7 @@ __math_divzero
 __math_divzerof
 __math_invalid
 __math_invalidf
+__math_invalidl
 __math_oflow
 __math_oflowf
 __math_uflow
@@ -181,6 +185,7 @@ __rem_pio2
 __rem_pio2_large
 __rem_pio2f
 __rem_pio2l
+__rsqrt_tab
 __secs_to_tm
 __secs_to_zone
 __seed48
index 63c07cc2561b4e1b0597c6d23ff0a0c23aceda2f..83fd5fbfb61207b424391469f956bdf235673c8a 100644 (file)
 #define IP_PMTUDISC_PROBE 3
 #define IP_PMTUDISC_WANT 1
 #define IP_RECVERR 11
+#define IP_RECVERR_RFC4884 26
 #define IP_RECVFRAGSIZE 25
 #define IP_RECVOPTS 6
 #define IP_RECVORIGDSTADDR IP_ORIGDSTADDR
 #define TCP_CONGESTION 13
 #define TCP_CORK 3
 #define TCP_DEFER_ACCEPT 9
+#define TCP_ENCAP_ESPINTCP 7
 #define TCP_ESTABLISHED 1
 #define TCP_FASTOPEN 23
 #define TCP_FASTOPEN_CONNECT 30
 #define TCP_MAXSEG 2
 #define TCP_MD5SIG 14
 #define TCP_MD5SIG_EXT 32
-#define TCP_MD5SIG_FLAG_PREFIX 1
+#define TCP_MD5SIG_FLAG_IFINDEX 0x2
+#define TCP_MD5SIG_FLAG_PREFIX 0x1
 #define TCP_MD5SIG_MAXKEYLEN 80
 #define TCP_NODELAY 1
 #define TCP_NOTSENT_LOWAT 25
index 22477b6ba0f99f2fef07011535da873c5907a862..c583691d750472fc7af337caed26506586febb75 100644 (file)
@@ -86,7 +86,7 @@ and ABI combinations:
 
 * SuperH (SH)
     * Standard ELF ABI or FDPIC ABI (shared-text without MMU)
-    * Little-endian by default; big-engian variant also supported
+    * Little-endian by default; big-endian variant also supported
     * Full FPU ABI or soft-float ABI is supported, but the
       single-precision-only FPU ABI is not
 
index 6085e946503a10fb4d58a5c7d9a6e572c21ddd2e..23aa8390630cc1ae7f102ddd472e4ba48b689844 100644 (file)
@@ -1 +1 @@
-1.2.1
+1.2.2
index d9826fc0ed0b547552ad40f1fb04664841d7f417..e1d01982a2ac66a25b64cb550e00e30df71a9822 100644 (file)
@@ -2236,3 +2236,54 @@ arch-specific bugs fixed:
 - mips* had negated error codes for some syscalls (kernel bug)
 - mips* SIGEMT was wrongly called SIGSTKFLT
 - sh fesetround didn't work correctly on sh
+
+
+
+1.2.2 release notes
+
+major changes:
+- child restrictions lifted after fork of multithreaded parent
+
+new features:
+- _Fork function (POSIX-future)
+- reallocarray function (extension from OpenBSD, now widespread)
+- gettid function (kernel tid as supported concept)
+- SIGEV_THREAD_ID sigevent API (Linux extension)
+- tcgetwinsize and tcsetwinsize functions (POSIX-future)
+
+performance:
+- faster software sqrt on archs without native sqrt instruction
+
+compatibility:
+- realpath no longer depends on procfs availability & accuracy
+- time zone parser now always prefers 64-bit tables if present
+- crypt_blowfish now supports $2b$ prefix
+- res_query now reports errors via h_errno
+- set*id and setrlimit are now safe in vforked/cloned child
+- setgroups now applies to all threads
+- dlopen debugger notification is improved, should work with lldb
+- setrlimit no longer needs __synccall broadcast on linux 2.6.36+
+- faccessat with AT_EACCESS no longer needs child process on linux 5.8+
+
+bugs fixed:
+- buffer overflow and infinite loop errors in wcsnrtombs (CVE-2020-28928)
+- sem_close unmapped still-referenced semaphores
+- fork of process with active aio could deadlock or crash paren
+- pthread_cond_wait was broken with priority-inheritance mutex
+- getgrouplist wrongly failed when nscd reported an empty list
+- abort could leak modified SIGABRT disposition to fork or posix_spawn child
+- regression with mallocng: malloc_usable_size(0) crashed
+- readlink wrongly gave EINVAL on zero length dest buffer
+- sqrtl was severely inaccurate (not correctly rounded) on ldquad archs
+- assert failure wrongly flushed stdio (possible deadlock)
+- MUSL_LOCPATH search was broken with multiple components
+- missing newline in herror output
+- possible deadlock in pthread_exit with pshared mutex or barrier usage
+- pthread_mutexattr_getprotocol didn't read back protocol
+- v4l2 ioctl translation for pre-time64 kernels didn't work
+
+arch-specific bugs fixed:
+- x86_64 longjmp failed to handle 0 argument reliably
+- i386 __set_thread_area fallback for pre-2.6 kernels didn't work
+- missing O_LARGEFILE macro value on x86_64, x32, mips64
+- unpredictable s390x breakage from failure to preserve call-saved registers
index a7484028e0a33f73d0538f93af205ffc591d9bd4..7ab73f99b68a06e9e372946eb5abe12174bf0607 100644 (file)
 #define HWCAP2_SVEBITPERM      (1 << 4)
 #define HWCAP2_SVESHA3         (1 << 5)
 #define HWCAP2_SVESM4          (1 << 6)
+#define HWCAP2_FLAGM2          (1 << 7)
+#define HWCAP2_FRINT           (1 << 8)
+#define HWCAP2_SVEI8MM         (1 << 9)
+#define HWCAP2_SVEF32MM                (1 << 10)
+#define HWCAP2_SVEF64MM                (1 << 11)
+#define HWCAP2_SVEBF16         (1 << 12)
+#define HWCAP2_I8MM            (1 << 13)
+#define HWCAP2_BF16            (1 << 14)
+#define HWCAP2_DGH             (1 << 15)
+#define HWCAP2_RNG             (1 << 16)
index b71261f56816b79708d7f875601d9e620a92ceb6..5098c7341d116b94ad0a76f177bb8e3d8a9b31f4 100644 (file)
@@ -11,7 +11,7 @@ typedef unsigned long greg_t;
 typedef unsigned long gregset_t[34];
 
 typedef struct {
-       long double vregs[32];
+       __uint128_t vregs[32];
        unsigned int fpsr;
        unsigned int fpcr;
 } fpregset_t;
@@ -34,7 +34,7 @@ struct fpsimd_context {
        struct _aarch64_ctx head;
        unsigned int fpsr;
        unsigned int fpcr;
-       long double vregs[32];
+       __uint128_t vregs[32];
 };
 struct esr_context {
        struct _aarch64_ctx head;
index 93648afdfee636733f4b92a8c482c4d74b6a4278..f9457c184a6318e78abf05d87f17c9b17574d1f8 100644 (file)
 #define __NR_fspick            433
 #define __NR_pidfd_open                434
 #define __NR_clone3            435
+#define __NR_close_range       436
+#define __NR_openat2           437
+#define __NR_pidfd_getfd       438
+#define __NR_faccessat2                439
 
index d12cdf7fe5c5d8f32494b8a9660591061cb4427d..8a1002aa679251ffb7a7915f01f7bc21572b1e20 100644 (file)
@@ -6,7 +6,7 @@ struct user_regs_struct {
 };
 
 struct user_fpsimd_struct {
-       long double vregs[32];
+       __uint128_t vregs[32];
        unsigned int fpsr;
        unsigned int fpcr;
 };
index e64b126d2c60339cfb4c361e6112d96c56583b2e..3909616c37a1c2587a70727ef51b1334bc8994b6 100644 (file)
@@ -1,12 +1,11 @@
-static inline struct pthread *__pthread_self()
+static inline uintptr_t __get_tp()
 {
-       char *self;
-       __asm__ ("mrs %0,tpidr_el0" : "=r"(self));
-       return (void*)(self - sizeof(struct pthread));
+       uintptr_t tp;
+       __asm__ ("mrs %0,tpidr_el0" : "=r"(tp));
+       return tp;
 }
 
 #define TLS_ABOVE_TP
 #define GAP_ABOVE_TP 16
-#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread))
 
 #define MC_PC pc
index 11d677635be39e7b05d7e387dff39b82869c278b..7e2fc26697adf6f6697b988f830e110b426cd581 100644 (file)
 #define __NR_fspick            433
 #define __NR_pidfd_open                434
 #define __NR_clone3            435
+#define __NR_close_range       436
+#define __NR_openat2           437
+#define __NR_pidfd_getfd       438
+#define __NR_faccessat2                439
 
 #define __ARM_NR_breakpoint    0x0f0001
 #define __ARM_NR_cacheflush    0x0f0002
index e689ea212ae22e148788deec9e74f5b2e9f49f7d..157e2eae66d21203f13647cf12a3b556bbcd9642 100644 (file)
@@ -1,11 +1,11 @@
 #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()
+static inline uintptr_t __get_tp()
 {
-       char *p;
-       __asm__ ( "mrc p15,0,%0,c13,c0,3" : "=r"(p) );
-       return (void *)(p-sizeof(struct pthread));
+       uintptr_t tp;
+       __asm__ ( "mrc p15,0,%0,c13,c0,3" : "=r"(tp) );
+       return tp;
 }
 
 #else
@@ -16,18 +16,17 @@ static inline pthread_t __pthread_self()
 #define BLX "blx"
 #endif
 
-static inline pthread_t __pthread_self()
+static inline uintptr_t __get_tp()
 {
        extern hidden uintptr_t __a_gettp_ptr;
-       register uintptr_t p __asm__("r0");
-       __asm__ ( BLX " %1" : "=r"(p) : "r"(__a_gettp_ptr) : "cc", "lr" );
-       return (void *)(p-sizeof(struct pthread));
+       register uintptr_t tp __asm__("r0");
+       __asm__ ( BLX " %1" : "=r"(tp) : "r"(__a_gettp_ptr) : "cc", "lr" );
+       return tp;
 }
 
 #endif
 
 #define TLS_ABOVE_TP
 #define GAP_ABOVE_TP 8
-#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread))
 
 #define MC_PC arm_pc
index ae233cc003c2c62ccdc2e39e5f6e7678976022a3..730a98cfe65a822965acc1e903df7d56046859d0 100644 (file)
 #define F_SETSIG 10
 #define F_GETSIG 11
 
+#if __LONG_MAX == 0x7fffffffL
 #define F_GETLK 12
 #define F_SETLK 13
 #define F_SETLKW 14
+#else
+#define F_GETLK 5
+#define F_SETLK 6
+#define F_SETLKW 7
+#endif
 
 #define F_SETOWN_EX 15
 #define F_GETOWN_EX 16
index 1ae4e48a8fea1a49cc189db7a5a19a4fb26da61d..abdb210d39703b913b828e086591eef7cd60ec75 100644 (file)
 #define __NR_fspick            433
 #define __NR_pidfd_open                434
 #define __NR_clone3            435
+#define __NR_close_range       436
+#define __NR_openat2           437
+#define __NR_pidfd_getfd       438
+#define __NR_faccessat2                439
 
index 6f600b9e0151a0ea6cfca1199d2f4e4097988c0e..a639c382ac2af5b351adfb2f728264e7ea4f932d 100644 (file)
@@ -1,10 +1,8 @@
-static inline struct pthread *__pthread_self()
+static inline uintptr_t __get_tp()
 {
-       struct pthread *self;
-       __asm__ ("movl %%gs:0,%0" : "=r" (self) );
-       return self;
+       uintptr_t tp;
+       __asm__ ("movl %%gs:0,%0" : "=r" (tp) );
+       return tp;
 }
 
-#define TP_ADJ(p) (p)
-
 #define MC_PC gregs[REG_EIP]
index 69642e578a5f16e783c2afe4f67744a9b17e8c73..f92b7aa9f448894ee25849c4b98f9ee9aea09f38 100644 (file)
@@ -87,5 +87,3 @@ static inline long __syscall6(long n, long a1, long a2, long a3, long a4, long a
 #define VDSO_CGT32_VER "LINUX_2.6"
 #define VDSO_CGT_SYM "__vdso_clock_gettime64"
 #define VDSO_CGT_VER "LINUX_2.6"
-
-#define SYSCALL_USE_SOCKETCALL
index ddfa72e4dd0b554f32ad29839e165cade59d9613..e10969a2641d4b942fe473ea0a4c33ac45fe73ae 100644 (file)
 #define __NR_fsmount           432
 #define __NR_fspick            433
 #define __NR_pidfd_open                434
+#define __NR_clone3            435
+#define __NR_close_range       436
+#define __NR_openat2           437
+#define __NR_pidfd_getfd       438
+#define __NR_faccessat2                439
index 02d5b8a089f77f61050c5e3291bda3f5f07a6c5d..5bea4e1adc1090cd32c1d9ac10d50cb6242b629c 100644 (file)
@@ -1,13 +1,12 @@
-static inline struct pthread *__pthread_self()
+static inline uintptr_t __get_tp()
 {
-       uintptr_t tp = __syscall(SYS_get_thread_area);
-       return (pthread_t)(tp - 0x7000 - sizeof(struct pthread));
+       return __syscall(SYS_get_thread_area);
 }
 
 #define TLS_ABOVE_TP
 #define GAP_ABOVE_TP 0
-#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000)
 
+#define TP_OFFSET 0x7000
 #define DTP_OFFSET 0x8000
 
 #define MC_PC gregs[R_PC]
index af79c3069061c83581d5f2fb51c39ec48bfa83e4..6a9d0ae8e4e826f4f4a189b5d4a50e3e78216aa0 100644 (file)
@@ -87,5 +87,4 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
        return d0;
 }
 
-#define SYSCALL_USE_SOCKETCALL
 #define SYSCALL_IPC_BROKEN_MODE
index 963386a83990acfd4b477ba16b94dbf35075186e..9d46904738df5e8afc2ef118e8656f161ee3e376 100644 (file)
 #define __NR_fspick            433
 #define __NR_pidfd_open                434
 #define __NR_clone3            435
+#define __NR_close_range       436
+#define __NR_openat2           437
+#define __NR_pidfd_getfd       438
+#define __NR_faccessat2                439
 
index f6ba8de981fd2b6b8a56c86f3b720665a5ccbe5e..ff26624efc328a647f65d9a64b90d1e9f1bf577a 100644 (file)
@@ -1,10 +1,8 @@
-static inline struct pthread *__pthread_self()
+static inline uintptr_t __get_tp()
 {
-       struct pthread *self;
-       __asm__ ("ori %0, r21, 0" : "=r" (self) );
-       return self;
+       uintptr_t tp;
+       __asm__ ("ori %0, r21, 0" : "=r" (tp) );
+       return tp;
 }
 
-#define TP_ADJ(p) (p)
-
 #define MC_PC regs.pc
index 169013f80e4eea1e0f1adfde0516562d673fae80..61d8248e8c05709c6fb7c9502ead975b4d689225 100644 (file)
@@ -95,3 +95,5 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
 }
 
 #define SYSCALL_IPC_BROKEN_MODE
+
+#undef SYS_socketcall
index 86251bf31b41413e5ff6f62c408304365b77ff99..2bb03f067ab431354e4459b3230ba04cd3d45f9c 100644 (file)
 #define __NR_fspick            4433
 #define __NR_pidfd_open                4434
 #define __NR_clone3            4435
+#define __NR_close_range       4436
+#define __NR_openat2           4437
+#define __NR_pidfd_getfd       4438
+#define __NR_faccessat2                4439
 
index 1e7839ea6740ceac26c7a5b222e02bf92b5b05e7..c45347ab92f6b85825e644201982bc4de42b5e5f 100644 (file)
@@ -1,19 +1,19 @@
-static inline struct pthread *__pthread_self()
+static inline uintptr_t __get_tp()
 {
 #if __mips_isa_rev < 2
-       register char *tp __asm__("$3");
+       register uintptr_t tp __asm__("$3");
        __asm__ (".word 0x7c03e83b" : "=r" (tp) );
 #else
-       char *tp;
+       uintptr_t tp;
        __asm__ ("rdhwr %0, $29" : "=r" (tp) );
 #endif
-       return (pthread_t)(tp - 0x7000 - sizeof(struct pthread));
+       return tp;
 }
 
 #define TLS_ABOVE_TP
 #define GAP_ABOVE_TP 0
-#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000)
 
+#define TP_OFFSET 0x7000
 #define DTP_OFFSET 0x8000
 
 #define MC_PC pc
index 380a94b366512c128101fc97ffbeec24b20052a9..5b7c38de2043f6250db3cb691aa1782a71e3d273 100644 (file)
@@ -149,3 +149,5 @@ static inline long __syscall7(long n, long a, long b, long c, long d, long e, lo
 
 #define SO_SNDTIMEO_OLD 0x1005
 #define SO_RCVTIMEO_OLD 0x1006
+
+#undef SYS_socketcall
index 3bcec15e0db4fdf40bfcf6f7b5b76df44d04c593..5da1eef80c3f19c5589b3160699804bfc29acf89 100644 (file)
@@ -13,7 +13,7 @@
 
 #define O_ASYNC      010000
 #define O_DIRECT    0100000
-#define O_LARGEFILE       0
+#define O_LARGEFILE  020000
 #define O_NOATIME  01000000
 #define O_PATH    010000000
 #define O_TMPFILE 020200000
index 9b406e9a4d9e937a5cdc524df29695a93c6606ab..045e8238ad0337f8ba36f7fd309a4a8873f0a538 100644 (file)
 #define __NR_fspick            5433
 #define __NR_pidfd_open                5434
 #define __NR_clone3            5435
+#define __NR_close_range       5436
+#define __NR_openat2           5437
+#define __NR_pidfd_getfd       5438
+#define __NR_faccessat2                5439
 
index 1e7839ea6740ceac26c7a5b222e02bf92b5b05e7..c45347ab92f6b85825e644201982bc4de42b5e5f 100644 (file)
@@ -1,19 +1,19 @@
-static inline struct pthread *__pthread_self()
+static inline uintptr_t __get_tp()
 {
 #if __mips_isa_rev < 2
-       register char *tp __asm__("$3");
+       register uintptr_t tp __asm__("$3");
        __asm__ (".word 0x7c03e83b" : "=r" (tp) );
 #else
-       char *tp;
+       uintptr_t tp;
        __asm__ ("rdhwr %0, $29" : "=r" (tp) );
 #endif
-       return (pthread_t)(tp - 0x7000 - sizeof(struct pthread));
+       return tp;
 }
 
 #define TLS_ABOVE_TP
 #define GAP_ABOVE_TP 0
-#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000)
 
+#define TP_OFFSET 0x7000
 #define DTP_OFFSET 0x8000
 
 #define MC_PC pc
index 2ad48d10d98686450d1494016f086d85c293b339..5b3225585e7ec743af32c426153f104fd0adc98a 100644 (file)
 #define __NR_fspick            6433
 #define __NR_pidfd_open                6434
 #define __NR_clone3            6435
+#define __NR_close_range       6436
+#define __NR_openat2           6437
+#define __NR_pidfd_getfd       6438
+#define __NR_faccessat2                6439
 
index 1e7839ea6740ceac26c7a5b222e02bf92b5b05e7..c45347ab92f6b85825e644201982bc4de42b5e5f 100644 (file)
@@ -1,19 +1,19 @@
-static inline struct pthread *__pthread_self()
+static inline uintptr_t __get_tp()
 {
 #if __mips_isa_rev < 2
-       register char *tp __asm__("$3");
+       register uintptr_t tp __asm__("$3");
        __asm__ (".word 0x7c03e83b" : "=r" (tp) );
 #else
-       char *tp;
+       uintptr_t tp;
        __asm__ ("rdhwr %0, $29" : "=r" (tp) );
 #endif
-       return (pthread_t)(tp - 0x7000 - sizeof(struct pthread));
+       return tp;
 }
 
 #define TLS_ABOVE_TP
 #define GAP_ABOVE_TP 0
-#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000)
 
+#define TP_OFFSET 0x7000
 #define DTP_OFFSET 0x8000
 
 #define MC_PC pc
index e9c925e41f42d2ba01728debab76d1a3720df8b7..b36038915d42d50b045d7a3c795ea056cefecf0a 100644 (file)
 #define __NR_fspick            433
 #define __NR_pidfd_open                434
 #define __NR_clone3            435
+#define __NR_close_range       436
+#define __NR_openat2           437
+#define __NR_pidfd_getfd       438
+#define __NR_faccessat2                439
 
index 1b806f8917140849f2c7463843c0594d96e2fc81..f75ea7e4e534e2726670de8a2b4e9842534cf0e9 100644 (file)
@@ -1,18 +1,16 @@
-/* or1k use variant I, but with the twist that tp points to the end of TCB */
-static inline struct pthread *__pthread_self()
+static inline uintptr_t __get_tp()
 {
 #ifdef __clang__
-       char *tp;
+       uintptr_t tp;
        __asm__ ("l.ori %0, r10, 0" : "=r" (tp) );
 #else
-       register char *tp __asm__("r10");
+       register uintptr_t tp __asm__("r10");
        __asm__ ("" : "=r" (tp) );
 #endif
-       return (struct pthread *) (tp - sizeof(struct pthread));
+       return tp;
 }
 
 #define TLS_ABOVE_TP
 #define GAP_ABOVE_TP 0
-#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread))
 
 #define MC_PC regs.pc
index 8d4f79b524c22cf9e8f13e7dceb77a84b1205e64..5c6fae3e5887ca7f3419b969943d76609455caee 100644 (file)
 #define __NR_fspick            433
 #define __NR_pidfd_open                434
 #define __NR_clone3            435
+#define __NR_close_range       436
+#define __NR_openat2           437
+#define __NR_pidfd_getfd       438
+#define __NR_faccessat2                439
 
index ae0f28d6d1e13c5161f4c13af3dc4048aecea144..42e88b07e8184080b03c7b297621cb9631255059 100644 (file)
@@ -1,18 +1,16 @@
-static inline struct pthread *__pthread_self()
+static inline uintptr_t __get_tp()
 {
-       register char *tp __asm__("r2");
+       register uintptr_t tp __asm__("r2");
        __asm__ ("" : "=r" (tp) );
-       return (pthread_t)(tp - 0x7000 - sizeof(struct pthread));
+       return tp;
 }
                         
 #define TLS_ABOVE_TP
 #define GAP_ABOVE_TP 0
-#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000)
 
+#define TP_OFFSET 0x7000
 #define DTP_OFFSET 0x8000
 
 // the kernel calls the ip "nip", it's the first saved value after the 32
 // GPRs.
 #define MC_PC gregs[32]
-
-#define CANARY canary_at_end
index b935864c41526a96aedd14af21d54e8998cc6d0b..edf73d3d6b1ddab8494630af3b25cf933fd552ff 100644 (file)
 #define __NR_fspick            433
 #define __NR_pidfd_open                434
 #define __NR_clone3            435
+#define __NR_close_range       436
+#define __NR_openat2           437
+#define __NR_pidfd_getfd       438
+#define __NR_faccessat2                439
 
index 79c3ecd8af03df07836af254373cb82b41746b8c..1b7b90797f4fb1cca547cbf26f0ec38ea844bc74 100644 (file)
@@ -1,18 +1,16 @@
-static inline struct pthread *__pthread_self()
+static inline uintptr_t __get_tp()
 {
-       register char *tp __asm__("r13");
+       register uintptr_t tp __asm__("r13");
        __asm__ ("" : "=r" (tp) );
-       return (pthread_t)(tp - 0x7000 - sizeof(struct pthread));
+       return tp;
 }
 
 #define TLS_ABOVE_TP
 #define GAP_ABOVE_TP 0
-#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000)
 
+#define TP_OFFSET 0x7000
 #define DTP_OFFSET 0x8000
 
 // the kernel calls the ip "nip", it's the first saved value after the 32
 // GPRs.
 #define MC_PC gp_regs[32]
-
-#define CANARY canary_at_end
diff --git a/libc-top-half/musl/arch/riscv64/bits/fcntl.h b/libc-top-half/musl/arch/riscv64/bits/fcntl.h
deleted file mode 100644 (file)
index ecb4d18..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-#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 0200000
-#define O_NOFOLLOW  0400000
-#define O_CLOEXEC  02000000
-
-#define O_ASYNC      020000
-#define O_DIRECT     040000
-#define O_LARGEFILE 0100000
-#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_GETLK  5
-#define F_SETLK  6
-#define F_SETLKW 7
-#define F_SETOWN 8
-#define F_GETOWN 9
-#define F_SETSIG 10
-#define F_GETSIG 11
-
-#define F_SETOWN_EX 15
-#define F_GETOWN_EX 16
-
-#define F_GETOWNER_UIDS 17
index b006334f78d7bbc971b195d7b51e108b1a36780b..287367db737127ecacd23f0912eee415eb251da1 100644 (file)
@@ -60,10 +60,10 @@ struct sigaltstack {
        size_t ss_size;
 };
 
-typedef struct ucontext_t
+typedef struct __ucontext
 {
        unsigned long uc_flags;
-       struct ucontext_t *uc_link;
+       struct __ucontext *uc_link;
        stack_t uc_stack;
        sigset_t uc_sigmask;
        mcontext_t uc_mcontext;
index 0043eeba3c1c29b63e8b55631a2309789173cfc9..5def016b129d675f4c5219b5dd439c1eb3e5fa73 100644 (file)
 #define __NR_fspick            433
 #define __NR_pidfd_open                434
 #define __NR_clone3            435
+#define __NR_close_range       436
+#define __NR_openat2           437
+#define __NR_pidfd_getfd       438
+#define __NR_faccessat2                439
 
 #define __NR_sysriscv __NR_arch_specific_syscall
 #define __NR_riscv_flush_icache (__NR_sysriscv + 15)
index db414b170281af8f29d9fbbd1d65d1145ad7bd7f..a20d7fba0d942ab944ba1b651229f3aafde07feb 100644 (file)
@@ -1,13 +1,12 @@
-static inline struct pthread *__pthread_self()
+static inline uintptr_t __get_tp()
 {
-       char *tp;
+       uintptr_t tp;
        __asm__ __volatile__("mv %0, tp" : "=r"(tp));
-       return (void *)(tp - sizeof(struct pthread));
+       return tp;
 }
 
 #define TLS_ABOVE_TP
 #define GAP_ABOVE_TP 0
-#define TP_ADJ(p) ((char *)p + sizeof(struct pthread))
 
 #define DTP_OFFSET 0x800
 
index 15d18c8f4a9c906f0f5c1a848de787b9bdf6f0ad..6c0eb7f4b81418ebe4dfe20af7d7f2333e1fd4f9 100644 (file)
@@ -9,7 +9,11 @@
 TYPEDEF int wchar_t;
 #endif
 
+#if defined(__FLT_EVAL_METHOD__) && __FLT_EVAL_METHOD__ == 1
 TYPEDEF double float_t;
+#else
+TYPEDEF float float_t;
+#endif
 TYPEDEF double double_t;
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
index 90b73beed4e5e1f5e92122141049c4a3dfa7e50b..e188cb6197a8d9089978836061a291a9f2206e88 100644 (file)
@@ -1,4 +1,8 @@
-#define FLT_EVAL_METHOD 1
+#ifdef __FLT_EVAL_METHOD__
+#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
+#else
+#define FLT_EVAL_METHOD 0
+#endif
 
 #define LDBL_TRUE_MIN 6.47517511943802511092443895822764655e-4966L
 #define LDBL_MIN 3.36210314311209350626267781732175260e-4932L
index e89f3782992769503f579fef1ec4cec3768b2a13..fb2e60e30b03f76c1b82a25e67dd3f0329e136cd 100644 (file)
 #define __NR_fspick            433
 #define __NR_pidfd_open                434
 #define __NR_clone3            435
+#define __NR_close_range       436
+#define __NR_openat2           437
+#define __NR_pidfd_getfd       438
+#define __NR_faccessat2                439
 
index e2251f1fa47f8eb74692cd0ea5942d5d9e4d7f21..e54fec3fe64fa763ae5b0fbcae71ef62a953aa4f 100644 (file)
@@ -1,14 +1,12 @@
-static inline struct pthread *__pthread_self()
+static inline uintptr_t __get_tp()
 {
-       struct pthread *self;
+       uintptr_t tp;
        __asm__ (
                "ear  %0, %%a0\n"
                "sllg %0, %0, 32\n"
                "ear  %0, %%a1\n"
-               : "=r"(self));
-       return self;
+               : "=r"(tp));
+       return tp;
 }
 
-#define TP_ADJ(p) (p)
-
 #define MC_PC psw.addr
index afb99852ebbe009514aab2e08c9f235d46241a55..83cc9a27c63f06a55613aab3f30e9b65d67248ef 100644 (file)
@@ -72,5 +72,3 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
        register long r7 __asm__("r7") = f;
        __asm_syscall("+r"(r2), "r"(r1), "r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7));
 }
-
-#define SYSCALL_USE_SOCKETCALL
index 160311faebeb8bdeae6f3bee925ebe3a63ac017f..d0b1482824ec231481324c60b5214348a9f0f1dc 100644 (file)
@@ -9,7 +9,16 @@
 #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
 typedef int greg_t, gregset_t[16];
 typedef int freg_t, fpregset_t[16];
-typedef struct sigcontext {
+typedef struct {
+       unsigned long oldmask;
+       unsigned long gregs[16];
+       unsigned long pc, pr, sr;
+       unsigned long gbr, mach, macl;
+       unsigned long fpregs[16];
+       unsigned long xfpregs[16];
+       unsigned int fpscr, fpul, ownedfp;
+} mcontext_t;
+struct sigcontext {
        unsigned long oldmask;
        unsigned long sc_regs[16];
        unsigned long sc_pc, sc_pr, sc_sr;
@@ -17,7 +26,7 @@ typedef struct sigcontext {
        unsigned long sc_fpregs[16];
        unsigned long sc_xfpregs[16];
        unsigned int sc_fpscr, sc_fpul, sc_ownedfp;
-} mcontext_t;
+};
 #else
 typedef struct {
        unsigned long __regs[58];
index 0102ddaf8d95879adc5183d53e8f0684887963f4..158afc091047e94dc52bce5ac8d9cd5927501f38 100644 (file)
 #define __NR_fsmount           432
 #define __NR_fspick            433
 #define __NR_pidfd_open                434
+#define __NR_clone3            435
+#define __NR_close_range       436
+#define __NR_openat2           437
+#define __NR_pidfd_getfd       438
+#define __NR_faccessat2                439
 
index 3ee9c1a9309a2cd3a647b11aa8b4cb0d129ec25b..199c2d55f936a0d9b95498f725f96ac04e9c7d1e 100644 (file)
@@ -1,17 +1,16 @@
-static inline struct pthread *__pthread_self()
+static inline uintptr_t __get_tp()
 {
-       char *self;
-       __asm__ ("stc gbr,%0" : "=r" (self) );
-       return (struct pthread *) (self - sizeof(struct pthread));
+       uintptr_t tp;
+       __asm__ ("stc gbr,%0" : "=r" (tp) );
+       return tp;
 }
 
 #define TLS_ABOVE_TP
 #define GAP_ABOVE_TP 8
-#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread))
 
-#define MC_PC sc_pc
+#define MC_PC pc
 
 #ifdef __FDPIC__
-#define MC_GOT sc_regs[12]
+#define MC_GOT gregs[12]
 #define CANCEL_GOT (*(uintptr_t *)((char *)__syscall_cp_asm+sizeof(uintptr_t)))
 #endif
index 1b88ad3917edefade45771b39e4d668e0e2ec23e..08627f812a720c07dd40334c7fc6cd6c6574a638 100644 (file)
@@ -13,7 +13,7 @@
 
 #define O_ASYNC      020000
 #define O_DIRECT     040000
-#define O_LARGEFILE       0
+#define O_LARGEFILE 0100000
 #define O_NOATIME  01000000
 #define O_PATH    010000000
 #define O_TMPFILE 020200000
index f47bdee5bf1e48cc172a1854265a04779d78287a..cfd9856f13d735750e9ef3aaae978dded9c9e746 100644 (file)
 #define __NR_fspick            (0x40000000 + 433)
 #define __NR_pidfd_open                (0x40000000 + 434)
 #define __NR_clone3            (0x40000000 + 435)
+#define __NR_close_range       (0x40000000 + 436)
+#define __NR_openat2           (0x40000000 + 437)
+#define __NR_pidfd_getfd       (0x40000000 + 438)
+#define __NR_faccessat2                (0x40000000 + 439)
 
 
 #define __NR_rt_sigaction (0x40000000 + 512)
index f640a1a1570903575ef960b32541e449d0b35b1d..c1e7716d525d82a98cea7523193dc07b524c0c2e 100644 (file)
@@ -1,14 +1,12 @@
-static inline struct pthread *__pthread_self()
+static inline uintptr_t __get_tp()
 {
-       struct pthread *self;
-       __asm__ ("mov %%fs:0,%0" : "=r" (self) );
-       return self;
+       uintptr_t tp;
+       __asm__ ("mov %%fs:0,%0" : "=r" (tp) );
+       return tp;
 }
 
-#define TP_ADJ(p) (p)
-
 #define MC_PC gregs[REG_RIP]
 
-#define CANARY canary2
+#define CANARY_PAD
 
 #define tls_mod_off_t unsigned long long
diff --git a/libc-top-half/musl/arch/x86_64/bits/fcntl.h b/libc-top-half/musl/arch/x86_64/bits/fcntl.h
deleted file mode 100644 (file)
index 1b88ad3..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#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 0200000
-#define O_NOFOLLOW  0400000
-#define O_CLOEXEC  02000000
-
-#define O_ASYNC      020000
-#define O_DIRECT     040000
-#define O_LARGEFILE       0
-#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 5
-#define F_SETLK 6
-#define F_SETLKW 7
-
-#define F_SETOWN_EX 15
-#define F_GETOWN_EX 16
-
-#define F_GETOWNER_UIDS 17
index 6a646ad3462322aaafe42a076f4bf3b4df048c19..a6117951047676835f1e26752986212c8216ebbb 100644 (file)
 #define __NR_fspick            433
 #define __NR_pidfd_open                434
 #define __NR_clone3            435
+#define __NR_close_range       436
+#define __NR_openat2           437
+#define __NR_pidfd_getfd       438
+#define __NR_faccessat2                439
 
index 65e880c62e2fa13ec874a7a7092b3c8093d5cbe3..c8c63f2e7a934081334a4ad0aa1ef0906dfd4249 100644 (file)
@@ -1,10 +1,8 @@
-static inline struct pthread *__pthread_self()
+static inline uintptr_t __get_tp()
 {
-       struct pthread *self;
-       __asm__ ("mov %%fs:0,%0" : "=r" (self) );
-       return self;
+       uintptr_t tp;
+       __asm__ ("mov %%fs:0,%0" : "=r" (tp) );
+       return tp;
 }
 
-#define TP_ADJ(p) (p)
-
 #define MC_PC gregs[REG_RIP]
index c50a66107d0decbaa0e8bcd7e9c3eded44260fd4..3a4ed7a12f93052b6f7ac6f9dd834041dfff63e0 100755 (executable)
@@ -30,7 +30,7 @@ System types:
 Optional features:
   --enable-optimize=...   optimize listed components for speed over size [auto]
   --enable-debug          build with debugging information [disabled]
-  --enable-warnings       build with recommended warnings flags [disabled]
+  --disable-warnings      build with recommended warnings flags [enabled]
   --enable-wrapper=...    build given musl toolchain wrapper [auto]
   --disable-shared        inhibit building shared library [enabled]
   --disable-static        inhibit building static library [enabled]
@@ -136,7 +136,7 @@ build=
 target=
 optimize=auto
 debug=no
-warnings=no
+warnings=yes
 shared=auto
 static=yes
 wrapper=auto
@@ -204,7 +204,7 @@ fi
 abs_builddir="$(pwd)" || fail "$0: cannot determine working directory"
 abs_srcdir="$(cd $srcdir && pwd)" || fail "$0: invalid source directory $srcdir"
 test "$abs_srcdir" = "$abs_builddir" && srcdir=.
-test "$srcdir" != "." -a -f Makefile -a ! -h Makefile && fail "$0: Makefile already exists in the working directory"
+test "$srcdir" != "." && test -f Makefile && test ! -h Makefile && fail "$0: Makefile already exists in the working directory"
 
 #
 # Get a temp filename we can use
@@ -279,7 +279,7 @@ echo "$cc_family"
 #
 # Figure out toolchain wrapper to build
 #
-if test "$wrapper" = auto -o "$wrapper" = detect ; then
+if test "$wrapper" = auto || test "$wrapper" = detect ; then
 echo "#include <stdlib.h>" > "$tmpc"
 echo "#if ! __GLIBC__" >> "$tmpc"
 echo "#error no" >> "$tmpc"
@@ -470,7 +470,7 @@ tryflag CFLAGS_AUTO -pipe
 # pointer is no longer needed for debugging.
 #
 if fnmatch '-g*|*\ -g*' "$CFLAGS_AUTO $CFLAGS" ; then :
-else 
+else
 tryflag CFLAGS_AUTO -fomit-frame-pointer
 fi
 
@@ -510,10 +510,13 @@ fi
 #
 # GCC defines -w as overriding any -W options, regardless of order, but
 # clang has a bunch of annoying warnings enabled by default and needs -w
-# to start from a clean slate. So use -w if building with clang.
+# to start from a clean slate. So use -w if building with clang. Also
+# turn off a common on-by-default cast warning regardless of compiler.
 #
 test "$cc_family" = clang && tryflag CFLAGS_AUTO -w
 
+tryflag CFLAGS_AUTO -Wno-pointer-to-int-cast
+
 #
 # Even with -std=c99, gcc accepts some constructs which are constraint
 # violations. We want to treat these as errors regardless of whether
@@ -524,6 +527,10 @@ tryflag CFLAGS_AUTO -Werror=implicit-function-declaration
 tryflag CFLAGS_AUTO -Werror=implicit-int
 tryflag CFLAGS_AUTO -Werror=pointer-sign
 tryflag CFLAGS_AUTO -Werror=pointer-arith
+tryflag CFLAGS_AUTO -Werror=int-conversion
+tryflag CFLAGS_AUTO -Werror=incompatible-pointer-types
+tryflag CFLAGS_AUTO -Werror=discarded-qualifiers
+tryflag CFLAGS_AUTO -Werror=discarded-array-qualifiers
 
 #
 # GCC ignores unused arguements by default, but Clang needs this extra
@@ -533,14 +540,17 @@ tryflag CFLAGS_AUTO -Werror=pointer-arith
 test "$cc_family" = clang && tryflag CFLAGS_AUTO -Qunused-arguments
 
 if test "x$warnings" = xyes ; then
-tryflag CFLAGS_AUTO -Wall
-tryflag CFLAGS_AUTO -Wno-parentheses
-tryflag CFLAGS_AUTO -Wno-uninitialized
-tryflag CFLAGS_AUTO -Wno-missing-braces
-tryflag CFLAGS_AUTO -Wno-unused-value
-tryflag CFLAGS_AUTO -Wno-unused-but-set-variable
-tryflag CFLAGS_AUTO -Wno-unknown-pragmas
-tryflag CFLAGS_AUTO -Wno-pointer-to-int-cast
+tryflag CFLAGS_AUTO -Waddress
+tryflag CFLAGS_AUTO -Warray-bounds
+tryflag CFLAGS_AUTO -Wchar-subscripts
+tryflag CFLAGS_AUTO -Wduplicate-decl-specifier
+tryflag CFLAGS_AUTO -Winit-self
+tryflag CFLAGS_AUTO -Wreturn-type
+tryflag CFLAGS_AUTO -Wsequence-point
+tryflag CFLAGS_AUTO -Wstrict-aliasing
+tryflag CFLAGS_AUTO -Wunused-function
+tryflag CFLAGS_AUTO -Wunused-label
+tryflag CFLAGS_AUTO -Wunused-variable
 fi
 
 # Determine if the compiler produces position-independent code (PIC)
index 3daf9f6004e4cfacf09fd1ff6470c2196f84455a..dcd474ff3acbcbed54bab229f399036a68dde258 100644 (file)
@@ -100,6 +100,8 @@ STRUCT iovec { void *iov_base; size_t iov_len; };
 #include <__struct_iovec.h>
 #endif
 
+STRUCT winsize { unsigned short ws_row, ws_col, ws_xpixel, ws_ypixel; };
+
 TYPEDEF unsigned socklen_t;
 TYPEDEF unsigned short sa_family_t;
 
index 549f92c1aa8841b8527f5ca1153d20637132c7f7..b5e7befb02980d7228d0d0ba4d58228ccfbcf435 100644 (file)
@@ -603,6 +603,7 @@ typedef struct {
 #define PT_GNU_EH_FRAME        0x6474e550
 #define PT_GNU_STACK   0x6474e551
 #define PT_GNU_RELRO   0x6474e552
+#define PT_GNU_PROPERTY        0x6474e553
 #define PT_LOSUNW      0x6ffffffa
 #define PT_SUNWBSS     0x6ffffffa
 #define PT_SUNWSTACK   0x6ffffffb
@@ -1085,6 +1086,7 @@ typedef struct {
 
 #define NT_GNU_BUILD_ID        3
 #define NT_GNU_GOLD_VERSION    4
+#define NT_GNU_PROPERTY_TYPE_0 5
 
 
 
index a08485e7f7cd2ef6da6b184d7d290e42a30f1da9..55a2ff1b1753176a2c5da66f8f2f0d821a9033ee 100644 (file)
@@ -59,6 +59,7 @@
 #define ETH_P_PREAUTH  0x88C7
 #define ETH_P_TIPC     0x88CA
 #define ETH_P_LLDP     0x88CC
+#define ETH_P_MRP      0x88E3
 #define ETH_P_MACSEC   0x88E5
 #define ETH_P_8021AH   0x88E7
 #define ETH_P_MVRP     0x88F5
index 06964893f1e6092caa1d1b003c15d42abfbf9781..b09efab018f2deeb2dae6750195d83f460a1fad5 100644 (file)
@@ -116,8 +116,10 @@ uint16_t ntohs(uint16_t);
 #define IPPROTO_MH       135
 #define IPPROTO_UDPLITE  136
 #define IPPROTO_MPLS     137
+#define IPPROTO_ETHERNET 143
 #define IPPROTO_RAW      255
-#define IPPROTO_MAX      256
+#define IPPROTO_MPTCP    262
+#define IPPROTO_MAX      263
 #endif
 
 #define IN6_IS_ADDR_UNSPECIFIED(a) \
@@ -216,6 +218,7 @@ uint16_t ntohs(uint16_t);
 #define IP_CHECKSUM        23
 #define IP_BIND_ADDRESS_NO_PORT 24
 #define IP_RECVFRAGSIZE    25
+#define IP_RECVERR_RFC4884 26
 #define IP_MULTICAST_IF    32
 #define IP_MULTICAST_TTL   33
 #define IP_MULTICAST_LOOP  34
index 44a007aaf5a252f21f5e5c76ec5fafd69267cf69..b7b997f5fde543203822036ebba6ff6c94bc7336 100644 (file)
@@ -78,6 +78,8 @@ enum {
        TCP_NLA_DSACK_DUPS,
        TCP_NLA_REORD_SEEN,
        TCP_NLA_SRTT,
+       TCP_NLA_TIMEOUT_REHASH,
+       TCP_NLA_BYTES_NOTSENT,
 };
 
 #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
@@ -181,6 +183,13 @@ struct tcphdr {
 #define TCP_CA_Recovery                3
 #define TCP_CA_Loss            4
 
+enum tcp_fastopen_client_fail {
+       TFO_STATUS_UNSPEC,
+       TFO_COOKIE_UNAVAILABLE,
+       TFO_DATA_NOT_ACKED,
+       TFO_SYN_RETRANSMITTED,
+};
+
 struct tcp_info {
        uint8_t tcpi_state;
        uint8_t tcpi_ca_state;
@@ -189,7 +198,7 @@ struct tcp_info {
        uint8_t tcpi_backoff;
        uint8_t tcpi_options;
        uint8_t tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4;
-       uint8_t tcpi_delivery_rate_app_limited : 1;
+       uint8_t tcpi_delivery_rate_app_limited : 1, tcpi_fastopen_client_fail : 2;
        uint32_t tcpi_rto;
        uint32_t tcpi_ato;
        uint32_t tcpi_snd_mss;
@@ -240,14 +249,15 @@ struct tcp_info {
 
 #define TCP_MD5SIG_MAXKEYLEN    80
 
-#define TCP_MD5SIG_FLAG_PREFIX  1
+#define TCP_MD5SIG_FLAG_PREFIX  0x1
+#define TCP_MD5SIG_FLAG_IFINDEX 0x2
 
 struct tcp_md5sig {
        struct sockaddr_storage tcpm_addr;
        uint8_t tcpm_flags;
        uint8_t tcpm_prefixlen;
        uint16_t tcpm_keylen;
-       uint32_t __tcpm_pad;
+       int tcpm_ifindex;
        uint8_t tcpm_key[TCP_MD5SIG_MAXKEYLEN];
 };
 
@@ -275,6 +285,8 @@ struct tcp_zerocopy_receive {
        uint64_t address;
        uint32_t length;
        uint32_t recv_skip_hint;
+       uint32_t inq;
+       int32_t err;
 };
 
 #endif
index ffd8907962eb24708cc089d9ba7b6fb544cba521..40c3f2034d6dfde07074041fc11791635e0aab72 100644 (file)
@@ -35,6 +35,7 @@ struct udphdr {
 #define UDP_ENCAP_GTP0         4
 #define UDP_ENCAP_GTP1U                5
 #define UDP_ENCAP_RXRPC                6
+#define TCP_ENCAP_ESPINTCP     7
 
 #define SOL_UDP            17
 
index 36dd4df1736875963773892def59c90528e0ffc7..a3a7f569d9d8d941c33fbf359dd8adb711017d1e 100644 (file)
@@ -52,6 +52,7 @@ int     sched_yield(void);
 
 #ifdef _GNU_SOURCE
 #define CSIGNAL                0x000000ff
+#define CLONE_NEWTIME  0x00000080
 #define CLONE_VM       0x00000100
 #define CLONE_FS       0x00000200
 #define CLONE_FILES    0x00000400
index a83503294d35604a36c111b1607b0b9ae6e0da20..ae74966b96bd9adcca641bdbba5706786d475a9e 100644 (file)
@@ -187,14 +187,24 @@ struct sigevent {
        union sigval sigev_value;
        int sigev_signo;
        int sigev_notify;
-       void (*sigev_notify_function)(union sigval);
-       pthread_attr_t *sigev_notify_attributes;
-       char __pad[56-3*sizeof(long)];
+       union {
+               char __pad[64 - 2*sizeof(int) - sizeof(union sigval)];
+               pid_t sigev_notify_thread_id;
+               struct {
+                       void (*sigev_notify_function)(union sigval);
+                       pthread_attr_t *sigev_notify_attributes;
+               } __sev_thread;
+       } __sev_fields;
 };
 
+#define sigev_notify_thread_id __sev_fields.sigev_notify_thread_id
+#define sigev_notify_function __sev_fields.__sev_thread.sigev_notify_function
+#define sigev_notify_attributes __sev_fields.__sev_thread.sigev_notify_attributes
+
 #define SIGEV_SIGNAL 0
 #define SIGEV_NONE 1
 #define SIGEV_THREAD 2
+#define SIGEV_THREAD_ID 4
 #endif
 
 #ifdef __wasilibc_unmodified_upstream /* WASI has no realtime signals */
index 3d4b1f3fc6e1c0ac8f85b9330845daa09b5bdaa7..e635275d681d0a9b99f89f19a156b12b5d3421b6 100644 (file)
@@ -170,6 +170,7 @@ int clearenv(void);
 #ifdef __wasilibc_unmodified_upstream /* WASI has no wait */
 #define WCOREDUMP(s) ((s) & 0x80)
 #define WIFCONTINUED(s) ((s) == 0xffff)
+void *reallocarray (void *, size_t, size_t);
 #endif
 #endif
 
index b637c8f58a18318f4f0beae3011fb000d653b14f..10e5f15e24b1d0684a292638d6501b62cd60f012 100644 (file)
@@ -55,8 +55,9 @@ struct fanotify_response {
 #define FAN_OPEN_PERM 0x10000
 #define FAN_ACCESS_PERM 0x20000
 #define FAN_OPEN_EXEC_PERM 0x40000
-#define FAN_ONDIR 0x40000000
+#define FAN_DIR_MODIFY 0x00080000
 #define FAN_EVENT_ON_CHILD 0x08000000
+#define FAN_ONDIR 0x40000000
 #define FAN_CLOSE (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE)
 #define FAN_MOVE (FAN_MOVED_FROM | FAN_MOVED_TO)
 #define FAN_CLOEXEC 0x01
@@ -70,6 +71,9 @@ struct fanotify_response {
 #define FAN_ENABLE_AUDIT 0x40
 #define FAN_REPORT_TID 0x100
 #define FAN_REPORT_FID 0x200
+#define FAN_REPORT_DIR_FID 0x00000400
+#define FAN_REPORT_NAME 0x00000800
+#define FAN_REPORT_DFID_NAME (FAN_REPORT_DIR_FID | FAN_REPORT_NAME)
 #define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK | FAN_ALL_CLASS_BITS | FAN_UNLIMITED_QUEUE | FAN_UNLIMITED_MARKS)
 #define FAN_MARK_ADD 0x01
 #define FAN_MARK_REMOVE 0x02
@@ -88,6 +92,8 @@ struct fanotify_response {
 #define FAN_ALL_OUTGOING_EVENTS (FAN_ALL_EVENTS | FAN_ALL_PERM_EVENTS | FAN_Q_OVERFLOW)
 #define FANOTIFY_METADATA_VERSION 3
 #define FAN_EVENT_INFO_TYPE_FID 1
+#define FAN_EVENT_INFO_TYPE_DFID_NAME 2
+#define FAN_EVENT_INFO_TYPE_DFID 3
 #define FAN_ALLOW 0x01
 #define FAN_DENY 0x02
 #define FAN_AUDIT 0x10
index 3877ca4bcb160ce80dbacd832b78d7e2cb86ce4c..cf3acb3ad842af6b30b01ebb74b1c8a6b2ac8596 100644 (file)
@@ -5,6 +5,8 @@
 extern "C" {
 #endif
 
+#define __NEED_struct_winsize
+
 #include <bits/alltypes.h>
 #include <bits/ioctl.h>
 
@@ -48,13 +50,6 @@ extern "C" {
 
 #define TIOCSER_TEMT 1
 
-struct winsize {
-       unsigned short ws_row;
-       unsigned short ws_col;
-       unsigned short ws_xpixel;
-       unsigned short ws_ypixel;
-};
-
 #define SIOCADDRT          0x890B
 #define SIOCDELRT          0x890C
 #define SIOCRTMSG          0x890D
index e6079c8442a01fa181d1711074ee09cbffaabee0..80615c5d57bf937a0990292a584187aa0b58de8d 100644 (file)
@@ -105,6 +105,7 @@ extern "C" {
 #ifdef _GNU_SOURCE
 #define MREMAP_MAYMOVE 1
 #define MREMAP_FIXED 2
+#define MREMAP_DONTUNMAP 4
 
 #define MLOCK_ONFAULT 0x01
 
index 31d43dfe13ea428a97709470832e06d5c10dacf1..411dc475639285c918b2db6ce7a821f397d158b5 100644 (file)
@@ -5,7 +5,9 @@
 extern "C" {
 #endif
 
+#define UNAME26            0x0020000
 #define ADDR_NO_RANDOMIZE  0x0040000
+#define FDPIC_FUNCPTRS     0x0080000
 #define MMAP_PAGE_ZERO     0x0100000
 #define ADDR_COMPAT_LAYOUT 0x0200000
 #define READ_IMPLIES_EXEC  0x0400000
@@ -17,6 +19,7 @@ extern "C" {
 
 #define PER_LINUX 0
 #define PER_LINUX_32BIT ADDR_LIMIT_32BIT
+#define PER_LINUX_FDPIC FDPIC_FUNCPTRS
 #define PER_SVR4 (1 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO)
 #define PER_SVR3 (2 | STICKY_TIMEOUTS | SHORT_INODE)
 #define PER_SCOSVR3 (3 | STICKY_TIMEOUTS | WHOLE_SECONDS | SHORT_INODE)
index d9c846e9c2eaec7103f71b9894d76a0b0345c1e2..4b9fcc050802c2e80a7565545886009442389eb7 100644 (file)
@@ -158,6 +158,9 @@ struct prctl_mm_map {
 #define PR_GET_TAGGED_ADDR_CTRL 56
 #define PR_TAGGED_ADDR_ENABLE (1UL << 0)
 
+#define PR_SET_IO_FLUSHER 57
+#define PR_GET_IO_FLUSHER 58
+
 int prctl (int, ...);
 
 #ifdef __cplusplus
index 092042503c975bf4f7930c92630a14ebacab9af9..51cf9d7ffb4bd9f33cb41f16f6113fb94e762595 100644 (file)
@@ -11,6 +11,7 @@ extern "C" {
 
 #define GRND_NONBLOCK  0x0001
 #define GRND_RANDOM    0x0002
+#define GRND_INSECURE  0x0004
 
 ssize_t getrandom(void *, size_t, unsigned);
 #else
index d73c780d41a4270f1665658b6c4f7d62b792780a..cbb533010e8b2b0f0eeab88788a1fa75d8b354cf 100644 (file)
@@ -8,6 +8,7 @@ extern "C" {
 #include <features.h>
 
 #define __NEED_pid_t
+#define __NEED_struct_winsize
 
 #include <bits/alltypes.h>
 
@@ -27,6 +28,9 @@ int cfsetispeed (struct termios *, speed_t);
 int tcgetattr (int, struct termios *);
 int tcsetattr (int, int, const struct termios *);
 
+int tcgetwinsize (int, struct winsize *);
+int tcsetwinsize (int, const struct winsize *);
+
 int tcsendbreak (int, int);
 int tcdrain (int);
 int tcflush (int, int);
index 0eac1cfe9d4a28c7d2db54be1b7f517276b9d0e8..c2469887ca19ecaf4fa43bee6e34db91aa2d447d 100644 (file)
@@ -134,6 +134,7 @@ int pause(void);
 
 #ifdef __wasilibc_unmodified_upstream /* WASI has no fork/exec */
 pid_t fork(void);
+pid_t _Fork(void);
 int execve(const char *, char *const [], char *const []);
 int execv(const char *, char *const []);
 int execle(const char *, const char *, ...);
@@ -268,6 +269,7 @@ int syncfs(int);
 int euidaccess(const char *, int);
 int eaccess(const char *, int);
 ssize_t copy_file_range(int, off_t *, int, off_t *, size_t, unsigned);
+pid_t gettid(void);
 #endif
 #endif
 
index d3d4ddd287fe91a23331bfd47934c9b7924e5c7b..6b868c841476a34b0bb3eea98be9611052b7b3ef 100644 (file)
@@ -1,6 +1,5 @@
 #define _GNU_SOURCE
 #define SYSCALL_NO_TLS 1
-#include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
 #include <stddef.h>
 #include <semaphore.h>
 #include <sys/membarrier.h>
 #include "pthread_impl.h"
+#include "fork_impl.h"
 #include "libc.h"
 #include "dynlink.h"
 
+#define malloc __libc_malloc
+#define calloc __libc_calloc
+#define realloc __libc_realloc
+#define free __libc_free
+
 static void error(const char *, ...);
 
 #define MAXP2(a,b) (-(-(a)&-(b)))
@@ -78,7 +83,7 @@ struct dso {
        struct dso **deps, *needed_by;
        size_t ndeps_direct;
        size_t next_dep;
-       int ctor_visitor;
+       pthread_t ctor_visitor;
        char *rpath_orig, *rpath;
        struct tls_module tls;
        size_t tls_id;
@@ -556,6 +561,20 @@ static void reclaim_gaps(struct dso *dso)
        }
 }
 
+static ssize_t read_loop(int fd, void *p, size_t n)
+{
+       for (size_t i=0; i<n; ) {
+               ssize_t l = read(fd, (char *)p+i, n-i);
+               if (l<0) {
+                       if (errno==EINTR) continue;
+                       else return -1;
+               }
+               if (l==0) return i;
+               i += l;
+       }
+       return n;
+}
+
 static void *mmap_fixed(void *p, size_t n, int prot, int flags, int fd, off_t off)
 {
        static int no_map_fixed;
@@ -1060,13 +1079,17 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
                                snprintf(etc_ldso_path, sizeof etc_ldso_path,
                                        "%.*s/etc/ld-musl-" LDSO_ARCH ".path",
                                        (int)prefix_len, prefix);
-                               FILE *f = fopen(etc_ldso_path, "rbe");
-                               if (f) {
-                                       if (getdelim(&sys_path, (size_t[1]){0}, 0, f) <= 0) {
+                               fd = open(etc_ldso_path, O_RDONLY|O_CLOEXEC);
+                               if (fd>=0) {
+                                       size_t n = 0;
+                                       if (!fstat(fd, &st)) n = st.st_size;
+                                       if ((sys_path = malloc(n+1)))
+                                               sys_path[n] = 0;
+                                       if (!sys_path || read_loop(fd, sys_path, n)<0) {
                                                free(sys_path);
                                                sys_path = "";
                                        }
-                                       fclose(f);
+                                       close(fd);
                                } else if (errno != ENOENT) {
                                        sys_path = "";
                                }
@@ -1378,7 +1401,7 @@ void __libc_exit_fini()
 {
        struct dso *p;
        size_t dyn[DYN_CNT];
-       int self = __pthread_self()->tid;
+       pthread_t self = __pthread_self();
 
        /* Take both locks before setting shutting_down, so that
         * either lock is sufficient to read its value. The lock
@@ -1404,6 +1427,17 @@ void __libc_exit_fini()
        }
 }
 
+void __ldso_atfork(int who)
+{
+       if (who<0) {
+               pthread_rwlock_wrlock(&lock);
+               pthread_mutex_lock(&init_fini_lock);
+       } else {
+               pthread_mutex_unlock(&init_fini_lock);
+               pthread_rwlock_unlock(&lock);
+       }
+}
+
 static struct dso **queue_ctors(struct dso *dso)
 {
        size_t cnt, qpos, spos, i;
@@ -1462,6 +1496,13 @@ static struct dso **queue_ctors(struct dso *dso)
        }
        queue[qpos] = 0;
        for (i=0; i<qpos; i++) queue[i]->mark = 0;
+       for (i=0; i<qpos; i++)
+               if (queue[i]->ctor_visitor && queue[i]->ctor_visitor->tid < 0) {
+                       error("State of %s is inconsistent due to multithreaded fork\n",
+                               queue[i]->name);
+                       free(queue);
+                       if (runtime) longjmp(*rtld_fail, 1);
+               }
 
        return queue;
 }
@@ -1470,7 +1511,7 @@ static void do_init_fini(struct dso **queue)
 {
        struct dso *p;
        size_t dyn[DYN_CNT], i;
-       int self = __pthread_self()->tid;
+       pthread_t self = __pthread_self();
 
        pthread_mutex_lock(&init_fini_lock);
        for (i=0; (p=queue[i]); i++) {
@@ -1579,7 +1620,7 @@ static void install_new_tls(void)
 
        /* Install new dtv for each thread. */
        for (j=0, td=self; !j || td!=self; j++, td=td->next) {
-               td->dtv = td->dtv_copy = newdtv[j];
+               td->dtv = newdtv[j];
        }
 
        __tl_unlock();
@@ -1947,7 +1988,7 @@ void __dls3(size_t *sp, size_t *auxv)
        debug.bp = dl_debug_state;
        debug.head = head;
        debug.base = ldso.base;
-       debug.state = 0;
+       debug.state = RT_CONSISTENT;
        _dl_debug_state();
 
        if (replace_argv0) argv[0] = replace_argv0;
@@ -1996,6 +2037,9 @@ void *dlopen(const char *file, int mode)
        pthread_rwlock_wrlock(&lock);
        __inhibit_ptc();
 
+       debug.state = RT_ADD;
+       _dl_debug_state();
+
        p = 0;
        if (shutting_down) {
                error("Cannot dlopen while program is exiting.");
@@ -2055,8 +2099,9 @@ void *dlopen(const char *file, int mode)
        load_deps(p);
        extend_bfs_deps(p);
        pthread_mutex_lock(&init_fini_lock);
-       if (!p->constructed) ctor_queue = queue_ctors(p);
+       int constructed = p->constructed;
        pthread_mutex_unlock(&init_fini_lock);
+       if (!constructed) ctor_queue = queue_ctors(p);
        if (!p->relocated && (mode & RTLD_LAZY)) {
                prepare_lazy(p);
                for (i=0; p->deps[i]; i++)
@@ -2088,9 +2133,10 @@ void *dlopen(const char *file, int mode)
        update_tls_size();
        if (tls_cnt != orig_tls_cnt)
                install_new_tls();
-       _dl_debug_state();
        orig_tail = tail;
 end:
+       debug.state = RT_CONSISTENT;
+       _dl_debug_state();
        __release_ptc();
        if (p) gencnt++;
        pthread_rwlock_unlock(&lock);
index 6d34fa869340810fc9abddfd5b8412df324aece7..a1a3e7914b02e138fa5aedd3eb8c7e6aa0d19f1f 100644 (file)
@@ -9,6 +9,12 @@
 #include "syscall.h"
 #include "atomic.h"
 #include "pthread_impl.h"
+#include "aio_impl.h"
+
+#define malloc __libc_malloc
+#define calloc __libc_calloc
+#define realloc __libc_realloc
+#define free __libc_free
 
 /* The following is a threads-based implementation of AIO with minimal
  * dependence on implementation details. Most synchronization is
@@ -70,6 +76,10 @@ static struct aio_queue *****map;
 static volatile int aio_fd_cnt;
 volatile int __aio_fut;
 
+static size_t io_thread_stack_size;
+
+#define MAX(a,b) ((a)>(b) ? (a) : (b))
+
 static struct aio_queue *__aio_get_queue(int fd, int need)
 {
        if (fd < 0) {
@@ -84,6 +94,10 @@ static struct aio_queue *__aio_get_queue(int fd, int need)
                pthread_rwlock_unlock(&maplock);
                if (fcntl(fd, F_GETFD) < 0) return 0;
                pthread_rwlock_wrlock(&maplock);
+               if (!io_thread_stack_size) {
+                       unsigned long val = __getauxval(AT_MINSIGSTKSZ);
+                       io_thread_stack_size = MAX(MINSIGSTKSZ+2048, val+512);
+               }
                if (!map) map = calloc(sizeof *map, (-1U/2+1)>>24);
                if (!map) goto out;
                if (!map[a]) map[a] = calloc(sizeof **map, 256);
@@ -259,15 +273,6 @@ static void *io_thread_func(void *ctx)
        return 0;
 }
 
-static size_t io_thread_stack_size = MINSIGSTKSZ+2048;
-static pthread_once_t init_stack_size_once;
-
-static void init_stack_size()
-{
-       unsigned long val = __getauxval(AT_MINSIGSTKSZ);
-       if (val > MINSIGSTKSZ) io_thread_stack_size = val + 512;
-}
-
 static int submit(struct aiocb *cb, int op)
 {
        int ret = 0;
@@ -293,7 +298,6 @@ static int submit(struct aiocb *cb, int op)
                else
                        pthread_attr_init(&a);
        } else {
-               pthread_once(&init_stack_size_once, init_stack_size);
                pthread_attr_init(&a);
                pthread_attr_setstacksize(&a, io_thread_stack_size);
                pthread_attr_setguardsize(&a, 0);
@@ -392,6 +396,20 @@ int __aio_close(int fd)
        return fd;
 }
 
+void __aio_atfork(int who)
+{
+       if (who<0) {
+               pthread_rwlock_rdlock(&maplock);
+               return;
+       }
+       if (who>0 && map) for (int a=0; a<(-1U/2+1)>>24; a++)
+               if (map[a]) for (int b=0; b<256; b++)
+                       if (map[a][b]) for (int c=0; c<256; c++)
+                               if (map[a][b][c]) for (int d=0; d<256; d++)
+                                       map[a][b][c][d] = 0;
+       pthread_rwlock_unlock(&maplock);
+}
+
 weak_alias(aio_cancel, aio_cancel64);
 weak_alias(aio_error, aio_error64);
 weak_alias(aio_fsync, aio_fsync64);
index 34b66f8787a49fb97c264b962285a413c34b50dc..1c1060e340a13cedcbd458c98578ec88c483f4e4 100644 (file)
@@ -3,6 +3,7 @@
 #include <time.h>
 #include "atomic.h"
 #include "pthread_impl.h"
+#include "aio_impl.h"
 
 int aio_suspend(const struct aiocb *const cbs[], int cnt, const struct timespec *ts)
 {
index d58da7f14eebbade38bad764be46095e840889f2..28b4bf2f2a4a4d70bc018d52c612505d049cfce4 100644 (file)
@@ -6,7 +6,9 @@
 #include <signal.h>
 #endif
 #include <sys/sysinfo.h>
+#ifdef __wasilibc_unmodified_upstream
 #include "syscall.h"
+#endif
 #include "libc.h"
 
 #define JT(x) (-256|(x))
index d3f798517e872099ffad66e783e2e1e3be3e84dd..d722607b02290fc37018bdb4e39be492fe57c2a5 100644 (file)
@@ -15,7 +15,7 @@
  * No copyright is claimed, and the software is hereby placed in the public
  * domain.  In case this attempt to disclaim copyright and place the software
  * in the public domain is deemed null and void, then the software is
- * Copyright (c) 1998-2012 Solar Designer and it is hereby released to the
+ * Copyright (c) 1998-2014 Solar Designer and it is hereby released to the
  * general public under the following terms:
  *
  * Redistribution and use in source and binary forms, with or without
  * you place this code and any modifications you make under a license
  * of your choice.
  *
- * This implementation is mostly compatible with OpenBSD's bcrypt.c (prefix
- * "$2a$") by Niels Provos <provos at citi.umich.edu>, and uses some of his
- * ideas.  The password hashing algorithm was designed by David Mazieres
- * <dm at lcs.mit.edu>.  For more information on the level of compatibility,
- * please refer to the comments in BF_set_key() below and to the included
- * crypt(3) man page.
+ * This implementation is fully compatible with OpenBSD's bcrypt.c for prefix
+ * "$2b$", originally by Niels Provos <provos at citi.umich.edu>, and it uses
+ * some of his ideas.  The password hashing algorithm was designed by David
+ * Mazieres <dm at lcs.mit.edu>.  For information on the level of
+ * compatibility for bcrypt hash prefixes other than "$2b$", please refer to
+ * the comments in BF_set_key() below and to the included crypt(3) man page.
  *
  * There's a paper on the algorithm that explains its design decisions:
  *
@@ -533,6 +533,7 @@ static void BF_set_key(const char *key, BF_key expanded, BF_key initial,
  * Valid combinations of settings are:
  *
  * Prefix "$2a$": bug = 0, safety = 0x10000
+ * Prefix "$2b$": bug = 0, safety = 0
  * Prefix "$2x$": bug = 1, safety = 0
  * Prefix "$2y$": bug = 0, safety = 0
  */
@@ -596,12 +597,14 @@ static void BF_set_key(const char *key, BF_key expanded, BF_key initial,
        initial[0] ^= sign;
 }
 
+static const unsigned char flags_by_subtype[26] = {
+       2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0
+};
+
 static char *BF_crypt(const char *key, const char *setting,
        char *output, BF_word min)
 {
-       static const unsigned char flags_by_subtype[26] =
-               {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0};
        struct {
                BF_ctx ctx;
                BF_key expanded_key;
@@ -746,9 +749,11 @@ char *__crypt_blowfish(const char *key, const char *setting, char *output)
 {
        const char *test_key = "8b \xd0\xc1\xd2\xcf\xcc\xd8";
        const char *test_setting = "$2a$00$abcdefghijklmnopqrstuu";
-       static const char test_hash[2][34] =
-               {"VUrPmXD6q/nVSSp7pNDhCR9071IfIRe\0\x55", /* $2x$ */
-               "i1D709vfamulimlGcq0qq3UvuUasvEa\0\x55"}; /* $2a$, $2y$ */
+       static const char test_hashes[2][34] = {
+               "i1D709vfamulimlGcq0qq3UvuUasvEa\0\x55", /* 'a', 'b', 'y' */
+               "VUrPmXD6q/nVSSp7pNDhCR9071IfIRe\0\x55", /* 'x' */
+       };
+       const char *test_hash = test_hashes[0];
        char *retval;
        const char *p;
        int ok;
@@ -768,8 +773,11 @@ char *__crypt_blowfish(const char *key, const char *setting, char *output)
  * detected by the self-test.
  */
        memcpy(buf.s, test_setting, sizeof(buf.s));
-       if (retval)
+       if (retval) {
+               unsigned int flags = flags_by_subtype[setting[2] - 'a'];
+               test_hash = test_hashes[flags & 1];
                buf.s[2] = setting[2];
+       }
        memset(buf.o, 0x55, sizeof(buf.o));
        buf.o[sizeof(buf.o) - 1] = 0;
        p = BF_crypt(test_key, buf.s, buf.o, 1);
@@ -777,7 +785,7 @@ char *__crypt_blowfish(const char *key, const char *setting, char *output)
        ok = (p == buf.o &&
            !memcmp(p, buf.s, 7 + 22) &&
            !memcmp(p + (7 + 22),
-           test_hash[buf.s[2] & 1],
+           test_hash,
            31 + 1 + 1 + 1));
 
        {
index 772baba32d54fff8b63e69952aeec60fce48a03f..a93141ed36a8d7d06d73100304a068f94a8011bc 100644 (file)
@@ -67,7 +67,7 @@ void *__copy_tls(unsigned char *mem)
        }
 #endif
        dtv[0] = libc.tls_cnt;
-       td->dtv = td->dtv_copy = dtv;
+       td->dtv = dtv;
        return td;
 }
 
index e32596d10fff84a89a73cab4c0d84c26101769af..bf5a280ad95b66187dabb3e61ce4ebecb5d2ac08 100644 (file)
@@ -9,7 +9,7 @@ void __init_ssp(void *entropy)
        if (entropy) memcpy(&__stack_chk_guard, entropy, sizeof(uintptr_t));
        else __stack_chk_guard = (uintptr_t)&__stack_chk_guard * 1103515245;
 
-       __pthread_self()->CANARY = __stack_chk_guard;
+       __pthread_self()->canary = __stack_chk_guard;
 }
 
 void __stack_chk_fail(void)
index e1980f10a5b6488a8a82a98a6a987e6db7997e3b..f21f458eca149e8f87b9eb4da706382c7d164ae3 100644 (file)
@@ -6,8 +6,6 @@
 #include "lock.h"
 #include "ksigaction.h"
 
-hidden volatile int __abort_lock[1];
-
 _Noreturn void abort(void)
 {
        raise(SIGABRT);
diff --git a/libc-top-half/musl/src/exit/abort_lock.c b/libc-top-half/musl/src/exit/abort_lock.c
new file mode 100644 (file)
index 0000000..3af72c7
--- /dev/null
@@ -0,0 +1,3 @@
+#include "pthread_impl.h"
+
+volatile int __abort_lock[1];
index 49b0dc3ec434c68a92ad3c38f087aec74c45e4e3..94edd8272792e79fb0e2079142342c518e22fbfe 100644 (file)
@@ -4,6 +4,5 @@
 _Noreturn void __assert_fail(const char *expr, const char *file, int line, const char *func)
 {
        fprintf(stderr, "Assertion failed: %s (%s: %s: %d)\n", expr, file, func, line);
-       fflush(NULL);
        abort();
 }
index d3ce6522df7dd810ee1014ae84a9ceaa08e66927..429d0b033004b257f0259ecc49a5f3965b325584 100644 (file)
@@ -1,12 +1,16 @@
 #include <stdlib.h>
 #include "libc.h"
 #include "lock.h"
+#include "fork_impl.h"
 
 #define COUNT 32
 
 static void (*funcs[COUNT])(void);
 static int count;
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
 static volatile int lock[1];
+volatile int *const __at_quick_exit_lockptr = lock;
+#endif
 
 void __funcs_on_quick_exit()
 {
index 160d277aeb76a3837f856052ec9b93653eabdb2b..155292d0ea5fed4390c0e6c86dce40032d6df470 100644 (file)
@@ -2,6 +2,12 @@
 #include <stdint.h>
 #include "libc.h"
 #include "lock.h"
+#include "fork_impl.h"
+
+#define malloc __libc_malloc
+#define calloc __libc_calloc
+#define realloc undef
+#define free undef
 
 /* Ensure that at least 32 atexit handlers can be registered without malloc */
 #define COUNT 32
@@ -14,7 +20,11 @@ static struct fl
 } builtin, *head;
 
 static int slot;
+
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
 static volatile int lock[1];
+volatile int *const __atexit_lockptr = lock;
+#endif
 
 void __funcs_on_exit()
 {
index d38a5417f1ea97a720e13fd8fbda223fe53c193a..e9da20158c157582eb45c72f63f552a0c87383e5 100644 (file)
@@ -9,4 +9,10 @@ hidden int __mkostemps(char *, int, int);
 hidden int __ptsname_r(int, char *, size_t);
 hidden char *__randname(char *);
 
+hidden void *__libc_malloc(size_t);
+hidden void *__libc_malloc_impl(size_t);
+hidden void *__libc_calloc(size_t, size_t);
+hidden void *__libc_realloc(void *, size_t);
+hidden void __libc_free(void *);
+
 #endif
index f372afe2d707657c6b7385d6f260c45e75717129..d02206ec1cbb3de3ce0a527f3464542f7520f428 100644 (file)
@@ -15,7 +15,6 @@ extern char **__environ;
 hidden int __dup3(int, int, int);
 hidden int __mkostemps(char *, int, int);
 hidden int __execvpe(const char *, char *const *, char *const *);
-hidden int __aio_close(int);
 hidden off_t __lseek(int, off_t, int);
 
 #endif
diff --git a/libc-top-half/musl/src/internal/aio_impl.h b/libc-top-half/musl/src/internal/aio_impl.h
new file mode 100644 (file)
index 0000000..a865766
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef AIO_IMPL_H
+#define AIO_IMPL_H
+
+extern hidden volatile int __aio_fut;
+
+extern hidden int __aio_close(int);
+extern hidden void __aio_atfork(int);
+
+#endif
diff --git a/libc-top-half/musl/src/internal/fork_impl.h b/libc-top-half/musl/src/internal/fork_impl.h
new file mode 100644 (file)
index 0000000..f6b3aa0
--- /dev/null
@@ -0,0 +1,21 @@
+#include <features.h>
+
+#ifdef __wasilibc_unmodified_upstream
+extern hidden volatile int *const __at_quick_exit_lockptr;
+extern hidden volatile int *const __atexit_lockptr;
+extern hidden volatile int *const __dlerror_lockptr;
+extern hidden volatile int *const __gettext_lockptr;
+extern hidden volatile int *const __locale_lockptr;
+extern hidden volatile int *const __random_lockptr;
+extern hidden volatile int *const __sem_open_lockptr;
+extern hidden volatile int *const __stdio_ofl_lockptr;
+extern hidden volatile int *const __syslog_lockptr;
+extern hidden volatile int *const __timezone_lockptr;
+
+extern hidden volatile int *const __bump_lockptr;
+
+extern hidden volatile int *const __vmlock_lockptr;
+
+hidden void __malloc_atfork(int);
+hidden void __ldso_atfork(int);
+#endif
index a45894b7e477ed0168736032be0908d0911f6493..2b06ac45aa99ab19d15212dae887b0d4225186da 100644 (file)
@@ -285,5 +285,8 @@ hidden double __math_uflow(uint32_t);
 hidden double __math_oflow(uint32_t);
 hidden double __math_divzero(uint32_t);
 hidden double __math_invalid(double);
+#if LDBL_MANT_DIG != DBL_MANT_DIG
+hidden long double __math_invalidl(long double);
+#endif
 
 #endif
index 228ca6445942a5970244830e367ad51417817c0e..7f79b7f5193781f1a13f7c9229baf2082302d3fe 100644 (file)
@@ -17,6 +17,10 @@ struct __locale_map {
        const struct __locale_map *next;
 };
 
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
+extern hidden volatile int __locale_lock[1];
+#endif
+
 extern hidden const struct __locale_map __c_dot_utf8;
 extern hidden const struct __locale_struct __c_locale;
 extern hidden const struct __locale_struct __c_dot_utf8_locale;
index 37115e61c4b5eac08033c07411a6f0a1ed175709..29787fb1f428127af3f4070061d9c7dd2f55550b 100644 (file)
@@ -8,8 +8,8 @@ hidden void __unlock(volatile int *);
 #define UNLOCK(x) __unlock(x)
 #else
 // No locking needed.
-#define LOCK(x) ((void)(x))
-#define UNLOCK(x) ((void)(x))
+#define LOCK(x) ((void)0)
+#define UNLOCK(x) ((void)0)
 #endif
 
 #endif
index 5742dfc55cb979a225dc6e12aaf784807da7eb12..de2b9d8b477e68d44191851048bd6fdfba91b0a2 100644 (file)
 #include "atomic.h"
 #include "futex.h"
 
+#include "pthread_arch.h"
+
 #define pthread __pthread
 
 struct pthread {
        /* Part 1 -- these fields may be external or
         * internal (accessed via asm) ABI. Do not change. */
        struct pthread *self;
+#ifndef TLS_ABOVE_TP
        uintptr_t *dtv;
+#endif
        struct pthread *prev, *next; /* non-ABI */
        uintptr_t sysinfo;
-       uintptr_t canary, canary2;
+#ifndef TLS_ABOVE_TP
+#ifdef CANARY_PAD
+       uintptr_t canary_pad;
+#endif
+       uintptr_t canary;
+#endif
 
        /* Part 2 -- implementation details, non-ABI. */
        int tid;
@@ -43,6 +52,7 @@ struct pthread {
                long off;
                volatile void *volatile pending;
        } robust_list;
+       int h_errno_val;
        volatile int timer_id;
        locale_t locale;
        volatile int killlock[1];
@@ -51,21 +61,19 @@ struct pthread {
 
        /* Part 3 -- the positions of these fields relative to
         * the end of the structure is external and internal ABI. */
-       uintptr_t canary_at_end;
-       uintptr_t *dtv_copy;
+#ifdef TLS_ABOVE_TP
+       uintptr_t canary;
+       uintptr_t *dtv;
+#endif
 };
 
 enum {
-       DT_EXITING = 0,
+       DT_EXITED = 0,
+       DT_EXITING,
        DT_JOINABLE,
        DT_DETACHED,
 };
 
-struct __timer {
-       int timerid;
-       pthread_t thread;
-};
-
 #define __SU (sizeof(size_t)/sizeof(int))
 
 #define _a_stacksize __u.__s[0]
@@ -98,16 +106,22 @@ struct __timer {
 #define _b_waiters2 __u.__vi[4]
 #define _b_inst __u.__p[3]
 
-#include "pthread_arch.h"
-
-#ifndef CANARY
-#define CANARY canary
+#ifndef TP_OFFSET
+#define TP_OFFSET 0
 #endif
 
 #ifndef DTP_OFFSET
 #define DTP_OFFSET 0
 #endif
 
+#ifdef TLS_ABOVE_TP
+#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + TP_OFFSET)
+#define __pthread_self() ((pthread_t)(__get_tp() - sizeof(struct __pthread) - TP_OFFSET))
+#else
+#define TP_ADJ(p) (p)
+#define __pthread_self() ((pthread_t)__get_tp())
+#endif
+
 #ifndef tls_mod_off_t
 #define tls_mod_off_t size_t
 #endif
@@ -141,7 +155,6 @@ hidden int __pthread_key_delete_impl(pthread_key_t);
 
 extern hidden volatile size_t __pthread_tsd_size;
 extern hidden void *__pthread_tsd_main[];
-extern hidden volatile int __aio_fut;
 extern hidden volatile int __eintr_valid_flag;
 
 hidden int __clone(int (*)(void *), void *, int, void *, ...);
@@ -176,6 +189,8 @@ hidden void __tl_sync(pthread_t);
 
 extern hidden volatile int __thread_list_lock;
 
+extern hidden volatile int __abort_lock[1];
+
 extern hidden unsigned __default_stacksize;
 extern hidden unsigned __default_guardsize;
 
index 4167ba72e7510d7c2da6a048306a03cdc4ad8f9e..7f19dd95160e2fe03c7ae44f0a5f03e15aa6e8a5 100644 (file)
@@ -2,7 +2,9 @@
 #define _STDIO_IMPL_H
 
 #include <stdio.h>
+#if defined(__wasilibc_unmodified_upstream)
 #include "syscall.h"
+#endif
 
 #define UNGET 8
 
index 975a0031d4fb6ef46892ba5e97821bc5b09e2c80..d5f294d437fb91ccd7870d8ff360b2bdadde668d 100644 (file)
@@ -2,6 +2,7 @@
 #define _INTERNAL_SYSCALL_H
 
 #include <features.h>
+#include <errno.h>
 #include <sys/syscall.h>
 #include "syscall_arch.h"
 
@@ -57,15 +58,22 @@ hidden long __syscall_ret(unsigned long),
 #define __syscall_cp(...) __SYSCALL_DISP(__syscall_cp,__VA_ARGS__)
 #define syscall_cp(...) __syscall_ret(__syscall_cp(__VA_ARGS__))
 
-#ifndef SYSCALL_USE_SOCKETCALL
-#define __socketcall(nm,a,b,c,d,e,f) __syscall(SYS_##nm, a, b, c, d, e, f)
-#define __socketcall_cp(nm,a,b,c,d,e,f) __syscall_cp(SYS_##nm, a, b, c, d, e, f)
-#else
-#define __socketcall(nm,a,b,c,d,e,f) __syscall(SYS_socketcall, __SC_##nm, \
-    ((long [6]){ (long)a, (long)b, (long)c, (long)d, (long)e, (long)f }))
-#define __socketcall_cp(nm,a,b,c,d,e,f) __syscall_cp(SYS_socketcall, __SC_##nm, \
-    ((long [6]){ (long)a, (long)b, (long)c, (long)d, (long)e, (long)f }))
-#endif
+static inline long __alt_socketcall(int sys, int sock, int cp, long a, long b, long c, long d, long e, long f)
+{
+       long r;
+       if (cp) r = __syscall_cp(sys, a, b, c, d, e, f);
+       else r = __syscall(sys, a, b, c, d, e, f);
+       if (r != -ENOSYS) return r;
+#ifdef SYS_socketcall
+       if (cp) r = __syscall_cp(SYS_socketcall, sock, ((long[6]){a, b, c, d, e, f}));
+       else r = __syscall(SYS_socketcall, sock, ((long[6]){a, b, c, d, e, f}));
+#endif
+       return r;
+}
+#define __socketcall(nm, a, b, c, d, e, f) __alt_socketcall(SYS_##nm, __SC_##nm, 0, \
+       (long)(a), (long)(b), (long)(c), (long)(d), (long)(e), (long)(f))
+#define __socketcall_cp(nm, a, b, c, d, e, f) __alt_socketcall(SYS_##nm, __SC_##nm, 1, \
+       (long)(a), (long)(b), (long)(c), (long)(d), (long)(e), (long)(f))
 
 /* fixup legacy 16-bit junk */
 
@@ -338,6 +346,12 @@ hidden long __syscall_ret(unsigned long),
 #define __SC_recvmmsg    19
 #define __SC_sendmmsg    20
 
+/* This is valid only because all socket syscalls are made via
+ * socketcall, which always fills unused argument slots with zeros. */
+#ifndef SYS_accept
+#define SYS_accept SYS_accept4
+#endif
+
 #ifndef SO_RCVTIMEO_OLD
 #define SO_RCVTIMEO_OLD  20
 #endif
index 3fcc7779530234fa7734c464876a70b8f2e9bab4..afe59253ea0ee9f46d55d64757c3e84ec43c99a7 100644 (file)
@@ -4,6 +4,12 @@
 #include "pthread_impl.h"
 #include "dynlink.h"
 #include "lock.h"
+#include "fork_impl.h"
+
+#define malloc __libc_malloc
+#define calloc __libc_calloc
+#define realloc __libc_realloc
+#define free __libc_free
 
 char *dlerror()
 {
@@ -19,6 +25,7 @@ char *dlerror()
 
 static volatile int freebuf_queue_lock[1];
 static void **freebuf_queue;
+volatile int *const __dlerror_lockptr = freebuf_queue_lock;
 
 void __dl_thread_cleanup(void)
 {
@@ -35,13 +42,16 @@ void __dl_thread_cleanup(void)
 hidden void __dl_vseterr(const char *fmt, va_list ap)
 {
        LOCK(freebuf_queue_lock);
-       while (freebuf_queue) {
-               void **p = freebuf_queue;
-               freebuf_queue = *p;
-               free(p);
-       }
+       void **q = freebuf_queue;
+       freebuf_queue = 0;
        UNLOCK(freebuf_queue_lock);
 
+       while (q) {
+               void **p = *q;
+               free(q);
+               q = p;
+       }
+
        va_list ap2;
        va_copy(ap2, ap);
        pthread_t self = __pthread_self();
index 2e5502d1e38f430db52e699ebbcbebe7fa3a5670..dd465923adf42a1baea9e79075d56655a234a608 100644 (file)
@@ -6,9 +6,11 @@
 int lutimes(const char *filename, const struct timeval tv[2])
 {
        struct timespec times[2];
-       times[0].tv_sec  = tv[0].tv_sec;
-       times[0].tv_nsec = tv[0].tv_usec * 1000;
-       times[1].tv_sec  = tv[1].tv_sec;
-       times[1].tv_nsec = tv[1].tv_usec * 1000;
-       return utimensat(AT_FDCWD, filename, times, AT_SYMLINK_NOFOLLOW);
+       if (tv) {
+               times[0].tv_sec  = tv[0].tv_sec;
+               times[0].tv_nsec = tv[0].tv_usec * 1000;
+               times[1].tv_sec  = tv[1].tv_sec;
+               times[1].tv_nsec = tv[1].tv_usec * 1000;
+       }
+       return utimensat(AT_FDCWD, filename, tv ? times : 0, AT_SYMLINK_NOFOLLOW);
 }
diff --git a/libc-top-half/musl/src/linux/gettid.c b/libc-top-half/musl/src/linux/gettid.c
new file mode 100644 (file)
index 0000000..7076713
--- /dev/null
@@ -0,0 +1,8 @@
+#define _GNU_SOURCE
+#include <unistd.h>
+#include "pthread_impl.h"
+
+pid_t gettid(void)
+{
+       return __pthread_self()->tid;
+}
index 9ebe906ed8b25d28590e2b909006969f4beee0c0..343f7360ee1199c917ca871c7cac9711856fc0a5 100644 (file)
@@ -9,13 +9,8 @@ static void dummy_0(void)
 {
 }
 
-static void dummy_1(pthread_t t)
-{
-}
-
 weak_alias(dummy_0, __tl_lock);
 weak_alias(dummy_0, __tl_unlock);
-weak_alias(dummy_1, __tl_sync);
 
 static sem_t barrier_sem;
 
index 1248fdbfdc83c10c9fea5a3a51d5be0edb905869..47142f141ff577d1cb4e39f37913b040d0955a52 100644 (file)
@@ -1,8 +1,36 @@
 #define _GNU_SOURCE
 #include <unistd.h>
+#include <signal.h>
 #include "syscall.h"
+#include "libc.h"
+
+struct ctx {
+       size_t count;
+       const gid_t *list;
+       int ret;
+};
+
+static void do_setgroups(void *p)
+{
+       struct ctx *c = p;
+       if (c->ret<0) return;
+       int ret = __syscall(SYS_setgroups, c->count, c->list);
+       if (ret && !c->ret) {
+               /* If one thread fails to set groups after another has already
+                * succeeded, forcibly killing the process is the only safe
+                * thing to do. State is inconsistent and dangerous. Use
+                * SIGKILL because it is uncatchable. */
+               __block_all_sigs(0);
+               __syscall(SYS_kill, __syscall(SYS_getpid), SIGKILL);
+       }
+       c->ret = ret;
+}
 
 int setgroups(size_t count, const gid_t list[])
 {
-       return syscall(SYS_setgroups, count, list);
+       /* ret is initially nonzero so that failure of the first thread does not
+        * trigger the safety kill above. */
+       struct ctx c = { .count = count, .list = list, .ret = 1 };
+       __synccall(do_setgroups, &c);
+       return __syscall_ret(c.ret);
 }
index 4c30439389805224cb14910f09674b56a2177711..d1e6c6d13af33d6f095a58ed583502214fa2bcad 100644 (file)
 #include "atomic.h"
 #include "pleval.h"
 #include "lock.h"
+#include "fork_impl.h"
+
+#define malloc __libc_malloc
+#define calloc __libc_calloc
+#define realloc undef
+#define free undef
 
 struct binding {
        struct binding *next;
@@ -34,9 +40,11 @@ static char *gettextdir(const char *domainname, size_t *dirlen)
        return 0;
 }
 
+static volatile int lock[1];
+volatile int *const __gettext_lockptr = lock;
+
 char *bindtextdomain(const char *domainname, const char *dirname)
 {
-       static volatile int lock[1];
        struct binding *p, *q;
 
        if (!domainname) return 0;
index 802b8bfe1c72458d8def7c505df0c022d026b1f0..385d12069d5733d8a291ceb6c870d842befed953 100644 (file)
@@ -1,6 +1,11 @@
 #include <stdlib.h>
 #include "locale_impl.h"
 
+#define malloc undef
+#define calloc undef
+#define realloc undef
+#define free __libc_free
+
 void freelocale(locale_t l)
 {
        if (__loc_is_allocated(l)) free(l);
index ff9ae981cfe001ffdab32b6315edd5cfd36c6144..ebfb158f4a32fc6c25d04f609c04e4cab647a287 100644 (file)
@@ -3,9 +3,16 @@
 #ifdef __wasilibc_unmodified_upstream // WASI has no mmap
 #include <sys/mman.h>
 #endif
+#include <stdlib.h>
 #include "locale_impl.h"
 #include "libc.h"
 #include "lock.h"
+#include "fork_impl.h"
+
+#define malloc __libc_malloc
+#define calloc undef
+#define realloc undef
+#define free undef
 
 const char *__lctrans_impl(const char *msg, const struct __locale_map *lm)
 {
@@ -23,9 +30,13 @@ static const char envvars[][12] = {
        "LC_MESSAGES",
 };
 
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
+volatile int __locale_lock[1];
+volatile int *const __locale_lockptr = __locale_lock;
+#endif
+
 const struct __locale_map *__get_locale(int cat, const char *val)
 {
-       static volatile int lock[1];
        static void *volatile loc_head;
        const struct __locale_map *p;
        struct __locale_map *new = 0;
@@ -56,21 +67,13 @@ const struct __locale_map *__get_locale(int cat, const char *val)
        for (p=loc_head; p; p=p->next)
                if (!strcmp(val, p->name)) return p;
 
-       LOCK(lock);
-
-       for (p=loc_head; p; p=p->next)
-               if (!strcmp(val, p->name)) {
-                       UNLOCK(lock);
-                       return p;
-               }
-
 #ifdef __wasilibc_unmodified_upstream // WASI has no mmap, though this code could be made to use something else
        if (!libc.secure) path = getenv("MUSL_LOCPATH");
        /* FIXME: add a default path? */
 
        if (path) for (; *path; path=z+!!*z) {
                z = __strchrnul(path, ':');
-               l = z - path - !!*z;
+               l = z - path;
                if (l >= sizeof buf - n - 2) continue;
                memcpy(buf, path, l);
                buf[l] = '/';
@@ -112,6 +115,5 @@ const struct __locale_map *__get_locale(int cat, const char *val)
         * requested name was "C" or "POSIX". */
        if (!new && cat == LC_CTYPE) new = (void *)&__c_dot_utf8;
 
-       UNLOCK(lock);
        return new;
 }
index be8fe44f7fc64f3ff41489ea3a4e19c21253d2d2..11c778557a484f16142467ecf07f5d24cc049972 100644 (file)
@@ -4,18 +4,15 @@
 #include <pthread.h>
 #endif
 #include "locale_impl.h"
+#include "lock.h"
 
-#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
-static pthread_once_t default_locale_once;
-#endif
-static struct __locale_struct default_locale, default_ctype_locale;
+#define malloc __libc_malloc
+#define calloc undef
+#define realloc undef
+#define free undef
 
-static void default_locale_init(void)
-{
-       for (int i=0; i<LC_ALL; i++)
-               default_locale.cat[i] = __get_locale(i, "");
-       default_ctype_locale.cat[LC_CTYPE] = default_locale.cat[LC_CTYPE];
-}
+static int default_locale_init_done;
+static struct __locale_struct default_locale, default_ctype_locale;
 
 int __loc_is_allocated(locale_t loc)
 {
@@ -23,7 +20,7 @@ int __loc_is_allocated(locale_t loc)
                && loc != &default_locale && loc != &default_ctype_locale;
 }
 
-locale_t __newlocale(int mask, const char *name, locale_t loc)
+static locale_t do_newlocale(int mask, const char *name, locale_t loc)
 {
        struct __locale_struct tmp;
 
@@ -46,19 +43,14 @@ locale_t __newlocale(int mask, const char *name, locale_t loc)
        if (!memcmp(&tmp, C_LOCALE, sizeof tmp)) return C_LOCALE;
        if (!memcmp(&tmp, UTF8_LOCALE, sizeof tmp)) return UTF8_LOCALE;
 
-#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
        /* And provide builtins for the initial default locale, and a
         * variant of the C locale honoring the default locale's encoding. */
-       pthread_once(&default_locale_once, default_locale_init);
-#else
-       {
-               static int called;
-               if (called == 0) {
-                       default_locale_init();
-                       called = 1;
-               }
+       if (!default_locale_init_done) {
+               for (int i=0; i<LC_ALL; i++)
+                       default_locale.cat[i] = __get_locale(i, "");
+               default_ctype_locale.cat[LC_CTYPE] = default_locale.cat[LC_CTYPE];
+               default_locale_init_done = 1;
        }
-#endif
        if (!memcmp(&tmp, &default_locale, sizeof tmp)) return &default_locale;
        if (!memcmp(&tmp, &default_ctype_locale, sizeof tmp))
                return &default_ctype_locale;
@@ -69,4 +61,12 @@ locale_t __newlocale(int mask, const char *name, locale_t loc)
        return loc;
 }
 
+locale_t __newlocale(int mask, const char *name, locale_t loc)
+{
+       LOCK(__locale_lock);
+       loc = do_newlocale(mask, name, loc);
+       UNLOCK(__locale_lock);
+       return loc;
+}
+
 weak_alias(__newlocale, newlocale);
index 2bc7b50070fc0dd21b3e24158fd4797b21b0345a..360c4437644b88f86ac8b9f0db5d92915019c8d7 100644 (file)
@@ -9,12 +9,11 @@ static char buf[LC_ALL*(LOCALE_NAME_MAX+1)];
 
 char *setlocale(int cat, const char *name)
 {
-       static volatile int lock[1];
        const struct __locale_map *lm;
 
        if ((unsigned)cat > LC_ALL) return 0;
 
-       LOCK(lock);
+       LOCK(__locale_lock);
 
        /* For LC_ALL, setlocale is required to return a string which
         * encodes the current setting for all categories. The format of
@@ -36,7 +35,7 @@ char *setlocale(int cat, const char *name)
                                }
                                lm = __get_locale(i, part);
                                if (lm == LOC_MAP_FAILED) {
-                                       UNLOCK(lock);
+                                       UNLOCK(__locale_lock);
                                        return 0;
                                }
                                tmp_locale.cat[i] = lm;
@@ -57,14 +56,14 @@ char *setlocale(int cat, const char *name)
                        s += l+1;
                }
                *--s = 0;
-               UNLOCK(lock);
+               UNLOCK(__locale_lock);
                return same==LC_ALL ? (char *)part : buf;
        }
 
        if (name) {
                lm = __get_locale(cat, name);
                if (lm == LOC_MAP_FAILED) {
-                       UNLOCK(lock);
+                       UNLOCK(__locale_lock);
                        return 0;
                }
                libc.global_locale.cat[cat] = lm;
@@ -73,7 +72,7 @@ char *setlocale(int cat, const char *name)
        }
        char *ret = lm ? (char *)lm->name : "C";
 
-       UNLOCK(lock);
+       UNLOCK(__locale_lock);
 
        return ret;
 }
diff --git a/libc-top-half/musl/src/malloc/free.c b/libc-top-half/musl/src/malloc/free.c
new file mode 100644 (file)
index 0000000..f17a952
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdlib.h>
+
+void free(void *p)
+{
+       return __libc_free(p);
+}
diff --git a/libc-top-half/musl/src/malloc/libc_calloc.c b/libc-top-half/musl/src/malloc/libc_calloc.c
new file mode 100644 (file)
index 0000000..d25eabe
--- /dev/null
@@ -0,0 +1,4 @@
+#define calloc __libc_calloc
+#define malloc __libc_malloc
+
+#include "calloc.c"
index f8931ba597dcadcd56a00e8858c89cbe43a6b8fb..43a988fbb8adcc3c6469c21b9a4ad13018f2758b 100644 (file)
@@ -6,6 +6,7 @@
 #include "libc.h"
 #include "lock.h"
 #include "syscall.h"
+#include "fork_impl.h"
 
 #define ALIGN 16
 
@@ -31,10 +32,12 @@ static int traverses_stack_p(uintptr_t old, uintptr_t new)
        return 0;
 }
 
+static volatile int lock[1];
+volatile int *const __bump_lockptr = lock;
+
 static void *__simple_malloc(size_t n)
 {
        static uintptr_t brk, cur, end;
-       static volatile int lock[1];
        static unsigned mmap_step;
        size_t align=1;
        void *p;
@@ -100,4 +103,16 @@ static void *__simple_malloc(size_t n)
        return p;
 }
 
-weak_alias(__simple_malloc, malloc);
+weak_alias(__simple_malloc, __libc_malloc_impl);
+
+void *__libc_malloc(size_t n)
+{
+       return __libc_malloc_impl(n);
+}
+
+static void *default_malloc(size_t n)
+{
+       return __libc_malloc_impl(n);
+}
+
+weak_alias(default_malloc, malloc);
index 16acd1ea3bfce5f00d7b5c222e87e77e166dac55..151c48b804b237b2bf77fb4008f1c02b534d8167 100644 (file)
 #define is_allzero __malloc_allzerop
 #define dump_heap __dump_heap
 
+#define malloc __libc_malloc_impl
+#define realloc __libc_realloc
+#define free __libc_free
+
 #if USE_REAL_ASSERT
 #include <assert.h>
 #else
@@ -56,7 +60,8 @@ __attribute__((__visibility__("hidden")))
 extern int __malloc_lock[1];
 
 #define LOCK_OBJ_DEF \
-int __malloc_lock[1];
+int __malloc_lock[1]; \
+void __malloc_atfork(int who) { malloc_atfork(who); }
 
 static inline void rdlock()
 {
@@ -73,5 +78,16 @@ static inline void unlock()
 static inline void upgradelock()
 {
 }
+static inline void resetlock()
+{
+       __malloc_lock[0] = 0;
+}
+
+static inline void malloc_atfork(int who)
+{
+       if (who<0) rdlock();
+       else if (who>0) resetlock();
+       else unlock();
+}
 
 #endif
index a440a4eab2d39172d6e0358a2aec34b98e21aba3..ce6a960c6f5835d5fd7f16818a139e5d9991edb4 100644 (file)
@@ -3,6 +3,7 @@
 
 size_t malloc_usable_size(void *p)
 {
+       if (!p) return 0;
        struct meta *g = get_meta(p);
        int idx = get_slot_index(p);
        size_t stride = get_stride(g);
index c0997ad858fdf8d554eece3b29e02affedf0aa90..53f5f959ec24c31dc57a4a22af1c445ccc35804f 100644 (file)
@@ -9,6 +9,11 @@
 #include "atomic.h"
 #include "pthread_impl.h"
 #include "malloc_impl.h"
+#include "fork_impl.h"
+
+#define malloc __libc_malloc
+#define realloc __libc_realloc
+#define free __libc_free
 
 #if defined(__GNUC__) && defined(__PIC__)
 #define inline inline __attribute__((always_inline))
@@ -527,3 +532,21 @@ void __malloc_donate(char *start, char *end)
        c->csize = n->psize = C_INUSE | (end-start);
        __bin_chunk(c);
 }
+
+void __malloc_atfork(int who)
+{
+       if (who<0) {
+               lock(mal.split_merge_lock);
+               for (int i=0; i<64; i++)
+                       lock(mal.bins[i].lock);
+       } else if (!who) {
+               for (int i=0; i<64; i++)
+                       unlock(mal.bins[i].lock);
+               unlock(mal.split_merge_lock);
+       } else {
+               for (int i=0; i<64; i++)
+                       mal.bins[i].lock[0] = mal.bins[i].lock[1] = 0;
+               mal.split_merge_lock[1] = 0;
+               mal.split_merge_lock[0] = 0;
+       }
+}
diff --git a/libc-top-half/musl/src/malloc/realloc.c b/libc-top-half/musl/src/malloc/realloc.c
new file mode 100644 (file)
index 0000000..fb0e8b7
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdlib.h>
+
+void *realloc(void *p, size_t n)
+{
+       return __libc_realloc(p, n);
+}
diff --git a/libc-top-half/musl/src/malloc/reallocarray.c b/libc-top-half/musl/src/malloc/reallocarray.c
new file mode 100644 (file)
index 0000000..4a6ebe4
--- /dev/null
@@ -0,0 +1,13 @@
+#define _BSD_SOURCE
+#include <errno.h>
+#include <stdlib.h>
+
+void *reallocarray(void *ptr, size_t m, size_t n)
+{
+       if (n && m > -1 / n) {
+               errno = ENOMEM;
+               return 0;
+       }
+
+       return realloc(ptr, m * n);
+}
diff --git a/libc-top-half/musl/src/math/__math_invalidl.c b/libc-top-half/musl/src/math/__math_invalidl.c
new file mode 100644 (file)
index 0000000..1fca99d
--- /dev/null
@@ -0,0 +1,9 @@
+#include <float.h>
+#include "libm.h"
+
+#if LDBL_MANT_DIG != DBL_MANT_DIG
+long double __math_invalidl(long double x)
+{
+       return (x - x) / (x - x);
+}
+#endif
index f890520a5cd78d38ee3285aba4e179c730f76768..6e1d367d3d6ad580798b3fb19ce6f8a070cf65e3 100644 (file)
@@ -1,6 +1,6 @@
 #include <math.h>
 
-#if __ARM_PCS_VFP
+#if __ARM_PCS_VFP && __ARM_FP&8
 
 double fabs(double x)
 {
index 874af9606c3c863a05a96ad89aa04c000fe37e69..567e2e91015374af42b5ce05f9cde2b92497a81b 100644 (file)
@@ -1,6 +1,6 @@
 #include <math.h>
 
-#if __ARM_PCS_VFP || (__VFP_FP__ && !__SOFTFP__)
+#if (__ARM_PCS_VFP || (__VFP_FP__ && !__SOFTFP__)) && (__ARM_FP&8)
 
 double sqrt(double x)
 {
index f1f6d76c780cee4b342e9facd441fa1e8d80384f..5ba26559621357018857a49e40b5745aaca4cc51 100644 (file)
-/* origin: FreeBSD /usr/src/lib/msun/src/e_sqrt.c */
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * Developed at SunSoft, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
- */
-/* sqrt(x)
- * Return correctly rounded sqrt.
- *           ------------------------------------------
- *           |  Use the hardware sqrt if you have one |
- *           ------------------------------------------
- * Method:
- *   Bit by bit method using integer arithmetic. (Slow, but portable)
- *   1. Normalization
- *      Scale x to y in [1,4) with even powers of 2:
- *      find an integer k such that  1 <= (y=x*2^(2k)) < 4, then
- *              sqrt(x) = 2^k * sqrt(y)
- *   2. Bit by bit computation
- *      Let q  = sqrt(y) truncated to i bit after binary point (q = 1),
- *           i                                                   0
- *                                     i+1         2
- *          s  = 2*q , and      y  =  2   * ( y - q  ).         (1)
- *           i      i            i                 i
- *
- *      To compute q    from q , one checks whether
- *                  i+1       i
- *
- *                            -(i+1) 2
- *                      (q + 2      ) <= y.                     (2)
- *                        i
- *                                                            -(i+1)
- *      If (2) is false, then q   = q ; otherwise q   = q  + 2      .
- *                             i+1   i             i+1   i
- *
- *      With some algebric manipulation, it is not difficult to see
- *      that (2) is equivalent to
- *                             -(i+1)
- *                      s  +  2       <= y                      (3)
- *                       i                i
- *
- *      The advantage of (3) is that s  and y  can be computed by
- *                                    i      i
- *      the following recurrence formula:
- *          if (3) is false
- *
- *          s     =  s  ,       y    = y   ;                    (4)
- *           i+1      i          i+1    i
- *
- *          otherwise,
- *                         -i                     -(i+1)
- *          s     =  s  + 2  ,  y    = y  -  s  - 2             (5)
- *           i+1      i          i+1    i     i
- *
- *      One may easily use induction to prove (4) and (5).
- *      Note. Since the left hand side of (3) contain only i+2 bits,
- *            it does not necessary to do a full (53-bit) comparison
- *            in (3).
- *   3. Final rounding
- *      After generating the 53 bits result, we compute one more bit.
- *      Together with the remainder, we can decide whether the
- *      result is exact, bigger than 1/2ulp, or less than 1/2ulp
- *      (it will never equal to 1/2ulp).
- *      The rounding mode can be detected by checking whether
- *      huge + tiny is equal to huge, and whether huge - tiny is
- *      equal to huge for some floating point number "huge" and "tiny".
- *
- * Special cases:
- *      sqrt(+-0) = +-0         ... exact
- *      sqrt(inf) = inf
- *      sqrt(-ve) = NaN         ... with invalid signal
- *      sqrt(NaN) = NaN         ... with invalid signal for signaling NaN
- */
-
+#include <stdint.h>
+#include <math.h>
 #include "libm.h"
+#include "sqrt_data.h"
 
-static const double tiny = 1.0e-300;
+#define FENV_SUPPORT 1
 
-double sqrt(double x)
+/* returns a*b*2^-32 - e, with error 0 <= e < 1.  */
+static inline uint32_t mul32(uint32_t a, uint32_t b)
 {
-       double z;
-       int32_t sign = (int)0x80000000;
-       int32_t ix0,s0,q,m,t,i;
-       uint32_t r,t1,s1,ix1,q1;
+       return (uint64_t)a*b >> 32;
+}
 
-       EXTRACT_WORDS(ix0, ix1, x);
+/* returns a*b*2^-64 - e, with error 0 <= e < 3.  */
+static inline uint64_t mul64(uint64_t a, uint64_t b)
+{
+       uint64_t ahi = a>>32;
+       uint64_t alo = a&0xffffffff;
+       uint64_t bhi = b>>32;
+       uint64_t blo = b&0xffffffff;
+       return ahi*bhi + (ahi*blo >> 32) + (alo*bhi >> 32);
+}
 
-       /* take care of Inf and NaN */
-       if ((ix0&0x7ff00000) == 0x7ff00000) {
-               return x*x + x;  /* sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN */
-       }
-       /* take care of zero */
-       if (ix0 <= 0) {
-               if (((ix0&~sign)|ix1) == 0)
-                       return x;  /* sqrt(+-0) = +-0 */
-               if (ix0 < 0)
-                       return (x-x)/(x-x);  /* sqrt(-ve) = sNaN */
-       }
-       /* normalize x */
-       m = ix0>>20;
-       if (m == 0) {  /* subnormal x */
-               while (ix0 == 0) {
-                       m -= 21;
-                       ix0 |= (ix1>>11);
-                       ix1 <<= 21;
-               }
-               for (i=0; (ix0&0x00100000) == 0; i++)
-                       ix0<<=1;
-               m -= i - 1;
-               ix0 |= ix1>>(32-i);
-               ix1 <<= i;
-       }
-       m -= 1023;    /* unbias exponent */
-       ix0 = (ix0&0x000fffff)|0x00100000;
-       if (m & 1) {  /* odd m, double x to make it even */
-               ix0 += ix0 + ((ix1&sign)>>31);
-               ix1 += ix1;
-       }
-       m >>= 1;      /* m = [m/2] */
-
-       /* generate sqrt(x) bit by bit */
-       ix0 += ix0 + ((ix1&sign)>>31);
-       ix1 += ix1;
-       q = q1 = s0 = s1 = 0;  /* [q,q1] = sqrt(x) */
-       r = 0x00200000;        /* r = moving bit from right to left */
-
-       while (r != 0) {
-               t = s0 + r;
-               if (t <= ix0) {
-                       s0   = t + r;
-                       ix0 -= t;
-                       q   += r;
-               }
-               ix0 += ix0 + ((ix1&sign)>>31);
-               ix1 += ix1;
-               r >>= 1;
-       }
+double sqrt(double x)
+{
+       uint64_t ix, top, m;
 
-       r = sign;
-       while (r != 0) {
-               t1 = s1 + r;
-               t  = s0;
-               if (t < ix0 || (t == ix0 && t1 <= ix1)) {
-                       s1 = t1 + r;
-                       if ((t1&sign) == sign && (s1&sign) == 0)
-                               s0++;
-                       ix0 -= t;
-                       if (ix1 < t1)
-                               ix0--;
-                       ix1 -= t1;
-                       q1 += r;
-               }
-               ix0 += ix0 + ((ix1&sign)>>31);
-               ix1 += ix1;
-               r >>= 1;
+       /* special case handling.  */
+       ix = asuint64(x);
+       top = ix >> 52;
+       if (predict_false(top - 0x001 >= 0x7ff - 0x001)) {
+               /* x < 0x1p-1022 or inf or nan.  */
+               if (ix * 2 == 0)
+                       return x;
+               if (ix == 0x7ff0000000000000)
+                       return x;
+               if (ix > 0x7ff0000000000000)
+                       return __math_invalid(x);
+               /* x is subnormal, normalize it.  */
+               ix = asuint64(x * 0x1p52);
+               top = ix >> 52;
+               top -= 52;
        }
 
-       /* use floating add to find out rounding direction */
-       if ((ix0|ix1) != 0) {
-               z = 1.0 - tiny; /* raise inexact flag */
-               if (z >= 1.0) {
-                       z = 1.0 + tiny;
-                       if (q1 == (uint32_t)0xffffffff) {
-                               q1 = 0;
-                               q++;
-                       } else if (z > 1.0) {
-                               if (q1 == (uint32_t)0xfffffffe)
-                                       q++;
-                               q1 += 2;
-                       } else
-                               q1 += q1 & 1;
-               }
+       /* argument reduction:
+          x = 4^e m; with integer e, and m in [1, 4)
+          m: fixed point representation [2.62]
+          2^e is the exponent part of the result.  */
+       int even = top & 1;
+       m = (ix << 11) | 0x8000000000000000;
+       if (even) m >>= 1;
+       top = (top + 0x3ff) >> 1;
+
+       /* approximate r ~ 1/sqrt(m) and s ~ sqrt(m) when m in [1,4)
+
+          initial estimate:
+          7bit table lookup (1bit exponent and 6bit significand).
+
+          iterative approximation:
+          using 2 goldschmidt iterations with 32bit int arithmetics
+          and a final iteration with 64bit int arithmetics.
+
+          details:
+
+          the relative error (e = r0 sqrt(m)-1) of a linear estimate
+          (r0 = a m + b) is |e| < 0.085955 ~ 0x1.6p-4 at best,
+          a table lookup is faster and needs one less iteration
+          6 bit lookup table (128b) gives |e| < 0x1.f9p-8
+          7 bit lookup table (256b) gives |e| < 0x1.fdp-9
+          for single and double prec 6bit is enough but for quad
+          prec 7bit is needed (or modified iterations). to avoid
+          one more iteration >=13bit table would be needed (16k).
+
+          a newton-raphson iteration for r is
+            w = r*r
+            u = 3 - m*w
+            r = r*u/2
+          can use a goldschmidt iteration for s at the end or
+            s = m*r
+
+          first goldschmidt iteration is
+            s = m*r
+            u = 3 - s*r
+            r = r*u/2
+            s = s*u/2
+          next goldschmidt iteration is
+            u = 3 - s*r
+            r = r*u/2
+            s = s*u/2
+          and at the end r is not computed only s.
+
+          they use the same amount of operations and converge at the
+          same quadratic rate, i.e. if
+            r1 sqrt(m) - 1 = e, then
+            r2 sqrt(m) - 1 = -3/2 e^2 - 1/2 e^3
+          the advantage of goldschmidt is that the mul for s and r
+          are independent (computed in parallel), however it is not
+          "self synchronizing": it only uses the input m in the
+          first iteration so rounding errors accumulate. at the end
+          or when switching to larger precision arithmetics rounding
+          errors dominate so the first iteration should be used.
+
+          the fixed point representations are
+            m: 2.30 r: 0.32, s: 2.30, d: 2.30, u: 2.30, three: 2.30
+          and after switching to 64 bit
+            m: 2.62 r: 0.64, s: 2.62, d: 2.62, u: 2.62, three: 2.62  */
+
+       static const uint64_t three = 0xc0000000;
+       uint64_t r, s, d, u, i;
+
+       i = (ix >> 46) % 128;
+       r = (uint32_t)__rsqrt_tab[i] << 16;
+       /* |r sqrt(m) - 1| < 0x1.fdp-9 */
+       s = mul32(m>>32, r);
+       /* |s/sqrt(m) - 1| < 0x1.fdp-9 */
+       d = mul32(s, r);
+       u = three - d;
+       r = mul32(r, u) << 1;
+       /* |r sqrt(m) - 1| < 0x1.7bp-16 */
+       s = mul32(s, u) << 1;
+       /* |s/sqrt(m) - 1| < 0x1.7bp-16 */
+       d = mul32(s, r);
+       u = three - d;
+       r = mul32(r, u) << 1;
+       /* |r sqrt(m) - 1| < 0x1.3704p-29 (measured worst-case) */
+       r = r << 32;
+       s = mul64(m, r);
+       d = mul64(s, r);
+       u = (three<<32) - d;
+       s = mul64(s, u);  /* repr: 3.61 */
+       /* -0x1p-57 < s - sqrt(m) < 0x1.8001p-61 */
+       s = (s - 2) >> 9; /* repr: 12.52 */
+       /* -0x1.09p-52 < s - sqrt(m) < -0x1.fffcp-63 */
+
+       /* s < sqrt(m) < s + 0x1.09p-52,
+          compute nearest rounded result:
+          the nearest result to 52 bits is either s or s+0x1p-52,
+          we can decide by comparing (2^52 s + 0.5)^2 to 2^104 m.  */
+       uint64_t d0, d1, d2;
+       double y, t;
+       d0 = (m << 42) - s*s;
+       d1 = s - d0;
+       d2 = d1 + s + 1;
+       s += d1 >> 63;
+       s &= 0x000fffffffffffff;
+       s |= top << 52;
+       y = asdouble(s);
+       if (FENV_SUPPORT) {
+               /* handle rounding modes and inexact exception:
+                  only (s+1)^2 == 2^42 m case is exact otherwise
+                  add a tiny value to cause the fenv effects.  */
+               uint64_t tiny = predict_false(d2==0) ? 0 : 0x0010000000000000;
+               tiny |= (d1^d2) & 0x8000000000000000;
+               t = asdouble(tiny);
+               y = eval_as_double(y + t);
        }
-       ix0 = (q>>1) + 0x3fe00000;
-       ix1 = q1>>1;
-       if (q&1)
-               ix1 |= sign;
-       INSERT_WORDS(z, ix0 + ((uint32_t)m << 20), ix1);
-       return z;
+       return y;
 }
diff --git a/libc-top-half/musl/src/math/sqrt_data.c b/libc-top-half/musl/src/math/sqrt_data.c
new file mode 100644 (file)
index 0000000..61bc22f
--- /dev/null
@@ -0,0 +1,19 @@
+#include "sqrt_data.h"
+const uint16_t __rsqrt_tab[128] = {
+0xb451,0xb2f0,0xb196,0xb044,0xaef9,0xadb6,0xac79,0xab43,
+0xaa14,0xa8eb,0xa7c8,0xa6aa,0xa592,0xa480,0xa373,0xa26b,
+0xa168,0xa06a,0x9f70,0x9e7b,0x9d8a,0x9c9d,0x9bb5,0x9ad1,
+0x99f0,0x9913,0x983a,0x9765,0x9693,0x95c4,0x94f8,0x9430,
+0x936b,0x92a9,0x91ea,0x912e,0x9075,0x8fbe,0x8f0a,0x8e59,
+0x8daa,0x8cfe,0x8c54,0x8bac,0x8b07,0x8a64,0x89c4,0x8925,
+0x8889,0x87ee,0x8756,0x86c0,0x862b,0x8599,0x8508,0x8479,
+0x83ec,0x8361,0x82d8,0x8250,0x81c9,0x8145,0x80c2,0x8040,
+0xff02,0xfd0e,0xfb25,0xf947,0xf773,0xf5aa,0xf3ea,0xf234,
+0xf087,0xeee3,0xed47,0xebb3,0xea27,0xe8a3,0xe727,0xe5b2,
+0xe443,0xe2dc,0xe17a,0xe020,0xdecb,0xdd7d,0xdc34,0xdaf1,
+0xd9b3,0xd87b,0xd748,0xd61a,0xd4f1,0xd3cd,0xd2ad,0xd192,
+0xd07b,0xcf69,0xce5b,0xcd51,0xcc4a,0xcb48,0xca4a,0xc94f,
+0xc858,0xc764,0xc674,0xc587,0xc49d,0xc3b7,0xc2d4,0xc1f4,
+0xc116,0xc03c,0xbf65,0xbe90,0xbdbe,0xbcef,0xbc23,0xbb59,
+0xba91,0xb9cc,0xb90a,0xb84a,0xb78c,0xb6d0,0xb617,0xb560,
+};
diff --git a/libc-top-half/musl/src/math/sqrt_data.h b/libc-top-half/musl/src/math/sqrt_data.h
new file mode 100644 (file)
index 0000000..260c7f9
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _SQRT_DATA_H
+#define _SQRT_DATA_H
+
+#include <features.h>
+#include <stdint.h>
+
+/* if x in [1,2): i = (int)(64*x);
+   if x in [2,4): i = (int)(32*x-64);
+   __rsqrt_tab[i]*2^-16 is estimating 1/sqrt(x) with small relative error:
+   |__rsqrt_tab[i]*0x1p-16*sqrt(x) - 1| < -0x1.fdp-9 < 2^-8 */
+extern hidden const uint16_t __rsqrt_tab[128];
+
+#endif
index d6ace38aa6b49491926c394651826d8f696ebcda..740d81cbab421707a090d2475523807fd27b1337 100644 (file)
@@ -1,83 +1,83 @@
-/* origin: FreeBSD /usr/src/lib/msun/src/e_sqrtf.c */
-/*
- * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
- */
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * Developed at SunPro, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
- */
-
+#include <stdint.h>
+#include <math.h>
 #include "libm.h"
+#include "sqrt_data.h"
 
-static const float tiny = 1.0e-30;
+#define FENV_SUPPORT 1
 
-float sqrtf(float x)
+static inline uint32_t mul32(uint32_t a, uint32_t b)
 {
-       float z;
-       int32_t sign = (int)0x80000000;
-       int32_t ix,s,q,m,t,i;
-       uint32_t r;
+       return (uint64_t)a*b >> 32;
+}
 
-       GET_FLOAT_WORD(ix, x);
+/* see sqrt.c for more detailed comments.  */
 
-       /* take care of Inf and NaN */
-       if ((ix&0x7f800000) == 0x7f800000)
-               return x*x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN */
+float sqrtf(float x)
+{
+       uint32_t ix, m, m1, m0, even, ey;
 
-       /* take care of zero */
-       if (ix <= 0) {
-               if ((ix&~sign) == 0)
-                       return x;  /* sqrt(+-0) = +-0 */
-               if (ix < 0)
-                       return (x-x)/(x-x);  /* sqrt(-ve) = sNaN */
-       }
-       /* normalize x */
-       m = ix>>23;
-       if (m == 0) {  /* subnormal x */
-               for (i = 0; (ix&0x00800000) == 0; i++)
-                       ix<<=1;
-               m -= i - 1;
+       ix = asuint(x);
+       if (predict_false(ix - 0x00800000 >= 0x7f800000 - 0x00800000)) {
+               /* x < 0x1p-126 or inf or nan.  */
+               if (ix * 2 == 0)
+                       return x;
+               if (ix == 0x7f800000)
+                       return x;
+               if (ix > 0x7f800000)
+                       return __math_invalidf(x);
+               /* x is subnormal, normalize it.  */
+               ix = asuint(x * 0x1p23f);
+               ix -= 23 << 23;
        }
-       m -= 127;  /* unbias exponent */
-       ix = (ix&0x007fffff)|0x00800000;
-       if (m&1)  /* odd m, double x to make it even */
-               ix += ix;
-       m >>= 1;  /* m = [m/2] */
 
-       /* generate sqrt(x) bit by bit */
-       ix += ix;
-       q = s = 0;       /* q = sqrt(x) */
-       r = 0x01000000;  /* r = moving bit from right to left */
+       /* x = 4^e m; with int e and m in [1, 4).  */
+       even = ix & 0x00800000;
+       m1 = (ix << 8) | 0x80000000;
+       m0 = (ix << 7) & 0x7fffffff;
+       m = even ? m0 : m1;
 
-       while (r != 0) {
-               t = s + r;
-               if (t <= ix) {
-                       s = t+r;
-                       ix -= t;
-                       q += r;
-               }
-               ix += ix;
-               r >>= 1;
-       }
+       /* 2^e is the exponent part of the return value.  */
+       ey = ix >> 1;
+       ey += 0x3f800000 >> 1;
+       ey &= 0x7f800000;
+
+       /* compute r ~ 1/sqrt(m), s ~ sqrt(m) with 2 goldschmidt iterations.  */
+       static const uint32_t three = 0xc0000000;
+       uint32_t r, s, d, u, i;
+       i = (ix >> 17) % 128;
+       r = (uint32_t)__rsqrt_tab[i] << 16;
+       /* |r*sqrt(m) - 1| < 0x1p-8 */
+       s = mul32(m, r);
+       /* |s/sqrt(m) - 1| < 0x1p-8 */
+       d = mul32(s, r);
+       u = three - d;
+       r = mul32(r, u) << 1;
+       /* |r*sqrt(m) - 1| < 0x1.7bp-16 */
+       s = mul32(s, u) << 1;
+       /* |s/sqrt(m) - 1| < 0x1.7bp-16 */
+       d = mul32(s, r);
+       u = three - d;
+       s = mul32(s, u);
+       /* -0x1.03p-28 < s/sqrt(m) - 1 < 0x1.fp-31 */
+       s = (s - 1)>>6;
+       /* s < sqrt(m) < s + 0x1.08p-23 */
 
-       /* use floating add to find out rounding direction */
-       if (ix != 0) {
-               z = 1.0f - tiny; /* raise inexact flag */
-               if (z >= 1.0f) {
-                       z = 1.0f + tiny;
-                       if (z > 1.0f)
-                               q += 2;
-                       else
-                               q += q & 1;
-               }
+       /* compute nearest rounded result.  */
+       uint32_t d0, d1, d2;
+       float y, t;
+       d0 = (m << 16) - s*s;
+       d1 = s - d0;
+       d2 = d1 + s + 1;
+       s += d1 >> 31;
+       s &= 0x007fffff;
+       s |= ey;
+       y = asfloat(s);
+       if (FENV_SUPPORT) {
+               /* handle rounding and inexact exception. */
+               uint32_t tiny = predict_false(d2==0) ? 0 : 0x01000000;
+               tiny |= (d1^d2) & 0x80000000;
+               t = asfloat(tiny);
+               y = eval_as_float(y + t);
        }
-       ix = (q>>1) + 0x3f000000;
-       SET_FLOAT_WORD(z, ix + ((uint32_t)m << 23));
-       return z;
+       return y;
 }
index 83a8f80c9984dc7b02e2de6d73f87ed58b566b8b..1b9f19c7d46b9dc921f6c952371e060df8665d54 100644 (file)
@@ -1,7 +1,259 @@
+#include <stdint.h>
 #include <math.h>
+#include <float.h>
+#include "libm.h"
 
+#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
 long double sqrtl(long double x)
 {
-       /* FIXME: implement in C, this is for LDBL_MANT_DIG == 64 only */
        return sqrt(x);
 }
+#elif (LDBL_MANT_DIG == 113 || LDBL_MANT_DIG == 64) && LDBL_MAX_EXP == 16384
+#include "sqrt_data.h"
+
+#define FENV_SUPPORT 1
+
+typedef struct {
+       uint64_t hi;
+       uint64_t lo;
+} u128;
+
+/* top: 16 bit sign+exponent, x: significand.  */
+static inline long double mkldbl(uint64_t top, u128 x)
+{
+       union ldshape u;
+#if LDBL_MANT_DIG == 113
+       u.i2.hi = x.hi;
+       u.i2.lo = x.lo;
+       u.i2.hi &= 0x0000ffffffffffff;
+       u.i2.hi |= top << 48;
+#elif LDBL_MANT_DIG == 64
+       u.i.se = top;
+       u.i.m = x.lo;
+       /* force the top bit on non-zero (and non-subnormal) results.  */
+       if (top & 0x7fff)
+               u.i.m |= 0x8000000000000000;
+#endif
+       return u.f;
+}
+
+/* return: top 16 bit is sign+exp and following bits are the significand.  */
+static inline u128 asu128(long double x)
+{
+       union ldshape u = {.f=x};
+       u128 r;
+#if LDBL_MANT_DIG == 113
+       r.hi = u.i2.hi;
+       r.lo = u.i2.lo;
+#elif LDBL_MANT_DIG == 64
+       r.lo = u.i.m<<49;
+       /* ignore the top bit: pseudo numbers are not handled. */
+       r.hi = u.i.m>>15;
+       r.hi &= 0x0000ffffffffffff;
+       r.hi |= (uint64_t)u.i.se << 48;
+#endif
+       return r;
+}
+
+/* returns a*b*2^-32 - e, with error 0 <= e < 1.  */
+static inline uint32_t mul32(uint32_t a, uint32_t b)
+{
+       return (uint64_t)a*b >> 32;
+}
+
+/* returns a*b*2^-64 - e, with error 0 <= e < 3.  */
+static inline uint64_t mul64(uint64_t a, uint64_t b)
+{
+       uint64_t ahi = a>>32;
+       uint64_t alo = a&0xffffffff;
+       uint64_t bhi = b>>32;
+       uint64_t blo = b&0xffffffff;
+       return ahi*bhi + (ahi*blo >> 32) + (alo*bhi >> 32);
+}
+
+static inline u128 add64(u128 a, uint64_t b)
+{
+       u128 r;
+       r.lo = a.lo + b;
+       r.hi = a.hi;
+       if (r.lo < a.lo)
+               r.hi++;
+       return r;
+}
+
+static inline u128 add128(u128 a, u128 b)
+{
+       u128 r;
+       r.lo = a.lo + b.lo;
+       r.hi = a.hi + b.hi;
+       if (r.lo < a.lo)
+               r.hi++;
+       return r;
+}
+
+static inline u128 sub64(u128 a, uint64_t b)
+{
+       u128 r;
+       r.lo = a.lo - b;
+       r.hi = a.hi;
+       if (a.lo < b)
+               r.hi--;
+       return r;
+}
+
+static inline u128 sub128(u128 a, u128 b)
+{
+       u128 r;
+       r.lo = a.lo - b.lo;
+       r.hi = a.hi - b.hi;
+       if (a.lo < b.lo)
+               r.hi--;
+       return r;
+}
+
+/* a<<n, 0 <= n <= 127 */
+static inline u128 lsh(u128 a, int n)
+{
+       if (n == 0)
+               return a;
+       if (n >= 64) {
+               a.hi = a.lo<<(n-64);
+               a.lo = 0;
+       } else {
+               a.hi = (a.hi<<n) | (a.lo>>(64-n));
+               a.lo = a.lo<<n;
+       }
+       return a;
+}
+
+/* a>>n, 0 <= n <= 127 */
+static inline u128 rsh(u128 a, int n)
+{
+       if (n == 0)
+               return a;
+       if (n >= 64) {
+               a.lo = a.hi>>(n-64);
+               a.hi = 0;
+       } else {
+               a.lo = (a.lo>>n) | (a.hi<<(64-n));
+               a.hi = a.hi>>n;
+       }
+       return a;
+}
+
+/* returns a*b exactly.  */
+static inline u128 mul64_128(uint64_t a, uint64_t b)
+{
+       u128 r;
+       uint64_t ahi = a>>32;
+       uint64_t alo = a&0xffffffff;
+       uint64_t bhi = b>>32;
+       uint64_t blo = b&0xffffffff;
+       uint64_t lo1 = ((ahi*blo)&0xffffffff) + ((alo*bhi)&0xffffffff) + (alo*blo>>32);
+       uint64_t lo2 = (alo*blo)&0xffffffff;
+       r.hi = ahi*bhi + (ahi*blo>>32) + (alo*bhi>>32) + (lo1>>32);
+       r.lo = (lo1<<32) + lo2;
+       return r;
+}
+
+/* returns a*b*2^-128 - e, with error 0 <= e < 7.  */
+static inline u128 mul128(u128 a, u128 b)
+{
+       u128 hi = mul64_128(a.hi, b.hi);
+       uint64_t m1 = mul64(a.hi, b.lo);
+       uint64_t m2 = mul64(a.lo, b.hi);
+       return add64(add64(hi, m1), m2);
+}
+
+/* returns a*b % 2^128.  */
+static inline u128 mul128_tail(u128 a, u128 b)
+{
+       u128 lo = mul64_128(a.lo, b.lo);
+       lo.hi += a.hi*b.lo + a.lo*b.hi;
+       return lo;
+}
+
+
+/* see sqrt.c for detailed comments.  */
+
+long double sqrtl(long double x)
+{
+       u128 ix, ml;
+       uint64_t top;
+
+       ix = asu128(x);
+       top = ix.hi >> 48;
+       if (predict_false(top - 0x0001 >= 0x7fff - 0x0001)) {
+               /* x < 0x1p-16382 or inf or nan.  */
+               if (2*ix.hi == 0 && ix.lo == 0)
+                       return x;
+               if (ix.hi == 0x7fff000000000000 && ix.lo == 0)
+                       return x;
+               if (top >= 0x7fff)
+                       return __math_invalidl(x);
+               /* x is subnormal, normalize it.  */
+               ix = asu128(x * 0x1p112);
+               top = ix.hi >> 48;
+               top -= 112;
+       }
+
+       /* x = 4^e m; with int e and m in [1, 4) */
+       int even = top & 1;
+       ml = lsh(ix, 15);
+       ml.hi |= 0x8000000000000000;
+       if (even) ml = rsh(ml, 1);
+       top = (top + 0x3fff) >> 1;
+
+       /* r ~ 1/sqrt(m) */
+       static const uint64_t three = 0xc0000000;
+       uint64_t r, s, d, u, i;
+       i = (ix.hi >> 42) % 128;
+       r = (uint32_t)__rsqrt_tab[i] << 16;
+       /* |r sqrt(m) - 1| < 0x1p-8 */
+       s = mul32(ml.hi>>32, r);
+       d = mul32(s, r);
+       u = three - d;
+       r = mul32(u, r) << 1;
+       /* |r sqrt(m) - 1| < 0x1.7bp-16, switch to 64bit */
+       r = r<<32;
+       s = mul64(ml.hi, r);
+       d = mul64(s, r);
+       u = (three<<32) - d;
+       r = mul64(u, r) << 1;
+       /* |r sqrt(m) - 1| < 0x1.a5p-31 */
+       s = mul64(u, s) << 1;
+       d = mul64(s, r);
+       u = (three<<32) - d;
+       r = mul64(u, r) << 1;
+       /* |r sqrt(m) - 1| < 0x1.c001p-59, switch to 128bit */
+
+       static const u128 threel = {.hi=three<<32, .lo=0};
+       u128 rl, sl, dl, ul;
+       rl.hi = r;
+       rl.lo = 0;
+       sl = mul128(ml, rl);
+       dl = mul128(sl, rl);
+       ul = sub128(threel, dl);
+       sl = mul128(ul, sl); /* repr: 3.125 */
+       /* -0x1p-116 < s - sqrt(m) < 0x3.8001p-125 */
+       sl = rsh(sub64(sl, 4), 125-(LDBL_MANT_DIG-1));
+       /* s < sqrt(m) < s + 1 ULP + tiny */
+
+       long double y;
+       u128 d2, d1, d0;
+       d0 = sub128(lsh(ml, 2*(LDBL_MANT_DIG-1)-126), mul128_tail(sl,sl));
+       d1 = sub128(sl, d0);
+       d2 = add128(add64(sl, 1), d1);
+       sl = add64(sl, d1.hi >> 63);
+       y = mkldbl(top, sl);
+       if (FENV_SUPPORT) {
+               /* handle rounding modes and inexact exception.  */
+               top = predict_false((d2.hi|d2.lo)==0) ? 0 : 1;
+               top |= ((d1.hi^d2.hi)&0x8000000000000000) >> 48;
+               y += mkldbl(top, (u128){0});
+       }
+       return y;
+}
+#else
+#error unsupported long double format
+#endif
index 8947751147a209f61222d68893a2030bdcfe557a..492828119aeaa8583ed7dd72ab67f89507e8aa9c 100644 (file)
@@ -4,6 +4,7 @@
 #include <time.h>
 #include <sys/time.h>
 #include <stddef.h>
+#include <stdint.h>
 #include <string.h>
 #include "syscall.h"
 
@@ -28,6 +29,12 @@ struct ioctl_compat_map {
  * number producing macros; only size of result is meaningful. */
 #define new_misaligned(n) struct { int i; time_t t; char c[(n)-4]; }
 
+struct v4l2_event {
+       uint32_t a;
+       uint64_t b[8];
+       uint32_t c[2], ts[2], d[9];
+};
+
 static const struct ioctl_compat_map compat_map[] = {
        { SIOCGSTAMP, SIOCGSTAMP_OLD, 8, R, 0, OFFS(0, 4) },
        { SIOCGSTAMPNS, SIOCGSTAMPNS_OLD, 8, R, 0, OFFS(0, 4) },
@@ -49,13 +56,14 @@ static const struct ioctl_compat_map compat_map[] = {
        { 0, 0, 8, WR, 1, OFFS(0,4) }, /* snd_pcm_mmap_control */
 
        /* VIDIOC_QUERYBUF, VIDIOC_QBUF, VIDIOC_DQBUF, VIDIOC_PREPARE_BUF */
-       { _IOWR('V',  9, new_misaligned(72)), _IOWR('V',  9, char[72]), 72, WR, 0, OFFS(20) },
-       { _IOWR('V', 15, new_misaligned(72)), _IOWR('V', 15, char[72]), 72, WR, 0, OFFS(20) },
-       { _IOWR('V', 17, new_misaligned(72)), _IOWR('V', 17, char[72]), 72, WR, 0, OFFS(20) },
-       { _IOWR('V', 93, new_misaligned(72)), _IOWR('V', 93, char[72]), 72, WR, 0, OFFS(20) },
+       { _IOWR('V',  9, new_misaligned(68)), _IOWR('V',  9, char[68]), 68, WR, 1, OFFS(20, 24) },
+       { _IOWR('V', 15, new_misaligned(68)), _IOWR('V', 15, char[68]), 68, WR, 1, OFFS(20, 24) },
+       { _IOWR('V', 17, new_misaligned(68)), _IOWR('V', 17, char[68]), 68, WR, 1, OFFS(20, 24) },
+       { _IOWR('V', 93, new_misaligned(68)), _IOWR('V', 93, char[68]), 68, WR, 1, OFFS(20, 24) },
 
        /* VIDIOC_DQEVENT */
-       { _IOR('V', 89, new_misaligned(96)), _IOR('V', 89, char[96]), 96, R, 0, OFFS(76,80) },
+       { _IOR('V', 89, new_misaligned(120)), _IOR('V', 89, struct v4l2_event), sizeof(struct v4l2_event),
+         R, 0, OFFS(offsetof(struct v4l2_event, ts[0]), offsetof(struct v4l2_event, ts[1])) },
 
        /* VIDIOC_OMAP3ISP_STAT_REQ */
        { _IOWR('V', 192+6, char[32]), _IOWR('V', 192+6, char[24]), 22, WR, 0, OFFS(0,4) },
index d2708e59da426b8d7210cd540f6a786e11c3e6f2..db8b74dc8dbbcce1b77885bcc446d603db22f284 100644 (file)
 #include <stdlib.h>
 #include <limits.h>
-#include <sys/stat.h>
-#include <fcntl.h>
 #include <errno.h>
 #include <unistd.h>
 #include <string.h>
-#include "syscall.h"
+
+static size_t slash_len(const char *s)
+{
+       const char *s0 = s;
+       while (*s == '/') s++;
+       return s-s0;
+}
 
 char *realpath(const char *restrict filename, char *restrict resolved)
 {
-       int fd;
-       ssize_t r;
-       struct stat st1, st2;
-       char buf[15+3*sizeof(int)];
-       char tmp[PATH_MAX];
+       char stack[PATH_MAX+1];
+       char output[PATH_MAX];
+       size_t p, q, l, l0, cnt=0, nup=0;
+       int check_dir=0;
 
        if (!filename) {
                errno = EINVAL;
                return 0;
        }
+       l = strnlen(filename, sizeof stack);
+       if (!l) {
+               errno = ENOENT;
+               return 0;
+       }
+       if (l >= PATH_MAX) goto toolong;
+       p = sizeof stack - l - 1;
+       q = 0;
+       memcpy(stack+p, filename, l+1);
+
+       /* Main loop. Each iteration pops the next part from stack of
+        * remaining path components and consumes any slashes that follow.
+        * If not a link, it's moved to output; if a link, contents are
+        * pushed to the stack. */
+restart:
+       for (; ; p+=slash_len(stack+p)) {
+               /* If stack starts with /, the whole component is / or //
+                * and the output state must be reset. */
+               if (stack[p] == '/') {
+                       check_dir=0;
+                       nup=0;
+                       q=0;
+                       output[q++] = '/';
+                       p++;
+                       /* Initial // is special. */
+                       if (stack[p] == '/' && stack[p+1] != '/')
+                               output[q++] = '/';
+                       continue;
+               }
+
+               char *z = __strchrnul(stack+p, '/');
+               l0 = l = z-(stack+p);
 
-       fd = sys_open(filename, O_PATH|O_NONBLOCK|O_CLOEXEC);
-       if (fd < 0) return 0;
-       __procfdname(buf, fd);
+               if (!l && !check_dir) break;
 
-       r = readlink(buf, tmp, sizeof tmp - 1);
-       if (r < 0) goto err;
-       tmp[r] = 0;
+               /* Skip any . component but preserve check_dir status. */
+               if (l==1 && stack[p]=='.') {
+                       p += l;
+                       continue;
+               }
 
-       fstat(fd, &st1);
-       r = stat(tmp, &st2);
-       if (r<0 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) {
-               if (!r) errno = ELOOP;
-               goto err;
+               /* Copy next component onto output at least temporarily, to
+                * call readlink, but wait to advance output position until
+                * determining it's not a link. */
+               if (q && output[q-1] != '/') {
+                       if (!p) goto toolong;
+                       stack[--p] = '/';
+                       l++;
+               }
+               if (q+l >= PATH_MAX) goto toolong;
+               memcpy(output+q, stack+p, l);
+               output[q+l] = 0;
+               p += l;
+
+               int up = 0;
+               if (l0==2 && stack[p-2]=='.' && stack[p-1]=='.') {
+                       up = 1;
+                       /* Any non-.. path components we could cancel start
+                        * after nup repetitions of the 3-byte string "../";
+                        * if there are none, accumulate .. components to
+                        * later apply to cwd, if needed. */
+                       if (q <= 3*nup) {
+                               nup++;
+                               q += l;
+                               continue;
+                       }
+                       /* When previous components are already known to be
+                        * directories, processing .. can skip readlink. */
+                       if (!check_dir) goto skip_readlink;
+               }
+               ssize_t k = readlink(output, stack, p);
+               if (k==p) goto toolong;
+               if (!k) {
+                       errno = ENOENT;
+                       return 0;
+               }
+               if (k<0) {
+                       if (errno != EINVAL) return 0;
+skip_readlink:
+                       check_dir = 0;
+                       if (up) {
+                               while(q && output[q-1]!='/') q--;
+                               if (q>1 && (q>2 || output[0]!='/')) q--;
+                               continue;
+                       }
+                       if (l0) q += l;
+                       check_dir = stack[p];
+                       continue;
+               }
+               if (++cnt == SYMLOOP_MAX) {
+                       errno = ELOOP;
+                       return 0;
+               }
+
+               /* If link contents end in /, strip any slashes already on
+                * stack to avoid /->// or //->/// or spurious toolong. */
+               if (stack[k-1]=='/') while (stack[p]=='/') p++;
+               p -= k;
+               memmove(stack+p, stack, k);
+
+               /* Skip the stack advancement in case we have a new
+                * absolute base path. */
+               goto restart;
        }
 
-       __syscall(SYS_close, fd);
-       return resolved ? strcpy(resolved, tmp) : strdup(tmp);
-err:
-       __syscall(SYS_close, fd);
+       output[q] = 0;
+
+       if (output[0] != '/') {
+               if (!getcwd(stack, sizeof stack)) return 0;
+               l = strlen(stack);
+               /* Cancel any initial .. components. */
+               p = 0;
+               while (nup--) {
+                       while(l>1 && stack[l-1]!='/') l--;
+                       if (l>1) l--;
+                       p += 2;
+                       if (p<q) p++;
+               }
+               if (q-p && stack[l-1]!='/') stack[l++] = '/';
+               if (l + (q-p) + 1 >= PATH_MAX) goto toolong;
+               memmove(output + l, output + p, q - p + 1);
+               memcpy(output, stack, l);
+               q = l + q-p;
+       }
+
+       if (resolved) return memcpy(resolved, output, q+1);
+       else return strdup(output);
+
+toolong:
+       errno = ENAMETOOLONG;
        return 0;
 }
index 7a66ab29756b4a179a8077d7b4f50598b639e9da..8340aee096413ea68cd4ef6b476d9c09203b4ae8 100644 (file)
@@ -6,25 +6,8 @@
 #define MIN(a, b) ((a)<(b) ? (a) : (b))
 #define FIX(x) do{ if ((x)>=SYSCALL_RLIM_INFINITY) (x)=RLIM_INFINITY; }while(0)
 
-static int __setrlimit(int resource, const struct rlimit *rlim)
-{
-       unsigned long k_rlim[2];
-       struct rlimit tmp;
-       if (SYSCALL_RLIM_INFINITY != RLIM_INFINITY) {
-               tmp = *rlim;
-               FIX(tmp.rlim_cur);
-               FIX(tmp.rlim_max);
-               rlim = &tmp;
-       }
-       int ret = __syscall(SYS_prlimit64, 0, resource, rlim, 0);
-       if (ret != -ENOSYS) return ret;
-       k_rlim[0] = MIN(rlim->rlim_cur, MIN(-1UL, SYSCALL_RLIM_INFINITY));
-       k_rlim[1] = MIN(rlim->rlim_max, MIN(-1UL, SYSCALL_RLIM_INFINITY));
-       return __syscall(SYS_setrlimit, resource, k_rlim);
-}
-
 struct ctx {
-       const struct rlimit *rlim;
+       unsigned long lim[2];
        int res;
        int err;
 };
@@ -33,12 +16,26 @@ static void do_setrlimit(void *p)
 {
        struct ctx *c = p;
        if (c->err>0) return;
-       c->err = -__setrlimit(c->res, c->rlim);
+       c->err = -__syscall(SYS_setrlimit, c->res, c->lim);
 }
 
 int setrlimit(int resource, const struct rlimit *rlim)
 {
-       struct ctx c = { .res = resource, .rlim = rlim, .err = -1 };
+       struct rlimit tmp;
+       if (SYSCALL_RLIM_INFINITY != RLIM_INFINITY) {
+               tmp = *rlim;
+               FIX(tmp.rlim_cur);
+               FIX(tmp.rlim_max);
+               rlim = &tmp;
+       }
+       int ret = __syscall(SYS_prlimit64, 0, resource, rlim, 0);
+       if (ret != -ENOSYS) return __syscall_ret(ret);
+
+       struct ctx c = {
+               .lim[0] = MIN(rlim->rlim_cur, MIN(-1UL, SYSCALL_RLIM_INFINITY)),
+               .lim[1] = MIN(rlim->rlim_max, MIN(-1UL, SYSCALL_RLIM_INFINITY)),
+               .res = resource, .err = -1
+       };
        __synccall(do_setrlimit, &c);
        if (c.err) {
                if (c.err>0) errno = c.err;
index bed11b53e607660743bb382e9e9880a01852ce60..b802acd9e21c0e1172c6f4f45f498ec7bc6c9982 100644 (file)
@@ -12,6 +12,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include "lock.h"
+#include "fork_impl.h"
 
 static volatile int lock[1];
 static char log_ident[32];
@@ -19,6 +20,7 @@ static int log_opt;
 static int log_facility = LOG_USER;
 static int log_mask = 0xff;
 static int log_fd = -1;
+volatile int *const __syslog_lockptr = lock;
 
 int setlogmask(int maskpri)
 {
index b6163c34677434cb5e88854613ca7dae9191fba5..36e816aa27117a8d0fc3796094fda5569802df6a 100644 (file)
@@ -1,6 +1,6 @@
 #include <sys/utsname.h>
-#include "syscall.h"
 #ifdef __wasilibc_unmodified_upstream // Implement uname with placeholders
+#include "syscall.h"
 #else
 #include <string.h>
 #endif
index 676932b5dcaa0d93da7fabded9c006dd57e19d90..95e25e708dd9d93b2617a72ca5eb428a40138e18 100644 (file)
@@ -1,41 +1,33 @@
 #include <wchar.h>
+#include <limits.h>
+#include <string.h>
 
 size_t wcsnrtombs(char *restrict dst, const wchar_t **restrict wcs, size_t wn, size_t n, mbstate_t *restrict st)
 {
-       size_t l, cnt=0, n2;
-       char *s, buf[256];
        const wchar_t *ws = *wcs;
-       const wchar_t *tmp_ws;
-
-       if (!dst) s = buf, n = sizeof buf;
-       else s = dst;
-
-       while ( ws && n && ( (n2=wn)>=n || n2>32 ) ) {
-               if (n2>=n) n2=n;
-               tmp_ws = ws;
-               l = wcsrtombs(s, &ws, n2, 0);
-               if (!(l+1)) {
-                       cnt = l;
-                       n = 0;
+       size_t cnt = 0;
+       if (!dst) n=0;
+       while (ws && wn) {
+               char tmp[MB_LEN_MAX];
+               size_t l = wcrtomb(n<MB_LEN_MAX ? tmp : dst, *ws, 0);
+               if (l==-1) {
+                       cnt = -1;
                        break;
                }
-               if (s != buf) {
-                       s += l;
+               if (dst) {
+                       if (n<MB_LEN_MAX) {
+                               if (l>n) break;
+                               memcpy(dst, tmp, l);
+                       }
+                       dst += l;
                        n -= l;
                }
-               wn = ws ? wn - (ws - tmp_ws) : 0;
-               cnt += l;
-       }
-       if (ws) while (n && wn) {
-               l = wcrtomb(s, *ws, 0);
-               if ((l+1)<=1) {
-                       if (!l) ws = 0;
-                       else cnt = l;
+               if (!*ws) {
+                       ws = 0;
                        break;
                }
-               ws++; wn--;
-               /* safe - this loop runs fewer than sizeof(buf) times */
-               s+=l; n-=l;
+               ws++;
+               wn--;
                cnt += l;
        }
        if (dst) *wcs = ws;
index 4f700ceaf1674d58ed57b1e1de94a3f6d88b4ce7..638f77180314a625e90507a7890cfafa94e7f1b6 100644 (file)
@@ -1,9 +1,11 @@
 #include <netdb.h>
+#include "pthread_impl.h"
 
 #undef h_errno
 int h_errno;
 
 int *__h_errno_location(void)
 {
-       return &h_errno;
+       if (!__pthread_self()->stack) return &h_errno;
+       return &__pthread_self()->h_errno_val;
 }
index 65f25ff3f45b6b0ce07ec61e8a8d54280b96817f..87f8cff4fd47ed50813c5b85191b59b645508377 100644 (file)
@@ -4,5 +4,5 @@
 
 void herror(const char *msg)
 {
-       fprintf(stderr, "%s%s%s", msg?msg:"", msg?": ":"", hstrerror(h_errno));
+       fprintf(stderr, "%s%s%s\n", msg?msg:"", msg?": ":"", hstrerror(h_errno));
 }
index aae0d95a041504b60cd1827278ba4ee1a3bee4c0..aa558c197abe813865ba28c1228be272bae62924 100644 (file)
@@ -50,7 +50,7 @@ static int name_from_hosts(struct address buf[static MAXADDRS], char canon[stati
 {
        char line[512];
        size_t l = strlen(name);
-       int cnt = 0, badfam = 0;
+       int cnt = 0, badfam = 0, have_canon = 0;
        unsigned char _buf[1032];
        FILE _f, *f = __fopen_rb_ca("/etc/hosts", &_f, _buf, sizeof _buf);
        if (!f) switch (errno) {
@@ -80,14 +80,19 @@ static int name_from_hosts(struct address buf[static MAXADDRS], char canon[stati
                        continue;
                default:
                        badfam = EAI_NONAME;
-                       continue;
+                       break;
                }
 
+               if (have_canon) continue;
+
                /* Extract first name as canonical name */
                for (; *p && isspace(*p); p++);
                for (z=p; *z && !isspace(*z); z++);
                *z = 0;
-               if (is_valid_hostname(p)) memcpy(canon, p, z-p+1);
+               if (is_valid_hostname(p)) {
+                       have_canon = 1;
+                       memcpy(canon, p, z-p+1);
+               }
        }
        __fclose_ca(f);
        return cnt ? cnt : badfam;
index 2f4da2e2e7a3214fb56b86ebedfaefdb67e05e1c..506dc231266d9e0795140782c05b8c91368f7ecb 100644 (file)
@@ -1,3 +1,4 @@
+#define _BSD_SOURCE
 #include <resolv.h>
 #include <netdb.h>
 
@@ -6,7 +7,20 @@ int res_query(const char *name, int class, int type, unsigned char *dest, int le
        unsigned char q[280];
        int ql = __res_mkquery(0, name, class, type, 0, 0, 0, q, sizeof q);
        if (ql < 0) return ql;
-       return __res_send(q, ql, dest, len);
+       int r = __res_send(q, ql, dest, len);
+       if (r<12) {
+               h_errno = TRY_AGAIN;
+               return -1;
+       }
+       if ((dest[3] & 15) == 3) {
+               h_errno = HOST_NOT_FOUND;
+               return -1;
+       }
+       if ((dest[3] & 15) == 0 && !dest[6] && !dest[7]) {
+               h_errno = NO_DATA;
+               return -1;
+       }
+       return r;
 }
 
 weak_alias(res_query, res_search);
index 43e518245f8e6bfdafdbdb2ff5aec92a247798e4..301824cec5ac1e973492aa3d252416faa6eb18ac 100644 (file)
@@ -31,7 +31,8 @@ int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups)
        if (resp[INITGRFOUND]) {
                nscdbuf = calloc(resp[INITGRNGRPS], sizeof(uint32_t));
                if (!nscdbuf) goto cleanup;
-               if (!fread(nscdbuf, sizeof(*nscdbuf)*resp[INITGRNGRPS], 1, f)) {
+               size_t nbytes = sizeof(*nscdbuf)*resp[INITGRNGRPS];
+               if (nbytes && !fread(nscdbuf, nbytes, 1, f)) {
                        if (!ferror(f)) errno = EIO;
                        goto cleanup;
                }
index 633a17f6902fcf9e287c0ecbc921304513bf23a9..3326f09f0db8ad1fdaddb68639850522bf326a2e 100644 (file)
@@ -1,6 +1,7 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include "lock.h"
+#include "fork_impl.h"
 
 /*
 this code uses the same lagged fibonacci generator as the
@@ -22,7 +23,10 @@ static int n = 31;
 static int i = 3;
 static int j = 0;
 static uint32_t *x = init+1;
+#ifdef __wasilibc_unmodified_upstream
 static volatile int lock[1];
+volatile int *const __random_lockptr = lock;
+#endif
 
 static uint32_t lcg31(uint32_t x) {
        return (1103515245*x + 12345) & 0x7fffffff;
diff --git a/libc-top-half/musl/src/process/_Fork.c b/libc-top-half/musl/src/process/_Fork.c
new file mode 100644 (file)
index 0000000..da06386
--- /dev/null
@@ -0,0 +1,38 @@
+#include <unistd.h>
+#include <signal.h>
+#include "syscall.h"
+#include "libc.h"
+#include "lock.h"
+#include "pthread_impl.h"
+#include "aio_impl.h"
+
+static void dummy(int x) { }
+weak_alias(dummy, __aio_atfork);
+
+pid_t _Fork(void)
+{
+       pid_t ret;
+       sigset_t set;
+       __block_all_sigs(&set);
+       __aio_atfork(-1);
+       LOCK(__abort_lock);
+#ifdef SYS_fork
+       ret = __syscall(SYS_fork);
+#else
+       ret = __syscall(SYS_clone, SIGCHLD, 0);
+#endif
+       if (!ret) {
+               pthread_t self = __pthread_self();
+               self->tid = __syscall(SYS_gettid);
+               self->robust_list.off = 0;
+               self->robust_list.pending = 0;
+               self->next = self->prev = self;
+               __thread_list_lock = 0;
+               libc.threads_minus_1 = 0;
+               if (libc.need_locks) libc.need_locks = -1;
+       }
+       UNLOCK(__abort_lock);
+       __aio_atfork(!ret);
+       __restore_sigs(&set);
+       return __syscall_ret(ret);
+}
index 7e984ff8c3444efc99a3a382394b539c2e8e0a3a..54bc289202955a8f47a0ed2f17d8b3722500bc81 100644 (file)
@@ -1,38 +1,86 @@
 #include <unistd.h>
-#include <string.h>
-#include <signal.h>
-#include "syscall.h"
+#include <errno.h>
 #include "libc.h"
+#include "lock.h"
 #include "pthread_impl.h"
+#include "fork_impl.h"
 
-static void dummy(int x)
-{
-}
+static volatile int *const dummy_lockptr = 0;
+
+weak_alias(dummy_lockptr, __at_quick_exit_lockptr);
+weak_alias(dummy_lockptr, __atexit_lockptr);
+weak_alias(dummy_lockptr, __dlerror_lockptr);
+weak_alias(dummy_lockptr, __gettext_lockptr);
+weak_alias(dummy_lockptr, __locale_lockptr);
+weak_alias(dummy_lockptr, __random_lockptr);
+weak_alias(dummy_lockptr, __sem_open_lockptr);
+weak_alias(dummy_lockptr, __stdio_ofl_lockptr);
+weak_alias(dummy_lockptr, __syslog_lockptr);
+weak_alias(dummy_lockptr, __timezone_lockptr);
+weak_alias(dummy_lockptr, __bump_lockptr);
+
+weak_alias(dummy_lockptr, __vmlock_lockptr);
 
+static volatile int *const *const atfork_locks[] = {
+       &__at_quick_exit_lockptr,
+       &__atexit_lockptr,
+       &__dlerror_lockptr,
+       &__gettext_lockptr,
+       &__locale_lockptr,
+       &__random_lockptr,
+       &__sem_open_lockptr,
+       &__stdio_ofl_lockptr,
+       &__syslog_lockptr,
+       &__timezone_lockptr,
+       &__bump_lockptr,
+};
+
+static void dummy(int x) { }
 weak_alias(dummy, __fork_handler);
+weak_alias(dummy, __malloc_atfork);
+weak_alias(dummy, __ldso_atfork);
+
+static void dummy_0(void) { }
+weak_alias(dummy_0, __tl_lock);
+weak_alias(dummy_0, __tl_unlock);
 
 pid_t fork(void)
 {
-       pid_t ret;
        sigset_t set;
        __fork_handler(-1);
-       __block_all_sigs(&set);
-#ifdef SYS_fork
-       ret = __syscall(SYS_fork);
-#else
-       ret = __syscall(SYS_clone, SIGCHLD, 0);
-#endif
-       if (!ret) {
-               pthread_t self = __pthread_self();
-               self->tid = __syscall(SYS_gettid);
-               self->robust_list.off = 0;
-               self->robust_list.pending = 0;
-               self->next = self->prev = self;
-               __thread_list_lock = 0;
-               libc.threads_minus_1 = 0;
-               if (libc.need_locks) libc.need_locks = -1;
+       __block_app_sigs(&set);
+       int need_locks = libc.need_locks > 0;
+       if (need_locks) {
+               __ldso_atfork(-1);
+               __inhibit_ptc();
+               for (int i=0; i<sizeof atfork_locks/sizeof *atfork_locks; i++)
+                       if (*atfork_locks[i]) LOCK(*atfork_locks[i]);
+               __malloc_atfork(-1);
+               __tl_lock();
+       }
+       pthread_t self=__pthread_self(), next=self->next;
+       pid_t ret = _Fork();
+       int errno_save = errno;
+       if (need_locks) {
+               if (!ret) {
+                       for (pthread_t td=next; td!=self; td=td->next)
+                               td->tid = -1;
+                       if (__vmlock_lockptr) {
+                               __vmlock_lockptr[0] = 0;
+                               __vmlock_lockptr[1] = 0;
+                       }
+               }
+               __tl_unlock();
+               __malloc_atfork(!ret);
+               for (int i=0; i<sizeof atfork_locks/sizeof *atfork_locks; i++)
+                       if (*atfork_locks[i])
+                               if (ret) UNLOCK(*atfork_locks[i]);
+                               else **atfork_locks[i] = 0;
+               __release_ptc();
+               __ldso_atfork(!ret);
        }
        __restore_sigs(&set);
        __fork_handler(!ret);
-       return __syscall_ret(ret);
+       if (ret<0) errno = errno_save;
+       return ret;
 }
index 29652197c58cbff007a3251b89a699e69dbbb2f7..728551b367926610c2fda6824a13d215c76dbecf 100644 (file)
@@ -6,6 +6,7 @@
 #include <fcntl.h>
 #include <sys/wait.h>
 #include "syscall.h"
+#include "lock.h"
 #include "pthread_impl.h"
 #include "fdop.h"
 
@@ -170,9 +171,6 @@ int posix_spawn(pid_t *restrict res, const char *restrict path,
        int ec=0, cs;
        struct args args;
 
-       if (pipe2(args.p, O_CLOEXEC))
-               return errno;
-
        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
 
        args.path = path;
@@ -182,9 +180,20 @@ int posix_spawn(pid_t *restrict res, const char *restrict path,
        args.envp = envp;
        pthread_sigmask(SIG_BLOCK, SIGALL_SET, &args.oldmask);
 
+       /* The lock guards both against seeing a SIGABRT disposition change
+        * by abort and against leaking the pipe fd to fork-without-exec. */
+       LOCK(__abort_lock);
+
+       if (pipe2(args.p, O_CLOEXEC)) {
+               UNLOCK(__abort_lock);
+               ec = errno;
+               goto fail;
+       }
+
        pid = __clone(child, stack+sizeof stack,
                CLONE_VM|CLONE_VFORK|SIGCHLD, &args);
        close(args.p[1]);
+       UNLOCK(__abort_lock);
 
        if (pid > 0) {
                if (read(args.p[0], &ec, sizeof ec) != sizeof ec) ec = 0;
@@ -197,6 +206,7 @@ int posix_spawn(pid_t *restrict res, const char *restrict path,
 
        if (!ec && res) *res = pid;
 
+fail:
        pthread_sigmask(SIG_SETMASK, &args.oldmask, 0);
        pthread_setcancelstate(cs, 0);
 
index 7c4655fa968c874fb79962f35e0d32cc79edc226..0af9c50ee5c80c5b07e83c6fb4ef49f8eed7d6dc 100644 (file)
@@ -18,7 +18,6 @@ longjmp:
        ldp d12, d13, [x0,#144]
        ldp d14, d15, [x0,#160]
 
-       mov x0, x1
-       cbnz x1, 1f
-       mov x0, #1
-1:     br x30
+       cmp w1, 0
+       csinc w0, w1, wzr, ne
+       br x30
index 772d28ddb283e8ee983e75ec6b167ef0f80979d7..8188f06bcd7f01d9518881effd14dfcce59e0614 100644 (file)
@@ -6,15 +6,11 @@ _longjmp:
 longjmp:
        mov  4(%esp),%edx
        mov  8(%esp),%eax
-       test    %eax,%eax
-       jnz 1f
-       inc     %eax
-1:
+       cmp       $1,%eax
+       adc       $0, %al
        mov   (%edx),%ebx
        mov  4(%edx),%esi
        mov  8(%edx),%edi
        mov 12(%edx),%ebp
-       mov 16(%edx),%ecx
-       mov     %ecx,%esp
-       mov 20(%edx),%ecx
-       jmp *%ecx
+       mov 16(%edx),%esp
+       jmp *20(%edx)
index e175a4b9606bba41eccc8972c22244e533718f0a..1b2661c3e5a948a0d957ca84ebf17043b3993ed5 100644 (file)
@@ -5,18 +5,14 @@
 .type longjmp,@function
 _longjmp:
 longjmp:
-       mov %rsi,%rax           /* val will be longjmp return */
-       test %rax,%rax
-       jnz 1f
-       inc %rax                /* if val==0, val=1 per longjmp semantics */
-1:
+       xor %eax,%eax
+       cmp $1,%esi             /* CF = val ? 0 : 1 */
+       adc %esi,%eax           /* eax = val + !val */
        mov (%rdi),%rbx         /* rdi is the jmp_buf, restore regs from it */
        mov 8(%rdi),%rbp
        mov 16(%rdi),%r12
        mov 24(%rdi),%r13
        mov 32(%rdi),%r14
        mov 40(%rdi),%r15
-       mov 48(%rdi),%rdx       /* this ends up being the stack pointer */
-       mov %rdx,%rsp
-       mov 56(%rdi),%rdx       /* this is the instruction pointer */
-       jmp *%rdx               /* goto saved address without altering rsp */
+       mov 48(%rdi),%rsp
+       jmp *56(%rdi)           /* goto saved address without altering rsp */
index 98f58b8d6551e391f426fc53c81678a03ac89074..d95e4853558f73329037c9057d758e73bc9be8d9 100644 (file)
@@ -18,5 +18,5 @@ setjmp:
        mov %rdx,48(%rdi)
        mov (%rsp),%rdx         /* save return addr ptr for new rip */
        mov %rdx,56(%rdi)
-       xor %rax,%rax           /* always return 0 */
+       xor %eax,%eax           /* always return 0 */
        ret
index e175a4b9606bba41eccc8972c22244e533718f0a..1b2661c3e5a948a0d957ca84ebf17043b3993ed5 100644 (file)
@@ -5,18 +5,14 @@
 .type longjmp,@function
 _longjmp:
 longjmp:
-       mov %rsi,%rax           /* val will be longjmp return */
-       test %rax,%rax
-       jnz 1f
-       inc %rax                /* if val==0, val=1 per longjmp semantics */
-1:
+       xor %eax,%eax
+       cmp $1,%esi             /* CF = val ? 0 : 1 */
+       adc %esi,%eax           /* eax = val + !val */
        mov (%rdi),%rbx         /* rdi is the jmp_buf, restore regs from it */
        mov 8(%rdi),%rbp
        mov 16(%rdi),%r12
        mov 24(%rdi),%r13
        mov 32(%rdi),%r14
        mov 40(%rdi),%r15
-       mov 48(%rdi),%rdx       /* this ends up being the stack pointer */
-       mov %rdx,%rsp
-       mov 56(%rdi),%rdx       /* this is the instruction pointer */
-       jmp *%rdx               /* goto saved address without altering rsp */
+       mov 48(%rdi),%rsp
+       jmp *56(%rdi)           /* goto saved address without altering rsp */
index 98f58b8d6551e391f426fc53c81678a03ac89074..d95e4853558f73329037c9057d758e73bc9be8d9 100644 (file)
@@ -18,5 +18,5 @@ setjmp:
        mov %rdx,48(%rdi)
        mov (%rsp),%rdx         /* save return addr ptr for new rip */
        mov %rdx,56(%rdi)
-       xor %rax,%rax           /* always return 0 */
+       xor %eax,%eax           /* always return 0 */
        ret
index c109bea0cfe360ce4191a175c1e561c2d7fb6419..2203471b243d954a2e0568597b6fcb5e7ada15db 100644 (file)
@@ -7,12 +7,6 @@
 #include "lock.h"
 #include "ksigaction.h"
 
-static volatile int dummy_lock[1] = { 0 };
-
-extern hidden volatile int __abort_lock[1];
-
-weak_alias(dummy_lock, __abort_lock);
-
 static int unmask_done;
 static unsigned long handler_set[_NSIG/(8*sizeof(long))];
 
@@ -26,7 +20,6 @@ volatile int __eintr_valid_flag;
 int __libc_sigaction(int sig, const struct sigaction *restrict sa, struct sigaction *restrict old)
 {
        struct k_sigaction ksa, ksa_old;
-       unsigned long set[_NSIG/(8*sizeof(long))];
        if (sa) {
                if ((uintptr_t)sa->sa_handler > 1UL) {
                        a_or_l(handler_set+(sig-1)/(8*sizeof(long)),
@@ -50,24 +43,12 @@ int __libc_sigaction(int sig, const struct sigaction *restrict sa, struct sigact
                                a_store(&__eintr_valid_flag, 1);
                        }
                }
-               /* Changing the disposition of SIGABRT to anything but
-                * SIG_DFL requires a lock, so that it cannot be changed
-                * while abort is terminating the process after simply
-                * calling raise(SIGABRT) failed to do so. */
-               if (sa->sa_handler != SIG_DFL && sig == SIGABRT) {
-                       __block_all_sigs(&set);
-                       LOCK(__abort_lock);
-               }
                ksa.handler = sa->sa_handler;
                ksa.flags = sa->sa_flags | SA_RESTORER;
                ksa.restorer = (sa->sa_flags & SA_SIGINFO) ? __restore_rt : __restore;
                memcpy(&ksa.mask, &sa->sa_mask, _NSIG/8);
        }
        int r = __syscall(SYS_rt_sigaction, sig, sa?&ksa:0, old?&ksa_old:0, _NSIG/8);
-       if (sig == SIGABRT && sa && sa->sa_handler != SIG_DFL) {
-               UNLOCK(__abort_lock);
-               __restore_sigs(&set);
-       }
        if (old && !r) {
                old->sa_handler = ksa_old.handler;
                old->sa_flags = ksa_old.flags;
@@ -78,11 +59,26 @@ int __libc_sigaction(int sig, const struct sigaction *restrict sa, struct sigact
 
 int __sigaction(int sig, const struct sigaction *restrict sa, struct sigaction *restrict old)
 {
+       unsigned long set[_NSIG/(8*sizeof(long))];
+
        if (sig-32U < 3 || sig-1U >= _NSIG-1) {
                errno = EINVAL;
                return -1;
        }
-       return __libc_sigaction(sig, sa, old);
+
+       /* Doing anything with the disposition of SIGABRT requires a lock,
+        * so that it cannot be changed while abort is terminating the
+        * process and so any change made by abort can't be observed. */
+       if (sig == SIGABRT) {
+               __block_all_sigs(&set);
+               LOCK(__abort_lock);
+       }
+       int r = __libc_sigaction(sig, sa, old);
+       if (sig == SIGABRT) {
+               UNLOCK(__abort_lock);
+               __restore_sigs(&set);
+       }
+       return r;
 }
 
 weak_alias(__sigaction, sigaction);
index 21a678c78445f5b8491adfdbad6bbfe71c6b5017..0d7c91e6083ec11e578fd04ebcfba2dd84d93a00 100644 (file)
@@ -3,6 +3,7 @@
 #include <unistd.h>
 #endif
 #include "stdio_impl.h"
+#include "aio_impl.h"
 
 #if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
 static int dummy(int fd)
index f2d3215a9e7d7eec8f32351991f3ec8b4d270fc9..33a8aa50bcec1a6f9632b0d12cff37f33e208e7b 100644 (file)
@@ -1,8 +1,12 @@
 #include "stdio_impl.h"
 #include "lock.h"
+#include "fork_impl.h"
 
 static FILE *ofl_head;
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
 static volatile int ofl_lock[1];
+volatile int *const __stdio_ofl_lockptr = ofl_lock;
+#endif
 
 FILE **__ofl_lock()
 {
index 43a0207a725be2a04af3b3cc6390a214aaae0995..96657bc23114d0fb8662c904d9bc4391ccb16b0f 100644 (file)
@@ -96,7 +96,7 @@ static char *twoway_strstr(const unsigned char *h, const unsigned char *n)
        for (;;) {
                /* Update incremental end-of-haystack pointer */
                if (z-h < l) {
-                       /* Fast estimate for MIN(l,63) */
+                       /* Fast estimate for MAX(l,63) */
                        size_t grow = l | 63;
                        const unsigned char *z2 = memchr(z, 0, grow);
                        if (z2) {
diff --git a/libc-top-half/musl/src/termios/tcgetwinsize.c b/libc-top-half/musl/src/termios/tcgetwinsize.c
new file mode 100644 (file)
index 0000000..9b3a65a
--- /dev/null
@@ -0,0 +1,8 @@
+#include <termios.h>
+#include <sys/ioctl.h>
+#include "syscall.h"
+
+int tcgetwinsize(int fd, struct winsize *wsz)
+{
+       return syscall(SYS_ioctl, fd, TIOCGWINSZ, wsz);
+}
diff --git a/libc-top-half/musl/src/termios/tcsetwinsize.c b/libc-top-half/musl/src/termios/tcsetwinsize.c
new file mode 100644 (file)
index 0000000..e01d0e2
--- /dev/null
@@ -0,0 +1,8 @@
+#include <termios.h>
+#include <sys/ioctl.h>
+#include "syscall.h"
+
+int tcsetwinsize(int fd, const struct winsize *wsz)
+{
+       return syscall(SYS_ioctl, fd, TIOCSWINSZ, wsz);
+}
index c2c21dd5d6ccdbe6198f516199f8c9093d7988b0..aa6852beb66bb7ccdfedff36ec110d6498328a2a 100644 (file)
@@ -28,6 +28,7 @@ __set_thread_area:
        ret
 2:
        mov %ebx,%ecx
+       xor %eax,%eax
        xor %ebx,%ebx
        xor %edx,%edx
        mov %ebx,(%esp)
index 4aa5afdb2881c6ae3aa344784b83b619d76e5a6b..f12ff442548dd65e85410a2606bb2904f511b256 100644 (file)
@@ -70,7 +70,7 @@ int pthread_condattr_getpshared(const pthread_condattr_t *restrict a, int *restr
 
 int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *restrict a, int *restrict protocol)
 {
-       *protocol = PTHREAD_PRIO_NONE;
+       *protocol = a->__attr / 8U % 2;
        return 0;
 }
 int pthread_mutexattr_getpshared(const pthread_mutexattr_t *restrict a, int *restrict pshared)
index d15012406d6fd98b5e8f11029d319eea3eb29658..6b761455c47f0f8c8afde4e2d57768208efc06ba 100644 (file)
@@ -146,14 +146,18 @@ relock:
 
        if (oldstate == WAITING) goto done;
 
-       if (!node.next) a_inc(&m->_m_waiters);
+       if (!node.next && !(m->_m_type & 8))
+               a_inc(&m->_m_waiters);
 
        /* Unlock the barrier that's holding back the next waiter, and
         * either wake it or requeue it to the mutex. */
-       if (node.prev)
-               unlock_requeue(&node.prev->barrier, &m->_m_lock, m->_m_type & 128);
-       else
-               a_dec(&m->_m_waiters);
+       if (node.prev) {
+               int val = m->_m_lock;
+               if (val>0) a_cas(&m->_m_lock, val, val|0x80000000);
+               unlock_requeue(&node.prev->barrier, &m->_m_lock, m->_m_type & (8|128));
+       } else if (!(m->_m_type & 8)) {
+               a_dec(&m->_m_waiters);          
+       }
 
        /* Since a signal was consumed, cancellation is not permitted. */
        if (e == ECANCELED) e = 0;
index 10f1b7d8cd39605d42dfea19370c88b9183e6036..6f187ee89d3dd4b9fced7e0060ceb5641601614f 100644 (file)
@@ -69,12 +69,25 @@ _Noreturn void __pthread_exit(void *result)
 
        __pthread_tsd_run_dtors();
 
+       __block_app_sigs(&set);
+
+       /* 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) {
+               /* Since __unmapself bypasses the normal munmap code path,
+                * explicitly wait for vmlock holders first. This must be
+                * done before any locks are taken, to avoid lock ordering
+                * issues that could lead to deadlock. */
+               __vm_wait();
+       }
+
        /* 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.
         * Signals must be blocked since pthread_kill must be AS-safe. */
-       __block_app_sigs(&set);
        LOCK(self->killlock);
 
        /* The thread list lock must be AS-safe, and thus depends on
@@ -87,6 +100,7 @@ _Noreturn void __pthread_exit(void *result)
        if (self->next == self) {
                __tl_unlock();
                UNLOCK(self->killlock);
+               self->detach_state = state;
                __restore_sigs(&set);
                exit(0);
        }
@@ -125,10 +139,6 @@ _Noreturn void __pthread_exit(void *result)
        self->prev->next = self->next;
        self->prev = self->next = self;
 
-       /* 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 block even implementation-internal
                 * signals, since they will not have a stack in their last
@@ -140,16 +150,13 @@ _Noreturn void __pthread_exit(void *result)
                if (self->robust_list.off)
                        __syscall(SYS_set_robust_list, 0, 3*sizeof(long));
 
-               /* Since __unmapself bypasses the normal munmap code path,
-                * explicitly wait for vmlock holders first. */
-               __vm_wait();
-
                /* The following call unmaps the thread's stack mapping
                 * and then exits without touching the stack. */
                __unmapself(self->map_base, self->map_size);
        }
 
        /* Wake any joiner. */
+       a_store(&self->detach_state, DT_EXITED);
        __wake(&self->detach_state, 1, 1);
 
        /* After the kernel thread exits, its tid may be reused. Clear it
@@ -314,7 +321,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att
                new->detach_state = DT_JOINABLE;
        }
        new->robust_list.head = &new->robust_list.head;
-       new->CANARY = self->CANARY;
+       new->canary = self->canary;
        new->sysinfo = self->sysinfo;
 
        /* Setup argument structure for the new thread on its stack.
index 6d49e689892265e02884cd451d719ab2bed80361..8d1bf77b879212256111446c657209dd7a5cd73c 100644 (file)
@@ -1,6 +1,10 @@
-#include <pthread.h>
+#include "pthread_impl.h"
 
 int pthread_mutex_destroy(pthread_mutex_t *mutex)
 {
+       /* If the mutex being destroyed is process-shared and has nontrivial
+        * type (tracking ownership), it might be in the pending slot of a
+        * robust_list; wait for quiescence. */
+       if (mutex->_m_type > 128) __vm_wait();
        return 0;
 }
index 511cc32d8f0ad9df99d4193901dbb514160f928e..8b80c1ce9b14c1b039de327c9870dea08a3ca846 100644 (file)
@@ -1,24 +1,23 @@
 #include "pthread_impl.h"
 #include "syscall.h"
 
-static pthread_once_t check_pi_once;
-static int check_pi_result;
-
-static void check_pi()
-{
-       volatile int lk = 0;
-       check_pi_result = -__syscall(SYS_futex, &lk, FUTEX_LOCK_PI, 0, 0);
-}
+static volatile int check_pi_result = -1;
 
 int pthread_mutexattr_setprotocol(pthread_mutexattr_t *a, int protocol)
 {
+       int r;
        switch (protocol) {
        case PTHREAD_PRIO_NONE:
                a->__attr &= ~8;
                return 0;
        case PTHREAD_PRIO_INHERIT:
-               pthread_once(&check_pi_once, check_pi);
-               if (check_pi_result) return check_pi_result;
+               r = check_pi_result;
+               if (r < 0) {
+                       volatile int lk = 0;
+                       r = -__syscall(SYS_futex, &lk, FUTEX_LOCK_PI, 0, 0);
+                       a_store(&check_pi_result, r);
+               }
+               if (r) return r;
                a->__attr |= 8;
                return 0;
        case PTHREAD_PRIO_PROTECT:
index 04db92a626dbd0b05eac4bcd88363a6e31e54207..30a9ac3bea559bb54b762c7df04e0fa035d3ec1e 100644 (file)
@@ -1,22 +1,20 @@
 #include "pthread_impl.h"
 #include "syscall.h"
 
-static pthread_once_t check_robust_once;
-static int check_robust_result;
-
-static void check_robust()
-{
-       void *p;
-       size_t l;
-       check_robust_result = -__syscall(SYS_get_robust_list, 0, &p, &l);
-}
+static volatile int check_robust_result = -1;
 
 int pthread_mutexattr_setrobust(pthread_mutexattr_t *a, int robust)
 {
        if (robust > 1U) return EINVAL;
        if (robust) {
-               pthread_once(&check_robust_once, check_robust);
-               if (check_robust_result) return check_robust_result;
+               int r = check_robust_result;
+               if (r < 0) {
+                       void *p;
+                       size_t l;
+                       r = -__syscall(SYS_get_robust_list, 0, &p, &l);
+                       a_store(&check_robust_result, r);
+               }
+               if (r) return r;
                a->__attr |= 4;
                return 0;
        }
index 577748eab3b3ab52968792b9730487d81cdfda47..2125f20b83c759056fdc0060d12e72c1484c16e1 100644 (file)
@@ -17,6 +17,9 @@ __clone:
        # if (!tid) syscall(SYS_exit, a(d));
        # return tid;
 
+       # preserve call-saved register used as syscall arg
+       stg  %r6, 48(%r15)
+
        # create initial stack frame for new thread
        nill %r3, 0xfff8
        aghi %r3, -160
@@ -35,6 +38,9 @@ __clone:
        lg   %r6, 160(%r15)
        svc  120
 
+       # restore call-saved register
+       lg   %r6, 48(%r15)
+
        # if error or if we're the parent, return
        ltgr %r2, %r2
        bnzr %r14
index c1da40de887f182768052729dd1e4c12e428babf..d094cbf5ae1044c96887e4a7b9d9bb88ff458877 100644 (file)
@@ -14,6 +14,7 @@ __cp_begin:
        icm %r2, 15, 0(%r2)
        jne __cp_cancel
 
+       stg %r6, 48(%r15)
        stg %r7, 56(%r15)
        lgr %r1, %r3
        lgr %r2, %r4
@@ -26,6 +27,7 @@ __cp_begin:
 
 __cp_end:
        lg  %r7, 56(%r15)
+       lg  %r6, 48(%r15)
        br  %r14
 
 __cp_cancel:
index de8555c5a6869ceda20c956cc6c8d1ea8470a138..0ad29de96cc1667f3a6d629f5da4104b56ede9d6 100644 (file)
 #include <stdlib.h>
 #include <pthread.h>
 #include "lock.h"
+#include "fork_impl.h"
+
+#define malloc __libc_malloc
+#define calloc __libc_calloc
+#define realloc undef
+#define free undef
 
 static struct {
        ino_t ino;
@@ -19,6 +25,7 @@ static struct {
        int refcnt;
 } *semtab;
 static volatile int lock[1];
+volatile int *const __sem_open_lockptr = lock;
 
 #define FLAGS (O_RDWR|O_NOFOLLOW|O_CLOEXEC|O_NONBLOCK)
 
@@ -163,10 +170,12 @@ int sem_close(sem_t *sem)
        int i;
        LOCK(lock);
        for (i=0; i<SEM_NSEMS_MAX && semtab[i].sem != sem; i++);
-       if (!--semtab[i].refcnt) {
-               semtab[i].sem = 0;
-               semtab[i].ino = 0;
+       if (--semtab[i].refcnt) {
+               UNLOCK(lock);
+               return 0;
        }
+       semtab[i].sem = 0;
+       semtab[i].ino = 0;
        UNLOCK(lock);
        munmap(sem, sizeof *sem);
        return 0;
index 648a6ad458d67c2f415929920c1c11c600cc1367..d58c851fcff4ad60e0abae520cf023802676993b 100644 (file)
@@ -63,7 +63,8 @@ void __synccall(void (*func)(void *), void *ctx)
        sem_init(&target_sem, 0, 0);
        sem_init(&caller_sem, 0, 0);
 
-       if (!libc.threads_minus_1) goto single_threaded;
+       if (!libc.threads_minus_1 || __syscall(SYS_gettid) != self->tid)
+               goto single_threaded;
 
        callback = func;
        context = ctx;
index 75f3cb76190fe4e8796997e7c3d29af80fb36792..fa0a8e3c2ed631572834329ba30ce76c4c4b2364 100644 (file)
@@ -1,6 +1,8 @@
 #include "pthread_impl.h"
+#include "fork_impl.h"
 
 static volatile int vmlock[2];
+volatile int *const __vmlock_lockptr = vmlock;
 
 void __vm_wait()
 {
index 383d05ec342ea0a3354ed27333cd31ca67d77ac2..092d343df3300bb605222ff194ed72dbd4b1287d 100644 (file)
@@ -8,6 +8,12 @@
 #endif
 #include "libc.h"
 #include "lock.h"
+#include "fork_impl.h"
+
+#define malloc __libc_malloc
+#define calloc undef
+#define realloc undef
+#define free undef
 
 #ifdef __wasilibc_unmodified_upstream // timezone data
 long  __timezone = 0;
@@ -35,6 +41,7 @@ static char *old_tz = old_tz_buf;
 static size_t old_tz_size = sizeof old_tz_buf;
 
 static volatile int lock[1];
+volatile int *const __timezone_lockptr = lock;
 
 static int getint(const char **p)
 {
@@ -183,7 +190,7 @@ static void do_tzset()
        zi = map;
        if (map) {
                int scale = 2;
-               if (sizeof(time_t) > 4 && map[4]=='2') {
+               if (map[4]!='1') {
                        size_t skip = zi_dotprod(zi+20, VEC(1,1,8,5,6,1), 6);
                        trans = zi+skip+44+44;
                        scale++;
index 455d49fc5035beca4b3f2b97553311d389cff164..4bef23905103e6853305076cb0096f25f089d8a3 100644 (file)
@@ -2,6 +2,7 @@
 #include <setjmp.h>
 #include <limits.h>
 #include "pthread_impl.h"
+#include "atomic.h"
 
 struct ksigevent {
        union sigval sigev_value;
@@ -32,19 +33,6 @@ static void cleanup_fromsig(void *p)
        longjmp(p, 1);
 }
 
-static void timer_handler(int sig, siginfo_t *si, void *ctx)
-{
-}
-
-static void install_handler()
-{
-       struct sigaction sa = {
-               .sa_sigaction = timer_handler,
-               .sa_flags = SA_SIGINFO | SA_RESTART
-       };
-       __libc_sigaction(SIGTIMER, &sa, 0);
-}
-
 static void *start(void *arg)
 {
        pthread_t self = __pthread_self();
@@ -71,7 +59,7 @@ static void *start(void *arg)
 
 int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict res)
 {
-       static pthread_once_t once = PTHREAD_ONCE_INIT;
+       volatile static int init = 0;
        pthread_t td;
        pthread_attr_t attr;
        int r;
@@ -83,11 +71,15 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict
        switch (evp ? evp->sigev_notify : SIGEV_SIGNAL) {
        case SIGEV_NONE:
        case SIGEV_SIGNAL:
+       case SIGEV_THREAD_ID:
                if (evp) {
                        ksev.sigev_value = evp->sigev_value;
                        ksev.sigev_signo = evp->sigev_signo;
                        ksev.sigev_notify = evp->sigev_notify;
-                       ksev.sigev_tid = 0;
+                       if (evp->sigev_notify == SIGEV_THREAD_ID)
+                               ksev.sigev_tid = evp->sigev_notify_thread_id;
+                       else
+                               ksev.sigev_tid = 0;
                        ksevp = &ksev;
                }
                if (syscall(SYS_timer_create, clk, ksevp, &timerid) < 0)
@@ -95,7 +87,11 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict
                *res = (void *)(intptr_t)timerid;
                break;
        case SIGEV_THREAD:
-               pthread_once(&once, install_handler);
+               if (!init) {
+                       struct sigaction sa = { .sa_handler = SIG_DFL };
+                       __libc_sigaction(SIGTIMER, &sa, 0);
+                       a_store(&init, 1);
+               }
                if (evp->sigev_notify_attributes)
                        attr = *evp->sigev_notify_attributes;
                else
@@ -115,7 +111,7 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict
 
                ksev.sigev_value.sival_ptr = 0;
                ksev.sigev_signo = SIGTIMER;
-               ksev.sigev_notify = 4; /* SIGEV_THREAD_ID */
+               ksev.sigev_notify = SIGEV_THREAD_ID;
                ksev.sigev_tid = td->tid;
                if (syscall(SYS_timer_create, clk, &ksev, &timerid) < 0)
                        timerid = -1;
index 5b38e0194606cf22e0663df576e73b4249b6a0f9..a2105f5060e235733a739bf6155ca25192210ef4 100644 (file)
@@ -1,5 +1,6 @@
 #include <unistd.h>
 #include <errno.h>
+#include "aio_impl.h"
 #include "syscall.h"
 
 static int dummy(int fd)
index 76bbd4c72a16dbea7cdef397aa12ccb013adaa85..557503eb6d8160fe9dc76fe8ee52083fedaa180c 100644 (file)
@@ -25,12 +25,17 @@ static int checker(void *p)
 
 int faccessat(int fd, const char *filename, int amode, int flag)
 {
-       if (!flag || (flag==AT_EACCESS && getuid()==geteuid() && getgid()==getegid()))
-               return syscall(SYS_faccessat, fd, filename, amode, flag);
+       if (flag) {
+               int ret = __syscall(SYS_faccessat2, fd, filename, amode, flag);
+               if (ret != -ENOSYS) return __syscall_ret(ret);
+       }
 
-       if (flag != AT_EACCESS)
+       if (flag & ~AT_EACCESS)
                return __syscall_ret(-EINVAL);
 
+       if (!flag || (getuid()==geteuid() && getgid()==getegid()))
+               return syscall(SYS_faccessat, fd, filename, amode);
+
        char stack[1024];
        sigset_t set;
        pid_t pid;
index a152d52492ed775d3d8fd57125423e461bfb20d8..32f4537f972b0fda8ed2325d9b48c2c8be8e4a45 100644 (file)
@@ -4,9 +4,16 @@
 
 ssize_t readlink(const char *restrict path, char *restrict buf, size_t bufsize)
 {
+       char dummy[1];
+       if (!bufsize) {
+               buf = dummy;
+               bufsize = 1;
+       }
 #ifdef SYS_readlink
-       return syscall(SYS_readlink, path, buf, bufsize);
+       int r = __syscall(SYS_readlink, path, buf, bufsize);
 #else
-       return syscall(SYS_readlinkat, AT_FDCWD, path, buf, bufsize);
+       int r = __syscall(SYS_readlinkat, AT_FDCWD, path, buf, bufsize);
 #endif
+       if (buf == dummy && r > 0) r = 0;
+       return __syscall_ret(r);
 }
index 9af45cd5a47d1e23c673806704a2cf07d75d948f..f79d3d14280ec46afc56dc715f684a1b0cd721e5 100644 (file)
@@ -3,5 +3,12 @@
 
 ssize_t readlinkat(int fd, const char *restrict path, char *restrict buf, size_t bufsize)
 {
-       return syscall(SYS_readlinkat, fd, path, buf, bufsize);
+       char dummy[1];
+       if (!bufsize) {
+               buf = dummy;
+               bufsize = 1;
+       }
+       int r = __syscall(SYS_readlinkat, fd, path, buf, bufsize);
+       if (buf == dummy && r > 0) r = 0;
+       return __syscall_ret(r);
 }
index 0239f8afa95019ae9aa6dad5d79fcaf4eade139b..487c1a160a606ffa27d68d2a15ee155c7113f700 100644 (file)
@@ -1,20 +1,19 @@
 #include <unistd.h>
-#include <errno.h>
+#include <signal.h>
 #include "syscall.h"
 #include "libc.h"
-#include "pthread_impl.h"
 
 struct ctx {
        int id, eid, sid;
-       int nr, err;
+       int nr, ret;
 };
 
 static void do_setxid(void *p)
 {
        struct ctx *c = p;
-       if (c->err>0) return;
-       int ret = -__syscall(c->nr, c->id, c->eid, c->sid);
-       if (ret && !c->err) {
+       if (c->ret<0) return;
+       int ret = __syscall(c->nr, c->id, c->eid, c->sid);
+       if (ret && !c->ret) {
                /* If one thread fails to set ids after another has already
                 * succeeded, forcibly killing the process is the only safe
                 * thing to do. State is inconsistent and dangerous. Use
@@ -22,18 +21,14 @@ static void do_setxid(void *p)
                __block_all_sigs(0);
                __syscall(SYS_kill, __syscall(SYS_getpid), SIGKILL);
        }
-       c->err = ret;
+       c->ret = ret;
 }
 
 int __setxid(int nr, int id, int eid, int sid)
 {
-       /* err is initially nonzero so that failure of the first thread does not
+       /* ret is initially nonzero so that failure of the first thread does not
         * trigger the safety kill above. */
-       struct ctx c = { .nr = nr, .id = id, .eid = eid, .sid = sid, .err = -1 };
+       struct ctx c = { .nr = nr, .id = id, .eid = eid, .sid = sid, .ret = 1 };
        __synccall(do_setxid, &c);
-       if (c.err) {
-               if (c.err>0) errno = c.err;
-               return -1;
-       }
-       return 0;
+       return __syscall_ret(c.ret);
 }