summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--VERSION2
-rw-r--r--WHATSNEW36
-rw-r--r--arch/arm/syscall_arch.h6
-rw-r--r--arch/mips/bits/signal.h2
-rw-r--r--arch/mips/syscall_arch.h80
-rw-r--r--arch/mips64/bits/signal.h2
-rw-r--r--arch/mips64/syscall_arch.h70
-rw-r--r--arch/mipsn32/bits/signal.h2
-rw-r--r--arch/mipsn32/syscall_arch.h75
-rw-r--r--arch/powerpc/bits/mman.h1
-rw-r--r--arch/powerpc64/bits/mman.h1
-rw-r--r--include/arpa/inet.h5
-rw-r--r--include/netinet/in.h2
-rw-r--r--include/pthread.h3
-rw-r--r--ldso/dynlink.c2
-rw-r--r--src/errno/__strerror.h13
-rw-r--r--src/errno/strerror.c41
-rw-r--r--src/fenv/sh/fenv.S2
-rw-r--r--src/internal/libc.h9
-rw-r--r--src/internal/libm.h4
-rw-r--r--src/internal/shgetc.c2
-rw-r--r--src/internal/stdio_impl.h2
-rw-r--r--src/ipc/msgctl.c10
-rw-r--r--src/ipc/semctl.c10
-rw-r--r--src/ipc/shmctl.c10
-rw-r--r--src/malloc/malloc.c5
-rw-r--r--src/math/__expo2.c5
-rw-r--r--src/math/__expo2f.c5
-rw-r--r--src/math/__rem_pio2.c15
-rw-r--r--src/math/__rem_pio2f.c13
-rw-r--r--src/math/__rem_pio2l.c16
-rw-r--r--src/math/cosh.c2
-rw-r--r--src/math/coshf.c2
-rw-r--r--src/math/i386/exp.c1
-rw-r--r--src/math/i386/exp2.s1
-rw-r--r--src/math/i386/exp2f.s1
-rw-r--r--src/math/i386/exp2l.s2
-rw-r--r--src/math/i386/exp_ld.s55
-rw-r--r--src/math/i386/expf.s1
-rw-r--r--src/math/i386/expm1.s1
-rw-r--r--src/math/i386/expm1f.s1
-rw-r--r--src/math/i386/expm1l.s2
-rw-r--r--src/math/i386/fabs.c7
-rw-r--r--src/math/i386/fabs.s6
-rw-r--r--src/math/i386/fabsf.c7
-rw-r--r--src/math/i386/fabsf.s6
-rw-r--r--src/math/i386/fabsl.c7
-rw-r--r--src/math/i386/fabsl.s6
-rw-r--r--src/math/i386/fmod.c10
-rw-r--r--src/math/i386/fmod.s11
-rw-r--r--src/math/i386/fmodf.c10
-rw-r--r--src/math/i386/fmodf.s11
-rw-r--r--src/math/i386/fmodl.c9
-rw-r--r--src/math/i386/fmodl.s11
-rw-r--r--src/math/i386/llrint.c8
-rw-r--r--src/math/i386/llrint.s8
-rw-r--r--src/math/i386/llrintf.c8
-rw-r--r--src/math/i386/llrintf.s9
-rw-r--r--src/math/i386/llrintl.c8
-rw-r--r--src/math/i386/llrintl.s8
-rw-r--r--src/math/i386/lrint.c8
-rw-r--r--src/math/i386/lrint.s7
-rw-r--r--src/math/i386/lrintf.c8
-rw-r--r--src/math/i386/lrintf.s7
-rw-r--r--src/math/i386/lrintl.c8
-rw-r--r--src/math/i386/lrintl.s7
-rw-r--r--src/math/i386/remainder.c12
-rw-r--r--src/math/i386/remainder.s14
-rw-r--r--src/math/i386/remainderf.c12
-rw-r--r--src/math/i386/remainderf.s14
-rw-r--r--src/math/i386/remainderl.c9
-rw-r--r--src/math/i386/remainderl.s11
-rw-r--r--src/math/i386/rint.c7
-rw-r--r--src/math/i386/rint.s6
-rw-r--r--src/math/i386/rintf.c7
-rw-r--r--src/math/i386/rintf.s6
-rw-r--r--src/math/i386/rintl.c7
-rw-r--r--src/math/i386/rintl.s6
-rw-r--r--src/math/i386/sqrt.c15
-rw-r--r--src/math/i386/sqrt.s21
-rw-r--r--src/math/i386/sqrtf.c12
-rw-r--r--src/math/i386/sqrtf.s7
-rw-r--r--src/math/i386/sqrtl.c7
-rw-r--r--src/math/i386/sqrtl.s5
-rw-r--r--src/math/sinh.c2
-rw-r--r--src/math/sinhf.c2
-rw-r--r--src/math/x86_64/fabs.c10
-rw-r--r--src/math/x86_64/fabs.s9
-rw-r--r--src/math/x86_64/fabsf.c10
-rw-r--r--src/math/x86_64/fabsf.s7
-rw-r--r--src/math/x86_64/fabsl.c7
-rw-r--r--src/math/x86_64/fabsl.s6
-rw-r--r--src/math/x86_64/fmodl.c9
-rw-r--r--src/math/x86_64/fmodl.s11
-rw-r--r--src/math/x86_64/llrint.c8
-rw-r--r--src/math/x86_64/llrint.s5
-rw-r--r--src/math/x86_64/llrintf.c8
-rw-r--r--src/math/x86_64/llrintf.s5
-rw-r--r--src/math/x86_64/llrintl.c8
-rw-r--r--src/math/x86_64/llrintl.s7
-rw-r--r--src/math/x86_64/lrint.c8
-rw-r--r--src/math/x86_64/lrint.s5
-rw-r--r--src/math/x86_64/lrintf.c8
-rw-r--r--src/math/x86_64/lrintf.s5
-rw-r--r--src/math/x86_64/lrintl.c8
-rw-r--r--src/math/x86_64/lrintl.s7
-rw-r--r--src/math/x86_64/remainderl.c9
-rw-r--r--src/math/x86_64/remainderl.s11
-rw-r--r--src/math/x86_64/remquol.c32
-rw-r--r--src/math/x86_64/rintl.c7
-rw-r--r--src/math/x86_64/rintl.s6
-rw-r--r--src/math/x86_64/sqrt.c7
-rw-r--r--src/math/x86_64/sqrt.s4
-rw-r--r--src/math/x86_64/sqrtf.c7
-rw-r--r--src/math/x86_64/sqrtf.s4
-rw-r--r--src/math/x86_64/sqrtl.c7
-rw-r--r--src/math/x86_64/sqrtl.s5
-rw-r--r--src/network/getnameinfo.c1
-rw-r--r--src/network/lookup_name.c12
-rw-r--r--src/network/res_mkquery.c1
-rw-r--r--src/network/res_send.c2
-rw-r--r--src/network/socket.c10
-rw-r--r--src/stat/fchmodat.c3
-rw-r--r--src/stdio/__string_read.c16
-rw-r--r--src/stdio/fmemopen.c6
-rw-r--r--src/stdio/tempnam.c5
-rw-r--r--src/stdio/tmpnam.c5
-rw-r--r--src/stdio/vdprintf.c7
-rw-r--r--src/stdio/vfscanf.c3
-rw-r--r--src/stdio/vsscanf.c16
-rw-r--r--src/stdlib/wcstod.c3
-rw-r--r--src/stdlib/wcstol.c3
-rw-r--r--src/string/memccpy.c2
-rw-r--r--src/string/memmem.c8
-rw-r--r--src/string/strsignal.c10
-rw-r--r--src/string/strstr.c8
-rw-r--r--src/thread/__lock.c4
-rw-r--r--src/thread/pthread_create.c23
-rw-r--r--src/time/__map_file.c3
-rw-r--r--src/time/__tz.c12
140 files changed, 716 insertions, 594 deletions
diff --git a/VERSION b/VERSION
index 3fe3e58a..26aaba0e 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.1.24
+1.2.0
diff --git a/WHATSNEW b/WHATSNEW
index f9879bd5..ecf0ceba 100644
--- a/WHATSNEW
+++ b/WHATSNEW
@@ -2164,3 +2164,39 @@ arch-specific bugs fixed:
- riscv64 atomics had broken asm constraints (missing earlyclobber flag)
- arm clone() was broken when compiled as thumb if start function returned
- mipsr6 setjmp/longjmp did not preserve fpu register state correctly
+
+
+
+1.2.0 release notes
+
+new features:
+- time_t is now 64-bit on all archs (not just 64-bit archs)
+- character type & case mapping data updated to Unicode 12.1.0
+- header-level support for new linux features in 5.3 and 5.4
+
+performance:
+- new O(1) wchar_t case mapping implementation
+- i386 now uses C math code for exp, faster than old asm
+- mips math asm
+
+compatibility & conformance:
+- endian.h now aims to conform to future POSIX definition
+- support older compilers that don't accept powerpc math asm constraints
+- fdpic code in ldso was incompatible with valid optimizations in gcc 9+
+- RLIMIT_RTTIME was missing from sys/resource.h
+
+bugs fixed:
+- wcwidth wrongly returned 0 for most of planes 4 and up
+- missing case mapping between U+03F3 and U+037F
+- wrong cacosh results for arguments with negative imaginary part
+- wrong catanf/catanl results for various classes of arguments
+- wrong return value for ungetc with argument outside [0,UCHAR_MAX]
+- posix_openpt with no ptys available produced wrong errno
+
+arch-specific bugs fixed:
+- sigcontext/regset definition mistakes & omissions on m68k, powerpc64
+- fesetenv(FE_DFL_ENV) crashed on riscv64
+- sh2 dynamic linker was broken since 1.1.21 (crash in stage 2b)
+- arm dynamic linker chose wrong tls/atomic variants since 1.1.21
+- some math library functions returned excess precision on i386
+- unconfirmed regression in fchmodat AT_SYMLINK_NOFOLLOW on mips*
diff --git a/arch/arm/syscall_arch.h b/arch/arm/syscall_arch.h
index 4b08762d..a877b2cf 100644
--- a/arch/arm/syscall_arch.h
+++ b/arch/arm/syscall_arch.h
@@ -98,12 +98,6 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
__asm_syscall(R7_OPERAND, "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5));
}
-#define VDSO_USEFUL
-#define VDSO_CGT32_SYM "__vdso_clock_gettime"
-#define VDSO_CGT32_VER "LINUX_2.6"
-#define VDSO_CGT_SYM "__vdso_clock_gettime64"
-#define VDSO_CGT_VER "LINUX_2.6"
-
#define SYSCALL_FADVISE_6_ARG
#define SYSCALL_IPC_BROKEN_MODE
diff --git a/arch/mips/bits/signal.h b/arch/mips/bits/signal.h
index e1d97ac7..1b69e762 100644
--- a/arch/mips/bits/signal.h
+++ b/arch/mips/bits/signal.h
@@ -93,7 +93,7 @@ typedef struct __ucontext {
#define SIGTRAP 5
#define SIGABRT 6
#define SIGIOT SIGABRT
-#define SIGSTKFLT 7
+#define SIGEMT 7
#define SIGFPE 8
#define SIGKILL 9
#define SIGBUS 10
diff --git a/arch/mips/syscall_arch.h b/arch/mips/syscall_arch.h
index f821e73f..380a94b3 100644
--- a/arch/mips/syscall_arch.h
+++ b/arch/mips/syscall_arch.h
@@ -18,26 +18,26 @@
static inline long __syscall0(long n)
{
register long r7 __asm__("$7");
- register long r2 __asm__("$2") = n;
+ register long r2 __asm__("$2");
__asm__ __volatile__ (
- "syscall"
- : "+r"(r2), "=r"(r7)
- :
+ "addu $2,$0,%2 ; syscall"
+ : "=&r"(r2), "=r"(r7)
+ : "ir"(n), "0"(r2)
: SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
- return r7 ? -r2 : r2;
+ return r7 && r2>0 ? -r2 : r2;
}
static inline long __syscall1(long n, long a)
{
register long r4 __asm__("$4") = a;
register long r7 __asm__("$7");
- register long r2 __asm__("$2") = n;
+ register long r2 __asm__("$2");
__asm__ __volatile__ (
- "syscall"
- : "+r"(r2), "=r"(r7)
- : "r"(r4)
+ "addu $2,$0,%2 ; syscall"
+ : "=&r"(r2), "=r"(r7)
+ : "ir"(n), "0"(r2), "r"(r4)
: SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
- return r7 ? -r2 : r2;
+ return r7 && r2>0 ? -r2 : r2;
}
static inline long __syscall2(long n, long a, long b)
@@ -45,13 +45,13 @@ static inline long __syscall2(long n, long a, long b)
register long r4 __asm__("$4") = a;
register long r5 __asm__("$5") = b;
register long r7 __asm__("$7");
- register long r2 __asm__("$2") = n;
+ register long r2 __asm__("$2");
__asm__ __volatile__ (
- "syscall"
- : "+r"(r2), "=r"(r7)
- : "r"(r4), "r"(r5)
+ "addu $2,$0,%2 ; syscall"
+ : "=&r"(r2), "=r"(r7)
+ : "ir"(n), "0"(r2), "r"(r4), "r"(r5)
: SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
- return r7 ? -r2 : r2;
+ return r7 && r2>0 ? -r2 : r2;
}
static inline long __syscall3(long n, long a, long b, long c)
@@ -60,13 +60,13 @@ static inline long __syscall3(long n, long a, long b, long c)
register long r5 __asm__("$5") = b;
register long r6 __asm__("$6") = c;
register long r7 __asm__("$7");
- register long r2 __asm__("$2") = n;
+ register long r2 __asm__("$2");
__asm__ __volatile__ (
- "syscall"
- : "+r"(r2), "=r"(r7)
- : "r"(r4), "r"(r5), "r"(r6)
+ "addu $2,$0,%2 ; syscall"
+ : "=&r"(r2), "=r"(r7)
+ : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6)
: SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
- return r7 ? -r2 : r2;
+ return r7 && r2>0 ? -r2 : r2;
}
static inline long __syscall4(long n, long a, long b, long c, long d)
@@ -75,13 +75,13 @@ static inline long __syscall4(long n, long a, long b, long c, long d)
register long r5 __asm__("$5") = b;
register long r6 __asm__("$6") = c;
register long r7 __asm__("$7") = d;
- register long r2 __asm__("$2") = n;
+ register long r2 __asm__("$2");
__asm__ __volatile__ (
- "syscall"
- : "+r"(r2), "+r"(r7)
- : "r"(r4), "r"(r5), "r"(r6)
+ "addu $2,$0,%2 ; syscall"
+ : "=&r"(r2), "+r"(r7)
+ : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6)
: SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
- return r7 ? -r2 : r2;
+ return r7 && r2>0 ? -r2 : r2;
}
static inline long __syscall5(long n, long a, long b, long c, long d, long e)
@@ -91,15 +91,15 @@ static inline long __syscall5(long n, long a, long b, long c, long d, long e)
register long r6 __asm__("$6") = c;
register long r7 __asm__("$7") = d;
register long r8 __asm__("$8") = e;
- register long r2 __asm__("$2") = n;
+ register long r2 __asm__("$2");
__asm__ __volatile__ (
"subu $sp,$sp,32 ; sw $8,16($sp) ; "
- "syscall ;"
+ "addu $2,$0,%3 ; syscall ;"
"addu $sp,$sp,32"
- : "+r"(r2), "+r"(r7), "+r"(r8)
- : "r"(r4), "r"(r5), "r"(r6)
+ : "=&r"(r2), "+r"(r7), "+r"(r8)
+ : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6)
: SYSCALL_CLOBBERLIST, "$9", "$10");
- return r7 ? -r2 : r2;
+ return r7 && r2>0 ? -r2 : r2;
}
static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
@@ -110,15 +110,15 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
register long r7 __asm__("$7") = d;
register long r8 __asm__("$8") = e;
register long r9 __asm__("$9") = f;
- register long r2 __asm__("$2") = n;
+ register long r2 __asm__("$2");
__asm__ __volatile__ (
"subu $sp,$sp,32 ; sw $8,16($sp) ; sw $9,20($sp) ; "
- "syscall ;"
+ "addu $2,$0,%4 ; syscall ;"
"addu $sp,$sp,32"
- : "+r"(r2), "+r"(r7), "+r"(r8), "+r"(r9)
- : "r"(r4), "r"(r5), "r"(r6)
+ : "=&r"(r2), "+r"(r7), "+r"(r8), "+r"(r9)
+ : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6)
: SYSCALL_CLOBBERLIST, "$10");
- return r7 ? -r2 : r2;
+ return r7 && r2>0 ? -r2 : r2;
}
static inline long __syscall7(long n, long a, long b, long c, long d, long e, long f, long g)
@@ -130,15 +130,15 @@ static inline long __syscall7(long n, long a, long b, long c, long d, long e, lo
register long r8 __asm__("$8") = e;
register long r9 __asm__("$9") = f;
register long r10 __asm__("$10") = g;
- register long r2 __asm__("$2") = n;
+ register long r2 __asm__("$2");
__asm__ __volatile__ (
"subu $sp,$sp,32 ; sw $8,16($sp) ; sw $9,20($sp) ; sw $10,24($sp) ; "
- "syscall ;"
+ "addu $2,$0,%5 ; syscall ;"
"addu $sp,$sp,32"
- : "+r"(r2), "+r"(r7), "+r"(r8), "+r"(r9), "+r"(r10)
- : "r"(r4), "r"(r5), "r"(r6)
+ : "=&r"(r2), "+r"(r7), "+r"(r8), "+r"(r9), "+r"(r10)
+ : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6)
: SYSCALL_CLOBBERLIST);
- return r7 ? -r2 : r2;
+ return r7 && r2>0 ? -r2 : r2;
}
#define VDSO_USEFUL
diff --git a/arch/mips64/bits/signal.h b/arch/mips64/bits/signal.h
index c31ad07e..4f91c9fc 100644
--- a/arch/mips64/bits/signal.h
+++ b/arch/mips64/bits/signal.h
@@ -112,7 +112,7 @@ typedef struct __ucontext {
#define SIGTRAP 5
#define SIGABRT 6
#define SIGIOT SIGABRT
-#define SIGSTKFLT 7
+#define SIGEMT 7
#define SIGFPE 8
#define SIGKILL 9
#define SIGBUS 10
diff --git a/arch/mips64/syscall_arch.h b/arch/mips64/syscall_arch.h
index 69c429b8..ae6532fc 100644
--- a/arch/mips64/syscall_arch.h
+++ b/arch/mips64/syscall_arch.h
@@ -16,26 +16,26 @@
static inline long __syscall0(long n)
{
register long r7 __asm__("$7");
- register long r2 __asm__("$2") = n;
+ register long r2 __asm__("$2");
__asm__ __volatile__ (
- "syscall"
- : "+&r"(r2), "=r"(r7)
- :
+ "daddu $2,$0,%2 ; syscall"
+ : "=&r"(r2), "=r"(r7)
+ : "ir"(n), "0"(r2)
: SYSCALL_CLOBBERLIST);
- return r7 ? -r2 : r2;
+ return r7 && r2>0 ? -r2 : r2;
}
static inline long __syscall1(long n, long a)
{
register long r4 __asm__("$4") = a;
register long r7 __asm__("$7");
- register long r2 __asm__("$2") = n;
+ register long r2 __asm__("$2");
__asm__ __volatile__ (
- "syscall"
- : "+&r"(r2), "=r"(r7)
- : "r"(r4)
+ "daddu $2,$0,%2 ; syscall"
+ : "=&r"(r2), "=r"(r7)
+ : "ir"(n), "0"(r2), "r"(r4)
: SYSCALL_CLOBBERLIST);
- return r7 ? -r2 : r2;
+ return r7 && r2>0 ? -r2 : r2;
}
static inline long __syscall2(long n, long a, long b)
@@ -43,14 +43,14 @@ static inline long __syscall2(long n, long a, long b)
register long r4 __asm__("$4") = a;
register long r5 __asm__("$5") = b;
register long r7 __asm__("$7");
- register long r2 __asm__("$2") = n;
+ register long r2 __asm__("$2");
__asm__ __volatile__ (
- "syscall"
- : "+&r"(r2), "=r"(r7)
- : "r"(r4), "r"(r5)
+ "daddu $2,$0,%2 ; syscall"
+ : "=&r"(r2), "=r"(r7)
+ : "ir"(n), "0"(r2), "r"(r4), "r"(r5)
: SYSCALL_CLOBBERLIST);
- return r7 ? -r2 : r2;
+ return r7 && r2>0 ? -r2 : r2;
}
static inline long __syscall3(long n, long a, long b, long c)
@@ -59,14 +59,14 @@ static inline long __syscall3(long n, long a, long b, long c)
register long r5 __asm__("$5") = b;
register long r6 __asm__("$6") = c;
register long r7 __asm__("$7");
- register long r2 __asm__("$2") = n;
+ register long r2 __asm__("$2");
__asm__ __volatile__ (
- "syscall"
- : "+&r"(r2), "=r"(r7)
- : "r"(r4), "r"(r5), "r"(r6)
+ "daddu $2,$0,%2 ; syscall"
+ : "=&r"(r2), "=r"(r7)
+ : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6)
: SYSCALL_CLOBBERLIST);
- return r7 ? -r2 : r2;
+ return r7 && r2>0 ? -r2 : r2;
}
static inline long __syscall4(long n, long a, long b, long c, long d)
@@ -75,14 +75,14 @@ static inline long __syscall4(long n, long a, long b, long c, long d)
register long r5 __asm__("$5") = b;
register long r6 __asm__("$6") = c;
register long r7 __asm__("$7") = d;
- register long r2 __asm__("$2") = n;
+ register long r2 __asm__("$2");
__asm__ __volatile__ (
- "syscall"
- : "+&r"(r2), "+r"(r7)
- : "r"(r4), "r"(r5), "r"(r6)
+ "daddu $2,$0,%2 ; syscall"
+ : "=&r"(r2), "+r"(r7)
+ : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6)
: SYSCALL_CLOBBERLIST);
- return r7 ? -r2 : r2;
+ return r7 && r2>0 ? -r2 : r2;
}
static inline long __syscall5(long n, long a, long b, long c, long d, long e)
@@ -92,14 +92,14 @@ static inline long __syscall5(long n, long a, long b, long c, long d, long e)
register long r6 __asm__("$6") = c;
register long r7 __asm__("$7") = d;
register long r8 __asm__("$8") = e;
- register long r2 __asm__("$2") = n;
+ register long r2 __asm__("$2");
__asm__ __volatile__ (
- "syscall"
- : "+&r"(r2), "+r"(r7)
- : "r"(r4), "r"(r5), "r"(r6), "r"(r8)
+ "daddu $2,$0,%2 ; syscall"
+ : "=&r"(r2), "+r"(r7)
+ : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6), "r"(r8)
: SYSCALL_CLOBBERLIST);
- return r7 ? -r2 : r2;
+ return r7 && r2>0 ? -r2 : r2;
}
static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
@@ -110,14 +110,14 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
register long r7 __asm__("$7") = d;
register long r8 __asm__("$8") = e;
register long r9 __asm__("$9") = f;
- register long r2 __asm__("$2") = n;
+ register long r2 __asm__("$2");
__asm__ __volatile__ (
- "syscall"
- : "+&r"(r2), "+r"(r7)
- : "r"(r4), "r"(r5), "r"(r6), "r"(r8), "r"(r9)
+ "daddu $2,$0,%2 ; syscall"
+ : "=&r"(r2), "+r"(r7)
+ : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6), "r"(r8), "r"(r9)
: SYSCALL_CLOBBERLIST);
- return r7 ? -r2 : r2;
+ return r7 && r2>0 ? -r2 : r2;
}
#define VDSO_USEFUL
diff --git a/arch/mipsn32/bits/signal.h b/arch/mipsn32/bits/signal.h
index c31ad07e..4f91c9fc 100644
--- a/arch/mipsn32/bits/signal.h
+++ b/arch/mipsn32/bits/signal.h
@@ -112,7 +112,7 @@ typedef struct __ucontext {
#define SIGTRAP 5
#define SIGABRT 6
#define SIGIOT SIGABRT
-#define SIGSTKFLT 7
+#define SIGEMT 7
#define SIGFPE 8
#define SIGKILL 9
#define SIGBUS 10
diff --git a/arch/mipsn32/syscall_arch.h b/arch/mipsn32/syscall_arch.h
index c1a4b7da..c681905d 100644
--- a/arch/mipsn32/syscall_arch.h
+++ b/arch/mipsn32/syscall_arch.h
@@ -16,26 +16,26 @@
static inline long __syscall0(long n)
{
register long r7 __asm__("$7");
- register long r2 __asm__("$2") = n;
+ register long r2 __asm__("$2");
__asm__ __volatile__ (
- "syscall"
- : "+&r"(r2), "=r"(r7)
- :
+ "daddu $2,$0,%2 ; syscall"
+ : "=&r"(r2), "=r"(r7)
+ : "ir"(n), "0"(r2)
: SYSCALL_CLOBBERLIST);
- return r7 ? -r2 : r2;
+ return r7 && r2>0 ? -r2 : r2;
}
static inline long __syscall1(long n, long a)
{
register long r4 __asm__("$4") = a;
register long r7 __asm__("$7");
- register long r2 __asm__("$2") = n;
+ register long r2 __asm__("$2");
__asm__ __volatile__ (
- "syscall"
- : "+&r"(r2), "=r"(r7)
- : "r"(r4)
+ "daddu $2,$0,%2 ; syscall"
+ : "=&r"(r2), "=r"(r7)
+ : "ir"(n), "0"(r2), "r"(r4)
: SYSCALL_CLOBBERLIST);
- return r7 ? -r2 : r2;
+ return r7 && r2>0 ? -r2 : r2;
}
static inline long __syscall2(long n, long a, long b)
@@ -43,13 +43,14 @@ static inline long __syscall2(long n, long a, long b)
register long r4 __asm__("$4") = a;
register long r5 __asm__("$5") = b;
register long r7 __asm__("$7");
- register long r2 __asm__("$2") = n;
+ register long r2 __asm__("$2");
+
__asm__ __volatile__ (
- "syscall"
- : "+&r"(r2), "=r"(r7)
- : "r"(r4), "r"(r5)
+ "daddu $2,$0,%2 ; syscall"
+ : "=&r"(r2), "=r"(r7)
+ : "ir"(n), "0"(r2), "r"(r4), "r"(r5)
: SYSCALL_CLOBBERLIST);
- return r7 ? -r2 : r2;
+ return r7 && r2>0 ? -r2 : r2;
}
static inline long __syscall3(long n, long a, long b, long c)
@@ -58,13 +59,14 @@ static inline long __syscall3(long n, long a, long b, long c)
register long r5 __asm__("$5") = b;
register long r6 __asm__("$6") = c;
register long r7 __asm__("$7");
- register long r2 __asm__("$2") = n;
+ register long r2 __asm__("$2");
+
__asm__ __volatile__ (
- "syscall"
- : "+&r"(r2), "=r"(r7)
- : "r"(r4), "r"(r5), "r"(r6)
+ "daddu $2,$0,%2 ; syscall"
+ : "=&r"(r2), "=r"(r7)
+ : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6)
: SYSCALL_CLOBBERLIST);
- return r7 ? -r2 : r2;
+ return r7 && r2>0 ? -r2 : r2;
}
static inline long __syscall4(long n, long a, long b, long c, long d)
@@ -73,13 +75,14 @@ static inline long __syscall4(long n, long a, long b, long c, long d)
register long r5 __asm__("$5") = b;
register long r6 __asm__("$6") = c;
register long r7 __asm__("$7") = d;
- register long r2 __asm__("$2") = n;
+ register long r2 __asm__("$2");
+
__asm__ __volatile__ (
- "syscall"
- : "+&r"(r2), "+r"(r7)
- : "r"(r4), "r"(r5), "r"(r6)
+ "daddu $2,$0,%2 ; syscall"
+ : "=&r"(r2), "+r"(r7)
+ : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6)
: SYSCALL_CLOBBERLIST);
- return r7 ? -r2 : r2;
+ return r7 && r2>0 ? -r2 : r2;
}
static inline long __syscall5(long n, long a, long b, long c, long d, long e)
@@ -89,13 +92,14 @@ static inline long __syscall5(long n, long a, long b, long c, long d, long e)
register long r6 __asm__("$6") = c;
register long r7 __asm__("$7") = d;
register long r8 __asm__("$8") = e;
- register long r2 __asm__("$2") = n;
+ register long r2 __asm__("$2");
+
__asm__ __volatile__ (
- "syscall"
- : "+&r"(r2), "+r"(r7)
- : "r"(r4), "r"(r5), "r"(r6), "r"(r8)
+ "daddu $2,$0,%2 ; syscall"
+ : "=&r"(r2), "+r"(r7)
+ : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6), "r"(r8)
: SYSCALL_CLOBBERLIST);
- return r7 ? -r2 : r2;
+ return r7 && r2>0 ? -r2 : r2;
}
static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
@@ -106,13 +110,14 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
register long r7 __asm__("$7") = d;
register long r8 __asm__("$8") = e;
register long r9 __asm__("$9") = f;
- register long r2 __asm__("$2") = n;
+ register long r2 __asm__("$2");
+
__asm__ __volatile__ (
- "syscall"
- : "+&r"(r2), "+r"(r7)
- : "r"(r4), "r"(r5), "r"(r6), "r"(r8), "r"(r9)
+ "daddu $2,$0,%2 ; syscall"
+ : "=&r"(r2), "+r"(r7)
+ : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6), "r"(r8), "r"(r9)
: SYSCALL_CLOBBERLIST);
- return r7 ? -r2 : r2;
+ return r7 && r2>0 ? -r2 : r2;
}
#define VDSO_USEFUL
diff --git a/arch/powerpc/bits/mman.h b/arch/powerpc/bits/mman.h
index b3a675a8..95ec4358 100644
--- a/arch/powerpc/bits/mman.h
+++ b/arch/powerpc/bits/mman.h
@@ -4,7 +4,6 @@
#define MAP_NORESERVE 0x40
#undef MAP_LOCKED
#define MAP_LOCKED 0x80
-#undef MAP_SYNC
#undef MCL_CURRENT
#define MCL_CURRENT 0x2000
diff --git a/arch/powerpc64/bits/mman.h b/arch/powerpc64/bits/mman.h
index b3a675a8..95ec4358 100644
--- a/arch/powerpc64/bits/mman.h
+++ b/arch/powerpc64/bits/mman.h
@@ -4,7 +4,6 @@
#define MAP_NORESERVE 0x40
#undef MAP_LOCKED
#define MAP_LOCKED 0x80
-#undef MAP_SYNC
#undef MCL_CURRENT
#define MCL_CURRENT 0x2000
diff --git a/include/arpa/inet.h b/include/arpa/inet.h
index 37f8c11e..9d20a15b 100644
--- a/include/arpa/inet.h
+++ b/include/arpa/inet.h
@@ -24,11 +24,6 @@ struct in_addr inet_makeaddr(in_addr_t, in_addr_t);
in_addr_t inet_lnaof(struct in_addr);
in_addr_t inet_netof(struct in_addr);
-#undef INET_ADDRSTRLEN
-#undef INET6_ADDRSTRLEN
-#define INET_ADDRSTRLEN 16
-#define INET6_ADDRSTRLEN 46
-
#ifdef __cplusplus
}
#endif
diff --git a/include/netinet/in.h b/include/netinet/in.h
index 5b8b21e6..103d2e04 100644
--- a/include/netinet/in.h
+++ b/include/netinet/in.h
@@ -60,8 +60,6 @@ struct ipv6_mreq {
extern const struct in6_addr in6addr_any, in6addr_loopback;
-#undef INET_ADDRSTRLEN
-#undef INET6_ADDRSTRLEN
#define INET_ADDRSTRLEN 16
#define INET6_ADDRSTRLEN 46
diff --git a/include/pthread.h b/include/pthread.h
index 984db680..0492f26a 100644
--- a/include/pthread.h
+++ b/include/pthread.h
@@ -74,6 +74,9 @@ extern "C" {
#define PTHREAD_BARRIER_SERIAL_THREAD (-1)
+#define PTHREAD_NULL ((pthread_t)0)
+
+
int pthread_create(pthread_t *__restrict, const pthread_attr_t *__restrict, void *(*)(void *), void *__restrict);
int pthread_detach(pthread_t);
_Noreturn void pthread_exit(void *);
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index afec985a..6468f203 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -415,8 +415,6 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
}
switch(type) {
- case REL_NONE:
- break;
case REL_OFFSET:
addend -= (size_t)reloc_addr;
case REL_SYMBOLIC:
diff --git a/src/errno/__strerror.h b/src/errno/__strerror.h
index 2f04d400..2d992da5 100644
--- a/src/errno/__strerror.h
+++ b/src/errno/__strerror.h
@@ -1,8 +1,9 @@
-/* This file is sorted such that 'errors' which represent exceptional
- * conditions under which a correct program may fail come first, followed
- * by messages that indicate an incorrect program or system failure. The
- * macro E() along with double-inclusion is used to ensure that ordering
- * of the strings remains synchronized. */
+/* The first entry is a catch-all for codes not enumerated here.
+ * This file is included multiple times to declare and define a structure
+ * with these messages, and then to define a lookup table translating
+ * error codes to offsets of corresponding fields in the structure. */
+
+E(0, "No error information")
E(EILSEQ, "Illegal byte sequence")
E(EDOM, "Domain error")
@@ -101,5 +102,3 @@ E(EDQUOT, "Quota exceeded")
E(ENOMEDIUM, "No medium found")
E(EMEDIUMTYPE, "Wrong medium type")
E(EMULTIHOP, "Multihop attempted")
-
-E(0, "No error information")
diff --git a/src/errno/strerror.c b/src/errno/strerror.c
index e3ed771a..7f926432 100644
--- a/src/errno/strerror.c
+++ b/src/errno/strerror.c
@@ -1,30 +1,41 @@
#include <errno.h>
+#include <stddef.h>
#include <string.h>
#include "locale_impl.h"
-#define E(a,b) ((unsigned char)a),
-static const unsigned char errid[] = {
+/* mips has one error code outside of the 8-bit range due to a
+ * historical typo, so we just remap it. */
+#if EDQUOT==1133
+#define EDQUOT_ORIG 1133
+#undef EDQUOT
+#define EDQUOT 109
+#endif
+
+static const struct errmsgstr_t {
+#define E(n, s) char str##n[sizeof(s)];
+#include "__strerror.h"
+#undef E
+} errmsgstr = {
+#define E(n, s) s,
#include "__strerror.h"
+#undef E
};
-#undef E
-#define E(a,b) b "\0"
-static const char errmsg[] =
+static const unsigned short errmsgidx[] = {
+#define E(n, s) [n] = offsetof(struct errmsgstr_t, str##n),
#include "__strerror.h"
-;
+#undef E
+};
char *__strerror_l(int e, locale_t loc)
{
const char *s;
- int i;
- /* mips has one error code outside of the 8-bit range due to a
- * historical typo, so we just remap it. */
- if (EDQUOT==1133) {
- if (e==109) e=-1;
- else if (e==EDQUOT) e=109;
- }
- for (i=0; errid[i] && errid[i] != e; i++);
- for (s=errmsg; i; s++, i--) for (; *s; s++);
+#ifdef EDQUOT_ORIG
+ if (e==EDQUOT) e=0;
+ else if (e==EDQUOT_ORIG) e=EDQUOT;
+#endif
+ if (e >= sizeof errmsgidx / sizeof *errmsgidx) e = 0;
+ s = (char *)&errmsgstr + errmsgidx[e];
return (char *)LCTRANS(s, LC_MESSAGES, loc);
}
diff --git a/src/fenv/sh/fenv.S b/src/fenv/sh/fenv.S
index 907aefc0..b3b7d66a 100644
--- a/src/fenv/sh/fenv.S
+++ b/src/fenv/sh/fenv.S
@@ -12,6 +12,8 @@ fegetround:
.type __fesetround, @function
__fesetround:
sts fpscr, r0
+ mov #-4, r1
+ and r1, r0
or r4, r0
lds r0, fpscr
rts
diff --git a/src/internal/libc.h b/src/internal/libc.h
index ac97dc7e..619bba86 100644
--- a/src/internal/libc.h
+++ b/src/internal/libc.h
@@ -18,10 +18,11 @@ struct tls_module {
};
struct __libc {
- int can_do_threads;
- int threaded;
- int secure;
- volatile int threads_minus_1;
+ char can_do_threads;
+ char threaded;
+ char secure;
+ volatile signed char need_locks;
+ int threads_minus_1;
size_t *auxv;
struct tls_module *tls_head;
size_t tls_size, tls_align, tls_cnt;
diff --git a/src/internal/libm.h b/src/internal/libm.h
index b5bd26b8..7533f6ba 100644
--- a/src/internal/libm.h
+++ b/src/internal/libm.h
@@ -236,13 +236,13 @@ hidden int __rem_pio2(double,double*);
hidden double __sin(double,double,int);
hidden double __cos(double,double);
hidden double __tan(double,double,int);
-hidden double __expo2(double);
+hidden double __expo2(double,double);
hidden int __rem_pio2f(float,double*);
hidden float __sindf(double);
hidden float __cosdf(double);
hidden float __tandf(double,int);
-hidden float __expo2f(float);
+hidden float __expo2f(float,float);
hidden int __rem_pio2l(long double, long double *);
hidden long double __sinl(long double, long double, int);
diff --git a/src/internal/shgetc.c b/src/internal/shgetc.c
index a4a9c633..7455d2f0 100644
--- a/src/internal/shgetc.c
+++ b/src/internal/shgetc.c
@@ -32,6 +32,6 @@ int __shgetc(FILE *f)
else
f->shend = f->rend;
f->shcnt = f->buf - f->rpos + cnt;
- if (f->rpos[-1] != c) f->rpos[-1] = c;
+ if (f->rpos <= f->buf) f->rpos[-1] = c;
return c;
}
diff --git a/src/internal/stdio_impl.h b/src/internal/stdio_impl.h
index d7398f59..0b2438d6 100644
--- a/src/internal/stdio_impl.h
+++ b/src/internal/stdio_impl.h
@@ -60,8 +60,6 @@ hidden size_t __stdout_write(FILE *, const unsigned char *, size_t);
hidden off_t __stdio_seek(FILE *, off_t, int);
hidden int __stdio_close(FILE *);
-hidden size_t __string_read(FILE *, unsigned char *, size_t);
-
hidden int __toread(FILE *);
hidden int __towrite(FILE *);
diff --git a/src/ipc/msgctl.c b/src/ipc/msgctl.c
index b043041a..9c114406 100644
--- a/src/ipc/msgctl.c
+++ b/src/ipc/msgctl.c
@@ -9,6 +9,14 @@
int msgctl(int q, int cmd, struct msqid_ds *buf)
{
+#if IPC_TIME64
+ struct msqid_ds out, *orig;
+ if (cmd&IPC_TIME64) {
+ out = (struct msqid_ds){0};
+ orig = buf;
+ buf = &out;
+ }
+#endif
#ifdef SYSCALL_IPC_BROKEN_MODE
struct msqid_ds tmp;
if (cmd == IPC_SET) {
@@ -32,6 +40,8 @@ int msgctl(int q, int cmd, struct msqid_ds *buf)
#endif
#if IPC_TIME64
if (r >= 0 && (cmd&IPC_TIME64)) {
+ buf = orig;
+ *buf = out;
IPC_HILO(buf, msg_stime);
IPC_HILO(buf, msg_rtime);
IPC_HILO(buf, msg_ctime);
diff --git a/src/ipc/semctl.c b/src/ipc/semctl.c
index ed982747..bbb97d7a 100644
--- a/src/ipc/semctl.c
+++ b/src/ipc/semctl.c
@@ -28,6 +28,14 @@ int semctl(int id, int num, int cmd, ...)
arg = va_arg(ap, union semun);
va_end(ap);
}
+#if IPC_TIME64
+ struct semid_ds out, *orig;
+ if (cmd&IPC_TIME64) {
+ out = (struct semid_ds){0};
+ orig = arg.buf;
+ arg.buf = &out;
+ }
+#endif
#ifdef SYSCALL_IPC_BROKEN_MODE
struct semid_ds tmp;
if (cmd == IPC_SET) {
@@ -51,6 +59,8 @@ int semctl(int id, int num, int cmd, ...)
#endif
#if IPC_TIME64
if (r >= 0 && (cmd&IPC_TIME64)) {
+ arg.buf = orig;
+ *arg.buf = out;
IPC_HILO(arg.buf, sem_otime);
IPC_HILO(arg.buf, sem_ctime);
}
diff --git a/src/ipc/shmctl.c b/src/ipc/shmctl.c
index de3ce9d4..1c9f78c2 100644
--- a/src/ipc/shmctl.c
+++ b/src/ipc/shmctl.c
@@ -9,6 +9,14 @@
int shmctl(int id, int cmd, struct shmid_ds *buf)
{
+#if IPC_TIME64
+ struct shmid_ds out, *orig;
+ if (cmd&IPC_TIME64) {
+ out = (struct shmid_ds){0};
+ orig = buf;
+ buf = &out;
+ }
+#endif
#ifdef SYSCALL_IPC_BROKEN_MODE
struct shmid_ds tmp;
if (cmd == IPC_SET) {
@@ -32,6 +40,8 @@ int shmctl(int id, int cmd, struct shmid_ds *buf)
#endif
#if IPC_TIME64
if (r >= 0 && (cmd&IPC_TIME64)) {
+ buf = orig;
+ *buf = out;
IPC_HILO(buf, shm_atime);
IPC_HILO(buf, shm_dtime);
IPC_HILO(buf, shm_ctime);
diff --git a/src/malloc/malloc.c b/src/malloc/malloc.c
index 96982596..a803d4c9 100644
--- a/src/malloc/malloc.c
+++ b/src/malloc/malloc.c
@@ -26,8 +26,11 @@ int __malloc_replaced;
static inline void lock(volatile int *lk)
{
- if (libc.threads_minus_1)
+ int need_locks = libc.need_locks;
+ if (need_locks) {
while(a_swap(lk, 1)) __wait(lk, lk+1, 1, 1);
+ if (need_locks < 0) libc.need_locks = 0;
+ }
}
static inline void unlock(volatile int *lk)
diff --git a/src/math/__expo2.c b/src/math/__expo2.c
index 740ac680..248f052b 100644
--- a/src/math/__expo2.c
+++ b/src/math/__expo2.c
@@ -5,12 +5,13 @@ static const int k = 2043;
static const double kln2 = 0x1.62066151add8bp+10;
/* exp(x)/2 for x >= log(DBL_MAX), slightly better than 0.5*exp(x/2)*exp(x/2) */
-double __expo2(double x)
+double __expo2(double x, double sign)
{
double scale;
/* note that k is odd and scale*scale overflows */
INSERT_WORDS(scale, (uint32_t)(0x3ff + k/2) << 20, 0);
/* exp(x - k ln2) * 2**(k-1) */
- return exp(x - kln2) * scale * scale;
+ /* in directed rounding correct sign before rounding or overflow is important */
+ return exp(x - kln2) * (sign * scale) * scale;
}
diff --git a/src/math/__expo2f.c b/src/math/__expo2f.c
index 5163e418..538eb09c 100644
--- a/src/math/__expo2f.c
+++ b/src/math/__expo2f.c
@@ -5,12 +5,13 @@ static const int k = 235;
static const float kln2 = 0x1.45c778p+7f;
/* expf(x)/2 for x >= log(FLT_MAX), slightly better than 0.5f*expf(x/2)*expf(x/2) */
-float __expo2f(float x)
+float __expo2f(float x, float sign)
{
float scale;
/* note that k is odd and scale*scale overflows */
SET_FLOAT_WORD(scale, (uint32_t)(0x7f + k/2) << 23);
/* exp(x - k ln2) * 2**(k-1) */
- return expf(x - kln2) * scale * scale;
+ /* in directed rounding correct sign before rounding or overflow is important */
+ return expf(x - kln2) * (sign * scale) * scale;
}
diff --git a/src/math/__rem_pio2.c b/src/math/__rem_pio2.c
index d403f81c..dcf672fb 100644
--- a/src/math/__rem_pio2.c
+++ b/src/math/__rem_pio2.c
@@ -36,6 +36,7 @@
*/
static const double
toint = 1.5/EPS,
+pio4 = 0x1.921fb54442d18p-1,
invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */
pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
@@ -117,11 +118,23 @@ int __rem_pio2(double x, double *y)
}
if (ix < 0x413921fb) { /* |x| ~< 2^20*(pi/2), medium size */
medium:
- /* rint(x/(pi/2)), Assume round-to-nearest. */
+ /* rint(x/(pi/2)) */
fn = (double_t)x*invpio2 + toint - toint;
n = (int32_t)fn;
r = x - fn*pio2_1;
w = fn*pio2_1t; /* 1st round, good to 85 bits */
+ /* Matters with directed rounding. */
+ if (predict_false(r - w < -pio4)) {
+ n--;
+ fn--;
+ r = x - fn*pio2_1;
+ w = fn*pio2_1t;
+ } else if (predict_false(r - w > pio4)) {
+ n++;
+ fn++;
+ r = x - fn*pio2_1;
+ w = fn*pio2_1t;
+ }
y[0] = r - w;
u.f = y[0];
ey = u.i>>52 & 0x7ff;
diff --git a/src/math/__rem_pio2f.c b/src/math/__rem_pio2f.c
index 4473c1c4..e6765643 100644
--- a/src/math/__rem_pio2f.c
+++ b/src/math/__rem_pio2f.c
@@ -35,6 +35,7 @@
*/
static const double
toint = 1.5/EPS,
+pio4 = 0x1.921fb6p-1,
invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
pio2_1 = 1.57079631090164184570e+00, /* 0x3FF921FB, 0x50000000 */
pio2_1t = 1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */
@@ -50,10 +51,20 @@ int __rem_pio2f(float x, double *y)
ix = u.i & 0x7fffffff;
/* 25+53 bit pi is good enough for medium size */
if (ix < 0x4dc90fdb) { /* |x| ~< 2^28*(pi/2), medium size */
- /* Use a specialized rint() to get fn. Assume round-to-nearest. */
+ /* Use a specialized rint() to get fn. */
fn = (double_t)x*invpio2 + toint - toint;
n = (int32_t)fn;
*y = x - fn*pio2_1 - fn*pio2_1t;
+ /* Matters with directed rounding. */
+ if (predict_false(*y < -pio4)) {
+ n--;
+ fn--;
+ *y = x - fn*pio2_1 - fn*pio2_1t;
+ } else if (predict_false(*y > pio4)) {
+ n++;
+ fn++;
+ *y = x - fn*pio2_1 - fn*pio2_1t;
+ }
return n;
}
if(ix>=0x7f800000) { /* x is inf or NaN */
diff --git a/src/math/__rem_pio2l.c b/src/math/__rem_pio2l.c
index 77255bd8..236b2def 100644
--- a/src/math/__rem_pio2l.c
+++ b/src/math/__rem_pio2l.c
@@ -44,6 +44,7 @@ pio2_1 = 1.57079632679597125389e+00, /* 0x3FF921FB, 0x54444000 */
pio2_2 = -1.07463465549783099519e-12, /* -0x12e7b967674000.0p-92 */
pio2_3 = 6.36831716351370313614e-25; /* 0x18a2e037074000.0p-133 */
static const long double
+pio4 = 0x1.921fb54442d1846ap-1L,
invpio2 = 6.36619772367581343076e-01L, /* 0xa2f9836e4e44152a.0p-64 */
pio2_1t = -1.07463465549719416346e-12L, /* -0x973dcb3b399d747f.0p-103 */
pio2_2t = 6.36831716351095013979e-25L, /* 0xc51701b839a25205.0p-144 */
@@ -57,6 +58,7 @@ pio2_3t = -2.75299651904407171810e-37L; /* -0xbb5bf6c7ddd660ce.0p-185 */
#define NX 5
#define NY 3
static const long double
+pio4 = 0x1.921fb54442d18469898cc51701b8p-1L,
invpio2 = 6.3661977236758134307553505349005747e-01L, /* 0x145f306dc9c882a53f84eafa3ea6a.0p-113 */
pio2_1 = 1.5707963267948966192292994253909555e+00L, /* 0x1921fb54442d18469800000000000.0p-112 */
pio2_1t = 2.0222662487959507323996846200947577e-21L, /* 0x13198a2e03707344a4093822299f3.0p-181 */
@@ -76,11 +78,23 @@ int __rem_pio2l(long double x, long double *y)
u.f = x;
ex = u.i.se & 0x7fff;
if (SMALL(u)) {
- /* rint(x/(pi/2)), Assume round-to-nearest. */
+ /* rint(x/(pi/2)) */
fn = x*invpio2 + toint - toint;
n = QUOBITS(fn);
r = x-fn*pio2_1;
w = fn*pio2_1t; /* 1st round good to 102/180 bits (ld80/ld128) */
+ /* Matters with directed rounding. */
+ if (predict_false(r - w < -pio4)) {
+ n--;
+ fn--;
+ r = x - fn*pio2_1;
+ w = fn*pio2_1t;
+ } else if (predict_false(r - w > pio4)) {
+ n++;
+ fn++;
+ r = x - fn*pio2_1;
+ w = fn*pio2_1t;
+ }
y[0] = r-w;
u.f = y[0];
ey = u.i.se & 0x7fff;
diff --git a/src/math/cosh.c b/src/math/cosh.c
index 100f8231..490c15fb 100644
--- a/src/math/cosh.c
+++ b/src/math/cosh.c
@@ -35,6 +35,6 @@ double cosh(double x)
/* |x| > log(DBL_MAX) or nan */
/* note: the result is stored to handle overflow */
- t = __expo2(x);
+ t = __expo2(x, 1.0);
return t;
}
diff --git a/src/math/coshf.c b/src/math/coshf.c
index b09f2ee5..e739cff9 100644
--- a/src/math/coshf.c
+++ b/src/math/coshf.c
@@ -28,6 +28,6 @@ float coshf(float x)
}
/* |x| > log(FLT_MAX) or nan */
- t = __expo2f(x);
+ t = __expo2f(x, 1.0f);
return t;
}
diff --git a/src/math/i386/exp.c b/src/math/i386/exp.c
deleted file mode 100644
index 11282284..00000000
--- a/src/math/i386/exp.c
+++ /dev/null
@@ -1 +0,0 @@
-// see exp_ld.s
diff --git a/src/math/i386/exp2.s b/src/math/i386/exp2.s
deleted file mode 100644
index f335a3e5..00000000
--- a/src/math/i386/exp2.s
+++ /dev/null
@@ -1 +0,0 @@
-# see exp.s
diff --git a/src/math/i386/exp2f.s b/src/math/i386/exp2f.s
deleted file mode 100644
index f335a3e5..00000000
--- a/src/math/i386/exp2f.s
+++ /dev/null
@@ -1 +0,0 @@
-# see exp.s
diff --git a/src/math/i386/exp2l.s b/src/math/i386/exp2l.s
index f335a3e5..8125761d 100644
--- a/src/math/i386/exp2l.s
+++ b/src/math/i386/exp2l.s
@@ -1 +1 @@
-# see exp.s
+# see exp_ld.s
diff --git a/src/math/i386/exp_ld.s b/src/math/i386/exp_ld.s
index df87c497..99cba01f 100644
--- a/src/math/i386/exp_ld.s
+++ b/src/math/i386/exp_ld.s
@@ -1,35 +1,8 @@
-.global expm1f
-.type expm1f,@function
-expm1f:
- flds 4(%esp)
- mov 4(%esp),%eax
- add %eax,%eax
- cmp $0x01000000,%eax
- jae 1f
- # subnormal x, return x with underflow
- fld %st(0)
- fmul %st(1)
- fstps 4(%esp)
- ret
-
.global expm1l
.type expm1l,@function
expm1l:
fldt 4(%esp)
- jmp 1f
-
-.global expm1
-.type expm1,@function
-expm1:
- fldl 4(%esp)
- mov 8(%esp),%eax
- add %eax,%eax
- cmp $0x00200000,%eax
- jae 1f
- # subnormal x, return x with underflow
- fsts 4(%esp)
- ret
-1: fldl2e
+ fldl2e
fmulp
mov $0xc2820000,%eax
push %eax
@@ -59,12 +32,6 @@ expm1:
fsubrp
ret
-.global exp2f
-.type exp2f,@function
-exp2f:
- flds 4(%esp)
- jmp 1f
-
.global exp2l
.global __exp2l
.hidden __exp2l
@@ -72,26 +39,6 @@ exp2f:
exp2l:
__exp2l:
fldt 4(%esp)
- jmp 1f
-
-.global expf
-.type expf,@function
-expf:
- flds 4(%esp)
- jmp 2f
-
-.global exp
-.type exp,@function
-exp:
- fldl 4(%esp)
-2: fldl2e
- fmulp
- jmp 1f
-
-.global exp2
-.type exp2,@function
-exp2:
- fldl 4(%esp)
1: sub $12,%esp
fld %st(0)
fstpt (%esp)
diff --git a/src/math/i386/expf.s b/src/math/i386/expf.s
deleted file mode 100644
index f335a3e5..00000000
--- a/src/math/i386/expf.s
+++ /dev/null
@@ -1 +0,0 @@
-# see exp.s
diff --git a/src/math/i386/expm1.s b/src/math/i386/expm1.s
deleted file mode 100644
index f335a3e5..00000000
--- a/src/math/i386/expm1.s
+++ /dev/null
@@ -1 +0,0 @@
-# see exp.s
diff --git a/src/math/i386/expm1f.s b/src/math/i386/expm1f.s
deleted file mode 100644
index f335a3e5..00000000
--- a/src/math/i386/expm1f.s
+++ /dev/null
@@ -1 +0,0 @@
-# see exp.s
diff --git a/src/math/i386/expm1l.s b/src/math/i386/expm1l.s
index f335a3e5..8125761d 100644
--- a/src/math/i386/expm1l.s
+++ b/src/math/i386/expm1l.s
@@ -1 +1 @@
-# see exp.s
+# see exp_ld.s
diff --git a/src/math/i386/fabs.c b/src/math/i386/fabs.c
new file mode 100644
index 00000000..39672786
--- /dev/null
+++ b/src/math/i386/fabs.c
@@ -0,0 +1,7 @@
+#include <math.h>
+
+double fabs(double x)
+{
+ __asm__ ("fabs" : "+t"(x));
+ return x;
+}
diff --git a/src/math/i386/fabs.s b/src/math/i386/fabs.s
deleted file mode 100644
index d66ea9a1..00000000
--- a/src/math/i386/fabs.s
+++ /dev/null
@@ -1,6 +0,0 @@
-.global fabs
-.type fabs,@function
-fabs:
- fldl 4(%esp)
- fabs
- ret
diff --git a/src/math/i386/fabsf.c b/src/math/i386/fabsf.c
new file mode 100644
index 00000000..d882eee3
--- /dev/null
+++ b/src/math/i386/fabsf.c
@@ -0,0 +1,7 @@
+#include <math.h>
+
+float fabsf(float x)
+{
+ __asm__ ("fabs" : "+t"(x));
+ return x;
+}
diff --git a/src/math/i386/fabsf.s b/src/math/i386/fabsf.s
deleted file mode 100644
index a981c422..00000000
--- a/src/math/i386/fabsf.s
+++ /dev/null
@@ -1,6 +0,0 @@
-.global fabsf
-.type fabsf,@function
-fabsf:
- flds 4(%esp)
- fabs
- ret
diff --git a/src/math/i386/fabsl.c b/src/math/i386/fabsl.c
new file mode 100644
index 00000000..cc1c9ed9
--- /dev/null
+++ b/src/math/i386/fabsl.c
@@ -0,0 +1,7 @@
+#include <math.h>
+
+long double fabsl(long double x)
+{
+ __asm__ ("fabs" : "+t"(x));
+ return x;
+}
diff --git a/src/math/i386/fabsl.s b/src/math/i386/fabsl.s
deleted file mode 100644
index ceef9e4c..00000000
--- a/src/math/i386/fabsl.s
+++ /dev/null
@@ -1,6 +0,0 @@
-.global fabsl
-.type fabsl,@function
-fabsl:
- fldt 4(%esp)
- fabs
- ret
diff --git a/src/math/i386/fmod.c b/src/math/i386/fmod.c
new file mode 100644
index 00000000..ea0c58d9
--- /dev/null
+++ b/src/math/i386/fmod.c
@@ -0,0 +1,10 @@
+#include <math.h>
+
+double fmod(double x, double y)
+{
+ unsigned short fpsr;
+ // fprem does not introduce excess precision into x
+ do __asm__ ("fprem; fnstsw %%ax" : "+t"(x), "=a"(fpsr) : "u"(y));
+ while (fpsr & 0x400);
+ return x;
+}
diff --git a/src/math/i386/fmod.s b/src/math/i386/fmod.s
deleted file mode 100644
index 2113b3c5..00000000
--- a/src/math/i386/fmod.s
+++ /dev/null
@@ -1,11 +0,0 @@
-.global fmod
-.type fmod,@function
-fmod:
- fldl 12(%esp)
- fldl 4(%esp)
-1: fprem
- fnstsw %ax
- sahf
- jp 1b
- fstp %st(1)
- ret
diff --git a/src/math/i386/fmodf.c b/src/math/i386/fmodf.c
new file mode 100644
index 00000000..90b56ab0
--- /dev/null
+++ b/src/math/i386/fmodf.c
@@ -0,0 +1,10 @@
+#include <math.h>
+
+float fmodf(float x, float y)
+{
+ unsigned short fpsr;
+ // fprem does not introduce excess precision into x
+ do __asm__ ("fprem; fnstsw %%ax" : "+t"(x), "=a"(fpsr) : "u"(y));
+ while (fpsr & 0x400);
+ return x;
+}
diff --git a/src/math/i386/fmodf.s b/src/math/i386/fmodf.s
deleted file mode 100644
index e04e2a56..00000000
--- a/src/math/i386/fmodf.s
+++ /dev/null
@@ -1,11 +0,0 @@
-.global fmodf
-.type fmodf,@function
-fmodf:
- flds 8(%esp)
- flds 4(%esp)
-1: fprem
- fnstsw %ax
- sahf
- jp 1b
- fstp %st(1)
- ret
diff --git a/src/math/i386/fmodl.c b/src/math/i386/fmodl.c
new file mode 100644
index 00000000..3daeab06
--- /dev/null
+++ b/src/math/i386/fmodl.c
@@ -0,0 +1,9 @@
+#include <math.h>
+
+long double fmodl(long double x, long double y)
+{
+ unsigned short fpsr;
+ do __asm__ ("fprem; fnstsw %%ax" : "+t"(x), "=a"(fpsr) : "u"(y));
+ while (fpsr & 0x400);
+ return x;
+}
diff --git a/src/math/i386/fmodl.s b/src/math/i386/fmodl.s
deleted file mode 100644
index 0cb3fe9b..00000000
--- a/src/math/i386/fmodl.s
+++ /dev/null
@@ -1,11 +0,0 @@
-.global fmodl
-.type fmodl,@function
-fmodl:
- fldt 16(%esp)
- fldt 4(%esp)
-1: fprem
- fnstsw %ax
- sahf
- jp 1b
- fstp %st(1)
- ret
diff --git a/src/math/i386/llrint.c b/src/math/i386/llrint.c
new file mode 100644
index 00000000..aa400817
--- /dev/null
+++ b/src/math/i386/llrint.c
@@ -0,0 +1,8 @@
+#include <math.h>
+
+long long llrint(double x)
+{
+ long long r;
+ __asm__ ("fistpll %0" : "=m"(r) : "t"(x) : "st");
+ return r;
+}
diff --git a/src/math/i386/llrint.s b/src/math/i386/llrint.s
deleted file mode 100644
index 8e89cd91..00000000
--- a/src/math/i386/llrint.s
+++ /dev/null
@@ -1,8 +0,0 @@
-.global llrint
-.type llrint,@function
-llrint:
- fldl 4(%esp)
- fistpll 4(%esp)
- mov 4(%esp),%eax
- mov 8(%esp),%edx
- ret
diff --git a/src/math/i386/llrintf.c b/src/math/i386/llrintf.c
new file mode 100644
index 00000000..c41a317b
--- /dev/null
+++ b/src/math/i386/llrintf.c
@@ -0,0 +1,8 @@
+#include <math.h>
+
+long long llrintf(float x)
+{
+ long long r;
+ __asm__ ("fistpll %0" : "=m"(r) : "t"(x) : "st");
+ return r;
+}
diff --git a/src/math/i386/llrintf.s b/src/math/i386/llrintf.s
deleted file mode 100644
index aa850c6c..00000000
--- a/src/math/i386/llrintf.s
+++ /dev/null
@@ -1,9 +0,0 @@
-.global llrintf
-.type llrintf,@function
-llrintf:
- sub $8,%esp
- flds 12(%esp)
- fistpll (%esp)
- pop %eax
- pop %edx
- ret
diff --git a/src/math/i386/llrintl.c b/src/math/i386/llrintl.c
new file mode 100644
index 00000000..c439ef28
--- /dev/null
+++ b/src/math/i386/llrintl.c
@@ -0,0 +1,8 @@
+#include <math.h>
+
+long long llrintl(long double x)
+{
+ long long r;
+ __asm__ ("fistpll %0" : "=m"(r) : "t"(x) : "st");
+ return r;
+}
diff --git a/src/math/i386/llrintl.s b/src/math/i386/llrintl.s
deleted file mode 100644
index 1cfb56f1..00000000
--- a/src/math/i386/llrintl.s
+++ /dev/null
@@ -1,8 +0,0 @@
-.global llrintl
-.type llrintl,@function
-llrintl:
- fldt 4(%esp)
- fistpll 4(%esp)
- mov 4(%esp),%eax
- mov 8(%esp),%edx
- ret
diff --git a/src/math/i386/lrint.c b/src/math/i386/lrint.c
new file mode 100644
index 00000000..89563ab2
--- /dev/null
+++ b/src/math/i386/lrint.c
@@ -0,0 +1,8 @@
+#include <math.h>
+
+long lrint(double x)
+{
+ long r;
+ __asm__ ("fistpl %0" : "=m"(r) : "t"(x) : "st");
+ return r;
+}
diff --git a/src/math/i386/lrint.s b/src/math/i386/lrint.s
deleted file mode 100644
index 02b83d9f..00000000
--- a/src/math/i386/lrint.s
+++ /dev/null
@@ -1,7 +0,0 @@
-.global lrint
-.type lrint,@function
-lrint:
- fldl 4(%esp)
- fistpl 4(%esp)
- mov 4(%esp),%eax
- ret
diff --git a/src/math/i386/lrintf.c b/src/math/i386/lrintf.c
new file mode 100644
index 00000000..0bbf29de
--- /dev/null
+++ b/src/math/i386/lrintf.c
@@ -0,0 +1,8 @@
+#include <math.h>
+
+long lrintf(float x)
+{
+ long r;
+ __asm__ ("fistpl %0" : "=m"(r) : "t"(x) : "st");
+ return r;
+}
diff --git a/src/math/i386/lrintf.s b/src/math/i386/lrintf.s
deleted file mode 100644
index 907aac29..00000000
--- a/src/math/i386/lrintf.s
+++ /dev/null
@@ -1,7 +0,0 @@
-.global lrintf
-.type lrintf,@function
-lrintf:
- flds 4(%esp)
- fistpl 4(%esp)
- mov 4(%esp),%eax
- ret
diff --git a/src/math/i386/lrintl.c b/src/math/i386/lrintl.c
new file mode 100644
index 00000000..eb8c0902
--- /dev/null
+++ b/src/math/i386/lrintl.c
@@ -0,0 +1,8 @@
+#include <math.h>
+
+long lrintl(long double x)
+{
+ long r;
+ __asm__ ("fistpl %0" : "=m"(r) : "t"(x) : "st");
+ return r;
+}
diff --git a/src/math/i386/lrintl.s b/src/math/i386/lrintl.s
deleted file mode 100644
index 3ae05aac..00000000
--- a/src/math/i386/lrintl.s
+++ /dev/null
@@ -1,7 +0,0 @@
-.global lrintl
-.type lrintl,@function
-lrintl:
- fldt 4(%esp)
- fistpl 4(%esp)
- mov 4(%esp),%eax
- ret
diff --git a/src/math/i386/remainder.c b/src/math/i386/remainder.c
new file mode 100644
index 00000000..c083df90
--- /dev/null
+++ b/src/math/i386/remainder.c
@@ -0,0 +1,12 @@
+#include <math.h>
+
+double remainder(double x, double y)
+{
+ unsigned short fpsr;
+ // fprem1 does not introduce excess precision into x
+ do __asm__ ("fprem1; fnstsw %%ax" : "+t"(x), "=a"(fpsr) : "u"(y));
+ while (fpsr & 0x400);
+ return x;
+}
+
+weak_alias(remainder, drem);
diff --git a/src/math/i386/remainder.s b/src/math/i386/remainder.s
deleted file mode 100644
index ab1da95d..00000000
--- a/src/math/i386/remainder.s
+++ /dev/null
@@ -1,14 +0,0 @@
-.global remainder
-.type remainder,@function
-remainder:
-.weak drem
-.type drem,@function
-drem:
- fldl 12(%esp)
- fldl 4(%esp)
-1: fprem1
- fnstsw %ax
- sahf
- jp 1b
- fstp %st(1)
- ret
diff --git a/src/math/i386/remainderf.c b/src/math/i386/remainderf.c
new file mode 100644
index 00000000..280207d2
--- /dev/null
+++ b/src/math/i386/remainderf.c
@@ -0,0 +1,12 @@
+#include <math.h>
+
+float remainderf(float x, float y)
+{
+ unsigned short fpsr;
+ // fprem1 does not introduce excess precision into x
+ do __asm__ ("fprem1; fnstsw %%ax" : "+t"(x), "=a"(fpsr) : "u"(y));
+ while (fpsr & 0x400);
+ return x;
+}
+
+weak_alias(remainderf, dremf);
diff --git a/src/math/i386/remainderf.s b/src/math/i386/remainderf.s
deleted file mode 100644
index 6a7378a3..00000000
--- a/src/math/i386/remainderf.s
+++ /dev/null
@@ -1,14 +0,0 @@
-.global remainderf
-.type remainderf,@function
-remainderf:
-.weak dremf
-.type dremf,@function
-dremf:
- flds 8(%esp)
- flds 4(%esp)
-1: fprem1
- fnstsw %ax
- sahf
- jp 1b
- fstp %st(1)
- ret
diff --git a/src/math/i386/remainderl.c b/src/math/i386/remainderl.c
new file mode 100644
index 00000000..8cf75071
--- /dev/null
+++ b/src/math/i386/remainderl.c
@@ -0,0 +1,9 @@
+#include <math.h>
+
+long double remainderl(long double x, long double y)
+{
+ unsigned short fpsr;
+ do __asm__ ("fprem1; fnstsw %%ax" : "+t"(x), "=a"(fpsr) : "u"(y));
+ while (fpsr & 0x400);
+ return x;
+}
diff --git a/src/math/i386/remainderl.s b/src/math/i386/remainderl.s
deleted file mode 100644
index b41518ed..00000000
--- a/src/math/i386/remainderl.s
+++ /dev/null
@@ -1,11 +0,0 @@
-.global remainderl
-.type remainderl,@function
-remainderl:
- fldt 16(%esp)
- fldt 4(%esp)
-1: fprem1
- fnstsw %ax
- sahf
- jp 1b
- fstp %st(1)
- ret
diff --git a/src/math/i386/rint.c b/src/math/i386/rint.c
new file mode 100644
index 00000000..a5276a60
--- /dev/null
+++ b/src/math/i386/rint.c
@@ -0,0 +1,7 @@
+#include <math.h>
+
+double rint(double x)
+{
+ __asm__ ("frndint" : "+t"(x));
+ return x;
+}
diff --git a/src/math/i386/rint.s b/src/math/i386/rint.s
deleted file mode 100644
index bb99a11c..00000000
--- a/src/math/i386/rint.s
+++ /dev/null
@@ -1,6 +0,0 @@
-.global rint
-.type rint,@function
-rint:
- fldl 4(%esp)
- frndint
- ret
diff --git a/src/math/i386/rintf.c b/src/math/i386/rintf.c
new file mode 100644
index 00000000..bb4121a4
--- /dev/null
+++ b/src/math/i386/rintf.c
@@ -0,0 +1,7 @@
+#include <math.h>
+
+float rintf(float x)
+{
+ __asm__ ("frndint" : "+t"(x));
+ return x;
+}
diff --git a/src/math/i386/rintf.s b/src/math/i386/rintf.s
deleted file mode 100644
index bce4c5a6..00000000
--- a/src/math/i386/rintf.s
+++ /dev/null
@@ -1,6 +0,0 @@
-.global rintf
-.type rintf,@function
-rintf:
- flds 4(%esp)
- frndint
- ret
diff --git a/src/math/i386/rintl.c b/src/math/i386/rintl.c
new file mode 100644
index 00000000..e1a92077
--- /dev/null
+++ b/src/math/i386/rintl.c
@@ -0,0 +1,7 @@
+#include <math.h>
+
+long double rintl(long double x)
+{
+ __asm__ ("frndint" : "+t"(x));
+ return x;
+}
diff --git a/src/math/i386/rintl.s b/src/math/i386/rintl.s
deleted file mode 100644
index cd2bf9a9..00000000
--- a/src/math/i386/rintl.s
+++ /dev/null
@@ -1,6 +0,0 @@
-.global rintl
-.type rintl,@function
-rintl:
- fldt 4(%esp)
- frndint
- ret
diff --git a/src/math/i386/sqrt.c b/src/math/i386/sqrt.c
new file mode 100644
index 00000000..934fbcca
--- /dev/null
+++ b/src/math/i386/sqrt.c
@@ -0,0 +1,15 @@
+#include "libm.h"
+
+double sqrt(double x)
+{
+ union ldshape ux;
+ unsigned fpsr;
+ __asm__ ("fsqrt; fnstsw %%ax": "=t"(ux.f), "=a"(fpsr) : "0"(x));
+ if ((ux.i.m & 0x7ff) != 0x400)
+ return (double)ux.f;
+ /* Rounding to double would have encountered an exact halfway case.
+ Adjust mantissa downwards if fsqrt rounded up, else upwards.
+ (result of fsqrt could not have been exact) */
+ ux.i.m ^= (fpsr & 0x200) + 0x300;
+ return (double)ux.f;
+}
diff --git a/src/math/i386/sqrt.s b/src/math/i386/sqrt.s
deleted file mode 100644
index 57837e25..00000000
--- a/src/math/i386/sqrt.s
+++ /dev/null
@@ -1,21 +0,0 @@
-.global sqrt
-.type sqrt,@function
-sqrt: fldl 4(%esp)
- fsqrt
- fnstsw %ax
- sub $12,%esp
- fld %st(0)
- fstpt (%esp)
- mov (%esp),%ecx
- and $0x7ff,%ecx
- cmp $0x400,%ecx
- jnz 1f
- and $0x200,%eax
- sub $0x100,%eax
- sub %eax,(%esp)
- fstp %st(0)
- fldt (%esp)
-1: add $12,%esp
- fstpl 4(%esp)
- fldl 4(%esp)
- ret
diff --git a/src/math/i386/sqrtf.c b/src/math/i386/sqrtf.c
new file mode 100644
index 00000000..41c65c2b
--- /dev/null
+++ b/src/math/i386/sqrtf.c
@@ -0,0 +1,12 @@
+#include <math.h>
+
+float sqrtf(float x)
+{
+ long double t;
+ /* The long double result has sufficient precision so that
+ * second rounding to float still keeps the returned value
+ * correctly rounded, see Pierre Roux, "Innocuous Double
+ * Rounding of Basic Arithmetic Operations". */
+ __asm__ ("fsqrt" : "=t"(t) : "0"(x));
+ return (float)t;
+}
diff --git a/src/math/i386/sqrtf.s b/src/math/i386/sqrtf.s
deleted file mode 100644
index 9e944f45..00000000
--- a/src/math/i386/sqrtf.s
+++ /dev/null
@@ -1,7 +0,0 @@
-.global sqrtf
-.type sqrtf,@function
-sqrtf: flds 4(%esp)
- fsqrt
- fstps 4(%esp)
- flds 4(%esp)
- ret
diff --git a/src/math/i386/sqrtl.c b/src/math/i386/sqrtl.c
new file mode 100644
index 00000000..864cfcc4
--- /dev/null
+++ b/src/math/i386/sqrtl.c
@@ -0,0 +1,7 @@
+#include <math.h>
+
+long double sqrtl(long double x)
+{
+ __asm__ ("fsqrt" : "+t"(x));
+ return x;
+}
diff --git a/src/math/i386/sqrtl.s b/src/math/i386/sqrtl.s
deleted file mode 100644
index e0d42616..00000000
--- a/src/math/i386/sqrtl.s
+++ /dev/null
@@ -1,5 +0,0 @@
-.global sqrtl
-.type sqrtl,@function
-sqrtl: fldt 4(%esp)
- fsqrt
- ret
diff --git a/src/math/sinh.c b/src/math/sinh.c
index 00022c4e..a01951ae 100644
--- a/src/math/sinh.c
+++ b/src/math/sinh.c
@@ -34,6 +34,6 @@ double sinh(double x)
/* |x| > log(DBL_MAX) or nan */
/* note: the result is stored to handle overflow */
- t = 2*h*__expo2(absx);
+ t = __expo2(absx, 2*h);
return t;
}
diff --git a/src/math/sinhf.c b/src/math/sinhf.c
index 6ad19ea2..b9caa793 100644
--- a/src/math/sinhf.c
+++ b/src/math/sinhf.c
@@ -26,6 +26,6 @@ float sinhf(float x)
}
/* |x| > logf(FLT_MAX) or nan */
- t = 2*h*__expo2f(absx);
+ t = __expo2f(absx, 2*h);
return t;
}
diff --git a/src/math/x86_64/fabs.c b/src/math/x86_64/fabs.c
new file mode 100644
index 00000000..16562477
--- /dev/null
+++ b/src/math/x86_64/fabs.c
@@ -0,0 +1,10 @@
+#include <math.h>
+
+double fabs(double x)
+{
+ double t;
+ __asm__ ("pcmpeqd %0, %0" : "=x"(t)); // t = ~0
+ __asm__ ("psrlq $1, %0" : "+x"(t)); // t >>= 1
+ __asm__ ("andps %1, %0" : "+x"(x) : "x"(t)); // x &= t
+ return x;
+}
diff --git a/src/math/x86_64/fabs.s b/src/math/x86_64/fabs.s
deleted file mode 100644
index 5715005e..00000000
--- a/src/math/x86_64/fabs.s
+++ /dev/null
@@ -1,9 +0,0 @@
-.global fabs
-.type fabs,@function
-fabs:
- xor %eax,%eax
- dec %rax
- shr %rax
- movq %rax,%xmm1
- andpd %xmm1,%xmm0
- ret
diff --git a/src/math/x86_64/fabsf.c b/src/math/x86_64/fabsf.c
new file mode 100644
index 00000000..36ea7481
--- /dev/null
+++ b/src/math/x86_64/fabsf.c
@@ -0,0 +1,10 @@
+#include <math.h>
+
+float fabsf(float x)
+{
+ float t;
+ __asm__ ("pcmpeqd %0, %0" : "=x"(t)); // t = ~0
+ __asm__ ("psrld $1, %0" : "+x"(t)); // t >>= 1
+ __asm__ ("andps %1, %0" : "+x"(x) : "x"(t)); // x &= t
+ return x;
+}
diff --git a/src/math/x86_64/fabsf.s b/src/math/x86_64/fabsf.s
deleted file mode 100644
index 501a1f17..00000000
--- a/src/math/x86_64/fabsf.s
+++ /dev/null
@@ -1,7 +0,0 @@
-.global fabsf
-.type fabsf,@function
-fabsf:
- mov $0x7fffffff,%eax
- movq %rax,%xmm1
- andps %xmm1,%xmm0
- ret
diff --git a/src/math/x86_64/fabsl.c b/src/math/x86_64/fabsl.c
new file mode 100644
index 00000000..cc1c9ed9
--- /dev/null
+++ b/src/math/x86_64/fabsl.c
@@ -0,0 +1,7 @@
+#include <math.h>
+
+long double fabsl(long double x)
+{
+ __asm__ ("fabs" : "+t"(x));
+ return x;
+}
diff --git a/src/math/x86_64/fabsl.s b/src/math/x86_64/fabsl.s
deleted file mode 100644
index 4e7ab525..00000000
--- a/src/math/x86_64/fabsl.s
+++ /dev/null
@@ -1,6 +0,0 @@
-.global fabsl
-.type fabsl,@function
-fabsl:
- fldt 8(%rsp)
- fabs
- ret
diff --git a/src/math/x86_64/fmodl.c b/src/math/x86_64/fmodl.c
new file mode 100644
index 00000000..3daeab06
--- /dev/null
+++ b/src/math/x86_64/fmodl.c
@@ -0,0 +1,9 @@
+#include <math.h>
+
+long double fmodl(long double x, long double y)
+{
+ unsigned short fpsr;
+ do __asm__ ("fprem; fnstsw %%ax" : "+t"(x), "=a"(fpsr) : "u"(y));
+ while (fpsr & 0x400);
+ return x;
+}
diff --git a/src/math/x86_64/fmodl.s b/src/math/x86_64/fmodl.s
deleted file mode 100644
index ea07b402..00000000
--- a/src/math/x86_64/fmodl.s
+++ /dev/null
@@ -1,11 +0,0 @@
-.global fmodl
-.type fmodl,@function
-fmodl:
- fldt 24(%rsp)
- fldt 8(%rsp)
-1: fprem
- fnstsw %ax
- testb $4,%ah
- jnz 1b
- fstp %st(1)
- ret
diff --git a/src/math/x86_64/llrint.c b/src/math/x86_64/llrint.c
new file mode 100644
index 00000000..dd38a722
--- /dev/null
+++ b/src/math/x86_64/llrint.c
@@ -0,0 +1,8 @@
+#include <math.h>
+
+long long llrint(double x)
+{
+ long long r;
+ __asm__ ("cvtsd2si %1, %0" : "=r"(r) : "x"(x));
+ return r;
+}
diff --git a/src/math/x86_64/llrint.s b/src/math/x86_64/llrint.s
deleted file mode 100644
index bf476498..00000000
--- a/src/math/x86_64/llrint.s
+++ /dev/null
@@ -1,5 +0,0 @@
-.global llrint
-.type llrint,@function
-llrint:
- cvtsd2si %xmm0,%rax
- ret
diff --git a/src/math/x86_64/llrintf.c b/src/math/x86_64/llrintf.c
new file mode 100644
index 00000000..fc8625e8
--- /dev/null
+++ b/src/math/x86_64/llrintf.c
@@ -0,0 +1,8 @@
+#include <math.h>
+
+long long llrintf(float x)
+{
+ long long r;
+ __asm__ ("cvtss2si %1, %0" : "=r"(r) : "x"(x));
+ return r;
+}
diff --git a/src/math/x86_64/llrintf.s b/src/math/x86_64/llrintf.s
deleted file mode 100644
index d7204ac0..00000000
--- a/src/math/x86_64/llrintf.s
+++ /dev/null
@@ -1,5 +0,0 @@
-.global llrintf
-.type llrintf,@function
-llrintf:
- cvtss2si %xmm0,%rax
- ret
diff --git a/src/math/x86_64/llrintl.c b/src/math/x86_64/llrintl.c
new file mode 100644
index 00000000..c439ef28
--- /dev/null
+++ b/src/math/x86_64/llrintl.c
@@ -0,0 +1,8 @@
+#include <math.h>
+
+long long llrintl(long double x)
+{
+ long long r;
+ __asm__ ("fistpll %0" : "=m"(r) : "t"(x) : "st");
+ return r;
+}
diff --git a/src/math/x86_64/llrintl.s b/src/math/x86_64/llrintl.s
deleted file mode 100644
index 1ec0817d..00000000
--- a/src/math/x86_64/llrintl.s
+++ /dev/null
@@ -1,7 +0,0 @@
-.global llrintl
-.type llrintl,@function
-llrintl:
- fldt 8(%rsp)
- fistpll 8(%rsp)
- mov 8(%rsp),%rax
- ret
diff --git a/src/math/x86_64/lrint.c b/src/math/x86_64/lrint.c
new file mode 100644
index 00000000..a742fec6
--- /dev/null
+++ b/src/math/x86_64/lrint.c
@@ -0,0 +1,8 @@
+#include <math.h>
+
+long lrint(double x)
+{
+ long r;
+ __asm__ ("cvtsd2si %1, %0" : "=r"(r) : "x"(x));
+ return r;
+}
diff --git a/src/math/x86_64/lrint.s b/src/math/x86_64/lrint.s
deleted file mode 100644
index 15fc2454..00000000
--- a/src/math/x86_64/lrint.s
+++ /dev/null
@@ -1,5 +0,0 @@
-.global lrint
-.type lrint,@function
-lrint:
- cvtsd2si %xmm0,%rax
- ret
diff --git a/src/math/x86_64/lrintf.c b/src/math/x86_64/lrintf.c
new file mode 100644
index 00000000..2ba5639d
--- /dev/null
+++ b/src/math/x86_64/lrintf.c
@@ -0,0 +1,8 @@
+#include <math.h>
+
+long lrintf(float x)
+{
+ long r;
+ __asm__ ("cvtss2si %1, %0" : "=r"(r) : "x"(x));
+ return r;
+}
diff --git a/src/math/x86_64/lrintf.s b/src/math/x86_64/lrintf.s
deleted file mode 100644
index 488423d2..00000000
--- a/src/math/x86_64/lrintf.s
+++ /dev/null
@@ -1,5 +0,0 @@
-.global lrintf
-.type lrintf,@function
-lrintf:
- cvtss2si %xmm0,%rax
- ret
diff --git a/src/math/x86_64/lrintl.c b/src/math/x86_64/lrintl.c
new file mode 100644
index 00000000..068e2e4d
--- /dev/null
+++ b/src/math/x86_64/lrintl.c
@@ -0,0 +1,8 @@
+#include <math.h>
+
+long lrintl(long double x)
+{
+ long r;
+ __asm__ ("fistpll %0" : "=m"(r) : "t"(x) : "st");
+ return r;
+}
diff --git a/src/math/x86_64/lrintl.s b/src/math/x86_64/lrintl.s
deleted file mode 100644
index d587b12b..00000000
--- a/src/math/x86_64/lrintl.s
+++ /dev/null
@@ -1,7 +0,0 @@
-.global lrintl
-.type lrintl,@function
-lrintl:
- fldt 8(%rsp)
- fistpll 8(%rsp)
- mov 8(%rsp),%rax
- ret
diff --git a/src/math/x86_64/remainderl.c b/src/math/x86_64/remainderl.c
new file mode 100644
index 00000000..8cf75071
--- /dev/null
+++ b/src/math/x86_64/remainderl.c
@@ -0,0 +1,9 @@
+#include <math.h>
+
+long double remainderl(long double x, long double y)
+{
+ unsigned short fpsr;
+ do __asm__ ("fprem1; fnstsw %%ax" : "+t"(x), "=a"(fpsr) : "u"(y));
+ while (fpsr & 0x400);
+ return x;
+}
diff --git a/src/math/x86_64/remainderl.s b/src/math/x86_64/remainderl.s
deleted file mode 100644
index cb3857b4..00000000
--- a/src/math/x86_64/remainderl.s
+++ /dev/null
@@ -1,11 +0,0 @@
-.global remainderl
-.type remainderl,@function
-remainderl:
- fldt 24(%rsp)
- fldt 8(%rsp)
-1: fprem1
- fnstsw %ax
- testb $4,%ah
- jnz 1b
- fstp %st(1)
- ret
diff --git a/src/math/x86_64/remquol.c b/src/math/x86_64/remquol.c
new file mode 100644
index 00000000..60eef089
--- /dev/null
+++ b/src/math/x86_64/remquol.c
@@ -0,0 +1,32 @@
+#include <math.h>
+
+long double remquol(long double x, long double y, int *quo)
+{
+ signed char *cx = (void *)&x, *cy = (void *)&y;
+ /* By ensuring that addresses of x and y cannot be discarded,
+ * this empty asm guides GCC into representing extraction of
+ * their sign bits as memory loads rather than making x and y
+ * not-address-taken internally and using bitfield operations,
+ * which in the end wouldn't work out, as extraction from FPU
+ * registers needs to go through memory anyway. This way GCC
+ * should manage to use incoming stack slots without spills. */
+ __asm__ ("" :: "X"(cx), "X"(cy));
+
+ long double t = x;
+ unsigned fpsr;
+ do __asm__ ("fprem1; fnstsw %%ax" : "+t"(t), "=a"(fpsr) : "u"(y));
+ while (fpsr & 0x400);
+ /* C0, C1, C3 flags in x87 status word carry low bits of quotient:
+ * 15 14 13 12 11 10 9 8
+ * . C3 . . . C2 C1 C0
+ * . b1 . . . 0 b0 b2 */
+ unsigned char i = fpsr >> 8;
+ i = i>>4 | i<<4;
+ /* i[5:2] is now {b0 b2 ? b1}. Retrieve {0 b2 b1 b0} via
+ * in-register table lookup. */
+ unsigned qbits = 0x7575313164642020 >> (i & 60);
+ qbits &= 7;
+
+ *quo = (cx[9]^cy[9]) < 0 ? -qbits : qbits;
+ return t;
+}
diff --git a/src/math/x86_64/rintl.c b/src/math/x86_64/rintl.c
new file mode 100644
index 00000000..e1a92077
--- /dev/null
+++ b/src/math/x86_64/rintl.c
@@ -0,0 +1,7 @@
+#include <math.h>
+
+long double rintl(long double x)
+{
+ __asm__ ("frndint" : "+t"(x));
+ return x;
+}
diff --git a/src/math/x86_64/rintl.s b/src/math/x86_64/rintl.s
deleted file mode 100644
index 64e663cd..00000000
--- a/src/math/x86_64/rintl.s
+++ /dev/null
@@ -1,6 +0,0 @@
-.global rintl
-.type rintl,@function
-rintl:
- fldt 8(%rsp)
- frndint
- ret
diff --git a/src/math/x86_64/sqrt.c b/src/math/x86_64/sqrt.c
new file mode 100644
index 00000000..657e09e3
--- /dev/null
+++ b/src/math/x86_64/sqrt.c
@@ -0,0 +1,7 @@
+#include <math.h>
+
+double sqrt(double x)
+{
+ __asm__ ("sqrtsd %1, %0" : "=x"(x) : "x"(x));
+ return x;
+}
diff --git a/src/math/x86_64/sqrt.s b/src/math/x86_64/sqrt.s
deleted file mode 100644
index d3c609f9..00000000
--- a/src/math/x86_64/sqrt.s
+++ /dev/null
@@ -1,4 +0,0 @@
-.global sqrt
-.type sqrt,@function
-sqrt: sqrtsd %xmm0, %xmm0
- ret
diff --git a/src/math/x86_64/sqrtf.c b/src/math/x86_64/sqrtf.c
new file mode 100644
index 00000000..720baec6
--- /dev/null
+++ b/src/math/x86_64/sqrtf.c
@@ -0,0 +1,7 @@
+#include <math.h>
+
+float sqrtf(float x)
+{
+ __asm__ ("sqrtss %1, %0" : "=x"(x) : "x"(x));
+ return x;
+}
diff --git a/src/math/x86_64/sqrtf.s b/src/math/x86_64/sqrtf.s
deleted file mode 100644
index eec48c60..00000000
--- a/src/math/x86_64/sqrtf.s
+++ /dev/null
@@ -1,4 +0,0 @@
-.global sqrtf
-.type sqrtf,@function
-sqrtf: sqrtss %xmm0, %xmm0
- ret
diff --git a/src/math/x86_64/sqrtl.c b/src/math/x86_64/sqrtl.c
new file mode 100644
index 00000000..864cfcc4
--- /dev/null
+++ b/src/math/x86_64/sqrtl.c
@@ -0,0 +1,7 @@
+#include <math.h>
+
+long double sqrtl(long double x)
+{
+ __asm__ ("fsqrt" : "+t"(x));
+ return x;
+}
diff --git a/src/math/x86_64/sqrtl.s b/src/math/x86_64/sqrtl.s
deleted file mode 100644
index 23cd687d..00000000
--- a/src/math/x86_64/sqrtl.s
+++ /dev/null
@@ -1,5 +0,0 @@
-.global sqrtl
-.type sqrtl,@function
-sqrtl: fldt 8(%rsp)
- fsqrt
- ret
diff --git a/src/network/getnameinfo.c b/src/network/getnameinfo.c
index f77e73ad..949e1811 100644
--- a/src/network/getnameinfo.c
+++ b/src/network/getnameinfo.c
@@ -158,6 +158,7 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t sl,
unsigned char query[18+PTR_MAX], reply[512];
int qlen = __res_mkquery(0, ptr, 1, RR_PTR,
0, 0, 0, query, sizeof query);
+ query[3] = 0; /* don't need AD flag */
int rlen = __res_send(query, qlen, reply, sizeof reply);
buf[0] = 0;
if (rlen > 0)
diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c
index c93263a9..aae0d95a 100644
--- a/src/network/lookup_name.c
+++ b/src/network/lookup_name.c
@@ -149,6 +149,7 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static
0, 0, 0, qbuf[nq], sizeof *qbuf);
if (qlens[nq] == -1)
return EAI_NONAME;
+ qbuf[nq][3] = 0; /* don't need AD flag */
nq++;
}
}
@@ -156,14 +157,17 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static
if (__res_msend_rc(nq, qp, qlens, ap, alens, sizeof *abuf, conf) < 0)
return EAI_SYSTEM;
+ for (i=0; i<nq; i++) {
+ if (alens[i] < 4 || (abuf[i][3] & 15) == 2) return EAI_AGAIN;
+ if ((abuf[i][3] & 15) == 3) return 0;
+ if ((abuf[i][3] & 15) != 0) return EAI_FAIL;
+ }
+
for (i=0; i<nq; i++)
__dns_parse(abuf[i], alens[i], dns_parse_callback, &ctx);
if (ctx.cnt) return ctx.cnt;
- if (alens[0] < 4 || (abuf[0][3] & 15) == 2) return EAI_AGAIN;
- if ((abuf[0][3] & 15) == 0) return EAI_NONAME;
- if ((abuf[0][3] & 15) == 3) return 0;
- return EAI_FAIL;
+ return EAI_NONAME;
}
static int name_from_dns_search(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family)
diff --git a/src/network/res_mkquery.c b/src/network/res_mkquery.c
index 6fa04a5c..33f50cb9 100644
--- a/src/network/res_mkquery.c
+++ b/src/network/res_mkquery.c
@@ -20,6 +20,7 @@ int __res_mkquery(int op, const char *dname, int class, int type,
/* Construct query template - ID will be filled later */
memset(q, 0, n);
q[2] = op*8 + 1;
+ q[3] = 32; /* AD */
q[5] = 1;
memcpy((char *)q+13, dname, l);
for (i=13; q[i]; i=j+1) {
diff --git a/src/network/res_send.c b/src/network/res_send.c
index b9cea0bf..ee4abf1f 100644
--- a/src/network/res_send.c
+++ b/src/network/res_send.c
@@ -3,7 +3,7 @@
int __res_send(const unsigned char *msg, int msglen, unsigned char *answer, int anslen)
{
int r = __res_msend(1, &msg, &msglen, &answer, &anslen, anslen);
- return r<0 ? r : anslen;
+ return r<0 || !anslen ? -1 : anslen;
}
weak_alias(__res_send, res_send);
diff --git a/src/network/socket.c b/src/network/socket.c
index a2e92d90..afa1a7f3 100644
--- a/src/network/socket.c
+++ b/src/network/socket.c
@@ -5,17 +5,17 @@
int socket(int domain, int type, int protocol)
{
- int s = socketcall(socket, domain, type, protocol, 0, 0, 0);
- if (s<0 && (errno==EINVAL || errno==EPROTONOSUPPORT)
+ int s = __socketcall(socket, domain, type, protocol, 0, 0, 0);
+ if ((s==-EINVAL || s==-EPROTONOSUPPORT)
&& (type&(SOCK_CLOEXEC|SOCK_NONBLOCK))) {
- s = socketcall(socket, domain,
+ s = __socketcall(socket, domain,
type & ~(SOCK_CLOEXEC|SOCK_NONBLOCK),
protocol, 0, 0, 0);
- if (s < 0) return s;
+ if (s < 0) return __syscall_ret(s);
if (type & SOCK_CLOEXEC)
__syscall(SYS_fcntl, s, F_SETFD, FD_CLOEXEC);
if (type & SOCK_NONBLOCK)
__syscall(SYS_fcntl, s, F_SETFL, O_NONBLOCK);
}
- return s;
+ return __syscall_ret(s);
}
diff --git a/src/stat/fchmodat.c b/src/stat/fchmodat.c
index be61bdf3..4ee00b0a 100644
--- a/src/stat/fchmodat.c
+++ b/src/stat/fchmodat.c
@@ -2,6 +2,7 @@
#include <fcntl.h>
#include <errno.h>
#include "syscall.h"
+#include "kstat.h"
int fchmodat(int fd, const char *path, mode_t mode, int flag)
{
@@ -10,7 +11,7 @@ int fchmodat(int fd, const char *path, mode_t mode, int flag)
if (flag != AT_SYMLINK_NOFOLLOW)
return __syscall_ret(-EINVAL);
- struct stat st;
+ struct kstat st;
int ret, fd2;
char proc[15+3*sizeof(int)];
diff --git a/src/stdio/__string_read.c b/src/stdio/__string_read.c
deleted file mode 100644
index 7b50a7e1..00000000
--- a/src/stdio/__string_read.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#include "stdio_impl.h"
-#include <string.h>
-
-size_t __string_read(FILE *f, unsigned char *buf, size_t len)
-{
- char *src = f->cookie;
- size_t k = len+256;
- char *end = memchr(src, 0, k);
- if (end) k = end-src;
- if (k < len) len = k;
- memcpy(buf, src, len);
- f->rpos = (void *)(src+len);
- f->rend = (void *)(src+k);
- f->cookie = src+k;
- return len;
-}
diff --git a/src/stdio/fmemopen.c b/src/stdio/fmemopen.c
index 5685092e..343e3e3f 100644
--- a/src/stdio/fmemopen.c
+++ b/src/stdio/fmemopen.c
@@ -2,6 +2,7 @@
#include <errno.h>
#include <string.h>
#include <stdlib.h>
+#include <stddef.h>
#include <inttypes.h>
#include "libc.h"
@@ -95,18 +96,17 @@ FILE *fmemopen(void *restrict buf, size_t size, const char *restrict mode)
f = malloc(sizeof *f + (buf?0:size));
if (!f) return 0;
- memset(&f->f, 0, sizeof f->f);
+ memset(f, 0, offsetof(struct mem_FILE, buf));
f->f.cookie = &f->c;
f->f.fd = -1;
f->f.lbf = EOF;
f->f.buf = f->buf + UNGET;
f->f.buf_size = sizeof f->buf - UNGET;
if (!buf) {
- buf = f->buf2;;
+ buf = f->buf2;
memset(buf, 0, size);
}
- memset(&f->c, 0, sizeof f->c);
f->c.buf = buf;
f->c.size = size;
f->c.mode = *mode;
diff --git a/src/stdio/tempnam.c b/src/stdio/tempnam.c
index 84f91978..565df6b6 100644
--- a/src/stdio/tempnam.c
+++ b/src/stdio/tempnam.c
@@ -6,6 +6,7 @@
#include <string.h>
#include <stdlib.h>
#include "syscall.h"
+#include "kstat.h"
#define MAXTRIES 100
@@ -37,10 +38,10 @@ char *tempnam(const char *dir, const char *pfx)
for (try=0; try<MAXTRIES; try++) {
__randname(s+l-6);
#ifdef SYS_lstat
- r = __syscall(SYS_lstat, s, &(struct stat){0});
+ r = __syscall(SYS_lstat, s, &(struct kstat){0});
#else
r = __syscall(SYS_fstatat, AT_FDCWD, s,
- &(struct stat){0}, AT_SYMLINK_NOFOLLOW);
+ &(struct kstat){0}, AT_SYMLINK_NOFOLLOW);
#endif
if (r == -ENOENT) return strdup(s);
}
diff --git a/src/stdio/tmpnam.c b/src/stdio/tmpnam.c
index 6c7c253a..d667a836 100644
--- a/src/stdio/tmpnam.c
+++ b/src/stdio/tmpnam.c
@@ -5,6 +5,7 @@
#include <string.h>
#include <stdlib.h>
#include "syscall.h"
+#include "kstat.h"
#define MAXTRIES 100
@@ -17,10 +18,10 @@ char *tmpnam(char *buf)
for (try=0; try<MAXTRIES; try++) {
__randname(s+12);
#ifdef SYS_lstat
- r = __syscall(SYS_lstat, s, &(struct stat){0});
+ r = __syscall(SYS_lstat, s, &(struct kstat){0});
#else
r = __syscall(SYS_fstatat, AT_FDCWD, s,
- &(struct stat){0}, AT_SYMLINK_NOFOLLOW);
+ &(struct kstat){0}, AT_SYMLINK_NOFOLLOW);
#endif
if (r == -ENOENT) return strcpy(buf ? buf : internal, s);
}
diff --git a/src/stdio/vdprintf.c b/src/stdio/vdprintf.c
index c35d9b4f..3b9c093b 100644
--- a/src/stdio/vdprintf.c
+++ b/src/stdio/vdprintf.c
@@ -1,14 +1,9 @@
#include "stdio_impl.h"
-static size_t wrap_write(FILE *f, const unsigned char *buf, size_t len)
-{
- return __stdio_write(f, buf, len);
-}
-
int vdprintf(int fd, const char *restrict fmt, va_list ap)
{
FILE f = {
- .fd = fd, .lbf = EOF, .write = wrap_write,
+ .fd = fd, .lbf = EOF, .write = __stdio_write,
.buf = (void *)fmt, .buf_size = 0,
.lock = -1
};
diff --git a/src/stdio/vfscanf.c b/src/stdio/vfscanf.c
index 9e030fc4..b5ebc16e 100644
--- a/src/stdio/vfscanf.c
+++ b/src/stdio/vfscanf.c
@@ -76,6 +76,9 @@ int vfscanf(FILE *restrict f, const char *restrict fmt, va_list ap)
FLOCK(f);
+ if (!f->rpos) __toread(f);
+ if (!f->rpos) goto input_fail;
+
for (p=(const unsigned char *)fmt; *p; p++) {
alloc = 0;
diff --git a/src/stdio/vsscanf.c b/src/stdio/vsscanf.c
index 98500225..4d6d259b 100644
--- a/src/stdio/vsscanf.c
+++ b/src/stdio/vsscanf.c
@@ -1,15 +1,25 @@
#include "stdio_impl.h"
+#include <string.h>
-static size_t do_read(FILE *f, unsigned char *buf, size_t len)
+static size_t string_read(FILE *f, unsigned char *buf, size_t len)
{
- return __string_read(f, buf, len);
+ char *src = f->cookie;
+ size_t k = len+256;
+ char *end = memchr(src, 0, k);
+ if (end) k = end-src;
+ if (k < len) len = k;
+ memcpy(buf, src, len);
+ f->rpos = (void *)(src+len);
+ f->rend = (void *)(src+k);
+ f->cookie = src+k;
+ return len;
}
int vsscanf(const char *restrict s, const char *restrict fmt, va_list ap)
{
FILE f = {
.buf = (void *)s, .cookie = (void *)s,
- .read = do_read, .lock = -1
+ .read = string_read, .lock = -1
};
return vfscanf(&f, fmt, ap);
}
diff --git a/src/stdlib/wcstod.c b/src/stdlib/wcstod.c
index 26fe9af8..0deb7010 100644
--- a/src/stdlib/wcstod.c
+++ b/src/stdlib/wcstod.c
@@ -33,8 +33,7 @@ static long double wcstox(const wchar_t *s, wchar_t **p, int prec)
unsigned char buf[64];
FILE f = {0};
f.flags = 0;
- f.rpos = f.rend = 0;
- f.buf = buf + 4;
+ f.rpos = f.rend = f.buf = buf + 4;
f.buf_size = sizeof buf - 4;
f.lock = -1;
f.read = do_read;
diff --git a/src/stdlib/wcstol.c b/src/stdlib/wcstol.c
index 4443f577..1eeb495f 100644
--- a/src/stdlib/wcstol.c
+++ b/src/stdlib/wcstol.c
@@ -35,8 +35,7 @@ static unsigned long long wcstox(const wchar_t *s, wchar_t **p, int base, unsign
unsigned char buf[64];
FILE f = {0};
f.flags = 0;
- f.rpos = f.rend = 0;
- f.buf = buf + 4;
+ f.rpos = f.rend = f.buf = buf + 4;
f.buf_size = sizeof buf - 4;
f.lock = -1;
f.read = do_read;
diff --git a/src/string/memccpy.c b/src/string/memccpy.c
index 00c18e2b..3b0a3700 100644
--- a/src/string/memccpy.c
+++ b/src/string/memccpy.c
@@ -29,6 +29,6 @@ void *memccpy(void *restrict dest, const void *restrict src, int c, size_t n)
#endif
for (; n && (*d=*s)!=c; n--, s++, d++);
tail:
- if (n && *s==c) return d+1;
+ if (n) return d+1;
return 0;
}
diff --git a/src/string/memmem.c b/src/string/memmem.c
index 58a21fcd..11eff86e 100644
--- a/src/string/memmem.c
+++ b/src/string/memmem.c
@@ -12,8 +12,8 @@ static char *twobyte_memmem(const unsigned char *h, size_t k, const unsigned cha
static char *threebyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
{
- uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8;
- uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8;
+ uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8;
+ uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8;
for (h+=3, k-=3; k; k--, hw = (hw|*h++)<<8)
if (hw == nw) return (char *)h-3;
return hw == nw ? (char *)h-3 : 0;
@@ -21,8 +21,8 @@ static char *threebyte_memmem(const unsigned char *h, size_t k, const unsigned c
static char *fourbyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
{
- uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
- uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
+ uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
+ uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
for (h+=4, k-=4; k; k--, hw = hw<<8 | *h++)
if (hw == nw) return (char *)h-4;
return hw == nw ? (char *)h-4 : 0;
diff --git a/src/string/strsignal.c b/src/string/strsignal.c
index 96bfe841..5156366e 100644
--- a/src/string/strsignal.c
+++ b/src/string/strsignal.c
@@ -31,7 +31,11 @@ static const char map[] = {
[SIGPIPE] = 13,
[SIGALRM] = 14,
[SIGTERM] = 15,
+#if defined(SIGSTKFLT)
[SIGSTKFLT] = 16,
+#elif defined(SIGEMT)
+ [SIGEMT] = 16,
+#endif
[SIGCHLD] = 17,
[SIGCONT] = 18,
[SIGSTOP] = 19,
@@ -70,7 +74,13 @@ static const char strings[] =
"Broken pipe\0"
"Alarm clock\0"
"Terminated\0"
+#if defined(SIGSTKFLT)
"Stack fault\0"
+#elif defined(SIGEMT)
+ "Emulator trap\0"
+#else
+ "Unknown signal\0"
+#endif
"Child process status\0"
"Continued\0"
"Stopped (signal)\0"
diff --git a/src/string/strstr.c b/src/string/strstr.c
index 55ba1c7b..43a0207a 100644
--- a/src/string/strstr.c
+++ b/src/string/strstr.c
@@ -10,16 +10,16 @@ static char *twobyte_strstr(const unsigned char *h, const unsigned char *n)
static char *threebyte_strstr(const unsigned char *h, const unsigned char *n)
{
- uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8;
- uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8;
+ uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8;
+ uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8;
for (h+=2; *h && hw != nw; hw = (hw|*++h)<<8);
return *h ? (char *)h-2 : 0;
}
static char *fourbyte_strstr(const unsigned char *h, const unsigned char *n)
{
- uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
- uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
+ uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
+ uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
for (h+=3; *h && hw != nw; hw = hw<<8 | *++h);
return *h ? (char *)h-3 : 0;
}
diff --git a/src/thread/__lock.c b/src/thread/__lock.c
index 45557c88..60eece49 100644
--- a/src/thread/__lock.c
+++ b/src/thread/__lock.c
@@ -18,9 +18,11 @@
void __lock(volatile int *l)
{
- if (!libc.threads_minus_1) return;
+ int need_locks = libc.need_locks;
+ if (!need_locks) return;
/* fast path: INT_MIN for the lock, +1 for the congestion */
int current = a_cas(l, 0, INT_MIN + 1);
+ if (need_locks < 0) libc.need_locks = 0;
if (!current) return;
/* A first spin loop, for medium congestion. */
for (unsigned i = 0; i < 10; ++i) {
diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c
index 5f491092..6bdfb44f 100644
--- a/src/thread/pthread_create.c
+++ b/src/thread/pthread_create.c
@@ -90,14 +90,7 @@ _Noreturn void __pthread_exit(void *result)
exit(0);
}
- /* At this point we are committed to thread termination. Unlink
- * the thread from the list. This change will not be visible
- * until the lock is released, which only happens after SYS_exit
- * has been called, via the exit futex address pointing at the lock. */
- libc.threads_minus_1--;
- self->next->prev = self->prev;
- self->prev->next = self->next;
- self->prev = self->next = self;
+ /* At this point we are committed to thread termination. */
/* Process robust list in userspace to handle non-pshared mutexes
* and the detached thread case where the robust list head will
@@ -121,6 +114,16 @@ _Noreturn void __pthread_exit(void *result)
__do_orphaned_stdio_locks();
__dl_thread_cleanup();
+ /* Last, unlink thread from the list. This change will not be visible
+ * until the lock is released, which only happens after SYS_exit
+ * has been called, via the exit futex address pointing at the lock.
+ * This needs to happen after any possible calls to LOCK() that might
+ * skip locking if process appears single-threaded. */
+ if (!--libc.threads_minus_1) libc.need_locks = -1;
+ self->next->prev = self->prev;
+ 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);
@@ -336,7 +339,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att
~(1UL<<((SIGCANCEL-1)%(8*sizeof(long))));
__tl_lock();
- libc.threads_minus_1++;
+ if (!libc.threads_minus_1++) libc.need_locks = 1;
ret = __clone((c11 ? start_c11 : start), stack, flags, args, &new->tid, TP_ADJ(new), &__thread_list_lock);
/* All clone failures translate to EAGAIN. If explicit scheduling
@@ -360,7 +363,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att
new->next->prev = new;
new->prev->next = new;
} else {
- libc.threads_minus_1--;
+ if (!--libc.threads_minus_1) libc.need_locks = 0;
}
__tl_unlock();
__restore_sigs(&set);
diff --git a/src/time/__map_file.c b/src/time/__map_file.c
index 9d376222..d3cefa82 100644
--- a/src/time/__map_file.c
+++ b/src/time/__map_file.c
@@ -2,10 +2,11 @@
#include <fcntl.h>
#include <sys/stat.h>
#include "syscall.h"
+#include "kstat.h"
const char unsigned *__map_file(const char *pathname, size_t *size)
{
- struct stat st;
+ struct kstat st;
const unsigned char *map = MAP_FAILED;
int fd = sys_open(pathname, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
if (fd < 0) return 0;
diff --git a/src/time/__tz.c b/src/time/__tz.c
index 185642e8..49a7371e 100644
--- a/src/time/__tz.c
+++ b/src/time/__tz.c
@@ -86,15 +86,15 @@ static void getname(char *d, const char **p)
int i;
if (**p == '<') {
++*p;
- for (i=0; (*p)[i]!='>' && i<TZNAME_MAX; i++)
- d[i] = (*p)[i];
- ++*p;
+ for (i=0; (*p)[i] && (*p)[i]!='>'; i++)
+ if (i<TZNAME_MAX) d[i] = (*p)[i];
+ if ((*p)[i]) ++*p;
} else {
- for (i=0; ((*p)[i]|32)-'a'<26U && i<TZNAME_MAX; i++)
- d[i] = (*p)[i];
+ for (i=0; ((*p)[i]|32)-'a'<26U; i++)
+ if (i<TZNAME_MAX) d[i] = (*p)[i];
}
*p += i;
- d[i] = 0;
+ d[i<TZNAME_MAX?i:TZNAME_MAX] = 0;
}
#define VEC(...) ((const unsigned char[]){__VA_ARGS__})