From 147e832a00dd1cec27e77f1976fc46ee2168e6a2 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Oct 21 2019 13:16:21 +0000 Subject: import glibc-2.17-306.el7 --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6862d2d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +SOURCES/glibc-2.17-c758a686-releng.tar.gz +SOURCES/glibc-2.17-c758a686.tar.gz diff --git a/.glibc.metadata b/.glibc.metadata new file mode 100644 index 0000000..5ca6e2b --- /dev/null +++ b/.glibc.metadata @@ -0,0 +1,2 @@ +3dd002978c064e6e318eefef5534467fe548603e SOURCES/glibc-2.17-c758a686-releng.tar.gz +4fba0f86423c135f33a82cf8b58664aacf72f628 SOURCES/glibc-2.17-c758a686.tar.gz diff --git a/SOURCES/glibc-aa64-commonpagesize-64k.patch b/SOURCES/glibc-aa64-commonpagesize-64k.patch new file mode 100644 index 0000000..a18a0e3 --- /dev/null +++ b/SOURCES/glibc-aa64-commonpagesize-64k.patch @@ -0,0 +1,11 @@ +--- glibc-2.17-c758a686/ports/sysdeps/aarch64/preconfigure 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/ports/sysdeps/aarch64/preconfigure 2014-05-12 14:29:52.007239252 -0400 +@@ -8,7 +8,7 @@ + case "$machine" in + aarch64*) + # Parameters to allow auto-detection of -z relro. +- libc_commonpagesize=0x1000 ++ libc_commonpagesize=0x10000 + libc_relro_required=yes + ;; + esac diff --git a/SOURCES/glibc-aa64-setcontext.patch b/SOURCES/glibc-aa64-setcontext.patch new file mode 100644 index 0000000..60fc6a5 --- /dev/null +++ b/SOURCES/glibc-aa64-setcontext.patch @@ -0,0 +1,220 @@ +Backport + +37d350073888887637aa67dddf988d9c4b226032 \ + aarch64: Re-implement setcontext without rt_sigreturn syscall +03ea4d9b6916857e3c2a021f55d2a853cb837398 \ + [AArch64] Simplify getcontext pstate initialization. +6e445a3d2bdf152ebf57d1c92bfea1828e070743 \ + [AArch64] Ensure getcontext() initializes PSTATE. + + +diff --git glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/getcontext.S glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/getcontext.S +index aff2e32..70b2e32 100644 +--- glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/getcontext.S ++++ glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/getcontext.S +@@ -1,6 +1,6 @@ + /* Save current context. + +- Copyright (C) 2009-2012 Free Software Foundation, Inc. ++ Copyright (C) 2009-2014 Free Software Foundation, Inc. + + This file is part of the GNU C Library. + +@@ -53,6 +53,9 @@ ENTRY(__getcontext) + mov x2, sp + str x2, [x0, oSP] + ++ /* Initialize the pstate. */ ++ str xzr, [x0, oPSTATE] ++ + /* Figure out where to place the first context extension + block. */ + add x2, x0, #oEXTENSION +diff --git glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/setcontext.S glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/setcontext.S +index a98f67f..f45a655 100644 +--- glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/setcontext.S ++++ glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/setcontext.S +@@ -1,6 +1,6 @@ + /* Set current context. + +- Copyright (C) 2009-2012 Free Software Foundation, Inc. ++ Copyright (C) 2009-2014 Free Software Foundation, Inc. + + This file is part of the GNU C Library. + +@@ -22,68 +22,108 @@ + #include "ucontext_i.h" + #include "ucontext-internal.h" + +-/* int setcontext (const ucontext_t *ucp) */ ++/* int __setcontext (const ucontext_t *ucp) + +- .text +- +-ENTRY(__setcontext) +- +- /* Create a signal frame on the stack: +- +- fp +- lr +- ... +- sp-> rt_sigframe +- */ +- +- stp x29, x30, [sp, -16]! +- cfi_adjust_cfa_offset (16) +- cfi_rel_offset (x29, 0) +- cfi_rel_offset (x30, 8) +- +- mov x29, sp +- cfi_def_cfa_register (x29) +- +- /* Allocate space for the sigcontext. */ +- mov w3, #((RT_SIGFRAME_SIZE + SP_ALIGN_SIZE) & SP_ALIGN_MASK) +- sub sp, sp, x3 ++ Restores the machine context in UCP and thereby resumes execution ++ in that context. + +- /* Compute the base address of the ucontext structure. */ +- add x1, sp, #RT_SIGFRAME_UCONTEXT ++ This implementation is intended to be used for *synchronous* context ++ switches only. Therefore, it does not have to restore anything ++ other than the PRESERVED state. */ + +- /* Only ucontext is required in the frame, *copy* it in. */ +- +-#if UCONTEXT_SIZE % 16 +-#error The implementation of setcontext.S assumes sizeof(ucontext_t) % 16 == 0 +-#endif +- +- mov x2, #UCONTEXT_SIZE / 16 +-0: +- ldp x3, x4, [x0], #16 +- stp x3, x4, [x1], #16 +- sub x2, x2, 1 +- cbnz x2, 0b ++ .text + +- /* rt_sigreturn () -- no arguments, sp points to struct rt_sigframe. */ +- mov x8, SYS_ify (rt_sigreturn) ++ENTRY (__setcontext) ++ /* Save a copy of UCP. */ ++ mov x9, x0 ++ ++ /* Set the signal mask with ++ rt_sigprocmask (SIG_SETMASK, mask, NULL, _NSIG/8). */ ++ mov x0, #SIG_SETMASK ++ add x1, x9, #UCONTEXT_SIGMASK ++ mov x2, #0 ++ mov x3, #_NSIG8 ++ mov x8, SYS_ify (rt_sigprocmask) + svc 0 +- +- /* Ooops we failed. Recover the stack */ +- +- mov sp, x29 +- cfi_def_cfa_register (sp) +- +- ldp x29, x30, [sp], 16 +- cfi_adjust_cfa_offset (16) +- cfi_restore (x29) +- cfi_restore (x30) +- b C_SYMBOL_NAME(__syscall_error) +- ++ cbz x0, 1f ++ b C_SYMBOL_NAME (__syscall_error) ++1: ++ /* Restore the general purpose registers. */ ++ mov x0, x9 ++ cfi_def_cfa (x0, 0) ++ cfi_offset (x18, oX0 + 18 * SZREG) ++ cfi_offset (x19, oX0 + 19 * SZREG) ++ cfi_offset (x20, oX0 + 20 * SZREG) ++ cfi_offset (x21, oX0 + 21 * SZREG) ++ cfi_offset (x22, oX0 + 22 * SZREG) ++ cfi_offset (x23, oX0 + 23 * SZREG) ++ cfi_offset (x24, oX0 + 24 * SZREG) ++ cfi_offset (x25, oX0 + 25 * SZREG) ++ cfi_offset (x26, oX0 + 26 * SZREG) ++ cfi_offset (x27, oX0 + 27 * SZREG) ++ cfi_offset (x28, oX0 + 28 * SZREG) ++ cfi_offset (x29, oX0 + 29 * SZREG) ++ cfi_offset (x30, oX0 + 30 * SZREG) ++ ++ cfi_offset ( d8, oV0 + 8 * SZVREG) ++ cfi_offset ( d9, oV0 + 9 * SZVREG) ++ cfi_offset (d10, oV0 + 10 * SZVREG) ++ cfi_offset (d11, oV0 + 11 * SZVREG) ++ cfi_offset (d12, oV0 + 12 * SZVREG) ++ cfi_offset (d13, oV0 + 13 * SZVREG) ++ cfi_offset (d14, oV0 + 14 * SZVREG) ++ cfi_offset (d15, oV0 + 15 * SZVREG) ++ ldp x18, x19, [x0, oX0 + 18 * SZREG] ++ ldp x20, x21, [x0, oX0 + 20 * SZREG] ++ ldp x22, x23, [x0, oX0 + 22 * SZREG] ++ ldp x24, x25, [x0, oX0 + 24 * SZREG] ++ ldp x26, x27, [x0, oX0 + 26 * SZREG] ++ ldp x28, x29, [x0, oX0 + 28 * SZREG] ++ ldr x30, [x0, oX0 + 30 * SZREG] ++ ldr x2, [x0, oSP] ++ mov sp, x2 ++ ++ /* Check for FP SIMD context. We don't support restoring ++ contexts created by the kernel, so this context must have ++ been created by getcontext. Hence we can rely on the ++ first extension block being the FP SIMD context. */ ++ add x2, x0, #oEXTENSION ++ ++ mov w3, #(FPSIMD_MAGIC & 0xffff) ++ movk w3, #(FPSIMD_MAGIC >> 16), lsl #16 ++ ldr w1, [x2, #oHEAD + oMAGIC] ++ cmp w1, w3 ++ b.ne 2f ++ ++ /* Restore the FP SIMD context. */ ++ add x3, x2, #oV0 + 8 * SZVREG ++ ldp d8, d9, [x3], #2 * SZVREG ++ ldp d10, d11, [x3], #2 * SZVREG ++ ldp d12, d13, [x3], #2 * SZVREG ++ ldp d14, d15, [x3], #2 * SZVREG ++ ++ add x3, x2, oFPSR ++ ++ ldr w4, [x3] ++ msr fpsr, x4 ++ ++ ldr w4, [x3, oFPCR - oFPSR] ++ msr fpcr, x4 ++ ++2: ++ ldr x16, [x0, oPC] ++ /* Restore arg registers. */ ++ ldp x2, x3, [x0, oX0 + 2 * SZREG] ++ ldp x4, x5, [x0, oX0 + 4 * SZREG] ++ ldp x6, x7, [x0, oX0 + 6 * SZREG] ++ ldp x0, x1, [x0, oX0 + 0 * SZREG] ++ /* Jump to the new pc value. */ ++ br x16 + PSEUDO_END (__setcontext) + weak_alias (__setcontext, setcontext) + +-ENTRY(__startcontext) ++ENTRY (__startcontext) + mov x0, x19 + cbnz x0, __setcontext +-1: b HIDDEN_JUMPTARGET(_exit) +-END(__startcontext) ++1: b HIDDEN_JUMPTARGET (_exit) ++END (__startcontext) +diff --git glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym +index 1afff78..ab3930c 100644 +--- glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym ++++ glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym +@@ -37,6 +37,7 @@ STACK_FLAGS stack (ss_flags) + oX0 mcontext (regs) + oSP mcontext (sp) + oPC mcontext (pc) ++oPSTATE mcontext (pstate) + oEXTENSION mcontext (__reserved) + + #define fpsimd_context(member) offsetof (struct fpsimd_context, member) diff --git a/SOURCES/glibc-aarch64-add-ptr_mangle-support.patch b/SOURCES/glibc-aarch64-add-ptr_mangle-support.patch new file mode 100644 index 0000000..dbdc551 --- /dev/null +++ b/SOURCES/glibc-aarch64-add-ptr_mangle-support.patch @@ -0,0 +1,233 @@ +commit 9188b6818a3d1a6e6d89bf10fa4aea27a591494c +Author: Venkataramanan Kumar +Date: Wed Jan 1 17:47:14 2014 +0000 + + [AArch64] Pointer mangling support for AArch64. + +diff --git glibc-2.17-c758a686/ports/sysdeps/aarch64/__longjmp.S glibc-2.17-c758a686/ports/sysdeps/aarch64/__longjmp.S +index 250f2af..2d38bbf 100644 +--- glibc-2.17-c758a686/ports/sysdeps/aarch64/__longjmp.S ++++ glibc-2.17-c758a686/ports/sysdeps/aarch64/__longjmp.S +@@ -50,8 +50,12 @@ ENTRY (__longjmp) + ldp x23, x24, [x0, #JB_X23<<3] + ldp x25, x26, [x0, #JB_X25<<3] + ldp x27, x28, [x0, #JB_X27<<3] ++#ifdef PTR_DEMANGLE ++ ldp x29, x4, [x0, #JB_X29<<3] ++ PTR_DEMANGLE (x30, x4, x3, x2) ++#else + ldp x29, x30, [x0, #JB_X29<<3] +- ++#endif + ldp d8, d9, [x0, #JB_D8<<3] + ldp d10, d11, [x0, #JB_D10<<3] + ldp d12, d13, [x0, #JB_D12<<3] +@@ -87,8 +91,12 @@ ENTRY (__longjmp) + cfi_same_value(d13) + cfi_same_value(d14) + cfi_same_value(d15) +- +- ldr x5, [x0, #JB_SP<<3] ++#ifdef PTR_DEMANGLE ++ ldr x4, [x0, #JB_SP<<3] ++ PTR_DEMANGLE (x5, x4, x3, x2) ++#else ++ ldr x5, [x0, #JB_SP<<3] ++#endif + mov sp, x5 + cmp x1, #0 + mov x0, #1 +diff --git glibc-2.17-c758a686/ports/sysdeps/aarch64/jmpbuf-offsets.h glibc-2.17-c758a686/ports/sysdeps/aarch64/jmpbuf-offsets.h +index 84c2ccc..bcf2afa 100644 +--- glibc-2.17-c758a686/ports/sysdeps/aarch64/jmpbuf-offsets.h ++++ glibc-2.17-c758a686/ports/sysdeps/aarch64/jmpbuf-offsets.h +@@ -39,6 +39,22 @@ + #define JB_D14 20 + #define JB_D15 21 + ++#ifndef __ASSEMBLER__ ++#include ++#include ++#include ++ ++static inline uintptr_t __attribute__ ((unused)) ++_jmpbuf_sp (__jmp_buf jmpbuf) ++{ ++ uintptr_t sp = jmpbuf[JB_SP]; ++#ifdef PTR_DEMANGLE ++ PTR_DEMANGLE (sp); ++#endif ++ return sp; ++} ++#endif ++ + /* Helper for generic ____longjmp_chk(). */ + #define JB_FRAME_ADDRESS(buf) \ +- ((void *) (buf[JB_SP])) ++ ((void *) _jmpbuf_sp (buf)) +diff --git glibc-2.17-c758a686/ports/sysdeps/aarch64/jmpbuf-unwind.h glibc-2.17-c758a686/ports/sysdeps/aarch64/jmpbuf-unwind.h +index 22c6c2b..39a5dc2 100644 +--- glibc-2.17-c758a686/ports/sysdeps/aarch64/jmpbuf-unwind.h ++++ glibc-2.17-c758a686/ports/sysdeps/aarch64/jmpbuf-unwind.h +@@ -29,16 +29,6 @@ + #define _JMPBUF_CFA_UNWINDS_ADJ(jmpbuf, context, adj) \ + _JMPBUF_UNWINDS_ADJ (jmpbuf, (void *) _Unwind_GetCFA (context), adj) + +-static inline uintptr_t __attribute__ ((unused)) +-_jmpbuf_sp (__jmp_buf jmpbuf) +-{ +- uintptr_t sp = jmpbuf[JB_SP]; +-#ifdef PTR_DEMANGLE +- PTR_DEMANGLE (sp); +-#endif +- return sp; +-} +- + #define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ + ((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj)) + +diff --git glibc-2.17-c758a686/ports/sysdeps/aarch64/setjmp.S glibc-2.17-c758a686/ports/sysdeps/aarch64/setjmp.S +index cb94e01..5822abd 100644 +--- glibc-2.17-c758a686/ports/sysdeps/aarch64/setjmp.S ++++ glibc-2.17-c758a686/ports/sysdeps/aarch64/setjmp.S +@@ -39,13 +39,25 @@ ENTRY (__sigsetjmp) + stp x23, x24, [x0, #JB_X23<<3] + stp x25, x26, [x0, #JB_X25<<3] + stp x27, x28, [x0, #JB_X27<<3] ++ ++#ifdef PTR_MANGLE ++ PTR_MANGLE (x4, x30, x3, x2) ++ stp x29, x4, [x0, #JB_X29<<3] ++#else + stp x29, x30, [x0, #JB_X29<<3] ++#endif + stp d8, d9, [x0, #JB_D8<<3] + stp d10, d11, [x0, #JB_D10<<3] + stp d12, d13, [x0, #JB_D12<<3] + stp d14, d15, [x0, #JB_D14<<3] ++#ifdef PTR_MANGLE ++ mov x4, sp ++ PTR_MANGLE (x5, x4, x3, x2) ++ str x5, [x0, #JB_SP<<3] ++#else + mov x2, sp + str x2, [x0, #JB_SP<<3] ++#endif + #if defined NOT_IN_libc && defined IS_IN_rtld + /* In ld.so we never save the signal mask */ + mov w0, #0 +diff --git glibc-2.17-c758a686/ports/sysdeps/aarch64/sysdep.h glibc-2.17-c758a686/ports/sysdeps/aarch64/sysdep.h +index 0dd597a..7169ba7 100644 +--- glibc-2.17-c758a686/ports/sysdeps/aarch64/sysdep.h ++++ glibc-2.17-c758a686/ports/sysdeps/aarch64/sysdep.h +@@ -78,6 +78,17 @@ + # define L(name) .L##name + #endif + ++/* Load or store to/from a pc-relative EXPR into/from R, using T. */ ++#define LDST_PCREL(OP, R, T, EXPR) \ ++ adrp T, EXPR; \ ++ OP R, [T, #:lo12:EXPR];\ ++ ++/* Load or store to/from a got-relative EXPR into/from R, using T. */ ++#define LDST_GLOBAL(OP, R, T, EXPR) \ ++ adrp T, :got:EXPR; \ ++ ldr T, [T, #:got_lo12:EXPR];\ ++ OP R, [T]; ++ + /* Since C identifiers are not normally prefixed with an underscore + on this system, the asm identifier `syscall_error' intrudes on the + C name space. Make sure we use an innocuous name. */ +diff --git glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/sysdep.h glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/sysdep.h +index f3f0ada..5ccf1da 100644 +--- glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/sysdep.h ++++ glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/sysdep.h +@@ -371,8 +371,44 @@ __local_syscall_error: \ + + #endif /* __ASSEMBLER__ */ + +-/* Pointer mangling is not yet supported for AArch64. */ +-#define PTR_MANGLE(var) (void) (var) +-#define PTR_DEMANGLE(var) (void) (var) ++/* Pointer mangling is supported for AArch64. */ ++#if (defined NOT_IN_libc && defined IS_IN_rtld) || \ ++ (!defined SHARED && (!defined NOT_IN_libc || defined IS_IN_libpthread)) ++# ifdef __ASSEMBLER__ ++# define PTR_MANGLE(dst, src, guard, tmp) \ ++ LDST_PCREL (ldr, guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard_local)); \ ++ PTR_MANGLE2 (dst, src, guard) ++/* Use PTR_MANGLE2 for efficiency if guard is already loaded. */ ++# define PTR_MANGLE2(dst, src, guard)\ ++ eor dst, src, guard ++# define PTR_DEMANGLE(dst, src, guard, tmp)\ ++ PTR_MANGLE (dst, src, guard, tmp) ++# define PTR_DEMANGLE2(dst, src, guard)\ ++ PTR_MANGLE2 (dst, src, guard) ++# else ++extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden; ++# define PTR_MANGLE(var) \ ++ (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local) ++# define PTR_DEMANGLE(var) PTR_MANGLE (var) ++# endif ++#else ++# ifdef __ASSEMBLER__ ++# define PTR_MANGLE(dst, src, guard, tmp) \ ++ LDST_GLOBAL (ldr, guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard)); \ ++ PTR_MANGLE2 (dst, src, guard) ++/* Use PTR_MANGLE2 for efficiency if guard is already loaded. */ ++# define PTR_MANGLE2(dst, src, guard)\ ++ eor dst, src, guard ++# define PTR_DEMANGLE(dst, src, guard, tmp)\ ++ PTR_MANGLE (dst, src, guard, tmp) ++# define PTR_DEMANGLE2(dst, src, guard)\ ++ PTR_MANGLE2 (dst, src, guard) ++# else ++extern uintptr_t __pointer_chk_guard attribute_relro; ++# define PTR_MANGLE(var) \ ++ (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard) ++# define PTR_DEMANGLE(var) PTR_MANGLE (var) ++# endif ++#endif + + #endif /* linux/aarch64/sysdep.h */ +commit 0b1f8e35640f5b3f7af11764ade3ff060211c309 +Author: Carlos O'Donell +Date: Mon Sep 23 01:44:38 2013 -0400 + + BZ #15754: Fix test case for ARM. + + Statically built binaries use __pointer_chk_guard_local, + while dynamically built binaries use __pointer_chk_guard. + Provide the right definition depending on the test case + we are building. + +diff --git glibc-2.17-c758a686/elf/Makefile glibc-2.17-c758a686/elf/Makefile +index cb8da93..27d249b 100644 +--- glibc-2.17-c758a686/elf/Makefile ++++ glibc-2.17-c758a686/elf/Makefile +@@ -1019,6 +1019,9 @@ tst-stackguard1-ARGS = --command "$(host-test-program-cmd) --child" + tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child" + + tst-ptrguard1-ARGS = --command "$(host-built-program-cmd) --child" ++# When built statically, the pointer guard interface uses ++# __pointer_chk_guard_local. ++CFLAGS-tst-ptrguard1-static.c = -DPTRGUARD_LOCAL + tst-ptrguard1-static-ARGS = --command "$(objpfx)tst-ptrguard1-static --child" + + $(objpfx)tst-leaks1: $(libdl) +diff --git glibc-2.17-c758a686/sysdeps/generic/stackguard-macros.h glibc-2.17-c758a686/sysdeps/generic/stackguard-macros.h +index 4fa3d96..b4a6b23 100644 +--- glibc-2.17-c758a686/sysdeps/generic/stackguard-macros.h ++++ glibc-2.17-c758a686/sysdeps/generic/stackguard-macros.h +@@ -3,5 +3,10 @@ + extern uintptr_t __stack_chk_guard; + #define STACK_CHK_GUARD __stack_chk_guard + ++#ifdef PTRGUARD_LOCAL + extern uintptr_t __pointer_chk_guard_local; +-#define POINTER_CHK_GUARD __pointer_chk_guard_local ++# define POINTER_CHK_GUARD __pointer_chk_guard_local ++#else ++extern uintptr_t __pointer_chk_guard; ++# define POINTER_CHK_GUARD __pointer_chk_guard ++#endif diff --git a/SOURCES/glibc-aarch64-fpu-optional-trapping-exceptions.patch b/SOURCES/glibc-aarch64-fpu-optional-trapping-exceptions.patch new file mode 100644 index 0000000..0afa504 --- /dev/null +++ b/SOURCES/glibc-aarch64-fpu-optional-trapping-exceptions.patch @@ -0,0 +1,122 @@ +commit 302949e2940a9da3f6364a1574619e621b7e1e71 +Author: Marcus Shawcroft +Date: Fri Mar 7 14:05:20 2014 +0000 + + [PATCH] [AArch64] Optional trapping exceptions support. + + Trapping exceptions in AArch64 are optional. The relevant exception + control bits in FPCR are are defined as RES0 hence the absence of + support can be detected by reading back the FPCR and comparing with + the desired value. + +--- glibc-2.17-c758a686/ports/sysdeps/aarch64/fpu/feenablxcpt.c ++++ glibc-2.17-c758a686/ports/sysdeps/aarch64/fpu/feenablxcpt.c +@@ -35,5 +35,18 @@ feenableexcept (int excepts) + + _FPU_SETCW (fpcr); + ++ /* Trapping exceptions are optional in AArch64 the relevant enable ++ bits in FPCR are RES0 hence the absence of support can be ++ detected by reading back the FPCR and comparing with the required ++ value. */ ++ if (excepts) ++ { ++ fpu_control_t updated_fpcr; ++ ++ _FPU_GETCW (updated_fpcr); ++ if (((updated_fpcr >> FE_EXCEPT_SHIFT) & excepts) != excepts) ++ return -1; ++ } ++ + return original_excepts; + } +--- glibc-2.17-c758a686/ports/sysdeps/aarch64/fpu/fesetenv.c ++++ glibc-2.17-c758a686/ports/sysdeps/aarch64/fpu/fesetenv.c +@@ -24,6 +24,7 @@ fesetenv (const fenv_t *envp) + { + fpu_control_t fpcr; + fpu_fpsr_t fpsr; ++ fpu_control_t updated_fpcr; + + _FPU_GETCW (fpcr); + _FPU_GETFPSR (fpsr); +@@ -51,6 +52,15 @@ fesetenv (const fenv_t *envp) + + _FPU_SETCW (fpcr); + ++ /* Trapping exceptions are optional in AArch64 the relevant enable ++ bits in FPCR are RES0 hence the absence of support can be ++ detected by reading back the FPCR and comparing with the required ++ value. */ ++ ++ _FPU_GETCW (updated_fpcr); ++ if ((updated_fpcr & fpcr) != fpcr) ++ return 1; ++ + return 0; + } + +commit 423a7160af7fcffc61aac5e2e36d0b6b5b083214 +Author: Wilco +Date: Thu Apr 17 09:39:27 2014 +0100 + + Add fenv test support for targets which don't have FP traps. + +(removed unnecessary code to limit it to test-fenv.c --kyle) + +--- glibc-2.17-c758a686/math/test-fenv.c ++++ glibc-2.17-c758a686/math/test-fenv.c +@@ -233,14 +234,9 @@ feenv_nomask_test (const char *flag_name, int fe_exc) + #if defined FE_NOMASK_ENV + int status; + pid_t pid; +- fenv_t saved; + +- fegetenv (&saved); +- errno = 0; +- fesetenv (FE_NOMASK_ENV); +- status = errno; +- fesetenv (&saved); +- if (status == ENOSYS) ++ if (1 ++ && fesetenv (FE_NOMASK_ENV) != 0) + { + printf ("Test: not testing FE_NOMASK_ENV, it isn't implemented.\n"); + return; +@@ -349,7 +345,13 @@ feexcp_nomask_test (const char *flag_name, int fe_exc) + int status; + pid_t pid; + +- printf ("Test: after fedisableexcept (%s) processes will abort\n", ++ if (1 && feenableexcept (fe_exc) == -1) ++ { ++ printf ("Test: not testing feenableexcept, it isn't implemented.\n"); ++ return; ++ } ++ ++ printf ("Test: after feenableexcept (%s) processes will abort\n", + flag_name); + printf (" when feraiseexcept (%s) is called.\n", flag_name); + pid = fork (); +@@ -470,7 +472,6 @@ feenable_test (const char *flag_name, int fe_exc) + { + int excepts; + +- + printf ("Tests for feenableexcepts etc. with flag %s\n", flag_name); + + /* First disable all exceptions. */ +@@ -488,8 +489,12 @@ feenable_test (const char *flag_name, int fe_exc) + flag_name, excepts); + ++count_errors; + } +- + excepts = feenableexcept (fe_exc); ++ if (1 && excepts == -1) ++ { ++ printf ("Test: not testing feenableexcept, it isn't implemented.\n"); ++ return; ++ } + if (excepts == -1) + { + printf ("Test: feenableexcept (%s) failed\n", flag_name); diff --git a/SOURCES/glibc-aarch64-ifunc.patch b/SOURCES/glibc-aarch64-ifunc.patch new file mode 100644 index 0000000..7ee9f1f --- /dev/null +++ b/SOURCES/glibc-aarch64-ifunc.patch @@ -0,0 +1,216 @@ +diff --git glibc-2.17-c758a686/elf/elf.h glibc-2.17-c758a686/elf/elf.h +index 8686fd5..2b10581 100644 +--- glibc-2.17-c758a686/elf/elf.h ++++ glibc-2.17-c758a686/elf/elf.h +@@ -2327,6 +2327,117 @@ typedef Elf32_Addr Elf32_Conflict; + #define R_AARCH64_NONE 0 /* No relocation. */ + #define R_AARCH64_ABS64 257 /* Direct 64 bit. */ + #define R_AARCH64_ABS32 258 /* Direct 32 bit. */ ++#define R_AARCH64_ABS16 259 /* Direct 16-bit. */ ++#define R_AARCH64_PREL64 260 /* PC-relative 64-bit. */ ++#define R_AARCH64_PREL32 261 /* PC-relative 32-bit. */ ++#define R_AARCH64_PREL16 262 /* PC-relative 16-bit. */ ++#define R_AARCH64_MOVW_UABS_G0 263 /* Dir. MOVZ imm. from bits 15:0. */ ++#define R_AARCH64_MOVW_UABS_G0_NC 264 /* Likewise for MOVK; no check. */ ++#define R_AARCH64_MOVW_UABS_G1 265 /* Dir. MOVZ imm. from bits 31:16. */ ++#define R_AARCH64_MOVW_UABS_G1_NC 266 /* Likewise for MOVK; no check. */ ++#define R_AARCH64_MOVW_UABS_G2 267 /* Dir. MOVZ imm. from bits 47:32. */ ++#define R_AARCH64_MOVW_UABS_G2_NC 268 /* Likewise for MOVK; no check. */ ++#define R_AARCH64_MOVW_UABS_G3 269 /* Dir. MOV{K,Z} imm. from 63:48. */ ++#define R_AARCH64_MOVW_SABS_G0 270 /* Dir. MOV{N,Z} imm. from 15:0. */ ++#define R_AARCH64_MOVW_SABS_G1 271 /* Dir. MOV{N,Z} imm. from 31:16. */ ++#define R_AARCH64_MOVW_SABS_G2 272 /* Dir. MOV{N,Z} imm. from 47:32. */ ++#define R_AARCH64_LD_PREL_LO19 273 /* PC-rel. LD imm. from bits 20:2. */ ++#define R_AARCH64_ADR_PREL_LO21 274 /* PC-rel. ADR imm. from bits 20:0. */ ++#define R_AARCH64_ADR_PREL_PG_HI21 275 /* Page-rel. ADRP imm. from 32:12. */ ++#define R_AARCH64_ADR_PREL_PG_HI21_NC 276 /* Likewise; no overflow check. */ ++#define R_AARCH64_ADD_ABS_LO12_NC 277 /* Dir. ADD imm. from bits 11:0. */ ++#define R_AARCH64_LDST8_ABS_LO12_NC 278 /* Likewise for LD/ST; no check. */ ++#define R_AARCH64_TSTBR14 279 /* PC-rel. TBZ/TBNZ imm. from 15:2. */ ++#define R_AARCH64_CONDBR19 280 /* PC-rel. cond. br. imm. from 20:2. */ ++#define R_AARCH64_JUMP26 282 /* PC-rel. B imm. from bits 27:2. */ ++#define R_AARCH64_CALL26 283 /* Likewise for CALL. */ ++#define R_AARCH64_LDST16_ABS_LO12_NC 284 /* Dir. ADD imm. from bits 11:1. */ ++#define R_AARCH64_LDST32_ABS_LO12_NC 285 /* Likewise for bits 11:2. */ ++#define R_AARCH64_LDST64_ABS_LO12_NC 286 /* Likewise for bits 11:3. */ ++#define R_AARCH64_MOVW_PREL_G0 287 /* PC-rel. MOV{N,Z} imm. from 15:0. */ ++#define R_AARCH64_MOVW_PREL_G0_NC 288 /* Likewise for MOVK; no check. */ ++#define R_AARCH64_MOVW_PREL_G1 289 /* PC-rel. MOV{N,Z} imm. from 31:16. */ ++#define R_AARCH64_MOVW_PREL_G1_NC 290 /* Likewise for MOVK; no check. */ ++#define R_AARCH64_MOVW_PREL_G2 291 /* PC-rel. MOV{N,Z} imm. from 47:32. */ ++#define R_AARCH64_MOVW_PREL_G2_NC 292 /* Likewise for MOVK; no check. */ ++#define R_AARCH64_MOVW_PREL_G3 293 /* PC-rel. MOV{N,Z} imm. from 63:48. */ ++#define R_AARCH64_LDST128_ABS_LO12_NC 299 /* Dir. ADD imm. from bits 11:4. */ ++#define R_AARCH64_MOVW_GOTOFF_G0 300 /* GOT-rel. off. MOV{N,Z} imm. 15:0. */ ++#define R_AARCH64_MOVW_GOTOFF_G0_NC 301 /* Likewise for MOVK; no check. */ ++#define R_AARCH64_MOVW_GOTOFF_G1 302 /* GOT-rel. o. MOV{N,Z} imm. 31:16. */ ++#define R_AARCH64_MOVW_GOTOFF_G1_NC 303 /* Likewise for MOVK; no check. */ ++#define R_AARCH64_MOVW_GOTOFF_G2 304 /* GOT-rel. o. MOV{N,Z} imm. 47:32. */ ++#define R_AARCH64_MOVW_GOTOFF_G2_NC 305 /* Likewise for MOVK; no check. */ ++#define R_AARCH64_MOVW_GOTOFF_G3 306 /* GOT-rel. o. MOV{N,Z} imm. 63:48. */ ++#define R_AARCH64_GOTREL64 307 /* GOT-relative 64-bit. */ ++#define R_AARCH64_GOTREL32 308 /* GOT-relative 32-bit. */ ++#define R_AARCH64_GOT_LD_PREL19 309 /* PC-rel. GOT off. load imm. 20:2. */ ++#define R_AARCH64_LD64_GOTOFF_LO15 310 /* GOT-rel. off. LD/ST imm. 14:3. */ ++#define R_AARCH64_ADR_GOT_PAGE 311 /* P-page-rel. GOT off. ADRP 32:12. */ ++#define R_AARCH64_LD64_GOT_LO12_NC 312 /* Dir. GOT off. LD/ST imm. 11:3. */ ++#define R_AARCH64_LD64_GOTPAGE_LO15 313 /* GOT-page-rel. GOT off. LD/ST 14:3 */ ++#define R_AARCH64_TLSGD_ADR_PREL21 512 /* PC-relative ADR imm. 20:0. */ ++#define R_AARCH64_TLSGD_ADR_PAGE21 513 /* page-rel. ADRP imm. 32:12. */ ++#define R_AARCH64_TLSGD_ADD_LO12_NC 514 /* direct ADD imm. from 11:0. */ ++#define R_AARCH64_TLSGD_MOVW_G1 515 /* GOT-rel. MOV{N,Z} 31:16. */ ++#define R_AARCH64_TLSGD_MOVW_G0_NC 516 /* GOT-rel. MOVK imm. 15:0. */ ++#define R_AARCH64_TLSLD_ADR_PREL21 517 /* Like 512; local dynamic model. */ ++#define R_AARCH64_TLSLD_ADR_PAGE21 518 /* Like 513; local dynamic model. */ ++#define R_AARCH64_TLSLD_ADD_LO12_NC 519 /* Like 514; local dynamic model. */ ++#define R_AARCH64_TLSLD_MOVW_G1 520 /* Like 515; local dynamic model. */ ++#define R_AARCH64_TLSLD_MOVW_G0_NC 521 /* Like 516; local dynamic model. */ ++#define R_AARCH64_TLSLD_LD_PREL19 522 /* TLS PC-rel. load imm. 20:2. */ ++#define R_AARCH64_TLSLD_MOVW_DTPREL_G2 523 /* TLS DTP-rel. MOV{N,Z} 47:32. */ ++#define R_AARCH64_TLSLD_MOVW_DTPREL_G1 524 /* TLS DTP-rel. MOV{N,Z} 31:16. */ ++#define R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC 525 /* Likewise; MOVK; no check. */ ++#define R_AARCH64_TLSLD_MOVW_DTPREL_G0 526 /* TLS DTP-rel. MOV{N,Z} 15:0. */ ++#define R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC 527 /* Likewise; MOVK; no check. */ ++#define R_AARCH64_TLSLD_ADD_DTPREL_HI12 528 /* DTP-rel. ADD imm. from 23:12. */ ++#define R_AARCH64_TLSLD_ADD_DTPREL_LO12 529 /* DTP-rel. ADD imm. from 11:0. */ ++#define R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 530 /* Likewise; no ovfl. check. */ ++#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12 531 /* DTP-rel. LD/ST imm. 11:0. */ ++#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC 532 /* Likewise; no check. */ ++#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12 533 /* DTP-rel. LD/ST imm. 11:1. */ ++#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC 534 /* Likewise; no check. */ ++#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12 535 /* DTP-rel. LD/ST imm. 11:2. */ ++#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC 536 /* Likewise; no check. */ ++#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12 537 /* DTP-rel. LD/ST imm. 11:3. */ ++#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC 538 /* Likewise; no check. */ ++#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 539 /* GOT-rel. MOV{N,Z} 31:16. */ ++#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC 540 /* GOT-rel. MOVK 15:0. */ ++#define R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 541 /* Page-rel. ADRP 32:12. */ ++#define R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC 542 /* Direct LD off. 11:3. */ ++#define R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 543 /* PC-rel. load imm. 20:2. */ ++#define R_AARCH64_TLSLE_MOVW_TPREL_G2 544 /* TLS TP-rel. MOV{N,Z} 47:32. */ ++#define R_AARCH64_TLSLE_MOVW_TPREL_G1 545 /* TLS TP-rel. MOV{N,Z} 31:16. */ ++#define R_AARCH64_TLSLE_MOVW_TPREL_G1_NC 546 /* Likewise; MOVK; no check. */ ++#define R_AARCH64_TLSLE_MOVW_TPREL_G0 547 /* TLS TP-rel. MOV{N,Z} 15:0. */ ++#define R_AARCH64_TLSLE_MOVW_TPREL_G0_NC 548 /* Likewise; MOVK; no check. */ ++#define R_AARCH64_TLSLE_ADD_TPREL_HI12 549 /* TP-rel. ADD imm. 23:12. */ ++#define R_AARCH64_TLSLE_ADD_TPREL_LO12 550 /* TP-rel. ADD imm. 11:0. */ ++#define R_AARCH64_TLSLE_ADD_TPREL_LO12_NC 551 /* Likewise; no ovfl. check. */ ++#define R_AARCH64_TLSLE_LDST8_TPREL_LO12 552 /* TP-rel. LD/ST off. 11:0. */ ++#define R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC 553 /* Likewise; no ovfl. check. */ ++#define R_AARCH64_TLSLE_LDST16_TPREL_LO12 554 /* TP-rel. LD/ST off. 11:1. */ ++#define R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC 555 /* Likewise; no check. */ ++#define R_AARCH64_TLSLE_LDST32_TPREL_LO12 556 /* TP-rel. LD/ST off. 11:2. */ ++#define R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC 557 /* Likewise; no check. */ ++#define R_AARCH64_TLSLE_LDST64_TPREL_LO12 558 /* TP-rel. LD/ST off. 11:3. */ ++#define R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC 559 /* Likewise; no check. */ ++#define R_AARCH64_TLSDESC_LD_PREL19 560 /* PC-rel. load immediate 20:2. */ ++#define R_AARCH64_TLSDESC_ADR_PREL21 561 /* PC-rel. ADR immediate 20:0. */ ++#define R_AARCH64_TLSDESC_ADR_PAGE21 562 /* Page-rel. ADRP imm. 32:12. */ ++#define R_AARCH64_TLSDESC_LD64_LO12 563 /* Direct LD off. from 11:3. */ ++#define R_AARCH64_TLSDESC_ADD_LO12 564 /* Direct ADD imm. from 11:0. */ ++#define R_AARCH64_TLSDESC_OFF_G1 565 /* GOT-rel. MOV{N,Z} imm. 31:16. */ ++#define R_AARCH64_TLSDESC_OFF_G0_NC 566 /* GOT-rel. MOVK imm. 15:0; no ck. */ ++#define R_AARCH64_TLSDESC_LDR 567 /* Relax LDR. */ ++#define R_AARCH64_TLSDESC_ADD 568 /* Relax ADD. */ ++#define R_AARCH64_TLSDESC_CALL 569 /* Relax BLR. */ ++#define R_AARCH64_TLSLE_LDST128_TPREL_LO12 570 /* TP-rel. LD/ST off. 11:4. */ ++#define R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC 571 /* Likewise; no check. */ ++#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12 572 /* DTP-rel. LD/ST imm. 11:4. */ ++#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC 573 /* Likewise; no check. */ + #define R_AARCH64_COPY 1024 /* Copy symbol at runtime. */ + #define R_AARCH64_GLOB_DAT 1025 /* Create GOT entry. */ + #define R_AARCH64_JUMP_SLOT 1026 /* Create PLT entry. */ +@@ -2335,6 +2446,7 @@ typedef Elf32_Addr Elf32_Conflict; + #define R_AARCH64_TLS_DTPREL64 1029 /* Module-relative offset, 64 bit. */ + #define R_AARCH64_TLS_TPREL64 1030 /* TP-relative offset, 64 bit. */ + #define R_AARCH64_TLSDESC 1031 /* TLS Descriptor. */ ++#define R_AARCH64_IRELATIVE 1032 /* STT_GNU_IFUNC relocation. */ + + /* ARM relocs. */ + +diff --git glibc-2.17-c758a686/ports/sysdeps/aarch64/dl-irel.h glibc-2.17-c758a686/ports/sysdeps/aarch64/dl-irel.h +index 32dee0f..9a48dc2 100644 +--- glibc-2.17-c758a686/ports/sysdeps/aarch64/dl-irel.h ++++ glibc-2.17-c758a686/ports/sysdeps/aarch64/dl-irel.h +@@ -1,6 +1,6 @@ + /* Machine-dependent ELF indirect relocation inline functions. + AArch64 version. +- Copyright (C) 2012 Free Software Foundation, Inc. ++ Copyright (C) 2012-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or +@@ -22,15 +22,31 @@ + + #include + #include ++#include + +-/* AArch64 does not yet implement IFUNC support. However since +- 2011-06-20 provision of a elf_ifunc_invoke has been mandatory. */ ++#define ELF_MACHINE_IRELA 1 + + static inline ElfW(Addr) + __attribute ((always_inline)) + elf_ifunc_invoke (ElfW(Addr) addr) + { +- return ((ElfW(Addr) (*) (void)) (addr)) (); ++ return ((ElfW(Addr) (*) (unsigned long int)) (addr)) (GLRO(dl_hwcap)); ++} ++ ++static inline void ++__attribute ((always_inline)) ++elf_irela (const ElfW(Rela) *reloc) ++{ ++ ElfW(Addr) *const reloc_addr = (void *) reloc->r_offset; ++ const unsigned long int r_type = ELFW(R_TYPE) (reloc->r_info); ++ ++ if (__glibc_likely (r_type == R_AARCH64_IRELATIVE)) ++ { ++ ElfW(Addr) value = elf_ifunc_invoke (reloc->r_addend); ++ *reloc_addr = value; ++ } ++ else ++ __libc_fatal ("unexpected reloc type in static binary"); + } + + #endif +diff --git glibc-2.17-c758a686/ports/sysdeps/aarch64/dl-machine.h glibc-2.17-c758a686/ports/sysdeps/aarch64/dl-machine.h +index b1878a7..1db5a5b 100644 +--- glibc-2.17-c758a686/ports/sysdeps/aarch64/dl-machine.h ++++ glibc-2.17-c758a686/ports/sysdeps/aarch64/dl-machine.h +@@ -23,6 +23,7 @@ + + #include + #include ++#include + + /* Return nonzero iff ELF header is compatible with the running host. */ + static inline int __attribute__ ((unused)) +@@ -336,6 +337,12 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, + } + break; + ++ case R_AARCH64_IRELATIVE: ++ value = map->l_addr + reloc->r_addend; ++ value = elf_ifunc_invoke (value); ++ *reloc_addr = value; ++ break; ++ + default: + _dl_reloc_bad_type (map, r_type, 0); + break; +@@ -379,6 +386,13 @@ elf_machine_lazy_rel (struct link_map *map, + td->entry = (void*)(D_PTR (map, l_info[ADDRIDX (DT_TLSDESC_PLT)]) + + map->l_addr); + } ++ else if (__glibc_unlikely (r_type == R_AARCH64_IRELATIVE)) ++ { ++ ElfW(Addr) value = map->l_addr + reloc->r_addend; ++ if (__glibc_likely (!skip_ifunc)) ++ value = elf_ifunc_invoke (value); ++ *reloc_addr = value; ++ } + else + _dl_reloc_bad_type (map, r_type, 1); + } diff --git a/SOURCES/glibc-aarch64-rh1076760.patch b/SOURCES/glibc-aarch64-rh1076760.patch new file mode 100644 index 0000000..801bfd6 --- /dev/null +++ b/SOURCES/glibc-aarch64-rh1076760.patch @@ -0,0 +1,20 @@ +--- glibc-2.17-c758a686/ports/sysdeps/aarch64/nptl/tls.h ++++ glibc-2.17-c758a686/ports/sysdeps/aarch64/nptl/tls.h +@@ -63,7 +63,7 @@ typedef struct + # define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + + /* Alignment requirements for the initial TCB. */ +-# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) ++# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) + + /* This is the size of the TCB. */ + # define TLS_TCB_SIZE sizeof (tcbhead_t) +@@ -72,7 +72,7 @@ typedef struct + # define TLS_PRE_TCB_SIZE sizeof (struct pthread) + + /* Alignment requirements for the TCB. */ +-# define TLS_TCB_ALIGN __alignof__ (tcbhead_t) ++# define TLS_TCB_ALIGN __alignof__ (struct pthread) + + /* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ diff --git a/SOURCES/glibc-aarch64-syscall-rewrite.patch b/SOURCES/glibc-aarch64-syscall-rewrite.patch new file mode 100644 index 0000000..ad4ab32 --- /dev/null +++ b/SOURCES/glibc-aarch64-syscall-rewrite.patch @@ -0,0 +1,540 @@ +From 9a7cb556eef7cb75b31d0bc05f73c6338dfd8e49 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Fri, 30 May 2014 13:57:04 -0400 +Subject: [PATCH] aarch64: Backport syscall rewrite + +From commits: +a60339aaff82beadea6f580e587d64052cb5e3b8 Fix handling of nocancel syscall... +3612eb8f25d978e7e4ac536a34098091f737161c Merge rtld_errno offset w/ mem ref +a6b3657be6bc5067aeec98d990f60765361c6557 Merge __local_multiple_threads ofs... +c69abcee726a6f63d9e5e8f0d9dcc79374ee3ef8 Fix DO_CALL block comment +6e6c2d01ebb1ef839675c7151d2a114f53663386 Remove DOARGS/UNDOARGS macros +ca3cfa40c16ef34c74951a07a57cfcbcd58898b1 Tidy syscall error check +af4e8ef9443e258ebeb0ddf3c5c9579f24dfacd5 Tabify sysdep-cancel.h +a8b4f04ad7dff4f39797a7ab7f8babda54266026 Share code in sysdep-cancel.h +645d44abe3ca6253a9d4762f092e4a1b9d294b11 Pass regno parameter to SINGLE_THREAD_P +b5be4597716eff94149f5529c8eb2cd3b4296188 Improve syscall-cancel stack frame +74f31c18593111725478a991b395ae45661985a3 Fix error return from __ioctl +f0712b543eaddeca8fc6d7a8eb6b5b8d24105ce2 Remove PSEUDO_RET + +And a not-yet-committed cleanup to clone.S. +--- + ports/sysdeps/unix/sysv/linux/aarch64/clone.S | 51 +++--- + ports/sysdeps/unix/sysv/linux/aarch64/ioctl.S | 13 +- + .../unix/sysv/linux/aarch64/nptl/localplt.data | 1 - + .../unix/sysv/linux/aarch64/nptl/sysdep-cancel.h | 189 +++++++-------------- + ports/sysdeps/unix/sysv/linux/aarch64/syscall.S | 4 +- + ports/sysdeps/unix/sysv/linux/aarch64/sysdep.h | 84 ++------- + ports/sysdeps/unix/sysv/linux/aarch64/vfork.S | 4 +- + 7 files changed, 108 insertions(+), 238 deletions(-) + +diff --git glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/clone.S glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/clone.S +index 8be1464..d5c31f3 100644 +--- glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/clone.S ++++ glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/clone.S +@@ -39,46 +39,43 @@ + */ + .text + ENTRY(__clone) ++ /* Save args for the child. */ ++ mov x10, x0 ++ mov x11, x2 ++ mov x12, x3 ++ + /* Sanity check args. */ +- cbz x0, 1f +- cbz x1, 1f +- /* Insert the args onto the new stack. */ +- stp x0, x3, [x1, #-16]! /* Fn, arg. */ ++ mov x0, #-EINVAL ++ cbz x10, .Lsyscall_error ++ cbz x1, .Lsyscall_error + + /* Do the system call. */ ++ /* X0:flags, x1:newsp, x2:parenttidptr, x3:newtls, x4:childtid. */ + mov x0, x2 /* flags */ +- + /* New sp is already in x1. */ + mov x2, x4 /* ptid */ + mov x3, x5 /* tls */ + mov x4, x6 /* ctid */ + +-#ifdef RESET_PID +- /* We rely on the kernel preserving the argument regsiters across a +- each system call so that we can inspect the flags against after +- the clone call. */ +- mov x5, x0 +-#endif +- + mov x8, #SYS_ify(clone) +- /* X0:flags, x1:newsp, x2:parenttidptr, x3:newtls, x4:childtid. */ + svc 0x0 +- cfi_endproc + cmp x0, #0 +- beq 2f +- blt C_SYMBOL_NAME(__syscall_error) ++ beq thread_start ++ blt .Lsyscall_error + RET +-1: mov x0, #-EINVAL +- b syscall_error ++PSEUDO_END (__clone) + +-2: ++ .align 4 ++ .type thread_start, %function ++thread_start: + cfi_startproc + cfi_undefined (x30) + mov x29, 0 ++ + #ifdef RESET_PID +- tbnz x5, #CLONE_THREAD_BIT, 3f ++ tbnz x11, #CLONE_THREAD_BIT, 3f + mov x0, #-1 +- tbnz x5, #CLONE_VM_BIT, 2f ++ tbnz x11, #CLONE_VM_BIT, 2f + mov x8, #SYS_ify(getpid) + svc 0x0 + 2: +@@ -86,18 +83,16 @@ ENTRY(__clone) + sub x1, x1, #PTHREAD_SIZEOF + str w0, [x1, #PTHREAD_PID_OFFSET] + str w0, [x1, #PTHREAD_TID_OFFSET] +- + 3: + #endif +- /* Pick the function arg and call address from the stack and +- execute. */ +- ldp x1, x0, [sp], #16 +- blr x1 ++ ++ /* Pick the function arg execute. */ ++ mov x0, x12 ++ blr x10 + + /* We are done, pass the return value through x0. */ + b HIDDEN_JUMPTARGET(_exit) + cfi_endproc +- cfi_startproc +-PSEUDO_END (__clone) ++ .size thread_start, .-thread_start + + weak_alias (__clone, clone) +diff --git glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/ioctl.S glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/ioctl.S +index f01fb84..be6c026 100644 +--- glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/ioctl.S ++++ glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/ioctl.S +@@ -20,13 +20,12 @@ + + .text + ENTRY(__ioctl) +- movz x8, #__NR_ioctl +- sxtw x0, w0 +- svc #0x0 +- cmn x0, #0x1, lsl #12 +- b.hi C_SYMBOL_NAME(__syscall_error) ++ mov x8, #__NR_ioctl ++ sxtw x0, w0 ++ svc #0x0 ++ cmn x0, #4095 ++ b.cs .Lsyscall_error + ret +- +- PSEUDO_END (__ioctl) ++PSEUDO_END (__ioctl) + + weak_alias (__ioctl, ioctl) +diff --git glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/nptl/localplt.data glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/nptl/localplt.data +index 84af95d..dfca9a7 100644 +--- glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/nptl/localplt.data ++++ glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/nptl/localplt.data +@@ -12,4 +12,3 @@ libm.so: matherr + libm.so: __signbit + libm.so: __signbitf + libm.so: __signbitl +-libpthread.so: __errno_location +diff --git glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/nptl/sysdep-cancel.h glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/nptl/sysdep-cancel.h +index e0e5cc0..a3b9284 100644 +--- glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/nptl/sysdep-cancel.h ++++ glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/nptl/sysdep-cancel.h +@@ -26,119 +26,60 @@ + + # undef PSEUDO + # define PSEUDO(name, syscall_name, args) \ +- .section ".text"; \ +- .type __##syscall_name##_nocancel,%function; \ +- .globl __##syscall_name##_nocancel; \ +- __##syscall_name##_nocancel: \ +- cfi_startproc; \ +- DO_CALL (syscall_name, args); \ +- PSEUDO_RET; \ +- cfi_endproc; \ +- .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \ +- ENTRY (name); \ +- SINGLE_THREAD_P; \ +- DOARGS_##args; \ +- bne .Lpseudo_cancel; \ +- DO_CALL (syscall_name, 0); \ +- UNDOARGS_##args; \ +- cmn x0, 4095; \ +- PSEUDO_RET; \ +- .Lpseudo_cancel: \ +- DOCARGS_##args; /* save syscall args etc. around CENABLE. */ \ +- CENABLE; \ +- mov x16, x0; /* put mask in safe place. */ \ +- UNDOCARGS_##args; /* restore syscall args. */ \ +- mov x8, SYS_ify (syscall_name); /* do the call. */ \ +- svc 0; \ +- str x0, [sp, -16]!; /* save syscall return value. */ \ +- cfi_adjust_cfa_offset (16); \ +- mov x0, x16; /* get mask back. */ \ +- CDISABLE; \ +- ldr x0, [sp], 16; \ +- cfi_adjust_cfa_offset (-16); \ +- ldr x30, [sp], 16; \ +- cfi_adjust_cfa_offset (-16); \ +- cfi_restore (x30); \ +- UNDOARGS_##args; \ +- cmn x0, 4095; +- +-# define DOCARGS_0 \ +- str x30, [sp, -16]!; \ +- cfi_adjust_cfa_offset (16); \ +- cfi_rel_offset (x30, 0) ++ .section ".text"; \ ++ENTRY (__##syscall_name##_nocancel); \ ++.Lpseudo_nocancel: \ ++ DO_CALL (syscall_name, args); \ ++.Lpseudo_finish: \ ++ cmn x0, 4095; \ ++ b.cs .Lsyscall_error; \ ++ .subsection 2; \ ++ .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \ ++ENTRY (name); \ ++ SINGLE_THREAD_P(16); \ ++ cbz w16, .Lpseudo_nocancel; \ ++ /* Setup common stack frame no matter the number of args. \ ++ Also save the first arg, since it's basically free. */ \ ++ stp x30, x0, [sp, -64]!; \ ++ cfi_adjust_cfa_offset (64); \ ++ cfi_rel_offset (x30, 0); \ ++ DOCARGS_##args; /* save syscall args around CENABLE. */ \ ++ CENABLE; \ ++ mov x16, x0; /* save mask around syscall. */ \ ++ UNDOCARGS_##args; /* restore syscall args. */ \ ++ DO_CALL (syscall_name, args); \ ++ str x0, [sp, 8]; /* save result around CDISABLE. */ \ ++ mov x0, x16; /* restore mask for CDISABLE. */ \ ++ CDISABLE; \ ++ /* Break down the stack frame, restoring result at once. */ \ ++ ldp x30, x0, [sp], 64; \ ++ cfi_adjust_cfa_offset (-64); \ ++ cfi_restore (x30); \ ++ b .Lpseudo_finish; \ ++ cfi_endproc; \ ++ .size name, .-name; \ ++ .previous ++ ++# undef PSEUDO_END ++# define PSEUDO_END(name) \ ++ SYSCALL_ERROR_HANDLER; \ ++ cfi_endproc ++ ++# define DOCARGS_0 ++# define DOCARGS_1 ++# define DOCARGS_2 str x1, [sp, 16] ++# define DOCARGS_3 stp x1, x2, [sp, 16] ++# define DOCARGS_4 DOCARGS_3; str x3, [sp, 32] ++# define DOCARGS_5 DOCARGS_3; stp x3, x4, [sp, 32] ++# define DOCARGS_6 DOCARGS_5; str x5, [sp, 48] + + # define UNDOCARGS_0 +- +-# define DOCARGS_1 \ +- DOCARGS_0; \ +- str x0, [sp, -16]!; \ +- cfi_adjust_cfa_offset (16); \ +- cfi_rel_offset (x0, 0) +- +-# define UNDOCARGS_1 \ +- ldr x0, [sp], 16; \ +- cfi_restore (x0); \ +- cfi_adjust_cfa_offset (-16); \ +- +-# define DOCARGS_2 \ +- DOCARGS_1; \ +- str x1, [sp, -16]!; \ +- cfi_adjust_cfa_offset (16); \ +- cfi_rel_offset (x1, 0) +- +-# define UNDOCARGS_2 \ +- ldr x1, [sp], 16; \ +- cfi_restore (x1); \ +- cfi_adjust_cfa_offset (-16); \ +- UNDOCARGS_1 +- +-# define DOCARGS_3 \ +- DOCARGS_2; \ +- str x2, [sp, -16]!; \ +- cfi_adjust_cfa_offset (16); \ +- cfi_rel_offset (x2, 0) +- +-# define UNDOCARGS_3 \ +- ldr x2, [sp], 16; \ +- cfi_restore (x2); \ +- cfi_adjust_cfa_offset (-16); \ +- UNDOCARGS_2 +- +-# define DOCARGS_4 \ +- DOCARGS_3; \ +- str x3, [sp, -16]!; \ +- cfi_adjust_cfa_offset (16); \ +- cfi_rel_offset (x3, 0) +- +-# define UNDOCARGS_4 \ +- ldr x3, [sp], 16; \ +- cfi_restore (x3); \ +- cfi_adjust_cfa_offset (-16); \ +- UNDOCARGS_3 +- +-# define DOCARGS_5 \ +- DOCARGS_4; \ +- str x4, [sp, -16]!; \ +- cfi_adjust_cfa_offset (16); \ +- cfi_rel_offset (x4, 0) +- +-# define UNDOCARGS_5 \ +- ldr x4, [sp], 16; \ +- cfi_restore (x4); \ +- cfi_adjust_cfa_offset (-16); \ +- UNDOCARGS_4 +- +-# define DOCARGS_6 \ +- DOCARGS_5; \ +- str x5, [sp, -16]!; \ +- cfi_adjust_cfa_offset (16); \ +- cfi_rel_offset (x5, 0) +- +-# define UNDOCARGS_6 \ +- ldr x5, [sp], 16; \ +- cfi_restore (x5); \ +- cfi_adjust_cfa_offset (-16); \ +- UNDOCARGS_5 ++# define UNDOCARGS_1 ldr x0, [sp, 8] ++# define UNDOCARGS_2 ldp x0, x1, [sp, 8] ++# define UNDOCARGS_3 UNDOCARGS_1; ldp x1, x2, [sp, 16] ++# define UNDOCARGS_4 UNDOCARGS_2; ldp x2, x3, [sp, 24] ++# define UNDOCARGS_5 UNDOCARGS_3; ldp x3, x4, [sp, 32] ++# define UNDOCARGS_6 UNDOCARGS_4; ldp x4, x5, [sp, 40] + + # ifdef IS_IN_libpthread + # define CENABLE bl __pthread_enable_asynccancel +@@ -160,11 +101,9 @@ + extern int __local_multiple_threads attribute_hidden; + # define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) + # else +-# define SINGLE_THREAD_P \ +- adrp x16, __local_multiple_threads; \ +- add x16, x16, #:lo12:__local_multiple_threads; \ +- ldr x16, [x16]; \ +- cmp x16, 0; ++# define SINGLE_THREAD_P(R) \ ++ adrp x##R, __local_multiple_threads; \ ++ ldr w##R, [x##R, :lo12:__local_multiple_threads] + # endif + # else + /* There is no __local_multiple_threads for librt, so use the TCB. */ +@@ -173,20 +112,10 @@ extern int __local_multiple_threads attribute_hidden; + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) + # else +-# define SINGLE_THREAD_P \ +- stp x0, x30, [sp, -16]!; \ +- cfi_adjust_cfa_offset (16); \ +- cfi_rel_offset (x0, 0); \ +- cfi_rel_offset (x30, 8); \ +- bl __read_tp; \ +- sub x0, x0, PTHREAD_SIZEOF; \ +- ldr x16, [x0, PTHREAD_MULTIPLE_THREADS_OFFSET]; \ +- ldp x0, x30, [sp], 16; \ +- cfi_restore (x0); \ +- cfi_restore (x30); \ +- cfi_adjust_cfa_offset (-16); \ +- cmp x16, 0 +-# define SINGLE_THREAD_P_PIC(x) SINGLE_THREAD_P ++# define SINGLE_THREAD_P(R) \ ++ mrs x##R, tpidr_el0; \ ++ sub x##R, x##R, PTHREAD_SIZEOF; \ ++ ldr w##R, [x##R, PTHREAD_MULTIPLE_THREADS_OFFSET] + # endif + # endif + +diff --git glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/syscall.S glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/syscall.S +index 574fdf1..fac6416 100644 +--- glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/syscall.S ++++ glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/syscall.S +@@ -37,8 +37,6 @@ ENTRY (syscall) + mov x6, x7 + svc 0x0 + cmn x0, #4095 +- b.cs 1f ++ b.cs .Lsyscall_error + RET +-1: +- b SYSCALL_ERROR + PSEUDO_END (syscall) +diff --git glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/sysdep.h glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/sysdep.h +index 713bf7d..9961c03 100644 +--- glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/sysdep.h ++++ glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/sysdep.h +@@ -58,19 +58,8 @@ + .text; \ + ENTRY (name); \ + DO_CALL (syscall_name, args); \ +- cmn x0, #4095; +- +-/* Notice the use of 'RET' instead of 'ret' the assembler is case +- insensitive and eglibc already uses the preprocessor symbol 'ret' +- so we use the upper case 'RET' to force through a ret instruction +- to the assembler */ +-# define PSEUDO_RET \ +- b.cs 1f; \ +- RET; \ +- 1: \ +- b SYSCALL_ERROR +-# undef ret +-# define ret PSEUDO_RET ++ cmn x0, #4095; \ ++ b.cs .Lsyscall_error + + # undef PSEUDO_END + # define PSEUDO_END(name) \ +@@ -83,15 +72,7 @@ + ENTRY (name); \ + DO_CALL (syscall_name, args); + +-/* Notice the use of 'RET' instead of 'ret' the assembler is case +- insensitive and eglibc already uses the preprocessor symbol 'ret' +- so we use the upper case 'RET' to force through a ret instruction +- to the assembler */ +-# define PSEUDO_RET_NOERRNO \ +- RET; +- +-# undef ret_NOERRNO +-# define ret_NOERRNO PSEUDO_RET_NOERRNO ++# define ret_NOERRNO ret + + # undef PSEUDO_END_NOERRNO + # define PSEUDO_END_NOERRNO(name) \ +@@ -109,47 +90,38 @@ + # define PSEUDO_END_ERRVAL(name) \ + END (name) + +-# define ret_ERRVAL PSEUDO_RET_NOERRNO ++# define ret_ERRVAL ret + ++# define SYSCALL_ERROR .Lsyscall_error + # if NOT_IN_libc +-# define SYSCALL_ERROR __local_syscall_error + # if RTLD_PRIVATE_ERRNO + # define SYSCALL_ERROR_HANDLER \ +-__local_syscall_error: \ ++.Lsyscall_error: \ + adrp x1, C_SYMBOL_NAME(rtld_errno); \ +- add x1, x1, #:lo12:C_SYMBOL_NAME(rtld_errno); \ + neg w0, w0; \ +- str w0, [x1]; \ ++ str w0, [x1, :lo12:C_SYMBOL_NAME(rtld_errno)]; \ + mov x0, -1; \ + RET; + # else + + # define SYSCALL_ERROR_HANDLER \ +-__local_syscall_error: \ +- stp x29, x30, [sp, -32]!; \ +- cfi_adjust_cfa_offset (32); \ +- cfi_rel_offset (x29, 0); \ +- cfi_rel_offset (x30, 8); \ +- add x29, sp, 0; \ +- str x19, [sp,16]; \ +- neg x19, x0; \ +- bl C_SYMBOL_NAME(__errno_location); \ +- str x19, [x0]; \ ++.Lsyscall_error: \ ++ adrp x1, :gottprel:errno; \ ++ neg w2, w0; \ ++ ldr x1, [x1, :gottprel_lo12:errno]; \ ++ mrs x3, tpidr_el0; \ + mov x0, -1; \ +- ldr x19, [sp,16]; \ +- ldp x29, x30, [sp], 32; \ +- cfi_adjust_cfa_offset (-32); \ +- cfi_restore (x29); \ +- cfi_restore (x30); \ ++ str w2, [x1, x3]; \ + RET; + # endif + # else +-# define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */ +-# define SYSCALL_ERROR __syscall_error ++# define SYSCALL_ERROR_HANDLER \ ++.Lsyscall_error: \ ++ b __syscall_error; + # endif + + /* Linux takes system call args in registers: +- syscall number in the SVC instruction ++ syscall number x8 + arg 1 x0 + arg 2 x1 + arg 3 x2 +@@ -177,28 +149,8 @@ __local_syscall_error: \ + + # undef DO_CALL + # define DO_CALL(syscall_name, args) \ +- DOARGS_##args \ + mov x8, SYS_ify (syscall_name); \ +- svc 0; \ +- UNDOARGS_##args +- +-# define DOARGS_0 /* nothing */ +-# define DOARGS_1 /* nothing */ +-# define DOARGS_2 /* nothing */ +-# define DOARGS_3 /* nothing */ +-# define DOARGS_4 /* nothing */ +-# define DOARGS_5 /* nothing */ +-# define DOARGS_6 /* nothing */ +-# define DOARGS_7 /* nothing */ +- +-# define UNDOARGS_0 /* nothing */ +-# define UNDOARGS_1 /* nothing */ +-# define UNDOARGS_2 /* nothing */ +-# define UNDOARGS_3 /* nothing */ +-# define UNDOARGS_4 /* nothing */ +-# define UNDOARGS_5 /* nothing */ +-# define UNDOARGS_6 /* nothing */ +-# define UNDOARGS_7 /* nothing */ ++ svc 0 + + #else /* not __ASSEMBLER__ */ + +diff --git glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/vfork.S glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/vfork.S +index f2dc49b..3fb68b9 100644 +--- glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/vfork.S ++++ glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/aarch64/vfork.S +@@ -38,10 +38,8 @@ ENTRY (__vfork) + RESTORE_PID + #endif + cmn x0, #4095 +- b.cs 1f ++ b.cs .Lsyscall_error + RET +-1: +- b SYSCALL_ERROR + + PSEUDO_END (__vfork) + libc_hidden_def (__vfork) +-- +1.8.3.1 + diff --git a/SOURCES/glibc-arm-hardfloat-3.patch b/SOURCES/glibc-arm-hardfloat-3.patch new file mode 100644 index 0000000..d9bebf3 --- /dev/null +++ b/SOURCES/glibc-arm-hardfloat-3.patch @@ -0,0 +1,22 @@ +(Not needed anymore.) + +diff -Nru glibc-2.17-c758a686/elf/dl-load.c glibc-2.17-c758a686/elf/dl-load.c +--- glibc-2.17-c758a686/elf/dl-load.c 2012-06-06 13:07:41.727524312 -0600 ++++ glibc-2.17-c758a686/elf/dl-load.c 2012-06-06 13:11:19.308681002 -0600 +@@ -2093,10 +2093,14 @@ _dl_map_object (struct link_map *loader, + soname = ((const char *) D_PTR (l, l_info[DT_STRTAB]) + + l->l_info[DT_SONAME]->d_un.d_val); + if (strcmp (name, soname) != 0) +- continue; ++#ifdef __arm__ ++ if (strcmp (name, "ld-linux.so.3") ++ || strcmp (soname, "ld-linux-armhf.so.3")) ++#endif ++ continue; + + /* We have a match on a new name -- cache it. */ +- add_name_to_object (l, soname); ++ add_name_to_object (l, name); + l->l_soname_added = 1; + } + diff --git a/SOURCES/glibc-cs-path.patch b/SOURCES/glibc-cs-path.patch new file mode 100644 index 0000000..c94a49a --- /dev/null +++ b/SOURCES/glibc-cs-path.patch @@ -0,0 +1,6 @@ +diff -pruN glibc-2.17-c758a686/sysdeps/unix/confstr.h glibc-2.17-c758a686/sysdeps/unix/confstr.h +--- glibc-2.17-c758a686/sysdeps/unix/confstr.h 2012-12-25 08:32:13.000000000 +0530 ++++ glibc-2.17-c758a686/sysdeps/unix/confstr.h 2014-09-05 20:02:55.698275219 +0530 +@@ -1 +1 @@ +-#define CS_PATH "/bin:/usr/bin" ++#define CS_PATH "/usr/bin" diff --git a/SOURCES/glibc-fedora-__libc_multiple_libcs.patch b/SOURCES/glibc-fedora-__libc_multiple_libcs.patch new file mode 100644 index 0000000..54c6d42 --- /dev/null +++ b/SOURCES/glibc-fedora-__libc_multiple_libcs.patch @@ -0,0 +1,83 @@ +From 16552c01a66633c9e412984d9d92616bd4e5303c Mon Sep 17 00:00:00 2001 +From: Andreas Schwab +Date: Fri, 11 Jun 2010 11:04:11 +0200 +Subject: [PATCH] Properly set __libc_multiple_libcs + +* elf/rtld.c (_dl_starting_up): Always define. +(dl_main): Always set _dl_starting_up. +* elf/dl-support.c (_dl_starting_up): Always define. +* elf/dl-init.c (_dl_init): Always clear _dl_starting_up. + +--- + ChangeLog | 7 +++++++ + elf/dl-init.c | 4 ---- + elf/dl-support.c | 2 -- + elf/rtld.c | 4 ---- + 4 files changed, 7 insertions(+), 10 deletions(-) + +--- glibc-2.17-c758a686/elf/dl-init.c ++++ glibc-2.17-c758a686/elf/dl-init.c +@@ -23,11 +23,9 @@ + /* Type of the initializer. */ + typedef void (*init_t) (int, char **, char **); + +-#ifndef HAVE_INLINED_SYSCALLS + /* Flag, nonzero during startup phase. */ + extern int _dl_starting_up; + extern int _dl_starting_up_internal attribute_hidden; +-#endif + + + static void +@@ -132,9 +130,7 @@ _dl_init (struct link_map *main_map, int argc, char **argv, char **env) + while (i-- > 0) + call_init (main_map->l_initfini[i], argc, argv, env); + +-#ifndef HAVE_INLINED_SYSCALLS + /* Finished starting up. */ + INTUSE(_dl_starting_up) = 0; +-#endif + } + INTDEF (_dl_init) +--- glibc-2.17-c758a686/elf/dl-support.c ++++ glibc-2.17-c758a686/elf/dl-support.c +@@ -81,10 +81,8 @@ unsigned long long _dl_load_adds; + create a fake scope containing nothing. */ + struct r_scope_elem _dl_initial_searchlist; + +-#ifndef HAVE_INLINED_SYSCALLS + /* Nonzero during startup. */ + int _dl_starting_up = 1; +-#endif + + /* Random data provided by the kernel. */ + void *_dl_random; +--- glibc-2.17-c758a686/elf/rtld.c ++++ glibc-2.17-c758a686/elf/rtld.c +@@ -106,7 +106,6 @@ static struct audit_list + struct audit_list *next; + } *audit_list; + +-#ifndef HAVE_INLINED_SYSCALLS + /* Set nonzero during loading and initialization of executable and + libraries, cleared before the executable's entry point runs. This + must not be initialized to nonzero, because the unused dynamic +@@ -116,7 +115,6 @@ static struct audit_list + never be called. */ + int _dl_starting_up = 0; + INTVARDEF(_dl_starting_up) +-#endif + + /* This is the structure which defines all variables global to ld.so + (except those which cannot be added for some reason). */ +@@ -929,10 +927,8 @@ dl_main (const ElfW(Phdr) *phdr, + /* Process the environment variable which control the behaviour. */ + process_envvars (&mode); + +-#ifndef HAVE_INLINED_SYSCALLS + /* Set up a flag which tells we are just starting. */ + INTUSE(_dl_starting_up) = 1; +-#endif + + if (*user_entry == (ElfW(Addr)) ENTRY_POINT) + { diff --git a/SOURCES/glibc-fedora-elf-init-hidden_undef.patch b/SOURCES/glibc-fedora-elf-init-hidden_undef.patch new file mode 100644 index 0000000..df667ec --- /dev/null +++ b/SOURCES/glibc-fedora-elf-init-hidden_undef.patch @@ -0,0 +1,30 @@ +* Fri May 29 2003 Jakub Jelinek 2.3.2-44 +- make __init_array_start etc. symbols in elf-init.oS hidden undefined + +diff -Nru glibc-2.17-c758a686/csu/elf-init.c glibc-2.17-c758a686/csu/elf-init.c +--- glibc-2.17-c758a686/csu/elf-init.c 2012-06-05 07:42:49.000000000 -0600 ++++ glibc-2.17-c758a686/csu/elf-init.c 2012-06-07 12:15:21.570319597 -0600 +@@ -63,6 +63,23 @@ extern void (*__init_array_end []) (int, + extern void (*__fini_array_start []) (void) attribute_hidden; + extern void (*__fini_array_end []) (void) attribute_hidden; + ++#if defined HAVE_VISIBILITY_ATTRIBUTE \ ++ && (defined SHARED || defined LIBC_NONSHARED) ++# define hidden_undef_2(x) #x ++# define hidden_undef_1(x) hidden_undef_2 (x) ++# define hidden_undef(x) \ ++ __asm (hidden_undef_1 (ASM_GLOBAL_DIRECTIVE) " " #x); \ ++ __asm (".hidden " #x); ++#else ++# define hidden_undef(x) ++#endif ++ ++hidden_undef (__preinit_array_start) ++hidden_undef (__preinit_array_end) ++hidden_undef (__init_array_start) ++hidden_undef (__init_array_end) ++hidden_undef (__fini_array_start) ++hidden_undef (__fini_array_end) + + /* These function symbols are provided for the .init/.fini section entry + points automagically by the linker. */ diff --git a/SOURCES/glibc-fedora-elf-rh737223.patch b/SOURCES/glibc-fedora-elf-rh737223.patch new file mode 100644 index 0000000..376f687 --- /dev/null +++ b/SOURCES/glibc-fedora-elf-rh737223.patch @@ -0,0 +1,15 @@ +Binary filesglibc-2.17-c758a686/elf/.rtld.c.rej.swp andglibc-2.17-c758a686/elf/.rtld.c.rej.swp differ +diff -Nru glibc-2.17-c758a686/elf/setup-vdso.h glibc-2.17-c758a686/elf/setup-vdso.h +--- glibc-2.17-c758a686/elf/setup-vdso.h 2012-10-10 21:34:38.000000000 -0600 ++++ glibc-2.17-c758a686/elf/setup-vdso.h 2012-10-11 09:43:14.152958832 -0600 +@@ -93,7 +93,9 @@ setup_vdso (struct link_map *main_map __ + char *copy = malloc (len); + if (copy == NULL) + _dl_fatal_printf ("out of memory\n"); +- l->l_libname->name = l->l_name = memcpy (copy, dsoname, len); ++ l->l_libname->name = memcpy (copy, dsoname, len); ++ if (GLRO(dl_debug_mask)) ++ l->l_name = copy; + } + + /* Add the vDSO to the object list. */ diff --git a/SOURCES/glibc-fedora-gai-canonical.patch b/SOURCES/glibc-fedora-gai-canonical.patch new file mode 100644 index 0000000..7f767ae --- /dev/null +++ b/SOURCES/glibc-fedora-gai-canonical.patch @@ -0,0 +1,124 @@ +Upstream commit, fixing [BZ #15218]: + +commit b957ced8890a4438c8efe2c15e5abf4e327f25cf +Author: Andreas Schwab +Date: Tue Oct 15 10:21:13 2013 +0200 + + Don't use gethostbyaddr to determine canonical name + + +--- glibc-2.17-c758a686/sysdeps/posix/getaddrinfo.c ++++ glibc-2.17-c758a686/sysdeps/posix/getaddrinfo.c +@@ -565,8 +565,8 @@ gaih_inet (const char *name, const struct gaih_service *service, + + /* If we do not have to look for IPv6 addresses, use + the simple, old functions, which do not support +- IPv6 scope ids. */ +- if (req->ai_family == AF_INET) ++ IPv6 scope ids, nor retrieving the canonical name. */ ++ if (req->ai_family == AF_INET && (req->ai_flags & AI_CANONNAME) == 0) + { + /* Allocate additional room for struct host_data. */ + size_t tmpbuflen = (512 + MAX_NR_ALIASES * sizeof(char*) +@@ -1107,70 +1107,10 @@ gaih_inet (const char *name, const struct gaih_service *service, + /* Only the first entry gets the canonical name. */ + if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0) + { +- char *tmpbuf2 = NULL; +- bool malloc_tmpbuf2 = false; +- + if (canon == NULL) +- { +- struct hostent *h = NULL; +- int herrno; +- struct hostent th; +- /* Add room for struct host_data. */ +- size_t tmpbuf2len = (512 + (MAX_NR_ALIASES+MAX_NR_ADDRS+1) +- * sizeof(char*) + 16 * sizeof(char)); +- +- do +- { +- if (__libc_use_alloca (alloca_used + 2 * tmpbuf2len)) +- tmpbuf2 = extend_alloca_account (tmpbuf2, tmpbuf2len, +- tmpbuf2len * 2, +- alloca_used); +- else +- { +- char *newp = realloc (malloc_tmpbuf2 ? tmpbuf2 : NULL, +- 2 * tmpbuf2len); +- if (newp == NULL) +- { +- if (malloc_tmpbuf2) +- free (tmpbuf2); +- result = -EAI_MEMORY; +- goto free_and_return; +- } +- +- tmpbuf2 = newp; +- tmpbuf2len = 2 * tmpbuf2len; +- malloc_tmpbuf2 = true; +- } +- +- rc = __gethostbyaddr_r (at2->addr, +- ((at2->family == AF_INET6) +- ? sizeof (struct in6_addr) +- : sizeof (struct in_addr)), +- at2->family, &th, tmpbuf2, +- tmpbuf2len, &h, &herrno); +- } +- while (rc == ERANGE && herrno == NETDB_INTERNAL); +- +- if (rc != 0 && herrno == NETDB_INTERNAL) +- { +- if (malloc_tmpbuf2) +- free (tmpbuf2); +- +- __set_h_errno (herrno); +- result = -EAI_SYSTEM; +- goto free_and_return; +- } +- +- if (h != NULL) +- canon = h->h_name; +- else +- { +- assert (orig_name != NULL); +- /* If the canonical name cannot be determined, use +- the passed in string. */ +- canon = orig_name; +- } +- } ++ /* If the canonical name cannot be determined, use ++ the passed in string. */ ++ canon = orig_name; + + #ifdef HAVE_LIBIDN + if (req->ai_flags & AI_CANONIDN) +@@ -1185,9 +1125,6 @@ gaih_inet (const char *name, const struct gaih_service *service, + int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags); + if (rc != IDNA_SUCCESS) + { +- if (malloc_tmpbuf2) +- free (tmpbuf2); +- + if (rc == IDNA_MALLOC_ERROR) + result = -EAI_MEMORY; + else if (rc == IDNA_DLOPEN_ERROR) +@@ -1217,17 +1154,11 @@ gaih_inet (const char *name, const struct gaih_service *service, + canon = strdup (canon); + if (canon == NULL) + { +- if (malloc_tmpbuf2) +- free (tmpbuf2); +- + result = -EAI_MEMORY; + goto free_and_return; + } + } + } +- +- if (malloc_tmpbuf2) +- free (tmpbuf2); + } + + family = at2->family; diff --git a/SOURCES/glibc-fedora-getrlimit-PLT.patch b/SOURCES/glibc-fedora-getrlimit-PLT.patch new file mode 100644 index 0000000..43cabea --- /dev/null +++ b/SOURCES/glibc-fedora-getrlimit-PLT.patch @@ -0,0 +1,35 @@ +Related upstream commit: + +commit c5c2b7c3fd823fc5c4a52506292a90eba60b0c62 +Author: Joseph Myers +Date: Sat Dec 6 23:40:48 2014 +0000 + + Fix pthreads getrlimit, gettimeofday namespace (bug 17682). + +--- glibc-2.17-c758a686/include/sys/resource.h ++++ glibc-2.17-c758a686/include/sys/resource.h +@@ -14,5 +14,6 @@ extern int __getrusage (enum __rusage_who __who, struct rusage *__usage) + + extern int __setrlimit (enum __rlimit_resource __resource, + const struct rlimit *__rlimits); ++libc_hidden_proto (__getrlimit) + #endif + #endif +--- glibc-2.17-c758a686/resource/getrlimit.c ++++ glibc-2.17-c758a686/resource/getrlimit.c +@@ -27,6 +27,7 @@ __getrlimit (enum __rlimit_resource resource, struct rlimit *rlimits) + __set_errno (ENOSYS); + return -1; + } ++libc_hidden_def (__getrlimit) + weak_alias (__getrlimit, getrlimit) + + stub_warning (getrlimit) +--- glibc-2.17-c758a686/sysdeps/mach/hurd/getrlimit.c ++++ glibc-2.17-c758a686/sysdeps/mach/hurd/getrlimit.c +@@ -43,4 +43,5 @@ __getrlimit (enum __rlimit_resource resource, struct rlimit *rlimits) + + return 0; + } ++libc_hidden_def (__getrlimit) + weak_alias (__getrlimit, getrlimit) diff --git a/SOURCES/glibc-fedora-i386-tls-direct-seg-refs.patch b/SOURCES/glibc-fedora-i386-tls-direct-seg-refs.patch new file mode 100644 index 0000000..451ebf9 --- /dev/null +++ b/SOURCES/glibc-fedora-i386-tls-direct-seg-refs.patch @@ -0,0 +1,18 @@ +diff -Nru glibc-2.17-c758a686/sysdeps/i386/Makefile glibc-2.17-c758a686/sysdeps/i386/Makefile +--- glibc-2.17-c758a686/sysdeps/i386/Makefile 2012-06-05 07:42:49.000000000 -0600 ++++ glibc-2.17-c758a686/sysdeps/i386/Makefile 2012-06-07 12:15:21.826318641 -0600 +@@ -62,6 +64,14 @@ endif + + ifneq (,$(filter -mno-tls-direct-seg-refs,$(CFLAGS))) + defines += -DNO_TLS_DIRECT_SEG_REFS ++else ++# .a libraries are not performance critical and so we ++# build them without direct TLS segment references ++# always. ++CPPFLAGS-.o += -DNO_TLS_DIRECT_SEG_REFS ++CFLAGS-.o += -mno-tls-direct-seg-refs ++CPPFLAGS-.oS += -DNO_TLS_DIRECT_SEG_REFS ++CFLAGS-.oS += -mno-tls-direct-seg-refs + endif + + ifeq ($(subdir),elf) diff --git a/SOURCES/glibc-fedora-include-bits-ldbl.patch b/SOURCES/glibc-fedora-include-bits-ldbl.patch new file mode 100644 index 0000000..0aa3c0f --- /dev/null +++ b/SOURCES/glibc-fedora-include-bits-ldbl.patch @@ -0,0 +1,36 @@ +Only needed for glibc builds with -mlong-double-64: + + https://sourceware.org/ml/libc-alpha/2017-08/msg01139.html + +This means the patch is no longer needed. + +From 5eb4509a6651d19c7a28c4506d6aa582c9ee095a Mon Sep 17 00:00:00 2001 +From: Jakub Jelinek +Date: Wed, 1 Feb 2006 09:30:43 +0000 +Subject: [PATCH] 128-bit long double fixes + +* include/bits/stdlib-ldbl.h: New file. +* include/bits/wchar-ldbl.h: New file. + +--- + ChangeLog | 5 +++++ + include/bits/stdlib-ldbl.h | 1 + + include/bits/wchar-ldbl.h | 1 + + 3 files changed, 7 insertions(+), 0 deletions(-) + create mode 100644 include/bits/stdlib-ldbl.h + create mode 100644 include/bits/wchar-ldbl.h + +diff --git glibc-2.17-c758a686/include/bits/stdlib-ldbl.h glibc-2.17-c758a686/include/bits/stdlib-ldbl.h +new file mode 100644 +index 0000000..6250949 +--- /dev/null ++++ glibc-2.17-c758a686/include/bits/stdlib-ldbl.h +@@ -0,0 +1 @@ ++#include +diff --git glibc-2.17-c758a686/include/bits/wchar-ldbl.h glibc-2.17-c758a686/include/bits/wchar-ldbl.h +new file mode 100644 +index 0000000..29baa2f +--- /dev/null ++++ glibc-2.17-c758a686/include/bits/wchar-ldbl.h +@@ -0,0 +1 @@ ++#include diff --git a/SOURCES/glibc-fedora-ldd.patch b/SOURCES/glibc-fedora-ldd.patch new file mode 100644 index 0000000..28f18d3 --- /dev/null +++ b/SOURCES/glibc-fedora-ldd.patch @@ -0,0 +1,38 @@ +Upstream commit: + +commit eedca9772e99c72ab4c3c34e43cc764250aa3e3c (HEAD -> master) +Author: Andreas Schwab +Date: Wed Aug 16 15:59:55 2017 +0200 + + ldd: never run file directly + +--- glibc-2.17-c758a686/elf/ldd.bash.in ++++ glibc-2.17-c758a686/elf/ldd.bash.in +@@ -166,18 +166,6 @@ warning: you do not have execution permission for" "\`$file'" >&2 + fi + done + case $ret in +- 0) +- # If the program exits with exit code 5, it means the process has been +- # invoked with __libc_enable_secure. Fall back to running it through +- # the dynamic linker. +- try_trace "$file" +- rc=$? +- if [ $rc = 5 ]; then +- try_trace "$RTLD" "$file" +- rc=$? +- fi +- [ $rc = 0 ] || result=1 +- ;; + 1) + # This can be a non-ELF binary or no binary at all. + nonelf "$file" || { +@@ -185,7 +173,7 @@ warning: you do not have execution permission for" "\`$file'" >&2 + result=1 + } + ;; +- 2) ++ 0|2) + try_trace "$RTLD" "$file" || result=1 + ;; + *) diff --git a/SOURCES/glibc-fedora-linux-tcsetattr.patch b/SOURCES/glibc-fedora-linux-tcsetattr.patch new file mode 100644 index 0000000..e47d5ec --- /dev/null +++ b/SOURCES/glibc-fedora-linux-tcsetattr.patch @@ -0,0 +1,48 @@ +diff -Nru glibc-2.17-c758a686/sysdeps/unix/sysv/linux/tcsetattr.c glibc-2.17-c758a686/sysdeps/unix/sysv/linux/tcsetattr.c +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/tcsetattr.c 2012-06-05 07:42:49.000000000 -0600 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/tcsetattr.c 2012-06-07 12:15:21.831318623 -0600 +@@ -48,6 +48,7 @@ tcsetattr (fd, optional_actions, termios + { + struct __kernel_termios k_termios; + unsigned long int cmd; ++ int retval; + + switch (optional_actions) + { +@@ -79,6 +80,35 @@ tcsetattr (fd, optional_actions, termios + memcpy (&k_termios.c_cc[0], &termios_p->c_cc[0], + __KERNEL_NCCS * sizeof (cc_t)); + +- return INLINE_SYSCALL (ioctl, 3, fd, cmd, &k_termios); ++ retval = INLINE_SYSCALL (ioctl, 3, fd, cmd, &k_termios); ++ ++ if (retval == 0 && cmd == TCSETS) ++ { ++ /* The Linux kernel has a bug which silently ignore the invalid ++ c_cflag on pty. We have to check it here. */ ++ int save = errno; ++ retval = INLINE_SYSCALL (ioctl, 3, fd, TCGETS, &k_termios); ++ if (retval) ++ { ++ /* We cannot verify if the setting is ok. We don't return ++ an error (?). */ ++ __set_errno (save); ++ retval = 0; ++ } ++ else if ((termios_p->c_cflag & (PARENB | CREAD)) ++ != (k_termios.c_cflag & (PARENB | CREAD)) ++ || ((termios_p->c_cflag & CSIZE) ++ && ((termios_p->c_cflag & CSIZE) ++ != (k_termios.c_cflag & CSIZE)))) ++ { ++ /* It looks like the Linux kernel silently changed the ++ PARENB/CREAD/CSIZE bits in c_cflag. Report it as an ++ error. */ ++ __set_errno (EINVAL); ++ retval = -1; ++ } ++ } ++ ++ return retval; + } + libc_hidden_def (tcsetattr) diff --git a/SOURCES/glibc-fedora-localedata-rh61908.patch b/SOURCES/glibc-fedora-localedata-rh61908.patch new file mode 100644 index 0000000..0cdd09f --- /dev/null +++ b/SOURCES/glibc-fedora-localedata-rh61908.patch @@ -0,0 +1,38 @@ +* Tue Mar 26 2002 Jakub Jelinek 2.2.5-28 +- add a couple of .ISO-8859-15 locales (#61908) + +diff -Nru glibc-2.17-c758a686/localedata/SUPPORTED glibc-2.17-c758a686/localedata/SUPPORTED +--- glibc-2.17-c758a686/localedata/SUPPORTED 2012-11-25 12:59:31.000000000 -0700 ++++ glibc-2.17-c758a686/localedata/SUPPORTED 2012-11-26 12:58:43.298223018 -0700 +@@ -89,6 +89,7 @@ cy_GB.UTF-8/UTF-8 \ + cy_GB/ISO-8859-14 \ + da_DK.UTF-8/UTF-8 \ + da_DK/ISO-8859-1 \ ++da_DK.ISO-8859-15/ISO-8859-15 \ + de_AT.UTF-8/UTF-8 \ + de_AT/ISO-8859-1 \ + de_AT@euro/ISO-8859-15 \ +@@ -121,6 +122,7 @@ en_DK.UTF-8/UTF-8 \ + en_DK/ISO-8859-1 \ + en_GB.UTF-8/UTF-8 \ + en_GB/ISO-8859-1 \ ++en_GB.ISO-8859-15/ISO-8859-15 \ + en_HK.UTF-8/UTF-8 \ + en_HK/ISO-8859-1 \ + en_IE.UTF-8/UTF-8 \ +@@ -136,6 +138,7 @@ en_SG.UTF-8/UTF-8 \ + en_SG/ISO-8859-1 \ + en_US.UTF-8/UTF-8 \ + en_US/ISO-8859-1 \ ++en_US.ISO-8859-15/ISO-8859-15 \ + en_ZA.UTF-8/UTF-8 \ + en_ZA/ISO-8859-1 \ + en_ZM/UTF-8 \ +@@ -385,6 +388,7 @@ sv_FI/ISO-8859-1 \ + sv_FI@euro/ISO-8859-15 \ + sv_SE.UTF-8/UTF-8 \ + sv_SE/ISO-8859-1 \ ++sv_SE.ISO-8859-15/ISO-8859-15 \ + sw_KE/UTF-8 \ + sw_TZ/UTF-8 \ + szl_PL/UTF-8 \ diff --git a/SOURCES/glibc-fedora-localedef.patch b/SOURCES/glibc-fedora-localedef.patch new file mode 100644 index 0000000..41deb0a --- /dev/null +++ b/SOURCES/glibc-fedora-localedef.patch @@ -0,0 +1,11 @@ +diff -Nru glibc-2.17-c758a686/localedata/Makefile glibc-2.17-c758a686/localedata/Makefile +--- glibc-2.17-c758a686/localedata/Makefile 2012-06-05 07:42:49.000000000 -0600 ++++ glibc-2.17-c758a686/localedata/Makefile 2012-06-07 12:15:21.776318827 -0600 +@@ -211,6 +211,7 @@ $(INSTALL-SUPPORTED-LOCALES): install-lo + echo -n '...'; \ + input=`echo $$locale | sed 's/\([^.]*\)[^@]*\(.*\)/\1\2/'`; \ + $(LOCALEDEF) --alias-file=../intl/locale.alias \ ++ --no-archive \ + -i locales/$$input -c -f charmaps/$$charset \ + $(addprefix --prefix=,$(install_root)) $$locale; \ + echo ' done'; \ diff --git a/SOURCES/glibc-fedora-locarchive.patch b/SOURCES/glibc-fedora-locarchive.patch new file mode 100644 index 0000000..245850a --- /dev/null +++ b/SOURCES/glibc-fedora-locarchive.patch @@ -0,0 +1,51 @@ +This is a part of commit glibc-2.3.3-1492-ga891c7b, +needed for fedora/build-locale-archive.c only. + +diff -Nru glibc-2.17-c758a686/ChangeLog.17 glibc-2.17-c758a686/ChangeLog.17 +--- glibc-2.17-c758a686/ChangeLog.17 2012-06-05 07:42:49.000000000 -0600 ++++ glibc-2.17-c758a686/ChangeLog.17 2012-06-07 12:15:21.564319619 -0600 +@@ -11818,6 +11829,10 @@ d2009-10-30 Ulrich Drepper ++ ++ * locale/programs/locarchive.c (add_alias, insert_name): Remove static. ++ + 2007-04-16 Ulrich Drepper + + [BZ #4364] +diff -Nru glibc-2.17-c758a686/locale/programs/locarchive.c glibc-2.17-c758a686/locale/programs/locarchive.c +--- glibc-2.17-c758a686/locale/programs/locarchive.c 2012-06-05 07:42:49.000000000 -0600 ++++ glibc-2.17-c758a686/locale/programs/locarchive.c 2012-06-07 12:15:21.585319540 -0600 +@@ -252,9 +252,9 @@ oldlocrecentcmp (const void *a, const vo + /* forward decls for below */ + static uint32_t add_locale (struct locarhandle *ah, const char *name, + locale_data_t data, bool replace); +-static void add_alias (struct locarhandle *ah, const char *alias, +- bool replace, const char *oldname, +- uint32_t *locrec_offset_p); ++void add_alias (struct locarhandle *ah, const char *alias, ++ bool replace, const char *oldname, ++ uint32_t *locrec_offset_p); + + + static bool +@@ -635,7 +635,7 @@ close_archive (struct locarhandle *ah) + #include "../../intl/explodename.c" + #include "../../intl/l10nflist.c" + +-static struct namehashent * ++struct namehashent * + insert_name (struct locarhandle *ah, + const char *name, size_t name_len, bool replace) + { +@@ -693,7 +693,7 @@ insert_name (struct locarhandle *ah, + return &namehashtab[idx]; + } + +-static void ++void + add_alias (struct locarhandle *ah, const char *alias, bool replace, + const char *oldname, uint32_t *locrec_offset_p) + { diff --git a/SOURCES/glibc-fedora-manual-dircategory.patch b/SOURCES/glibc-fedora-manual-dircategory.patch new file mode 100644 index 0000000..9dce832 --- /dev/null +++ b/SOURCES/glibc-fedora-manual-dircategory.patch @@ -0,0 +1,20 @@ +From 4820b9175535e13df79ce816106016040014916e Mon Sep 17 00:00:00 2001 +From: Jakub Jelinek +Date: Fri, 3 Nov 2006 16:31:21 +0000 +Subject: [PATCH] Change @dircategory. + +--- + manual/libc.texinfo | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +--- glibc-2.17-c758a686/manual/libc.texinfo ++++ glibc-2.17-c758a686/manual/libc.texinfo +@@ -7,7 +7,7 @@ + @include macros.texi + + @comment Tell install-info what to do. +-@dircategory Software libraries ++@dircategory Libraries + @direntry + * Libc: (libc). C library. + @end direntry diff --git a/SOURCES/glibc-fedora-nis-rh188246.patch b/SOURCES/glibc-fedora-nis-rh188246.patch new file mode 100644 index 0000000..f266774 --- /dev/null +++ b/SOURCES/glibc-fedora-nis-rh188246.patch @@ -0,0 +1,21 @@ +From baba5d9461d4e8a581ac26fe4412ad783ffc73e7 Mon Sep 17 00:00:00 2001 +From: Jakub Jelinek +Date: Mon, 1 May 2006 08:02:53 +0000 +Subject: [PATCH] Enable SETENT_BATCH_READ nis/nss option by default + +* Mon May 1 2006 Jakub Jelinek 2.4.90-4 +- SETENT_BATCH_READ /etc/default/nss option for speeding up + some usages of NIS+ (#188246) + +diff --git glibc-2.17-c758a686/nis/nss glibc-2.17-c758a686/nis/nss +--- glibc-2.17-c758a686/nis/nss ++++ glibc-2.17-c758a686/nis/nss +@@ -25,7 +25,7 @@ + # memory with every getXXent() call. Otherwise each getXXent() call + # might result into a network communication with the server to get + # the next entry. +-#SETENT_BATCH_READ=TRUE ++SETENT_BATCH_READ=TRUE + # + # ADJUNCT_AS_SHADOW + # If set to TRUE, the passwd routines in the NIS NSS module will not diff --git a/SOURCES/glibc-fedora-nptl-linklibc.patch b/SOURCES/glibc-fedora-nptl-linklibc.patch new file mode 100644 index 0000000..e6866ee --- /dev/null +++ b/SOURCES/glibc-fedora-nptl-linklibc.patch @@ -0,0 +1,25 @@ +diff -Nru glibc-2.17-c758a686/nptl/Makefile glibc-2.17-c758a686/nptl/Makefile +--- glibc-2.17-c758a686/nptl/Makefile 2012-06-05 07:42:49.000000000 -0600 ++++ glibc-2.17-c758a686/nptl/Makefile 2012-06-07 12:15:21.816318678 -0600 +@@ -529,15 +529,19 @@ $(addprefix $(objpfx), \ + $(tests) $(xtests) $(test-srcs))): $(objpfx)libpthread.so \ + $(objpfx)libpthread_nonshared.a + $(objpfx)tst-unload: $(common-objpfx)dlfcn/libdl.so +-# $(objpfx)../libc.so is used instead of $(common-objpfx)libc.so, ++# $(objpfx)linklibc.so is used instead of $(common-objpfx)libc.so, + # since otherwise libpthread.so comes before libc.so when linking. + $(addprefix $(objpfx), $(tests-reverse)): \ +- $(objpfx)../libc.so $(objpfx)libpthread.so \ ++ $(objpfx)linklibc.so $(objpfx)libpthread.so \ + $(objpfx)libpthread_nonshared.a + $(objpfx)../libc.so: $(common-objpfx)libc.so ; + $(addprefix $(objpfx),$(tests-static) $(xtests-static)): $(objpfx)libpthread.a + + $(objpfx)tst-atfork2.out: $(objpfx)tst-atfork2mod.so ++ ++$(objpfx)linklibc.so: $(common-objpfx)libc.so ++ ln -s ../libc.so $@ ++generated += libclink.so + else + $(addprefix $(objpfx),$(tests) $(test-srcs)): $(objpfx)libpthread.a + endif diff --git a/SOURCES/glibc-fedora-nscd.patch b/SOURCES/glibc-fedora-nscd.patch new file mode 100644 index 0000000..b236ecc --- /dev/null +++ b/SOURCES/glibc-fedora-nscd.patch @@ -0,0 +1,12 @@ +diff -Nru glibc-2.17-c758a686/nscd/nscd.conf glibc-2.17-c758a686/nscd/nscd.conf +--- glibc-2.17-c758a686/nscd/nscd.conf 2012-06-05 07:42:49.000000000 -0600 ++++ glibc-2.17-c758a686/nscd/nscd.conf 2012-06-07 12:15:21.818318670 -0600 +@@ -33,7 +33,7 @@ + # logfile /var/log/nscd.log + # threads 4 + # max-threads 32 +-# server-user nobody ++ server-user nscd + # stat-user somebody + debug-level 0 + # reload-count 5 diff --git a/SOURCES/glibc-fedora-ppc-unwind.patch b/SOURCES/glibc-fedora-ppc-unwind.patch new file mode 100644 index 0000000..28a1e58 --- /dev/null +++ b/SOURCES/glibc-fedora-ppc-unwind.patch @@ -0,0 +1,23 @@ +(This patch is no longer needed because we currently build all of +glibc with -fno-asynchronous-unwind-tables.) + +glibc-2.3.3-1478-g37582bc + +* Thu Nov 30 2006 Jakub Jelinek 2.5.90-9 +- on ppc64 build __libc_start_main without unwind info, + as it breaks MD_FROB_UPDATE_CONTEXT (#217729, #217775; in the + future that could be fixable just by providing .cfi_undefined r2 + in __libc_start_main instead) + +diff -Nru glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/Makefile glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/Makefile +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/Makefile 2012-06-05 07:42:49.000000000 -0600 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/Makefile 2012-06-07 12:15:21.828318633 -0600 +@@ -35,6 +35,8 @@ CFLAGS-rtld-memmove.os = $(no-special-re + CFLAGS-rtld-memchr.os = $(no-special-regs) + CFLAGS-rtld-strnlen.os = $(no-special-regs) + ++CFLAGS-libc-start.c += -fno-asynchronous-unwind-tables ++ + ifeq ($(subdir),csu) + sysdep_routines += hp-timing + elide-routines.os += hp-timing diff --git a/SOURCES/glibc-fedora-regcomp-sw11561.patch b/SOURCES/glibc-fedora-regcomp-sw11561.patch new file mode 100644 index 0000000..3366dd9 --- /dev/null +++ b/SOURCES/glibc-fedora-regcomp-sw11561.patch @@ -0,0 +1,155 @@ +Upstream commit: + +commit 7e2f0d2d77e4bc273fe00f99d970605d8e38d4d6 +Author: Andreas Schwab +Date: Mon Feb 4 10:16:33 2013 +0100 + + Fix handling of collating symbols in regexps + +From c1b97d6d896b1f22fdf5d28471ef7859ec840a57 Mon Sep 17 00:00:00 2001 +From: Andreas Schwab +Date: Wed, 1 Sep 2010 17:26:15 +0200 +Subject: [PATCH] Fix handling of collating symbols in regexps + +[BZ #11561] +* posix/regcomp.c (parse_bracket_exp): When looking up collating +elements compare against the byte sequence of it, not its name. + +--- + ChangeLog | 4 +++ + posix/regcomp.c | 72 ++++++++++++++++++++---------------------------------- + 2 files changed, 31 insertions(+), 45 deletions(-) + +--- glibc-2.17-c758a686/posix/regcomp.c ++++ glibc-2.17-c758a686/posix/regcomp.c +@@ -2772,40 +2772,29 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, + + /* Local function for parse_bracket_exp used in _LIBC environement. + Seek the collating symbol entry correspondings to NAME. +- Return the index of the symbol in the SYMB_TABLE. */ ++ Return the index of the symbol in the SYMB_TABLE, ++ or -1 if not found. */ + + auto inline int32_t + __attribute ((always_inline)) +- seek_collating_symbol_entry (name, name_len) +- const unsigned char *name; +- size_t name_len; ++ seek_collating_symbol_entry (const unsigned char *name, size_t name_len) + { +- int32_t hash = elem_hash ((const char *) name, name_len); +- int32_t elem = hash % table_size; +- if (symb_table[2 * elem] != 0) +- { +- int32_t second = hash % (table_size - 2) + 1; +- +- do +- { +- /* First compare the hashing value. */ +- if (symb_table[2 * elem] == hash +- /* Compare the length of the name. */ +- && name_len == extra[symb_table[2 * elem + 1]] +- /* Compare the name. */ +- && memcmp (name, &extra[symb_table[2 * elem + 1] + 1], +- name_len) == 0) +- { +- /* Yep, this is the entry. */ +- break; +- } ++ int32_t elem; + +- /* Next entry. */ +- elem += second; +- } +- while (symb_table[2 * elem] != 0); +- } +- return elem; ++ for (elem = 0; elem < table_size; elem++) ++ if (symb_table[2 * elem] != 0) ++ { ++ int32_t idx = symb_table[2 * elem + 1]; ++ /* Skip the name of collating element name. */ ++ idx += 1 + extra[idx]; ++ if (/* Compare the length of the name. */ ++ name_len == extra[idx] ++ /* Compare the name. */ ++ && memcmp (name, &extra[idx + 1], name_len) == 0) ++ /* Yep, this is the entry. */ ++ return elem; ++ } ++ return -1; + } + + /* Local function for parse_bracket_exp used in _LIBC environment. +@@ -2814,8 +2803,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, + + auto inline unsigned int + __attribute ((always_inline)) +- lookup_collation_sequence_value (br_elem) +- bracket_elem_t *br_elem; ++ lookup_collation_sequence_value (bracket_elem_t *br_elem) + { + if (br_elem->type == SB_CHAR) + { +@@ -2843,7 +2831,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, + int32_t elem, idx; + elem = seek_collating_symbol_entry (br_elem->opr.name, + sym_name_len); +- if (symb_table[2 * elem] != 0) ++ if (elem != -1) + { + /* We found the entry. */ + idx = symb_table[2 * elem + 1]; +@@ -2861,7 +2849,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, + /* Return the collation sequence value. */ + return *(unsigned int *) (extra + idx); + } +- else if (symb_table[2 * elem] == 0 && sym_name_len == 1) ++ else if (sym_name_len == 1) + { + /* No valid character. Match it as a single byte + character. */ +@@ -2883,11 +2871,8 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, + + auto inline reg_errcode_t + __attribute ((always_inline)) +- build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem) +- re_charset_t *mbcset; +- int *range_alloc; +- bitset_t sbcset; +- bracket_elem_t *start_elem, *end_elem; ++ build_range_exp (bitset_t sbcset, re_charset_t *mbcset, int *range_alloc, ++ bracket_elem_t *start_elem, bracket_elem_t *end_elem) + { + unsigned int ch; + uint32_t start_collseq; +@@ -2966,25 +2951,22 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, + + auto inline reg_errcode_t + __attribute ((always_inline)) +- build_collating_symbol (sbcset, mbcset, coll_sym_alloc, name) +- re_charset_t *mbcset; +- int *coll_sym_alloc; +- bitset_t sbcset; +- const unsigned char *name; ++ build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset, ++ int *coll_sym_alloc, const unsigned char *name) + { + int32_t elem, idx; + size_t name_len = strlen ((const char *) name); + if (nrules != 0) + { + elem = seek_collating_symbol_entry (name, name_len); +- if (symb_table[2 * elem] != 0) ++ if (elem != -1) + { + /* We found the entry. */ + idx = symb_table[2 * elem + 1]; + /* Skip the name of collating element name. */ + idx += 1 + extra[idx]; + } +- else if (symb_table[2 * elem] == 0 && name_len == 1) ++ else if (name_len == 1) + { + /* No valid character, treat it as a normal + character. */ diff --git a/SOURCES/glibc-fedora-streams-rh436349.patch b/SOURCES/glibc-fedora-streams-rh436349.patch new file mode 100644 index 0000000..6b862db --- /dev/null +++ b/SOURCES/glibc-fedora-streams-rh436349.patch @@ -0,0 +1,28 @@ +This is part of commit glibc-2.3.3-1564-gd0b6ac6 + +* Fri Mar 14 2008 Jakub Jelinek 2.7.90-11 +- remove , define _XOPEN_STREAMS -1 (#436349) + +diff -Nru glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h +--- glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h 2012-06-05 07:42:49.000000000 -0600 ++++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h 2012-06-07 12:15:21.817318674 -0600 +@@ -188,4 +188,7 @@ + /* Typed memory objects are not available. */ + #define _POSIX_TYPED_MEMORY_OBJECTS -1 + ++/* Streams are not available. */ ++#define _XOPEN_STREAMS -1 ++ + #endif /* bits/posix_opt.h */ +diff -Nru glibc-2.17-c758a686/streams/Makefile glibc-2.17-c758a686/streams/Makefile +--- glibc-2.17-c758a686/streams/Makefile 2012-06-05 07:42:49.000000000 -0600 ++++ glibc-2.17-c758a686/streams/Makefile 2012-06-07 12:15:21.824318649 -0600 +@@ -20,7 +20,7 @@ + # + subdir := streams + +-headers = stropts.h sys/stropts.h bits/stropts.h bits/xtitypes.h ++#headers = stropts.h sys/stropts.h bits/stropts.h bits/xtitypes.h + routines = isastream getmsg getpmsg putmsg putpmsg fattach fdetach + + include ../Rules diff --git a/SOURCES/glibc-fedora-uname-getrlimit.patch b/SOURCES/glibc-fedora-uname-getrlimit.patch new file mode 100644 index 0000000..3529d0c --- /dev/null +++ b/SOURCES/glibc-fedora-uname-getrlimit.patch @@ -0,0 +1,52 @@ +Related upstream commit: + +commit c5c2b7c3fd823fc5c4a52506292a90eba60b0c62 +Author: Joseph Myers +Date: Sat Dec 6 23:40:48 2014 +0000 + + Fix pthreads getrlimit, gettimeofday namespace (bug 17682). + +The uname call is again present in Fedora because UTS namespaces can +be used nowadays to change the uname result. + +--- glibc-2.17-c758a686/nptl/Version ++++ glibc-2.17-c758a686/nptl/Versions +@@ -30,6 +30,7 @@ libc { + __libc_alloca_cutoff; + # Internal libc interface to libpthread + __libc_dl_error_tsd; ++ __getrlimit; + } + } + +--- glibc-2.17-c758a686/nptl/nptl-init.c ++++ glibc-2.17-c758a686/nptl/nptl-init.c +@@ -414,7 +414,7 @@ __pthread_initialize_minimal_internal (void) + /* Determine the default allowed stack size. This is the size used + in case the user does not specify one. */ + struct rlimit limit; +- if (getrlimit (RLIMIT_STACK, &limit) != 0 ++ if (__getrlimit (RLIMIT_STACK, &limit) != 0 + || limit.rlim_cur == RLIM_INFINITY) + /* The system limit is not usable. Use an architecture-specific + default. */ +--- glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/i386/Versions ++++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/i386/Versions +@@ -0,0 +1,6 @@ ++libc { ++ GLIBC_PRIVATE { ++ # Internal libc interface to libpthread ++ __uname; ++ } ++} +--- glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/i386/smp.h ++++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/i386/smp.h +@@ -36,7 +36,7 @@ is_smp_system (void) + char *cp; + + /* Try reading the number using `sysctl' first. */ +- if (uname (&u.uts) == 0) ++ if (__uname (&u.uts) == 0) + cp = u.uts.version; + else + { diff --git a/SOURCES/glibc-fix-test-write-buf-size.patch b/SOURCES/glibc-fix-test-write-buf-size.patch new file mode 100644 index 0000000..104b97b --- /dev/null +++ b/SOURCES/glibc-fix-test-write-buf-size.patch @@ -0,0 +1,54 @@ +# This patch fixes tst-cancel4, tst-cancel5, tst-cancelx4 and tst-cancelx5 +# failures on newer kernels where the write buffers are larger. +# +# commit e7074e4c5edb0acaa979ea08e533736f906a9d68 +# Author: David S. Miller +# Date: Tue Jul 23 02:31:37 2013 -0700 +# +# Increase nptl test case buffer size so we really block on current Linux kernels. +# +# * tst-cancel4.c (WRITE_BUFFER_SIZE): Increase to 16384. +# +# commit 135529b443631f840cc66d0cc395f79c416434d9 +# Author: David S. Miller +# Date: Tue Jul 23 11:31:39 2013 -0700 +# +# Remove Linux kernel version ambiguity in comment added by previous commit. +# +# * tst-cancel4.c (WRITE_BUFFER_SIZE): Adjust comment. +# +diff -urN glibc-2.17-c758a686/nptl/tst-cancel4.c glibc-2.17-c758a686/nptl/tst-cancel4.c +--- glibc-2.17-c758a686/nptl/tst-cancel4.c 2014-07-25 22:07:09.130021164 -0400 ++++ glibc-2.17-c758a686/nptl/tst-cancel4.c 2014-07-25 22:12:07.580022919 -0400 +@@ -83,7 +83,30 @@ + # define IPC_ADDVAL 0 + #endif + +-#define WRITE_BUFFER_SIZE 4096 ++/* The WRITE_BUFFER_SIZE value needs to be choosen such that if we set ++ the socket send buffer size to '1', a write of this size on that ++ socket will block. ++ ++ The Linux kernel imposes a minimum send socket buffer size which ++ has changed over the years. As of Linux 3.10 the value is: ++ ++ 2 * (2048 + SKB_DATA_ALIGN(sizeof(struct sk_buff))) ++ ++ which is attempting to make sure that with standard MTUs, ++ TCP can always queue up at least 2 full sized packets. ++ ++ Furthermore, there is logic in the socket send paths that ++ will allow one more packet (of any size) to be queued up as ++ long as some socket buffer space remains. Blocking only ++ occurs when we try to queue up a new packet and the send ++ buffer space has already been fully consumed. ++ ++ Therefore we must set this value to the largest possible value of ++ the formula above (and since it depends upon the size of "struct ++ sk_buff", it is dependent upon machine word size etc.) plus some ++ slack space. */ ++ ++#define WRITE_BUFFER_SIZE 16384 + + /* Cleanup handling test. */ + static int cl_called; diff --git a/SOURCES/glibc-gmake.patch b/SOURCES/glibc-gmake.patch new file mode 100644 index 0000000..8431c0e --- /dev/null +++ b/SOURCES/glibc-gmake.patch @@ -0,0 +1,37 @@ +# +# BZ #16037 +# +# Allow building glibc with make version 4.0 or greater. +# This facilitates testing and QE on non-RHEL environments during +# patch development. +# +# commit 28d708c44bc47b56f6551ff285f78edcf61c208a +# Author: Marc-Antoine Perennou +# Date: Thu Oct 31 12:37:50 2013 +1000 +# +# Accept make versions 4.0 and greater +# +diff -urN glibc-2.17-c758a686/configure glibc-2.17-c758a686/configure +--- glibc-2.17-c758a686/configure 2015-01-15 16:32:14.983435268 -0500 ++++ glibc-2.17-c758a686/configure 2015-01-15 16:32:45.396495266 -0500 +@@ -4991,7 +4991,7 @@ + ac_prog_version=`$MAKE --version 2>&1 | sed -n 's/^.*GNU Make[^0-9]*\([0-9][0-9.]*\).*$/\1/p'` + case $ac_prog_version in + '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; +- 3.79* | 3.[89]*) ++ 3.79* | 3.[89]* | [4-9].* | [1-9][0-9]*) + ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;; + *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;; + +diff -urN glibc-2.17-c758a686/configure.in glibc-2.17-c758a686/configure.in +--- glibc-2.17-c758a686/configure.in 2015-01-15 16:32:14.781441511 -0500 ++++ glibc-2.17-c758a686/configure.in 2015-01-15 16:32:34.970817501 -0500 +@@ -945,7 +945,7 @@ + critic_missing="$critic_missing gcc") + AC_CHECK_PROG_VER(MAKE, gnumake gmake make, --version, + [GNU Make[^0-9]*\([0-9][0-9.]*\)], +- [3.79* | 3.[89]*], critic_missing="$critic_missing make") ++ [3.79* | 3.[89]* | [4-9].* | [1-9][0-9]*], critic_missing="$critic_missing make") + + AC_CHECK_PROG_VER(MSGFMT, gnumsgfmt gmsgfmt msgfmt, --version, + [GNU gettext.* \([0-9]*\.[0-9.]*\)], diff --git a/SOURCES/glibc-manual-update.patch b/SOURCES/glibc-manual-update.patch new file mode 100644 index 0000000..bed496b --- /dev/null +++ b/SOURCES/glibc-manual-update.patch @@ -0,0 +1,19408 @@ +# +# Synchronize RHEL 7.1 manual with upstream manual. +# +# Include updates that don't impact material differences +# between the upstream master and 2.17-based RHEL implemenation. +# +diff -urN glibc-2.17-c758a686/manual/argp.texi glibc-2.17-c758a686/manual/argp.texi +--- glibc-2.17-c758a686/manual/argp.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/argp.texi 2014-09-12 16:10:06.043792722 -0400 +@@ -36,6 +36,35 @@ + @comment argp.h + @comment GNU + @deftypefun {error_t} argp_parse (const struct argp *@var{argp}, int @var{argc}, char **@var{argv}, unsigned @var{flags}, int *@var{arg_index}, void *@var{input}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:argpbuf} @mtslocale{} @mtsenv{}}@asunsafe{@ascuheap{} @ascuintl{} @asulock{} @asucorrupt{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}} ++@c Optionally alloca()tes standard help options, initializes the parser, ++@c then parses individual args in a loop, and then finalizes. ++@c parser_init ++@c calc_sizes ok ++@c option_is_end ok ++@c malloc @ascuheap @acsmem ++@c parser_convert @mtslocale ++@c convert_options @mtslocale ++@c option_is_end ok ++@c option_is_short ok ++@c isprint, but locale may change within the loop ++@c find_long_option ok ++@c group_parse ++@c group->parser (from argp->parser) ++@c parser_parse_next ++@c getopt_long(_only)_r many issues, same as non_r minus @mtasurace ++@c parser_parse_arg ++@c group_parse dup ++@c parser_parse_opt ++@c group_parse dup ++@c argp_error dup @mtasurace:argpbuf @mtsenv @mtslocale @ascuheap @ascuintl @asucorrupt @acsmem @acucorrupt @aculock ++@c dgettext (bad key error) dup @mtsenv @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsfd @acsmem ++@c parser_finalize ++@c group_parse ++@c fprintf dup @mtslocale @asucorrupt @aculock @acucorrupt [no @ascuheap @acsmem] ++@c dgettext dup @mtsenv @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsfd @acsmem ++@c arg_state_help ++@c free dup @ascuhelp @acsmem + The @code{argp_parse} function parses the arguments in @var{argv}, of + length @var{argc}, using the argp parser @var{argp}. @xref{Argp + Parsers}. Passing a null pointer for @var{argp} is the same as using +@@ -660,6 +689,8 @@ + @comment argp.h + @comment GNU + @deftypefun void argp_usage (const struct argp_state *@var{state}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:argpbuf} @mtsenv{} @mtslocale{}}@asunsafe{@ascuheap{} @ascuintl{} @asucorrupt{}}@acunsafe{@acsmem{} @acucorrupt{} @aculock{}}} ++@c Just calls argp_state_help with stderr and ARGP_HELP_STD_USAGE. + Outputs the standard usage message for the argp parser referred to by + @var{state} to @code{@var{state}->err_stream} and terminate the program + with @code{exit (argp_err_exit_status)}. @xref{Argp Global Variables}. +@@ -669,6 +700,13 @@ + @comment argp.h + @comment GNU + @deftypefun void argp_error (const struct argp_state *@var{state}, const char *@var{fmt}, @dots{}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:argpbuf} @mtsenv{} @mtslocale{}}@asunsafe{@ascuheap{} @ascuintl{} @asucorrupt{}}@acunsafe{@acsmem{} @acucorrupt{} @aculock{}}} ++@c Lock stream, vasprintf the formatted message into a buffer, print the ++@c buffer prefixed by the short program name (in libc, ++@c argp_short_program_name is a macro that expands to ++@c program_invocation_short_name), releases the buffer, then call ++@c argp_state_help with stream and ARGP_HELP_STD_ERR, unlocking the ++@c stream at the end. + Prints the printf format string @var{fmt} and following args, preceded + by the program name and @samp{:}, and followed by a @w{@samp{Try @dots{} + --help}} message, and terminates the program with an exit status of +@@ -679,6 +717,12 @@ + @comment argp.h + @comment GNU + @deftypefun void argp_failure (const struct argp_state *@var{state}, int @var{status}, int @var{errnum}, const char *@var{fmt}, @dots{}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@aculock{} @acucorrupt{} @acsmem{}}} ++@c Lock stream, write out the short program name, vasprintf the optional ++@c formatted message to a buffer, print the buffer prefixed by colon and ++@c blank, release the buffer, call strerror_r with an automatic buffer, ++@c print it out after colon and blank, put[w]c a line break, unlock the ++@c stream, then exit unless ARGP_NO_EXIT. + Similar to the standard gnu error-reporting function @code{error}, this + prints the program name and @samp{:}, the printf format string + @var{fmt}, and the appropriate following args. If it is non-zero, the +@@ -695,6 +739,142 @@ + @comment argp.h + @comment GNU + @deftypefun void argp_state_help (const struct argp_state *@var{state}, FILE *@var{stream}, unsigned @var{flags}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:argpbuf} @mtsenv{} @mtslocale{}}@asunsafe{@ascuheap{} @ascuintl{} @asucorrupt{}}@acunsafe{@acsmem{} @acucorrupt{} @aculock{}}} ++@c Just calls _help with the short program name and optionally exit. ++@c The main problems in _help, besides the usual issues with stream I/O ++@c and translation, are the use of a static buffer (uparams, thus ++@c @mtasurace:argpbuf) that makes the whole thing thread-unsafe, reading ++@c from the environment for ARGP_HELP_FMT, accessing the locale object ++@c multiple times. ++ ++@c _help @mtsenv @mtasurace:argpbuf @mtslocale @ascuheap @ascuintl @asucorrupt @acsmem @acucorrupt @aculock ++@c dgettext @ascuintl ++@c flockfile @aculock ++@c funlockfile @aculock ++@c fill_in_uparams @mtsenv @mtasurace:argpbuf @mtslocale @asucorrupt @ascuheap @aculock @acucorrupt @acsmem ++@c argp_failure dup (status = errnum = 0) ++@c atoi dup @mtslocale ++@c argp_hol @ascuheap @acsmem ++@c make_hol @ascuheap @acsmem ++@c hol_add_cluster @ascuheap @acsmem ++@c hol_append @ascuheap @acsmem ++@c hol_set_group ok ++@c hol_find_entry ok ++@c hol_sort @mtslocale @acucorrupt ++@c qsort dup @acucorrupt ++@c hol_entry_qcmp @mtslocale ++@c hol_entry_cmp @mtslocale ++@c group_cmp ok ++@c hol_cluster_cmp ok ++@c group_cmp ok ++@c hol_entry_first_short @mtslocale ++@c hol_entry_short_iterate [@mtslocale] ++@c until_short ok ++@c oshort ok ++@c isprint ok ++@c odoc ok ++@c hol_entry_first_long ok ++@c canon_doc_option @mtslocale ++@c tolower dup ++@c hol_usage @mtslocale @ascuintl @ascuheap @acsmem ++@c hol_entry_short_iterate ok ++@c add_argless_short_opt ok ++@c argp_fmtstream_printf dup ++@c hol_entry_short_iterate @mtslocale @ascuintl @ascuheap @acsmem ++@c usage_argful_short_opt @mtslocale @ascuintl @ascuheap @acsmem ++@c dgettext dup ++@c argp_fmtstream_printf dup ++@c hol_entry_long_iterate @mtslocale @ascuintl @ascuheap @acsmem ++@c usage_long_opt @mtslocale @ascuintl @ascuheap @acsmem ++@c dgettext dup ++@c argp_fmtstream_printf dup ++@c hol_help @mtslocale @mtasurace:argpbuf @ascuheap @ascuintl @asucorrupt @acsmem @acucorrupt @aculock ++@c hol_entry_help @mtslocale @mtasurace:argpbuf @ascuheap @ascuintl @asucorrupt @acsmem @acucorrupt @aculock ++@c argp_fmtstream_set_lmargin dup ++@c argp_fmtstream_wmargin dup ++@c argp_fmtstream_set_wmargin dup ++@c comma @mtslocale @ascuheap @ascuintl @asucorrupt @acsmem @acucorrupt @aculock ++@c argp_fmtstream_putc dup ++@c hol_cluster_is_child ok ++@c argp_fmtstream_wmargin dup ++@c print_header dup ++@c argp_fmtstream_set_wmargin dup ++@c argp_fmtstream_puts dup ++@c indent_to dup ++@c argp_fmtstream_putc dup ++@c arg @mtslocale @ascuheap @acsmem ++@c argp_fmtstream_printf dup ++@c odoc dup ++@c argp_fmtstream_puts dup ++@c argp_fmtstream_printf dup ++@c print_header @mtslocale @mtasurace:argpbuf @ascuheap @ascuintl @asucorrupt @acsmem @acucorrupt @aculock ++@c dgettext dup ++@c filter_doc dup ++@c argp_fmtstream_putc dup ++@c indent_to dup ++@c argp_fmtstream_set_lmargin dup ++@c argp_fmtstream_set_wmargin dup ++@c argp_fmtstream_puts dup ++@c free dup ++@c filter_doc dup ++@c argp_fmtstream_point dup ++@c indent_to @mtslocale @ascuheap @asucorrupt @acsmem @acucorrupt @aculock ++@c argp_fmtstream_point dup ++@c argp_fmtstream_putc dup ++@c dgettext dup ++@c filter_doc dup ++@c argp_fmtstream_putc dup ++@c argp_fmtstream_puts dup ++@c free dup ++@c hol_free @ascuheap @acsmem ++@c free dup ++@c argp_args_levels ok ++@c argp_args_usage @mtslocale @ascuintl @ascuheap @asucorrupt @acsmem @acucorrupt @aculock ++@c dgettext dup ++@c filter_doc ok ++@c argp_input ok ++@c argp->help_filter ++@c space @mtslocale @ascuheap @asucorrupt @acsmem @acucorrupt @aculock ++@c argp_fmtstream_point dup ++@c argp_fmtstream_rmargin @mtslocale @asucorrupt @acucorrupt @aculock ++@c argp_fmtstream_update dup ++@c argp_fmtstream_putc dup ++@c argp_fmtstream_write dup ++@c free dup ++@c argp_doc @mtslocale @ascuheap @ascuintl @asucorrupt @acsmem @acucorrupt @aculock ++@c dgettext @ascuintl ++@c strndup @ascuheap @acsmem ++@c argp_input dup ++@c argp->help_filter ++@c argp_fmtstream_putc @mtslocale @ascuheap @asucorrupt @acsmem @acucorrupt @aculock ++@c argp_fmtstream_ensure dup ++@c argp_fmtstream_write dup ++@c argp_fmtstream_puts dup ++@c argp_fmtstream_point @mtslocale @asucorrupt @acucorrupt @aculock ++@c argp_fmtstream_update dup ++@c argp_fmtstream_lmargin dup ++@c free dup ++@c argp_make_fmtstream @ascuheap @acsmem ++@c argp_fmtstream_free @mtslocale @ascuheap @asucorrupt @acsmem @acucorrupt @aculock ++@c argp_fmtstream_update @mtslocale @asucorrupt @acucorrupt @aculock ++@c put[w]c_unlocked dup ++@c isblank in loop @mtslocale ++@c fxprintf @aculock ++@c fxprintf @aculock ++@c free dup ++@c argp_fmtstream_set_wmargin @mtslocale @asucorrupt @acucorrupt @aculock ++@c argp_fmtstream_update dup ++@c argp_fmtstream_printf @mtslocale @ascuheap @acsmem ++@c argp_fmtstream_ensure dup ++@c vsnprintf dup ++@c argp_fmtstream_set_lmargin @mtslocale @asucorrupt @acucorrupt @aculock ++@c argp_fmtstream_update dup ++@c argp_fmtstream_puts @mtslocale @ascuheap @asucorrupt @acsmem @acucorrupt @aculock ++@c argp_fmtstream_write @mtslocale @ascuheap @asucorrupt @acsmem @acucorrupt @aculock ++@c argp_fmtstream_ensure @mtslocale @ascuheap @asucorrupt @acsmem @acucorrupt @aculock ++@c argp_fmtstream_update dup ++@c fxprintf @aculock ++@c realloc @ascuheap @acsmem + Outputs a help message for the argp parser referred to by @var{state}, + to @var{stream}. The @var{flags} argument determines what sort of help + message is produced. @xref{Argp Help Flags}. +@@ -928,6 +1108,8 @@ + @comment argp.h + @comment GNU + @deftypefun void argp_help (const struct argp *@var{argp}, FILE *@var{stream}, unsigned @var{flags}, char *@var{name}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:argpbuf} @mtsenv{} @mtslocale{}}@asunsafe{@ascuheap{} @ascuintl{} @asucorrupt{}}@acunsafe{@acsmem{} @acucorrupt{} @aculock{}}} ++@c Just calls _help. + This outputs a help message for the argp parser @var{argp} to + @var{stream}. The type of messages printed will be determined by + @var{flags}. +diff -urN glibc-2.17-c758a686/manual/arith.texi glibc-2.17-c758a686/manual/arith.texi +--- glibc-2.17-c758a686/manual/arith.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/arith.texi 2014-09-12 16:10:06.043792722 -0400 +@@ -160,6 +160,8 @@ + @comment stdlib.h + @comment ISO + @deftypefun div_t div (int @var{numerator}, int @var{denominator}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Functions in this section are pure, and thus safe. + This function @code{div} computes the quotient and remainder from + the division of @var{numerator} by @var{denominator}, returning the + result in a structure of type @code{div_t}. +@@ -199,6 +201,7 @@ + @comment stdlib.h + @comment ISO + @deftypefun ldiv_t ldiv (long int @var{numerator}, long int @var{denominator}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{ldiv} function is similar to @code{div}, except that the + arguments are of type @code{long int} and the result is returned as a + structure of type @code{ldiv_t}. +@@ -225,6 +228,7 @@ + @comment stdlib.h + @comment ISO + @deftypefun lldiv_t lldiv (long long int @var{numerator}, long long int @var{denominator}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{lldiv} function is like the @code{div} function, but the + arguments are of type @code{long long int} and the result is returned as + a structure of type @code{lldiv_t}. +@@ -256,6 +260,7 @@ + @comment inttypes.h + @comment ISO + @deftypefun imaxdiv_t imaxdiv (intmax_t @var{numerator}, intmax_t @var{denominator}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{imaxdiv} function is like the @code{div} function, but the + arguments are of type @code{intmax_t} and the result is returned as + a structure of type @code{imaxdiv_t}. +@@ -318,6 +323,7 @@ + @comment math.h + @comment ISO + @deftypefn {Macro} int fpclassify (@emph{float-type} @var{x}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This is a generic macro which works on all floating-point types and + which returns a value of type @code{int}. The possible values are: + +@@ -354,6 +360,7 @@ + @comment math.h + @comment ISO + @deftypefn {Macro} int isfinite (@emph{float-type} @var{x}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This macro returns a nonzero value if @var{x} is finite: not plus or + minus infinity, and not NaN. It is equivalent to + +@@ -368,6 +375,7 @@ + @comment math.h + @comment ISO + @deftypefn {Macro} int isnormal (@emph{float-type} @var{x}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This macro returns a nonzero value if @var{x} is finite and normalized. + It is equivalent to + +@@ -379,6 +387,7 @@ + @comment math.h + @comment ISO + @deftypefn {Macro} int isnan (@emph{float-type} @var{x}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This macro returns a nonzero value if @var{x} is NaN. It is equivalent + to + +@@ -387,6 +396,15 @@ + @end smallexample + @end deftypefn + ++@comment math.h ++@comment GNU ++@deftypefn {Macro} int issignaling (@emph{float-type} @var{x}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++This macro returns a nonzero value if @var{x} is a signaling NaN ++(sNaN). It is based on draft TS 18661 and currently enabled as a GNU ++extension. ++@end deftypefn ++ + Another set of floating-point classification functions was provided by + BSD. @Theglibc{} also supports these functions; however, we + recommend that you use the ISO C99 macros in new code. Those are standard +@@ -402,6 +420,7 @@ + @comment math.h + @comment BSD + @deftypefunx int isinfl (long double @var{x}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function returns @code{-1} if @var{x} represents negative infinity, + @code{1} if @var{x} represents positive infinity, and @code{0} otherwise. + @end deftypefun +@@ -415,6 +434,7 @@ + @comment math.h + @comment BSD + @deftypefunx int isnanl (long double @var{x}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function returns a nonzero value if @var{x} is a ``not a number'' + value, and zero otherwise. + +@@ -437,6 +457,7 @@ + @comment math.h + @comment BSD + @deftypefunx int finitel (long double @var{x}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function returns a nonzero value if @var{x} is finite or a ``not a + number'' value, and zero otherwise. + @end deftypefun +@@ -489,7 +510,8 @@ + is called when certain exceptions occur inside math library functions. + However, the Unix98 standard deprecates this interface. We support it + for historical compatibility, but recommend that you do not use it in +-new programs. ++new programs. When this interface is used, exceptions may not be ++raised. + + @noindent + The exceptions defined in @w{IEEE 754} are: +@@ -705,6 +727,14 @@ + @comment fenv.h + @comment ISO + @deftypefun int feclearexcept (int @var{excepts}) ++@safety{@prelim{}@mtsafe{}@assafe{@assposix{}}@acsafe{@acsposix{}}} ++@c The other functions in this section that modify FP status register ++@c mostly do so with non-atomic load-modify-store sequences, but since ++@c the register is thread-specific, this should be fine, and safe for ++@c cancellation. As long as the FP environment is restored before the ++@c signal handler returns control to the interrupted thread (like any ++@c kernel should do), the functions are also safe for use in signal ++@c handlers. + This function clears all of the supported exception flags indicated by + @var{excepts}. + +@@ -715,6 +745,7 @@ + @comment fenv.h + @comment ISO + @deftypefun int feraiseexcept (int @var{excepts}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function raises the supported exceptions indicated by + @var{excepts}. If more than one exception bit in @var{excepts} is set + the order in which the exceptions are raised is undefined except that +@@ -730,6 +761,7 @@ + @comment fenv.h + @comment ISO + @deftypefun int fetestexcept (int @var{excepts}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Test whether the exception flags indicated by the parameter @var{except} + are currently set. If any of them are, a nonzero value is returned + which specifies which exceptions are set. Otherwise the result is zero. +@@ -766,6 +798,7 @@ + @comment fenv.h + @comment ISO + @deftypefun int fegetexceptflag (fexcept_t *@var{flagp}, int @var{excepts}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function stores in the variable pointed to by @var{flagp} an + implementation-defined value representing the current setting of the + exception flags indicated by @var{excepts}. +@@ -777,6 +810,7 @@ + @comment fenv.h + @comment ISO + @deftypefun int fesetexceptflag (const fexcept_t *@var{flagp}, int @var{excepts}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function restores the flags for the exceptions indicated by + @var{excepts} to the values stored in the variable pointed to by + @var{flagp}. +@@ -798,7 +832,8 @@ + Many of the math functions are defined only over a subset of the real or + complex numbers. Even if they are mathematically defined, their result + may be larger or smaller than the range representable by their return +-type. These are known as @dfn{domain errors}, @dfn{overflows}, and ++type without loss of accuracy. These are known as @dfn{domain errors}, ++@dfn{overflows}, and + @dfn{underflows}, respectively. Math functions do several things when + one of these errors occurs. In this manual we will refer to the + complete response as @dfn{signalling} a domain error, overflow, or +@@ -808,11 +843,20 @@ + exception and returns NaN. It also sets @var{errno} to @code{EDOM}; + this is for compatibility with old systems that do not support @w{IEEE + 754} exception handling. Likewise, when overflow occurs, math +-functions raise the overflow exception and return @math{@infinity{}} or +-@math{-@infinity{}} as appropriate. They also set @var{errno} to +-@code{ERANGE}. When underflow occurs, the underflow exception is +-raised, and zero (appropriately signed) is returned. @var{errno} may be +-set to @code{ERANGE}, but this is not guaranteed. ++functions raise the overflow exception and, in the default rounding ++mode, return @math{@infinity{}} or @math{-@infinity{}} as appropriate ++(in other rounding modes, the largest finite value of the appropriate ++sign is returned when appropriate for that rounding mode). They also ++set @var{errno} to @code{ERANGE} if returning @math{@infinity{}} or ++@math{-@infinity{}}; @var{errno} may or may not be set to ++@code{ERANGE} when a finite value is returned on overflow. When ++underflow occurs, the underflow exception is raised, and zero ++(appropriately signed) or a subnormal value, as appropriate for the ++mathematical result of the function and the rounding mode, is ++returned. @var{errno} may be set to @code{ERANGE}, but this is not ++guaranteed; it is intended that @theglibc{} should set it when the ++underflow is to an appropriately signed zero, but not necessarily for ++other underflows. + + Some of the math functions are defined mathematically to result in a + complex value over parts of their domains. The most familiar example of +@@ -932,6 +976,7 @@ + @comment fenv.h + @comment ISO + @deftypefun int fegetround (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Returns the currently selected rounding mode, represented by one of the + values of the defined rounding mode macros. + @end deftypefun +@@ -942,6 +987,7 @@ + @comment fenv.h + @comment ISO + @deftypefun int fesetround (int @var{round}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Changes the currently selected rounding mode to @var{round}. If + @var{round} does not correspond to one of the supported rounding modes + nothing is changed. @code{fesetround} returns zero if it changed the +@@ -986,6 +1032,7 @@ + @comment fenv.h + @comment ISO + @deftypefun int fegetenv (fenv_t *@var{envp}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Store the floating-point environment in the variable pointed to by + @var{envp}. + +@@ -996,6 +1043,7 @@ + @comment fenv.h + @comment ISO + @deftypefun int feholdexcept (fenv_t *@var{envp}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Store the current floating-point environment in the object pointed to by + @var{envp}. Then clear all exception flags, and set the FPU to trap no + exceptions. Not all FPUs support trapping no exceptions; if +@@ -1034,6 +1082,7 @@ + @comment fenv.h + @comment ISO + @deftypefun int fesetenv (const fenv_t *@var{envp}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Set the floating-point environment to that described by @var{envp}. + + The function returns zero in case the operation was successful, a +@@ -1043,6 +1092,7 @@ + @comment fenv.h + @comment ISO + @deftypefun int feupdateenv (const fenv_t *@var{envp}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Like @code{fesetenv}, this function sets the floating-point environment + to that described by @var{envp}. However, if any exceptions were + flagged in the status word before @code{feupdateenv} was called, they +@@ -1063,6 +1113,7 @@ + @comment fenv.h + @comment GNU + @deftypefun int feenableexcept (int @var{excepts}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This functions enables traps for each of the exceptions as indicated by + the parameter @var{except}. The individual exceptions are described in + @ref{Status bit operations}. Only the specified exceptions are +@@ -1075,6 +1126,7 @@ + @comment fenv.h + @comment GNU + @deftypefun int fedisableexcept (int @var{excepts}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This functions disables traps for each of the exceptions as indicated by + the parameter @var{except}. The individual exceptions are described in + @ref{Status bit operations}. Only the specified exceptions are +@@ -1086,7 +1138,8 @@ + + @comment fenv.h + @comment GNU +-@deftypefun int fegetexcept (int @var{excepts}) ++@deftypefun int fegetexcept (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The function returns a bitmask of all currently enabled exceptions. It + returns @code{-1} in case of failure. + @end deftypefun +@@ -1138,6 +1191,7 @@ + @comment inttypes.h + @comment ISO + @deftypefunx intmax_t imaxabs (intmax_t @var{number}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + These functions return the absolute value of @var{number}. + + Most computers use a two's complement integer representation, in which +@@ -1159,6 +1213,7 @@ + @comment math.h + @comment ISO + @deftypefunx {long double} fabsl (long double @var{number}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function returns the absolute value of the floating-point number + @var{number}. + @end deftypefun +@@ -1172,6 +1227,7 @@ + @comment complex.h + @comment ISO + @deftypefunx {long double} cabsl (complex long double @var{z}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + These functions return the absolute value of the complex number @var{z} + (@pxref{Complex Numbers}). The absolute value of a complex number is: + +@@ -1181,7 +1237,7 @@ + + This function should always be used instead of the direct formula + because it takes special care to avoid losing precision. It may also +-take advantage of hardware support for this operation. See @code{hypot} ++take advantage of hardware support for this operation. See @code{hypot} + in @ref{Exponents and Logarithms}. + @end deftypefun + +@@ -1209,12 +1265,13 @@ + @comment math.h + @comment ISO + @deftypefunx {long double} frexpl (long double @var{value}, int *@var{exponent}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + These functions are used to split the number @var{value} + into a normalized fraction and an exponent. + + If the argument @var{value} is not zero, the return value is @var{value} +-times a power of two, and is always in the range 1/2 (inclusive) to 1 +-(exclusive). The corresponding exponent is stored in ++times a power of two, and its magnitude is always in the range 1/2 ++(inclusive) to 1 (exclusive). The corresponding exponent is stored in + @code{*@var{exponent}}; the return value multiplied by 2 raised to this + exponent equals the original number @var{value}. + +@@ -1234,6 +1291,7 @@ + @comment math.h + @comment ISO + @deftypefunx {long double} ldexpl (long double @var{value}, int @var{exponent}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + These functions return the result of multiplying the floating-point + number @var{value} by 2 raised to the power @var{exponent}. (It can + be used to reassemble floating-point numbers that were taken apart +@@ -1248,51 +1306,55 @@ + + @comment math.h + @comment BSD +-@deftypefun double scalb (double @var{value}, int @var{exponent}) ++@deftypefun double scalb (double @var{value}, double @var{exponent}) + @comment math.h + @comment BSD +-@deftypefunx float scalbf (float @var{value}, int @var{exponent}) ++@deftypefunx float scalbf (float @var{value}, float @var{exponent}) + @comment math.h + @comment BSD +-@deftypefunx {long double} scalbl (long double @var{value}, int @var{exponent}) ++@deftypefunx {long double} scalbl (long double @var{value}, long double @var{exponent}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{scalb} function is the BSD name for @code{ldexp}. + @end deftypefun + + @comment math.h + @comment BSD +-@deftypefun {long long int} scalbn (double @var{x}, int @var{n}) ++@deftypefun double scalbn (double @var{x}, int @var{n}) + @comment math.h + @comment BSD +-@deftypefunx {long long int} scalbnf (float @var{x}, int @var{n}) ++@deftypefunx float scalbnf (float @var{x}, int @var{n}) + @comment math.h + @comment BSD +-@deftypefunx {long long int} scalbnl (long double @var{x}, int @var{n}) ++@deftypefunx {long double} scalbnl (long double @var{x}, int @var{n}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + @code{scalbn} is identical to @code{scalb}, except that the exponent + @var{n} is an @code{int} instead of a floating-point number. + @end deftypefun + + @comment math.h + @comment BSD +-@deftypefun {long long int} scalbln (double @var{x}, long int @var{n}) ++@deftypefun double scalbln (double @var{x}, long int @var{n}) + @comment math.h + @comment BSD +-@deftypefunx {long long int} scalblnf (float @var{x}, long int @var{n}) ++@deftypefunx float scalblnf (float @var{x}, long int @var{n}) + @comment math.h + @comment BSD +-@deftypefunx {long long int} scalblnl (long double @var{x}, long int @var{n}) ++@deftypefunx {long double} scalblnl (long double @var{x}, long int @var{n}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + @code{scalbln} is identical to @code{scalb}, except that the exponent + @var{n} is a @code{long int} instead of a floating-point number. + @end deftypefun + + @comment math.h + @comment BSD +-@deftypefun {long long int} significand (double @var{x}) ++@deftypefun double significand (double @var{x}) + @comment math.h + @comment BSD +-@deftypefunx {long long int} significandf (float @var{x}) ++@deftypefunx float significandf (float @var{x}) + @comment math.h + @comment BSD +-@deftypefunx {long long int} significandl (long double @var{x}) ++@deftypefunx {long double} significandl (long double @var{x}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + @code{significand} returns the mantissa of @var{x} scaled to the range + @math{[1, 2)}. + It is equivalent to @w{@code{scalb (@var{x}, (double) -ilogb (@var{x}))}}. +@@ -1307,7 +1369,7 @@ + + @pindex math.h + The functions listed here perform operations such as rounding and +-truncation of floating-point values. Some of these functions convert ++truncation of floating-point values. Some of these functions convert + floating point numbers to integer values. They are all declared in + @file{math.h}. + +@@ -1327,6 +1389,7 @@ + @comment math.h + @comment ISO + @deftypefunx {long double} ceill (long double @var{x}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + These functions round @var{x} upwards to the nearest integer, + returning that value as a @code{double}. Thus, @code{ceil (1.5)} + is @code{2.0}. +@@ -1341,6 +1404,7 @@ + @comment math.h + @comment ISO + @deftypefunx {long double} floorl (long double @var{x}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + These functions round @var{x} downwards to the nearest + integer, returning that value as a @code{double}. Thus, @code{floor + (1.5)} is @code{1.0} and @code{floor (-1.5)} is @code{-2.0}. +@@ -1355,6 +1419,7 @@ + @comment math.h + @comment ISO + @deftypefunx {long double} truncl (long double @var{x}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{trunc} functions round @var{x} towards zero to the nearest + integer (returned in floating-point format). Thus, @code{trunc (1.5)} + is @code{1.0} and @code{trunc (-1.5)} is @code{-1.0}. +@@ -1369,6 +1434,7 @@ + @comment math.h + @comment ISO + @deftypefunx {long double} rintl (long double @var{x}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + These functions round @var{x} to an integer value according to the + current rounding mode. @xref{Floating Point Parameters}, for + information about the various rounding modes. The default +@@ -1389,6 +1455,7 @@ + @comment math.h + @comment ISO + @deftypefunx {long double} nearbyintl (long double @var{x}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + These functions return the same value as the @code{rint} functions, but + do not raise the inexact exception if @var{x} is not an integer. + @end deftypefun +@@ -1402,6 +1469,7 @@ + @comment math.h + @comment ISO + @deftypefunx {long double} roundl (long double @var{x}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + These functions are similar to @code{rint}, but they round halfway + cases away from zero instead of to the nearest integer (or other + current rounding mode). +@@ -1416,6 +1484,7 @@ + @comment math.h + @comment ISO + @deftypefunx {long int} lrintl (long double @var{x}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + These functions are just like @code{rint}, but they return a + @code{long int} instead of a floating-point number. + @end deftypefun +@@ -1429,6 +1498,7 @@ + @comment math.h + @comment ISO + @deftypefunx {long long int} llrintl (long double @var{x}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + These functions are just like @code{rint}, but they return a + @code{long long int} instead of a floating-point number. + @end deftypefun +@@ -1442,6 +1512,7 @@ + @comment math.h + @comment ISO + @deftypefunx {long int} lroundl (long double @var{x}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + These functions are just like @code{round}, but they return a + @code{long int} instead of a floating-point number. + @end deftypefun +@@ -1455,6 +1526,7 @@ + @comment math.h + @comment ISO + @deftypefunx {long long int} llroundl (long double @var{x}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + These functions are just like @code{round}, but they return a + @code{long long int} instead of a floating-point number. + @end deftypefun +@@ -1469,6 +1541,7 @@ + @comment math.h + @comment ISO + @deftypefunx {long double} modfl (long double @var{value}, long double *@var{integer-part}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + These functions break the argument @var{value} into an integer part and a + fractional part (between @code{-1} and @code{1}, exclusive). Their sum + equals @var{value}. Each of the parts has the same sign as @var{value}, +@@ -1495,6 +1568,7 @@ + @comment math.h + @comment ISO + @deftypefunx {long double} fmodl (long double @var{numerator}, long double @var{denominator}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + These functions compute the remainder from the division of + @var{numerator} by @var{denominator}. Specifically, the return value is + @code{@var{numerator} - @w{@var{n} * @var{denominator}}}, where @var{n} +@@ -1517,6 +1591,7 @@ + @comment math.h + @comment BSD + @deftypefunx {long double} dreml (long double @var{numerator}, long double @var{denominator}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + These functions are like @code{fmod} except that they round the + internal quotient @var{n} to the nearest integer instead of towards zero + to an integer. For example, @code{drem (6.5, 2.3)} returns @code{-0.4}, +@@ -1540,6 +1615,7 @@ + @comment math.h + @comment BSD + @deftypefunx {long double} remainderl (long double @var{numerator}, long double @var{denominator}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function is another name for @code{drem}. + @end deftypefun + +@@ -1561,6 +1637,7 @@ + @comment math.h + @comment ISO + @deftypefunx {long double} copysignl (long double @var{x}, long double @var{y}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + These functions return @var{x} but with the sign of @var{y}. They work + even if @var{x} or @var{y} are NaN or zero. Both of these can carry a + sign (although not all implementations support it) and this is one of +@@ -1576,6 +1653,7 @@ + @comment math.h + @comment ISO + @deftypefun int signbit (@emph{float-type} @var{x}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + @code{signbit} is a generic macro which can work on all floating-point + types. It returns a nonzero value if the value of @var{x} has its sign + bit set. +@@ -1594,6 +1672,7 @@ + @comment math.h + @comment ISO + @deftypefunx {long double} nextafterl (long double @var{x}, long double @var{y}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{nextafter} function returns the next representable neighbor of + @var{x} in the direction towards @var{y}. The size of the step between + @var{x} and the result depends on the type of the result. If +@@ -1617,6 +1696,7 @@ + @comment math.h + @comment ISO + @deftypefunx {long double} nexttowardl (long double @var{x}, long double @var{y}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + These functions are identical to the corresponding versions of + @code{nextafter} except that their second argument is a @code{long + double}. +@@ -1632,6 +1712,8 @@ + @comment math.h + @comment ISO + @deftypefunx {long double} nanl (const char *@var{tagp}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} ++@c The unsafe-but-ruled-safe locale use comes from strtod. + The @code{nan} function returns a representation of NaN, provided that + NaN is supported by the target platform. + @code{nan ("@var{n-char-sequence}")} is equivalent to +@@ -1666,6 +1748,7 @@ + @comment math.h + @comment ISO + @deftypefn Macro int isgreater (@emph{real-floating} @var{x}, @emph{real-floating} @var{y}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This macro determines whether the argument @var{x} is greater than + @var{y}. It is equivalent to @code{(@var{x}) > (@var{y})}, but no + exception is raised if @var{x} or @var{y} are NaN. +@@ -1674,6 +1757,7 @@ + @comment math.h + @comment ISO + @deftypefn Macro int isgreaterequal (@emph{real-floating} @var{x}, @emph{real-floating} @var{y}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This macro determines whether the argument @var{x} is greater than or + equal to @var{y}. It is equivalent to @code{(@var{x}) >= (@var{y})}, but no + exception is raised if @var{x} or @var{y} are NaN. +@@ -1682,6 +1766,7 @@ + @comment math.h + @comment ISO + @deftypefn Macro int isless (@emph{real-floating} @var{x}, @emph{real-floating} @var{y}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This macro determines whether the argument @var{x} is less than @var{y}. + It is equivalent to @code{(@var{x}) < (@var{y})}, but no exception is + raised if @var{x} or @var{y} are NaN. +@@ -1690,6 +1775,7 @@ + @comment math.h + @comment ISO + @deftypefn Macro int islessequal (@emph{real-floating} @var{x}, @emph{real-floating} @var{y}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This macro determines whether the argument @var{x} is less than or equal + to @var{y}. It is equivalent to @code{(@var{x}) <= (@var{y})}, but no + exception is raised if @var{x} or @var{y} are NaN. +@@ -1698,6 +1784,7 @@ + @comment math.h + @comment ISO + @deftypefn Macro int islessgreater (@emph{real-floating} @var{x}, @emph{real-floating} @var{y}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This macro determines whether the argument @var{x} is less or greater + than @var{y}. It is equivalent to @code{(@var{x}) < (@var{y}) || + (@var{x}) > (@var{y})} (although it only evaluates @var{x} and @var{y} +@@ -1710,6 +1797,7 @@ + @comment math.h + @comment ISO + @deftypefn Macro int isunordered (@emph{real-floating} @var{x}, @emph{real-floating} @var{y}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This macro determines whether its arguments are unordered. In other + words, it is true if @var{x} or @var{y} are NaN, and false otherwise. + @end deftypefn +@@ -1743,6 +1831,7 @@ + @comment math.h + @comment ISO + @deftypefunx {long double} fminl (long double @var{x}, long double @var{y}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{fmin} function returns the lesser of the two values @var{x} + and @var{y}. It is similar to the expression + @smallexample +@@ -1763,6 +1852,7 @@ + @comment math.h + @comment ISO + @deftypefunx {long double} fmaxl (long double @var{x}, long double @var{y}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{fmax} function returns the greater of the two values @var{x} + and @var{y}. + +@@ -1779,6 +1869,7 @@ + @comment math.h + @comment ISO + @deftypefunx {long double} fdiml (long double @var{x}, long double @var{y}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{fdim} function returns the positive difference between + @var{x} and @var{y}. The positive difference is @math{@var{x} - + @var{y}} if @var{x} is greater than @var{y}, and @math{0} otherwise. +@@ -1796,6 +1887,7 @@ + @comment ISO + @deftypefunx {long double} fmal (long double @var{x}, long double @var{y}, long double @var{z}) + @cindex butterfly ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{fma} function performs floating-point multiply-add. This is + the operation @math{(@var{x} @mul{} @var{y}) + @var{z}}, but the + intermediate result is not rounded to the destination type. This can +@@ -1925,6 +2017,7 @@ + @comment complex.h + @comment ISO + @deftypefunx {long double} creall (complex long double @var{z}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + These functions return the real part of the complex number @var{z}. + @end deftypefun + +@@ -1937,6 +2030,7 @@ + @comment complex.h + @comment ISO + @deftypefunx {long double} cimagl (complex long double @var{z}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + These functions return the imaginary part of the complex number @var{z}. + @end deftypefun + +@@ -1949,6 +2043,7 @@ + @comment complex.h + @comment ISO + @deftypefunx {complex long double} conjl (complex long double @var{z}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + These functions return the conjugate value of the complex number + @var{z}. The conjugate of a complex number has the same real part and a + negated imaginary part. In other words, @samp{conj(a + bi) = a + -bi}. +@@ -1963,6 +2058,7 @@ + @comment complex.h + @comment ISO + @deftypefunx {long double} cargl (complex long double @var{z}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + These functions return the argument of the complex number @var{z}. + The argument of a complex number is the angle in the complex plane + between the positive real axis and a line passing through zero and the +@@ -1981,8 +2077,9 @@ + @comment complex.h + @comment ISO + @deftypefunx {complex long double} cprojl (complex long double @var{z}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + These functions return the projection of the complex value @var{z} onto +-the Riemann sphere. Values with a infinite imaginary part are projected ++the Riemann sphere. Values with an infinite imaginary part are projected + to positive infinity on the real axis, even if the real part is NaN. If + the real part is infinite, the result is equivalent to + +@@ -2026,6 +2123,15 @@ + @comment stdlib.h + @comment ISO + @deftypefun {long int} strtol (const char *restrict @var{string}, char **restrict @var{tailptr}, int @var{base}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} ++@c strtol uses the thread-local pointer to the locale in effect, and ++@c strtol_l loads the LC_NUMERIC locale data from it early on and once, ++@c but if the locale is the global locale, and another thread calls ++@c setlocale in a way that modifies the pointer to the LC_CTYPE locale ++@c category, the behavior of e.g. IS*, TOUPPER will vary throughout the ++@c execution of the function, because they re-read the locale data from ++@c the given locale pointer. We solved this by documenting setlocale as ++@c MT-Unsafe. + The @code{strtol} (``string-to-long'') function converts the initial + part of @var{string} to a signed integer, which is returned as a value + of type @code{long int}. +@@ -2089,6 +2195,7 @@ + @comment wchar.h + @comment ISO + @deftypefun {long int} wcstol (const wchar_t *restrict @var{string}, wchar_t **restrict @var{tailptr}, int @var{base}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + The @code{wcstol} function is equivalent to the @code{strtol} function + in nearly all aspects but handles wide character strings. + +@@ -2098,6 +2205,7 @@ + @comment stdlib.h + @comment ISO + @deftypefun {unsigned long int} strtoul (const char *retrict @var{string}, char **restrict @var{tailptr}, int @var{base}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + The @code{strtoul} (``string-to-unsigned-long'') function is like + @code{strtol} except it converts to an @code{unsigned long int} value. + The syntax is the same as described above for @code{strtol}. The value +@@ -2116,6 +2224,7 @@ + @comment wchar.h + @comment ISO + @deftypefun {unsigned long int} wcstoul (const wchar_t *restrict @var{string}, wchar_t **restrict @var{tailptr}, int @var{base}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + The @code{wcstoul} function is equivalent to the @code{strtoul} function + in nearly all aspects but handles wide character strings. + +@@ -2125,6 +2234,7 @@ + @comment stdlib.h + @comment ISO + @deftypefun {long long int} strtoll (const char *restrict @var{string}, char **restrict @var{tailptr}, int @var{base}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + The @code{strtoll} function is like @code{strtol} except that it returns + a @code{long long int} value, and accepts numbers with a correspondingly + larger range. +@@ -2141,6 +2251,7 @@ + @comment wchar.h + @comment ISO + @deftypefun {long long int} wcstoll (const wchar_t *restrict @var{string}, wchar_t **restrict @var{tailptr}, int @var{base}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + The @code{wcstoll} function is equivalent to the @code{strtoll} function + in nearly all aspects but handles wide character strings. + +@@ -2150,12 +2261,14 @@ + @comment stdlib.h + @comment BSD + @deftypefun {long long int} strtoq (const char *restrict @var{string}, char **restrict @var{tailptr}, int @var{base}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + @code{strtoq} (``string-to-quad-word'') is the BSD name for @code{strtoll}. + @end deftypefun + + @comment wchar.h + @comment GNU + @deftypefun {long long int} wcstoq (const wchar_t *restrict @var{string}, wchar_t **restrict @var{tailptr}, int @var{base}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + The @code{wcstoq} function is equivalent to the @code{strtoq} function + in nearly all aspects but handles wide character strings. + +@@ -2165,6 +2278,7 @@ + @comment stdlib.h + @comment ISO + @deftypefun {unsigned long long int} strtoull (const char *restrict @var{string}, char **restrict @var{tailptr}, int @var{base}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + The @code{strtoull} function is related to @code{strtoll} the same way + @code{strtoul} is related to @code{strtol}. + +@@ -2174,6 +2288,7 @@ + @comment wchar.h + @comment ISO + @deftypefun {unsigned long long int} wcstoull (const wchar_t *restrict @var{string}, wchar_t **restrict @var{tailptr}, int @var{base}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + The @code{wcstoull} function is equivalent to the @code{strtoull} function + in nearly all aspects but handles wide character strings. + +@@ -2183,12 +2298,14 @@ + @comment stdlib.h + @comment BSD + @deftypefun {unsigned long long int} strtouq (const char *restrict @var{string}, char **restrict @var{tailptr}, int @var{base}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + @code{strtouq} is the BSD name for @code{strtoull}. + @end deftypefun + + @comment wchar.h + @comment GNU + @deftypefun {unsigned long long int} wcstouq (const wchar_t *restrict @var{string}, wchar_t **restrict @var{tailptr}, int @var{base}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + The @code{wcstouq} function is equivalent to the @code{strtouq} function + in nearly all aspects but handles wide character strings. + +@@ -2198,6 +2315,7 @@ + @comment inttypes.h + @comment ISO + @deftypefun intmax_t strtoimax (const char *restrict @var{string}, char **restrict @var{tailptr}, int @var{base}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + The @code{strtoimax} function is like @code{strtol} except that it returns + a @code{intmax_t} value, and accepts numbers of a corresponding range. + +@@ -2214,6 +2332,7 @@ + @comment wchar.h + @comment ISO + @deftypefun intmax_t wcstoimax (const wchar_t *restrict @var{string}, wchar_t **restrict @var{tailptr}, int @var{base}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + The @code{wcstoimax} function is equivalent to the @code{strtoimax} function + in nearly all aspects but handles wide character strings. + +@@ -2223,6 +2342,7 @@ + @comment inttypes.h + @comment ISO + @deftypefun uintmax_t strtoumax (const char *restrict @var{string}, char **restrict @var{tailptr}, int @var{base}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + The @code{strtoumax} function is related to @code{strtoimax} + the same way that @code{strtoul} is related to @code{strtol}. + +@@ -2233,6 +2353,7 @@ + @comment wchar.h + @comment ISO + @deftypefun uintmax_t wcstoumax (const wchar_t *restrict @var{string}, wchar_t **restrict @var{tailptr}, int @var{base}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + The @code{wcstoumax} function is equivalent to the @code{strtoumax} function + in nearly all aspects but handles wide character strings. + +@@ -2242,6 +2363,7 @@ + @comment stdlib.h + @comment ISO + @deftypefun {long int} atol (const char *@var{string}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + This function is similar to the @code{strtol} function with a @var{base} + argument of @code{10}, except that it need not detect overflow errors. + The @code{atol} function is provided mostly for compatibility with +@@ -2251,6 +2373,7 @@ + @comment stdlib.h + @comment ISO + @deftypefun int atoi (const char *@var{string}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + This function is like @code{atol}, except that it returns an @code{int}. + The @code{atoi} function is also considered obsolete; use @code{strtol} + instead. +@@ -2259,6 +2382,7 @@ + @comment stdlib.h + @comment ISO + @deftypefun {long long int} atoll (const char *@var{string}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + This function is similar to @code{atol}, except it returns a @code{long + long int}. + +@@ -2323,6 +2447,35 @@ + @comment stdlib.h + @comment ISO + @deftypefun double strtod (const char *restrict @var{string}, char **restrict @var{tailptr}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} ++@c Besides the unsafe-but-ruled-safe locale uses, this uses a lot of ++@c mpn, but it's all safe. ++@c ++@c round_and_return ++@c get_rounding_mode ok ++@c mpn_add_1 ok ++@c mpn_rshift ok ++@c MPN_ZERO ok ++@c MPN2FLOAT -> mpn_construct_(float|double|long_double) ok ++@c str_to_mpn ++@c mpn_mul_1 -> umul_ppmm ok ++@c mpn_add_1 ok ++@c mpn_lshift_1 -> mpn_lshift ok ++@c STRTOF_INTERNAL ++@c MPN_VAR ok ++@c SET_MANTISSA ok ++@c STRNCASECMP ok, wide and narrow ++@c round_and_return ok ++@c mpn_mul ok ++@c mpn_addmul_1 ok ++@c ... mpn_sub ++@c mpn_lshift ok ++@c udiv_qrnnd ok ++@c count_leading_zeros ok ++@c add_ssaaaa ok ++@c sub_ddmmss ok ++@c umul_ppmm ok ++@c mpn_submul_1 ok + The @code{strtod} (``string-to-double'') function converts the initial + part of @var{string} to a floating-point number, which is returned as a + value of type @code{double}. +@@ -2408,6 +2561,7 @@ + @comment stdlib.h + @comment ISO + @deftypefunx {long double} strtold (const char *@var{string}, char **@var{tailptr}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + These functions are analogous to @code{strtod}, but return @code{float} + and @code{long double} values respectively. They report errors in the + same way as @code{strtod}. @code{strtof} can be substantially faster +@@ -2427,6 +2581,7 @@ + @comment stdlib.h + @comment ISO + @deftypefunx {long double} wcstold (const wchar_t *@var{string}, wchar_t **@var{tailptr}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + The @code{wcstod}, @code{wcstof}, and @code{wcstol} functions are + equivalent in nearly all aspect to the @code{strtod}, @code{strtof}, and + @code{strtold} functions but it handles wide character string. +@@ -2439,6 +2594,7 @@ + @comment stdlib.h + @comment ISO + @deftypefun double atof (const char *@var{string}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + This function is similar to the @code{strtod} function, except that it + need not detect overflow and underflow errors. The @code{atof} function + is provided mostly for compatibility with existing code; using +@@ -2447,7 +2603,8 @@ + + @Theglibc{} also provides @samp{_l} versions of these functions, + which take an additional argument, the locale to use in conversion. +-@xref{Parsing of Integers}. ++ ++See also @ref{Parsing of Integers}. + + @node System V Number Conversion + @section Old-fashioned System V number-to-string functions +@@ -2465,9 +2622,10 @@ + @comment stdlib.h + @comment SVID, Unix98 + @deftypefun {char *} ecvt (double @var{value}, int @var{ndigit}, int *@var{decpt}, int *@var{neg}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:ecvt}}@asunsafe{}@acsafe{}} + The function @code{ecvt} converts the floating-point number @var{value} + to a string with at most @var{ndigit} decimal digits. The +-returned string contains no decimal point or sign. The first digit of ++returned string contains no decimal point or sign. The first digit of + the string is non-zero (unless @var{value} is actually zero) and the + last digit is rounded to nearest. @code{*@var{decpt}} is set to the + index in the string of the first digit after the decimal point. +@@ -2490,6 +2648,7 @@ + @comment stdlib.h + @comment SVID, Unix98 + @deftypefun {char *} fcvt (double @var{value}, int @var{ndigit}, int *@var{decpt}, int *@var{neg}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:fcvt}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + The function @code{fcvt} is like @code{ecvt}, but @var{ndigit} specifies + the number of digits after the decimal point. If @var{ndigit} is less + than zero, @var{value} is rounded to the @math{@var{ndigit}+1}'th place to the +@@ -2508,6 +2667,9 @@ + @comment stdlib.h + @comment SVID, Unix98 + @deftypefun {char *} gcvt (double @var{value}, int @var{ndigit}, char *@var{buf}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c gcvt calls sprintf, that ultimately calls vfprintf, which malloc()s ++@c args_value if it's too large, but gcvt never exercises this path. + @code{gcvt} is functionally equivalent to @samp{sprintf(buf, "%*g", + ndigit, value}. It is provided only for compatibility's sake. It + returns @var{buf}. +@@ -2522,6 +2684,7 @@ + @comment stdlib.h + @comment GNU + @deftypefun {char *} qecvt (long double @var{value}, int @var{ndigit}, int *@var{decpt}, int *@var{neg}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:qecvt}}@asunsafe{}@acsafe{}} + This function is equivalent to @code{ecvt} except that it takes a + @code{long double} for the first parameter and that @var{ndigit} is + restricted by the precision of a @code{long double}. +@@ -2530,6 +2693,7 @@ + @comment stdlib.h + @comment GNU + @deftypefun {char *} qfcvt (long double @var{value}, int @var{ndigit}, int *@var{decpt}, int *@var{neg}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:qfcvt}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + This function is equivalent to @code{fcvt} except that it + takes a @code{long double} for the first parameter and that @var{ndigit} is + restricted by the precision of a @code{long double}. +@@ -2538,6 +2702,7 @@ + @comment stdlib.h + @comment GNU + @deftypefun {char *} qgcvt (long double @var{value}, int @var{ndigit}, char *@var{buf}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function is equivalent to @code{gcvt} except that it takes a + @code{long double} for the first parameter and that @var{ndigit} is + restricted by the precision of a @code{long double}. +@@ -2558,6 +2723,7 @@ + @comment stdlib.h + @comment GNU + @deftypefun int ecvt_r (double @var{value}, int @var{ndigit}, int *@var{decpt}, int *@var{neg}, char *@var{buf}, size_t @var{len}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{ecvt_r} function is the same as @code{ecvt}, except + that it places its result into the user-specified buffer pointed to by + @var{buf}, with length @var{len}. The return value is @code{-1} in +@@ -2569,6 +2735,7 @@ + @comment stdlib.h + @comment SVID, Unix98 + @deftypefun int fcvt_r (double @var{value}, int @var{ndigit}, int *@var{decpt}, int *@var{neg}, char *@var{buf}, size_t @var{len}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{fcvt_r} function is the same as @code{fcvt}, except that it + places its result into the user-specified buffer pointed to by + @var{buf}, with length @var{len}. The return value is @code{-1} in +@@ -2580,6 +2747,7 @@ + @comment stdlib.h + @comment GNU + @deftypefun int qecvt_r (long double @var{value}, int @var{ndigit}, int *@var{decpt}, int *@var{neg}, char *@var{buf}, size_t @var{len}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{qecvt_r} function is the same as @code{qecvt}, except + that it places its result into the user-specified buffer pointed to by + @var{buf}, with length @var{len}. The return value is @code{-1} in +@@ -2591,6 +2759,7 @@ + @comment stdlib.h + @comment GNU + @deftypefun int qfcvt_r (long double @var{value}, int @var{ndigit}, int *@var{decpt}, int *@var{neg}, char *@var{buf}, size_t @var{len}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{qfcvt_r} function is the same as @code{qfcvt}, except + that it places its result into the user-specified buffer pointed to by + @var{buf}, with length @var{len}. The return value is @code{-1} in +diff -urN glibc-2.17-c758a686/manual/charset.texi glibc-2.17-c758a686/manual/charset.texi +--- glibc-2.17-c758a686/manual/charset.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/charset.texi 2014-09-12 16:10:06.045792717 -0400 +@@ -504,6 +504,14 @@ + @comment wchar.h + @comment ISO + @deftypefun int mbsinit (const mbstate_t *@var{ps}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c ps is dereferenced once, unguarded. This would call for @mtsrace:ps, ++@c but since a single word-sized field is (atomically) accessed, any ++@c race here would be harmless. Other functions that take an optional ++@c mbstate_t* argument named ps are marked with @mtasurace:/!ps, ++@c to indicate that the function uses a static buffer if ps is NULL. ++@c These could also have been marked with @mtsrace:ps, but we'll omit ++@c that for brevity, for it's somewhat redundant with the @mtasurace. + The @code{mbsinit} function determines whether the state object pointed + to by @var{ps} is in the initial state. If @var{ps} is a null pointer or + the object is in the initial state the return value is nonzero. Otherwise +@@ -559,6 +567,14 @@ + @comment wchar.h + @comment ISO + @deftypefun wint_t btowc (int @var{c}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} ++@c Calls btowc_fct or __fct; reads from locale, and from the ++@c get_gconv_fcts result multiple times. get_gconv_fcts calls ++@c __wcsmbs_load_conv to initialize the ctype if it's null. ++@c wcsmbs_load_conv takes a non-recursive wrlock before allocating ++@c memory for the fcts structure, initializing it, and then storing it ++@c in the locale object. The initialization involves dlopening and a ++@c lot more. + The @code{btowc} function (``byte to wide character'') converts a valid + single byte character @var{c} in the initial shift state into the wide + character equivalent using the conversion rules from the currently +@@ -615,6 +631,7 @@ + @comment wchar.h + @comment ISO + @deftypefun int wctob (wint_t @var{c}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} + The @code{wctob} function (``wide character to byte'') takes as the + parameter a valid wide character. If the multibyte representation for + this character in the initial state is exactly one byte long, the return +@@ -634,6 +651,7 @@ + @comment wchar.h + @comment ISO + @deftypefun size_t mbrtowc (wchar_t *restrict @var{pwc}, const char *restrict @var{s}, size_t @var{n}, mbstate_t *restrict @var{ps}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:mbrtowc/!ps}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} + @cindex stateful + The @code{mbrtowc} function (``multibyte restartable to wide + character'') converts the next multibyte character in the string pointed +@@ -728,6 +746,7 @@ + @comment wchar.h + @comment ISO + @deftypefun size_t mbrlen (const char *restrict @var{s}, size_t @var{n}, mbstate_t *@var{ps}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:mbrlen/!ps}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} + The @code{mbrlen} function (``multibyte restartable length'') computes + the number of at most @var{n} bytes starting at @var{s}, which form the + next valid and complete multibyte character. +@@ -786,7 +805,7 @@ + This function simply calls @code{mbrlen} for each multibyte character + in the string and counts the number of function calls. Please note that + we here use @code{MB_LEN_MAX} as the size argument in the @code{mbrlen} +-call. This is acceptable since a) this value is larger then the length of ++call. This is acceptable since a) this value is larger than the length of + the longest multibyte character sequence and b) we know that the string + @var{s} ends with a NUL byte, which cannot be part of any other multibyte + character sequence but the one representing the NUL wide character. +@@ -811,6 +830,50 @@ + @comment wchar.h + @comment ISO + @deftypefun size_t wcrtomb (char *restrict @var{s}, wchar_t @var{wc}, mbstate_t *restrict @var{ps}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:wcrtomb/!ps}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} ++@c wcrtomb uses a static, non-thread-local unguarded state variable when ++@c PS is NULL. When a state is passed in, and it's not used ++@c concurrently in other threads, this function behaves safely as long ++@c as gconv modules don't bring MT safety issues of their own. ++@c Attempting to load gconv modules or to build conversion chains in ++@c signal handlers may encounter gconv databases or caches in a ++@c partially-updated state, and asynchronous cancellation may leave them ++@c in such states, besides leaking the lock that guards them. ++@c get_gconv_fcts ok ++@c wcsmbs_load_conv ok ++@c norm_add_slashes ok ++@c wcsmbs_getfct ok ++@c gconv_find_transform ok ++@c gconv_read_conf (libc_once) ++@c gconv_lookup_cache ok ++@c find_module_idx ok ++@c find_module ok ++@c gconv_find_shlib (ok) ++@c ->init_fct (assumed ok) ++@c gconv_get_builtin_trans ok ++@c gconv_release_step ok ++@c do_lookup_alias ok ++@c find_derivation ok ++@c derivation_lookup ok ++@c increment_counter ok ++@c gconv_find_shlib ok ++@c step->init_fct (assumed ok) ++@c gen_steps ok ++@c gconv_find_shlib ok ++@c dlopen (presumed ok) ++@c dlsym (presumed ok) ++@c step->init_fct (assumed ok) ++@c step->end_fct (assumed ok) ++@c gconv_get_builtin_trans ok ++@c gconv_release_step ok ++@c add_derivation ok ++@c gconv_close_transform ok ++@c gconv_release_step ok ++@c step->end_fct (assumed ok) ++@c gconv_release_shlib ok ++@c dlclose (presumed ok) ++@c gconv_release_cache ok ++@c ->tomb->__fct (assumed ok) + The @code{wcrtomb} function (``wide character restartable to + multibyte'') converts a single wide character into a multibyte string + corresponding to that wide character. +@@ -955,8 +1018,9 @@ + @comment wchar.h + @comment ISO + @deftypefun size_t mbsrtowcs (wchar_t *restrict @var{dst}, const char **restrict @var{src}, size_t @var{len}, mbstate_t *restrict @var{ps}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:mbsrtowcs/!ps}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} + The @code{mbsrtowcs} function (``multibyte string restartable to wide +-character string'') converts an NUL-terminated multibyte character ++character string'') converts a NUL-terminated multibyte character + string at @code{*@var{src}} into an equivalent wide character string, + including the NUL wide character at the end. The conversion is started + using the state information from the object pointed to by @var{ps} or +@@ -1039,6 +1103,7 @@ + @comment wchar.h + @comment ISO + @deftypefun size_t wcsrtombs (char *restrict @var{dst}, const wchar_t **restrict @var{src}, size_t @var{len}, mbstate_t *restrict @var{ps}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:wcsrtombs/!ps}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} + The @code{wcsrtombs} function (``wide character string restartable to + multibyte string'') converts the NUL-terminated wide character string at + @code{*@var{src}} into an equivalent multibyte character string and +@@ -1084,6 +1149,7 @@ + @comment wchar.h + @comment GNU + @deftypefun size_t mbsnrtowcs (wchar_t *restrict @var{dst}, const char **restrict @var{src}, size_t @var{nmc}, size_t @var{len}, mbstate_t *restrict @var{ps}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:mbsnrtowcs/!ps}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} + The @code{mbsnrtowcs} function is very similar to the @code{mbsrtowcs} + function. All the parameters are the same except for @var{nmc}, which is + new. The return value is the same as for @code{mbsrtowcs}. +@@ -1136,6 +1202,7 @@ + @comment wchar.h + @comment GNU + @deftypefun size_t wcsnrtombs (char *restrict @var{dst}, const wchar_t **restrict @var{src}, size_t @var{nwc}, size_t @var{len}, mbstate_t *restrict @var{ps}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:wcsnrtombs/!ps}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} + The @code{wcsnrtombs} function implements the conversion from wide + character strings to multibyte character strings. It is similar to + @code{wcsrtombs} but, just like @code{mbsnrtowcs}, it takes an extra +@@ -1280,6 +1347,7 @@ + @comment stdlib.h + @comment ISO + @deftypefun int mbtowc (wchar_t *restrict @var{result}, const char *restrict @var{string}, size_t @var{size}) ++@safety{@prelim{}@mtunsafe{@mtasurace{}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} + The @code{mbtowc} (``multibyte to wide character'') function when called + with non-null @var{string} converts the first multibyte character + beginning at @var{string} to its corresponding wide character code. It +@@ -1314,6 +1382,7 @@ + @comment stdlib.h + @comment ISO + @deftypefun int wctomb (char *@var{string}, wchar_t @var{wchar}) ++@safety{@prelim{}@mtunsafe{@mtasurace{}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} + The @code{wctomb} (``wide character to multibyte'') function converts + the wide character code @var{wchar} to its corresponding multibyte + character sequence, and stores the result in bytes starting at +@@ -1353,6 +1422,7 @@ + @comment stdlib.h + @comment ISO + @deftypefun int mblen (const char *@var{string}, size_t @var{size}) ++@safety{@prelim{}@mtunsafe{@mtasurace{}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} + The @code{mblen} function with a non-null @var{string} argument returns + the number of bytes that make up the multibyte character beginning at + @var{string}, never examining more than @var{size} bytes. (The idea is +@@ -1391,6 +1461,9 @@ + @comment stdlib.h + @comment ISO + @deftypefun size_t mbstowcs (wchar_t *@var{wstring}, const char *@var{string}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} ++@c Odd... Although this was supposed to be non-reentrant, the internal ++@c state is not a static buffer, but an automatic variable. + The @code{mbstowcs} (``multibyte string to wide character string'') + function converts the null-terminated string of multibyte characters + @var{string} to an array of wide character codes, storing not more than +@@ -1431,6 +1504,7 @@ + @comment stdlib.h + @comment ISO + @deftypefun size_t wcstombs (char *@var{string}, const wchar_t *@var{wstring}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} + The @code{wcstombs} (``wide character string to multibyte string'') + function converts the null-terminated wide character array @var{wstring} + into a string containing multibyte characters, storing not more than +@@ -1618,6 +1692,16 @@ + @comment iconv.h + @comment XPG2 + @deftypefun iconv_t iconv_open (const char *@var{tocode}, const char *@var{fromcode}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} ++@c Calls malloc if tocode and/or fromcode are too big for alloca. Calls ++@c strip and upstr on both, then gconv_open. strip and upstr call ++@c isalnum_l and toupper_l with the C locale. gconv_open may MT-safely ++@c tokenize toset, replace unspecified codesets with the current locale ++@c (possibly two different accesses), and finally it calls ++@c gconv_find_transform and initializes the gconv_t result with all the ++@c steps in the conversion sequence, running each one's initializer, ++@c destructing and releasing them all if anything fails. ++ + The @code{iconv_open} function has to be used before starting a + conversion. The two parameters this function takes determine the + source and destination character set for the conversion, and if the +@@ -1625,7 +1709,7 @@ + function returns a handle. + + If the wanted conversion is not available, the @code{iconv_open} function +-returns @code{(iconv_t) -1}. In this case the global variable ++returns @code{(iconv_t) -1}. In this case the global variable + @code{errno} can have the following values: + + @table @code +@@ -1682,6 +1766,12 @@ + @comment iconv.h + @comment XPG2 + @deftypefun int iconv_close (iconv_t @var{cd}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{}}} ++@c Calls gconv_close to destruct and release each of the conversion ++@c steps, release the gconv_t object, then call gconv_close_transform. ++@c Access to the gconv_t object is not guarded, but calling iconv_close ++@c concurrently with any other use is undefined. ++ + The @code{iconv_close} function frees all resources associated with the + handle @var{cd}, which must have been returned by a successful call to + the @code{iconv_open} function. +@@ -1708,6 +1798,10 @@ + @comment iconv.h + @comment XPG2 + @deftypefun size_t iconv (iconv_t @var{cd}, char **@var{inbuf}, size_t *@var{inbytesleft}, char **@var{outbuf}, size_t *@var{outbytesleft}) ++@safety{@prelim{}@mtsafe{@mtsrace{:cd}}@assafe{}@acunsafe{@acucorrupt{}}} ++@c Without guarding access to the iconv_t object pointed to by cd, call ++@c the conversion function to convert inbuf or flush the internal ++@c conversion state. + @cindex stateful + The @code{iconv} function converts the text in the input buffer + according to the rules associated with the descriptor @var{cd} and +@@ -1744,7 +1838,7 @@ + Therefore an @code{iconv} call to reset the state should always be + performed if some protocol requires this for the output text. + +-The conversion stops for one of three reasons. The first is that all ++The conversion stops for one of three reasons. The first is that all + characters from the input buffer are converted. This actually can mean + two things: either all bytes from the input buffer are consumed or + there are some bytes at the end of the buffer that possibly can form a +@@ -2039,7 +2133,7 @@ + + Unfortunately, the answer is: there is no general solution. On some + systems guessing might help. On those systems most character sets can +-convert to and from UTF-8 encoded @w{ISO 10646} or Unicode text. Beside ++convert to and from UTF-8 encoded @w{ISO 10646} or Unicode text. Beside + this only some very system-specific methods can help. Since the + conversion functions come from loadable modules and these modules must + be stored somewhere in the filesystem, one @emph{could} try to find them +@@ -2239,7 +2333,7 @@ + + So far this section has described how modules are located and considered + to be used. What remains to be described is the interface of the modules +-so that one can write new ones. This section describes the interface as ++so that one can write new ones. This section describes the interface as + it is in use in January 1999. The interface will change a bit in the + future but, with luck, only in an upwardly compatible way. + +@@ -2485,7 +2579,7 @@ + same size, the minimum and maximum values are the same. + + @item __stateful +-This element must be initialized to an nonzero value if the source ++This element must be initialized to a nonzero value if the source + character set is stateful. Otherwise it must be zero. + @end table + +@@ -2824,7 +2918,7 @@ + /* @r{Run the conversion loop. @code{status} is set} + @r{appropriately afterwards.} */ + +- /* @r{If this is the last step, leave the loop. There is} ++ /* @r{If this is the last step, leave the loop. There is} + @r{nothing we can do.} */ + if (data->__is_last) + @{ +diff -urN glibc-2.17-c758a686/manual/check-safety.sh glibc-2.17-c758a686/manual/check-safety.sh +--- glibc-2.17-c758a686/manual/check-safety.sh 1969-12-31 19:00:00.000000000 -0500 ++++ glibc-2.17-c758a686/manual/check-safety.sh 2014-09-12 16:10:06.044792719 -0400 +@@ -0,0 +1,119 @@ ++#! /bin/sh ++ ++# Copyright 2014 Free Software Foundation, Inc. ++# This file is part of the GNU C Library. ++ ++# The GNU C Library is free software; you can redistribute it and/or ++# modify it under the terms of the GNU Lesser General Public ++# License as published by the Free Software Foundation; either ++# version 2.1 of the License, or (at your option) any later version. ++ ++# The GNU C Library is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++# Lesser General Public License for more details. ++ ++# You should have received a copy of the GNU Lesser General Public ++# License along with the GNU C Library; if not, see ++# . ++ ++ ++# Check that the @safety notes are self-consistent, i.e., that they're ++# in proper order (mt then as then ac), that remarks appear within ++# corresponding sections (mt within mt, etc), that unsafety always has ++# an explicit reason and when there's a reason for unsafety it's not ++# safe, and that there aren't duplicates remarks. ++ ++ ++success=: ++ ++# If no arguments are given, take all *.texi files in the current directory. ++test $# != 0 || set *.texi ++ ++# Check that all safety remarks have entries for all of MT, AS and AC, ++# in this order, with an optional prelim note before them. ++grep -n '^@safety' "$@" | ++grep -v ':@safety{\(@prelim{}\)\?@mt\(un\)\?safe{.*}'\ ++'@as\(un\)\?safe{.*}@ac\(un\)\?safe{.*}}' && ++success=false ++ ++# Check that @mt-started notes appear within @mtsafe or @mtunsafe, ++# that @as-started notes appear within @assafe or @asunsafe, and that ++# @ac-started notes appear within @acsafe or @acunsafe. Also check ++# that @mt, @as and @ac are followed by an s (for safe) or u (for ++# unsafe), but let @mt have as, ac or asc before [su], and let @as ++# have a c (for cancel) before [su]. Also make sure blanks separate ++# each of the annotations. ++grep -n '^@safety' "$@" | ++grep -v ':@safety{\(@prelim{}\)\?'\ ++'@mt\(un\)\?safe{\(@mt\(asc\?\|ac\)\?[su][^ ]*}\)\?'\ ++'\( @mt\(asc\?\|ac\)\?[su][^ ]*}\)*}'\ ++'@as\(un\)\?safe{\(@asc\?[su][^ ]*}\)\?'\ ++'\( @asc\?[su][^ ]*}\)*}'\ ++'@ac\(un\)\?safe{\(@ac[su][^ ]*}\)\?'\ ++'\( @ac[su][^ ]*}\)*}}' && ++success=false ++ ++# Make sure safety lines marked as @mtsafe do not contain any ++# MT-Unsafe remark; that would be @mtu, but there could be as, ac or ++# asc between mt and u. ++grep -n '^@safety.*@mtsafe' "$@" | ++grep '@mt\(asc\?\|ac\)?u' "$@" && ++success=false ++ ++# Make sure @mtunsafe lines contain at least one @mtu remark (with ++# optional as, ac or asc between mt and u). ++grep -n '^@safety.*@mtunsafe' "$@" | ++grep -v '@mtunsafe{.*@mt\(asc\?\|ac\)\?u' && ++success=false ++ ++# Make sure safety lines marked as @assafe do not contain any AS-Unsafe ++# remark, which could be @asu or @mtasu note (with an optional c ++# between as and u in both cases). ++grep -n '^@safety.*@assafe' "$@" | ++grep '@\(mt\)\?asc\?u' && ++success=false ++ ++# Make sure @asunsafe lines contain at least one @asu remark (which ++# could be @ascu, or @mtasu or even @mtascu). ++grep -n '^@safety.*@asunsafe' "$@" | ++grep -v '@mtasc\?u.*@asunsafe\|@asunsafe{.*@asc\?u' && ++success=false ++ ++# Make sure safety lines marked as @acsafe do not contain any ++# AC-Unsafe remark, which could be @acu, @ascu or even @mtacu or ++# @mtascu. ++grep -n '^@safety.*@acsafe' "$@" | ++grep '@\(mt\)\?as\?cu' && ++success=false ++ ++# Make sure @acunsafe lines contain at least one @acu remark (possibly ++# implied by @ascu, @mtacu or @mtascu). ++grep -n '^@safety.*@acunsafe' "$@" | ++grep -v '@\(mtas\?\|as\)cu.*@acunsafe\|@acunsafe{.*@acu' && ++success=false ++ ++# Make sure there aren't duplicate remarks in the same safety note. ++grep -n '^@safety' "$@" | ++grep '[^:]\(@\(mt\|a[sc]\)[^ {]*{[^ ]*}\).*[^:]\1' && ++success=false ++ ++# Check that comments containing safety remarks do not contain {}s, ++# that all @mt remarks appear before @as remarks, that in turn appear ++# before @ac remarks, all properly blank-separated, and that an ++# optional comment about exclusions is between []s at the end of the ++# line. ++grep -n '^@c \+[^@ ]\+\( dup\)\?'\ ++'\( @\(mt\|a[sc]\)[^ ]*\)*\( \[.*\]\)\?$' "$@" | ++grep -v ':@c *[^@{}]*\( @mt[^ {}]*\)*'\ ++'\( @as[^ {}]*\)*\( @ac[^ {}]*\)*\( \[.*\]\)\?$' && ++success=false ++ ++# Check that comments containing safety remarks do not contain ++# duplicate remarks. ++grep -n '^@c \+[^@ ]\+\( dup\)\?'\ ++'\( @\(mt\|a[sc]\)[^ ]*\)*\( \[.*\]\)\?$' "$@" | ++grep '[^:]\(@\(mt\|a[sc]\)[^ ]*\) \(.*[^:]\)\?\1\($\| \)' && ++success=false ++ ++$success +diff -urN glibc-2.17-c758a686/manual/conf.texi glibc-2.17-c758a686/manual/conf.texi +--- glibc-2.17-c758a686/manual/conf.texi 2014-09-12 16:08:17.965070383 -0400 ++++ glibc-2.17-c758a686/manual/conf.texi 2014-09-12 16:10:06.047792712 -0400 +@@ -114,7 +114,7 @@ + + @comment limits.h + @comment POSIX.1 +-@deftypevr Macro int SSIZE_MAX ++@deftypevr Macro ssize_t SSIZE_MAX + The largest value that can fit in an object of type @code{ssize_t}. + Effectively, this is the limit on the number of bytes that can be read + or written in a single operation. +@@ -288,6 +288,17 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun {long int} sysconf (int @var{parameter}) ++@safety{@prelim{}@mtsafe{@mtsenv{}}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsmem{} @acsfd{}}} ++@c Some parts of the implementation open /proc and /sys files and dirs ++@c to collect system details, using fd and stream I/O depending on the ++@c case. _SC_TZNAME_MAX calls __tzname_max, that (while holding a lock) ++@c calls tzset_internal, that calls getenv if it's called the first ++@c time; there are free and strdup calls in there too. The returned max ++@c value may change over time for TZNAME_MAX, depending on selected ++@c timezones; NPROCS, NPROCS_CONF, PHYS_PAGES, AVPHYS_PAGES, ++@c NGROUPS_MAX, SIGQUEUE_MAX, depending on variable values read from ++@c /proc at each call, and from rlimit-obtained values CHILD_MAX, ++@c OPEN_MAX, ARG_MAX, SIGQUEUE_MAX. + This function is used to inquire about runtime system parameters. The + @var{parameter} argument should be one of the @samp{_SC_} symbols listed + below. +@@ -1121,7 +1132,7 @@ + have on @emph{any} POSIX system. @xref{File Minimums}. + + @cindex limits, link count of files +-@comment limits.h ++@comment limits.h (optional) + @comment POSIX.1 + @deftypevr Macro int LINK_MAX + The uniform system limit (if any) for the number of names for a given +@@ -1348,6 +1359,11 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun {long int} pathconf (const char *@var{filename}, int @var{parameter}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} ++@c When __statfs_link_max finds an ext* filesystem, it may read ++@c /proc/mounts or similar as a mntent stream. ++@c __statfs_chown_restricted may read from ++@c /proc/sys/fs/xfs/restrict_chown as a file descriptor. + This function is used to inquire about the limits that apply to + the file named @var{filename}. + +@@ -1375,6 +1391,8 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun {long int} fpathconf (int @var{filedes}, int @var{parameter}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} ++@c Same caveats as pathconf. + This is just like @code{pathconf} except that an open file descriptor + is used to specify the file for which information is requested, instead + of a file name. +@@ -1624,6 +1642,7 @@ + @comment unistd.h + @comment POSIX.2 + @deftypefun size_t confstr (int @var{parameter}, char *@var{buf}, size_t @var{len}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function reads the value of a string-valued system parameter, + storing the string into @var{len} bytes of memory space starting at + @var{buf}. The @var{parameter} argument should be one of the +diff -urN glibc-2.17-c758a686/manual/crypt.texi glibc-2.17-c758a686/manual/crypt.texi +--- glibc-2.17-c758a686/manual/crypt.texi 2014-09-12 16:08:18.169069859 -0400 ++++ glibc-2.17-c758a686/manual/crypt.texi 2014-09-12 16:10:06.042792724 -0400 +@@ -30,15 +30,15 @@ + and the other based on the Data Encryption Standard (DES) that is + compatible with Unix systems. + +-@cindex AUTH_DES ++@vindex AUTH_DES + @cindex FIPS 140-2 + It also provides support for Secure RPC, and some library functions that +-can be used to perform normal DES encryption. The use of DES when +-using @code{AUTH_DES} in Secure RPC for authentication as provided by +-@theglibc{} is not FIPS 140-2 compliant nor is any other use of DES +-within @theglibc{}. It is recommended that Secure RPC should not be used +-for systems that need to be FIPS 140-2 compliant since all forms of +-supported authentication use normal DES. ++can be used to perform normal DES encryption. The @code{AUTH_DES} ++authentication flavor in Secure RPC, as provided by @theglibc{}, ++uses DES and does not comply with FIPS 140-2 nor does any other use of DES ++within @theglibc{}. It is recommended that Secure RPC should not be used ++for systems that need to comply with FIPS 140-2 since all flavors of ++encrypted authentication use normal DES. + + @menu + * Legal Problems:: This software can get you locked up, or worse. +@@ -99,6 +99,13 @@ + @comment unistd.h + @comment BSD + @deftypefun {char *} getpass (const char *@var{prompt}) ++@safety{@prelim{}@mtunsafe{@mtasuterm{}}@asunsafe{@ascuheap{} @asulock{} @asucorrupt{}}@acunsafe{@acuterm{} @aculock{} @acucorrupt{}}} ++@c This function will attempt to create a stream for terminal I/O, but ++@c will fallback to stdio/stderr. It attempts to change the terminal ++@c mode in a thread-unsafe way, write out the prompt, read the password, ++@c then restore the terminal mode. It has a cleanup to close the stream ++@c in case of (synchronous) cancellation, but not to restore the ++@c terminal mode. + + @code{getpass} outputs @var{prompt}, then reads a string in from the + terminal without echoing it. It tries to connect to the real terminal, +@@ -134,6 +141,13 @@ + @comment crypt.h + @comment BSD, SVID + @deftypefun {char *} crypt (const char *@var{key}, const char *@var{salt}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:crypt}}@asunsafe{@asucorrupt{} @asulock{} @ascuheap{} @ascudlopen{}}@acunsafe{@aculock{} @acsmem{}}} ++@c Besides the obvious problem of returning a pointer into static ++@c storage, the DES initializer takes an internal lock with the usual ++@c set of problems for AS- and AC-Safety. The FIPS mode checker and the ++@c NSS implementations of may leak file descriptors if canceled. The ++@c The MD5, SHA256 and SHA512 implementations will malloc on long keys, ++@c and NSS relies on dlopening, which brings about another can of worms. + + The @code{crypt} function takes a password, @var{key}, as a string, and + a @var{salt} character array which is described below, and returns a +@@ -195,6 +209,9 @@ + @comment crypt.h + @comment GNU + @deftypefun {char *} crypt_r (const char *@var{key}, const char *@var{salt}, {struct crypt_data *} @var{data}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{} @asulock{} @ascuheap{} @ascudlopen{}}@acunsafe{@aculock{} @acsmem{}}} ++@c Compared with crypt, this function fixes the @mtasurace:crypt ++@c problem, but nothing else. + + The @code{crypt_r} function does the same thing as @code{crypt}, but + takes an extra parameter which includes space for its result (among +@@ -241,6 +258,11 @@ + @comment crypt.h + @comment BSD, SVID + @deftypefun void setkey (const char *@var{key}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:crypt}}@asunsafe{@asucorrupt{} @asulock{}}@acunsafe{@aculock{}}} ++@c The static buffer stores the key, making it fundamentally ++@c thread-unsafe. The locking issues are only in the initialization ++@c path; cancelling the initialization will leave the lock held, it ++@c would otherwise repeat the initialization on the next call. + + The @code{setkey} function sets an internal data structure to be an + expanded form of @var{key}. @var{key} is specified as an array of 64 +@@ -252,6 +274,8 @@ + @comment crypt.h + @comment BSD, SVID + @deftypefun void encrypt (char *@var{block}, int @var{edflag}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:crypt}}@asunsafe{@asucorrupt{} @asulock{}}@acunsafe{@aculock{}}} ++@c Same issues as setkey. + + The @code{encrypt} function encrypts @var{block} if + @var{edflag} is 0, otherwise it decrypts @var{block}, using a key +@@ -265,9 +289,11 @@ + @comment crypt.h + @comment GNU + @deftypefun void setkey_r (const char *@var{key}, {struct crypt_data *} @var{data}) ++@c @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{} @asulock{}}@acunsafe{@aculock{}}} + @comment crypt.h + @comment GNU + @deftypefunx void encrypt_r (char *@var{block}, int @var{edflag}, {struct crypt_data *} @var{data}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{} @asulock{}}@acunsafe{@aculock{}}} + + These are reentrant versions of @code{setkey} and @code{encrypt}. The + only difference is the extra parameter, which stores the expanded +@@ -282,6 +308,7 @@ + @comment rpc/des_crypt.h + @comment SUNRPC + @deftypefun int ecb_crypt (char *@var{key}, char *@var{blocks}, unsigned @var{len}, unsigned @var{mode}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + + The function @code{ecb_crypt} encrypts or decrypts one or more blocks + using DES. Each block is encrypted independently. +@@ -356,6 +383,7 @@ + @comment rpc/des_crypt.h + @comment SUNRPC + @deftypefun int DES_FAILED (int @var{err}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This macro returns 1 if @var{err} is a `success' result code from + @code{ecb_crypt} or @code{cbc_crypt}, and 0 otherwise. + @end deftypefun +@@ -363,6 +391,7 @@ + @comment rpc/des_crypt.h + @comment SUNRPC + @deftypefun int cbc_crypt (char *@var{key}, char *@var{blocks}, unsigned @var{len}, unsigned @var{mode}, char *@var{ivec}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + + The function @code{cbc_crypt} encrypts or decrypts one or more blocks + using DES in Cipher Block Chaining mode. +@@ -389,6 +418,7 @@ + @comment rpc/des_crypt.h + @comment SUNRPC + @deftypefun void des_setparity (char *@var{key}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + + The function @code{des_setparity} changes the 64-bit @var{key}, stored + packed in 8-bit bytes, to have odd parity by altering the low bits of +diff -urN glibc-2.17-c758a686/manual/ctype.texi glibc-2.17-c758a686/manual/ctype.texi +--- glibc-2.17-c758a686/manual/ctype.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/ctype.texi 2014-09-12 16:10:06.042792724 -0400 +@@ -66,6 +66,16 @@ + @comment ctype.h + @comment ISO + @deftypefun int islower (int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c The is* macros call __ctype_b_loc to get the ctype array from the ++@c current locale, and then index it by c. __ctype_b_loc reads from ++@c thread-local memory the (indirect) pointer to the ctype array, which ++@c may involve one word access to the global locale object, if that's ++@c the active locale for the thread, and the array, being part of the ++@c locale data, is undeletable, so there's no thread-safety issue. We ++@c might want to mark these with @mtslocale to flag to callers that ++@c changing locales might affect them, even if not these simpler ++@c functions. + Returns true if @var{c} is a lower-case letter. The letter need not be + from the Latin alphabet, any alphabet representable is valid. + @end deftypefun +@@ -74,6 +84,7 @@ + @comment ctype.h + @comment ISO + @deftypefun int isupper (int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Returns true if @var{c} is an upper-case letter. The letter need not be + from the Latin alphabet, any alphabet representable is valid. + @end deftypefun +@@ -82,6 +93,7 @@ + @comment ctype.h + @comment ISO + @deftypefun int isalpha (int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Returns true if @var{c} is an alphabetic character (a letter). If + @code{islower} or @code{isupper} is true of a character, then + @code{isalpha} is also true. +@@ -97,6 +109,7 @@ + @comment ctype.h + @comment ISO + @deftypefun int isdigit (int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Returns true if @var{c} is a decimal digit (@samp{0} through @samp{9}). + @end deftypefun + +@@ -104,6 +117,7 @@ + @comment ctype.h + @comment ISO + @deftypefun int isalnum (int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Returns true if @var{c} is an alphanumeric character (a letter or + number); in other words, if either @code{isalpha} or @code{isdigit} is + true of a character, then @code{isalnum} is also true. +@@ -113,6 +127,7 @@ + @comment ctype.h + @comment ISO + @deftypefun int isxdigit (int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Returns true if @var{c} is a hexadecimal digit. + Hexadecimal digits include the normal decimal digits @samp{0} through + @samp{9} and the letters @samp{A} through @samp{F} and +@@ -123,6 +138,7 @@ + @comment ctype.h + @comment ISO + @deftypefun int ispunct (int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Returns true if @var{c} is a punctuation character. + This means any printing character that is not alphanumeric or a space + character. +@@ -132,6 +148,7 @@ + @comment ctype.h + @comment ISO + @deftypefun int isspace (int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Returns true if @var{c} is a @dfn{whitespace} character. In the standard + @code{"C"} locale, @code{isspace} returns true for only the standard + whitespace characters: +@@ -161,6 +178,7 @@ + @comment ctype.h + @comment ISO + @deftypefun int isblank (int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Returns true if @var{c} is a blank character; that is, a space or a tab. + This function was originally a GNU extension, but was added in @w{ISO C99}. + @end deftypefun +@@ -169,6 +187,7 @@ + @comment ctype.h + @comment ISO + @deftypefun int isgraph (int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Returns true if @var{c} is a graphic character; that is, a character + that has a glyph associated with it. The whitespace characters are not + considered graphic. +@@ -178,6 +197,7 @@ + @comment ctype.h + @comment ISO + @deftypefun int isprint (int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Returns true if @var{c} is a printing character. Printing characters + include all the graphic characters, plus the space (@samp{ }) character. + @end deftypefun +@@ -186,6 +206,7 @@ + @comment ctype.h + @comment ISO + @deftypefun int iscntrl (int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Returns true if @var{c} is a control character (that is, a character that + is not a printing character). + @end deftypefun +@@ -194,6 +215,7 @@ + @comment ctype.h + @comment SVID, BSD + @deftypefun int isascii (int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Returns true if @var{c} is a 7-bit @code{unsigned char} value that fits + into the US/UK ASCII character set. This function is a BSD extension + and is also an SVID extension. +@@ -227,6 +249,10 @@ + @comment ctype.h + @comment ISO + @deftypefun int tolower (int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c The to* macros/functions call different functions that use different ++@c arrays than those of__ctype_b_loc, but the access patterns and ++@c thus safety guarantees are the same. + If @var{c} is an upper-case letter, @code{tolower} returns the corresponding + lower-case letter. If @var{c} is not an upper-case letter, + @var{c} is returned unchanged. +@@ -235,6 +261,7 @@ + @comment ctype.h + @comment ISO + @deftypefun int toupper (int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + If @var{c} is a lower-case letter, @code{toupper} returns the corresponding + upper-case letter. Otherwise @var{c} is returned unchanged. + @end deftypefun +@@ -242,6 +269,7 @@ + @comment ctype.h + @comment SVID, BSD + @deftypefun int toascii (int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function converts @var{c} to a 7-bit @code{unsigned char} value + that fits into the US/UK ASCII character set, by clearing the high-order + bits. This function is a BSD extension and is also an SVID extension. +@@ -250,6 +278,7 @@ + @comment ctype.h + @comment SVID + @deftypefun int _tolower (int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This is identical to @code{tolower}, and is provided for compatibility + with the SVID. @xref{SVID}.@refill + @end deftypefun +@@ -257,6 +286,7 @@ + @comment ctype.h + @comment SVID + @deftypefun int _toupper (int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This is identical to @code{toupper}, and is provided for compatibility + with the SVID. + @end deftypefun +@@ -303,6 +333,18 @@ + @comment wctype.h + @comment ISO + @deftypefun wctype_t wctype (const char *@var{property}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} ++@c Although the source code of wctype contains multiple references to ++@c the locale, that could each reference different locale_data objects ++@c should the global locale object change while active, the compiler can ++@c and does combine them all into a single dereference that resolves ++@c once to the LCTYPE locale object used throughout the function, so it ++@c is safe in (optimized) practice, if not in theory, even when the ++@c locale changes. Ideally we'd explicitly save the resolved ++@c locale_data object to make it visibly safe instead of safe only under ++@c compiler optimizations, but given the decision that setlocale is ++@c MT-Unsafe, all this would afford us would be the ability to not mark ++@c this function with @mtslocale. + The @code{wctype} returns a value representing a class of wide + characters which is identified by the string @var{property}. Beside + some standard properties each locale can define its own ones. In case +@@ -331,6 +373,8 @@ + @comment wctype.h + @comment ISO + @deftypefun int iswctype (wint_t @var{wc}, wctype_t @var{desc}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c The compressed lookup table returned by wctype is read-only. + This function returns a nonzero value if @var{wc} is in the character + class specified by @var{desc}. @var{desc} must previously be returned + by a successful call to @code{wctype}. +@@ -350,6 +394,16 @@ + @comment wctype.h + @comment ISO + @deftypefun int iswalnum (wint_t @var{wc}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} ++@c The implicit wctype call in the isw* functions is actually an ++@c optimized version because the category has a known offset, but the ++@c wctype is equally safe when optimized, unsafe with changing locales ++@c if not optimized (thus @mtslocale). Since it's not a macro, we ++@c always optimize, and the locale can't change in any MT-Safe way, it's ++@c fine. The test whether wc is ASCII to use the non-wide is* ++@c macro/function doesn't bring any other safety issues: the test does ++@c not depend on the locale, and each path after the decision resolves ++@c the locale object only once. + This function returns a nonzero value if @var{wc} is an alphanumeric + character (a letter or number); in other words, if either @code{iswalpha} + or @code{iswdigit} is true of a character, then @code{iswalnum} is also +@@ -370,6 +424,7 @@ + @comment wctype.h + @comment ISO + @deftypefun int iswalpha (wint_t @var{wc}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + Returns true if @var{wc} is an alphabetic character (a letter). If + @code{iswlower} or @code{iswupper} is true of a character, then + @code{iswalpha} is also true. +@@ -394,6 +449,7 @@ + @comment wctype.h + @comment ISO + @deftypefun int iswcntrl (wint_t @var{wc}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + Returns true if @var{wc} is a control character (that is, a character that + is not a printing character). + +@@ -412,6 +468,7 @@ + @comment wctype.h + @comment ISO + @deftypefun int iswdigit (wint_t @var{wc}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + Returns true if @var{wc} is a digit (e.g., @samp{0} through @samp{9}). + Please note that this function does not only return a nonzero value for + @emph{decimal} digits, but for all kinds of digits. A consequence is +@@ -442,6 +499,7 @@ + @comment wctype.h + @comment ISO + @deftypefun int iswgraph (wint_t @var{wc}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + Returns true if @var{wc} is a graphic character; that is, a character + that has a glyph associated with it. The whitespace characters are not + considered graphic. +@@ -461,6 +519,7 @@ + @comment ctype.h + @comment ISO + @deftypefun int iswlower (wint_t @var{wc}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + Returns true if @var{wc} is a lower-case letter. The letter need not be + from the Latin alphabet, any alphabet representable is valid. + +@@ -479,6 +538,7 @@ + @comment wctype.h + @comment ISO + @deftypefun int iswprint (wint_t @var{wc}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + Returns true if @var{wc} is a printing character. Printing characters + include all the graphic characters, plus the space (@samp{ }) character. + +@@ -497,6 +557,7 @@ + @comment wctype.h + @comment ISO + @deftypefun int iswpunct (wint_t @var{wc}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + Returns true if @var{wc} is a punctuation character. + This means any printing character that is not alphanumeric or a space + character. +@@ -516,6 +577,7 @@ + @comment wctype.h + @comment ISO + @deftypefun int iswspace (wint_t @var{wc}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + Returns true if @var{wc} is a @dfn{whitespace} character. In the standard + @code{"C"} locale, @code{iswspace} returns true for only the standard + whitespace characters: +@@ -555,6 +617,7 @@ + @comment wctype.h + @comment ISO + @deftypefun int iswupper (wint_t @var{wc}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + Returns true if @var{wc} is an upper-case letter. The letter need not be + from the Latin alphabet, any alphabet representable is valid. + +@@ -573,6 +636,7 @@ + @comment wctype.h + @comment ISO + @deftypefun int iswxdigit (wint_t @var{wc}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + Returns true if @var{wc} is a hexadecimal digit. + Hexadecimal digits include the normal decimal digits @samp{0} through + @samp{9} and the letters @samp{A} through @samp{F} and +@@ -597,6 +661,7 @@ + @comment wctype.h + @comment ISO + @deftypefun int iswblank (wint_t @var{wc}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + Returns true if @var{wc} is a blank character; that is, a space or a tab. + This function was originally a GNU extension, but was added in @w{ISO C99}. + It is declared in @file{wchar.h}. +@@ -691,6 +756,8 @@ + @comment wctype.h + @comment ISO + @deftypefun wctrans_t wctrans (const char *@var{property}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} ++@c Similar implementation, same caveats as wctype. + The @code{wctrans} function has to be used to find out whether a named + mapping is defined in the current locale selected for the + @code{LC_CTYPE} category. If the returned value is non-zero, you can use +@@ -713,6 +780,8 @@ + @comment wctype.h + @comment ISO + @deftypefun wint_t towctrans (wint_t @var{wc}, wctrans_t @var{desc}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Same caveats as iswctype. + @code{towctrans} maps the input character @var{wc} + according to the rules of the mapping for which @var{desc} is a + descriptor, and returns the value it finds. @var{desc} must be +@@ -730,6 +799,9 @@ + @comment wctype.h + @comment ISO + @deftypefun wint_t towlower (wint_t @var{wc}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} ++@c Same caveats as iswalnum, just using a wctrans rather than a wctype ++@c table. + If @var{wc} is an upper-case letter, @code{towlower} returns the corresponding + lower-case letter. If @var{wc} is not an upper-case letter, + @var{wc} is returned unchanged. +@@ -749,6 +821,7 @@ + @comment wctype.h + @comment ISO + @deftypefun wint_t towupper (wint_t @var{wc}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + If @var{wc} is a lower-case letter, @code{towupper} returns the corresponding + upper-case letter. Otherwise @var{wc} is returned unchanged. + +diff -urN glibc-2.17-c758a686/manual/debug.texi glibc-2.17-c758a686/manual/debug.texi +--- glibc-2.17-c758a686/manual/debug.texi 2014-09-12 16:08:17.824070745 -0400 ++++ glibc-2.17-c758a686/manual/debug.texi 2014-09-12 16:10:06.045792717 -0400 +@@ -1,5 +1,5 @@ + @node Debugging Support +-@c @node Debugging Support, Internal Probes, Cryptographic Functions, Top ++@c @node Debugging Support, POSIX Threads, Cryptographic Functions, Top + @c %MENU% Functions to help debugging applications + @chapter Debugging support + +@@ -36,6 +36,16 @@ + @comment execinfo.h + @comment GNU + @deftypefun int backtrace (void **@var{buffer}, int @var{size}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asuinit{} @ascuheap{} @ascudlopen{} @ascuplugin{} @asulock{}}@acunsafe{@acuinit{} @acsmem{} @aculock{} @acsfd{}}} ++@c The generic implementation just does pointer chasing within the local ++@c stack, without any guarantees that this will handle signal frames ++@c correctly, so it's AS-Unsafe to begin with. However, most (all?) ++@c arches defer to libgcc_s's _Unwind_* implementation, dlopening ++@c libgcc_s.so to that end except in a static version of libc. ++@c libgcc_s's implementation may in turn defer to libunwind. We can't ++@c assume those implementations are AS- or AC-safe, but even if we ++@c could, our own initialization path isn't, and libgcc's implementation ++@c calls malloc and performs internal locking, so... + The @code{backtrace} function obtains a backtrace for the current + thread, as a list of pointers, and places the information into + @var{buffer}. The argument @var{size} should be the number of +@@ -56,6 +66,17 @@ + @comment execinfo.h + @comment GNU + @deftypefun {char **} backtrace_symbols (void *const *@var{buffer}, int @var{size}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{} @aculock{}}} ++@c Collects info returned by _dl_addr in an auto array, allocates memory ++@c for the whole return buffer with malloc then sprintfs into it storing ++@c pointers to the strings into the array entries in the buffer. ++@c _dl_addr takes the recursive dl_load_lock then calls ++@c _dl_find_dso_for_object and determine_info. ++@c _dl_find_dso_for_object calls _dl-addr_inside_object. ++@c All of them are safe as long as the lock is held. ++@c @asucorrupt? It doesn't look like the dynamic loader's data ++@c structures could be in an inconsistent state that would cause ++@c malfunction here. + The @code{backtrace_symbols} function translates the information + obtained from the @code{backtrace} function into an array of strings. + The argument @var{buffer} should be a pointer to an array of addresses +@@ -88,6 +109,11 @@ + @comment execinfo.h + @comment GNU + @deftypefun void backtrace_symbols_fd (void *const *@var{buffer}, int @var{size}, int @var{fd}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@aculock{}}} ++@c Single loop of _dl_addr over addresses, collecting info into an iovec ++@c written out with a writev call per iteration. Addresses and offsets ++@c are converted to hex in auto buffers, so the only potential issue ++@c here is leaking the dl lock in case of cancellation. + The @code{backtrace_symbols_fd} function performs the same translation + as the function @code{backtrace_symbols} function. Instead of returning + the strings to the caller, it writes the strings to the file descriptor +diff -urN glibc-2.17-c758a686/manual/errno.texi glibc-2.17-c758a686/manual/errno.texi +--- glibc-2.17-c758a686/manual/errno.texi 2014-09-12 16:08:17.752070930 -0400 ++++ glibc-2.17-c758a686/manual/errno.texi 2014-09-12 16:10:06.045792717 -0400 +@@ -1293,6 +1293,9 @@ + @comment string.h + @comment ISO + @deftypefun {char *} strerror (int @var{errnum}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:strerror}}@asunsafe{@ascuheap{} @ascuintl{}}@acunsafe{@acsmem{}}} ++@c Calls strerror_r with a static buffer allocated with malloc on the ++@c first use. + The @code{strerror} function maps the error code (@pxref{Checking for + Errors}) specified by the @var{errnum} argument to a descriptive error + message string. The return value is a pointer to this string. +@@ -1310,10 +1313,11 @@ + @comment string.h + @comment GNU + @deftypefun {char *} strerror_r (int @var{errnum}, char *@var{buf}, size_t @var{n}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuintl{}}@acunsafe{}} + The @code{strerror_r} function works like @code{strerror} but instead of + returning the error message in a statically allocated buffer shared by + all threads in the process, it returns a private copy for the +-thread. This might be either some permanent global data or a message ++thread. This might be either some permanent global data or a message + string in the user supplied buffer starting at @var{buf} with the + length of @var{n} bytes. + +@@ -1331,6 +1335,10 @@ + @comment stdio.h + @comment ISO + @deftypefun void perror (const char *@var{message}) ++@safety{@prelim{}@mtsafe{@mtasurace{:stderr}}@asunsafe{@asucorrupt{} @ascuintl{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} ++@c Besides strerror_r's and some of fprintf's issues, if stderr is not ++@c oriented yet, create a new stream with a dup of stderr's fd and write ++@c to that instead of stderr, to avoid orienting it. + This function prints an error message to the stream @code{stderr}; + see @ref{Standard Streams}. The orientation of @code{stderr} is not + changed. +@@ -1442,6 +1450,13 @@ + @comment error.h + @comment GNU + @deftypefun void error (int @var{status}, int @var{errnum}, const char *@var{format}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @asuheap{} @asuintl{}}@acsafe{}} ++@c Cancellation is disabled throughout the execution. It flushes stdout ++@c and then holds a lock on stderr while printing the program name and ++@c then running error_tail. The non-wide case just runs vfprintf; the ++@c wide case converts the message to an alloca/malloc-allocated buffer ++@c with mbsrtowcs, then prints it with vfwprintf. Afterwards, ++@c print_errno_message calls strerror_r and fxprintf. + The @code{error} function can be used to report general problems during + program execution. The @var{format} argument is a format string just + like those given to the @code{printf} family of functions. The +@@ -1477,6 +1492,15 @@ + @comment error.h + @comment GNU + @deftypefun void error_at_line (int @var{status}, int @var{errnum}, const char *@var{fname}, unsigned int @var{lineno}, const char *@var{format}, @dots{}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:error_at_line/error_one_per_line} @mtslocale{}}@asunsafe{@asucorrupt{} @asuheap{} @asuintl{}}@acunsafe{@acucorrupt{/error_one_per_line}}} ++@c The error_one_per_line variable is accessed (without any form of ++@c synchronization, but since it's an int used once, it should be safe ++@c enough) and, if this mode is enabled, static variables used to hold ++@c the last printed file name and line number are accessed and modified ++@c without synchronization; the update is not atomic and it occurs ++@c before disabling cancellation, so it can be interrupted after only ++@c one of the two variables is modified. After that, it's very much ++@c like error. + + The @code{error_at_line} function is very similar to the @code{error} + function. The only difference are the additional parameters @var{fname} +@@ -1508,7 +1532,7 @@ + + @comment error.h + @comment GNU +-@deftypevar {void (*) error_print_progname } (void) ++@deftypevar {void (*error_print_progname)} (void) + If the @code{error_print_progname} variable is defined to a non-zero + value the function pointed to is called by @code{error} or + @code{error_at_line}. It is expected to print the program name or do +@@ -1582,6 +1606,8 @@ + @comment err.h + @comment BSD + @deftypefun void warn (const char *@var{format}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{} @ascuintl{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{}}} ++@c Just calls vwarn with the va_list. + The @code{warn} function is roughly equivalent to a call like + @smallexample + error (0, errno, format, @r{the parameters}) +@@ -1594,14 +1620,21 @@ + @comment err.h + @comment BSD + @deftypefun void vwarn (const char *@var{format}, va_list @var{ap}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{} @ascuintl{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{}}} ++@c While holding stderr's recursive lock, it prints the programname, the ++@c given message, and the error string with fw?printf's %m. When the ++@c stream is wide, convert_and_print converts the format string to an ++@c alloca/malloc-created buffer using mbsrtowcs and then calls fwprintf. + The @code{vwarn} function is just like @code{warn} except that the + parameters for the handling of the format string @var{format} are passed +-in as an value of type @code{va_list}. ++in as a value of type @code{va_list}. + @end deftypefun + + @comment err.h + @comment BSD + @deftypefun void warnx (const char *@var{format}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{}}} ++@c Same as warn, but without the strerror translation issues. + The @code{warnx} function is roughly equivalent to a call like + @smallexample + error (0, 0, format, @r{the parameters}) +@@ -1615,14 +1648,18 @@ + @comment err.h + @comment BSD + @deftypefun void vwarnx (const char *@var{format}, va_list @var{ap}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{}}} ++@c Same as vwarn, but without the strerror translation issues. + The @code{vwarnx} function is just like @code{warnx} except that the + parameters for the handling of the format string @var{format} are passed +-in as an value of type @code{va_list}. ++in as a value of type @code{va_list}. + @end deftypefun + + @comment err.h + @comment BSD + @deftypefun void err (int @var{status}, const char *@var{format}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{} @ascuintl{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{}}} ++@c Same as warn followed by exit. + The @code{err} function is roughly equivalent to a call like + @smallexample + error (status, errno, format, @r{the parameters}) +@@ -1635,14 +1672,18 @@ + @comment err.h + @comment BSD + @deftypefun void verr (int @var{status}, const char *@var{format}, va_list @var{ap}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{} @ascuintl{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{}}} ++@c Same as vwarn followed by exit. + The @code{verr} function is just like @code{err} except that the + parameters for the handling of the format string @var{format} are passed +-in as an value of type @code{va_list}. ++in as a value of type @code{va_list}. + @end deftypefun + + @comment err.h + @comment BSD + @deftypefun void errx (int @var{status}, const char *@var{format}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{}}} ++@c Same as warnx followed by exit. + The @code{errx} function is roughly equivalent to a call like + @smallexample + error (status, 0, format, @r{the parameters}) +@@ -1657,7 +1698,9 @@ + @comment err.h + @comment BSD + @deftypefun void verrx (int @var{status}, const char *@var{format}, va_list @var{ap}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{}}} ++@c Same as vwarnx followed by exit. + The @code{verrx} function is just like @code{errx} except that the + parameters for the handling of the format string @var{format} are passed +-in as an value of type @code{va_list}. ++in as a value of type @code{va_list}. + @end deftypefun +diff -urN glibc-2.17-c758a686/manual/examples/add.c glibc-2.17-c758a686/manual/examples/add.c +--- glibc-2.17-c758a686/manual/examples/add.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/add.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* Example of a Variadic Function +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/argp-ex1.c glibc-2.17-c758a686/manual/examples/argp-ex1.c +--- glibc-2.17-c758a686/manual/examples/argp-ex1.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/argp-ex1.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* Argp example #1 -- a minimal program using argp +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/argp-ex2.c glibc-2.17-c758a686/manual/examples/argp-ex2.c +--- glibc-2.17-c758a686/manual/examples/argp-ex2.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/argp-ex2.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* Argp example #2 -- a pretty minimal program using argp +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/argp-ex3.c glibc-2.17-c758a686/manual/examples/argp-ex3.c +--- glibc-2.17-c758a686/manual/examples/argp-ex3.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/argp-ex3.c 2014-09-12 16:10:06.047792712 -0400 +@@ -1,5 +1,5 @@ + /* Argp example #3 -- a program with options and arguments using argp +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/argp-ex4.c glibc-2.17-c758a686/manual/examples/argp-ex4.c +--- glibc-2.17-c758a686/manual/examples/argp-ex4.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/argp-ex4.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* Argp example #4 -- a program with somewhat more complicated options +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/atexit.c glibc-2.17-c758a686/manual/examples/atexit.c +--- glibc-2.17-c758a686/manual/examples/atexit.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/atexit.c 2014-09-12 16:10:06.047792712 -0400 +@@ -1,5 +1,5 @@ + /* Cleanups on Exit +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/db.c glibc-2.17-c758a686/manual/examples/db.c +--- glibc-2.17-c758a686/manual/examples/db.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/db.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* User and Group Database Example +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/dir2.c glibc-2.17-c758a686/manual/examples/dir2.c +--- glibc-2.17-c758a686/manual/examples/dir2.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/dir2.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* Simple Program to List a Directory, Mark II +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/dir.c glibc-2.17-c758a686/manual/examples/dir.c +--- glibc-2.17-c758a686/manual/examples/dir.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/dir.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* Simple Program to List a Directory +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/execinfo.c glibc-2.17-c758a686/manual/examples/execinfo.c +--- glibc-2.17-c758a686/manual/examples/execinfo.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/execinfo.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* Obtain a backtrace and print it. +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/filecli.c glibc-2.17-c758a686/manual/examples/filecli.c +--- glibc-2.17-c758a686/manual/examples/filecli.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/filecli.c 2014-09-12 16:10:06.047792712 -0400 +@@ -1,5 +1,5 @@ + /* Example of Reading Datagrams +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/filesrv.c glibc-2.17-c758a686/manual/examples/filesrv.c +--- glibc-2.17-c758a686/manual/examples/filesrv.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/filesrv.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* Datagram Socket Example +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/fmtmsgexpl.c glibc-2.17-c758a686/manual/examples/fmtmsgexpl.c +--- glibc-2.17-c758a686/manual/examples/fmtmsgexpl.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/fmtmsgexpl.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* How to use fmtmsg and addseverity. +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/genpass.c glibc-2.17-c758a686/manual/examples/genpass.c +--- glibc-2.17-c758a686/manual/examples/genpass.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/genpass.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* Encrypting Passwords +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/inetcli.c glibc-2.17-c758a686/manual/examples/inetcli.c +--- glibc-2.17-c758a686/manual/examples/inetcli.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/inetcli.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* Byte Stream Socket Example +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/inetsrv.c glibc-2.17-c758a686/manual/examples/inetsrv.c +--- glibc-2.17-c758a686/manual/examples/inetsrv.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/inetsrv.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* Byte Stream Connection Server Example +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/isockad.c glibc-2.17-c758a686/manual/examples/isockad.c +--- glibc-2.17-c758a686/manual/examples/isockad.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/isockad.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* Internet Socket Example using sockaddr_in. +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/longopt.c glibc-2.17-c758a686/manual/examples/longopt.c +--- glibc-2.17-c758a686/manual/examples/longopt.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/longopt.c 2014-09-12 16:10:06.047792712 -0400 +@@ -1,5 +1,5 @@ + /* Example of Parsing Long Options with getopt_long. +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/memopen.c glibc-2.17-c758a686/manual/examples/memopen.c +--- glibc-2.17-c758a686/manual/examples/memopen.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/memopen.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* String Streams +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/memstrm.c glibc-2.17-c758a686/manual/examples/memstrm.c +--- glibc-2.17-c758a686/manual/examples/memstrm.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/memstrm.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* open_memstream example. +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/mkfsock.c glibc-2.17-c758a686/manual/examples/mkfsock.c +--- glibc-2.17-c758a686/manual/examples/mkfsock.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/mkfsock.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* Example of Local-Namespace Sockets +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +@@ -45,13 +45,12 @@ + + /* The size of the address is + the offset of the start of the filename, +- plus its length, +- plus one for the terminating null byte. ++ plus its length (not including the terminating null byte). + Alternatively you can just do: + size = SUN_LEN (&name); + */ + size = (offsetof (struct sockaddr_un, sun_path) +- + strlen (name.sun_path) + 1); ++ + strlen (name.sun_path)); + + if (bind (sock, (struct sockaddr *) &name, size) < 0) + { +diff -urN glibc-2.17-c758a686/manual/examples/mkisock.c glibc-2.17-c758a686/manual/examples/mkisock.c +--- glibc-2.17-c758a686/manual/examples/mkisock.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/mkisock.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* Internet Socket Example +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/mygetpass.c glibc-2.17-c758a686/manual/examples/mygetpass.c +--- glibc-2.17-c758a686/manual/examples/mygetpass.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/mygetpass.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* Reading Passwords +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/pipe.c glibc-2.17-c758a686/manual/examples/pipe.c +--- glibc-2.17-c758a686/manual/examples/pipe.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/pipe.c 2014-09-12 16:10:06.047792712 -0400 +@@ -1,5 +1,5 @@ + /* Creating a Pipe +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/popen.c glibc-2.17-c758a686/manual/examples/popen.c +--- glibc-2.17-c758a686/manual/examples/popen.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/popen.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* Pipe to a Subprocess +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/rprintf.c glibc-2.17-c758a686/manual/examples/rprintf.c +--- glibc-2.17-c758a686/manual/examples/rprintf.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/rprintf.c 2014-09-12 16:10:06.047792712 -0400 +@@ -1,5 +1,5 @@ + /* Printf Extension Example +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/search.c glibc-2.17-c758a686/manual/examples/search.c +--- glibc-2.17-c758a686/manual/examples/search.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/search.c 2014-09-12 16:10:06.047792712 -0400 +@@ -1,5 +1,5 @@ + /* Searching and Sorting Example +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/select.c glibc-2.17-c758a686/manual/examples/select.c +--- glibc-2.17-c758a686/manual/examples/select.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/select.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* Waiting for Input or Output +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/setjmp.c glibc-2.17-c758a686/manual/examples/setjmp.c +--- glibc-2.17-c758a686/manual/examples/setjmp.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/setjmp.c 2014-09-12 16:10:06.047792712 -0400 +@@ -1,5 +1,5 @@ + /* Introduction to Non-Local Exits +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/sigh1.c glibc-2.17-c758a686/manual/examples/sigh1.c +--- glibc-2.17-c758a686/manual/examples/sigh1.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/sigh1.c 2014-09-12 16:10:06.047792712 -0400 +@@ -1,5 +1,5 @@ + /* Signal Handlers that Return +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/sigusr.c glibc-2.17-c758a686/manual/examples/sigusr.c +--- glibc-2.17-c758a686/manual/examples/sigusr.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/sigusr.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* Using kill for Communication +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/stpcpy.c glibc-2.17-c758a686/manual/examples/stpcpy.c +--- glibc-2.17-c758a686/manual/examples/stpcpy.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/stpcpy.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* stpcpy example. +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/strdupa.c glibc-2.17-c758a686/manual/examples/strdupa.c +--- glibc-2.17-c758a686/manual/examples/strdupa.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/strdupa.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* strdupa example. +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/strftim.c glibc-2.17-c758a686/manual/examples/strftim.c +--- glibc-2.17-c758a686/manual/examples/strftim.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/strftim.c 2014-09-12 16:10:06.047792712 -0400 +@@ -1,5 +1,5 @@ + /* Time Functions Example +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/strncat.c glibc-2.17-c758a686/manual/examples/strncat.c +--- glibc-2.17-c758a686/manual/examples/strncat.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/strncat.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* strncat example. +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/subopt.c glibc-2.17-c758a686/manual/examples/subopt.c +--- glibc-2.17-c758a686/manual/examples/subopt.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/subopt.c 2014-09-12 16:10:06.047792712 -0400 +@@ -1,5 +1,5 @@ + /* Parsing of Suboptions Example +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/swapcontext.c glibc-2.17-c758a686/manual/examples/swapcontext.c +--- glibc-2.17-c758a686/manual/examples/swapcontext.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/swapcontext.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* Complete Context Control +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/termios.c glibc-2.17-c758a686/manual/examples/termios.c +--- glibc-2.17-c758a686/manual/examples/termios.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/termios.c 2014-09-12 16:10:06.046792714 -0400 +@@ -1,5 +1,5 @@ + /* Noncanonical Mode Example +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/testopt.c glibc-2.17-c758a686/manual/examples/testopt.c +--- glibc-2.17-c758a686/manual/examples/testopt.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/testopt.c 2014-09-12 16:10:06.047792712 -0400 +@@ -1,5 +1,5 @@ + /* Example of Parsing Arguments with getopt. +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/testpass.c glibc-2.17-c758a686/manual/examples/testpass.c +--- glibc-2.17-c758a686/manual/examples/testpass.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/testpass.c 2014-09-12 16:10:06.047792712 -0400 +@@ -1,5 +1,5 @@ + /* Verify a password. +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/examples/timeval_subtract.c glibc-2.17-c758a686/manual/examples/timeval_subtract.c +--- glibc-2.17-c758a686/manual/examples/timeval_subtract.c 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/examples/timeval_subtract.c 2014-09-12 16:10:06.047792712 -0400 +@@ -1,5 +1,5 @@ + /* struct timeval subtraction. +- Copyright (C) 1991-2012 Free Software Foundation, Inc. ++ Copyright (C) 1991-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License +diff -urN glibc-2.17-c758a686/manual/filesys.texi glibc-2.17-c758a686/manual/filesys.texi +--- glibc-2.17-c758a686/manual/filesys.texi 2014-09-12 16:08:17.966070381 -0400 ++++ glibc-2.17-c758a686/manual/filesys.texi 2014-09-12 16:10:06.044792719 -0400 +@@ -58,6 +58,25 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun {char *} getcwd (char *@var{buffer}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{} @acsfd{}}} ++@c If buffer is NULL, this function calls malloc and realloc, and, in ++@c case of error, free. Linux offers a getcwd syscall that we use on ++@c GNU/Linux systems, but it may fail if the pathname is too long. As a ++@c fallback, and on other systems, the generic implementation opens each ++@c parent directory with opendir, which allocates memory for the ++@c directory stream with malloc. If a fstatat64 syscall is not ++@c available, very deep directory trees may also have to malloc to build ++@c longer sequences of ../../../... than those supported by a global ++@c const read-only string. ++ ++@c linux/__getcwd ++@c posix/__getcwd ++@c malloc/realloc/free if buffer is NULL, or if dir is too deep ++@c lstat64 -> see its own entry ++@c fstatat64 ++@c direct syscall if possible, alloca+snprintf+*stat64 otherwise ++@c openat64_not_cancel_3, close_not_cancel_no_status ++@c __fdopendir, __opendir, __readdir, rewinddir + The @code{getcwd} function returns an absolute file name representing + the current working directory, storing it in the character array + @var{buffer} that you provide. The @var{size} argument is how you tell +@@ -116,6 +135,9 @@ + @comment unistd.h + @comment BSD + @deftypefn {Deprecated Function} {char *} getwd (char *@var{buffer}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @ascuintl{}}@acunsafe{@acsmem{} @acsfd{}}} ++@c Besides the getcwd safety issues, it calls strerror_r on error, which ++@c brings in all of the i18n issues. + This is similar to @code{getcwd}, but has no way to specify the size of + the buffer. @Theglibc{} provides @code{getwd} only + for backwards compatibility with BSD. +@@ -130,6 +152,9 @@ + @comment unistd.h + @comment GNU + @deftypefun {char *} get_current_dir_name (void) ++@safety{@prelim{}@mtsafe{@mtsenv{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{} @acsfd{}}} ++@c Besides getcwd, which this function calls as a fallback, it calls ++@c getenv, with the potential thread-safety issues that brings about. + @vindex PWD + This @code{get_current_dir_name} function is basically equivalent to + @w{@code{getcwd (NULL, 0)}}. The only difference is that the value of +@@ -145,6 +170,7 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun int chdir (const char *@var{filename}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function is used to set the process's working directory to + @var{filename}. + +@@ -158,6 +184,7 @@ + @comment unistd.h + @comment XPG + @deftypefun int fchdir (int @var{filedes}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function is used to set the process's working directory to + directory associated with the file descriptor @var{filedes}. + +@@ -294,12 +321,14 @@ + @comment dirent.h + @comment BSD + @deftypefun int IFTODT (mode_t @var{mode}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This returns the @code{d_type} value corresponding to @var{mode}. + @end deftypefun + + @comment dirent.h + @comment BSD + @deftypefun mode_t DTTOIF (int @var{dtype}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This returns the @code{st_mode} value corresponding to @var{dtype}. + @end deftypefun + @end table +@@ -342,6 +371,9 @@ + @comment dirent.h + @comment POSIX.1 + @deftypefun {DIR *} opendir (const char *@var{dirname}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{} @acsfd{}}} ++@c Besides the safe syscall, we have to allocate the DIR object with ++@c __alloc_dir, that calls malloc. + The @code{opendir} function opens and returns a directory stream for + reading the directory whose file name is @var{dirname}. The stream has + type @code{DIR *}. +@@ -381,6 +413,8 @@ + @comment dirent.h + @comment GNU + @deftypefun {DIR *} fdopendir (int @var{fd}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{} @acsfd{}}} ++@c The DIR object is allocated with __alloc_dir, that calls malloc. + The @code{fdopendir} function works just like @code{opendir} but + instead of taking a file name and opening a file descriptor for the + directory the caller is required to provide a file descriptor. This +@@ -425,6 +459,7 @@ + @comment dirent.h + @comment GNU + @deftypefun int dirfd (DIR *@var{dirstream}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The function @code{dirfd} returns the file descriptor associated with + the directory stream @var{dirstream}. This descriptor can be used until + the directory is closed with @code{closedir}. If the directory stream +@@ -443,6 +478,12 @@ + @comment dirent.h + @comment POSIX.1 + @deftypefun {struct dirent *} readdir (DIR *@var{dirstream}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:dirstream}}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} ++@c This function holds dirstream's non-recursive lock, which brings ++@c about the usual issues with locks and async signals and cancellation, ++@c but the lock taking is not enough to make the returned value safe to ++@c use, since it points to a stream's internal buffer that can be ++@c overwritten by subsequent calls or even released by closedir. + This function reads the next entry from the directory. It normally + returns a pointer to a structure containing information about the + file. This structure is associated with the @var{dirstream} handle +@@ -478,6 +519,7 @@ + @comment dirent.h + @comment GNU + @deftypefun int readdir_r (DIR *@var{dirstream}, struct dirent *@var{entry}, struct dirent **@var{result}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} + This function is a version of @code{readdir} which performs internal + locking. Like @code{readdir} it returns the next entry from the + directory. To prevent conflicts between simultaneously running +@@ -549,6 +591,7 @@ + @comment dirent.h + @comment LFS + @deftypefun {struct dirent64 *} readdir64 (DIR *@var{dirstream}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:dirstream}}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} + The @code{readdir64} function is just like the @code{readdir} function + except that it returns a pointer to a record of type @code{struct + dirent64}. Some of the members of this data type (notably @code{d_ino}) +@@ -560,6 +603,7 @@ + @comment dirent.h + @comment LFS + @deftypefun int readdir64_r (DIR *@var{dirstream}, struct dirent64 *@var{entry}, struct dirent64 **@var{result}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} + The @code{readdir64_r} function is equivalent to the @code{readdir_r} + function except that it takes parameters of base type @code{struct + dirent64} instead of @code{struct dirent} in the second and third +@@ -570,6 +614,10 @@ + @comment dirent.h + @comment POSIX.1 + @deftypefun int closedir (DIR *@var{dirstream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @asulock{/hurd}}@acunsafe{@acsmem{} @acsfd{} @aculock{/hurd}}} ++@c No synchronization in the posix implementation, only in the hurd ++@c one. This is regarded as safe because it is undefined behavior if ++@c other threads could still be using the dir stream while it's closed. + This function closes the directory stream @var{dirstream}. It returns + @code{0} on success and @code{-1} on failure. + +@@ -609,6 +657,7 @@ + @comment dirent.h + @comment POSIX.1 + @deftypefun void rewinddir (DIR *@var{dirstream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} + The @code{rewinddir} function is used to reinitialize the directory + stream @var{dirstream}, so that if you call @code{readdir} it + returns information about the first entry in the directory again. This +@@ -622,6 +671,10 @@ + @comment dirent.h + @comment BSD + @deftypefun {long int} telldir (DIR *@var{dirstream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{/bsd} @asulock{/bsd}}@acunsafe{@acsmem{/bsd} @aculock{/bsd}}} ++@c The implementation is safe on most platforms, but on BSD it uses ++@c cookies, buckets and records, and the global array of pointers to ++@c dynamically allocated records is guarded by a non-recursive lock. + The @code{telldir} function returns the file position of the directory + stream @var{dirstream}. You can use this value with @code{seekdir} to + restore the directory stream to that position. +@@ -630,6 +683,10 @@ + @comment dirent.h + @comment BSD + @deftypefun void seekdir (DIR *@var{dirstream}, long int @var{pos}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{/bsd} @asulock{/bsd}}@acunsafe{@acsmem{/bsd} @aculock{/bsd}}} ++@c The implementation is safe on most platforms, but on BSD it uses ++@c cookies, buckets and records, and the global array of pointers to ++@c dynamically allocated records is guarded by a non-recursive lock. + The @code{seekdir} function sets the file position of the directory + stream @var{dirstream} to @var{pos}. The value @var{pos} must be the + result of a previous call to @code{telldir} on this particular stream; +@@ -648,7 +705,20 @@ + + @comment dirent.h + @comment BSD/SVID +-@deftypefun int scandir (const char *@var{dir}, struct dirent ***@var{namelist}, int (*@var{selector}) (const struct dirent *), int (*@var{cmp}) (const void *, const void *)) ++@deftypefun int scandir (const char *@var{dir}, struct dirent ***@var{namelist}, int (*@var{selector}) (const struct dirent *), int (*@var{cmp}) (const struct dirent **, const struct dirent **)) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{} @acsfd{}}} ++@c The scandir function calls __opendirat, __readdir, and __closedir to ++@c go over the named dir; malloc and realloc to allocate the namelist ++@c and copies of each selected dirent, besides the selector, if given, ++@c and qsort and the cmp functions if the latter is given. In spite of ++@c the cleanup handler that releases memory and the file descriptor in ++@c case of synchronous cancellation, an asynchronous cancellation may ++@c still leak memory and a file descriptor. Although readdir is unsafe ++@c in general, the use of an internal dir stream for sequential scanning ++@c of the directory with copying of dirents before subsequent calls ++@c makes the use safe, and the fact that the dir stream is private to ++@c each scandir call does away with the lock issues in readdir and ++@c closedir. + + The @code{scandir} function scans the contents of the directory selected + by @var{dir}. The result in *@var{namelist} is an array of pointers to +@@ -678,7 +748,9 @@ + + @comment dirent.h + @comment BSD/SVID +-@deftypefun int alphasort (const void *@var{a}, const void *@var{b}) ++@deftypefun int alphasort (const struct dirent **@var{a}, const struct dirent **@var{b}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} ++@c Calls strcoll. + The @code{alphasort} function behaves like the @code{strcoll} function + (@pxref{String/Array Comparison}). The difference is that the arguments + are not string pointers but instead they are of type +@@ -690,7 +762,10 @@ + + @comment dirent.h + @comment GNU +-@deftypefun int versionsort (const void *@var{a}, const void *@var{b}) ++@deftypefun int versionsort (const struct dirent **@var{a}, const struct dirent **@var{b}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} ++@c Calls strverscmp, which will accesses the locale object multiple ++@c times. + The @code{versionsort} function is like @code{alphasort} except that it + uses the @code{strverscmp} function internally. + @end deftypefun +@@ -702,7 +777,9 @@ + + @comment dirent.h + @comment GNU +-@deftypefun int scandir64 (const char *@var{dir}, struct dirent64 ***@var{namelist}, int (*@var{selector}) (const struct dirent64 *), int (*@var{cmp}) (const void *, const void *)) ++@deftypefun int scandir64 (const char *@var{dir}, struct dirent64 ***@var{namelist}, int (*@var{selector}) (const struct dirent64 *), int (*@var{cmp}) (const struct dirent64 **, const struct dirent64 **)) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{} @acsfd{}}} ++@c See scandir. + The @code{scandir64} function works like the @code{scandir} function + except that the directory entries it returns are described by elements + of type @w{@code{struct dirent64}}. The function pointed to by +@@ -720,7 +797,9 @@ + + @comment dirent.h + @comment GNU +-@deftypefun int alphasort64 (const void *@var{a}, const void *@var{b}) ++@deftypefun int alphasort64 (const struct dirent64 **@var{a}, const struct dirent **@var{b}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} ++@c See alphasort. + The @code{alphasort64} function behaves like the @code{strcoll} function + (@pxref{String/Array Comparison}). The difference is that the arguments + are not string pointers but instead they are of type +@@ -732,7 +811,9 @@ + + @comment dirent.h + @comment GNU +-@deftypefun int versionsort64 (const void *@var{a}, const void *@var{b}) ++@deftypefun int versionsort64 (const struct dirent64 **@var{a}, const struct dirent64 **@var{b}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} ++@c See versionsort. + The @code{versionsort64} function is like @code{alphasort64}, excepted that it + uses the @code{strverscmp} function internally. + @end deftypefun +@@ -812,7 +893,7 @@ + file does not exist. The situation for @code{nftw} is different. + + This value is only available if the program is compiled with +-@code{_BSD_SOURCE} or @code{_XOPEN_EXTENDED} defined before including ++@code{_XOPEN_EXTENDED} defined before including + the first header. The original SVID systems do not have symbolic links. + @end vtable + +@@ -913,6 +994,8 @@ + @comment ftw.h + @comment SVID + @deftypefun int ftw (const char *@var{filename}, __ftw_func_t @var{func}, int @var{descriptors}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{} @acsfd{}}} ++@c see nftw for safety details + The @code{ftw} function calls the callback function given in the + parameter @var{func} for every item which is found in the directory + specified by @var{filename} and all directories below. The function +@@ -963,6 +1046,7 @@ + @comment ftw.h + @comment Unix98 + @deftypefun int ftw64 (const char *@var{filename}, __ftw64_func_t @var{func}, int @var{descriptors}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{} @acsfd{}}} + This function is similar to @code{ftw} but it can work on filesystems + with large files. File information is reported using a variable of type + @code{struct stat64} which is passed by reference to the callback +@@ -976,6 +1060,17 @@ + @comment ftw.h + @comment XPG4.2 + @deftypefun int nftw (const char *@var{filename}, __nftw_func_t @var{func}, int @var{descriptors}, int @var{flag}) ++@safety{@prelim{}@mtsafe{@mtasscwd{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{} @acsfd{} @acscwd{}}} ++@c ftw_startup calls alloca, malloc, free, xstat/lxstat, tdestroy, and ftw_dir ++@c if FTW_CHDIR, call open, and fchdir, or chdir and getcwd ++@c ftw_dir calls open_dir_stream, readdir64, process_entry, closedir ++@c if FTW_CHDIR, also calls fchdir ++@c open_dir_stream calls malloc, realloc, readdir64, free, closedir, ++@c then openat64_not_cancel_3 and fdopendir or opendir, then dirfd. ++@c process_entry may cal realloc, fxstatat/lxstat/xstat, ftw_dir, and ++@c find_object (tsearch) and add_object (tfind). ++@c Since each invocation of *ftw uses its own private search tree, none ++@c of the search tree concurrency issues apply. + The @code{nftw} function works like the @code{ftw} functions. They call + the callback function @var{func} for all items found in the directory + @var{filename} and below. At most @var{descriptors} file descriptors +@@ -1036,6 +1131,7 @@ + @comment ftw.h + @comment Unix98 + @deftypefun int nftw64 (const char *@var{filename}, __nftw64_func_t @var{func}, int @var{descriptors}, int @var{flag}) ++@safety{@prelim{}@mtsafe{@mtasscwd{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{} @acsfd{} @acscwd{}}} + This function is similar to @code{nftw} but it can work on filesystems + with large files. File information is reported using a variable of type + @code{struct stat64} which is passed by reference to the callback +@@ -1079,6 +1175,7 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun int link (const char *@var{oldname}, const char *@var{newname}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{link} function makes a new link to the existing file named by + @var{oldname}, under the new name @var{newname}. + +@@ -1186,6 +1283,7 @@ + @comment unistd.h + @comment BSD + @deftypefun int symlink (const char *@var{oldname}, const char *@var{newname}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{symlink} function makes a symbolic link to @var{oldname} named + @var{newname}. + +@@ -1222,7 +1320,8 @@ + + @comment unistd.h + @comment BSD +-@deftypefun int readlink (const char *@var{filename}, char *@var{buffer}, size_t @var{size}) ++@deftypefun ssize_t readlink (const char *@var{filename}, char *@var{buffer}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{readlink} function gets the value of the symbolic link + @var{filename}. The file name that the link points to is copied into + @var{buffer}. This file name string is @emph{not} null-terminated; +@@ -1282,6 +1381,8 @@ + @comment stdlib.h + @comment GNU + @deftypefun {char *} canonicalize_file_name (const char *@var{name}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{} @acsfd{}}} ++@c Calls realpath. + + The @code{canonicalize_file_name} function returns the absolute name of + the file named by @var{name} which contains no @code{.}, @code{..} +@@ -1323,6 +1424,8 @@ + @comment stdlib.h + @comment XPG + @deftypefun {char *} realpath (const char *restrict @var{name}, char *restrict @var{resolved}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{} @acsfd{}}} ++@c Calls malloc, realloc, getcwd, lxstat64, readlink, alloca. + + A call to @code{realpath} where the @var{resolved} parameter is + @code{NULL} behaves exactly like @code{canonicalize_file_name}. The +@@ -1362,6 +1465,7 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun int unlink (const char *@var{filename}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{unlink} function deletes the file name @var{filename}. If + this is a file's sole name, the file itself is also deleted. (Actually, + if any process has the file open when this happens, deletion is +@@ -1404,6 +1508,7 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun int rmdir (const char *@var{filename}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + @cindex directories, deleting + @cindex deleting a directory + The @code{rmdir} function deletes a directory. The directory must be +@@ -1431,6 +1536,8 @@ + @comment stdio.h + @comment ISO + @deftypefun int remove (const char *@var{filename}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Calls unlink and rmdir. + This is the @w{ISO C} function to remove a file. It works like + @code{unlink} for files and like @code{rmdir} for directories. + @code{remove} is declared in @file{stdio.h}. +@@ -1446,6 +1553,10 @@ + @comment stdio.h + @comment ISO + @deftypefun int rename (const char *@var{oldname}, const char *@var{newname}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c In the absence of a rename syscall, there's an emulation with link ++@c and unlink, but it's racy, even more so if newname exists and is ++@c unlinked first. + The @code{rename} function renames the file @var{oldname} to + @var{newname}. The file formerly accessible under the name + @var{oldname} is afterwards accessible as @var{newname} instead. (If +@@ -1541,6 +1652,7 @@ + @comment sys/stat.h + @comment POSIX.1 + @deftypefun int mkdir (const char *@var{filename}, mode_t @var{mode}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{mkdir} function creates a new, empty directory with name + @var{filename}. + +@@ -1882,6 +1994,7 @@ + @comment sys/stat.h + @comment POSIX.1 + @deftypefun int stat (const char *@var{filename}, struct stat *@var{buf}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{stat} function returns information about the attributes of the + file named by @w{@var{filename}} in the structure pointed to by @var{buf}. + +@@ -1908,8 +2021,9 @@ + @comment sys/stat.h + @comment Unix98 + @deftypefun int stat64 (const char *@var{filename}, struct stat64 *@var{buf}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function is similar to @code{stat} but it is also able to work on +-files larger then @math{2^31} bytes on 32-bit systems. To be able to do ++files larger than @math{2^31} bytes on 32-bit systems. To be able to do + this the result is stored in a variable of type @code{struct stat64} to + which @var{buf} must point. + +@@ -1921,6 +2035,7 @@ + @comment sys/stat.h + @comment POSIX.1 + @deftypefun int fstat (int @var{filedes}, struct stat *@var{buf}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{fstat} function is like @code{stat}, except that it takes an + open file descriptor as an argument instead of a file name. + @xref{Low-Level I/O}. +@@ -1942,6 +2057,7 @@ + @comment sys/stat.h + @comment Unix98 + @deftypefun int fstat64 (int @var{filedes}, struct stat64 *@var{buf}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function is similar to @code{fstat} but is able to work on large + files on 32-bit platforms. For large files the file descriptor + @var{filedes} should be obtained by @code{open64} or @code{creat64}. +@@ -1953,9 +2069,16 @@ + replaces the interface for small files on 32-bit machines. + @end deftypefun + ++@c fstatat will call alloca and snprintf if the syscall is not ++@c available. ++@c @safety{@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} ++ + @comment sys/stat.h + @comment BSD + @deftypefun int lstat (const char *@var{filename}, struct stat *@var{buf}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct system call through lxstat, sometimes with an xstat conv call ++@c afterwards. + The @code{lstat} function is like @code{stat}, except that it does not + follow symbolic links. If @var{filename} is the name of a symbolic + link, @code{lstat} returns information about the link itself; otherwise +@@ -1969,8 +2092,11 @@ + @comment sys/stat.h + @comment Unix98 + @deftypefun int lstat64 (const char *@var{filename}, struct stat64 *@var{buf}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct system call through lxstat64, sometimes with an xstat conv ++@c call afterwards. + This function is similar to @code{lstat} but it is also able to work on +-files larger then @math{2^31} bytes on 32-bit systems. To be able to do ++files larger than @math{2^31} bytes on 32-bit systems. To be able to do + this the result is stored in a variable of type @code{struct stat64} to + which @var{buf} must point. + +@@ -2007,12 +2133,14 @@ + @comment sys/stat.h + @comment POSIX + @deftypefn Macro int S_ISDIR (mode_t @var{m}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This macro returns non-zero if the file is a directory. + @end deftypefn + + @comment sys/stat.h + @comment POSIX + @deftypefn Macro int S_ISCHR (mode_t @var{m}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This macro returns non-zero if the file is a character special file (a + device like a terminal). + @end deftypefn +@@ -2020,6 +2148,7 @@ + @comment sys/stat.h + @comment POSIX + @deftypefn Macro int S_ISBLK (mode_t @var{m}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This macro returns non-zero if the file is a block special file (a device + like a disk). + @end deftypefn +@@ -2027,12 +2156,14 @@ + @comment sys/stat.h + @comment POSIX + @deftypefn Macro int S_ISREG (mode_t @var{m}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This macro returns non-zero if the file is a regular file. + @end deftypefn + + @comment sys/stat.h + @comment POSIX + @deftypefn Macro int S_ISFIFO (mode_t @var{m}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This macro returns non-zero if the file is a FIFO special file, or a + pipe. @xref{Pipes and FIFOs}. + @end deftypefn +@@ -2040,6 +2171,7 @@ + @comment sys/stat.h + @comment GNU + @deftypefn Macro int S_ISLNK (mode_t @var{m}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This macro returns non-zero if the file is a symbolic link. + @xref{Symbolic Links}. + @end deftypefn +@@ -2047,6 +2179,7 @@ + @comment sys/stat.h + @comment GNU + @deftypefn Macro int S_ISSOCK (mode_t @var{m}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This macro returns non-zero if the file is a socket. @xref{Sockets}. + @end deftypefn + +@@ -2129,6 +2262,7 @@ + @comment sys/stat.h + @comment POSIX + @deftypefn Macro int S_TYPEISMQ (struct stat *@var{s}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + If the system implement POSIX message queues as distinct objects and the + file is a message queue object, this macro returns a non-zero value. + In all other cases the result is zero. +@@ -2137,6 +2271,7 @@ + @comment sys/stat.h + @comment POSIX + @deftypefn Macro int S_TYPEISSEM (struct stat *@var{s}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + If the system implement POSIX semaphores as distinct objects and the + file is a semaphore object, this macro returns a non-zero value. + In all other cases the result is zero. +@@ -2145,8 +2280,9 @@ + @comment sys/stat.h + @comment POSIX + @deftypefn Macro int S_TYPEISSHM (struct stat *@var{s}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + If the system implement POSIX shared memory objects as distinct objects +-and the file is an shared memory object, this macro returns a non-zero ++and the file is a shared memory object, this macro returns a non-zero + value. In all other cases the result is zero. + @end deftypefn + +@@ -2189,6 +2325,7 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun int chown (const char *@var{filename}, uid_t @var{owner}, gid_t @var{group}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{chown} function changes the owner of the file @var{filename} to + @var{owner}, and its group owner to @var{group}. + +@@ -2222,7 +2359,8 @@ + + @comment unistd.h + @comment BSD +-@deftypefun int fchown (int @var{filedes}, int @var{owner}, int @var{group}) ++@deftypefun int fchown (int @var{filedes}, uid_t @var{owner}, gid_t @var{group}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This is like @code{chown}, except that it changes the owner of the open + file with descriptor @var{filedes}. + +@@ -2502,6 +2641,7 @@ + @comment sys/stat.h + @comment POSIX.1 + @deftypefun mode_t umask (mode_t @var{mask}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{umask} function sets the file creation mask of the current + process to @var{mask}, and returns the previous value of the file + creation mask. +@@ -2527,6 +2667,7 @@ + @comment sys/stat.h + @comment GNU + @deftypefun mode_t getumask (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Return the current value of the file creation mask for the current + process. This function is a GNU extension and is only available on + @gnuhurdsystems{}. +@@ -2535,6 +2676,7 @@ + @comment sys/stat.h + @comment POSIX.1 + @deftypefun int chmod (const char *@var{filename}, mode_t @var{mode}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{chmod} function sets the access permission bits for the file + named by @var{filename} to @var{mode}. + +@@ -2574,7 +2716,8 @@ + + @comment sys/stat.h + @comment BSD +-@deftypefun int fchmod (int @var{filedes}, int @var{mode}) ++@deftypefun int fchmod (int @var{filedes}, mode_t @var{mode}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This is like @code{chmod}, except that it changes the permissions of the + currently open file given by @var{filedes}. + +@@ -2645,6 +2788,7 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun int access (const char *@var{filename}, int @var{how}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{access} function checks to see whether the file named by + @var{filename} can be accessed in the way specified by the @var{how} + argument. The @var{how} argument either can be the bitwise OR of the +@@ -2746,7 +2890,7 @@ + need to include the header file @file{utime.h} to use this facility. + @pindex utime.h + +-@comment time.h ++@comment utime.h + @comment POSIX.1 + @deftp {Data Type} {struct utimbuf} + The @code{utimbuf} structure is used with the @code{utime} function to +@@ -2762,9 +2906,12 @@ + @end table + @end deftp + +-@comment time.h ++@comment utime.h + @comment POSIX.1 + @deftypefun int utime (const char *@var{filename}, const struct utimbuf *@var{times}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c In the absence of a utime syscall, it non-atomically converts times ++@c to a struct timeval and calls utimes. + This function is used to modify the file times associated with the file + named @var{filename}. + +@@ -2815,7 +2962,11 @@ + + @comment sys/time.h + @comment BSD +-@deftypefun int utimes (const char *@var{filename}, struct timeval @var{tvp}@t{[2]}) ++@deftypefun int utimes (const char *@var{filename}, const struct timeval @var{tvp}@t{[2]}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c In the absence of a utimes syscall, it non-atomically converts tvp ++@c to struct timespec array and issues a utimensat syscall, or to ++@c struct utimbuf and calls utime. + This function sets the file access and modification times of the file + @var{filename}. The new file access time is specified by + @code{@var{tvp}[0]}, and the new modification time by +@@ -2829,7 +2980,10 @@ + + @comment sys/time.h + @comment BSD +-@deftypefun int lutimes (const char *@var{filename}, struct timeval @var{tvp}@t{[2]}) ++@deftypefun int lutimes (const char *@var{filename}, const struct timeval @var{tvp}@t{[2]}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Since there's no lutimes syscall, it non-atomically converts tvp ++@c to struct timespec array and issues a utimensat syscall. + This function is like @code{utimes}, except that it does not follow + symbolic links. If @var{filename} is the name of a symbolic link, + @code{lutimes} sets the file access and modification times of the +@@ -2845,7 +2999,11 @@ + + @comment sys/time.h + @comment BSD +-@deftypefun int futimes (int @var{fd}, struct timeval @var{tvp}@t{[2]}) ++@deftypefun int futimes (int @var{fd}, const struct timeval @var{tvp}@t{[2]}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Since there's no futimes syscall, it non-atomically converts tvp ++@c to struct timespec array and issues a utimensat syscall, falling back ++@c to utimes on a /proc/self/fd symlink. + This function is like @code{utimes}, except that it takes an open file + descriptor as an argument instead of a file name. @xref{Low-Level + I/O}. This function comes from FreeBSD, and is not available on all +@@ -2900,6 +3058,8 @@ + @comment unistd.h + @comment X/Open + @deftypefun int truncate (const char *@var{filename}, off_t @var{length}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c In the absence of a truncate syscall, we use open and ftruncate. + + The @code{truncate} function changes the size of @var{filename} to + @var{length}. If @var{length} is shorter than the previous length, data +@@ -2944,6 +3104,8 @@ + @comment unistd.h + @comment Unix98 + @deftypefun int truncate64 (const char *@var{name}, off64_t @var{length}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c In the absence of a syscall, try truncate if length fits. + This function is similar to the @code{truncate} function. The + difference is that the @var{length} argument is 64 bits wide even on 32 + bits machines, which allows the handling of files with sizes up to +@@ -2957,6 +3119,7 @@ + @comment unistd.h + @comment POSIX + @deftypefun int ftruncate (int @var{fd}, off_t @var{length}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + + This is like @code{truncate}, but it works on a file descriptor @var{fd} + for an opened file instead of a file name to identify the object. The +@@ -3021,6 +3184,8 @@ + @comment unistd.h + @comment Unix98 + @deftypefun int ftruncate64 (int @var{id}, off64_t @var{length}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c In the absence of a syscall, try ftruncate if length fits. + This function is similar to the @code{ftruncate} function. The + difference is that the @var{length} argument is 64 bits wide even on 32 + bits machines which allows the handling of files with sizes up to +@@ -3082,7 +3247,11 @@ + + @comment sys/stat.h + @comment BSD +-@deftypefun int mknod (const char *@var{filename}, int @var{mode}, int @var{dev}) ++@deftypefun int mknod (const char *@var{filename}, mode_t @var{mode}, dev_t @var{dev}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Instead of issuing the syscall directly, we go through xmknod. ++@c Although the internal xmknod takes a dev_t*, that could lead to ++@c @mtsrace races, it's passed a pointer to mknod's dev. + The @code{mknod} function makes a special file with name @var{filename}. + The @var{mode} specifies the mode of the file, and may include the various + special file bits, such as @code{S_IFCHR} (for a character special file) +@@ -3134,6 +3303,20 @@ + @comment stdio.h + @comment ISO + @deftypefun {FILE *} tmpfile (void) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@acsmem{} @acsfd{} @aculock{}}} ++@c The unsafety issues are those of fdopen, plus @acsfd because of the ++@c open. ++@c __path_search (internal buf, !dir, const pfx, !try_tmpdir) ok ++@c libc_secure_genenv only if try_tmpdir ++@c xstat64, strlen, strcmp, sprintf ++@c __gen_tempname (internal tmpl, __GT_FILE) ok ++@c strlen, memcmp, getpid, open/mkdir/lxstat64 ok ++@c HP_TIMING_NOW if available ok ++@c gettimeofday (!tz) first time, or every time if no HP_TIMING_NOW ok ++@c static value is used and modified without synchronization ok ++@c but the use is as a source of non-cryptographic randomness ++@c with retries in case of collision, so it should be safe ++@c unlink, fdopen + This function creates a temporary binary file for update mode, as if by + calling @code{fopen} with mode @code{"wb+"}. The file is deleted + automatically when it is closed or when the program terminates. (On +@@ -3150,9 +3333,10 @@ + @comment stdio.h + @comment Unix98 + @deftypefun {FILE *} tmpfile64 (void) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@acsmem{} @acsfd{} @aculock{}}} + This function is similar to @code{tmpfile}, but the stream it returns a + pointer to was opened using @code{tmpfile64}. Therefore this stream can +-be used for files larger then @math{2^31} bytes on 32-bit machines. ++be used for files larger than @math{2^31} bytes on 32-bit machines. + + Please note that the return type is still @code{FILE *}. There is no + special @code{FILE} type for the LFS interface. +@@ -3165,6 +3349,11 @@ + @comment stdio.h + @comment ISO + @deftypefun {char *} tmpnam (char *@var{result}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:tmpnam/!result}}@asunsafe{}@acsafe{}} ++@c The passed-in buffer should not be modified concurrently with the ++@c call. ++@c __path_search (static or passed-in buf, !dir, !pfx, !try_tmpdir) ok ++@c __gen_tempname (internal tmpl, __GT_NOCREATE) ok + This function constructs and returns a valid file name that does not + refer to any existing file. If the @var{result} argument is a null + pointer, the return value is a pointer to an internal static string, +@@ -3189,6 +3378,7 @@ + @comment stdio.h + @comment GNU + @deftypefun {char *} tmpnam_r (char *@var{result}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function is nearly identical to the @code{tmpnam} function, except + that if @var{result} is a null pointer it returns a null pointer. + +@@ -3225,6 +3415,13 @@ + @comment stdio.h + @comment SVID + @deftypefun {char *} tempnam (const char *@var{dir}, const char *@var{prefix}) ++@safety{@prelim{}@mtsafe{@mtsenv{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} ++@c There's no way (short of being setuid) to avoid getenv("TMPDIR"), ++@c even with a non-NULL dir. ++@c ++@c __path_search (internal buf, dir, pfx, try_tmpdir) unsafe getenv ++@c __gen_tempname (internal tmpl, __GT_NOCREATE) ok ++@c strdup + This function generates a unique temporary file name. If @var{prefix} + is not a null pointer, up to five characters of this string are used as + a prefix for the file name. The return value is a string newly +@@ -3288,6 +3485,8 @@ + @comment stdlib.h + @comment Unix + @deftypefun {char *} mktemp (char *@var{template}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c __gen_tempname (caller tmpl, __GT_NOCREATE) ok + The @code{mktemp} function generates a unique file name by modifying + @var{template} as described above. If successful, it returns + @var{template} as modified. If @code{mktemp} cannot find a unique file +@@ -3306,6 +3505,8 @@ + @comment stdlib.h + @comment BSD + @deftypefun int mkstemp (char *@var{template}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{@acsfd{}}} ++@c __gen_tempname (caller tmpl, __GT_FILE) ok + The @code{mkstemp} function generates a unique file name just as + @code{mktemp} does, but it also opens the file for you with @code{open} + (@pxref{Opening and Closing Files}). If successful, it modifies +@@ -3328,6 +3529,8 @@ + @comment stdlib.h + @comment BSD + @deftypefun {char *} mkdtemp (char *@var{template}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c __gen_tempname (caller tmpl, __GT_DIR) ok + The @code{mkdtemp} function creates a directory with a unique name. If + it succeeds, it overwrites @var{template} with the name of the + directory, and returns @var{template}. As with @code{mktemp} and +@@ -3349,3 +3552,23 @@ + @xref{Creating Directories}. + + The @code{mkdtemp} function comes from OpenBSD. ++ ++@c FIXME these are undocumented: ++@c faccessat ++@c fchmodat ++@c fchownat ++@c futimesat ++@c fstatat (there's a commented-out safety assessment for this one) ++@c linkat ++@c mkdirat ++@c mkfifoat ++@c name_to_handle_at ++@c openat ++@c open_by_handle_at ++@c readlinkat ++@c renameat ++@c scandirat ++@c symlinkat ++@c unlinkat ++@c utimensat ++@c mknodat +diff -urN glibc-2.17-c758a686/manual/freemanuals.texi glibc-2.17-c758a686/manual/freemanuals.texi +--- glibc-2.17-c758a686/manual/freemanuals.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/freemanuals.texi 2014-09-12 16:10:06.044792719 -0400 +@@ -1,4 +1,7 @@ +-@appendix Free Software Needs Free Documentation ++@c freemanuals.texi - blurb for free documentation. ++@c This file is intended to be included within another document, ++@c hence no sectioning command or @node. ++ + @cindex free documentation + + The biggest deficiency in the free software community today is not in +diff -urN glibc-2.17-c758a686/manual/getopt.texi glibc-2.17-c758a686/manual/getopt.texi +--- glibc-2.17-c758a686/manual/getopt.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/getopt.texi 2014-09-12 16:10:06.044792719 -0400 +@@ -59,7 +59,29 @@ + + @comment unistd.h + @comment POSIX.2 +-@deftypefun int getopt (int @var{argc}, char **@var{argv}, const char *@var{options}) ++@deftypefun int getopt (int @var{argc}, char *const *@var{argv}, const char *@var{options}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:getopt} @mtsenv{}}@asunsafe{@ascuheap{} @ascuintl{} @asulock{} @asucorrupt{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}} ++@c Swapping elements of passed-in argv may be partial in case of ++@c cancellation. Gettext brings about a whole lot of AS and AC safety ++@c issues. The getopt API involves returning values in the ++@c non-thread-specific optarg variable, which adds another thread-safety ++@c issue. Given print_errors, it may output errors to stderr, which may ++@c self-deadlock, leak locks, or encounter (in a signal handler) or ++@c leave (in case of cancellation) stderr in an inconsistent state. ++@c Various implicit, indirect uses of malloc, in uses of memstream and ++@c asprintf for error-printing, bring about the usual malloc issues. ++@c (The explicit use of malloc in a conditional situation in ++@c _getopt_initialize is never exercised in glibc.) ++@c ++@c _getopt_internal ++@c _getopt_internal_r ++@c gettext ++@c _getopt_initialize ++@c getenv ++@c malloc if USE_NONOPTION_FLAGS, never defined in libc ++@c open_memstream ++@c lockfile, unlockfile, __fxprintf -> stderr ++@c asprintf + The @code{getopt} function gets the next option argument from the + argument list specified by the @var{argv} and @var{argc} arguments. + Normally these values come directly from the arguments received by +@@ -225,6 +247,8 @@ + @comment getopt.h + @comment GNU + @deftypefun int getopt_long (int @var{argc}, char *const *@var{argv}, const char *@var{shortopts}, const struct option *@var{longopts}, int *@var{indexptr}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:getopt} @mtsenv{}}@asunsafe{@ascuheap{} @ascuintl{} @asulock{} @asucorrupt{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}} ++@c Same issues as getopt. + Decode options from the vector @var{argv} (whose length is @var{argc}). + The argument @var{shortopts} describes the short options to accept, just as + it does in @code{getopt}. The argument @var{longopts} describes the long +@@ -278,6 +302,8 @@ + @comment getopt.h + @comment GNU + @deftypefun int getopt_long_only (int @var{argc}, char *const *@var{argv}, const char *@var{shortopts}, const struct option *@var{longopts}, int *@var{indexptr}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:getopt} @mtsenv{}}@asunsafe{@ascuheap{} @ascuintl{} @asulock{} @asucorrupt{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}} ++@c Same issues as getopt. + + The @code{getopt_long_only} function is equivalent to the + @code{getopt_long} function but it allows to specify the user of the +diff -urN glibc-2.17-c758a686/manual/install-plain.texi glibc-2.17-c758a686/manual/install-plain.texi +--- glibc-2.17-c758a686/manual/install-plain.texi 1969-12-31 19:00:00.000000000 -0500 ++++ glibc-2.17-c758a686/manual/install-plain.texi 2014-09-12 16:10:06.046792714 -0400 +@@ -0,0 +1,5 @@ ++@c This is for making the `INSTALL' file for the distribution. ++@c Makeinfo ignores it when processing the file from the include. ++@setfilename INSTALL ++@set plain ++@include install.texi +diff -urN glibc-2.17-c758a686/manual/install.texi glibc-2.17-c758a686/manual/install.texi +--- glibc-2.17-c758a686/manual/install.texi 2014-09-12 16:08:17.783070851 -0400 ++++ glibc-2.17-c758a686/manual/install.texi 2014-09-12 16:10:06.043792722 -0400 +@@ -1,10 +1,10 @@ +-@c This is for making the `INSTALL' file for the distribution. +-@c Makeinfo ignores it when processing the file from the include. +-@setfilename INSTALL + @include macros.texi + @include pkgvers.texi + ++@ifclear plain + @node Installation, Maintenance, Library Summary, Top ++@end ifclear ++ + @c %MENU% How to install the GNU C Library + @appendix Installing @theglibc{} + +@@ -21,6 +21,7 @@ + You will need recent versions of several GNU tools: definitely GCC and + GNU Make, and possibly others. @xref{Tools for Compilation}, below. + ++@ifclear plain + @menu + * Configuring and compiling:: How to compile and test GNU libc. + * Running make install:: How to install it once you've got it +@@ -29,6 +30,7 @@ + * Linux:: Specific advice for GNU/Linux systems. + * Reporting Bugs:: So they'll get fixed. + @end menu ++@end ifclear + + @node Configuring and compiling + @appendixsec Configuring and compiling @theglibc{} +@@ -138,11 +140,6 @@ + Don't build libraries with profiling information. You may want to use + this option if you don't plan to do profiling. + +-@item --disable-versioning +-Don't compile the shared libraries with symbol version information. +-Doing this will make the resulting library incompatible with old +-binaries, so it's not recommended. +- + @item --enable-static-nss + Compile static versions of the NSS (Name Service Switch) libraries. + This is not recommended because it defeats the purpose of NSS; a program +@@ -155,6 +152,14 @@ + prevented though there generally is no reason since it creates + compatibility problems. + ++@item --enable-hardcoded-path-in-tests ++By default, dynamic tests are linked to run with the installed C library. ++This option hardcodes the newly built C library path in dynamic tests ++so that they can be invoked directly. ++ ++@item --enable-lock-elision=yes ++Enable lock elision for pthread mutexes by default. ++ + @pindex pt_chown + @findex grantpt + @item --enable-pt_chown +@@ -180,11 +185,11 @@ + + If you only specify @samp{--host}, @code{configure} will prepare for a + native compile but use what you specify instead of guessing what your +-system is. This is most useful to change the CPU submodel. For example, +-if @code{configure} guesses your machine as @code{i586-pc-linux-gnu} but +-you want to compile a library for 386es, give +-@samp{--host=i386-pc-linux-gnu} or just @samp{--host=i386-linux} and add +-the appropriate compiler flags (@samp{-mcpu=i386} will do the trick) to ++system is. This is most useful to change the CPU submodel. For example, ++if @code{configure} guesses your machine as @code{i686-pc-linux-gnu} but ++you want to compile a library for 586es, give ++@samp{--host=i586-pc-linux-gnu} or just @samp{--host=i586-linux} and add ++the appropriate compiler flags (@samp{-mcpu=i586} will do the trick) to + @var{CFLAGS}. + + If you specify just @samp{--build}, @code{configure} will get confused. +@@ -230,6 +235,12 @@ + system such as @file{/etc/passwd}, @file{/etc/nsswitch.conf} and others. + These files must all contain correct and sensible content. + ++Normally, @code{make check} will run all the tests before reporting ++all problems found and exiting with error status if any problems ++occurred. You can specify @samp{stop-on-test-failure=y} when running ++@code{make check} to make the test run stop and exit with an error ++status immediately when a failure occurs. ++ + To format the @cite{GNU C Library Reference Manual} for printing, type + @w{@code{make dvi}}. You need a working @TeX{} installation to do + this. The distribution builds the on-line formatted version of the +@@ -264,13 +275,15 @@ + In general, when testing @theglibc{}, @samp{test-wrapper} may be set + to the name and arguments of any program to run newly built binaries. + This program must preserve the arguments to the binary being run, its +-working directory, all environment variables set as part of testing +-and the standard input, output and error file descriptors. If ++working directory and the standard input, output and error file ++descriptors. If + @samp{@var{test-wrapper} env} will not work to run a program with + environment variables set, then @samp{test-wrapper-env} must be set to + a program that runs a newly built program with environment variable + assignments in effect, those assignments being specified as +-@samp{@var{var}=@var{value}} before the name of the program to be run. ++@samp{@var{var}=@var{value}} before the name of the program to be ++run. If multiple assignments to the same variable are specified, ++the last assignment specified must take precedence. + + + @node Running make install +@@ -278,7 +291,7 @@ + @cindex installing + + To install the library and its header files, and the Info files of the +-manual, type @code{env LANGUAGE=C LC_ALL=C make install}. This will ++manual, type @code{make install}. This will + build things, if necessary, before installing them; however, you should + still compile everything first. If you are installing @theglibc{} as your + primary C library, we recommend that you shut the system down to +@@ -317,14 +330,11 @@ + well. + + One auxiliary program, @file{/usr/libexec/pt_chown}, is installed setuid +-@code{root}. This program is invoked by the @code{grantpt} function; it +-sets the permissions on a pseudoterminal so it can be used by the +-calling process. This means programs like @code{xterm} and +-@code{screen} do not have to be setuid to get a pty. (There may be +-other reasons why they need privileges.) If you are using a +-Linux kernel with the @code{devptsfs} or @code{devfs} filesystems +-providing pty slaves, you don't need this program; otherwise you do. +-The source for @file{pt_chown} is in @file{login/programs/pt_chown.c}. ++@code{root} if the @samp{--enable-pt_chown} configuration option is used. ++This program is invoked by the @code{grantpt} function; it sets the ++permissions on a pseudoterminal so it can be used by the calling process. ++If you are using a Linux kernel with the @code{devpts} filesystem enabled ++and mounted at @file{/dev/pts}, you don't need this program. + + After installation you might want to configure the timezone and locale + installation of your system. @Theglibc{} comes with a locale +@@ -362,9 +372,9 @@ + bugs or lack features. + + @item +-GCC 4.3 or newer, GCC 4.6 recommended ++GCC 4.4 or newer, GCC 4.6 recommended + +-GCC 4.3 or higher is required; as of this writing, GCC 4.6 is the ++GCC 4.4 or higher is required; as of this writing, GCC 4.6 is the + compiler we advise to use to build @theglibc{}. + + You can use whatever compiler you like to compile programs that use +@@ -388,10 +398,11 @@ + mechanism for the info files is not present or works differently. + + @item +-GNU @code{awk} 3.0, or higher ++GNU @code{awk} 3.1.2, or higher + +-@code{Awk} is used in several places to generate files. +-@code{gawk} 3.0 is known to work. ++@code{awk} is used in several places to generate files. ++Some @code{gawk} extensions are used, including the @code{asorti} ++function, which was introduced in version 3.1.2 of @code{gawk}. + + @item + Perl 5 +@@ -412,7 +423,7 @@ + @end itemize + + @noindent +-If you change any of the @file{configure.in} files you will also need ++If you change any of the @file{configure.ac} files you will also need + + @itemize @bullet + @item +@@ -436,7 +447,7 @@ + @cindex kernel header files + + If you are installing @theglibc{} on @gnulinuxsystems{}, you need to have +-the header files from a 2.6.19.1 or newer kernel around for reference. ++the header files from a 2.6.32 or newer kernel around for reference. + These headers must be installed using @samp{make headers_install}; the + headers present in the kernel source directory are not suitable for + direct use by @theglibc{}. You do not need to use that kernel, just have +diff -urN glibc-2.17-c758a686/manual/intro.texi glibc-2.17-c758a686/manual/intro.texi +--- glibc-2.17-c758a686/manual/intro.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/intro.texi 2014-09-12 16:10:06.044792719 -0400 +@@ -159,6 +159,14 @@ + These include utilities for dealing with regular expressions and other + pattern matching facilities (@pxref{Pattern Matching}). + ++@menu ++* POSIX Safety Concepts:: Safety concepts from POSIX. ++* Unsafe Features:: Features that make functions unsafe. ++* Conditionally Safe Features:: Features that make functions unsafe ++ in the absence of workarounds. ++* Other Safety Remarks:: Additional safety features and remarks. ++@end menu ++ + @comment Roland sez: + @comment The GNU C library as it stands conforms to 1003.2 draft 11, which + @comment specifies: +@@ -172,6 +180,725 @@ + @comment (not yet implemented) + @comment confstr + ++@node POSIX Safety Concepts, Unsafe Features, , POSIX ++@subsubsection POSIX Safety Concepts ++@cindex POSIX Safety Concepts ++ ++This manual documents various safety properties of @glibcadj{} ++functions, in lines that follow their prototypes and look like: ++ ++@sampsafety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++ ++The properties are assessed according to the criteria set forth in the ++POSIX standard for such safety contexts as Thread-, Async-Signal- and ++Async-Cancel- -Safety. Intuitive definitions of these properties, ++attempting to capture the meaning of the standard definitions, follow. ++ ++@itemize @bullet ++ ++@item ++@cindex MT-Safe ++@cindex Thread-Safe ++@code{MT-Safe} or Thread-Safe functions are safe to call in the presence ++of other threads. MT, in MT-Safe, stands for Multi Thread. ++ ++Being MT-Safe does not imply a function is atomic, nor that it uses any ++of the memory synchronization mechanisms POSIX exposes to users. It is ++even possible that calling MT-Safe functions in sequence does not yield ++an MT-Safe combination. For example, having a thread call two MT-Safe ++functions one right after the other does not guarantee behavior ++equivalent to atomic execution of a combination of both functions, since ++concurrent calls in other threads may interfere in a destructive way. ++ ++Whole-program optimizations that could inline functions across library ++interfaces may expose unsafe reordering, and so performing inlining ++across the @glibcadj{} interface is not recommended. The documented ++MT-Safety status is not guaranteed under whole-program optimization. ++However, functions defined in user-visible headers are designed to be ++safe for inlining. ++ ++ ++@item ++@cindex AS-Safe ++@cindex Async-Signal-Safe ++@code{AS-Safe} or Async-Signal-Safe functions are safe to call from ++asynchronous signal handlers. AS, in AS-Safe, stands for Asynchronous ++Signal. ++ ++Many functions that are AS-Safe may set @code{errno}, or modify the ++floating-point environment, because their doing so does not make them ++unsuitable for use in signal handlers. However, programs could ++misbehave should asynchronous signal handlers modify this thread-local ++state, and the signal handling machinery cannot be counted on to ++preserve it. Therefore, signal handlers that call functions that may ++set @code{errno} or modify the floating-point environment @emph{must} ++save their original values, and restore them before returning. ++ ++ ++@item ++@cindex AC-Safe ++@cindex Async-Cancel-Safe ++@code{AC-Safe} or Async-Cancel-Safe functions are safe to call when ++asynchronous cancellation is enabled. AC in AC-Safe stands for ++Asynchronous Cancellation. ++ ++The POSIX standard defines only three functions to be AC-Safe, namely ++@code{pthread_cancel}, @code{pthread_setcancelstate}, and ++@code{pthread_setcanceltype}. At present @theglibc{} provides no ++guarantees beyond these three functions, but does document which ++functions are presently AC-Safe. This documentation is provided for use ++by @theglibc{} developers. ++ ++Just like signal handlers, cancellation cleanup routines must configure ++the floating point environment they require. The routines cannot assume ++a floating point environment, particularly when asynchronous ++cancellation is enabled. If the configuration of the floating point ++environment cannot be performed atomically then it is also possible that ++the environment encountered is internally inconsistent. ++ ++ ++@item ++@cindex MT-Unsafe ++@cindex Thread-Unsafe ++@cindex AS-Unsafe ++@cindex Async-Signal-Unsafe ++@cindex AC-Unsafe ++@cindex Async-Cancel-Unsafe ++@code{MT-Unsafe}, @code{AS-Unsafe}, @code{AC-Unsafe} functions are not ++safe to call within the safety contexts described above. Calling them ++within such contexts invokes undefined behavior. ++ ++Functions not explicitly documented as safe in a safety context should ++be regarded as Unsafe. ++ ++ ++@item ++@cindex Preliminary ++@code{Preliminary} safety properties are documented, indicating these ++properties may @emph{not} be counted on in future releases of ++@theglibc{}. ++ ++Such preliminary properties are the result of an assessment of the ++properties of our current implementation, rather than of what is ++mandated and permitted by current and future standards. ++ ++Although we strive to abide by the standards, in some cases our ++implementation is safe even when the standard does not demand safety, ++and in other cases our implementation does not meet the standard safety ++requirements. The latter are most likely bugs; the former, when marked ++as @code{Preliminary}, should not be counted on: future standards may ++require changes that are not compatible with the additional safety ++properties afforded by the current implementation. ++ ++Furthermore, the POSIX standard does not offer a detailed definition of ++safety. We assume that, by ``safe to call'', POSIX means that, as long ++as the program does not invoke undefined behavior, the ``safe to call'' ++function behaves as specified, and does not cause other functions to ++deviate from their specified behavior. We have chosen to use its loose ++definitions of safety, not because they are the best definitions to use, ++but because choosing them harmonizes this manual with POSIX. ++ ++Please keep in mind that these are preliminary definitions and ++annotations, and certain aspects of the definitions are still under ++discussion and might be subject to clarification or change. ++ ++Over time, we envision evolving the preliminary safety notes into stable ++commitments, as stable as those of our interfaces. As we do, we will ++remove the @code{Preliminary} keyword from safety notes. As long as the ++keyword remains, however, they are not to be regarded as a promise of ++future behavior. ++ ++ ++@end itemize ++ ++Other keywords that appear in safety notes are defined in subsequent ++sections. ++ ++ ++@node Unsafe Features, Conditionally Safe Features, POSIX Safety Concepts, POSIX ++@subsubsection Unsafe Features ++@cindex Unsafe Features ++ ++Functions that are unsafe to call in certain contexts are annotated with ++keywords that document their features that make them unsafe to call. ++AS-Unsafe features in this section indicate the functions are never safe ++to call when asynchronous signals are enabled. AC-Unsafe features ++indicate they are never safe to call when asynchronous cancellation is ++enabled. There are no MT-Unsafe marks in this section. ++ ++@itemize @bullet ++ ++@item @code{lock} ++@cindex lock ++ ++Functions marked with @code{lock} as an AS-Unsafe feature may be ++interrupted by a signal while holding a non-recursive lock. If the ++signal handler calls another such function that takes the same lock, the ++result is a deadlock. ++ ++Functions annotated with @code{lock} as an AC-Unsafe feature may, if ++cancelled asynchronously, fail to release a lock that would have been ++released if their execution had not been interrupted by asynchronous ++thread cancellation. Once a lock is left taken, attempts to take that ++lock will block indefinitely. ++ ++ ++@item @code{corrupt} ++@cindex corrupt ++ ++Functions marked with @code{corrupt} as an AS-Unsafe feature may corrupt ++data structures and misbehave when they interrupt, or are interrupted ++by, another such function. Unlike functions marked with @code{lock}, ++these take recursive locks to avoid MT-Safety problems, but this is not ++enough to stop a signal handler from observing a partially-updated data ++structure. Further corruption may arise from the interrupted function's ++failure to notice updates made by signal handlers. ++ ++Functions marked with @code{corrupt} as an AC-Unsafe feature may leave ++data structures in a corrupt, partially updated state. Subsequent uses ++of the data structure may misbehave. ++ ++@c A special case, probably not worth documenting separately, involves ++@c reallocing, or even freeing pointers. Any case involving free could ++@c be easily turned into an ac-safe leak by resetting the pointer before ++@c releasing it; I don't think we have any case that calls for this sort ++@c of fixing. Fixing the realloc cases would require a new interface: ++@c instead of @code{ptr=realloc(ptr,size)} we'd have to introduce ++@c @code{acsafe_realloc(&ptr,size)} that would modify ptr before ++@c releasing the old memory. The ac-unsafe realloc could be implemented ++@c in terms of an internal interface with this semantics (say ++@c __acsafe_realloc), but since realloc can be overridden, the function ++@c we call to implement realloc should not be this internal interface, ++@c but another internal interface that calls __acsafe_realloc if realloc ++@c was not overridden, and calls the overridden realloc with async ++@c cancel disabled. --lxoliva ++ ++ ++@item @code{heap} ++@cindex heap ++ ++Functions marked with @code{heap} may call heap memory management ++functions from the @code{malloc}/@code{free} family of functions and are ++only as safe as those functions. This note is thus equivalent to: ++ ++@sampsafety{@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} ++ ++ ++@c Check for cases that should have used plugin instead of or in ++@c addition to this. Then, after rechecking gettext, adjust i18n if ++@c needed. ++@item @code{dlopen} ++@cindex dlopen ++ ++Functions marked with @code{dlopen} use the dynamic loader to load ++shared libraries into the current execution image. This involves ++opening files, mapping them into memory, allocating additional memory, ++resolving symbols, applying relocations and more, all of this while ++holding internal dynamic loader locks. ++ ++The locks are enough for these functions to be AS- and AC-Unsafe, but ++other issues may arise. At present this is a placeholder for all ++potential safety issues raised by @code{dlopen}. ++ ++@c dlopen runs init and fini sections of the module; does this mean ++@c dlopen always implies plugin? ++ ++ ++@item @code{plugin} ++@cindex plugin ++ ++Functions annotated with @code{plugin} may run code from plugins that ++may be external to @theglibc{}. Such plugin functions are assumed to be ++MT-Safe, AS-Unsafe and AC-Unsafe. Examples of such plugins are stack ++@cindex NSS ++unwinding libraries, name service switch (NSS) and character set ++@cindex iconv ++conversion (iconv) back-ends. ++ ++Although the plugins mentioned as examples are all brought in by means ++of dlopen, the @code{plugin} keyword does not imply any direct ++involvement of the dynamic loader or the @code{libdl} interfaces, those ++are covered by @code{dlopen}. For example, if one function loads a ++module and finds the addresses of some of its functions, while another ++just calls those already-resolved functions, the former will be marked ++with @code{dlopen}, whereas the latter will get the @code{plugin}. When ++a single function takes all of these actions, then it gets both marks. ++ ++ ++@item @code{i18n} ++@cindex i18n ++ ++Functions marked with @code{i18n} may call internationalization ++functions of the @code{gettext} family and will be only as safe as those ++functions. This note is thus equivalent to: ++ ++@sampsafety{@mtsafe{@mtsenv{}}@asunsafe{@asucorrupt{} @ascuheap{} @ascudlopen{}}@acunsafe{@acucorrupt{}}} ++ ++ ++@item @code{timer} ++@cindex timer ++ ++Functions marked with @code{timer} use the @code{alarm} function or ++similar to set a time-out for a system call or a long-running operation. ++In a multi-threaded program, there is a risk that the time-out signal ++will be delivered to a different thread, thus failing to interrupt the ++intended thread. Besides being MT-Unsafe, such functions are always ++AS-Unsafe, because calling them in signal handlers may interfere with ++timers set in the interrupted code, and AC-Unsafe, because there is no ++safe way to guarantee an earlier timer will be reset in case of ++asynchronous cancellation. ++ ++@end itemize ++ ++ ++@node Conditionally Safe Features, Other Safety Remarks, Unsafe Features, POSIX ++@subsubsection Conditionally Safe Features ++@cindex Conditionally Safe Features ++ ++For some features that make functions unsafe to call in certain ++contexts, there are known ways to avoid the safety problem other than ++refraining from calling the function altogether. The keywords that ++follow refer to such features, and each of their definitions indicate ++how the whole program needs to be constrained in order to remove the ++safety problem indicated by the keyword. Only when all the reasons that ++make a function unsafe are observed and addressed, by applying the ++documented constraints, does the function become safe to call in a ++context. ++ ++@itemize @bullet ++ ++@item @code{init} ++@cindex init ++ ++Functions marked with @code{init} as an MT-Unsafe feature perform ++MT-Unsafe initialization when they are first called. ++ ++Calling such a function at least once in single-threaded mode removes ++this specific cause for the function to be regarded as MT-Unsafe. If no ++other cause for that remains, the function can then be safely called ++after other threads are started. ++ ++Functions marked with @code{init} as an AS- or AC-Unsafe feature use the ++internal @code{libc_once} machinery or similar to initialize internal ++data structures. ++ ++If a signal handler interrupts such an initializer, and calls any ++function that also performs @code{libc_once} initialization, it will ++deadlock if the thread library has been loaded. ++ ++Furthermore, if an initializer is partially complete before it is ++canceled or interrupted by a signal whose handler requires the same ++initialization, some or all of the initialization may be performed more ++than once, leaking resources or even resulting in corrupt internal data. ++ ++Applications that need to call functions marked with @code{init} as an ++AS- or AC-Unsafe feature should ensure the initialization is performed ++before configuring signal handlers or enabling cancellation, so that the ++AS- and AC-Safety issues related with @code{libc_once} do not arise. ++ ++@c We may have to extend the annotations to cover conditions in which ++@c initialization may or may not occur, since an initial call in a safe ++@c context is no use if the initialization doesn't take place at that ++@c time: it doesn't remove the risk for later calls. ++ ++ ++@item @code{race} ++@cindex race ++ ++Functions annotated with @code{race} as an MT-Safety issue operate on ++objects in ways that may cause data races or similar forms of ++destructive interference out of concurrent execution. In some cases, ++the objects are passed to the functions by users; in others, they are ++used by the functions to return values to users; in others, they are not ++even exposed to users. ++ ++We consider access to objects passed as (indirect) arguments to ++functions to be data race free. The assurance of data race free objects ++is the caller's responsibility. We will not mark a function as ++MT-Unsafe or AS-Unsafe if it misbehaves when users fail to take the ++measures required by POSIX to avoid data races when dealing with such ++objects. As a general rule, if a function is documented as reading from ++an object passed (by reference) to it, or modifying it, users ought to ++use memory synchronization primitives to avoid data races just as they ++would should they perform the accesses themselves rather than by calling ++the library function. @code{FILE} streams are the exception to the ++general rule, in that POSIX mandates the library to guard against data ++races in many functions that manipulate objects of this specific opaque ++type. We regard this as a convenience provided to users, rather than as ++a general requirement whose expectations should extend to other types. ++ ++In order to remind users that guarding certain arguments is their ++responsibility, we will annotate functions that take objects of certain ++types as arguments. We draw the line for objects passed by users as ++follows: objects whose types are exposed to users, and that users are ++expected to access directly, such as memory buffers, strings, and ++various user-visible @code{struct} types, do @emph{not} give reason for ++functions to be annotated with @code{race}. It would be noisy and ++redundant with the general requirement, and not many would be surprised ++by the library's lack of internal guards when accessing objects that can ++be accessed directly by users. ++ ++As for objects that are opaque or opaque-like, in that they are to be ++manipulated only by passing them to library functions (e.g., ++@code{FILE}, @code{DIR}, @code{obstack}, @code{iconv_t}), there might be ++additional expectations as to internal coordination of access by the ++library. We will annotate, with @code{race} followed by a colon and the ++argument name, functions that take such objects but that do not take ++care of synchronizing access to them by default. For example, ++@code{FILE} stream @code{unlocked} functions will be annotated, but ++those that perform implicit locking on @code{FILE} streams by default ++will not, even though the implicit locking may be disabled on a ++per-stream basis. ++ ++In either case, we will not regard as MT-Unsafe functions that may ++access user-supplied objects in unsafe ways should users fail to ensure ++the accesses are well defined. The notion prevails that users are ++expected to safeguard against data races any user-supplied objects that ++the library accesses on their behalf. ++ ++@c The above describes @mtsrace; @mtasurace is described below. ++ ++This user responsibility does not apply, however, to objects controlled ++by the library itself, such as internal objects and static buffers used ++to return values from certain calls. When the library doesn't guard ++them against concurrent uses, these cases are regarded as MT-Unsafe and ++AS-Unsafe (although the @code{race} mark under AS-Unsafe will be omitted ++as redundant with the one under MT-Unsafe). As in the case of ++user-exposed objects, the mark may be followed by a colon and an ++identifier. The identifier groups all functions that operate on a ++certain unguarded object; users may avoid the MT-Safety issues related ++with unguarded concurrent access to such internal objects by creating a ++non-recursive mutex related with the identifier, and always holding the ++mutex when calling any function marked as racy on that identifier, as ++they would have to should the identifier be an object under user ++control. The non-recursive mutex avoids the MT-Safety issue, but it ++trades one AS-Safety issue for another, so use in asynchronous signals ++remains undefined. ++ ++When the identifier relates to a static buffer used to hold return ++values, the mutex must be held for as long as the buffer remains in use ++by the caller. Many functions that return pointers to static buffers ++offer reentrant variants that store return values in caller-supplied ++buffers instead. In some cases, such as @code{tmpname}, the variant is ++chosen not by calling an alternate entry point, but by passing a ++non-@code{NULL} pointer to the buffer in which the returned values are ++to be stored. These variants are generally preferable in multi-threaded ++programs, although some of them are not MT-Safe because of other ++internal buffers, also documented with @code{race} notes. ++ ++ ++@item @code{const} ++@cindex const ++ ++Functions marked with @code{const} as an MT-Safety issue non-atomically ++modify internal objects that are better regarded as constant, because a ++substantial portion of @theglibc{} accesses them without ++synchronization. Unlike @code{race}, that causes both readers and ++writers of internal objects to be regarded as MT-Unsafe and AS-Unsafe, ++this mark is applied to writers only. Writers remain equally MT- and ++AS-Unsafe to call, but the then-mandatory constness of objects they ++modify enables readers to be regarded as MT-Safe and AS-Safe (as long as ++no other reasons for them to be unsafe remain), since the lack of ++synchronization is not a problem when the objects are effectively ++constant. ++ ++The identifier that follows the @code{const} mark will appear by itself ++as a safety note in readers. Programs that wish to work around this ++safety issue, so as to call writers, may use a non-recursve ++@code{rwlock} associated with the identifier, and guard @emph{all} calls ++to functions marked with @code{const} followed by the identifier with a ++write lock, and @emph{all} calls to functions marked with the identifier ++by itself with a read lock. The non-recursive locking removes the ++MT-Safety problem, but it trades one AS-Safety problem for another, so ++use in asynchronous signals remains undefined. ++ ++@c But what if, instead of marking modifiers with const:id and readers ++@c with just id, we marked writers with race:id and readers with ro:id? ++@c Instead of having to define each instance of “id”, we'd have a ++@c general pattern governing all such “id”s, wherein race:id would ++@c suggest the need for an exclusive/write lock to make the function ++@c safe, whereas ro:id would indicate “id” is expected to be read-only, ++@c but if any modifiers are called (while holding an exclusive lock), ++@c then ro:id-marked functions ought to be guarded with a read lock for ++@c safe operation. ro:env or ro:locale, for example, seems to convey ++@c more clearly the expectations and the meaning, than just env or ++@c locale. ++ ++ ++@item @code{sig} ++@cindex sig ++ ++Functions marked with @code{sig} as a MT-Safety issue (that implies an ++identical AS-Safety issue, omitted for brevity) may temporarily install ++a signal handler for internal purposes, which may interfere with other ++uses of the signal, identified after a colon. ++ ++This safety problem can be worked around by ensuring that no other uses ++of the signal will take place for the duration of the call. Holding a ++non-recursive mutex while calling all functions that use the same ++temporary signal; blocking that signal before the call and resetting its ++handler afterwards is recommended. ++ ++There is no safe way to guarantee the original signal handler is ++restored in case of asynchronous cancellation, therefore so-marked ++functions are also AC-Unsafe. ++ ++@c fixme: at least deferred cancellation should get it right, and would ++@c obviate the restoring bit below, and the qualifier above. ++ ++Besides the measures recommended to work around the MT- and AS-Safety ++problem, in order to avert the cancellation problem, disabling ++asynchronous cancellation @emph{and} installing a cleanup handler to ++restore the signal to the desired state and to release the mutex are ++recommended. ++ ++ ++@item @code{term} ++@cindex term ++ ++Functions marked with @code{term} as an MT-Safety issue may change the ++terminal settings in the recommended way, namely: call @code{tcgetattr}, ++modify some flags, and then call @code{tcsetattr}; this creates a window ++in which changes made by other threads are lost. Thus, functions marked ++with @code{term} are MT-Unsafe. The same window enables changes made by ++asynchronous signals to be lost. These functions are also AS-Unsafe, ++but the corresponding mark is omitted as redundant. ++ ++It is thus advisable for applications using the terminal to avoid ++concurrent and reentrant interactions with it, by not using it in signal ++handlers or blocking signals that might use it, and holding a lock while ++calling these functions and interacting with the terminal. This lock ++should also be used for mutual exclusion with functions marked with ++@code{@mtasurace{:tcattr(fd)}}, where @var{fd} is a file descriptor for ++the controlling terminal. The caller may use a single mutex for ++simplicity, or use one mutex per terminal, even if referenced by ++different file descriptors. ++ ++Functions marked with @code{term} as an AC-Safety issue are supposed to ++restore terminal settings to their original state, after temporarily ++changing them, but they may fail to do so if cancelled. ++ ++@c fixme: at least deferred cancellation should get it right, and would ++@c obviate the restoring bit below, and the qualifier above. ++ ++Besides the measures recommended to work around the MT- and AS-Safety ++problem, in order to avert the cancellation problem, disabling ++asynchronous cancellation @emph{and} installing a cleanup handler to ++restore the terminal settings to the original state and to release the ++mutex are recommended. ++ ++ ++@end itemize ++ ++ ++@node Other Safety Remarks, , Conditionally Safe Features, POSIX ++@subsubsection Other Safety Remarks ++@cindex Other Safety Remarks ++ ++Additional keywords may be attached to functions, indicating features ++that do not make a function unsafe to call, but that may need to be ++taken into account in certain classes of programs: ++ ++@itemize @bullet ++ ++@item @code{locale} ++@cindex locale ++ ++Functions annotated with @code{locale} as an MT-Safety issue read from ++the locale object without any form of synchronization. Functions ++annotated with @code{locale} called concurrently with locale changes may ++behave in ways that do not correspond to any of the locales active ++during their execution, but an unpredictable mix thereof. ++ ++We do not mark these functions as MT- or AS-Unsafe, however, because ++functions that modify the locale object are marked with ++@code{const:locale} and regarded as unsafe. Being unsafe, the latter ++are not to be called when multiple threads are running or asynchronous ++signals are enabled, and so the locale can be considered effectively ++constant in these contexts, which makes the former safe. ++ ++@c Should the locking strategy suggested under @code{const} be used, ++@c failure to guard locale uses is not as fatal as data races in ++@c general: unguarded uses will @emph{not} follow dangling pointers or ++@c access uninitialized, unmapped or recycled memory. Each access will ++@c read from a consistent locale object that is or was active at some ++@c point during its execution. Without synchronization, however, it ++@c cannot even be assumed that, after a change in locale, earlier ++@c locales will no longer be used, even after the newly-chosen one is ++@c used in the thread. Nevertheless, even though unguarded reads from ++@c the locale will not violate type safety, functions that access the ++@c locale multiple times may invoke all sorts of undefined behavior ++@c because of the unexpected locale changes. ++ ++ ++@item @code{env} ++@cindex env ++ ++Functions marked with @code{env} as an MT-Safety issue access the ++environment with @code{getenv} or similar, without any guards to ensure ++safety in the presence of concurrent modifications. ++ ++We do not mark these functions as MT- or AS-Unsafe, however, because ++functions that modify the environment are all marked with ++@code{const:env} and regarded as unsafe. Being unsafe, the latter are ++not to be called when multiple threads are running or asynchronous ++signals are enabled, and so the environment can be considered ++effectively constant in these contexts, which makes the former safe. ++ ++ ++@item @code{hostid} ++@cindex hostid ++ ++The function marked with @code{hostid} as an MT-Safety issue reads from ++the system-wide data structures that hold the ``host ID'' of the ++machine. These data structures cannot generally be modified atomically. ++Since it is expected that the ``host ID'' will not normally change, the ++function that reads from it (@code{gethostid}) is regarded as safe, ++whereas the function that modifies it (@code{sethostid}) is marked with ++@code{@mtasuconst{:@mtshostid{}}}, indicating it may require special ++care if it is to be called. In this specific case, the special care ++amounts to system-wide (not merely intra-process) coordination. ++ ++ ++@item @code{sigintr} ++@cindex sigintr ++ ++Functions marked with @code{sigintr} as an MT-Safety issue access the ++@code{_sigintr} internal data structure without any guards to ensure ++safety in the presence of concurrent modifications. ++ ++We do not mark these functions as MT- or AS-Unsafe, however, because ++functions that modify the this data structure are all marked with ++@code{const:sigintr} and regarded as unsafe. Being unsafe, the latter ++are not to be called when multiple threads are running or asynchronous ++signals are enabled, and so the data structure can be considered ++effectively constant in these contexts, which makes the former safe. ++ ++ ++@item @code{fd} ++@cindex fd ++ ++Functions annotated with @code{fd} as an AC-Safety issue may leak file ++descriptors if asynchronous thread cancellation interrupts their ++execution. ++ ++Functions that allocate or deallocate file descriptors will generally be ++marked as such. Even if they attempted to protect the file descriptor ++allocation and deallocation with cleanup regions, allocating a new ++descriptor and storing its number where the cleanup region could release ++it cannot be performed as a single atomic operation. Similarly, ++releasing the descriptor and taking it out of the data structure ++normally responsible for releasing it cannot be performed atomically. ++There will always be a window in which the descriptor cannot be released ++because it was not stored in the cleanup handler argument yet, or it was ++already taken out before releasing it. It cannot be taken out after ++release: an open descriptor could mean either that the descriptor still ++has to be closed, or that it already did so but the descriptor was ++reallocated by another thread or signal handler. ++ ++Such leaks could be internally avoided, with some performance penalty, ++by temporarily disabling asynchronous thread cancellation. However, ++since callers of allocation or deallocation functions would have to do ++this themselves, to avoid the same sort of leak in their own layer, it ++makes more sense for the library to assume they are taking care of it ++than to impose a performance penalty that is redundant when the problem ++is solved in upper layers, and insufficient when it is not. ++ ++This remark by itself does not cause a function to be regarded as ++AC-Unsafe. However, cumulative effects of such leaks may pose a ++problem for some programs. If this is the case, suspending asynchronous ++cancellation for the duration of calls to such functions is recommended. ++ ++ ++@item @code{mem} ++@cindex mem ++ ++Functions annotated with @code{mem} as an AC-Safety issue may leak ++memory if asynchronous thread cancellation interrupts their execution. ++ ++The problem is similar to that of file descriptors: there is no atomic ++interface to allocate memory and store its address in the argument to a ++cleanup handler, or to release it and remove its address from that ++argument, without at least temporarily disabling asynchronous ++cancellation, which these functions do not do. ++ ++This remark does not by itself cause a function to be regarded as ++generally AC-Unsafe. However, cumulative effects of such leaks may be ++severe enough for some programs that disabling asynchronous cancellation ++for the duration of calls to such functions may be required. ++ ++ ++@item @code{cwd} ++@cindex cwd ++ ++Functions marked with @code{cwd} as an MT-Safety issue may temporarily ++change the current working directory during their execution, which may ++cause relative pathnames to be resolved in unexpected ways in other ++threads or within asynchronous signal or cancellation handlers. ++ ++This is not enough of a reason to mark so-marked functions as MT- or ++AS-Unsafe, but when this behavior is optional (e.g., @code{nftw} with ++@code{FTW_CHDIR}), avoiding the option may be a good alternative to ++using full pathnames or file descriptor-relative (e.g. @code{openat}) ++system calls. ++ ++ ++@item @code{!posix} ++@cindex !posix ++ ++This remark, as an MT-, AS- or AC-Safety note to a function, indicates ++the safety status of the function is known to differ from the specified ++status in the POSIX standard. For example, POSIX does not require a ++function to be Safe, but our implementation is, or vice-versa. ++ ++For the time being, the absence of this remark does not imply the safety ++properties we documented are identical to those mandated by POSIX for ++the corresponding functions. ++ ++ ++@item @code{:identifier} ++@cindex :identifier ++ ++Annotations may sometimes be followed by identifiers, intended to group ++several functions that e.g. access the data structures in an unsafe way, ++as in @code{race} and @code{const}, or to provide more specific ++information, such as naming a signal in a function marked with ++@code{sig}. It is envisioned that it may be applied to @code{lock} and ++@code{corrupt} as well in the future. ++ ++In most cases, the identifier will name a set of functions, but it may ++name global objects or function arguments, or identifiable properties or ++logical components associated with them, with a notation such as ++e.g. @code{:buf(arg)} to denote a buffer associated with the argument ++@var{arg}, or @code{:tcattr(fd)} to denote the terminal attributes of a ++file descriptor @var{fd}. ++ ++The most common use for identifiers is to provide logical groups of ++functions and arguments that need to be protected by the same ++synchronization primitive in order to ensure safe operation in a given ++context. ++ ++ ++@item @code{/condition} ++@cindex /condition ++ ++Some safety annotations may be conditional, in that they only apply if a ++boolean expression involving arguments, global variables or even the ++underlying kernel evaluates evaluates to true. Such conditions as ++@code{/hurd} or @code{/!linux!bsd} indicate the preceding marker only ++applies when the underlying kernel is the HURD, or when it is neither ++Linux nor a BSD kernel, respectively. @code{/!ps} and ++@code{/one_per_line} indicate the preceding marker only applies when ++argument @var{ps} is NULL, or global variable @var{one_per_line} is ++nonzero. ++ ++When all marks that render a function unsafe are adorned with such ++conditions, and none of the named conditions hold, then the function can ++be regarded as safe. ++ ++ ++@end itemize ++ + + @node Berkeley Unix, SVID, POSIX, Standards and Portability + @subsection Berkeley Unix +@@ -556,19 +1283,59 @@ + Here is an overview of the contents of the remaining chapters of + this manual. + ++@c The chapter overview ordering is: ++@c Error Reporting (2) ++@c Virtual Memory Allocation and Paging (3) ++@c Character Handling (4) ++@c Strings and Array Utilities (5) ++@c Character Set Handling (6) ++@c Locales and Internationalization (7) ++@c Searching and Sorting (9) ++@c Pattern Matching (10) ++@c Input/Output Overview (11) ++@c Input/Output on Streams (12) ++@c Low-level Input/Ooutput (13) ++@c File System Interface (14) ++@c Pipes and FIFOs (15) ++@c Sockets (16) ++@c Low-Level Terminal Interface (17) ++@c Syslog (18) ++@c Mathematics (19) ++@c Aritmetic Functions (20) ++@c Date and Time (21) ++@c Non-Local Exist (23) ++@c Signal Handling (24) ++@c The Basic Program/System Interface (25) ++@c Processes (26) ++@c Job Control (28) ++@c System Databases and Name Service Switch (29) ++@c Users and Groups (30) -- References `User Database' and `Group Database' ++@c System Management (31) ++@c System Configuration Parameters (32) ++@c C Language Facilities in the Library (AA) ++@c Summary of Library Facilities (AB) ++@c Installing (AC) ++@c Library Maintenance (AD) ++ ++@c The following chapters need overview text to be added: ++@c Message Translation (8) ++@c Resource Usage And Limitations (22) ++@c Inter-Process Communication (27) ++@c DES Encryption and Password Handling (33) ++@c Debugging support (34) ++@c POSIX Threads (35) ++@c Internal Probes (36) ++@c Platform-specific facilities (AE) ++@c Contributors to (AF) ++@c Free Software Needs Free Documentation (AG) ++@c GNU Lesser General Public License (AH) ++@c GNU Free Documentation License (AI) ++ + @itemize @bullet + @item + @ref{Error Reporting}, describes how errors detected by the library + are reported. + +-@item +-@ref{Language Features}, contains information about library support for +-standard parts of the C language, including things like the @code{sizeof} +-operator and the symbolic constant @code{NULL}, how to write functions +-accepting variable numbers of arguments, and constants describing the +-ranges and other properties of the numerical types. There is also a simple +-debugging mechanism which allows you to put assertions in your code, and +-have diagnostic messages printed if the tests fail. + + @item + @ref{Memory}, describes @theglibc{}'s facilities for managing and +@@ -588,6 +1355,26 @@ + byte arrays, including operations such as copying and comparison. + + @item ++@ref{Character Set Handling}, contains information about manipulating ++characters and strings using character sets larger than will fit in ++the usual @code{char} data type. ++ ++@item ++@ref{Locales}, describes how selecting a particular country ++or language affects the behavior of the library. For example, the locale ++affects collation sequences for strings and how monetary values are ++formatted. ++ ++@item ++@ref{Searching and Sorting}, contains information about functions ++for searching and sorting arrays. You can use these functions on any ++kind of array by providing an appropriate comparison function. ++ ++@item ++@ref{Pattern Matching}, presents functions for matching regular expressions ++and shell file name patterns, and for expanding words as the shell does. ++ ++@item + @ref{I/O Overview}, gives an overall look at the input and output + facilities in the library, and contains information about basic concepts + such as file names. +@@ -639,30 +1426,10 @@ + numbers from strings. + + @item +-@ref{Searching and Sorting}, contains information about functions +-for searching and sorting arrays. You can use these functions on any +-kind of array by providing an appropriate comparison function. +- +-@item +-@ref{Pattern Matching}, presents functions for matching regular expressions +-and shell file name patterns, and for expanding words as the shell does. +- +-@item + @ref{Date and Time}, describes functions for measuring both calendar time + and CPU time, as well as functions for setting alarms and timers. + + @item +-@ref{Character Set Handling}, contains information about manipulating +-characters and strings using character sets larger than will fit in +-the usual @code{char} data type. +- +-@item +-@ref{Locales}, describes how selecting a particular country +-or language affects the behavior of the library. For example, the locale +-affects collation sequences for strings and how monetary values are +-formatted. +- +-@item + @ref{Non-Local Exits}, contains descriptions of the @code{setjmp} and + @code{longjmp} functions. These functions provide a facility for + @code{goto}-like jumps which can jump from one function to another. +@@ -708,6 +1475,15 @@ + compatibility with POSIX. + + @item ++@ref{Language Features}, contains information about library support for ++standard parts of the C language, including things like the @code{sizeof} ++operator and the symbolic constant @code{NULL}, how to write functions ++accepting variable numbers of arguments, and constants describing the ++ranges and other properties of the numerical types. There is also a simple ++debugging mechanism which allows you to put assertions in your code, and ++have diagnostic messages printed if the tests fail. ++ ++@item + @ref{Library Summary}, gives a summary of all the functions, variables, and + macros in the library, with complete data types and function prototypes, + and says what standard or system each is derived from. +diff -urN glibc-2.17-c758a686/manual/ipc.texi glibc-2.17-c758a686/manual/ipc.texi +--- glibc-2.17-c758a686/manual/ipc.texi 1969-12-31 19:00:00.000000000 -0500 ++++ glibc-2.17-c758a686/manual/ipc.texi 2014-09-12 16:10:06.047792712 -0400 +@@ -0,0 +1,116 @@ ++@node Inter-Process Communication, Job Control, Processes, Top ++@c %MENU% All about inter-process communication ++@chapter Inter-Process Communication ++@cindex ipc ++ ++This chapter describes the @glibcadj{} inter-process communication primitives. ++ ++@menu ++* Semaphores:: Support for creating and managing semaphores ++@end menu ++ ++@node Semaphores ++@section Semaphores ++ ++@Theglibc{} implements the semaphore APIs as defined in POSIX and ++System V. Semaphores can be used by multiple processes to coordinate shared ++resources. The following is a complete list of the semaphore functions provided ++by @theglibc{}. ++ ++@c Need descriptions for all of these functions. ++ ++@subsection System V Semaphores ++@deftypefun int semctl (int @var{semid}, int @var{semnum}, int @var{cmd}); ++@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@acucorrupt{/linux}}} ++@c syscall(ipc) ok ++@c ++@c AC-unsafe because we need to translate the new kernel ++@c semid_ds buf into the userspace layout. Cancellation ++@c at that point results in an inconsistent userspace ++@c semid_ds. ++@end deftypefun ++ ++@deftypefun int semget (key_t @var{key}, int @var{nsems}, int @var{semflg}); ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c syscall(ipc) ok ++@end deftypefun ++ ++@deftypefun int semop (int @var{semid}, struct sembuf *@var{sops}, size_t @var{nsops}); ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c syscall(ipc) ok ++@end deftypefun ++ ++@deftypefun int semtimedop (int @var{semid}, struct sembuf *@var{sops}, size_t @var{nsops}, const struct timespec *@var{timeout}); ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c syscall(ipc) ok ++@end deftypefun ++ ++@subsection POSIX Semaphores ++ ++@deftypefun int sem_init (sem_t *@var{sem}, int @var{pshared}, unsigned int @var{value}); ++@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@acucorrupt{}}} ++@c Does not atomically update sem_t therefore AC-unsafe ++@c because it can leave sem_t partially initialized. ++@end deftypefun ++ ++@deftypefun int sem_destroy (sem_t *@var{sem}); ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Function does nothing and is therefore always safe. ++@end deftypefun ++ ++@deftypefun sem_t *sem_open (const char *@var{name}, int @var{oflag}, ...); ++@safety{@prelim{}@mtsafe{}@asunsafe{@asuinit{}}@acunsafe{@acuinit{}}} ++@c pthread_once asuinit ++@c ++@c We are AC-Unsafe becuase we use pthread_once to initialize ++@c a global variable that holds the location of the mounted ++@c shmfs on Linux. ++@end deftypefun ++ ++@deftypefun int sem_close (sem_t *@var{sem}); ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} ++@c lll_lock asulock aculock ++@c twalk mtsrace{:root} ++@c ++@c We are AS-unsafe because we take a non-recursive lock. ++@c We are AC-unsafe because several internal data structures ++@c are not updated atomically. ++@end deftypefun ++ ++@deftypefun int sem_unlink (const char *@var{name}); ++@safety{@prelim{}@mtsafe{}@asunsafe{@asuinit{}}@acunsafe{@acucorrupt{}}} ++@c pthread_once asuinit acucorrupt aculock ++@c mempcpy acucorrupt ++@end deftypefun ++ ++@deftypefun int sem_wait (sem_t *@var{sem}); ++@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@acucorrupt{}}} ++@c atomic_increment (nwaiters) acucorrupt ++@c ++@c Given the use atomic operations this function seems ++@c to be AS-safe. It is AC-unsafe because there is still ++@c a window between atomic_decrement and the pthread_push ++@c of the handler that undoes that operation. A cancellation ++@c at that point would fail to remove the process from the ++@c waiters count. ++@end deftypefun ++ ++@deftypefun int sem_timedwait (sem_t *@var{sem}, const struct timespec *@var{abstime}); ++@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@acucorrupt{}}} ++@c Same safety issues as sem_wait. ++@end deftypefun ++ ++@deftypefun int sem_trywait (sem_t *@var{sem}); ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c All atomic operations are safe in all contexts. ++@end deftypefun ++ ++@deftypefun int sem_post (sem_t *@var{sem}); ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Same safety as sem_trywait. ++@end deftypefun ++ ++@deftypefun int sem_getvalue (sem_t *@var{sem}, int *@var{sval}); ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Atomic write of a value is safe in all contexts. ++@end deftypefun +diff -urN glibc-2.17-c758a686/manual/job.texi glibc-2.17-c758a686/manual/job.texi +--- glibc-2.17-c758a686/manual/job.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/job.texi 2014-09-12 16:10:06.048792709 -0400 +@@ -1,4 +1,4 @@ +-@node Job Control, Name Service Switch, Processes, Top ++@node Job Control, Name Service Switch, Inter-Process Communication, Top + @c %MENU% All about process groups and sessions + @chapter Job Control + +@@ -1039,6 +1039,10 @@ + @comment stdio.h + @comment POSIX.1 + @deftypefun {char *} ctermid (char *@var{string}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c This function is a stub by default; the actual implementation, for ++@c posix systems, returns an internal buffer if passed a NULL string, ++@c but the internal buffer is always set to /dev/tty. + The @code{ctermid} function returns a string containing the file name of + the controlling terminal for the current process. If @var{string} is + not a null pointer, it should be an array that can hold at least +@@ -1075,6 +1079,12 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun pid_t setsid (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c This is usually a direct syscall, but if a syscall is not available, ++@c we use a stub, or Hurd- and BSD-specific implementations. The former ++@c uses a mutex and a hurd critical section, and the latter issues a few ++@c syscalls, so both seem safe, the locking on Hurd is safe because of ++@c the critical section. + The @code{setsid} function creates a new session. The calling process + becomes the session leader, and is put in a new process group whose + process group ID is the same as the process ID of that process. There +@@ -1098,6 +1108,8 @@ + @comment unistd.h + @comment SVID + @deftypefun pid_t getsid (pid_t @var{pid}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Stub or direct syscall, except on hurd, where it is equally safe. + + The @code{getsid} function returns the process group ID of the session + leader of the specified process. If a @var{pid} is @code{0}, the +@@ -1118,39 +1130,21 @@ + @end table + @end deftypefun + +-The @code{getpgrp} function has two definitions: one derived from BSD +-Unix, and one from the POSIX.1 standard. The feature test macros you +-have selected (@pxref{Feature Test Macros}) determine which definition +-you get. Specifically, you get the BSD version if you define +-@code{_BSD_SOURCE}; otherwise, you get the POSIX version if you define +-@code{_POSIX_SOURCE} or @code{_GNU_SOURCE}. Programs written for old +-BSD systems will not include @file{unistd.h}, which defines +-@code{getpgrp} specially under @code{_BSD_SOURCE}. You must link such +-programs with the @code{-lbsd-compat} option to get the BSD definition.@refill +-@pindex -lbsd-compat +-@pindex bsd-compat +-@cindex BSD compatibility library +- + @comment unistd.h + @comment POSIX.1 +-@deftypefn {POSIX.1 Function} pid_t getpgrp (void) +-The POSIX.1 definition of @code{getpgrp} returns the process group ID of ++@deftypefun pid_t getpgrp (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++The @code{getpgrp} function returns the process group ID of + the calling process. +-@end deftypefn +- +-@comment unistd.h +-@comment BSD +-@deftypefn {BSD Function} pid_t getpgrp (pid_t @var{pid}) +-The BSD definition of @code{getpgrp} returns the process group ID of the +-process @var{pid}. You can supply a value of @code{0} for the @var{pid} +-argument to get information about the calling process. +-@end deftypefn ++@end deftypefun + + @comment unistd.h +-@comment SVID +-@deftypefn {System V Function} int getpgid (pid_t @var{pid}) ++@comment POSIX.1 ++@deftypefun int getpgid (pid_t @var{pid}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Stub or direct syscall, except on hurd, where it is equally safe. + +-@code{getpgid} is the same as the BSD function @code{getpgrp}. It ++The @code{getpgid} function + returns the process group ID of the process @var{pid}. You can supply a + value of @code{0} for the @var{pid} argument to get information about + the calling process. +@@ -1166,11 +1160,13 @@ + process group ID of the process with ID @var{pid} from the calling + process. + @end table +-@end deftypefn ++@end deftypefun + + @comment unistd.h + @comment POSIX.1 + @deftypefun int setpgid (pid_t @var{pid}, pid_t @var{pgid}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Stub or direct syscall, except on hurd, where it is equally safe. + The @code{setpgid} function puts the process @var{pid} into the process + group @var{pgid}. As a special case, either @var{pid} or @var{pgid} can + be zero to indicate the process ID of the calling process. +@@ -1208,6 +1204,8 @@ + @comment unistd.h + @comment BSD + @deftypefun int setpgrp (pid_t @var{pid}, pid_t @var{pgid}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall or setpgid wrapper. + This is the BSD Unix name for @code{setpgid}. Both functions do exactly + the same thing. + @end deftypefun +@@ -1230,6 +1228,8 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun pid_t tcgetpgrp (int @var{filedes}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Stub, or ioctl on BSD and GNU/Linux. + This function returns the process group ID of the foreground process + group associated with the terminal open on descriptor @var{filedes}. + +@@ -1258,6 +1258,8 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun int tcsetpgrp (int @var{filedes}, pid_t @var{pgid}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Stub, or ioctl on BSD and GNU/Linux. + This function is used to set a terminal's foreground process group ID. + The argument @var{filedes} is a descriptor which specifies the terminal; + @var{pgid} specifies the process group. The calling process must be a +@@ -1297,6 +1299,8 @@ + @comment termios.h + @comment Unix98 + @deftypefun pid_t tcgetsid (int @var{fildes}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Ioctl call, if available, or tcgetpgrp followed by getsid. + This function is used to obtain the process group ID of the session + for which the terminal specified by @var{fildes} is the controlling terminal. + If the call is successful the group ID is returned. Otherwise the +diff -urN glibc-2.17-c758a686/manual/lang.texi glibc-2.17-c758a686/manual/lang.texi +--- glibc-2.17-c758a686/manual/lang.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/lang.texi 2014-09-12 16:10:06.045792717 -0400 +@@ -51,6 +51,8 @@ + @comment assert.h + @comment ISO + @deftypefn Macro void assert (int @var{expression}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @asucorrupt{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}} ++@c assert_fail_base calls asprintf, and fflushes stderr. + Verify the programmer's belief that @var{expression} is nonzero at + this point in the program. + +@@ -91,6 +93,8 @@ + @comment assert.h + @comment GNU + @deftypefn Macro void assert_perror (int @var{errnum}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @asucorrupt{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}} ++@c assert_fail_base calls asprintf, and fflushes stderr. + Similar to @code{assert}, but verifies that @var{errnum} is zero. + + If @code{NDEBUG} is not defined, @code{assert_perror} tests the value of +@@ -423,6 +427,8 @@ + @comment stdarg.h + @comment ISO + @deftypefn {Macro} void va_start (va_list @var{ap}, @var{last-required}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c This is no longer provided by glibc, but rather by the compiler. + This macro initializes the argument pointer variable @var{ap} to point + to the first of the optional arguments of the current function; + @var{last-required} must be the last required argument to the function. +@@ -431,6 +437,11 @@ + @comment stdarg.h + @comment ISO + @deftypefn {Macro} @var{type} va_arg (va_list @var{ap}, @var{type}) ++@safety{@prelim{}@mtsafe{@mtsrace{:ap}}@assafe{}@acunsafe{@acucorrupt{}}} ++@c This is no longer provided by glibc, but rather by the compiler. ++@c Unlike the other va_ macros, that either start/end the lifetime of ++@c the va_list object or don't modify it, this one modifies ap, and it ++@c may leave it in a partially updated state. + The @code{va_arg} macro returns the value of the next optional argument, + and modifies the value of @var{ap} to point to the subsequent argument. + Thus, successive uses of @code{va_arg} return successive optional +@@ -445,6 +456,8 @@ + @comment stdarg.h + @comment ISO + @deftypefn {Macro} void va_end (va_list @var{ap}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c This is no longer provided by glibc, but rather by the compiler. + This ends the use of @var{ap}. After a @code{va_end} call, further + @code{va_arg} calls with the same @var{ap} may not work. You should invoke + @code{va_end} before returning from the function in which @code{va_start} +@@ -466,6 +479,8 @@ + @comment ISO + @deftypefn {Macro} void va_copy (va_list @var{dest}, va_list @var{src}) + @deftypefnx {Macro} void __va_copy (va_list @var{dest}, va_list @var{src}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c This is no longer provided by glibc, but rather by the compiler. + The @code{va_copy} macro allows copying of objects of type + @code{va_list} even if this is not an integral type. The argument pointer + in @var{dest} is initialized to point to the same argument as the +@@ -1212,7 +1227,9 @@ + @comment stddef.h + @comment ISO + @deftypefn {Macro} size_t offsetof (@var{type}, @var{member}) +-This expands to a integer constant expression that is the offset of the ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c This is no longer provided by glibc, but rather by the compiler. ++This expands to an integer constant expression that is the offset of the + structure member named @var{member} in the structure type @var{type}. + For example, @code{offsetof (struct s, elem)} is the offset, in bytes, + of the member @code{elem} in a @code{struct s}. +diff -urN glibc-2.17-c758a686/manual/libc.texinfo glibc-2.17-c758a686/manual/libc.texinfo +--- glibc-2.17-c758a686/manual/libc.texinfo 2014-09-12 16:08:17.677071123 -0400 ++++ glibc-2.17-c758a686/manual/libc.texinfo 2014-09-12 16:10:25.996741462 -0400 +@@ -7,7 +7,7 @@ + @include macros.texi + + @comment Tell install-info what to do. +-@dircategory Libraries ++@dircategory Software libraries + @direntry + * Libc: (libc). C library. + @end direntry +@@ -46,7 +46,7 @@ + @value{VERSION} @value{PKGVERSION}. + @end ifclear + +-Copyright @copyright{} 1993--2012 Free Software Foundation, Inc. ++Copyright @copyright{} 1993--2014 Free Software Foundation, Inc. + + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version +@@ -118,6 +118,7 @@ + @include chapters.texi + + @node Free Manuals, Copying, Contributors, Top ++@appendix Free Software Needs Free Documentation + @include freemanuals.texi + + @node Copying, Documentation License, Free Manuals, Top +diff -urN glibc-2.17-c758a686/manual/libc-texinfo.sh glibc-2.17-c758a686/manual/libc-texinfo.sh +--- glibc-2.17-c758a686/manual/libc-texinfo.sh 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/libc-texinfo.sh 2014-09-12 16:10:06.042792724 -0400 +@@ -91,9 +91,11 @@ + * Variable Index:: Index of variables and variable-like macros. + * File Index:: Index of programs and files. + ++ @detailmenu + --- The Detailed Node Listing --- + EOF + cat ${OUTDIR}lmenu.$$ ++ echo '@end detailmenu' + echo '@end menu'; } >${OUTDIR}top-menu.texi.$$ + mv -f ${OUTDIR}top-menu.texi.$$ ${OUTDIR}top-menu.texi + +diff -urN glibc-2.17-c758a686/manual/libdl.texi glibc-2.17-c758a686/manual/libdl.texi +--- glibc-2.17-c758a686/manual/libdl.texi 1969-12-31 19:00:00.000000000 -0500 ++++ glibc-2.17-c758a686/manual/libdl.texi 2014-09-12 16:10:06.045792717 -0400 +@@ -0,0 +1,10 @@ ++@c FIXME these are undocumented: ++@c dladdr ++@c dladdr1 ++@c dlclose ++@c dlerror ++@c dlinfo ++@c dlmopen ++@c dlopen ++@c dlsym ++@c dlvsym +diff -urN glibc-2.17-c758a686/manual/llio.texi glibc-2.17-c758a686/manual/llio.texi +--- glibc-2.17-c758a686/manual/llio.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/llio.texi 2014-09-12 16:10:06.047792712 -0400 +@@ -78,6 +82,7 @@ + @comment fcntl.h + @comment POSIX.1 + @deftypefun int open (const char *@var{filename}, int @var{flags}[, mode_t @var{mode}]) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{@acsfd{}}} + The @code{open} function creates and returns a new file descriptor for + the file named by @var{filename}. Initially, the file position + indicator for the file is at the beginning of the file. The argument +@@ -164,6 +169,7 @@ + @comment fcntl.h + @comment Unix98 + @deftypefun int open64 (const char *@var{filename}, int @var{flags}[, mode_t @var{mode}]) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{@acsfd{}}} + This function is similar to @code{open}. It returns a file descriptor + which can be used to access the file named by @var{filename}. The only + difference is that on 32 bit systems the file is opened in the +@@ -178,6 +184,7 @@ + @comment fcntl.h + @comment POSIX.1 + @deftypefn {Obsolete function} int creat (const char *@var{filename}, mode_t @var{mode}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{@acsfd{}}} + This function is obsolete. The call: + + @smallexample +@@ -202,6 +209,7 @@ + @comment fcntl.h + @comment Unix98 + @deftypefn {Obsolete function} int creat64 (const char *@var{filename}, mode_t @var{mode}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{@acsfd{}}} + This function is similar to @code{creat}. It returns a file descriptor + which can be used to access the file named by @var{filename}. The only + the difference is that on 32 bit systems the file is opened in the +@@ -219,6 +227,7 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun int close (int @var{filedes}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{@acsfd{}}} + The function @code{close} closes the file descriptor @var{filedes}. + Closing a file has the following consequences: + +@@ -300,6 +309,7 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun ssize_t read (int @var{filedes}, void *@var{buffer}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{read} function reads up to @var{size} bytes from the file + with descriptor @var{filedes}, storing the results in the @var{buffer}. + (This is not necessarily a character string, and no terminating null +@@ -395,6 +405,10 @@ + @comment unistd.h + @comment Unix98 + @deftypefun ssize_t pread (int @var{filedes}, void *@var{buffer}, size_t @var{size}, off_t @var{offset}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c This is usually a safe syscall. The sysdeps/posix fallback emulation ++@c is not MT-Safe because it uses lseek, read and lseek back, but is it ++@c used anywhere? + The @code{pread} function is similar to the @code{read} function. The + first three arguments are identical, and the return values and error + codes also correspond. +@@ -430,6 +444,10 @@ + @comment unistd.h + @comment Unix98 + @deftypefun ssize_t pread64 (int @var{filedes}, void *@var{buffer}, size_t @var{size}, off64_t @var{offset}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c This is usually a safe syscall. The sysdeps/posix fallback emulation ++@c is not MT-Safe because it uses lseek64, read and lseek64 back, but is ++@c it used anywhere? + This function is similar to the @code{pread} function. The difference + is that the @var{offset} parameter is of type @code{off64_t} instead of + @code{off_t} which makes it possible on 32 bit machines to address +@@ -447,6 +465,7 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun ssize_t write (int @var{filedes}, const void *@var{buffer}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{write} function writes up to @var{size} bytes from + @var{buffer} to the file with descriptor @var{filedes}. The data in + @var{buffer} is not necessarily a character string and a null character is +@@ -557,6 +576,10 @@ + @comment unistd.h + @comment Unix98 + @deftypefun ssize_t pwrite (int @var{filedes}, const void *@var{buffer}, size_t @var{size}, off_t @var{offset}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c This is usually a safe syscall. The sysdeps/posix fallback emulation ++@c is not MT-Safe because it uses lseek, write and lseek back, but is it ++@c used anywhere? + The @code{pwrite} function is similar to the @code{write} function. The + first three arguments are identical, and the return values and error codes + also correspond. +@@ -592,6 +615,10 @@ + @comment unistd.h + @comment Unix98 + @deftypefun ssize_t pwrite64 (int @var{filedes}, const void *@var{buffer}, size_t @var{size}, off64_t @var{offset}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c This is usually a safe syscall. The sysdeps/posix fallback emulation ++@c is not MT-Safe because it uses lseek64, write and lseek64 back, but ++@c is it used anywhere? + This function is similar to the @code{pwrite} function. The difference + is that the @var{offset} parameter is of type @code{off64_t} instead of + @code{off_t} which makes it possible on 32 bit machines to address +@@ -624,6 +651,7 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun off_t lseek (int @var{filedes}, off_t @var{offset}, int @var{whence}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{lseek} function is used to change the file position of the + file with descriptor @var{filedes}. + +@@ -713,6 +741,7 @@ + @comment unistd.h + @comment Unix98 + @deftypefun off64_t lseek64 (int @var{filedes}, off64_t @var{offset}, int @var{whence}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function is similar to the @code{lseek} function. The difference + is that the @var{offset} parameter is of type @code{off64_t} instead of + @code{off_t} which makes it possible on 32 bit machines to address +@@ -825,6 +854,7 @@ + @comment stdio.h + @comment POSIX.1 + @deftypefun {FILE *} fdopen (int @var{filedes}, const char *@var{opentype}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@acsmem{} @aculock{}}} + The @code{fdopen} function returns a new stream for the file descriptor + @var{filedes}. + +@@ -853,6 +883,7 @@ + @comment stdio.h + @comment POSIX.1 + @deftypefun int fileno (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function returns the file descriptor associated with the stream + @var{stream}. If an error is detected (for example, if the @var{stream} + is not valid) or if @var{stream} does not do I/O to a file, +@@ -862,6 +893,7 @@ + @comment stdio.h + @comment GNU + @deftypefun int fileno_unlocked (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{fileno_unlocked} function is equivalent to the @code{fileno} + function except that it does not implicitly lock the stream if the state + is @code{FSETLOCKING_INTERNAL}. +@@ -1055,7 +1087,7 @@ + @comment BSD + @deftp {Data Type} {struct iovec} + +-The @code{iovec} structure describes a buffer. It contains two fields: ++The @code{iovec} structure describes a buffer. It contains two fields: + + @table @code + +@@ -1071,6 +1103,11 @@ + @comment sys/uio.h + @comment BSD + @deftypefun ssize_t readv (int @var{filedes}, const struct iovec *@var{vector}, int @var{count}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} ++@c The fallback sysdeps/posix implementation, used even on GNU/Linux ++@c with old kernels that lack a full readv/writev implementation, may ++@c malloc the buffer into which data is read, if the total read size is ++@c too large for alloca. + + The @code{readv} function reads data from @var{filedes} and scatters it + into the buffers described in @var{vector}, which is taken to be +@@ -1089,6 +1126,11 @@ + @comment sys/uio.h + @comment BSD + @deftypefun ssize_t writev (int @var{filedes}, const struct iovec *@var{vector}, int @var{count}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} ++@c The fallback sysdeps/posix implementation, used even on GNU/Linux ++@c with old kernels that lack a full readv/writev implementation, may ++@c malloc the buffer from which data is written, if the total write size ++@c is too large for alloca. + + The @code{writev} function gathers data from the buffers described in + @var{vector}, which is taken to be @var{count} structures long, and writes +@@ -1103,8 +1145,8 @@ + + @end deftypefun + +-@c Note - I haven't read this anywhere. I surmised it from my knowledge +-@c of computer science. Thus, there could be subtleties I'm missing. ++@c Note - I haven't read this anywhere. I surmised it from my knowledge ++@c of computer science. Thus, there could be subtleties I'm missing. + + Note that if the buffers are small (under about 1kB), high-level streams + may be easier to use than these functions. However, @code{readv} and +@@ -1149,6 +1191,7 @@ + @comment sys/mman.h + @comment POSIX + @deftypefun {void *} mmap (void *@var{address}, size_t @var{length}, int @var{protect}, int @var{flags}, int @var{filedes}, off_t @var{offset}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + + The @code{mmap} function creates a new mapping, connected to bytes + (@var{offset}) to (@var{offset} + @var{length} - 1) in the file open on +@@ -1156,8 +1199,8 @@ + is created, which is not removed by closing the file. + + @var{address} gives a preferred starting address for the mapping. +-@code{NULL} expresses no preference. Any previous mapping at that +-address is automatically removed. The address you give may still be ++@code{NULL} expresses no preference. Any previous mapping at that ++address is automatically removed. The address you give may still be + changed, unless you use the @code{MAP_FIXED} flag. + + @vindex PROT_READ +@@ -1221,13 +1264,13 @@ + + @c Linux has some other MAP_ options, which I have not discussed here. + @c MAP_DENYWRITE, MAP_EXECUTABLE and MAP_GROWSDOWN don't seem applicable to +-@c user programs (and I don't understand the last two). MAP_LOCKED does ++@c user programs (and I don't understand the last two). MAP_LOCKED does + @c not appear to be implemented. + + @end vtable + +-@code{mmap} returns the address of the new mapping, or @math{-1} for an +-error. ++@code{mmap} returns the address of the new mapping, or ++@code{MAP_FAILED} for an error. + + Possible errors include: + +@@ -1268,6 +1311,9 @@ + @comment sys/mman.h + @comment LFS + @deftypefun {void *} mmap64 (void *@var{address}, size_t @var{length}, int @var{protect}, int @var{flags}, int @var{filedes}, off64_t @var{offset}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c The page_shift auto detection when MMAP2_PAGE_SHIFT is -1 (it never ++@c is) would be thread-unsafe. + The @code{mmap64} function is equivalent to the @code{mmap} function but + the @var{offset} parameter is of type @code{off64_t}. On 32-bit systems + this allows the file associated with the @var{filedes} descriptor to be +@@ -1284,6 +1330,7 @@ + @comment sys/mman.h + @comment POSIX + @deftypefun int munmap (void *@var{addr}, size_t @var{length}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + + @code{munmap} removes any memory maps from (@var{addr}) to (@var{addr} + + @var{length}). @var{length} should be the length of the mapping. +@@ -1310,6 +1357,7 @@ + @comment sys/mman.h + @comment POSIX + @deftypefun int msync (void *@var{address}, size_t @var{length}, int @var{flags}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + + When using shared mappings, the kernel can write the file at any time + before the mapping is removed. To be certain data has actually been +@@ -1357,17 +1405,18 @@ + @comment sys/mman.h + @comment GNU + @deftypefun {void *} mremap (void *@var{address}, size_t @var{length}, size_t @var{new_length}, int @var{flag}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + + This function can be used to change the size of an existing memory + area. @var{address} and @var{length} must cover a region entirely mapped +-in the same @code{mmap} statement. A new mapping with the same ++in the same @code{mmap} statement. A new mapping with the same + characteristics will be returned with the length @var{new_length}. + +-One option is possible, @code{MREMAP_MAYMOVE}. If it is given in ++One option is possible, @code{MREMAP_MAYMOVE}. If it is given in + @var{flags}, the system may remove the existing mapping and create a new + one of the desired length in another location. + +-The address of the resulting mapping is returned, or @math{-1}. Possible ++The address of the resulting mapping is returned, or @math{-1}. Possible + error codes include: + + @table @code +@@ -1405,6 +1454,7 @@ + @comment sys/mman.h + @comment POSIX + @deftypefun int madvise (void *@var{addr}, size_t @var{length}, int @var{advice}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + + This function can be used to provide the system with @var{advice} about + the intended usage patterns of the memory region starting at @var{addr} +@@ -1418,11 +1468,11 @@ + The region should receive no further special treatment. + + @item MADV_RANDOM +-The region will be accessed via random page references. The kernel ++The region will be accessed via random page references. The kernel + should page-in the minimal number of pages for each page fault. + + @item MADV_SEQUENTIAL +-The region will be accessed via sequential page references. This ++The region will be accessed via sequential page references. This + may cause the kernel to aggressively read-ahead, expecting further + sequential references after any page fault within this region. + +@@ -1471,6 +1521,58 @@ + @end table + @end deftypefun + ++@comment sys/mman.h ++@comment POSIX ++@deftypefn Function int shm_open (const char *@var{name}, int @var{oflag}, mode_t @var{mode}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asuinit{} @ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsmem{} @acsfd{}}} ++@c shm_open @mtslocale @asuinit @ascuheap @asulock @aculock @acsmem @acsfd ++@c libc_once(where_is_shmfs) @mtslocale @asuinit @ascuheap @asulock @aculock @acsmem @acsfd ++@c where_is_shmfs @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c statfs dup ok ++@c setmntent dup @ascuheap @asulock @acsmem @acsfd @aculock ++@c getmntent_r dup @mtslocale @ascuheap @aculock @acsmem [no @asucorrupt @acucorrupt; exclusive stream] ++@c strcmp dup ok ++@c strlen dup ok ++@c malloc dup @ascuheap @acsmem ++@c mempcpy dup ok ++@c endmntent dup @ascuheap @asulock @aculock @acsmem @acsfd ++@c strlen dup ok ++@c strchr dup ok ++@c mempcpy dup ok ++@c open dup @acsfd ++@c fcntl dup ok ++@c close dup @acsfd ++ ++This function returns a file descriptor that can be used to allocate shared ++memory via mmap. Unrelated processes can use same @var{name} to create or ++open existing shared memory objects. ++ ++A @var{name} argument specifies the shared memory object to be opened. ++In @theglibc{} it must be a string smaller than @code{NAME_MAX} bytes starting ++with an optional slash but containing no other slashes. ++ ++The semantics of @var{oflag} and @var{mode} arguments is same as in @code{open}. ++ ++@code{shm_open} returns the file descriptor on success or @math{-1} on error. ++On failure @code{errno} is set. ++@end deftypefn ++ ++@deftypefn Function int shm_unlink (const char *@var{name}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asuinit{} @ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsmem{} @acsfd{}}} ++@c shm_unlink @mtslocale @asuinit @ascuheap @asulock @aculock @acsmem @acsfd ++@c libc_once(where_is_shmfs) dup @mtslocale @asuinit @ascuheap @asulock @aculock @acsmem @acsfd ++@c strlen dup ok ++@c strchr dup ok ++@c mempcpy dup ok ++@c unlink dup ok ++ ++This function is inverse of @code{shm_open} and removes the object with ++the given @var{name} previously created by @code{shm_open}. ++ ++@code{shm_unlink} returns @math{0} on success or @math{-1} on error. ++On failure @code{errno} is set. ++@end deftypefn ++ + @node Waiting for I/O + @section Waiting for Input or Output + @cindex waiting for input or output +@@ -1531,6 +1633,7 @@ + @comment sys/types.h + @comment BSD + @deftypefn Macro void FD_ZERO (fd_set *@var{set}) ++@safety{@prelim{}@mtsafe{@mtsrace{:set}}@assafe{}@acsafe{}} + This macro initializes the file descriptor set @var{set} to be the + empty set. + @end deftypefn +@@ -1538,6 +1641,9 @@ + @comment sys/types.h + @comment BSD + @deftypefn Macro void FD_SET (int @var{filedes}, fd_set *@var{set}) ++@safety{@prelim{}@mtsafe{@mtsrace{:set}}@assafe{}@acsafe{}} ++@c Setting a bit isn't necessarily atomic, so there's a potential race ++@c here if set is not used exclusively. + This macro adds @var{filedes} to the file descriptor set @var{set}. + + The @var{filedes} parameter must not have side effects since it is +@@ -1547,6 +1653,9 @@ + @comment sys/types.h + @comment BSD + @deftypefn Macro void FD_CLR (int @var{filedes}, fd_set *@var{set}) ++@safety{@prelim{}@mtsafe{@mtsrace{:set}}@assafe{}@acsafe{}} ++@c Setting a bit isn't necessarily atomic, so there's a potential race ++@c here if set is not used exclusively. + This macro removes @var{filedes} from the file descriptor set @var{set}. + + The @var{filedes} parameter must not have side effects since it is +@@ -1556,6 +1665,7 @@ + @comment sys/types.h + @comment BSD + @deftypefn Macro int FD_ISSET (int @var{filedes}, const fd_set *@var{set}) ++@safety{@prelim{}@mtsafe{@mtsrace{:set}}@assafe{}@acsafe{}} + This macro returns a nonzero value (true) if @var{filedes} is a member + of the file descriptor set @var{set}, and zero (false) otherwise. + +@@ -1568,6 +1678,10 @@ + @comment sys/types.h + @comment BSD + @deftypefun int select (int @var{nfds}, fd_set *@var{read-fds}, fd_set *@var{write-fds}, fd_set *@var{except-fds}, struct timeval *@var{timeout}) ++@safety{@prelim{}@mtsafe{@mtsrace{:read-fds} @mtsrace{:write-fds} @mtsrace{:except-fds}}@assafe{}@acsafe{}} ++@c The select syscall is preferred, but pselect6 may be used instead, ++@c which requires converting timeout to a timespec and back. The ++@c conversions are not atomic. + The @code{select} function blocks the calling process until there is + activity on any of the specified sets of file descriptors, or until the + timeout period has expired. +@@ -1669,15 +1783,14 @@ + + @comment unistd.h + @comment X/Open +-@deftypefun int sync (void) ++@deftypefun void sync (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + A call to this function will not return as long as there is data which + has not been written to the device. All dirty buffers in the kernel will + be written and so an overall consistent system can be achieved (if no + other process in parallel writes data). + + A prototype for @code{sync} can be found in @file{unistd.h}. +- +-The return value is zero to indicate no error. + @end deftypefun + + Programs more often want to ensure that data written to a given file is +@@ -1687,6 +1800,7 @@ + @comment unistd.h + @comment POSIX + @deftypefun int fsync (int @var{fildes}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{fsync} function can be used to make sure all data associated with + the open file @var{fildes} is written to the device associated with the + descriptor. The function call does not return unless all actions have +@@ -1724,6 +1838,7 @@ + @comment unistd.h + @comment POSIX + @deftypefun int fdatasync (int @var{fildes}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + When a call to the @code{fdatasync} function returns, it is ensured + that all of the file data is written to the device. For all pending I/O + operations, the parts guaranteeing data integrity finished. +@@ -1925,6 +2040,158 @@ + @comment aio.h + @comment POSIX.1b + @deftypefun int aio_read (struct aiocb *@var{aiocbp}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsmem{}}} ++@c Calls aio_enqueue_request. ++@c aio_enqueue_request @asulock @ascuheap @aculock @acsmem ++@c pthread_self ok ++@c pthread_getschedparam @asulock @aculock ++@c lll_lock (pthread descriptor's lock) @asulock @aculock ++@c sched_getparam ok ++@c sched_getscheduler ok ++@c lll_unlock @aculock ++@c pthread_mutex_lock (aio_requests_mutex) @asulock @aculock ++@c get_elem @ascuheap @acsmem [@asucorrupt @acucorrupt] ++@c realloc @ascuheap @acsmem ++@c calloc @ascuheap @acsmem ++@c aio_create_helper_thread @asulock @ascuheap @aculock @acsmem ++@c pthread_attr_init ok ++@c pthread_attr_setdetachstate ok ++@c pthread_get_minstack ok ++@c pthread_attr_setstacksize ok ++@c sigfillset ok ++@c memset ok ++@c sigdelset ok ++@c SYSCALL rt_sigprocmask ok ++@c pthread_create @asulock @ascuheap @aculock @acsmem ++@c lll_lock (default_pthread_attr_lock) @asulock @aculock ++@c alloca/malloc @ascuheap @acsmem ++@c lll_unlock @aculock ++@c allocate_stack @asulock @ascuheap @aculock @acsmem ++@c getpagesize dup ++@c lll_lock (default_pthread_attr_lock) @asulock @aculock ++@c lll_unlock @aculock ++@c _dl_allocate_tls @ascuheap @acsmem ++@c _dl_allocate_tls_storage @ascuheap @acsmem ++@c memalign @ascuheap @acsmem ++@c memset ok ++@c allocate_dtv dup ++@c free @ascuheap @acsmem ++@c allocate_dtv @ascuheap @acsmem ++@c calloc @ascuheap @acsmem ++@c INSTALL_DTV ok ++@c list_add dup ++@c get_cached_stack ++@c lll_lock (stack_cache_lock) @asulock @aculock ++@c list_for_each ok ++@c list_entry dup ++@c FREE_P dup ++@c stack_list_del dup ++@c stack_list_add dup ++@c lll_unlock @aculock ++@c _dl_allocate_tls_init ok ++@c GET_DTV ok ++@c mmap ok ++@c atomic_increment_val ok ++@c munmap ok ++@c change_stack_perm ok ++@c mprotect ok ++@c mprotect ok ++@c stack_list_del dup ++@c _dl_deallocate_tls dup ++@c munmap ok ++@c THREAD_COPY_STACK_GUARD ok ++@c THREAD_COPY_POINTER_GUARD ok ++@c atomic_exchange_acq ok ++@c lll_futex_wake ok ++@c deallocate_stack @asulock @ascuheap @aculock @acsmem ++@c lll_lock (state_cache_lock) @asulock @aculock ++@c stack_list_del ok ++@c atomic_write_barrier ok ++@c list_del ok ++@c atomic_write_barrier ok ++@c queue_stack @ascuheap @acsmem ++@c stack_list_add ok ++@c atomic_write_barrier ok ++@c list_add ok ++@c atomic_write_barrier ok ++@c free_stacks @ascuheap @acsmem ++@c list_for_each_prev_safe ok ++@c list_entry ok ++@c FREE_P ok ++@c stack_list_del dup ++@c _dl_deallocate_tls dup ++@c munmap ok ++@c _dl_deallocate_tls @ascuheap @acsmem ++@c free @ascuheap @acsmem ++@c lll_unlock @aculock ++@c create_thread @asulock @ascuheap @aculock @acsmem ++@c td_eventword ++@c td_eventmask ++@c do_clone @asulock @ascuheap @aculock @acsmem ++@c PREPARE_CREATE ok ++@c lll_lock (pd->lock) @asulock @aculock ++@c atomic_increment ok ++@c clone ok ++@c atomic_decrement ok ++@c atomic_exchange_acq ok ++@c lll_futex_wake ok ++@c deallocate_stack dup ++@c sched_setaffinity ok ++@c tgkill ok ++@c sched_setscheduler ok ++@c atomic_compare_and_exchange_bool_acq ok ++@c nptl_create_event ok ++@c lll_unlock (pd->lock) @aculock ++@c free @ascuheap @acsmem ++@c pthread_attr_destroy ok (cpuset won't be set, so free isn't called) ++@c add_request_to_runlist ok ++@c pthread_cond_signal ok ++@c aio_free_request ok ++@c pthread_mutex_unlock @aculock ++ ++@c (in the new thread, initiated with clone) ++@c start_thread ok ++@c HP_TIMING_NOW ok ++@c ctype_init @mtslocale ++@c atomic_exchange_acq ok ++@c lll_futex_wake ok ++@c sigemptyset ok ++@c sigaddset ok ++@c setjmp ok ++@c CANCEL_ASYNC -> pthread_enable_asynccancel ok ++@c do_cancel ok ++@c pthread_unwind ok ++@c Unwind_ForcedUnwind or longjmp ok [@ascuheap @acsmem?] ++@c lll_lock @asulock @aculock ++@c lll_unlock @asulock @aculock ++@c CANCEL_RESET -> pthread_disable_asynccancel ok ++@c lll_futex_wait ok ++@c ->start_routine ok ----- ++@c call_tls_dtors @asulock @ascuheap @aculock @acsmem ++@c user-supplied dtor ++@c rtld_lock_lock_recursive (dl_load_lock) @asulock @aculock ++@c rtld_lock_unlock_recursive @aculock ++@c free @ascuheap @acsmem ++@c nptl_deallocate_tsd @ascuheap @acsmem ++@c tsd user-supplied dtors ok ++@c free @ascuheap @acsmem ++@c libc_thread_freeres ++@c libc_thread_subfreeres ok ++@c atomic_decrement_and_test ok ++@c td_eventword ok ++@c td_eventmask ok ++@c atomic_compare_exchange_bool_acq ok ++@c nptl_death_event ok ++@c lll_robust_dead ok ++@c getpagesize ok ++@c madvise ok ++@c free_tcb @asulock @ascuheap @aculock @acsmem ++@c free @ascuheap @acsmem ++@c deallocate_stack @asulock @ascuheap @aculock @acsmem ++@c lll_futex_wait ok ++@c exit_thread_inline ok ++@c syscall(exit) ok ++ + This function initiates an asynchronous read operation. It + immediately returns after the operation was enqueued or when an + error was encountered. +@@ -1989,7 +2256,8 @@ + + @comment aio.h + @comment Unix98 +-@deftypefun int aio_read64 (struct aiocb *@var{aiocbp}) ++@deftypefun int aio_read64 (struct aiocb64 *@var{aiocbp}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsmem{}}} + This function is similar to the @code{aio_read} function. The only + difference is that on @w{32 bit} machines, the file descriptor should + be opened in the large file mode. Internally, @code{aio_read64} uses +@@ -2008,13 +2276,14 @@ + @comment aio.h + @comment POSIX.1b + @deftypefun int aio_write (struct aiocb *@var{aiocbp}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsmem{}}} + This function initiates an asynchronous write operation. The function + call immediately returns after the operation was enqueued or if before + this happens an error was encountered. + + The first @code{aiocbp->aio_nbytes} bytes from the buffer starting at + @code{aiocbp->aio_buf} are written to the file for which +-@code{aiocbp->aio_fildes} is an descriptor, starting at the absolute ++@code{aiocbp->aio_fildes} is a descriptor, starting at the absolute + position @code{aiocbp->aio_offset} in the file. + + If prioritized I/O is supported by the platform, the +@@ -2073,7 +2342,8 @@ + + @comment aio.h + @comment Unix98 +-@deftypefun int aio_write64 (struct aiocb *@var{aiocbp}) ++@deftypefun int aio_write64 (struct aiocb64 *@var{aiocbp}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsmem{}}} + This function is similar to the @code{aio_write} function. The only + difference is that on @w{32 bit} machines the file descriptor should + be opened in the large file mode. Internally @code{aio_write64} uses +@@ -2095,6 +2365,12 @@ + @comment aio.h + @comment POSIX.1b + @deftypefun int lio_listio (int @var{mode}, struct aiocb *const @var{list}[], int @var{nent}, struct sigevent *@var{sig}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsmem{}}} ++@c Call lio_listio_internal, that takes the aio_requests_mutex lock and ++@c enqueues each request. Then, it waits for notification or prepares ++@c for it before releasing the lock. Even though it performs memory ++@c allocation and locking of its own, it doesn't add any classes of ++@c safety issues that aren't already covered by aio_enqueue_request. + The @code{lio_listio} function can be used to enqueue an arbitrary + number of read and write requests at one time. The requests can all be + meant for the same file, all for different files or every solution in +@@ -2177,7 +2453,8 @@ + + @comment aio.h + @comment Unix98 +-@deftypefun int lio_listio64 (int @var{mode}, struct aiocb *const @var{list}, int @var{nent}, struct sigevent *@var{sig}) ++@deftypefun int lio_listio64 (int @var{mode}, struct aiocb64 *const @var{list}[], int @var{nent}, struct sigevent *@var{sig}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsmem{}}} + This function is similar to the @code{lio_listio} function. The only + difference is that on @w{32 bit} machines, the file descriptor should + be opened in the large file mode. Internally, @code{lio_listio64} uses +@@ -2206,6 +2483,7 @@ + @comment aio.h + @comment POSIX.1b + @deftypefun int aio_error (const struct aiocb *@var{aiocbp}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function determines the error state of the request described by the + @code{struct aiocb} variable pointed to by @var{aiocbp}. If the + request has not yet terminated the value returned is always +@@ -2227,6 +2505,7 @@ + @comment aio.h + @comment Unix98 + @deftypefun int aio_error64 (const struct aiocb64 *@var{aiocbp}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function is similar to @code{aio_error} with the only difference + that the argument is a reference to a variable of type @code{struct + aiocb64}. +@@ -2239,7 +2518,8 @@ + + @comment aio.h + @comment POSIX.1b +-@deftypefun ssize_t aio_return (const struct aiocb *@var{aiocbp}) ++@deftypefun ssize_t aio_return (struct aiocb *@var{aiocbp}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function can be used to retrieve the return status of the operation + carried out by the request described in the variable pointed to by + @var{aiocbp}. As long as the error status of this request as returned +@@ -2262,7 +2542,8 @@ + + @comment aio.h + @comment Unix98 +-@deftypefun int aio_return64 (const struct aiocb64 *@var{aiocbp}) ++@deftypefun ssize_t aio_return64 (struct aiocb64 *@var{aiocbp}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function is similar to @code{aio_return} with the only difference + that the argument is a reference to a variable of type @code{struct + aiocb64}. +@@ -2291,6 +2572,9 @@ + @comment aio.h + @comment POSIX.1b + @deftypefun int aio_fsync (int @var{op}, struct aiocb *@var{aiocbp}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsmem{}}} ++@c After fcntl to check that the FD is open, it calls ++@c aio_enqueue_request. + Calling this function forces all I/O operations operating queued at the + time of the function call operating on the file descriptor + @code{aiocbp->aio_fildes} into the synchronized I/O completion state +@@ -2322,8 +2606,7 @@ + @item EAGAIN + The request could not be enqueued due to temporary lack of resources. + @item EBADF +-The file descriptor @code{aiocbp->aio_fildes} is not valid or not open +-for writing. ++The file descriptor @code{@var{aiocbp}->aio_fildes} is not valid. + @item EINVAL + The implementation does not support I/O synchronization or the @var{op} + parameter is other than @code{O_DSYNC} and @code{O_SYNC}. +@@ -2339,6 +2622,7 @@ + @comment aio.h + @comment Unix98 + @deftypefun int aio_fsync64 (int @var{op}, struct aiocb64 *@var{aiocbp}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsmem{}}} + This function is similar to @code{aio_fsync} with the only difference + that the argument is a reference to a variable of type @code{struct + aiocb64}. +@@ -2365,6 +2649,9 @@ + @comment aio.h + @comment POSIX.1b + @deftypefun int aio_suspend (const struct aiocb *const @var{list}[], int @var{nent}, const struct timespec *@var{timeout}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} ++@c Take aio_requests_mutex, set up waitlist and requestlist, wait ++@c for completion or timeout, and release the mutex. + When calling this function, the calling thread is suspended until at + least one of the requests pointed to by the @var{nent} elements of the + array @var{list} has completed. If any of the requests has already +@@ -2403,6 +2690,7 @@ + @comment aio.h + @comment Unix98 + @deftypefun int aio_suspend64 (const struct aiocb64 *const @var{list}[], int @var{nent}, const struct timespec *@var{timeout}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} + This function is similar to @code{aio_suspend} with the only difference + that the argument is a reference to a variable of type @code{struct + aiocb64}. +@@ -2430,6 +2718,16 @@ + @comment aio.h + @comment POSIX.1b + @deftypefun int aio_cancel (int @var{fildes}, struct aiocb *@var{aiocbp}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsmem{}}} ++@c After fcntl to check the fd is open, hold aio_requests_mutex, call ++@c aio_find_req_fd, aio_remove_request, then aio_notify and ++@c aio_free_request each request before releasing the lock. ++@c aio_notify calls aio_notify_only and free, besides cond signal or ++@c similar. aio_notify_only calls pthread_attr_init, ++@c pthread_attr_setdetachstate, malloc, pthread_create, ++@c notify_func_wrapper, aio_sigqueue, getpid, raise. ++@c notify_func_wraper calls aio_start_notify_thread, free and then the ++@c notifier function. + The @code{aio_cancel} function can be used to cancel one or more + outstanding requests. If the @var{aiocbp} parameter is @code{NULL}, the + function tries to cancel all of the outstanding requests which would process +@@ -2477,6 +2775,7 @@ + @comment aio.h + @comment Unix98 + @deftypefun int aio_cancel64 (int @var{fildes}, struct aiocb64 *@var{aiocbp}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsmem{}}} + This function is similar to @code{aio_cancel} with the only difference + that the argument is a reference to a variable of type @code{struct + aiocb64}. +@@ -2532,6 +2831,8 @@ + @comment aio.h + @comment GNU + @deftypefun void aio_init (const struct aioinit *@var{init}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} ++@c All changes to global objects are guarded by aio_requests_mutex. + This function must be called before any other AIO function. Calling it + is completely voluntary, as it is only meant to help the AIO + implementation perform better. +@@ -2566,6 +2867,7 @@ + @comment fcntl.h + @comment POSIX.1 + @deftypefun int fcntl (int @var{filedes}, int @var{command}, @dots{}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{fcntl} function performs the operation specified by + @var{command} on the file descriptor @var{filedes}. Some commands + require additional arguments to be supplied. These additional arguments +@@ -2592,7 +2894,7 @@ + Set flags associated with the open file. @xref{File Status Flags}. + + @item F_GETLK +-Get a file lock. @xref{File Locks}. ++Test a file lock. @xref{File Locks}. + + @item F_SETLK + Set or clear a file lock. @xref{File Locks}. +@@ -2648,6 +2962,7 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun int dup (int @var{old}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function copies descriptor @var{old} to the first available + descriptor number (the first number not currently open). It is + equivalent to @code{fcntl (@var{old}, F_DUPFD, 0)}. +@@ -2656,6 +2971,7 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun int dup2 (int @var{old}, int @var{new}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function copies the descriptor @var{old} to descriptor number + @var{new}. + +@@ -2929,19 +3245,19 @@ + But most programs will want to be portable to other POSIX.1 systems and + should use the POSIX.1 names above instead. + +-@comment fcntl.h ++@comment fcntl.h (optional) + @comment GNU + @deftypevr Macro int O_READ + Open the file for reading. Same as @code{O_RDONLY}; only defined on GNU. + @end deftypevr + +-@comment fcntl.h ++@comment fcntl.h (optional) + @comment GNU + @deftypevr Macro int O_WRITE + Open the file for writing. Same as @code{O_WRONLY}; only defined on GNU. + @end deftypevr + +-@comment fcntl.h ++@comment fcntl.h (optional) + @comment GNU + @deftypevr Macro int O_EXEC + Open the file for executing. Only defined on GNU. +@@ -3045,7 +3361,7 @@ + The following three file name translation flags exist only on + @gnuhurdsystems{}. + +-@comment fcntl.h ++@comment fcntl.h (optional) + @comment GNU + @deftypevr Macro int O_IGNORE_CTTY + Do not recognize the named file as the controlling terminal, even if it +@@ -3054,7 +3370,7 @@ + @xref{Job Control}. + @end deftypevr + +-@comment fcntl.h ++@comment fcntl.h (optional) + @comment GNU + @deftypevr Macro int O_NOLINK + If the named file is a symbolic link, open the link itself instead of +@@ -3063,7 +3379,7 @@ + @cindex symbolic link, opening + @end deftypevr + +-@comment fcntl.h ++@comment fcntl.h (optional) + @comment GNU + @deftypevr Macro int O_NOTRANS + If the named file is specially translated, do not invoke the translator. +@@ -3095,7 +3411,7 @@ + The remaining operating modes are BSD extensions. They exist only + on some systems. On other systems, these macros are not defined. + +-@comment fcntl.h ++@comment fcntl.h (optional) + @comment BSD + @deftypevr Macro int O_SHLOCK + Acquire a shared lock on the file, as with @code{flock}. +@@ -3106,7 +3422,7 @@ + the lock on the new file first. + @end deftypevr + +-@comment fcntl.h ++@comment fcntl.h (optional) + @comment BSD + @deftypevr Macro int O_EXLOCK + Acquire an exclusive lock on the file, as with @code{flock}. +@@ -3599,7 +4134,7 @@ + @gnusystems{} can handle most input/output operations on many different + devices and objects in terms of a few file primitives - @code{read}, + @code{write} and @code{lseek}. However, most devices also have a few +-peculiar operations which do not fit into this model. Such as: ++peculiar operations which do not fit into this model. Such as: + + @itemize @bullet + +@@ -3634,6 +4169,7 @@ + @comment sys/ioctl.h + @comment BSD + @deftypefun int ioctl (int @var{filedes}, int @var{command}, @dots{}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + + The @code{ioctl} function performs the generic I/O operation + @var{command} on @var{filedes}. +@@ -3653,3 +4189,6 @@ + Most IOCTLs are OS-specific and/or only used in special system utilities, + and are thus beyond the scope of this document. For an example of the use + of an IOCTL, see @ref{Out-of-Band Data}. ++ ++@c FIXME this is undocumented: ++@c dup3 +diff -urN glibc-2.17-c758a686/manual/locale.texi glibc-2.17-c758a686/manual/locale.texi +--- glibc-2.17-c758a686/manual/locale.texi 2014-09-12 16:08:18.266069610 -0400 ++++ glibc-2.17-c758a686/manual/locale.texi 2014-09-12 16:10:06.044792719 -0400 +@@ -231,6 +231,136 @@ + @comment locale.h + @comment ISO + @deftypefun {char *} setlocale (int @var{category}, const char *@var{locale}) ++@safety{@prelim{}@mtunsafe{@mtasuconst{:@mtslocale{}} @mtsenv{}}@asunsafe{@asuinit{} @asulock{} @ascuheap{} @asucorrupt{}}@acunsafe{@acuinit{} @acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} ++@c Uses of the global locale object are unguarded in functions that ++@c ought to be MT-Safe, so we're ruling out the use of this function ++@c once threads are started. It takes a write lock itself, but it may ++@c return a pointer loaded from the global locale object after releasing ++@c the lock, or before taking it. ++@c setlocale @mtasuconst:@mtslocale @mtsenv @asuinit @ascuheap @asulock @asucorrupt @acucorrupt @acsmem @acsfd @aculock ++@c libc_rwlock_wrlock @asulock @aculock ++@c libc_rwlock_unlock @aculock ++@c getenv LOCPATH @mtsenv ++@c malloc @ascuheap @acsmem ++@c free @ascuheap @acsmem ++@c new_composite_name ok ++@c setdata ok ++@c setname ok ++@c _nl_find_locale @mtsenv @asuinit @ascuheap @asulock @asucorrupt @acucorrupt @acsmem @acsfd @aculock ++@c getenv LC_ALL and LANG @mtsenv ++@c _nl_load_locale_from_archive @ascuheap @acucorrupt @acsmem @acsfd ++@c sysconf _SC_PAGE_SIZE ok ++@c _nl_normalize_codeset @ascuheap @acsmem ++@c isalnum_l ok (C locale) ++@c isdigit_l ok (C locale) ++@c malloc @ascuheap @acsmem ++@c tolower_l ok (C locale) ++@c open_not_cancel_2 @acsfd ++@c fxstat64 ok ++@c close_not_cancel_no_status ok ++@c __mmap64 @acsmem ++@c calculate_head_size ok ++@c __munmap ok ++@c compute_hashval ok ++@c qsort dup @acucorrupt ++@c rangecmp ok ++@c malloc @ascuheap @acsmem ++@c strdup @ascuheap @acsmem ++@c _nl_intern_locale_data @ascuheap @acsmem ++@c malloc @ascuheap @acsmem ++@c free @ascuheap @acsmem ++@c _nl_expand_alias @ascuheap @asulock @acsmem @acsfd @aculock ++@c libc_lock_lock @asulock @aculock ++@c bsearch ok ++@c alias_compare ok ++@c strcasecmp ok ++@c read_alias_file @ascuheap @asulock @acsmem @acsfd @aculock ++@c fopen @ascuheap @asulock @acsmem @acsfd @aculock ++@c fsetlocking ok ++@c feof_unlocked ok ++@c fgets_unlocked ok ++@c isspace ok (locale mutex is locked) ++@c extend_alias_table @ascuheap @acsmem ++@c realloc @ascuheap @acsmem ++@c realloc @ascuheap @acsmem ++@c fclose @ascuheap @asulock @acsmem @acsfd @aculock ++@c qsort @ascuheap @acsmem ++@c alias_compare dup ++@c libc_lock_unlock @aculock ++@c _nl_explode_name @ascuheap @acsmem ++@c _nl_find_language ok ++@c _nl_normalize_codeset dup @ascuheap @acsmem ++@c _nl_make_l10nflist @ascuheap @acsmem ++@c malloc @ascuheap @acsmem ++@c free @ascuheap @acsmem ++@c __argz_stringify ok ++@c __argz_count ok ++@c __argz_next ok ++@c _nl_load_locale @ascuheap @acsmem @acsfd ++@c open_not_cancel_2 @acsfd ++@c __fxstat64 ok ++@c close_not_cancel_no_status ok ++@c mmap @acsmem ++@c malloc @ascuheap @acsmem ++@c read_not_cancel ok ++@c free @ascuheap @acsmem ++@c _nl_intern_locale_data dup @ascuheap @acsmem ++@c munmap ok ++@c __gconv_compare_alias @asuinit @ascuheap @asucorrupt @asulock @acsmem@acucorrupt @acsfd @aculock ++@c __gconv_read_conf @asuinit @ascuheap @asucorrupt @asulock @acsmem@acucorrupt @acsfd @aculock ++@c (libc_once-initializes gconv_cache and gconv_path_envvar; they're ++@c never modified afterwards) ++@c __gconv_load_cache @ascuheap @acsmem @acsfd ++@c getenv GCONV_PATH @mtsenv ++@c open_not_cancel @acsfd ++@c __fxstat64 ok ++@c close_not_cancel_no_status ok ++@c mmap @acsmem ++@c malloc @ascuheap @acsmem ++@c __read ok ++@c free @ascuheap @acsmem ++@c munmap ok ++@c __gconv_get_path @asulock @ascuheap @aculock @acsmem @acsfd ++@c getcwd @ascuheap @acsmem @acsfd ++@c libc_lock_lock @asulock @aculock ++@c malloc @ascuheap @acsmem ++@c strtok_r ok ++@c libc_lock_unlock @aculock ++@c read_conf_file @ascuheap @asucorrupt @asulock @acsmem @acucorrupt @acsfd @aculock ++@c fopen @ascuheap @asulock @acsmem @acsfd @aculock ++@c fsetlocking ok ++@c feof_unlocked ok ++@c getdelim @ascuheap @asucorrupt @acsmem @acucorrupt ++@c isspace_l ok (C locale) ++@c add_alias ++@c isspace_l ok (C locale) ++@c toupper_l ok (C locale) ++@c add_alias2 dup @ascuheap @acucorrupt @acsmem ++@c add_module @ascuheap @acsmem ++@c isspace_l ok (C locale) ++@c toupper_l ok (C locale) ++@c strtol ok (@mtslocale but we hold the locale lock) ++@c tfind __gconv_alias_db ok ++@c __gconv_alias_compare dup ok ++@c calloc @ascuheap @acsmem ++@c insert_module dup @ascuheap ++@c __tfind ok (because the tree is read only by then) ++@c __gconv_alias_compare dup ok ++@c insert_module @ascuheap ++@c free @ascuheap ++@c add_alias2 @ascuheap @acucorrupt @acsmem ++@c detect_conflict ok, reads __gconv_modules_db ++@c malloc @ascuheap @acsmem ++@c tsearch __gconv_alias_db @ascuheap @acucorrupt @acsmem [exclusive tree, no @mtsrace] ++@c __gconv_alias_compare ok ++@c free @ascuheap ++@c __gconv_compare_alias_cache ok ++@c find_module_idx ok ++@c do_lookup_alias ok ++@c __tfind ok (because the tree is read only by then) ++@c __gconv_alias_compare ok ++@c strndup @ascuheap @acsmem ++@c strcasecmp_l ok (C locale) + The function @code{setlocale} sets the current locale for category + @var{category} to @var{locale}. + +@@ -496,6 +626,10 @@ + @comment locale.h + @comment ISO + @deftypefun {struct lconv *} localeconv (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:localeconv} @mtslocale{}}@asunsafe{}@acsafe{}} ++@c This function reads from multiple components of the locale object, ++@c without synchronization, while writing to the static buffer it uses ++@c as the return value. + The @code{localeconv} function returns a pointer to a structure whose + components contain information about how numeric and monetary values + should be formatted in the current locale. +@@ -762,6 +896,9 @@ + @comment langinfo.h + @comment XOPEN + @deftypefun {char *} nl_langinfo (nl_item @var{item}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} ++@c It calls _nl_langinfo_l with the current locale, which returns a ++@c pointer into constant strings defined in locale data structures. + The @code{nl_langinfo} function can be used to access individual + elements of the locale categories. Unlike the @code{localeconv} + function, which returns all the information, @code{nl_langinfo} +@@ -1056,6 +1193,11 @@ + numbers according to these rules. + + @deftypefun ssize_t strfmon (char *@var{s}, size_t @var{maxsize}, const char *@var{format}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} ++@c It (and strfmon_l) both call vstrfmon_l, which, besides accessing the ++@c locale object passed to it, accesses the active locale through ++@c isdigit (but to_digit assumes ASCII digits only). It may call ++@c __printf_fp (@mtslocale @ascuheap @acsmem) and guess_grouping (safe). + The @code{strfmon} function is similar to the @code{strftime} function + in that it takes a buffer, its size, a format string, + and values to write into the buffer as text in a form specified +@@ -1267,6 +1409,10 @@ + @comment GNU + @comment stdlib.h + @deftypefun int rpmatch (const char *@var{response}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} ++@c Calls nl_langinfo with YESEXPR and NOEXPR, triggering @mtslocale but ++@c it's regcomp and regexec that bring in all of the safety issues. ++@c regfree is also called, but it doesn't introduce any further issues. + The function @code{rpmatch} checks the string in @var{response} whether + or not it is a correct yes-or-no answer and if yes, which one. The + check uses the @code{YESEXPR} and @code{NOEXPR} data in the +@@ -1318,5 +1464,5 @@ + free (line); + @end smallexample + +-Note that the loop continues until an read error is detected or until a ++Note that the loop continues until a read error is detected or until a + definitive (positive or negative) answer is read. +diff -urN glibc-2.17-c758a686/manual/macros.texi glibc-2.17-c758a686/manual/macros.texi +--- glibc-2.17-c758a686/manual/macros.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/macros.texi 2014-09-12 16:10:06.045792717 -0400 +@@ -35,16 +35,225 @@ + GNU/Linux and GNU/Hurd systems + @end macro + +-@c Descrption applying to GNU/Hurd systems; that is, systems using the ++@c Description applying to GNU/Hurd systems; that is, systems using the + @c GNU Hurd with the GNU C Library. + @macro gnuhurdsystems + GNU/Hurd systems + @end macro + +-@c Descrption applying to GNU/Linux systems; that is, systems using ++@c Description applying to GNU/Linux systems; that is, systems using + @c the Linux kernel with the GNU C Library. + @macro gnulinuxsystems + GNU/Linux systems + @end macro + ++@c Document the safety functions as preliminary. It does NOT expand its ++@c comments. ++@macro prelim {comments} ++Preliminary: ++ ++@end macro ++@c Document a function as thread safe. ++@macro mtsafe {comments} ++| MT-Safe \comments\ ++ ++@end macro ++@c Document a function as thread unsafe. ++@macro mtunsafe {comments} ++| MT-Unsafe \comments\ ++ ++@end macro ++@c Document a function as safe for use in asynchronous signal handlers. ++@macro assafe {comments} ++| AS-Safe \comments\ ++ ++@end macro ++@c Document a function as unsafe for use in asynchronous signal ++@c handlers. This distinguishes unmarked functions, for which this ++@c property has not been assessed, from those that have been analyzed. ++@macro asunsafe {comments} ++| AS-Unsafe \comments\ ++ ++@end macro ++@c Document a function as safe for use when asynchronous cancellation is ++@c enabled. ++@macro acsafe {comments} ++| AC-Safe \comments\ ++ ++@end macro ++@c Document a function as unsafe for use when asynchronous cancellation ++@c is enabled. This distinguishes unmarked functions, for which this ++@c property has not been assessed, from those that have been analyzed. ++@macro acunsafe {comments} ++| AC-Unsafe \comments\ ++ ++@end macro ++@c Format safety properties without referencing the section of the ++@c definitions. To be used in the definitions of the properties ++@c themselves. ++@macro sampsafety {notes} ++@noindent ++\notes\| ++ ++ ++@end macro ++@c Format the safety properties of a function. ++@macro safety {notes} ++\notes\| @xref{POSIX Safety Concepts}. ++ ++ ++@end macro ++@c Function is MT- and AS-Unsafe due to an internal race. ++@macro mtasurace {comments} ++race\comments\ ++@end macro ++@c Function is AS-Unsafe due to an internal race. ++@macro asurace {comments} ++race\comments\ ++@end macro ++@c Function is MT-Safe, but with potential race on user-supplied object ++@c of opaque type. ++@macro mtsrace {comments} ++race\comments\ ++@end macro ++@c Function is MT- and AS-Unsafe for modifying an object that is decreed ++@c MT-constant due to MT-Unsafe accesses elsewhere. ++@macro mtasuconst {comments} ++const\comments\ ++@end macro ++@c Function accesses the assumed-constant locale object. ++@macro mtslocale {comments} ++locale\comments\ ++@end macro ++@c Function accesses the assumed-constant environment. ++@macro mtsenv {comments} ++env\comments\ ++@end macro ++@c Function accesses the assumed-constant hostid. ++@macro mtshostid {comments} ++hostid\comments\ ++@end macro ++@c Function accesses the assumed-constant _sigintr variable. ++@macro mtssigintr {comments} ++sigintr\comments\ ++@end macro ++@c Function performs MT-Unsafe initialization at the first call. ++@macro mtuinit {comments} ++init\comments\ ++@end macro ++@c Function performs libc_once AS-Unsafe initialization. ++@macro asuinit {comments} ++init\comments\ ++@end macro ++@c Function performs libc_once AC-Unsafe initialization. ++@macro acuinit {comments} ++init\comments\ ++@end macro ++@c Function is AS-Unsafe because it takes a non-recursive mutex that may ++@c already be held by the function interrupted by the signal. ++@macro asulock {comments} ++lock\comments\ ++@end macro ++@c Function is AC-Unsafe because it may fail to release a mutex. ++@macro aculock {comments} ++lock\comments\ ++@end macro ++@c Function is AS-Unsafe because some data structure may be inconsistent ++@c due to an ongoing updated interrupted by a signal. ++@macro asucorrupt {comments} ++corrupt\comments\ ++@end macro ++@c Function is AC-Unsafe because some data structure may be left ++@c inconsistent when cancelled. ++@macro acucorrupt {comments} ++corrupt\comments\ ++@end macro ++@c Function is AS- and AC-Unsafe because of malloc/free. ++@macro ascuheap {comments} ++heap\comments\ ++@end macro ++@c Function is AS-Unsafe because of malloc/free. ++@macro asuheap {comments} ++heap\comments\ ++@end macro ++@c Function is AS- and AC-Unsafe because of dlopen/dlclose. ++@macro ascudlopen {comments} ++dlopen\comments\ ++@end macro ++@c Function is AS- and AC-Unsafe because of unknown plugins. ++@macro ascuplugin {comments} ++plugin\comments\ ++@end macro ++@c Function is AS- and AC-Unsafe because of i18n. ++@macro ascuintl {comments} ++i18n\comments\ ++@end macro ++@c Function is AS--Unsafe because of i18n. ++@macro asuintl {comments} ++i18n\comments\ ++@end macro ++@c Function may leak file descriptors if async-cancelled. ++@macro acsfd {comments} ++fd\comments\ ++@end macro ++@c Function may leak memory if async-cancelled. ++@macro acsmem {comments} ++mem\comments\ ++@end macro ++@c Function is unsafe due to temporary overriding a signal handler. ++@macro mtascusig {comments} ++sig\comments\ ++@end macro ++@c Function is MT- and AS-Unsafe due to temporarily changing attributes ++@c of the controlling terminal. ++@macro mtasuterm {comments} ++term\comments\ ++@end macro ++@c Function is AC-Unsafe for failing to restore attributes of the ++@c controlling terminal. ++@macro acuterm {comments} ++term\comments\ ++@end macro ++@c Function sets timers atomically. ++@macro mtstimer {comments} ++timer\comments\ ++@end macro ++@c Function sets and restores timers. ++@macro mtascutimer {comments} ++timer\comments\ ++@end macro ++@c Function temporarily changes the current working directory. ++@macro mtasscwd {comments} ++cwd\comments\ ++@end macro ++@c Function may fail to restore to the original current working ++@c directory after temporarily changing it. ++@macro acscwd {comments} ++cwd\comments\ ++@end macro ++@c Function is MT-Safe while POSIX says it needn't be MT-Safe. ++@macro mtsposix {comments} ++!posix\comments\ ++@end macro ++@c Function is MT-Unsafe while POSIX says it should be MT-Safe. ++@macro mtuposix {comments} ++!posix\comments\ ++@end macro ++@c Function is AS-Safe while POSIX says it needn't be AS-Safe. ++@macro assposix {comments} ++!posix\comments\ ++@end macro ++@c Function is AS-Unsafe while POSIX says it should be AS-Safe. ++@macro asuposix {comments} ++!posix\comments\ ++@end macro ++@c Function is AC-Safe while POSIX says it needn't be AC-Safe. ++@macro acsposix {comments} ++!posix\comments\ ++@end macro ++@c Function is AC-Unsafe while POSIX says it should be AC-Safe. ++@macro acuposix {comments} ++!posix\comments\ ++@end macro ++ + @end ifclear +diff -urN glibc-2.17-c758a686/manual/maint.texi glibc-2.17-c758a686/manual/maint.texi +--- glibc-2.17-c758a686/manual/maint.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/maint.texi 2014-09-12 16:10:06.045792717 -0400 +@@ -316,7 +316,7 @@ + The top-level @file{configure} script uses the shell @code{.} command to + read the @file{configure} file in each system-dependent directory + chosen, in order. The @file{configure} files are often generated from +-@file{configure.in} files using Autoconf. ++@file{configure.ac} files using Autoconf. + + A system-dependent @file{configure} script will usually add things to + the shell variables @samp{DEFS} and @samp{config_vars}; see the +@@ -329,14 +329,14 @@ + just @w{@samp{--with-@var{package}}} (no argument), then it sets + @w{@samp{with_@var{package}}} to @samp{yes}. + +-@item configure.in ++@item configure.ac + + This file is an Autoconf input fragment to be processed into the file + @file{configure} in this subdirectory. @xref{Introduction,,, + autoconf.info, Autoconf: Generating Automatic Configuration Scripts}, + for a description of Autoconf. You should write either @file{configure} +-or @file{configure.in}, but not both. The first line of +-@file{configure.in} should invoke the @code{m4} macro ++or @file{configure.ac}, but not both. The first line of ++@file{configure.ac} should invoke the @code{m4} macro + @samp{GLIBC_PROVIDES}. This macro does several @code{AC_PROVIDE} calls + for Autoconf macros which are used by the top-level @file{configure} + script; without this, those macros might be invoked again unnecessarily +@@ -424,7 +424,7 @@ + files specific to those machine architectures, but not specific to any + particular operating system. There might be subdirectories for + specializations of those architectures, such as +-@w{@file{sysdeps/m68k/68020}}. Code which is specific to the ++@w{@file{sysdeps/m68k/68020}}. Code which is specific to the + floating-point coprocessor used with a particular machine should go in + @w{@file{sysdeps/@var{machine}/fpu}}. + +diff -urN glibc-2.17-c758a686/manual/Makefile glibc-2.17-c758a686/manual/Makefile +--- glibc-2.17-c758a686/manual/Makefile 2014-09-12 16:08:17.823070748 -0400 ++++ glibc-2.17-c758a686/manual/Makefile 2014-09-12 16:10:06.045792717 -0400 +@@ -1,5 +1,4 @@ +-# Copyright (C) 1992-2012 +-# Free Software Foundation, Inc. ++# Copyright (C) 1992-2014 Free Software Foundation, Inc. + # This file is part of the GNU C Library. + + # The GNU C Library is free software; you can redistribute it and/or +@@ -20,14 +19,10 @@ + + subdir := manual + +-# Allow override +-INSTALL_INFO = install-info ++include ../Makeconfig + + .PHONY: dvi pdf info html + +-# Get glibc's configuration info. +-include ../Makeconfig +- + dvi: $(objpfx)libc.dvi + pdf: $(objpfx)libc.pdf + +@@ -42,8 +37,8 @@ + intro errno memory ctype string charset locale \ + message search pattern io stdio llio filesys \ + pipe socket terminal syslog math arith time \ +- resource setjmp signal startup process job nss \ +- users sysinfo conf crypt debug probes) ++ resource setjmp signal startup process ipc job \ ++ nss users sysinfo conf crypt debug threads probes) + add-chapters = $(wildcard $(foreach d, $(add-ons), ../$d/$d.texi)) + appendices = lang.texi header.texi install.texi maint.texi platform.texi \ + contrib.texi +@@ -89,6 +84,7 @@ + $(objpfx)summary.texi: $(objpfx)stamp-summary ; + $(objpfx)stamp-summary: summary.awk $(filter-out $(objpfx)summary.texi, \ + $(texis-path)) ++ -$(SHELL) ./check-safety.sh $(filter-out $(objpfx)%, $(texis-path)) + $(AWK) -f $^ | sort -t' ' -df -k 1,1 | tr '\014' '\012' \ + > $(objpfx)summary-tmp + $(move-if-change) $(objpfx)summary-tmp $(objpfx)summary.texi +@@ -145,8 +141,7 @@ + mv -f $@.new $@ + + $(objpfx)%.info: %.texinfo +- LANGUAGE=C LC_ALL=C $(MAKEINFO) -P $(objpfx) --output=`basename $@` $< +- mv `basename $@`* $(objpfx) ++ LANGUAGE=C LC_ALL=C $(MAKEINFO) -P $(objpfx) --output=$@ $< + + $(objpfx)%.dvi: %.texinfo + cd $(objpfx);$(TEXI2DVI) -I $(shell cd $(mutex) @asulock @aculock ++@c malloc_consolidate dup ok ++@c set_max_fast ok ++@c mutex_unlock dup @aculock ++ + When calling @code{mallopt}, the @var{param} argument specifies the + parameter to be set, and @var{value} the new value to be set. Possible + choices for @var{param}, as defined in @file{malloc.h}, are: + + @table @code +-@item M_TRIM_THRESHOLD +-This is the minimum size (in bytes) of the top-most, releasable chunk +-that will cause @code{sbrk} to be called with a negative argument in +-order to return memory to the system. +-@item M_TOP_PAD +-This parameter determines the amount of extra memory to obtain from the +-system when a call to @code{sbrk} is required. It also specifies the +-number of bytes to retain when shrinking the heap by calling @code{sbrk} +-with a negative argument. This provides the necessary hysteresis in +-heap size such that excessive amounts of system calls can be avoided. ++@comment TODO: @item M_ARENA_MAX ++@comment - Document ARENA_MAX env var. ++@comment TODO: @item M_ARENA_TEST ++@comment - Document ARENA_TEST env var. ++@comment TODO: @item M_CHECK_ACTION ++@item M_MMAP_MAX ++The maximum number of chunks to allocate with @code{mmap}. Setting this ++to zero disables all use of @code{mmap}. + @item M_MMAP_THRESHOLD + All chunks larger than this value are allocated outside the normal + heap, using the @code{mmap} system call. This way it is guaranteed + that the memory for these chunks can be returned to the system on + @code{free}. Note that requests smaller than this threshold might still + be allocated via @code{mmap}. +-@item M_MMAP_MAX +-The maximum number of chunks to allocate with @code{mmap}. Setting this +-to zero disables all use of @code{mmap}. ++@comment TODO: @item M_MXFAST + @item M_PERTURB + If non-zero, memory blocks are filled with values depending on some + low order bits of this parameter when they are allocated (except when +@@ -710,6 +1140,16 @@ + guarantee that the freed block will have any specific values. It only + guarantees that the content the block had before it was freed will be + overwritten. ++@item M_TOP_PAD ++This parameter determines the amount of extra memory to obtain from the ++system when a call to @code{sbrk} is required. It also specifies the ++number of bytes to retain when shrinking the heap by calling @code{sbrk} ++with a negative argument. This provides the necessary hysteresis in ++heap size such that excessive amounts of system calls can be avoided. ++@item M_TRIM_THRESHOLD ++This is the minimum size (in bytes) of the top-most, releasable chunk ++that will cause @code{sbrk} to be called with a negative argument in ++order to return memory to the system. + @end table + + @end deftypefun +@@ -728,6 +1168,17 @@ + @comment mcheck.h + @comment GNU + @deftypefun int mcheck (void (*@var{abortfn}) (enum mcheck_status @var{status})) ++@safety{@prelim{}@mtunsafe{@mtasurace{:mcheck} @mtasuconst{:malloc_hooks}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} ++@c The hooks must be set up before malloc is first used, which sort of ++@c implies @mtuinit/@asuinit but since the function is a no-op if malloc ++@c was already used, that doesn't pose any safety issues. The actual ++@c problem is with the hooks, designed for single-threaded ++@c fully-synchronous operation: they manage an unguarded linked list of ++@c allocated blocks, and get temporarily overwritten before calling the ++@c allocation functions recursively while holding the old hooks. There ++@c are no guards for thread safety, and inconsistent hooks may be found ++@c within signal handlers or left behind in case of cancellation. ++ + Calling @code{mcheck} tells @code{malloc} to perform occasional + consistency checks. These will catch things such as writing + past the end of a block that was allocated with @code{malloc}. +@@ -770,6 +1221,18 @@ + @end deftypefun + + @deftypefun {enum mcheck_status} mprobe (void *@var{pointer}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:mcheck} @mtasuconst{:malloc_hooks}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} ++@c The linked list of headers may be modified concurrently by other ++@c threads, and it may find a partial update if called from a signal ++@c handler. It's mostly read only, so cancelling it might be safe, but ++@c it will modify global state that, if cancellation hits at just the ++@c right spot, may be left behind inconsistent. This path is only taken ++@c if checkhdr finds an inconsistency. If the inconsistency could only ++@c occur because of earlier undefined behavior, that wouldn't be an ++@c additional safety issue problem, but because of the other concurrency ++@c issues in the mcheck hooks, the apparent inconsistency could be the ++@c result of mcheck's own internal data race. So, AC-Unsafe it is. ++ + The @code{mprobe} function lets you explicitly check for inconsistencies + in a particular allocated block. You must have already called + @code{mcheck} at the beginning of the program, to do its occasional +@@ -896,16 +1359,18 @@ + @comment malloc.h + @comment GNU + @defvar __memalign_hook +-The value of this variable is a pointer to function that @code{memalign} +-uses whenever it is called. You should define this function to look +-like @code{memalign}; that is, like: ++The value of this variable is a pointer to function that @code{aligned_alloc}, ++@code{memalign}, @code{posix_memalign} and @code{valloc} use whenever they ++are called. You should define this function to look like @code{aligned_alloc}; ++that is, like: + + @smallexample + void *@var{function} (size_t @var{alignment}, size_t @var{size}, const void *@var{caller}) + @end smallexample + + The value of @var{caller} is the return address found on the stack when +-the @code{memalign} function was called. This value allows you to trace the ++the @code{aligned_alloc}, @code{memalign}, @code{posix_memalign} or ++@code{valloc} functions are called. This value allows you to trace the + memory consumption of the program. + @end defvar + +@@ -1082,6 +1547,24 @@ + @comment malloc.h + @comment SVID + @deftypefun {struct mallinfo} mallinfo (void) ++@safety{@prelim{}@mtunsafe{@mtuinit{} @mtasuconst{:mallopt}}@asunsafe{@asuinit{} @asulock{}}@acunsafe{@acuinit{} @aculock{}}} ++@c Accessing mp_.n_mmaps and mp_.max_mmapped_mem, modified with atomics ++@c but non-atomically elsewhere, may get us inconsistent results. We ++@c mark the statistics as unsafe, rather than the fast-path functions ++@c that collect the possibly inconsistent data. ++ ++@c __libc_mallinfo @mtuinit @mtasuconst:mallopt @asuinit @asulock @aculock ++@c ptmalloc_init (once) dup @mtsenv @asulock @aculock @acsfd @acsmem ++@c mutex_lock dup @asulock @aculock ++@c int_mallinfo @mtasuconst:mallopt [mp_ access on main_arena] ++@c malloc_consolidate dup ok ++@c check_malloc_state dup ok/disabled ++@c chunksize dup ok ++@c fastbin dupo ok ++@c bin_at dup ok ++@c last dup ok ++@c mutex_unlock @aculock ++ + This function returns information about the current dynamic memory usage + in a structure of type @code{struct mallinfo}. + @end deftypefun +@@ -1112,6 +1595,14 @@ + Allocate a block of @var{size} bytes, starting on a page boundary. + @xref{Aligned Memory Blocks}. + ++@item void *aligned_alloc (size_t @var{size}, size_t @var{alignment}) ++Allocate a block of @var{size} bytes, starting on an address that is a ++multiple of @var{alignment}. @xref{Aligned Memory Blocks}. ++ ++@item int posix_memalign (void **@var{memptr}, size_t @var{alignment}, size_t @var{size}) ++Allocate a block of @var{size} bytes, starting on an address that is a ++multiple of @var{alignment}. @xref{Aligned Memory Blocks}. ++ + @item void *memalign (size_t @var{size}, size_t @var{boundary}) + Allocate a block of @var{size} bytes, starting on an address that is a + multiple of @var{boundary}. @xref{Aligned Memory Blocks}. +@@ -1134,7 +1625,8 @@ + A pointer to a function that @code{free} uses whenever it is called. + + @item void (*__memalign_hook) (size_t @var{size}, size_t @var{alignment}, const void *@var{caller}) +-A pointer to a function that @code{memalign} uses whenever it is called. ++A pointer to a function that @code{aligned_alloc}, @code{memalign}, ++@code{posix_memalign} and @code{valloc} use whenever they are called. + + @item struct mallinfo mallinfo (void) + Return information about the current dynamic memory usage. +@@ -1171,6 +1663,20 @@ + @comment mcheck.h + @comment GNU + @deftypefun void mtrace (void) ++@safety{@prelim{}@mtunsafe{@mtsenv{} @mtasurace{:mtrace} @mtasuconst{:malloc_hooks} @mtuinit{}}@asunsafe{@asuinit{} @ascuheap{} @asucorrupt{} @asulock{}}@acunsafe{@acuinit{} @acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c Like the mcheck hooks, these are not designed with thread safety in ++@c mind, because the hook pointers are temporarily modified without ++@c regard to other threads, signals or cancellation. ++ ++@c mtrace @mtuinit @mtasurace:mtrace @mtsenv @asuinit @ascuheap @asucorrupt @acuinit @acucorrupt @aculock @acsfd @acsmem ++@c __libc_secure_getenv dup @mtsenv ++@c malloc dup @ascuheap @acsmem ++@c fopen dup @ascuheap @asulock @aculock @acsmem @acsfd ++@c fcntl dup ok ++@c setvbuf dup @aculock ++@c fprintf dup (on newly-created stream) @aculock ++@c __cxa_atexit (once) dup @asulock @aculock @acsmem ++@c free dup @ascuheap @acsmem + When the @code{mtrace} function is called it looks for an environment + variable named @code{MALLOC_TRACE}. This variable is supposed to + contain a valid file name. The user must have write access. If the +@@ -1194,6 +1700,11 @@ + @comment mcheck.h + @comment GNU + @deftypefun void muntrace (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:mtrace} @mtasuconst{:malloc_hooks} @mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{} @aculock{} @acsfd{}}} ++ ++@c muntrace @mtasurace:mtrace @mtslocale @asucorrupt @ascuheap @acucorrupt @acsmem @aculock @acsfd ++@c fprintf (fputs) dup @mtslocale @asucorrupt @ascuheap @acsmem @aculock @acucorrupt ++@c fclose dup @ascuheap @asulock @aculock @acsmem @acsfd + The @code{muntrace} function can be called after @code{mtrace} was used + to enable tracing the @code{malloc} calls. If no (successful) call of + @code{mtrace} was made @code{muntrace} does nothing. +@@ -1505,6 +2016,20 @@ + @comment obstack.h + @comment GNU + @deftypefun int obstack_init (struct obstack *@var{obstack-ptr}) ++@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{@acsmem{}}} ++@c obstack_init @mtsrace:obstack-ptr @acsmem ++@c _obstack_begin @acsmem ++@c chunkfun = obstack_chunk_alloc (suggested malloc) ++@c freefun = obstack_chunk_free (suggested free) ++@c *chunkfun @acsmem ++@c obstack_chunk_alloc user-supplied ++@c *obstack_alloc_failed_handler user-supplied ++@c -> print_and_abort (default) ++@c ++@c print_and_abort ++@c _ dup @ascuintl ++@c fxprintf dup @asucorrupt @aculock @acucorrupt ++@c exit @acucorrupt? + Initialize obstack @var{obstack-ptr} for allocation of objects. This + function calls the obstack's @code{obstack_chunk_alloc} function. If + allocation of memory fails, the function pointed to by +@@ -1560,6 +2085,10 @@ + @comment obstack.h + @comment GNU + @deftypefun {void *} obstack_alloc (struct obstack *@var{obstack-ptr}, int @var{size}) ++@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}} ++@c obstack_alloc @mtsrace:obstack-ptr @acucorrupt @acsmem ++@c obstack_blank dup @mtsrace:obstack-ptr @acucorrupt @acsmem ++@c obstack_finish dup @mtsrace:obstack-ptr @acucorrupt + This allocates an uninitialized block of @var{size} bytes in an obstack + and returns its address. Here @var{obstack-ptr} specifies which obstack + to allocate the block in; it is the address of the @code{struct obstack} +@@ -1594,6 +2123,10 @@ + @comment obstack.h + @comment GNU + @deftypefun {void *} obstack_copy (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size}) ++@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}} ++@c obstack_copy @mtsrace:obstack-ptr @acucorrupt @acsmem ++@c obstack_grow dup @mtsrace:obstack-ptr @acucorrupt @acsmem ++@c obstack_finish dup @mtsrace:obstack-ptr @acucorrupt + This allocates a block and initializes it by copying @var{size} + bytes of data starting at @var{address}. It calls + @code{obstack_alloc_failed_handler} if allocation of memory by +@@ -1603,6 +2136,10 @@ + @comment obstack.h + @comment GNU + @deftypefun {void *} obstack_copy0 (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size}) ++@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}} ++@c obstack_copy0 @mtsrace:obstack-ptr @acucorrupt @acsmem ++@c obstack_grow0 dup @mtsrace:obstack-ptr @acucorrupt @acsmem ++@c obstack_finish dup @mtsrace:obstack-ptr @acucorrupt + Like @code{obstack_copy}, but appends an extra byte containing a null + character. This extra byte is not counted in the argument @var{size}. + @end deftypefun +@@ -1635,6 +2172,10 @@ + @comment obstack.h + @comment GNU + @deftypefun void obstack_free (struct obstack *@var{obstack-ptr}, void *@var{object}) ++@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{}}} ++@c obstack_free @mtsrace:obstack-ptr @acucorrupt ++@c (obstack_free) @mtsrace:obstack-ptr @acucorrupt ++@c *freefun dup user-supplied + If @var{object} is a null pointer, everything allocated in the obstack + is freed. Otherwise, @var{object} must be the address of an object + allocated in the obstack. Then @var{object} is freed, along with +@@ -1739,6 +2280,13 @@ + @comment obstack.h + @comment GNU + @deftypefun void obstack_blank (struct obstack *@var{obstack-ptr}, int @var{size}) ++@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}} ++@c obstack_blank @mtsrace:obstack-ptr @acucorrupt @acsmem ++@c _obstack_newchunk @mtsrace:obstack-ptr @acucorrupt @acsmem ++@c *chunkfun dup @acsmem ++@c *obstack_alloc_failed_handler dup user-supplied ++@c *freefun ++@c obstack_blank_fast dup @mtsrace:obstack-ptr + The most basic function for adding to a growing object is + @code{obstack_blank}, which adds space without initializing it. + @end deftypefun +@@ -1746,6 +2294,10 @@ + @comment obstack.h + @comment GNU + @deftypefun void obstack_grow (struct obstack *@var{obstack-ptr}, void *@var{data}, int @var{size}) ++@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}} ++@c obstack_grow @mtsrace:obstack-ptr @acucorrupt @acsmem ++@c _obstack_newchunk dup @mtsrace:obstack-ptr @acucorrupt @acsmem ++@c memcpy ok + To add a block of initialized space, use @code{obstack_grow}, which is + the growing-object analogue of @code{obstack_copy}. It adds @var{size} + bytes of data to the growing object, copying the contents from +@@ -1755,6 +2307,12 @@ + @comment obstack.h + @comment GNU + @deftypefun void obstack_grow0 (struct obstack *@var{obstack-ptr}, void *@var{data}, int @var{size}) ++@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}} ++@c obstack_grow0 @mtsrace:obstack-ptr @acucorrupt @acsmem ++@c (no sequence point between storing NUL and incrementing next_free) ++@c (multiple changes to next_free => @acucorrupt) ++@c _obstack_newchunk dup @mtsrace:obstack-ptr @acucorrupt @acsmem ++@c memcpy ok + This is the growing-object analogue of @code{obstack_copy0}. It adds + @var{size} bytes copied from @var{data}, followed by an additional null + character. +@@ -1763,6 +2321,10 @@ + @comment obstack.h + @comment GNU + @deftypefun void obstack_1grow (struct obstack *@var{obstack-ptr}, char @var{c}) ++@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}} ++@c obstack_1grow @mtsrace:obstack-ptr @acucorrupt @acsmem ++@c _obstack_newchunk dup @mtsrace:obstack-ptr @acucorrupt @acsmem ++@c obstack_1grow_fast dup @mtsrace:obstack-ptr @acucorrupt @acsmem + To add one character at a time, use the function @code{obstack_1grow}. + It adds a single byte containing @var{c} to the growing object. + @end deftypefun +@@ -1770,6 +2332,10 @@ + @comment obstack.h + @comment GNU + @deftypefun void obstack_ptr_grow (struct obstack *@var{obstack-ptr}, void *@var{data}) ++@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}} ++@c obstack_ptr_grow @mtsrace:obstack-ptr @acucorrupt @acsmem ++@c _obstack_newchunk dup @mtsrace:obstack-ptr @acucorrupt @acsmem ++@c obstack_ptr_grow_fast dup @mtsrace:obstack-ptr + Adding the value of a pointer one can use the function + @code{obstack_ptr_grow}. It adds @code{sizeof (void *)} bytes + containing the value of @var{data}. +@@ -1778,6 +2344,10 @@ + @comment obstack.h + @comment GNU + @deftypefun void obstack_int_grow (struct obstack *@var{obstack-ptr}, int @var{data}) ++@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}} ++@c obstack_int_grow @mtsrace:obstack-ptr @acucorrupt @acsmem ++@c _obstack_newchunk dup @mtsrace:obstack-ptr @acucorrupt @acsmem ++@c obstack_int_grow_fast dup @mtsrace:obstack-ptr + A single value of type @code{int} can be added by using the + @code{obstack_int_grow} function. It adds @code{sizeof (int)} bytes to + the growing object and initializes them with the value of @var{data}. +@@ -1786,6 +2356,8 @@ + @comment obstack.h + @comment GNU + @deftypefun {void *} obstack_finish (struct obstack *@var{obstack-ptr}) ++@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{}}} ++@c obstack_finish @mtsrace:obstack-ptr @acucorrupt + When you are finished growing the object, use the function + @code{obstack_finish} to close it off and return its final address. + +@@ -1805,6 +2377,7 @@ + @comment obstack.h + @comment GNU + @deftypefun int obstack_object_size (struct obstack *@var{obstack-ptr}) ++@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}} + This function returns the current size of the growing object, in bytes. + Remember to call this function @emph{before} finishing the object. + After it is finished, @code{obstack_object_size} will return zero. +@@ -1848,6 +2421,7 @@ + @comment obstack.h + @comment GNU + @deftypefun int obstack_room (struct obstack *@var{obstack-ptr}) ++@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}} + This returns the number of bytes that can be added safely to the current + growing object (or to an object about to be started) in obstack + @var{obstack} using the fast growth functions. +@@ -1859,6 +2433,9 @@ + @comment obstack.h + @comment GNU + @deftypefun void obstack_1grow_fast (struct obstack *@var{obstack-ptr}, char @var{c}) ++@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}} ++@c obstack_1grow_fast @mtsrace:obstack-ptr @acucorrupt @acsmem ++@c (no sequence point between copying c and incrementing next_free) + The function @code{obstack_1grow_fast} adds one byte containing the + character @var{c} to the growing object in obstack @var{obstack-ptr}. + @end deftypefun +@@ -1866,6 +2443,8 @@ + @comment obstack.h + @comment GNU + @deftypefun void obstack_ptr_grow_fast (struct obstack *@var{obstack-ptr}, void *@var{data}) ++@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}} ++@c obstack_ptr_grow_fast @mtsrace:obstack-ptr + The function @code{obstack_ptr_grow_fast} adds @code{sizeof (void *)} + bytes containing the value of @var{data} to the growing object in + obstack @var{obstack-ptr}. +@@ -1874,6 +2453,8 @@ + @comment obstack.h + @comment GNU + @deftypefun void obstack_int_grow_fast (struct obstack *@var{obstack-ptr}, int @var{data}) ++@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}} ++@c obstack_int_grow_fast @mtsrace:obstack-ptr + The function @code{obstack_int_grow_fast} adds @code{sizeof (int)} bytes + containing the value of @var{data} to the growing object in obstack + @var{obstack-ptr}. +@@ -1882,6 +2463,8 @@ + @comment obstack.h + @comment GNU + @deftypefun void obstack_blank_fast (struct obstack *@var{obstack-ptr}, int @var{size}) ++@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}} ++@c obstack_blank_fast @mtsrace:obstack-ptr + The function @code{obstack_blank_fast} adds @var{size} bytes to the + growing object in obstack @var{obstack-ptr} without initializing them. + @end deftypefun +@@ -1909,7 +2492,7 @@ + int room = obstack_room (obstack); + if (room == 0) + @{ +- /* @r{Not enough room. Add one character slowly,} ++ /* @r{Not enough room. Add one character slowly,} + @r{which may copy to a new chunk and make room.} */ + obstack_1grow (obstack, *ptr++); + len--; +@@ -1940,6 +2523,7 @@ + @comment obstack.h + @comment GNU + @deftypefun {void *} obstack_base (struct obstack *@var{obstack-ptr}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acsafe{}} + This function returns the tentative address of the beginning of the + currently growing object in @var{obstack-ptr}. If you finish the object + immediately, it will have that address. If you make it larger first, it +@@ -1953,6 +2537,7 @@ + @comment obstack.h + @comment GNU + @deftypefun {void *} obstack_next_free (struct obstack *@var{obstack-ptr}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acsafe{}} + This function returns the address of the first free byte in the current + chunk of obstack @var{obstack-ptr}. This is the end of the currently + growing object. If no object is growing, @code{obstack_next_free} +@@ -1962,6 +2547,8 @@ + @comment obstack.h + @comment GNU + @deftypefun int obstack_object_size (struct obstack *@var{obstack-ptr}) ++@c dup ++@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}} + This function returns the size in bytes of the currently growing object. + This is equivalent to + +@@ -1986,6 +2573,7 @@ + @comment obstack.h + @comment GNU + @deftypefn Macro int obstack_alignment_mask (struct obstack *@var{obstack-ptr}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The value is a bit mask; a bit that is 1 indicates that the corresponding + bit in the address of an object should be 0. The mask value should be one + less than a power of 2; the effect is that all object addresses are +@@ -2053,6 +2641,7 @@ + @comment obstack.h + @comment GNU + @deftypefn Macro int obstack_chunk_size (struct obstack *@var{obstack-ptr}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This returns the chunk size of the given obstack. + @end deftypefn + +@@ -2172,6 +2761,7 @@ + @comment stdlib.h + @comment GNU, BSD + @deftypefun {void *} alloca (size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The return value of @code{alloca} is the address of a block of @var{size} + bytes of memory, allocated in the stack frame of the calling function. + @end deftypefun +@@ -2354,6 +2944,7 @@ + @comment unistd.h + @comment BSD + @deftypefun int brk (void *@var{addr}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + + @code{brk} sets the high end of the calling process' data segment to + @var{addr}. +@@ -2396,6 +2987,8 @@ + @comment unistd.h + @comment BSD + @deftypefun void *sbrk (ptrdiff_t @var{delta}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++ + This function is the same as @code{brk} except that you specify the new + end of the data segment as an offset @var{delta} from the current end + and on success the return value is the address of the resulting end of +@@ -2535,6 +3128,7 @@ + @comment sys/mman.h + @comment POSIX.1b + @deftypefun int mlock (const void *@var{addr}, size_t @var{len}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + + @code{mlock} locks a range of the calling process' virtual pages. + +@@ -2588,6 +3182,7 @@ + @comment sys/mman.h + @comment POSIX.1b + @deftypefun int munlock (const void *@var{addr}, size_t @var{len}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + + @code{munlock} unlocks a range of the calling process' virtual pages. + +@@ -2600,6 +3195,7 @@ + @comment sys/mman.h + @comment POSIX.1b + @deftypefun int mlockall (int @var{flags}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + + @code{mlockall} locks all the pages in a process' virtual memory address + space, and/or any that are added to it in the future. This includes the +@@ -2676,6 +3272,7 @@ + @comment sys/mman.h + @comment POSIX.1b + @deftypefun int munlockall (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + + @code{munlockall} unlocks every page in the calling process' virtual + address space and turn off @code{MCL_FUTURE} future locking mode. +diff -urN glibc-2.17-c758a686/manual/message.texi glibc-2.17-c758a686/manual/message.texi +--- glibc-2.17-c758a686/manual/message.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/message.texi 2014-09-12 16:10:06.043792722 -0400 +@@ -2,9 +2,9 @@ + @c %MENU% How to make the program speak the user's language + @chapter Message Translation + +-The program's interface with the human should be designed in a way to +-ease the human the task. One of the possibilities is to use messages in +-whatever language the user prefers. ++The program's interface with the user should be designed to ease the user's ++task. One way to ease the user's task is to use messages in whatever ++language the user prefers. + + Printing messages in different languages can be implemented in different + ways. One could add all the different languages in the source code and +@@ -40,7 +40,7 @@ + @end itemize + + The two approaches mainly differ in the implementation of this last +-step. The design decisions made for this influences the whole rest. ++step. Decisions made in the last step influence the rest of the design. + + @menu + * Message catalogs a la X/Open:: The @code{catgets} family of functions. +@@ -86,7 +86,32 @@ + @comment nl_types.h + @comment X/Open + @deftypefun nl_catd catopen (const char *@var{cat_name}, int @var{flag}) +-The @code{catgets} function tries to locate the message data file names ++@safety{@prelim{}@mtsafe{@mtsenv{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} ++@c catopen @mtsenv @ascuheap @acsmem ++@c strchr ok ++@c setlocale(,NULL) ok ++@c getenv @mtsenv ++@c strlen ok ++@c alloca ok ++@c stpcpy ok ++@c malloc @ascuheap @acsmem ++@c __open_catalog @ascuheap @acsmem ++@c strchr ok ++@c open_not_cancel_2 @acsfd ++@c strlen ok ++@c ENOUGH ok ++@c alloca ok ++@c memcpy ok ++@c fxstat64 ok ++@c __set_errno ok ++@c mmap @acsmem ++@c malloc dup @ascuheap @acsmem ++@c read_not_cancel ok ++@c free dup @ascuheap @acsmem ++@c munmap ok ++@c close_not_cancel_no_status ok ++@c free @ascuheap @acsmem ++The @code{catopen} function tries to locate the message data file names + @var{cat_name} and loads it when found. The return value is of an + opaque type and can be used in calls to the other functions to refer to + this loaded catalog. +@@ -243,6 +268,7 @@ + + + @deftypefun {char *} catgets (nl_catd @var{catalog_desc}, int @var{set}, int @var{message}, const char *@var{string}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The function @code{catgets} has to be used to access the massage catalog + previously opened using the @code{catopen} function. The + @var{catalog_desc} parameter must be a value previously returned by +@@ -281,6 +307,11 @@ + Usage}). + + @deftypefun int catclose (nl_catd @var{catalog_desc}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{}}} ++@c catclose @ascuheap @acucorrupt @acsmem ++@c __set_errno ok ++@c munmap ok ++@c free @ascuheap @acsmem + The @code{catclose} function can be used to free the resources + associated with a message catalog which previously was opened by a call + to @code{catopen}. If the resources can be successfully freed the +@@ -803,12 +834,14 @@ + @comment libintl.h + @comment GNU + @deftypefun {char *} gettext (const char *@var{msgid}) ++@safety{@prelim{}@mtsafe{@mtsenv{}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c Wrapper for dcgettext. + The @code{gettext} function searches the currently selected message + catalogs for a string which is equal to @var{msgid}. If there is such a + string available it is returned. Otherwise the argument string + @var{msgid} is returned. + +-Please note that all though the return value is @code{char *} the ++Please note that although the return value is @code{char *} the + returned string must not be changed. This broken type results from the + history of the function and does not reflect the way the function should + be used. +@@ -850,6 +883,8 @@ + @comment libintl.h + @comment GNU + @deftypefun {char *} dgettext (const char *@var{domainname}, const char *@var{msgid}) ++@safety{@prelim{}@mtsafe{@mtsenv{}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c Wrapper for dcgettext. + The @code{dgettext} functions acts just like the @code{gettext} + function. It only takes an additional first argument @var{domainname} + which guides the selection of the message catalogs which are searched +@@ -864,6 +899,102 @@ + @comment libintl.h + @comment GNU + @deftypefun {char *} dcgettext (const char *@var{domainname}, const char *@var{msgid}, int @var{category}) ++@safety{@prelim{}@mtsafe{@mtsenv{}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c dcgettext @mtsenv @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsfd @acsmem ++@c dcigettext @mtsenv @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsfd @acsmem ++@c libc_rwlock_rdlock @asulock @aculock ++@c current_locale_name ok [protected from @mtslocale] ++@c tfind ok ++@c libc_rwlock_unlock ok ++@c plural_lookup ok ++@c plural_eval ok ++@c rawmemchr ok ++@c DETERMINE_SECURE ok, nothing ++@c strcmp ok ++@c strlen ok ++@c getcwd @ascuheap @acsmem @acsfd ++@c strchr ok ++@c stpcpy ok ++@c category_to_name ok ++@c guess_category_value @mtsenv ++@c getenv @mtsenv ++@c current_locale_name dup ok [protected from @mtslocale by dcigettext] ++@c strcmp ok ++@c ENABLE_SECURE ok ++@c _nl_find_domain @mtsenv @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsfd @acsmem ++@c libc_rwlock_rdlock dup @asulock @aculock ++@c _nl_make_l10nflist dup @ascuheap @acsmem ++@c libc_rwlock_unlock dup ok ++@c _nl_load_domain @mtsenv @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock_recursive @aculock ++@c libc_lock_unlock_recursive @aculock ++@c open->open_not_cancel_2 @acsfd ++@c fstat ok ++@c mmap dup @acsmem ++@c close->close_not_cancel_no_status @acsfd ++@c malloc dup @ascuheap @acsmem ++@c read->read_not_cancel ok ++@c munmap dup @acsmem ++@c W dup ok ++@c strlen dup ok ++@c get_sysdep_segment_value ok ++@c memcpy dup ok ++@c hash_string dup ok ++@c free dup @ascuheap @acsmem ++@c libc_rwlock_init ok ++@c _nl_find_msg dup @mtsenv @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsfd @acsmem ++@c libc_rwlock_fini ok ++@c EXTRACT_PLURAL_EXPRESSION @ascuheap @acsmem ++@c strstr dup ok ++@c isspace ok ++@c strtoul ok ++@c PLURAL_PARSE @ascuheap @acsmem ++@c malloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c INIT_GERMANIC_PLURAL ok, nothing ++@c the pre-C99 variant is @acucorrupt [protected from @mtuinit by dcigettext] ++@c _nl_expand_alias dup @ascuheap @asulock @acsmem @acsfd @aculock ++@c _nl_explode_name dup @ascuheap @acsmem ++@c libc_rwlock_wrlock dup @asulock @aculock ++@c free dup @asulock @aculock @acsfd @acsmem ++@c _nl_find_msg @mtsenv @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsfd @acsmem ++@c _nl_load_domain dup @mtsenv @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsfd @acsmem ++@c strlen ok ++@c hash_string ok ++@c W ok ++@c SWAP ok ++@c bswap_32 ok ++@c strcmp ok ++@c get_output_charset @mtsenv @ascuheap @acsmem ++@c getenv dup @mtsenv ++@c strlen dup ok ++@c malloc dup @ascuheap @acsmem ++@c memcpy dup ok ++@c libc_rwlock_rdlock dup @asulock @aculock ++@c libc_rwlock_unlock dup ok ++@c libc_rwlock_wrlock dup @asulock @aculock ++@c realloc @ascuheap @acsmem ++@c strdup @ascuheap @acsmem ++@c strstr ok ++@c strcspn ok ++@c mempcpy dup ok ++@c norm_add_slashes dup ok ++@c gconv_open @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c [protected from @mtslocale by dcigettext locale lock] ++@c free dup @ascuheap @acsmem ++@c libc_lock_lock @asulock @aculock ++@c calloc @ascuheap @acsmem ++@c gconv dup @acucorrupt [protected from @mtsrace and @asucorrupt by lock] ++@c libc_lock_unlock ok ++@c malloc @ascuheap @acsmem ++@c mempcpy ok ++@c memcpy ok ++@c strcpy ok ++@c libc_rwlock_wrlock @asulock @aculock ++@c tsearch @ascuheap @acucorrupt @acsmem [protected from @mtsrace and @asucorrupt] ++@c transcmp ok ++@c strmp dup ok ++@c free @ascuheap @acsmem + The @code{dcgettext} adds another argument to those which + @code{dgettext} takes. This argument @var{category} specifies the last + piece of information needed to localize the message catalog. I.e., the +@@ -967,7 +1098,7 @@ + second best choice to fall back on the language of the developer and + simply not translate any message. Instead a user might be better able + to read the messages in another language and so the user of the program +-should be able to define an precedence order of languages. ++should be able to define a precedence order of languages. + @end itemize + + We can divide the configuration actions in two parts: the one is +@@ -988,6 +1119,13 @@ + @comment libintl.h + @comment GNU + @deftypefun {char *} textdomain (const char *@var{domainname}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsmem{}}} ++@c textdomain @asulock @ascuheap @aculock @acsmem ++@c libc_rwlock_wrlock @asulock @aculock ++@c strcmp ok ++@c strdup @ascuheap @acsmem ++@c free @ascuheap @acsmem ++@c libc_rwlock_unlock ok + The @code{textdomain} function sets the default domain, which is used in + all future @code{gettext} calls, to @var{domainname}. Please note that + @code{dgettext} and @code{dcgettext} calls are not influenced if the +@@ -1019,6 +1157,14 @@ + @comment libintl.h + @comment GNU + @deftypefun {char *} bindtextdomain (const char *@var{domainname}, const char *@var{dirname}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} ++@c bindtextdomain @ascuheap @acsmem ++@c set_binding_values @ascuheap @acsmem ++@c libc_rwlock_wrlock dup @asulock @aculock ++@c strcmp dup ok ++@c strdup dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c malloc dup @ascuheap @acsmem + The @code{bindtextdomain} function can be used to specify the directory + which contains the message catalogs for domain @var{domainname} for the + different languages. To be correct, this is the directory where the +@@ -1114,7 +1260,7 @@ + extended @code{gettext} interface should be used. + + These extra functions are taking instead of the one key string two +-strings and an numerical argument. The idea behind this is that using ++strings and a numerical argument. The idea behind this is that using + the numerical argument and the first string as a key, the implementation + can select using rules specified by the translator the right plural + form. The two string arguments then will be used to provide a return +@@ -1134,6 +1280,8 @@ + @comment libintl.h + @comment GNU + @deftypefun {char *} ngettext (const char *@var{msgid1}, const char *@var{msgid2}, unsigned long int @var{n}) ++@safety{@prelim{}@mtsafe{@mtsenv{}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c Wrapper for dcngettext. + The @code{ngettext} function is similar to the @code{gettext} function + as it finds the message catalogs in the same way. But it takes two + extra arguments. The @var{msgid1} parameter must contain the singular +@@ -1157,6 +1305,8 @@ + @comment libintl.h + @comment GNU + @deftypefun {char *} dngettext (const char *@var{domain}, const char *@var{msgid1}, const char *@var{msgid2}, unsigned long int @var{n}) ++@safety{@prelim{}@mtsafe{@mtsenv{}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c Wrapper for dcngettext. + The @code{dngettext} is similar to the @code{dgettext} function in the + way the message catalog is selected. The difference is that it takes + two extra parameter to provide the correct plural form. These two +@@ -1166,6 +1316,8 @@ + @comment libintl.h + @comment GNU + @deftypefun {char *} dcngettext (const char *@var{domain}, const char *@var{msgid1}, const char *@var{msgid2}, unsigned long int @var{n}, int @var{category}) ++@safety{@prelim{}@mtsafe{@mtsenv{}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c Wrapper for dcigettext. + The @code{dcngettext} is similar to the @code{dcgettext} function in the + way the message catalog is selected. The difference is that it takes + two extra parameter to provide the correct plural form. These two +@@ -1422,6 +1574,9 @@ + @comment libintl.h + @comment GNU + @deftypefun {char *} bind_textdomain_codeset (const char *@var{domainname}, const char *@var{codeset}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} ++@c bind_textdomain_codeset @ascuheap @acsmem ++@c set_binding_values dup @ascuheap @acsmem + The @code{bind_textdomain_codeset} function can be used to specify the + output character set for message catalogs for domain @var{domainname}. + The @var{codeset} argument must be a valid codeset name which can be used +@@ -1429,7 +1584,7 @@ + + If the @var{codeset} parameter is the null pointer, + @code{bind_textdomain_codeset} returns the currently selected codeset +-for the domain with the name @var{domainname}. It returns @code{NULL} if ++for the domain with the name @var{domainname}. It returns @code{NULL} if + no codeset has yet been selected. + + The @code{bind_textdomain_codeset} function can be used several times. +@@ -1441,7 +1596,8 @@ + allocated internally in the function and must not be changed by the + user. If the system went out of core during the execution of + @code{bind_textdomain_codeset}, the return value is @code{NULL} and the +-global variable @var{errno} is set accordingly. @end deftypefun ++global variable @var{errno} is set accordingly. ++@end deftypefun + + + @node GUI program problems +diff -urN glibc-2.17-c758a686/manual/nss.texi glibc-2.17-c758a686/manual/nss.texi +--- glibc-2.17-c758a686/manual/nss.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/nss.texi 2014-09-12 16:10:25.996741462 -0400 +@@ -10,7 +10,7 @@ + using files (e.g., @file{/etc/passwd}), but other nameservices (like the + Network Information Service (NIS) and the Domain Name Service (DNS)) + became popular, and were hacked into the C library, usually with a fixed +-search order (@pxref{frobnicate, , ,jargon, The Jargon File}). ++search order. + + @Theglibc{} contains a cleaner solution of this problem. It is + designed after a method used by Sun Microsystems in the C library of +diff -urN glibc-2.17-c758a686/manual/pattern.texi glibc-2.17-c758a686/manual/pattern.texi +--- glibc-2.17-c758a686/manual/pattern.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/pattern.texi 2014-09-12 16:10:06.045792717 -0400 +@@ -28,6 +28,38 @@ + @comment fnmatch.h + @comment POSIX.2 + @deftypefun int fnmatch (const char *@var{pattern}, const char *@var{string}, int @var{flags}) ++@safety{@prelim{}@mtsafe{@mtsenv{} @mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} ++@c fnmatch @mtsenv @mtslocale @ascuheap @acsmem ++@c strnlen dup ok ++@c mbsrtowcs ++@c memset dup ok ++@c malloc dup @ascuheap @acsmem ++@c mbsinit dup ok ++@c free dup @ascuheap @acsmem ++@c FCT = internal_fnwmatch @mtsenv @mtslocale @ascuheap @acsmem ++@c FOLD @mtslocale ++@c towlower @mtslocale ++@c EXT @mtsenv @mtslocale @ascuheap @acsmem ++@c STRLEN = wcslen dup ok ++@c getenv @mtsenv ++@c malloc dup @ascuheap @acsmem ++@c MEMPCPY = wmempcpy dup ok ++@c FCT dup @mtsenv @mtslocale @ascuheap @acsmem ++@c STRCAT = wcscat dup ok ++@c free dup @ascuheap @acsmem ++@c END @mtsenv ++@c getenv @mtsenv ++@c MEMCHR = wmemchr dup ok ++@c getenv @mtsenv ++@c IS_CHAR_CLASS = is_char_class @mtslocale ++@c wctype @mtslocale ++@c BTOWC ok ++@c ISWCTYPE ok ++@c auto findidx dup ok ++@c elem_hash dup ok ++@c memcmp dup ok ++@c collseq_table_lookup dup ok ++@c NO_LEADING_PERIOD ok + This function tests whether the string @var{string} matches the pattern + @var{pattern}. It returns @code{0} if they do match; otherwise, it + returns the nonzero value @code{FNM_NOMATCH}. The arguments +@@ -36,11 +68,8 @@ + The argument @var{flags} is a combination of flag bits that alter the + details of matching. See below for a list of the defined flags. + +-In @theglibc{}, @code{fnmatch} cannot experience an ``error''---it +-always returns an answer for whether the match succeeds. However, other +-implementations of @code{fnmatch} might sometimes report ``errors''. +-They would do so by returning nonzero values that are not equal to +-@code{FNM_NOMATCH}. ++In @theglibc{}, @code{fnmatch} might sometimes report ``errors'' by ++returning nonzero values that are not equal to @code{FNM_NOMATCH}. + @end deftypefun + + These are the available flags for the @var{flags} argument: +@@ -234,6 +263,12 @@ + (*) (const char *,} @w{struct stat *)}}. + + This is a GNU extension. ++ ++@item gl_flags ++The flags used when @code{glob} was called. In addition, @code{GLOB_MAGCHAR} ++might be set. See @ref{Flags for Globbing} for more details. ++ ++This is a GNU extension. + @end table + @end deftp + +@@ -312,12 +347,75 @@ + (*) (const char *,} @w{struct stat64 *)}}. + + This is a GNU extension. ++ ++@item gl_flags ++The flags used when @code{glob} was called. In addition, @code{GLOB_MAGCHAR} ++might be set. See @ref{Flags for Globbing} for more details. ++ ++This is a GNU extension. + @end table + @end deftp + + @comment glob.h + @comment POSIX.2 + @deftypefun int glob (const char *@var{pattern}, int @var{flags}, int (*@var{errfunc}) (const char *@var{filename}, int @var{error-code}), glob_t *@var{vector-ptr}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtsenv{} @mtascusig{:ALRM} @mtascutimer{} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @asucorrupt{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c glob @mtasurace:utent @mtsenv @mtascusig:ALRM @mtascutimer @mtslocale @ascudlopen @ascuplugin @asucorrupt @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c strlen dup ok ++@c strchr dup ok ++@c malloc dup @ascuheap @acsmem ++@c mempcpy dup ok ++@c next_brace_sub ok ++@c free dup @ascuheap @acsmem ++@c globfree dup @asucorrupt @ascuheap @acucorrupt @acsmem ++@c glob_pattern_p ok ++@c glob_pattern_type dup ok ++@c getenv dup @mtsenv ++@c GET_LOGIN_NAME_MAX ok ++@c getlogin_r dup @mtasurace:utent @mtascusig:ALRM @mtascutimer @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c GETPW_R_SIZE_MAX ok ++@c getpwnam_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c realloc dup @ascuheap @acsmem ++@c memcpy dup ok ++@c memchr dup ok ++@c *pglob->gl_stat user-supplied ++@c stat64 dup ok ++@c S_ISDIR dup ok ++@c strdup dup @ascuheap @acsmem ++@c glob_pattern_type ok ++@c glob_in_dir @mtsenv @mtslocale @asucorrupt @ascuheap @acucorrupt @acsfd @acsmem ++@c strlen dup ok ++@c glob_pattern_type dup ok ++@c malloc dup @ascuheap @acsmem ++@c mempcpy dup ok ++@c *pglob->gl_stat user-supplied ++@c stat64 dup ok ++@c free dup @ascuheap @acsmem ++@c *pglob->gl_opendir user-supplied ++@c opendir dup @ascuheap @acsmem @acsfd ++@c dirfd dup ok ++@c *pglob->gl_readdir user-supplied ++@c CONVERT_DIRENT_DIRENT64 ok ++@c readdir64 ok [protected by exclusive use of the stream] ++@c REAL_DIR_ENTRY ok ++@c DIRENT_MIGHT_BE_DIR ok ++@c fnmatch dup @mtsenv @mtslocale @ascuheap @acsmem ++@c DIRENT_MIGHT_BE_SYMLINK ok ++@c link_exists_p ok ++@c link_exists2_p ok ++@c strlen dup ok ++@c mempcpy dup ok ++@c *pglob->gl_stat user-supplied ++@c fxstatat64 dup ok ++@c realloc dup @ascuheap @acsmem ++@c pglob->gl_closedir user-supplied ++@c closedir @ascuheap @acsmem @acsfd ++@c prefix_array dup @asucorrupt @ascuheap @acucorrupt @acsmem ++@c strlen dup ok ++@c malloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c mempcpy dup ok ++@c strcpy dup ok + The function @code{glob} does globbing using the pattern @var{pattern} + in the current directory. It puts the result in a newly allocated + vector, and stores the size and address of this vector into +@@ -389,6 +487,8 @@ + @comment glob.h + @comment GNU + @deftypefun int glob64 (const char *@var{pattern}, int @var{flags}, int (*@var{errfunc}) (const char *@var{filename}, int @var{error-code}), glob64_t *@var{vector-ptr}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtsenv{} @mtascusig{:ALRM} @mtascutimer{} @mtslocale{}}@asunsafe{@ascudlopen{} @asucorrupt{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c Same code as glob, but with glob64_t #defined as glob_t. + The @code{glob64} function was added as part of the Large File Summit + extensions but is not part of the original LFS proposal. The reason for + this is simple: it is not necessary. The necessity for a @code{glob64} +@@ -408,10 +508,12 @@ + @node Flags for Globbing + @subsection Flags for Globbing + +-This section describes the flags that you can specify in the ++This section describes the standard flags that you can specify in the + @var{flags} argument to @code{glob}. Choose the flags you want, + and combine them with the C bitwise OR operator @code{|}. + ++Note that there are @ref{More Flags for Globbing} available as GNU extensions. ++ + @vtable @code + @comment glob.h + @comment POSIX.2 +@@ -481,13 +583,6 @@ + + @comment glob.h + @comment POSIX.2 +-@item GLOB_NOSORT +-Don't sort the file names; return them in no particular order. +-(In practice, the order will depend on the order of the entries in +-the directory.) The only reason @emph{not} to sort is to save time. +- +-@comment glob.h +-@comment POSIX.2 + @item GLOB_NOESCAPE + Don't treat the @samp{\} character specially in patterns. Normally, + @samp{\} quotes the following character, turning off its special meaning +@@ -500,6 +595,13 @@ + @code{glob} does its work by calling the function @code{fnmatch} + repeatedly. It handles the flag @code{GLOB_NOESCAPE} by turning on the + @code{FNM_NOESCAPE} flag in calls to @code{fnmatch}. ++ ++@comment glob.h ++@comment POSIX.2 ++@item GLOB_NOSORT ++Don't sort the file names; return them in no particular order. ++(In practice, the order will depend on the order of the entries in ++the directory.) The only reason @emph{not} to sort is to save time. + @end vtable + + @node More Flags for Globbing +@@ -651,6 +753,9 @@ + @comment glob.h + @comment POSIX.2 + @deftypefun void globfree (glob_t *@var{pglob}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{}}} ++@c globfree dup @asucorrupt @ascuheap @acucorrupt @acsmem ++@c free dup @ascuheap @acsmem + The @code{globfree} function frees all resources allocated by previous + calls to @code{glob} associated with the object pointed to by + @var{pglob}. This function should be called whenever the currently used +@@ -660,6 +765,7 @@ + @comment glob.h + @comment GNU + @deftypefun void globfree64 (glob64_t *@var{pglob}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} + This function is equivalent to @code{globfree} but it frees records of + type @code{glob64_t} which were allocated by @code{glob64}. + @end deftypefun +@@ -722,6 +828,250 @@ + @comment regex.h + @comment POSIX.2 + @deftypefun int regcomp (regex_t *restrict @var{compiled}, const char *restrict @var{pattern}, int @var{cflags}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} ++@c All of the issues have to do with memory allocation and multi-byte ++@c character handling present in the input string, or implied by ranges ++@c or inverted character classes. ++@c (re_)malloc @ascuheap @acsmem ++@c re_compile_internal @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c (re_)realloc @ascuheap @acsmem [no @asucorrupt @acucorrupt for we zero the buffer] ++@c init_dfa @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c (re_)malloc @ascuheap @acsmem ++@c calloc @ascuheap @acsmem ++@c _NL_CURRENT ok ++@c _NL_CURRENT_WORD ok ++@c btowc @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c libc_lock_init ok ++@c re_string_construct @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c re_string_construct_common ok ++@c re_string_realloc_buffers @ascuheap @acsmem ++@c (re_)realloc dup @ascuheap @acsmem ++@c build_wcs_upper_buffer @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c isascii ok ++@c mbsinit ok ++@c toupper ok ++@c mbrtowc dup @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c iswlower @mtslocale ++@c towupper @mtslocale ++@c wcrtomb dup @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c (re_)malloc dup @ascuheap @acsmem ++@c build_upper_buffer ok (@mtslocale but optimized) ++@c islower ok ++@c toupper ok ++@c build_wcs_buffer @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c mbrtowc dup @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c re_string_translate_buffer ok ++@c parse @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c fetch_token @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c peek_token @mtslocale ++@c re_string_eoi ok ++@c re_string_peek_byte ok ++@c re_string_cur_idx ok ++@c re_string_length ok ++@c re_string_peek_byte_case @mtslocale ++@c re_string_peek_byte dup ok ++@c re_string_is_single_byte_char ok ++@c isascii ok ++@c re_string_peek_byte dup ok ++@c re_string_wchar_at ok ++@c re_string_skip_bytes ok ++@c re_string_skip_bytes dup ok ++@c parse_reg_exp @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c parse_branch @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c parse_expression @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c create_token_tree dup @ascuheap @acsmem ++@c re_string_eoi dup ok ++@c re_string_first_byte ok ++@c fetch_token dup @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c create_tree dup @ascuheap @acsmem ++@c parse_sub_exp @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c fetch_token dup @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c parse_reg_exp dup @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c postorder() @ascuheap @acsmem ++@c free_tree @ascuheap @acsmem ++@c free_token dup @ascuheap @acsmem ++@c create_tree dup @ascuheap @acsmem ++@c parse_bracket_exp @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c _NL_CURRENT dup ok ++@c _NL_CURRENT_WORD dup ok ++@c calloc dup @ascuheap @acsmem ++@c (re_)free dup @ascuheap @acsmem ++@c peek_token_bracket ok ++@c re_string_eoi dup ok ++@c re_string_peek_byte dup ok ++@c re_string_first_byte dup ok ++@c re_string_cur_idx dup ok ++@c re_string_length dup ok ++@c re_string_skip_bytes dup ok ++@c bitset_set ok ++@c re_string_skip_bytes ok ++@c parse_bracket_element @mtslocale ++@c re_string_char_size_at ok ++@c re_string_wchar_at dup ok ++@c re_string_skip_bytes dup ok ++@c parse_bracket_symbol @mtslocale ++@c re_string_eoi dup ok ++@c re_string_fetch_byte_case @mtslocale ++@c re_string_fetch_byte ok ++@c re_string_first_byte dup ok ++@c isascii ok ++@c re_string_char_size_at dup ok ++@c re_string_skip_bytes dup ok ++@c re_string_fetch_byte dup ok ++@c re_string_peek_byte dup ok ++@c re_string_skip_bytes dup ok ++@c peek_token_bracket dup ok ++@c auto build_range_exp @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c auto lookup_collation_sequence_value @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c btowc dup @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c collseq_table_lookup ok ++@c auto seek_collating_symbol_entry dup ok ++@c (re_)realloc dup @ascuheap @acsmem ++@c collseq_table_lookup dup ok ++@c bitset_set dup ok ++@c (re_)realloc dup @ascuheap @acsmem ++@c build_equiv_class @mtslocale @ascuheap @acsmem ++@c _NL_CURRENT ok ++@c auto findidx ok ++@c bitset_set dup ok ++@c (re_)realloc dup @ascuheap @acsmem ++@c auto build_collating_symbol @ascuheap @acsmem ++@c auto seek_collating_symbol_entry ok ++@c bitset_set dup ok ++@c (re_)realloc dup @ascuheap @acsmem ++@c build_charclass @mtslocale @ascuheap @acsmem ++@c (re_)realloc dup @ascuheap @acsmem ++@c bitset_set dup ok ++@c isalnum ok ++@c iscntrl ok ++@c isspace ok ++@c isalpha ok ++@c isdigit ok ++@c isprint ok ++@c isupper ok ++@c isblank ok ++@c isgraph ok ++@c ispunct ok ++@c isxdigit ok ++@c bitset_not ok ++@c bitset_mask ok ++@c create_token_tree dup @ascuheap @acsmem ++@c create_tree dup @ascuheap @acsmem ++@c free_charset dup @ascuheap @acsmem ++@c init_word_char @mtslocale ++@c isalnum ok ++@c build_charclass_op @mtslocale @ascuheap @acsmem ++@c calloc dup @ascuheap @acsmem ++@c build_charclass dup @mtslocale @ascuheap @acsmem ++@c (re_)free dup @ascuheap @acsmem ++@c free_charset dup @ascuheap @acsmem ++@c bitset_set dup ok ++@c bitset_not dup ok ++@c bitset_mask dup ok ++@c create_token_tree dup @ascuheap @acsmem ++@c create_tree dup @ascuheap @acsmem ++@c parse_dup_op @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c re_string_cur_idx dup ok ++@c fetch_number @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c fetch_token dup @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c re_string_set_index ok ++@c postorder() @ascuheap @acsmem ++@c free_tree dup @ascuheap @acsmem ++@c mark_opt_subexp ok ++@c duplicate_tree @ascuheap @acsmem ++@c create_token_tree dup @ascuheap @acsmem ++@c create_tree dup @ascuheap @acsmem ++@c postorder() @ascuheap @acsmem ++@c free_tree dup @ascuheap @acsmem ++@c fetch_token dup @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c parse_branch dup @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c create_tree dup @ascuheap @acsmem ++@c create_tree @ascuheap @acsmem ++@c create_token_tree @ascuheap @acsmem ++@c (re_)malloc dup @ascuheap @acsmem ++@c analyze @ascuheap @acsmem ++@c (re_)malloc dup @ascuheap @acsmem ++@c preorder() @ascuheap @acsmem ++@c optimize_subexps ok ++@c calc_next ok ++@c link_nfa_nodes @ascuheap @acsmem ++@c re_node_set_init_1 @ascuheap @acsmem ++@c (re_)malloc dup @ascuheap @acsmem ++@c re_node_set_init_2 @ascuheap @acsmem ++@c (re_)malloc dup @ascuheap @acsmem ++@c postorder() @ascuheap @acsmem ++@c lower_subexps @ascuheap @acsmem ++@c lower_subexp @ascuheap @acsmem ++@c create_tree dup @ascuheap @acsmem ++@c calc_first @ascuheap @acsmem ++@c re_dfa_add_node @ascuheap @acsmem ++@c (re_)realloc dup @ascuheap @acsmem ++@c re_node_set_init_empty ok ++@c calc_eclosure @ascuheap @acsmem ++@c calc_eclosure_iter @ascuheap @acsmem ++@c re_node_set_alloc @ascuheap @acsmem ++@c (re_)malloc dup @ascuheap @acsmem ++@c duplicate_node_closure @ascuheap @acsmem ++@c re_node_set_empty ok ++@c duplicate_node @ascuheap @acsmem ++@c re_dfa_add_node dup @ascuheap @acsmem ++@c re_node_set_insert @ascuheap @acsmem ++@c (re_)realloc dup @ascuheap @acsmem ++@c search_duplicated_node ok ++@c re_node_set_merge @ascuheap @acsmem ++@c (re_)realloc dup @ascuheap @acsmem ++@c re_node_set_free @ascuheap @acsmem ++@c (re_)free dup @ascuheap @acsmem ++@c re_node_set_insert dup @ascuheap @acsmem ++@c re_node_set_free dup @ascuheap @acsmem ++@c calc_inveclosure @ascuheap @acsmem ++@c re_node_set_init_empty dup ok ++@c re_node_set_insert_last @ascuheap @acsmem ++@c (re_)realloc dup @ascuheap @acsmem ++@c optimize_utf8 ok ++@c create_initial_state @ascuheap @acsmem ++@c re_node_set_init_copy @ascuheap @acsmem ++@c (re_)malloc dup @ascuheap @acsmem ++@c re_node_set_init_empty dup ok ++@c re_node_set_contains ok ++@c re_node_set_merge dup @ascuheap @acsmem ++@c re_acquire_state_context @ascuheap @acsmem ++@c calc_state_hash ok ++@c re_node_set_compare ok ++@c create_cd_newstate @ascuheap @acsmem ++@c calloc dup @ascuheap @acsmem ++@c re_node_set_init_copy dup @ascuheap @acsmem ++@c (re_)free dup @ascuheap @acsmem ++@c free_state @ascuheap @acsmem ++@c re_node_set_free dup @ascuheap @acsmem ++@c (re_)free dup @ascuheap @acsmem ++@c NOT_SATISFY_PREV_CONSTRAINT ok ++@c re_node_set_remove_at ok ++@c register_state @ascuheap @acsmem ++@c re_node_set_alloc dup @ascuheap @acsmem ++@c re_node_set_insert_last dup @ascuheap @acsmem ++@c (re_)realloc dup @ascuheap @acsmem ++@c re_node_set_free dup @ascuheap @acsmem ++@c free_workarea_compile @ascuheap @acsmem ++@c (re_)free dup @ascuheap @acsmem ++@c re_string_destruct @ascuheap @acsmem ++@c (re_)free dup @ascuheap @acsmem ++@c free_dfa_content @ascuheap @acsmem ++@c free_token @ascuheap @acsmem ++@c free_charset @ascuheap @acsmem ++@c (re_)free dup @ascuheap @acsmem ++@c (re_)free dup @ascuheap @acsmem ++@c (re_)free dup @ascuheap @acsmem ++@c re_node_set_free dup @ascuheap @acsmem ++@c re_compile_fastmap @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c re_compile_fastmap_iter @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c re_set_fastmap ok ++@c tolower ok ++@c mbrtowc dup @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c wcrtomb dup @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c towlower @mtslocale ++@c _NL_CURRENT ok ++@c (re_)free @ascuheap @acsmem + The function @code{regcomp} ``compiles'' a regular expression into a + data structure that you can use with @code{regexec} to match against a + string. The compiled regular expression format is designed for +@@ -871,6 +1221,247 @@ + @comment regex.h + @comment POSIX.2 + @deftypefun int regexec (const regex_t *restrict @var{compiled}, const char *restrict @var{string}, size_t @var{nmatch}, regmatch_t @var{matchptr}[restrict], int @var{eflags}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} ++@c libc_lock_lock @asulock @aculock ++@c re_search_internal @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c re_string_allocate @ascuheap @acsmem ++@c re_string_construct_common dup ok ++@c re_string_realloc_buffers dup @ascuheap @acsmem ++@c match_ctx_init @ascuheap @acsmem ++@c (re_)malloc dup @ascuheap @acsmem ++@c re_string_byte_at ok ++@c re_string_first_byte dup ok ++@c check_matching @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c re_string_cur_idx dup ok ++@c acquire_init_state_context dup @ascuheap @acsmem ++@c re_string_context_at ok ++@c re_string_byte_at dup ok ++@c bitset_contain ok ++@c re_acquire_state_context dup @ascuheap @acsmem ++@c check_subexp_matching_top @ascuheap @acsmem ++@c match_ctx_add_subtop @ascuheap @acsmem ++@c (re_)realloc dup @ascuheap @acsmem ++@c calloc dup @ascuheap @acsmem ++@c transit_state_bkref @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c re_string_cur_idx dup ok ++@c re_string_context_at dup ok ++@c NOT_SATISFY_NEXT_CONSTRAINT ok ++@c get_subexp @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c re_string_get_buffer ok ++@c search_cur_bkref_entry ok ++@c clean_state_log_if_needed @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c extend_buffers @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c re_string_realloc_buffers dup @ascuheap @acsmem ++@c (re_)realloc dup @ascuheap @acsmem ++@c build_wcs_upper_buffer dup @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c build_upper_buffer dup ok (@mtslocale but optimized) ++@c build_wcs_buffer dup @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c re_string_translate_buffer dup ok ++@c get_subexp_sub @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c check_arrival @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c (re_)realloc dup @ascuheap @acsmem ++@c re_string_context_at dup ok ++@c re_node_set_init_1 dup @ascuheap @acsmem ++@c check_arrival_expand_ecl @ascuheap @acsmem ++@c re_node_set_alloc dup @ascuheap @acsmem ++@c find_subexp_node ok ++@c re_node_set_merge dup @ascuheap @acsmem ++@c re_node_set_free dup @ascuheap @acsmem ++@c check_arrival_expand_ecl_sub @ascuheap @acsmem ++@c re_node_set_contains dup ok ++@c re_node_set_insert dup @ascuheap @acsmem ++@c re_node_set_free dup @ascuheap @acsmem ++@c re_node_set_init_copy dup @ascuheap @acsmem ++@c re_node_set_init_empty dup ok ++@c expand_bkref_cache @ascuheap @acsmem ++@c search_cur_bkref_entry dup ok ++@c re_node_set_contains dup ok ++@c re_node_set_init_1 dup @ascuheap @acsmem ++@c check_arrival_expand_ecl dup @ascuheap @acsmem ++@c re_node_set_merge dup @ascuheap @acsmem ++@c re_node_set_init_copy dup @ascuheap @acsmem ++@c re_node_set_insert dup @ascuheap @acsmem ++@c re_node_set_free dup @ascuheap @acsmem ++@c re_acquire_state @ascuheap @acsmem ++@c calc_state_hash dup ok ++@c re_node_set_compare dup ok ++@c create_ci_newstate @ascuheap @acsmem ++@c calloc dup @ascuheap @acsmem ++@c re_node_set_init_copy dup @ascuheap @acsmem ++@c (re_)free dup @ascuheap @acsmem ++@c register_state dup @ascuheap @acsmem ++@c free_state dup @ascuheap @acsmem ++@c re_acquire_state_context dup @ascuheap @acsmem ++@c re_node_set_merge dup @ascuheap @acsmem ++@c check_arrival_add_next_nodes @mtslocale @ascuheap @acsmem ++@c re_node_set_init_empty dup ok ++@c check_node_accept_bytes @mtslocale @ascuheap @acsmem ++@c re_string_byte_at dup ok ++@c re_string_char_size_at dup ok ++@c re_string_elem_size_at @mtslocale ++@c _NL_CURRENT_WORD dup ok ++@c _NL_CURRENT dup ok ++@c auto findidx dup ok ++@c _NL_CURRENT_WORD dup ok ++@c _NL_CURRENT dup ok ++@c collseq_table_lookup dup ok ++@c find_collation_sequence_value @mtslocale ++@c _NL_CURRENT_WORD dup ok ++@c _NL_CURRENT dup ok ++@c auto findidx dup ok ++@c wcscoll @mtslocale @ascuheap @acsmem ++@c re_node_set_empty dup ok ++@c re_node_set_merge dup @ascuheap @acsmem ++@c re_node_set_free dup @ascuheap @acsmem ++@c re_node_set_insert dup @ascuheap @acsmem ++@c re_acquire_state dup @ascuheap @acsmem ++@c check_node_accept ok ++@c re_string_byte_at dup ok ++@c bitset_contain dup ok ++@c re_string_context_at dup ok ++@c NOT_SATISFY_NEXT_CONSTRAINT dup ok ++@c match_ctx_add_entry @ascuheap @acsmem ++@c (re_)realloc dup @ascuheap @acsmem ++@c (re_)free dup @ascuheap @acsmem ++@c clean_state_log_if_needed dup @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c extend_buffers dup @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c find_subexp_node dup ok ++@c calloc dup @ascuheap @acsmem ++@c check_arrival dup *** ++@c match_ctx_add_sublast @ascuheap @acsmem ++@c (re_)realloc dup @ascuheap @acsmem ++@c re_acquire_state_context dup @ascuheap @acsmem ++@c re_node_set_init_union @ascuheap @acsmem ++@c (re_)malloc dup @ascuheap @acsmem ++@c re_node_set_init_copy dup @ascuheap @acsmem ++@c re_node_set_init_empty dup ok ++@c re_node_set_free dup @ascuheap @acsmem ++@c check_subexp_matching_top dup @ascuheap @acsmem ++@c check_halt_state_context ok ++@c re_string_context_at dup ok ++@c check_halt_node_context ok ++@c NOT_SATISFY_NEXT_CONSTRAINT dup ok ++@c re_string_eoi dup ok ++@c extend_buffers dup @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c transit_state @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c transit_state_mb @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c re_string_context_at dup ok ++@c NOT_SATISFY_NEXT_CONSTRAINT dup ok ++@c check_node_accept_bytes dup @mtslocale @ascuheap @acsmem ++@c re_string_cur_idx dup ok ++@c clean_state_log_if_needed @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c re_node_set_init_union dup @ascuheap @acsmem ++@c re_acquire_state_context dup @ascuheap @acsmem ++@c re_string_fetch_byte dup ok ++@c re_string_context_at dup ok ++@c build_trtable @ascuheap @acsmem ++@c (re_)malloc dup @ascuheap @acsmem ++@c group_nodes_into_DFAstates @ascuheap @acsmem ++@c bitset_empty dup ok ++@c bitset_set dup ok ++@c bitset_merge dup ok ++@c bitset_set_all ok ++@c bitset_clear ok ++@c bitset_contain dup ok ++@c bitset_copy ok ++@c re_node_set_init_copy dup @ascuheap @acsmem ++@c re_node_set_insert dup @ascuheap @acsmem ++@c re_node_set_init_1 dup @ascuheap @acsmem ++@c re_node_set_free dup @ascuheap @acsmem ++@c re_node_set_alloc dup @ascuheap @acsmem ++@c malloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c re_node_set_free dup @ascuheap @acsmem ++@c bitset_empty ok ++@c re_node_set_empty dup ok ++@c re_node_set_merge dup @ascuheap @acsmem ++@c re_acquire_state_context dup @ascuheap @acsmem ++@c bitset_merge ok ++@c calloc dup @ascuheap @acsmem ++@c bitset_contain dup ok ++@c merge_state_with_log @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c re_string_cur_idx dup ok ++@c re_node_set_init_union dup @ascuheap @acsmem ++@c re_string_context_at dup ok ++@c re_node_set_free dup @ascuheap @acsmem ++@c check_subexp_matching_top @ascuheap @acsmem ++@c match_ctx_add_subtop dup @ascuheap @acsmem ++@c transit_state_bkref dup @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c find_recover_state ++@c re_string_cur_idx dup ok ++@c re_string_skip_bytes dup ok ++@c merge_state_with_log dup @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c check_halt_state_context dup ok ++@c prune_impossible_nodes @mtslocale @ascuheap @acsmem ++@c (re_)malloc dup @ascuheap @acsmem ++@c sift_ctx_init ok ++@c re_node_set_init_empty dup ok ++@c sift_states_backward @mtslocale @ascuheap @acsmem ++@c re_node_set_init_1 dup @ascuheap @acsmem ++@c update_cur_sifted_state @mtslocale @ascuheap @acsmem ++@c add_epsilon_src_nodes @ascuheap @acsmem ++@c re_acquire_state dup @ascuheap @acsmem ++@c re_node_set_alloc dup @ascuheap @acsmem ++@c re_node_set_merge dup @ascuheap @acsmem ++@c re_node_set_add_intersect @ascuheap @acsmem ++@c (re_)realloc dup @ascuheap @acsmem ++@c check_subexp_limits @ascuheap @acsmem ++@c sub_epsilon_src_nodes @ascuheap @acsmem ++@c re_node_set_init_empty dup ok ++@c re_node_set_contains dup ok ++@c re_node_set_add_intersect dup @ascuheap @acsmem ++@c re_node_set_free dup @ascuheap @acsmem ++@c re_node_set_remove_at dup ok ++@c re_node_set_contains dup ok ++@c re_acquire_state dup @ascuheap @acsmem ++@c sift_states_bkref @mtslocale @ascuheap @acsmem ++@c search_cur_bkref_entry dup ok ++@c check_dst_limits ok ++@c search_cur_bkref_entry dup ok ++@c check_dst_limits_calc_pos ok ++@c check_dst_limits_calc_pos_1 ok ++@c re_node_set_init_copy dup @ascuheap @acsmem ++@c re_node_set_insert dup @ascuheap @acsmem ++@c sift_states_backward dup @mtslocale @ascuheap @acsmem ++@c merge_state_array dup @ascuheap @acsmem ++@c re_node_set_remove ok ++@c re_node_set_contains dup ok ++@c re_node_set_remove_at dup ok ++@c re_node_set_free dup @ascuheap @acsmem ++@c re_node_set_free dup @ascuheap @acsmem ++@c re_node_set_empty dup ok ++@c build_sifted_states @mtslocale @ascuheap @acsmem ++@c sift_states_iter_mb @mtslocale @ascuheap @acsmem ++@c check_node_accept_bytes dup @mtslocale @ascuheap @acsmem ++@c check_node_accept dup ok ++@c check_dst_limits dup ok ++@c re_node_set_insert dup @ascuheap @acsmem ++@c re_node_set_free dup @ascuheap @acsmem ++@c check_halt_state_context dup ok ++@c merge_state_array @ascuheap @acsmem ++@c re_node_set_init_union dup @ascuheap @acsmem ++@c re_acquire_state dup @ascuheap @acsmem ++@c re_node_set_free dup @ascuheap @acsmem ++@c (re_)free dup @ascuheap @acsmem ++@c set_regs @ascuheap @acsmem ++@c (re_)malloc dup @ascuheap @acsmem ++@c re_node_set_init_empty dup ok ++@c free_fail_stack_return @ascuheap @acsmem ++@c re_node_set_free dup @ascuheap @acsmem ++@c (re_)free dup @ascuheap @acsmem ++@c update_regs ok ++@c re_node_set_free dup @ascuheap @acsmem ++@c pop_fail_stack @ascuheap @acsmem ++@c re_node_set_free dup @ascuheap @acsmem ++@c (re_)free dup @ascuheap @acsmem ++@c (re_)free dup @ascuheap @acsmem ++@c (re_)free dup @ascuheap @acsmem ++@c match_ctx_free @ascuheap @acsmem ++@c match_ctx_clean @ascuheap @acsmem ++@c (re_)free dup @ascuheap @acsmem ++@c (re_)free dup @ascuheap @acsmem ++@c re_string_destruct dup @ascuheap @acsmem ++@c libc_lock_unlock @aculock + This function tries to match the compiled regular expression + @code{*@var{compiled}} against @var{string}. + +@@ -1033,6 +1624,9 @@ + @comment regex.h + @comment POSIX.2 + @deftypefun void regfree (regex_t *@var{compiled}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} ++@c (re_)free dup @ascuheap @acsmem ++@c free_dfa_content dup @ascuheap @acsmem + Calling @code{regfree} frees all the storage that @code{*@var{compiled}} + points to. This includes various internal fields of the @code{regex_t} + structure that aren't documented in this manual. +@@ -1050,6 +1644,8 @@ + @comment regex.h + @comment POSIX.2 + @deftypefun size_t regerror (int @var{errcode}, const regex_t *restrict @var{compiled}, char *restrict @var{buffer}, size_t @var{length}) ++@safety{@prelim{}@mtsafe{@mtsenv{}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c regerror calls gettext, strcmp and mempcpy or memcpy. + This function produces an error message string for the error code + @var{errcode}, and stores the string in @var{length} bytes of memory + starting at @var{buffer}. For the @var{compiled} argument, supply the +@@ -1215,6 +1811,145 @@ + @comment wordexp.h + @comment POSIX.2 + @deftypefun int wordexp (const char *@var{words}, wordexp_t *@var{word-vector-ptr}, int @var{flags}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtasuconst{:@mtsenv{}} @mtsenv{} @mtascusig{:ALRM} @mtascutimer{} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuintl{} @ascuheap{} @asucorrupt{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c wordexp @mtasurace:utent @mtasuconst:@mtsenv @mtsenv @mtascusig:ALRM @mtascutimer @mtslocale @ascudlopen @ascuplugin @ascuintl @ascuheap @asucorrupt @asulock @acucorrupt @aculock @acsfd @acsmem ++@c w_newword ok ++@c wordfree dup @asucorrupt @ascuheap @acucorrupt @acsmem ++@c calloc dup @ascuheap @acsmem ++@c getenv dup @mtsenv ++@c strcpy dup ok ++@c parse_backslash @ascuheap @acsmem ++@c w_addchar dup @ascuheap @acsmem ++@c parse_dollars @mtasuconst:@mtsenv @mtslocale @mtsenv @ascudlopen @ascuplugin @ascuintl @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c w_addchar dup @ascuheap @acsmem ++@c parse_arith @mtasuconst:@mtsenv @mtslocale @mtsenv @ascudlopen @ascuplugin @ascuintl @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c w_newword dup ok ++@c parse_dollars dup @mtasuconst:@mtsenv @mtslocale @mtsenv @ascudlopen @ascuplugin @ascuintl @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c parse_backtick dup @ascuplugin @ascuheap @aculock @acsfd @acsmem ++@c parse_qtd_backslash dup @ascuheap @acsmem ++@c eval_expr @mtslocale ++@c eval_expr_multidiv @mtslocale ++@c eval_expr_val @mtslocale ++@c isspace dup @mtslocale ++@c eval_expr dup @mtslocale ++@c isspace dup @mtslocale ++@c isspace dup @mtslocale ++@c free dup @ascuheap @acsmem ++@c w_addchar dup @ascuheap @acsmem ++@c w_addstr dup @ascuheap @acsmem ++@c itoa_word dup ok ++@c parse_comm @ascuplugin @ascuheap @aculock @acsfd @acsmem ++@c w_newword dup ok ++@c pthread_setcancelstate @ascuplugin @ascuheap @acsmem ++@c (disable cancellation around exec_comm; it may do_cancel the ++@c second time, if async cancel is enabled) ++@c THREAD_ATOMIC_CMPXCHG_VAL dup ok ++@c CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS dup ok ++@c do_cancel @ascuplugin @ascuheap @acsmem ++@c THREAD_ATOMIC_BIT_SET dup ok ++@c pthread_unwind @ascuplugin @ascuheap @acsmem ++@c Unwind_ForcedUnwind if available @ascuplugin @ascuheap @acsmem ++@c libc_unwind_longjmp otherwise ++@c cleanups ++@c exec_comm @ascuplugin @ascuheap @aculock @acsfd @acsmem ++@c pipe2 dup ok ++@c pipe dup ok ++@c fork dup @ascuplugin @aculock ++@c close dup @acsfd ++@c on child: exec_comm_child -> exec or abort ++@c waitpid dup ok ++@c read dup ok ++@c w_addmem dup @ascuheap @acsmem ++@c strchr dup ok ++@c w_addword dup @ascuheap @acsmem ++@c w_newword dup ok ++@c w_addchar dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c kill dup ok ++@c free dup @ascuheap @acsmem ++@c parse_param @mtasuconst:@mtsenv @mtslocale @mtsenv @ascudlopen @ascuplugin @ascuintl @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c reads from __libc_argc and __libc_argv without guards ++@c w_newword dup ok ++@c isalpha dup @mtslocale^^ ++@c w_addchar dup @ascuheap @acsmem ++@c isalnum dup @mtslocale^^ ++@c isdigit dup @mtslocale^^ ++@c strchr dup ok ++@c itoa_word dup ok ++@c atoi dup @mtslocale ++@c getpid dup ok ++@c w_addstr dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c strlen dup ok ++@c malloc dup @ascuheap @acsmem ++@c stpcpy dup ok ++@c w_addword dup @ascuheap @acsmem ++@c strdup dup @ascuheap @acsmem ++@c getenv dup @mtsenv ++@c parse_dollars dup @mtasuconst:@mtsenv @mtslocale @mtsenv @ascudlopen @ascuplugin @ascuintl @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c parse_tilde dup @mtslocale @mtsenv @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c fnmatch dup @mtsenv @mtslocale @ascuheap @acsmem ++@c mempcpy dup ok ++@c _ dup @ascuintl ++@c fxprintf dup @aculock ++@c setenv dup @mtasuconst:@mtsenv @ascuheap @asulock @acucorrupt @aculock @acsmem ++@c strspn dup ok ++@c strcspn dup ok ++@c parse_backtick @ascuplugin @ascuheap @aculock @acsfd @acsmem ++@c w_newword dup ok ++@c exec_comm dup @ascuplugin @ascuheap @aculock @acsfd @acsmem ++@c free dup @ascuheap @acsmem ++@c parse_qtd_backslash dup @ascuheap @acsmem ++@c parse_backslash dup @ascuheap @acsmem ++@c w_addchar dup @ascuheap @acsmem ++@c parse_dquote @mtasuconst:@mtsenv @mtslocale @mtsenv @ascudlopen @ascuplugin @ascuintl @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c parse_dollars dup @mtasuconst:@mtsenv @mtslocale @mtsenv @ascudlopen @ascuplugin @ascuintl @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c parse_backtick dup @ascuplugin @ascuheap @aculock @acsfd @acsmem ++@c parse_qtd_backslash dup @ascuheap @acsmem ++@c w_addchar dup @ascuheap @acsmem ++@c w_addword dup @ascuheap @acsmem ++@c strdup dup @ascuheap @acsmem ++@c realloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c parse_squote dup @ascuheap @acsmem ++@c w_addchar dup @ascuheap @acsmem ++@c parse_tilde @mtslocale @mtsenv @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c strchr dup ok ++@c w_addchar dup @ascuheap @acsmem ++@c getenv dup @mtsenv ++@c w_addstr dup @ascuheap @acsmem ++@c strlen dup ok ++@c w_addmem dup @ascuheap @acsmem ++@c realloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c mempcpy dup ok ++@c getuid dup ok ++@c getpwuid_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c getpwnam_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c parse_glob @mtasurace:utent @mtasuconst:@mtsenv @mtsenv @mtascusig:ALRM @mtascutimer @mtslocale @ascudlopen @ascuplugin @ascuintl @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c strchr dup ok ++@c parse_dollars dup @mtasuconst:@mtsenv @mtslocale @mtsenv @ascudlopen @ascuplugin @ascuintl @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c parse_qtd_backslash @ascuheap @acsmem ++@c w_addchar dup @ascuheap @acsmem ++@c parse_backslash dup @ascuheap @acsmem ++@c w_addchar dup @ascuheap @acsmem ++@c w_addword dup @ascuheap @acsmem ++@c w_newword dup ok ++@c do_parse_glob @mtasurace:utent @mtsenv @mtascusig:ALRM @mtascutimer @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @aculock @acsfd @acsmem ++@c glob dup @mtasurace:utent @mtsenv @mtascusig:ALRM @mtascutimer @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @aculock @acsfd @acsmem [auto glob_t avoids @asucorrupt @acucorrupt] ++@c w_addstr dup @ascuheap @acsmem ++@c w_addchar dup @ascuheap @acsmem ++@c globfree dup @ascuheap @acsmem [auto glob_t avoids @asucorrupt @acucorrupt] ++@c free dup @ascuheap @acsmem ++@c w_newword dup ok ++@c strdup dup @ascuheap @acsmem ++@c w_addword dup @ascuheap @acsmem ++@c wordfree dup @asucorrupt @ascuheap @acucorrupt @acsmem ++@c strchr dup ok ++@c w_addchar dup @ascuheap @acsmem ++@c realloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem + Perform word expansion on the string @var{words}, putting the result in + a newly allocated vector, and store the size and address of this vector + into @code{*@var{word-vector-ptr}}. The argument @var{flags} is a +@@ -1278,6 +2013,9 @@ + @comment wordexp.h + @comment POSIX.2 + @deftypefun void wordfree (wordexp_t *@var{word-vector-ptr}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{}}} ++@c wordfree dup @asucorrupt @ascuheap @acucorrupt @acsmem ++@c free dup @ascuheap @acsmem + Free the storage used for the word-strings and vector that + @code{*@var{word-vector-ptr}} points to. This does not free the + structure @code{*@var{word-vector-ptr}} itself---only the other +diff -urN glibc-2.17-c758a686/manual/pipe.texi glibc-2.17-c758a686/manual/pipe.texi +--- glibc-2.17-c758a686/manual/pipe.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/pipe.texi 2014-09-12 16:10:06.048792709 -0400 +@@ -56,6 +56,8 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun int pipe (int @var{filedes}@t{[2]}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{@acsfd{}}} ++@c On Linux, syscall pipe2. On HURD, call socketpair. + The @code{pipe} function creates a pipe and puts the file descriptors + for the reading and writing ends of the pipe (respectively) into + @code{@var{filedes}[0]} and @code{@var{filedes}[1]}. +@@ -108,6 +110,41 @@ + @comment stdio.h + @comment POSIX.2, SVID, BSD + @deftypefun {FILE *} popen (const char *@var{command}, const char *@var{mode}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c popen @ascuheap @asucorrupt @acucorrupt @aculock @acsfd @acsmem ++@c malloc dup @ascuheap @acsmem ++@c _IO_init ok ++@c _IO_no_init ok ++@c _IO_old_init ok ++@c _IO_lock_init ok ++@c _IO_new_file_init @asucorrupt @acucorrupt @aculock @acsfd ++@c _IO_link_in @asucorrupt @acucorrupt @aculock @acsfd ++@c the linked list is guarded by a recursive lock; ++@c it may get corrupted with async signals and cancellation ++@c _IO_lock_lock dup @aculock ++@c _IO_flockfile dup @aculock ++@c _IO_funlockfile dup @aculock ++@c _IO_lock_unlock dup @aculock ++@c _IO_new_proc_open @asucorrupt @acucorrupt @aculock @acsfd ++@c the linked list is guarded by a recursive lock; ++ @c it may get corrupted with async signals and cancellation ++@c _IO_file_is_open ok ++@c pipe2 dup @acsfd ++@c pipe dup @acsfd ++@c _IO_fork=fork @aculock ++@c _IO_close=close_not_cancel dup @acsfd ++@c fcntl dup ok ++@c _IO_lock_lock @aculock ++@c _IO_lock_unlock @aculock ++@c _IO_mask_flags ok [no @mtasurace:stream, nearly but sufficiently exclusive access] ++@c _IO_un_link @asucorrupt @acucorrupt @aculock @acsfd ++@c the linked list is guarded by a recursive lock; ++@c it may get corrupted with async signals and cancellation ++@c _IO_lock_lock dup @aculock ++@c _IO_flockfile dup @aculock ++@c _IO_funlockfile dup @aculock ++@c _IO_lock_unlock dup @aculock ++@c free dup @ascuheap @acsmem + The @code{popen} function is closely related to the @code{system} + function; see @ref{Running a Command}. It executes the shell command + @var{command} as a subprocess. However, instead of waiting for the +@@ -131,6 +168,77 @@ + @comment stdio.h + @comment POSIX.2, SVID, BSD + @deftypefun int pclose (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @ascuplugin{} @asucorrupt{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c Although the stream cannot be used after the call, even in case of ++@c async cancellation, because the stream must not be used after pclose ++@c is called, other stdio linked lists and their locks may be left in ++@c corrupt states; that's where the corrupt and lock annotations come ++@c from. ++@c ++@c pclose @ascuheap @ascuplugin @asucorrupt @asulock @acucorrupt @aculock @acsfd @acsmem ++@c _IO_new_fclose @ascuheap @ascuplugin @asucorrupt @asulock @acucorrupt @aculock @acsfd @acsmem ++@c _IO_un_link dup @asucorrupt @acucorrupt @aculock @acsfd ++@c _IO_acquire_lock dup @aculock ++@c _IO_flockfile dup @aculock ++@c _IO_file_close_it @ascuheap @ascuplugin @asucorrupt @aculock @acucorrupt @acsfd @acsmem ++@c _IO_file_is_open dup ok ++@c _IO_do_flush @asucorrupt @ascuplugin @acucorrupt ++@c _IO_do_write @asucorrupt @acucorrupt ++@c new_do_write @asucorrupt @acucorrupt ++@c _IO_SYSSEEK ok ++@c lseek64 dup ok ++@c _IO_SYSWRITE ok ++@c write_not_cancel dup ok ++@c write dup ok ++@c _IO_adjust_column ok ++@c _IO_setg dup @asucorrupt @acucorrupt [no @mtasurace:stream, locked] ++@c _IO_wdo_write @asucorrupt @ascuplugin @acucorrupt ++@c _IO_new_do_write=_IO_do_write dup @asucorrupt @acucorrupt ++@c *cc->__codecvt_do_out @ascuplugin ++@c _IO_wsetg dup @asucorrupt @acucorrupt [no @mtasurace:stream, locked] ++@c _IO_unsave_markers @ascuheap @asucorrupt @acucorrupt @acsmem ++@c _IO_have_backup dup ok ++@c _IO_free_backup_area dup @ascuheap @asucorrupt @acucorrupt @acsmem ++@c _IO_SYSCLOSE @aculock @acucorrupt @acsfd ++@c _IO_lock_lock dup @aculock ++@c _IO_close=close_not_cancel dup @acsfd ++@c _IO_lock_unlock dup @aculock ++@c _IO_waitpid=waitpid_not_cancel dup ok ++@c _IO_have_wbackup ok ++@c _IO_free_wbackup_area @ascuheap @asucorrupt @acucorrupt @acsmem ++@c _IO_in_backup dup ok ++@c _IO_switch_to_main_wget_area @asucorrupt @acucorrupt ++@c free dup @ascuheap @acsmem ++@c _IO_wsetb @asucorrupt @acucorrupt [no @mtasurace:stream, locked] ++@c _IO_wsetg @asucorrupt @acucorrupt [no @mtasurace:stream, locked] ++@c _IO_wsetp @asucorrupt @acucorrupt [no @mtasurace:stream, locked] ++@c _IO_setb @asucorrupt @acucorrupt [no @mtasurace:stream, locked] ++@c _IO_setg @asucorrupt @acucorrupt [no @mtasurace:stream, locked] ++@c _IO_setp @asucorrupt @acucorrupt [no @mtasurace:stream, locked] ++@c _IO_un_link dup @asucorrupt @acucorrupt @aculock @acsfd ++@c _IO_release_lock dup @aculock ++@c _IO_funlockfile dup @aculock ++@c _IO_FINISH @ascuheap @ascuplugin @asucorrupt @acucorrupt @aculock @acsfd @acsmem ++@c _IO_new_file_finish @ascuheap @ascuplugin @asucorrupt @acucorrupt @aculock @acsfd @acsmem ++@c _IO_file_is_open dup ok ++@c _IO_do_flush dup @ascuplugin @asucorrupt @acucorrupt ++@c _IO_SYSCLOSE dup @aculock @acucorrupt @acsfd ++@c _IO_default_finish @ascuheap @asucorrupt @acucorrupt @aculock @acsfd @acsmem ++@c FREE_BUF @acsmem ++@c munmap dup @acsmem ++@c free dup @ascuheap @acsmem ++@c _IO_un_link dup @asucorrupt @acucorrupt @aculock @acsfd ++@c _IO_lock_fini ok ++@c libc_lock_fini_recursive ok ++@c libc_lock_lock dup @asulock @aculock ++@c gconv_release_step ok ++@c libc_lock_unlock dup @asulock @aculock ++@c _IO_have_backup ok ++@c _IO_free_backup_area @ascuheap @asucorrupt @acucorrupt @acsmem ++@c _IO_in_backup ok ++@c _IO_switch_to_main_get_area @asucorrupt @acucorrupt ++@c free dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem + The @code{pclose} function is used to close a stream created by @code{popen}. + It waits for the child process to terminate and returns its status value, + as for the @code{system} function. +@@ -168,6 +276,8 @@ + @comment sys/stat.h + @comment POSIX.1 + @deftypefun int mkfifo (const char *@var{filename}, mode_t @var{mode}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c On generic Posix, calls xmknod. + The @code{mkfifo} function makes a FIFO special file with name + @var{filename}. The @var{mode} argument is used to set the file's + permissions; see @ref{Setting Permissions}. +diff -urN glibc-2.17-c758a686/manual/platform.texi glibc-2.17-c758a686/manual/platform.texi +--- glibc-2.17-c758a686/manual/platform.texi 2014-09-12 16:08:17.865070640 -0400 ++++ glibc-2.17-c758a686/manual/platform.texi 2014-09-12 16:10:06.046792714 -0400 +@@ -15,6 +15,7 @@ + operating system are declared in @file{sys/platform/ppc.h}. + + @deftypefun {uint64_t} __ppc_get_timebase (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Read the current value of the Time Base Register. + + The @dfn{Time Base Register} is a 64-bit register that stores a monotonically +@@ -28,6 +29,17 @@ + @end deftypefun + + @deftypefun {uint64_t} __ppc_get_timebase_freq (void) ++@safety{@prelim{}@mtunsafe{@mtuinit{}}@asunsafe{@asucorrupt{:init}}@acunsafe{@acucorrupt{:init}}} ++@c __ppc_get_timebase_freq=__get_timebase_freq @mtuinit @acsfd ++@c __get_clockfreq @mtuinit @asucorrupt:init @acucorrupt:init @acsfd ++@c the initialization of the static timebase_freq is not exactly ++@c safe, because hp_timing_t cannot be atomically set up. ++@c syscall:get_tbfreq ok ++@c open dup @acsfd ++@c read dup ok ++@c memcpy dup ok ++@c memmem dup ok ++@c close dup @acsfd + Read the current frequency at which the Time Base Register is updated. + + This frequency is not related to the processor clock or the bus clock. +@@ -42,17 +54,20 @@ + Section 3.2}. + + @deftypefun {void} __ppc_yield (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Provide a hint that performance will probably be improved if shared resources + dedicated to the executing processor are released for use by other processors. + @end deftypefun + + @deftypefun {void} __ppc_mdoio (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Provide a hint that performance will probably be improved if shared resources + dedicated to the executing processor are released until all outstanding storage + accesses to caching-inhibited storage have been completed. + @end deftypefun + + @deftypefun {void} __ppc_mdoom (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Provide a hint that performance will probably be improved if shared resources + dedicated to the executing processor are released until all outstanding storage + accesses to cacheable storage for which the data is not in the cache have been +@@ -60,6 +75,7 @@ + @end deftypefun + + @deftypefun {void} __ppc_set_ppr_med (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Set the Program Priority Register to medium value (default). + + The @dfn{Program Priority Register} (PPR) is a 64-bit register that controls +@@ -73,9 +89,11 @@ + @end deftypefun + + @deftypefun {void} __ppc_set_ppr_low (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Set the Program Priority Register to low value. + @end deftypefun + + @deftypefun {void} __ppc_set_ppr_med_low (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Set the Program Priority Register to medium low value. + @end deftypefun +diff -urN glibc-2.17-c758a686/manual/process.texi glibc-2.17-c758a686/manual/process.texi +--- glibc-2.17-c758a686/manual/process.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/process.texi 2014-09-12 16:10:06.044792719 -0400 +@@ -1,4 +1,4 @@ +-@node Processes, Job Control, Program Basics, Top ++@node Processes, Inter-Process Communication, Program Basics, Top + @c %MENU% How to create processes and run other programs + @chapter Processes + +@@ -55,6 +55,43 @@ + @comment ISO + @deftypefun int system (const char *@var{command}) + @pindex sh ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsmem{}}} ++@c system @ascuplugin @ascuheap @asulock @aculock @acsmem ++@c do_system @ascuplugin @ascuheap @asulock @aculock @acsmem ++@c sigemptyset dup ok ++@c libc_lock_lock @asulock @aculock ++@c ADD_REF ok ++@c sigaction dup ok ++@c SUB_REF ok ++@c libc_lock_unlock @aculock ++@c sigaddset dup ok ++@c sigprocmask dup ok ++@c CLEANUP_HANDLER @ascuplugin @ascuheap @acsmem ++@c libc_cleanup_region_start @ascuplugin @ascuheap @acsmem ++@c pthread_cleanup_push_defer @ascuplugin @ascuheap @acsmem ++@c CANCELLATION_P @ascuplugin @ascuheap @acsmem ++@c CANCEL_ENABLED_AND_CANCELED ok ++@c do_cancel @ascuplugin @ascuheap @acsmem ++@c cancel_handler ok ++@c kill syscall ok ++@c waitpid dup ok ++@c libc_lock_lock ok ++@c sigaction dup ok ++@c libc_lock_unlock ok ++@c FORK ok ++@c clone syscall ok ++@c waitpid dup ok ++@c CLEANUP_RESET ok ++@c libc_cleanup_region_end ok ++@c pthread_cleanup_pop_restore ok ++@c SINGLE_THREAD_P ok ++@c LIBC_CANCEL_ASYNC @ascuplugin @ascuheap @acsmem ++@c libc_enable_asynccancel @ascuplugin @ascuheap @acsmem ++@c CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS dup ok ++@c do_cancel dup @ascuplugin @ascuheap @acsmem ++@c LIBC_CANCEL_RESET ok ++@c libc_disable_asynccancel ok ++@c lll_futex_wait dup ok + This function executes @var{command} as a shell command. In @theglibc{}, + it always uses the default shell @code{sh} to run the command. + In particular, it searches the directories in @code{PATH} to find +@@ -157,12 +194,14 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun pid_t getpid (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{getpid} function returns the process ID of the current process. + @end deftypefun + + @comment unistd.h + @comment POSIX.1 + @deftypefun pid_t getppid (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{getppid} function returns the process ID of the parent of the + current process. + @end deftypefun +@@ -177,6 +216,19 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun pid_t fork (void) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuplugin{}}@acunsafe{@aculock{}}} ++@c The nptl/.../linux implementation safely collects fork_handlers into ++@c an alloca()ed linked list and increments ref counters; it uses atomic ++@c ops and retries, avoiding locking altogether. It then takes the ++@c IO_list lock, resets the thread-local pid, and runs fork. The parent ++@c restores the thread-local pid, releases the lock, and runs parent ++@c handlers, decrementing the ref count and signaling futex wait if ++@c requested by unregister_atfork. The child bumps the fork generation, ++@c sets the thread-local pid, resets cpu clocks, initializes the robust ++@c mutex list, the stream locks, the IO_list lock, the dynamic loader ++@c lock, runs the child handlers, reseting ref counters to 1, and ++@c initializes the fork lock. These are all safe, unless atfork ++@c handlers themselves are unsafe. + The @code{fork} function creates a new process. + + If the operation is successful, there are then both parent and child +@@ -242,6 +294,9 @@ + @comment unistd.h + @comment BSD + @deftypefun pid_t vfork (void) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuplugin{}}@acunsafe{@aculock{}}} ++@c The vfork implementation proper is a safe syscall, but it may fall ++@c back to fork if the vfork syscall is not available. + The @code{vfork} function is similar to @code{fork} but on some systems + it is more efficient; however, there are restrictions you must follow to + use it safely. +@@ -287,6 +342,7 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun int execv (const char *@var{filename}, char *const @var{argv}@t{[]}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{execv} function executes the file named by @var{filename} as a + new process image. + +@@ -305,6 +361,7 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun int execl (const char *@var{filename}, const char *@var{arg0}, @dots{}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + This is similar to @code{execv}, but the @var{argv} strings are + specified individually instead of as an array. A null pointer must be + passed as the last such argument. +@@ -313,6 +370,7 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun int execve (const char *@var{filename}, char *const @var{argv}@t{[]}, char *const @var{env}@t{[]}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This is similar to @code{execv}, but permits you to specify the environment + for the new program explicitly as the @var{env} argument. This should + be an array of strings in the same format as for the @code{environ} +@@ -322,6 +380,7 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun int execle (const char *@var{filename}, const char *@var{arg0}, @dots{}, char *const @var{env}@t{[]}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + This is similar to @code{execl}, but permits you to specify the + environment for the new program explicitly. The environment argument is + passed following the null pointer that marks the last @var{argv} +@@ -332,6 +391,7 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun int execvp (const char *@var{filename}, char *const @var{argv}@t{[]}) ++@safety{@prelim{}@mtsafe{@mtsenv{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + The @code{execvp} function is similar to @code{execv}, except that it + searches the directories listed in the @code{PATH} environment variable + (@pxref{Standard Environment}) to find the full file name of a +@@ -345,6 +405,7 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun int execlp (const char *@var{filename}, const char *@var{arg0}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtsenv{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + This function is like @code{execl}, except that it performs the same + file name searching as the @code{execvp} function. + @end deftypefun +@@ -462,6 +523,7 @@ + @comment sys/wait.h + @comment POSIX.1 + @deftypefun pid_t waitpid (pid_t @var{pid}, int *@var{status-ptr}, int @var{options}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{waitpid} function is used to request status information from a + child process whose process ID is @var{pid}. Normally, the calling + process is suspended until the child process makes status information +@@ -565,6 +627,7 @@ + @comment sys/wait.h + @comment POSIX.1 + @deftypefun pid_t wait (int *@var{status-ptr}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This is a simplified version of @code{waitpid}, and is used to wait + until any one child process terminates. The call: + +@@ -591,6 +654,7 @@ + @comment sys/wait.h + @comment BSD + @deftypefun pid_t wait4 (pid_t @var{pid}, int *@var{status-ptr}, int @var{options}, struct rusage *@var{usage}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + If @var{usage} is a null pointer, @code{wait4} is equivalent to + @code{waitpid (@var{pid}, @var{status-ptr}, @var{options})}. + +@@ -643,6 +707,7 @@ + @comment sys/wait.h + @comment POSIX.1 + @deftypefn Macro int WIFEXITED (int @var{status}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This macro returns a nonzero value if the child process terminated + normally with @code{exit} or @code{_exit}. + @end deftypefn +@@ -650,6 +715,7 @@ + @comment sys/wait.h + @comment POSIX.1 + @deftypefn Macro int WEXITSTATUS (int @var{status}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + If @code{WIFEXITED} is true of @var{status}, this macro returns the + low-order 8 bits of the exit status value from the child process. + @xref{Exit Status}. +@@ -658,6 +724,7 @@ + @comment sys/wait.h + @comment POSIX.1 + @deftypefn Macro int WIFSIGNALED (int @var{status}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This macro returns a nonzero value if the child process terminated + because it received a signal that was not handled. + @xref{Signal Handling}. +@@ -666,6 +733,7 @@ + @comment sys/wait.h + @comment POSIX.1 + @deftypefn Macro int WTERMSIG (int @var{status}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + If @code{WIFSIGNALED} is true of @var{status}, this macro returns the + signal number of the signal that terminated the child process. + @end deftypefn +@@ -673,6 +741,7 @@ + @comment sys/wait.h + @comment BSD + @deftypefn Macro int WCOREDUMP (int @var{status}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This macro returns a nonzero value if the child process terminated + and produced a core dump. + @end deftypefn +@@ -680,12 +749,14 @@ + @comment sys/wait.h + @comment POSIX.1 + @deftypefn Macro int WIFSTOPPED (int @var{status}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This macro returns a nonzero value if the child process is stopped. + @end deftypefn + + @comment sys/wait.h + @comment POSIX.1 + @deftypefn Macro int WSTOPSIG (int @var{status}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + If @code{WIFSTOPPED} is true of @var{status}, this macro returns the + signal number of the signal that caused the child process to stop. + @end deftypefn +@@ -739,6 +810,7 @@ + @comment sys/wait.h + @comment BSD + @deftypefun pid_t wait3 (union wait *@var{status-ptr}, int @var{options}, struct rusage *@var{usage}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + If @var{usage} is a null pointer, @code{wait3} is equivalent to + @code{waitpid (-1, @var{status-ptr}, @var{options})}. + +diff -urN glibc-2.17-c758a686/manual/resource.texi glibc-2.17-c758a686/manual/resource.texi +--- glibc-2.17-c758a686/manual/resource.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/resource.texi 2014-09-12 16:10:06.044792719 -0400 +@@ -25,6 +25,8 @@ + @comment sys/resource.h + @comment BSD + @deftypefun int getrusage (int @var{processes}, struct rusage *@var{rusage}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c On HURD, this calls task_info 3 times. On UNIX, it's a syscall. + This function reports resource usage totals for processes specified by + @var{processes}, storing the information in @code{*@var{rusage}}. + +@@ -129,9 +131,11 @@ + @code{vtimes} and its @code{vtimes} data structure are declared in + @file{sys/vtimes.h}. + @pindex sys/vtimes.h +-@comment vtimes.h + +-@deftypefun int vtimes (struct vtimes @var{current}, struct vtimes @var{child}) ++@comment sys/vtimes.h ++@deftypefun int vtimes (struct vtimes *@var{current}, struct vtimes *@var{child}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Calls getrusage twice. + + @code{vtimes} reports resource usage totals for a process. + +@@ -223,6 +227,8 @@ + @comment sys/resource.h + @comment BSD + @deftypefun int getrlimit (int @var{resource}, struct rlimit *@var{rlp}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall on most systems. + Read the current and maximum limits for the resource @var{resource} + and store them in @code{*@var{rlp}}. + +@@ -237,6 +243,8 @@ + @comment sys/resource.h + @comment Unix98 + @deftypefun int getrlimit64 (int @var{resource}, struct rlimit64 *@var{rlp}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall on most systems, wrapper to getrlimit otherwise. + This function is similar to @code{getrlimit} but its second parameter is + a pointer to a variable of type @code{struct rlimit64}, which allows it + to read values which wouldn't fit in the member of a @code{struct +@@ -250,6 +258,8 @@ + @comment sys/resource.h + @comment BSD + @deftypefun int setrlimit (int @var{resource}, const struct rlimit *@var{rlp}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall on most systems; lock-taking critical section on HURD. + Store the current and maximum limits for the resource @var{resource} + in @code{*@var{rlp}}. + +@@ -275,6 +285,8 @@ + @comment sys/resource.h + @comment Unix98 + @deftypefun int setrlimit64 (int @var{resource}, const struct rlimit64 *@var{rlp}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Wrapper for setrlimit or direct syscall. + This function is similar to @code{setrlimit} but its second parameter is + a pointer to a variable of type @code{struct rlimit64} which allows it + to set values which wouldn't fit in the member of a @code{struct +@@ -419,7 +431,7 @@ + + @comment sys/resource.h + @comment BSD +-@deftypevr Constant int RLIM_INFINITY ++@deftypevr Constant rlim_t RLIM_INFINITY + This constant stands for a value of ``infinity'' when supplied as + the limit value in @code{setrlimit}. + @end deftypevr +@@ -433,7 +445,10 @@ + + @comment ulimit.h + @comment BSD +-@deftypefun int ulimit (int @var{cmd}, @dots{}) ++@deftypefun {long int} ulimit (int @var{cmd}, @dots{}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Wrapper for getrlimit, setrlimit or ++@c sysconf(_SC_OPEN_MAX)->getdtablesize->getrlimit. + + @code{ulimit} gets the current limit or sets the current and maximum + limit for a particular resource for the calling process according to the +@@ -480,6 +495,10 @@ + @comment sys/vlimit.h + @comment BSD + @deftypefun int vlimit (int @var{resource}, int @var{limit}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:setrlimit}}@asunsafe{}@acsafe{}} ++@c It calls getrlimit and modifies the rlim_cur field before calling ++@c setrlimit. There's a window for a concurrent call to setrlimit that ++@c modifies e.g. rlim_max, which will be lost if running as super-user. + + @code{vlimit} sets the current limit for a resource for a process. + +@@ -778,6 +797,8 @@ + @comment sched.h + @comment POSIX + @deftypefun int sched_setscheduler (pid_t @var{pid}, int @var{policy}, const struct sched_param *@var{param}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall, Linux only. + + This function sets both the absolute priority and the scheduling policy + for a process. +@@ -848,6 +869,8 @@ + @comment sched.h + @comment POSIX + @deftypefun int sched_getscheduler (pid_t @var{pid}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall, Linux only. + + This function returns the scheduling policy assigned to the process with + Process ID (pid) @var{pid}, or the calling process if @var{pid} is zero. +@@ -881,6 +904,8 @@ + @comment sched.h + @comment POSIX + @deftypefun int sched_setparam (pid_t @var{pid}, const struct sched_param *@var{param}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall, Linux only. + + This function sets a process' absolute priority. + +@@ -893,7 +918,9 @@ + + @comment sched.h + @comment POSIX +-@deftypefun int sched_getparam (pid_t @var{pid}, const struct sched_param *@var{param}) ++@deftypefun int sched_getparam (pid_t @var{pid}, struct sched_param *@var{param}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall, Linux only. + + This function returns a process' absolute priority. + +@@ -922,7 +949,9 @@ + + @comment sched.h + @comment POSIX +-@deftypefun int sched_get_priority_min (int *@var{policy}) ++@deftypefun int sched_get_priority_min (int @var{policy}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall, Linux only. + + This function returns the lowest absolute priority value that is + allowable for a process with scheduling policy @var{policy}. +@@ -942,7 +971,9 @@ + + @comment sched.h + @comment POSIX +-@deftypefun int sched_get_priority_max (int *@var{policy}) ++@deftypefun int sched_get_priority_max (int @var{policy}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall, Linux only. + + This function returns the highest absolute priority value that is + allowable for a process that with scheduling policy @var{policy}. +@@ -963,6 +994,8 @@ + @comment sched.h + @comment POSIX + @deftypefun int sched_rr_get_interval (pid_t @var{pid}, struct timespec *@var{interval}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall, Linux only. + + This function returns the length of the quantum (time slice) used with + the Round Robin scheduling policy, if it is used, for the process with +@@ -987,6 +1020,8 @@ + @comment sched.h + @comment POSIX + @deftypefun int sched_yield (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall on Linux; alias to swtch on HURD. + + This function voluntarily gives up the process' claim on the CPU. + +@@ -1045,7 +1080,7 @@ + about. + + But just to be clear about the scope of this scheduling: Any time a +-process with a absolute priority of 0 and a process with an absolute ++process with an absolute priority of 0 and a process with an absolute + priority higher than 0 are ready to run at the same time, the one with + absolute priority 0 does not run. If it's already running when the + higher priority ready-to-run process comes into existence, it stops +@@ -1138,6 +1173,8 @@ + @comment sys/resource.h + @comment BSD,POSIX + @deftypefun int getpriority (int @var{class}, int @var{id}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall on UNIX. On HURD, calls _hurd_priority_which_map. + Return the nice value of a set of processes; @var{class} and @var{id} + specify which ones (see below). If the processes specified do not all + have the same nice value, this returns the lowest value that any of them +@@ -1165,6 +1202,8 @@ + @comment sys/resource.h + @comment BSD,POSIX + @deftypefun int setpriority (int @var{class}, int @var{id}, int @var{niceval}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall on UNIX. On HURD, calls _hurd_priority_which_map. + Set the nice value of a set of processes to @var{niceval}; @var{class} + and @var{id} specify which ones (see below). + +@@ -1222,6 +1261,11 @@ + @comment unistd.h + @comment BSD + @deftypefun int nice (int @var{increment}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:setpriority}}@asunsafe{}@acsafe{}} ++@c Calls getpriority before and after setpriority, using the result of ++@c the first call to compute the argument for setpriority. This creates ++@c a window for a concurrent setpriority (or nice) call to be lost or ++@c exhibit surprising behavior. + Increment the nice value of the calling process by @var{increment}. + The return value is the new nice value on success, and @code{-1} on + failure. In the case of failure, @code{errno} will be set to the +@@ -1319,6 +1363,10 @@ + @comment sched.h + @comment GNU + @deftypefn Macro void CPU_ZERO (cpu_set_t *@var{set}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c CPU_ZERO ok ++@c __CPU_ZERO_S ok ++@c memset dup ok + This macro initializes the CPU set @var{set} to be the empty set. + + This macro is a GNU extension and is defined in @file{sched.h}. +@@ -1327,6 +1375,11 @@ + @comment sched.h + @comment GNU + @deftypefn Macro void CPU_SET (int @var{cpu}, cpu_set_t *@var{set}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c CPU_SET ok ++@c __CPU_SET_S ok ++@c __CPUELT ok ++@c __CPUMASK ok + This macro adds @var{cpu} to the CPU set @var{set}. + + The @var{cpu} parameter must not have side effects since it is +@@ -1338,6 +1391,11 @@ + @comment sched.h + @comment GNU + @deftypefn Macro void CPU_CLR (int @var{cpu}, cpu_set_t *@var{set}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c CPU_CLR ok ++@c __CPU_CLR_S ok ++@c __CPUELT dup ok ++@c __CPUMASK dup ok + This macro removes @var{cpu} from the CPU set @var{set}. + + The @var{cpu} parameter must not have side effects since it is +@@ -1349,6 +1407,11 @@ + @comment sched.h + @comment GNU + @deftypefn Macro int CPU_ISSET (int @var{cpu}, const cpu_set_t *@var{set}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c CPU_ISSET ok ++@c __CPU_ISSET_S ok ++@c __CPUELT dup ok ++@c __CPUMASK dup ok + This macro returns a nonzero value (true) if @var{cpu} is a member + of the CPU set @var{set}, and zero (false) otherwise. + +@@ -1365,6 +1428,9 @@ + @comment sched.h + @comment GNU + @deftypefun int sched_getaffinity (pid_t @var{pid}, size_t @var{cpusetsize}, cpu_set_t *@var{cpuset}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Wrapped syscall to zero out past the kernel cpu set size; Linux ++@c only. + + This functions stores the CPU affinity mask for the process or thread + with the ID @var{pid} in the @var{cpusetsize} bytes long bitmap +@@ -1393,6 +1459,9 @@ + @comment sched.h + @comment GNU + @deftypefun int sched_setaffinity (pid_t @var{pid}, size_t @var{cpusetsize}, const cpu_set_t *@var{cpuset}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Wrapped syscall to detect attempts to set bits past the kernel cpu ++@c set size; Linux only. + + This function installs the @var{cpusetsize} bytes long affinity mask + pointed to by @var{cpuset} for the process or thread with the ID @var{pid}. +@@ -1516,6 +1585,9 @@ + @comment unistd.h + @comment BSD + @deftypefun int getpagesize (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Obtained from the aux vec at program startup time. GNU/Linux/m68k is ++@c the exception, with the possibility of a syscall. + The @code{getpagesize} function returns the page size of the process. + This value is fixed for the runtime of the process but can vary in + different runs of the application. +@@ -1559,6 +1631,8 @@ + @comment sys/sysinfo.h + @comment GNU + @deftypefun {long int} get_phys_pages (void) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} ++@c This fopens a /proc file and scans it for the requested information. + The @code{get_phys_pages} function returns the total number of pages of + physical the system has. To get the amount of memory this number has to + be multiplied by the page size. +@@ -1569,7 +1643,8 @@ + @comment sys/sysinfo.h + @comment GNU + @deftypefun {long int} get_avphys_pages (void) +-The @code{get_phys_pages} function returns the number of available pages of ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} ++The @code{get_avphys_pages} function returns the number of available pages of + physical the system has. To get the amount of memory this number has to + be multiplied by the page size. + +@@ -1614,6 +1689,9 @@ + @comment sys/sysinfo.h + @comment GNU + @deftypefun int get_nprocs_conf (void) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} ++@c This function reads from from /sys using dir streams (single user, so ++@c no @mtasurace issue), and on some arches, from /proc using streams. + The @code{get_nprocs_conf} function returns the number of processors the + operating system configured. + +@@ -1623,6 +1701,8 @@ + @comment sys/sysinfo.h + @comment GNU + @deftypefun int get_nprocs (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{@acsfd{}}} ++@c This function reads from /proc using file descriptor I/O. + The @code{get_nprocs} function returns the number of available processors. + + This function is a GNU extension. +@@ -1638,8 +1718,12 @@ + @comment stdlib.h + @comment BSD + @deftypefun int getloadavg (double @var{loadavg}[], int @var{nelem}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{@acsfd{}}} ++@c Calls host_info on HURD; on Linux, opens /proc/loadavg, reads from ++@c it, closes it, without cancellation point, and calls strtod_l with ++@c the C locale to convert the strings to doubles. + This function gets the 1, 5 and 15 minute load averages of the +-system. The values are placed in @var{loadavg}. @code{getloadavg} will ++system. The values are placed in @var{loadavg}. @code{getloadavg} will + place at most @var{nelem} elements into the array but never more than + three elements. The return value is the number of elements written to + @var{loadavg}, or -1 on error. +diff -urN glibc-2.17-c758a686/manual/search.texi glibc-2.17-c758a686/manual/search.texi +--- glibc-2.17-c758a686/manual/search.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/search.texi 2014-09-12 16:10:06.043792722 -0400 +@@ -71,7 +71,8 @@ + + @comment search.h + @comment SVID +-@deftypefun {void *} lfind (const void *@var{key}, void *@var{base}, size_t *@var{nmemb}, size_t @var{size}, comparison_fn_t @var{compar}) ++@deftypefun {void *} lfind (const void *@var{key}, const void *@var{base}, size_t *@var{nmemb}, size_t @var{size}, comparison_fn_t @var{compar}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{lfind} function searches in the array with @code{*@var{nmemb}} + elements of @var{size} bytes pointed to by @var{base} for an element + which matches the one pointed to by @var{key}. The function pointed to +@@ -90,6 +91,21 @@ + @comment search.h + @comment SVID + @deftypefun {void *} lsearch (const void *@var{key}, void *@var{base}, size_t *@var{nmemb}, size_t @var{size}, comparison_fn_t @var{compar}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c A signal handler that interrupted an insertion and performed an ++@c insertion itself would leave the array in a corrupt state (e.g. one ++@c new element initialized twice, with parts of both initializations ++@c prevailing, and another uninitialized element), but this is just a ++@c special case of races on user-controlled objects, that have to be ++@c avoided by users. ++ ++@c In case of cancellation, we know the array won't be left in a corrupt ++@c state; the new element is initialized before the element count is ++@c incremented, and the compiler can't reorder these operations because ++@c it can't know that they don't alias. So, we'll either cancel after ++@c the increment and the initialization are both complete, or the ++@c increment won't have taken place, and so how far the initialization ++@c got doesn't matter. + The @code{lsearch} function is similar to the @code{lfind} function. It + searches the given array for an element and returns it if found. The + difference is that if no matching element is found the @code{lsearch} +@@ -113,6 +129,7 @@ + @comment stdlib.h + @comment ISO + @deftypefun {void *} bsearch (const void *@var{key}, const void *@var{array}, size_t @var{count}, size_t @var{size}, comparison_fn_t @var{compare}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{bsearch} function searches the sorted array @var{array} for an object + that is equivalent to @var{key}. The array contains @var{count} elements, + each of which is of size @var{size} bytes. +@@ -146,6 +163,7 @@ + @comment stdlib.h + @comment ISO + @deftypefun void qsort (void *@var{array}, size_t @var{count}, size_t @var{size}, comparison_fn_t @var{compare}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@acucorrupt{}}} + The @var{qsort} function sorts the array @var{array}. The array contains + @var{count} elements, each of which is of size @var{size}. + +@@ -256,6 +274,9 @@ + @comment search.h + @comment SVID + @deftypefun int hcreate (size_t @var{nel}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:hsearch}}@asunsafe{@ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{}}} ++@c hcreate @mtasurace:hsearch @ascuheap @acucorrupt @acsmem ++@c hcreate_r dup @mtsrace:htab @ascuheap @acucorrupt @acsmem + The @code{hcreate} function creates a hashing table which can contain at + least @var{nel} elements. There is no possibility to grow this table so + it is necessary to choose the value for @var{nel} wisely. The method +@@ -270,7 +291,7 @@ + The weakest aspect of this function is that there can be at most one + hashing table used through the whole program. The table is allocated + in local memory out of control of the programmer. As an extension @theglibc{} +-provides an additional set of functions with an reentrant ++provides an additional set of functions with a reentrant + interface which provide a similar interface but which allow to keep + arbitrarily many hashing tables. + +@@ -285,6 +306,9 @@ + @comment search.h + @comment SVID + @deftypefun void hdestroy (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:hsearch}}@asunsafe{@ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{}}} ++@c hdestroy @mtasurace:hsearch @ascuheap @acucorrupt @acsmem ++@c hdestroy_r dup @mtsrace:htab @ascuheap @acucorrupt @acsmem + The @code{hdestroy} function can be used to free all the resources + allocated in a previous call of @code{hcreate}. After a call to this + function it is again possible to call @code{hcreate} and allocate a new +@@ -328,6 +352,9 @@ + @comment search.h + @comment SVID + @deftypefun {ENTRY *} hsearch (ENTRY @var{item}, ACTION @var{action}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:hsearch}}@asunsafe{}@acunsafe{@acucorrupt{/action==ENTER}}} ++@c hsearch @mtasurace:hsearch @acucorrupt/action==ENTER ++@c hsearch_r dup @mtsrace:htab @acucorrupt/action==ENTER + To search in a hashing table created using @code{hcreate} the + @code{hsearch} function must be used. This function can perform simple + search for an element (if @var{action} has the @code{FIND}) or it can +@@ -358,6 +385,24 @@ + @comment search.h + @comment GNU + @deftypefun int hcreate_r (size_t @var{nel}, struct hsearch_data *@var{htab}) ++@safety{@prelim{}@mtsafe{@mtsrace{:htab}}@asunsafe{@ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{}}} ++@c Unlike the lsearch array, the htab is (at least in part) opaque, so ++@c let's make it absolutely clear that ensuring exclusive access is a ++@c caller responsibility. ++ ++@c Cancellation is unlikely to leave the htab in a corrupt state: the ++@c last field to be initialized is the one that tells whether the entire ++@c data structure was initialized, and there's a function call (calloc) ++@c in between that will often ensure all other fields are written before ++@c the table. However, should this call be inlined (say with LTO), this ++@c assumption may not hold. The calloc call doesn't cross our library ++@c interface barrier, so let's consider this could happen and mark this ++@c with @acucorrupt. It's no safety loss, since we already have ++@c @ascuheap anyway... ++ ++@c hcreate_r @mtsrace:htab @ascuheap @acucorrupt @acsmem ++@c isprime ok ++@c calloc dup @ascuheap @acsmem + The @code{hcreate_r} function initializes the object pointed to by + @var{htab} to contain a hashing table with at least @var{nel} elements. + So this function is equivalent to the @code{hcreate} function except +@@ -376,6 +421,16 @@ + @comment search.h + @comment GNU + @deftypefun void hdestroy_r (struct hsearch_data *@var{htab}) ++@safety{@prelim{}@mtsafe{@mtsrace{:htab}}@asunsafe{@ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{}}} ++@c The table is released while the table pointer still points to it. ++@c Async cancellation is thus unsafe, but it already was because we call ++@c free(). Using the table in a handler while it's being released would ++@c also be dangerous, but calling free() already makes it unsafe, and ++@c the requirement on the caller to ensure exclusive access already ++@c guarantees this doesn't happen, so we don't get @asucorrupt. ++ ++@c hdestroy_r @mtsrace:htab @ascuheap @acucorrupt @acsmem ++@c free dup @ascuheap @acsmem + The @code{hdestroy_r} function frees all resources allocated by the + @code{hcreate_r} function for this very same object @var{htab}. As for + @code{hdestroy} it is the programs responsibility to free the strings +@@ -385,6 +440,13 @@ + @comment search.h + @comment GNU + @deftypefun int hsearch_r (ENTRY @var{item}, ACTION @var{action}, ENTRY **@var{retval}, struct hsearch_data *@var{htab}) ++@safety{@prelim{}@mtsafe{@mtsrace{:htab}}@assafe{}@acunsafe{@acucorrupt{/action==ENTER}}} ++@c Callers have to ensure mutual exclusion; insertion, if cancelled, ++@c leaves the table in a corrupt state. ++ ++@c hsearch_r @mtsrace:htab @acucorrupt/action==ENTER ++@c strlen dup ok ++@c strcmp dup ok + The @code{hsearch_r} function is equivalent to @code{hsearch}. The + meaning of the first two arguments is identical. But instead of + operating on a single global hashing table the function works on the +@@ -401,7 +463,7 @@ + + @table @code + @item ENOMEM +-The table is filled and @code{hsearch_r} was called with an so far ++The table is filled and @code{hsearch_r} was called with a so far + unknown key and @var{action} set to @code{ENTER}. + @item ESRCH + The @var{action} parameter is @code{FIND} and no corresponding element +@@ -436,6 +498,12 @@ + @comment search.h + @comment SVID + @deftypefun {void *} tsearch (const void *@var{key}, void **@var{rootp}, comparison_fn_t @var{compar}) ++@safety{@prelim{}@mtsafe{@mtsrace{:rootp}}@asunsafe{@ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{}}} ++@c The tree is not modified in a thread-safe manner, and rotations may ++@c leave the tree in an inconsistent state that could be observed in an ++@c asynchronous signal handler (except for the caller-synchronization ++@c requirement) or after asynchronous cancellation of the thread ++@c performing the rotation or the insertion. + The @code{tsearch} function searches in the tree pointed to by + @code{*@var{rootp}} for an element matching @var{key}. The function + pointed to by @var{compar} is used to determine whether two elements +@@ -465,6 +533,7 @@ + @comment search.h + @comment SVID + @deftypefun {void *} tfind (const void *@var{key}, void *const *@var{rootp}, comparison_fn_t @var{compar}) ++@safety{@prelim{}@mtsafe{@mtsrace{:rootp}}@assafe{}@acsafe{}} + The @code{tfind} function is similar to the @code{tsearch} function. It + locates an element matching the one pointed to by @var{key} and returns + a pointer to this element. But if no matching element is available no +@@ -479,6 +548,7 @@ + @comment search.h + @comment SVID + @deftypefun {void *} tdelete (const void *@var{key}, void **@var{rootp}, comparison_fn_t @var{compar}) ++@safety{@prelim{}@mtsafe{@mtsrace{:rootp}}@asunsafe{@ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{}}} + To remove a specific element matching @var{key} from the tree + @code{tdelete} can be used. It locates the matching element using the + same method as @code{tfind}. The corresponding element is then removed +@@ -492,6 +562,7 @@ + @comment search.h + @comment GNU + @deftypefun void tdestroy (void *@var{vroot}, __free_fn_t @var{freefct}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + If the complete search tree has to be removed one can use + @code{tdestroy}. It frees all resources allocated by the @code{tsearch} + function to generate the tree pointed to by @var{vroot}. +@@ -546,6 +617,7 @@ + @comment search.h + @comment SVID + @deftypefun void twalk (const void *@var{root}, __action_fn_t @var{action}) ++@safety{@prelim{}@mtsafe{@mtsrace{:root}}@assafe{}@acsafe{}} + For each node in the tree with a node pointed to by @var{root}, the + @code{twalk} function calls the function provided by the parameter + @var{action}. For leaf nodes the function is called exactly once with +diff -urN glibc-2.17-c758a686/manual/setjmp.texi glibc-2.17-c758a686/manual/setjmp.texi +--- glibc-2.17-c758a686/manual/setjmp.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/setjmp.texi 2014-09-12 16:10:06.043792722 -0400 +@@ -107,6 +107,10 @@ + @comment setjmp.h + @comment ISO + @deftypefn Macro int setjmp (jmp_buf @var{state}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c _setjmp ok ++@c __sigsetjmp(!savemask) ok ++@c __sigjmp_save(!savemask) ok, does not call sigprocmask + When called normally, @code{setjmp} stores information about the + execution state of the program in @var{state} and returns zero. If + @code{longjmp} is later used to perform a non-local exit to this +@@ -116,6 +120,20 @@ + @comment setjmp.h + @comment ISO + @deftypefun void longjmp (jmp_buf @var{state}, int @var{value}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuplugin{} @asucorrupt{} @asulock{/hurd}}@acunsafe{@acucorrupt{} @aculock{/hurd}}} ++@c __libc_siglongjmp @ascuplugin @asucorrupt @asulock/hurd @acucorrupt @aculock/hurd ++@c _longjmp_unwind @ascuplugin @asucorrupt @acucorrupt ++@c __pthread_cleanup_upto @ascuplugin @asucorrupt @acucorrupt ++@c plugins may be unsafe themselves, but even if they weren't, this ++@c function isn't robust WRT async signals and cancellation: ++@c cleanups aren't taken off the stack right away, only after all ++@c cleanups have been run. This means that async-cancelling ++@c longjmp, or interrupting longjmp with an async signal handler ++@c that calls longjmp may run the same cleanups multiple times. ++@c _JMPBUF_UNWINDS_ADJ ok ++@c *cleanup_buf->__routine @ascuplugin ++@c sigprocmask(SIG_SETMASK) dup @asulock/hurd @aculock/hurd ++@c __longjmp ok + This function restores current execution to the state saved in + @var{state}, and continues execution from the call to @code{setjmp} that + established that return point. Returning from @code{setjmp} by means of +@@ -141,7 +159,7 @@ + statement (such as @samp{if}, @samp{switch}, or @samp{while}). + + @item +-As one operand of a equality or comparison operator that appears as the ++As one operand of an equality or comparison operator that appears as the + test expression of a selection or iteration statement. The other + operand must be an integer constant expression. + +@@ -199,6 +217,11 @@ + @comment setjmp.h + @comment POSIX.1 + @deftypefun int sigsetjmp (sigjmp_buf @var{state}, int @var{savesigs}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{/hurd}}@acunsafe{@aculock{/hurd}}} ++@c sigsetjmp @asulock/hurd @aculock/hurd ++@c __sigsetjmp(savemask) @asulock/hurd @aculock/hurd ++@c __sigjmp_save(savemask) @asulock/hurd @aculock/hurd ++@c sigprocmask(SIG_BLOCK probe) dup @asulock/hurd @aculock/hurd + This is similar to @code{setjmp}. If @var{savesigs} is nonzero, the set + of blocked signals is saved in @var{state} and will be restored if a + @code{siglongjmp} is later performed with this @var{state}. +@@ -207,6 +230,8 @@ + @comment setjmp.h + @comment POSIX.1 + @deftypefun void siglongjmp (sigjmp_buf @var{state}, int @var{value}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuplugin{} @asucorrupt{} @asulock{/hurd}}@acunsafe{@acucorrupt{} @aculock{/hurd}}} ++@c Alias to longjmp. + This is similar to @code{longjmp} except for the type of its @var{state} + argument. If the @code{sigsetjmp} call that set this @var{state} used a + nonzero @var{savesigs} flag, @code{siglongjmp} also restores the set of +@@ -237,7 +262,7 @@ + @comment SVID + @deftp {Data Type} ucontext_t + +-The @code{ucontext_t} type is defined as a structure with as least the ++The @code{ucontext_t} type is defined as a structure with at least the + following elements: + + @table @code +@@ -267,6 +292,10 @@ + @comment ucontext.h + @comment SVID + @deftypefun int getcontext (ucontext_t *@var{ucp}) ++@safety{@prelim{}@mtsafe{@mtsrace{:ucp}}@assafe{}@acsafe{}} ++@c Linux-only implementations in assembly, including sigprocmask ++@c syscall. A few cases call the sigprocmask function, but that's safe ++@c too. The ppc case is implemented in terms of a swapcontext syscall. + The @code{getcontext} function initializes the variable pointed to by + @var{ucp} with the context of the calling thread. The context contains + the content of the registers, the signal mask, and the current stack. +@@ -278,25 +307,26 @@ + @end deftypefun + + The @code{getcontext} function is similar to @code{setjmp} but it does +-not provide an indication of whether the function returns for the first +-time or whether the initialized context was used and the execution is +-resumed at just that point. If this is necessary the user has to take +-determine this herself. This must be done carefully since the context +-contains registers which might contain register variables. This is a +-good situation to define variables with @code{volatile}. ++not provide an indication of whether @code{getcontext} is returning for ++the first time or whether an initialized context has just been restored. ++If this is necessary the user has to determine this herself. This must ++be done carefully since the context contains registers which might contain ++register variables. This is a good situation to define variables with ++@code{volatile}. + + Once the context variable is initialized it can be used as is or it can +-be modified. The latter is normally done to implement co-routines or +-similar constructs. The @code{makecontext} function is what has to be +-used to do that. ++be modified using the @code{makecontext} function. The latter is normally ++done when implementing co-routines or similar constructs. + + @comment ucontext.h + @comment SVID + @deftypefun void makecontext (ucontext_t *@var{ucp}, void (*@var{func}) (void), int @var{argc}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtsrace{:ucp}}@assafe{}@acsafe{}} ++@c Linux-only implementations mostly in assembly, nothing unsafe. + +-The @var{ucp} parameter passed to the @code{makecontext} shall be ++The @var{ucp} parameter passed to @code{makecontext} shall be + initialized by a call to @code{getcontext}. The context will be +-modified to in a way so that if the context is resumed it will start by ++modified in a way such that if the context is resumed it will start by + calling the function @code{func} which gets @var{argc} integer arguments + passed. The integer arguments which are to be passed should follow the + @var{argc} parameter in the call to @code{makecontext}. +@@ -316,7 +346,7 @@ + While allocating the memory for the stack one has to be careful. Most + modern processors keep track of whether a certain memory region is + allowed to contain code which is executed or not. Data segments and +-heap memory is normally not tagged to allow this. The result is that ++heap memory are normally not tagged to allow this. The result is that + programs would fail. Examples for such code include the calling + sequences the GNU C compiler generates for calls to nested functions. + Safe ways to allocate stacks correctly include using memory on the +@@ -332,13 +362,22 @@ + allocated for the stack and the size of the memory region is stored in + @code{ss_size}. There are implements out there which require + @code{ss_sp} to be set to the value the stack pointer will have (which +-can depending on the direction the stack grows be different). This ++can, depending on the direction the stack grows, be different). This + difference makes the @code{makecontext} function hard to use and it + requires detection of the platform at compile time. + + @comment ucontext.h + @comment SVID + @deftypefun int setcontext (const ucontext_t *@var{ucp}) ++@safety{@prelim{}@mtsafe{@mtsrace{:ucp}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} ++@c Linux-only implementations mostly in assembly. Some ports use ++@c sigreturn or swapcontext syscalls; others restore the signal mask ++@c first and then proceed restore other registers in userland, which ++@c leaves a window for cancellation or async signals with misaligned or ++@c otherwise corrupt stack. ??? Switching to a different stack, or even ++@c to an earlier state on the same stack, may conflict with pthread ++@c cleanups. This is not quite MT-Unsafe, it's a different kind of ++@c safety issue. + + The @code{setcontext} function restores the context described by + @var{ucp}. The context is not modified and can be reused as often as +@@ -357,6 +396,9 @@ + terminates normally with an exit status value of @code{EXIT_SUCCESS} + (@pxref{Program Termination}). + ++If the context was created by a call to a signal handler or from any ++other source then the behaviour of @code{setcontext} is unspecified. ++ + Since the context contains information about the stack no two threads + should use the same context at the same time. The result in most cases + would be disastrous. +@@ -372,6 +414,10 @@ + @comment ucontext.h + @comment SVID + @deftypefun int swapcontext (ucontext_t *restrict @var{oucp}, const ucontext_t *restrict @var{ucp}) ++@safety{@prelim{}@mtsafe{@mtsrace{:oucp} @mtsrace{:ucp}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} ++@c Linux-only implementations mostly in assembly. Some ports call or ++@c inline getcontext and/or setcontext, adjusting the saved context in ++@c between, so we inherit the potential issues of both. + + The @code{swapcontext} function is similar to @code{setcontext} but + instead of just replacing the current context the latter is first saved +@@ -385,15 +431,15 @@ + If @code{swapcontext} succeeds the function does not return unless the + context @var{oucp} is used without prior modification by + @code{makecontext}. The return value in this case is @code{0}. If the +-function fails it returns @code{-1} and set @var{errno} accordingly. ++function fails it returns @code{-1} and sets @var{errno} accordingly. + @end deftypefun + + @heading Example for SVID Context Handling + + The easiest way to use the context handling functions is as a + replacement for @code{setjmp} and @code{longjmp}. The context contains +-on most platforms more information which might lead to less surprises +-but this also means using these functions is more expensive (beside ++on most platforms more information which may lead to fewer surprises ++but this also means using these functions is more expensive (besides + being less portable). + + @smallexample +@@ -440,11 +486,11 @@ + This an example how the context functions can be used to implement + co-routines or cooperative multi-threading. All that has to be done is + to call every once in a while @code{swapcontext} to continue running a +-different context. It is not allowed to do the context switching from +-the signal handler directly since neither @code{setcontext} nor +-@code{swapcontext} are functions which can be called from a signal +-handler. But setting a variable in the signal handler and checking it +-in the body of the functions which are executed. Since +-@code{swapcontext} is saving the current context it is possible to have +-multiple different scheduling points in the code. Execution will always +-resume where it was left. ++different context. It is not recommended to do the context switching from ++the signal handler directly since leaving the signal handler via ++@code{setcontext} if the signal was delivered during code that was not ++asynchronous signal safe could lead to problems. Setting a variable in ++the signal handler and checking it in the body of the functions which ++are executed is a safer approach. Since @code{swapcontext} is saving the ++current context it is possible to have multiple different scheduling points ++in the code. Execution will always resume where it was left. +diff -urN glibc-2.17-c758a686/manual/signal.texi glibc-2.17-c758a686/manual/signal.texi +--- glibc-2.17-c758a686/manual/signal.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/signal.texi 2014-09-12 16:10:06.045792717 -0400 +@@ -889,6 +889,20 @@ + @comment string.h + @comment GNU + @deftypefun {char *} strsignal (int @var{signum}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:strsignal} @mtslocale{}}@asunsafe{@asuinit{} @ascuintl{} @asucorrupt{} @ascuheap{}}@acunsafe{@acuinit{} @acucorrupt{} @acsmem{}}} ++@c strsignal @mtasurace:strsignal @mtslocale @asuinit @ascuintl @asucorrupt @ascuheap @acucorrupt @acsmem ++@c uses a static buffer if tsd key creation fails ++@c [once] init ++@c libc_key_create ok ++@c pthread_key_create dup ok ++@c getbuffer @asucorrupt @ascuheap @acsmem ++@c libc_getspecific ok ++@c pthread_getspecific dup ok ++@c malloc dup @ascuheap @acsmem ++@c libc_setspecific @asucorrupt @ascuheap @acucorrupt @acsmem ++@c pthread_setspecific dup @asucorrupt @ascuheap @acucorrupt @acsmem ++@c snprintf dup @mtslocale @ascuheap @acsmem ++@c _ @ascuintl + This function returns a pointer to a statically-allocated string + containing a message describing the signal @var{signum}. You + should not modify the contents of this string; and, since it can be +@@ -903,6 +917,12 @@ + @comment signal.h + @comment BSD + @deftypefun void psignal (int @var{signum}, const char *@var{message}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuintl{} @ascuheap{}}@acunsafe{@aculock{} @acucorrupt{} @acsmem{}}} ++@c psignal @mtslocale @asucorrupt @ascuintl @ascuheap @aculock @acucorrupt @acsmem ++@c _ @ascuintl ++@c fxprintf @asucorrupt @aculock @acucorrupt ++@c asprintf @mtslocale @ascuheap @acsmem ++@c free dup @ascuheap @acsmem + This function prints a message describing the signal @var{signum} to the + standard error output stream @code{stderr}; see @ref{Standard Streams}. + +@@ -972,6 +992,12 @@ + @comment signal.h + @comment ISO + @deftypefun sighandler_t signal (int @var{signum}, sighandler_t @var{action}) ++@safety{@prelim{}@mtsafe{@mtssigintr{}}@assafe{}@acsafe{}} ++@c signal ok ++@c sigemptyset dup ok ++@c sigaddset dup ok ++@c sigismember dup ok ++@c sigaction dup ok + The @code{signal} function establishes @var{action} as the action for + the signal @var{signum}. + +@@ -1094,6 +1120,10 @@ + @comment signal.h + @comment GNU + @deftypefun sighandler_t sysv_signal (int @var{signum}, sighandler_t @var{action}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c sysv_signal ok ++@c sigemptyset dup ok ++@c sigaction dup ok + The @code{sysv_signal} implements the behavior of the standard + @code{signal} function as found on SVID systems. The difference to BSD + systems is that the handler is deinstalled after a delivery of a signal. +@@ -1106,6 +1136,8 @@ + @comment signal.h + @comment SVID + @deftypefun sighandler_t ssignal (int @var{signum}, sighandler_t @var{action}) ++@safety{@prelim{}@mtsafe{@mtssigintr{}}@assafe{}@acsafe{}} ++@c Aliases signal and bsd_signal. + The @code{ssignal} function does the same thing as @code{signal}; it is + provided only for compatibility with SVID. + @end deftypefun +@@ -1172,6 +1204,7 @@ + @comment signal.h + @comment POSIX.1 + @deftypefun int sigaction (int @var{signum}, const struct sigaction *restrict @var{action}, struct sigaction *restrict @var{old-action}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @var{action} argument is used to set up a new action for the signal + @var{signum}, while the @var{old-action} argument is used to return + information about the action previously associated with this symbol. +@@ -2168,6 +2194,14 @@ + @comment signal.h + @comment ISO + @deftypefun int raise (int @var{signum}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c raise ok ++@c [posix] ++@c getpid dup ok ++@c kill dup ok ++@c [linux] ++@c syscall(gettid) ok ++@c syscall(tgkill) ok + The @code{raise} function sends the signal @var{signum} to the calling + process. It returns zero if successful and a nonzero value if it fails. + About the only reason for failure would be if the value of @var{signum} +@@ -2177,6 +2211,8 @@ + @comment signal.h + @comment SVID + @deftypefun int gsignal (int @var{signum}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Aliases raise. + The @code{gsignal} function does the same thing as @code{raise}; it is + provided only for compatibility with SVID. + @end deftypefun +@@ -2269,6 +2305,11 @@ + @comment signal.h + @comment POSIX.1 + @deftypefun int kill (pid_t @var{pid}, int @var{signum}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c The hurd implementation is not a critical section, so it's not ++@c immediately obvious that, in case of cancellation, it won't leak ++@c ports or the memory allocated by proc_getpgrppids when pid <= 0. ++@c Since none of these make it AC-Unsafe, I'm leaving them out. + The @code{kill} function sends the signal @var{signum} to the process + or process group specified by @var{pid}. Besides the signals listed in + @ref{Standard Signals}, @var{signum} can also have a value of zero to +@@ -2325,6 +2366,8 @@ + @comment signal.h + @comment BSD + @deftypefun int killpg (int @var{pgid}, int @var{signum}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Calls kill with -pgid. + This is similar to @code{kill}, but sends signal @var{signum} to the + process group @var{pgid}. This function is provided for compatibility + with BSD; using @code{kill} to do this is more portable. +@@ -2497,6 +2540,8 @@ + @comment signal.h + @comment POSIX.1 + @deftypefun int sigemptyset (sigset_t *@var{set}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Just memsets all of set to zero. + This function initializes the signal set @var{set} to exclude all of the + defined signals. It always returns @code{0}. + @end deftypefun +@@ -2504,6 +2549,7 @@ + @comment signal.h + @comment POSIX.1 + @deftypefun int sigfillset (sigset_t *@var{set}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function initializes the signal set @var{set} to include + all of the defined signals. Again, the return value is @code{0}. + @end deftypefun +@@ -2511,6 +2557,7 @@ + @comment signal.h + @comment POSIX.1 + @deftypefun int sigaddset (sigset_t *@var{set}, int @var{signum}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function adds the signal @var{signum} to the signal set @var{set}. + All @code{sigaddset} does is modify @var{set}; it does not block or + unblock any signals. +@@ -2527,6 +2574,7 @@ + @comment signal.h + @comment POSIX.1 + @deftypefun int sigdelset (sigset_t *@var{set}, int @var{signum}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function removes the signal @var{signum} from the signal set + @var{set}. All @code{sigdelset} does is modify @var{set}; it does not + block or unblock any signals. The return value and error conditions are +@@ -2538,6 +2586,7 @@ + @comment signal.h + @comment POSIX.1 + @deftypefun int sigismember (const sigset_t *@var{set}, int @var{signum}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{sigismember} function tests whether the signal @var{signum} is + a member of the signal set @var{set}. It returns @code{1} if the signal + is in the set, @code{0} if not, and @code{-1} if there is an error. +@@ -2566,7 +2615,7 @@ + + Note that you must not use @code{sigprocmask} in multi-threaded processes, + because each thread has its own signal mask and there is no single process +-signal mask. According to POSIX, the behavior of @code{sigprocmask} in a ++signal mask. According to POSIX, the behavior of @code{sigprocmask} in a + multi-threaded process is ``unspecified''. + Instead, use @code{pthread_sigmask}. + @ifset linuxthreads +@@ -2576,6 +2625,10 @@ + @comment signal.h + @comment POSIX.1 + @deftypefun int sigprocmask (int @var{how}, const sigset_t *restrict @var{set}, sigset_t *restrict @var{oldset}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:sigprocmask/bsd(SIG_UNBLOCK)}}@asunsafe{@asulock{/hurd}}@acunsafe{@aculock{/hurd}}} ++@c This takes the hurd_self_sigstate-returned object's lock on HURD. On ++@c BSD, SIG_UNBLOCK is emulated with two sigblock calls, which ++@c introduces a race window. + The @code{sigprocmask} function is used to examine or change the calling + process's signal mask. The @var{how} argument determines how the signal + mask is changed, and must be one of the following values: +@@ -2759,6 +2812,10 @@ + @comment signal.h + @comment POSIX.1 + @deftypefun int sigpending (sigset_t *@var{set}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{/hurd}}@acunsafe{@aculock{/hurd}}} ++@c Direct rt_sigpending syscall on most systems. On hurd, calls ++@c hurd_self_sigstate, it copies the sigstate's pending while holding ++@c its lock. + The @code{sigpending} function stores information about pending signals + in @var{set}. If there is a pending signal that is blocked from + delivery, then that signal is a member of the returned set. (You can +@@ -2921,7 +2978,18 @@ + + @comment unistd.h + @comment POSIX.1 +-@deftypefun int pause () ++@deftypefun int pause (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:sigprocmask/!bsd!linux}}@asunsafe{@asulock{/hurd}}@acunsafe{@aculock{/hurd}}} ++@c The signal mask read by sigprocmask may be overridden by another ++@c thread or by a signal handler before we call sigsuspend. Is this a ++@c safety issue? Probably not. ++@c pause @mtasurace:sigprocmask/!bsd!linux @asulock/hurd @aculock/hurd ++@c [ports/linux/generic] ++@c syscall_pause ok ++@c [posix] ++@c sigemptyset dup ok ++@c sigprocmask(SIG_BLOCK) dup @asulock/hurd @aculock/hurd [no @mtasurace:sigprocmask/bsd(SIG_UNBLOCK)] ++@c sigsuspend dup @mtasurace:sigprocmask/!bsd!linux @asulock/hurd @aculock/hurd + The @code{pause} function suspends program execution until a signal + arrives whose action is either to execute a handler function, or to + terminate the process. +@@ -3017,6 +3085,18 @@ + @comment signal.h + @comment POSIX.1 + @deftypefun int sigsuspend (const sigset_t *@var{set}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:sigprocmask/!bsd!linux}}@asunsafe{@asulock{/hurd}}@acunsafe{@aculock{/hurd}}} ++@c sigsuspend @mtasurace:sigprocmask/!bsd!linux @asulock/hurd @aculock/hurd ++@c [posix] @mtasurace:sigprocmask/!bsd!linux ++@c saving and restoring the procmask is racy ++@c sigprocmask(SIG_SETMASK) dup @asulock/hurd @aculock/hurd [no @mtasurace:sigprocmask/bsd(SIG_UNBLOCK)] ++@c pause @asulock/hurd @aculock/hurd ++@c [bsd] ++@c sigismember dup ok ++@c sigmask dup ok ++@c sigpause dup ok [no @mtasurace:sigprocmask/!bsd!linux @asulock/hurd @aculock/hurd] ++@c [linux] ++@c do_sigsuspend ok + This function replaces the process's signal mask with @var{set} and then + suspends the process until a signal is delivered whose action is either + to terminate the process or invoke a signal handling function. In other +@@ -3150,6 +3230,9 @@ + @comment signal.h + @comment XPG + @deftypefun int sigaltstack (const stack_t *restrict @var{stack}, stack_t *restrict @var{oldstack}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{/hurd}}@acunsafe{@aculock{/hurd}}} ++@c Syscall on Linux and BSD; the HURD implementation takes a lock on ++@c the hurd_self_sigstate-returned struct. + The @code{sigaltstack} function specifies an alternate stack for use + during signal handling. When a signal is received by the process and + its action indicates that the signal stack is used, the system arranges +@@ -3195,7 +3278,9 @@ + + @comment signal.h + @comment BSD +-@deftypefun int sigstack (const struct sigstack *@var{stack}, struct sigstack *@var{oldstack}) ++@deftypefun int sigstack (struct sigstack *@var{stack}, struct sigstack *@var{oldstack}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{/hurd}}@acunsafe{@aculock{/hurd}}} ++@c Lossy and dangerous (no size limit) wrapper for sigaltstack. + The @code{sigstack} function specifies an alternate stack for use during + signal handling. When a signal is received by the process and its + action indicates that the signal stack is used, the system arranges a +@@ -3301,6 +3386,13 @@ + @comment signal.h + @comment BSD + @deftypefun int sigvec (int @var{signum}, const struct sigvec *@var{action}, struct sigvec *@var{old-action}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c This is mostly a safe wrapper for sigaction. The exception are ++@c systems that lack SA_RESETHAND, in which a signal handler wrapper is ++@c used that calls sigaction to reset the handler before calling the ++@c user-supplied handler; it's unlikely that this emulation is used ++@c anywhere, for user-supplied flags and mask don't seem to be used ++@c the way one would expect. + This function is the equivalent of @code{sigaction} (@pxref{Advanced Signal + Handling}); it installs the action @var{action} for the signal @var{signum}, + returning information about the previous action in effect for that signal +@@ -3310,6 +3402,14 @@ + @comment signal.h + @comment BSD + @deftypefun int siginterrupt (int @var{signum}, int @var{failflag}) ++@safety{@prelim{}@mtunsafe{@mtasuconst{:@mtssigintr{}}}@asunsafe{}@acunsafe{@acucorrupt{}}} ++@c This calls sigaction twice, once to get the current sigaction for the ++@c specified signal, another to apply the flags change. This could ++@c override the effects of a concurrent sigaction call. It also ++@c modifies without any guards the global _sigintr variable, that ++@c bsd_signal reads from, and it may leave _sigintr modified without ++@c overriding the active handler if cancelled between the two ++@c operations. + This function specifies which approach to use when certain primitives + are interrupted by handling signal @var{signum}. If @var{failflag} is + false, signal @var{signum} restarts primitives. If @var{failflag} is +@@ -3323,6 +3423,8 @@ + @comment signal.h + @comment BSD + @deftypefn Macro int sigmask (int @var{signum}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c This just shifts signum. + This macro returns a signal mask that has the bit for signal @var{signum} + set. You can bitwise-OR the results of several calls to @code{sigmask} + together to specify more than one signal. For example, +@@ -3339,6 +3441,11 @@ + @comment signal.h + @comment BSD + @deftypefun int sigblock (int @var{mask}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{/hurd}}@acunsafe{@aculock{/hurd}}} ++@c On most POSIX systems, this is a wrapper for sigprocmask(SIG_BLOCK). ++@c The exception are BSD systems other than 4.4, where it is a syscall. ++@c sigblock @asulock/hurd @aculock/hurd ++@c sigprocmask(SIG_BLOCK) dup @asulock/hurd @aculock/hurd [no @mtasurace:sigprocmask/bsd(SIG_UNBLOCK)] + This function is equivalent to @code{sigprocmask} (@pxref{Process Signal + Mask}) with a @var{how} argument of @code{SIG_BLOCK}: it adds the + signals specified by @var{mask} to the calling process's set of blocked +@@ -3348,6 +3455,11 @@ + @comment signal.h + @comment BSD + @deftypefun int sigsetmask (int @var{mask}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{/hurd}}@acunsafe{@aculock{/hurd}}} ++@c On most POSIX systems, this is a wrapper for sigprocmask(SIG_SETMASK). ++@c The exception are BSD systems other than 4.4, where it is a syscall. ++@c sigsetmask @asulock/hurd @aculock/hurd ++@c sigprocmask(SIG_SETMASK) dup @asulock/hurd @aculock/hurd [no @mtasurace:sigprocmask/bsd(SIG_UNBLOCK)] + This function equivalent to @code{sigprocmask} (@pxref{Process + Signal Mask}) with a @var{how} argument of @code{SIG_SETMASK}: it sets + the calling process's signal mask to @var{mask}. The return value is +@@ -3357,6 +3469,15 @@ + @comment signal.h + @comment BSD + @deftypefun int sigpause (int @var{mask}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:sigprocmask/!bsd!linux}}@asunsafe{@asulock{/hurd}}@acunsafe{@aculock{/hurd}}} ++@c sigpause @mtasurace:sigprocmask/!bsd!linux @asulock/hurd @aculock/hurd ++@c [posix] ++@c __sigpause @mtasurace:sigprocmask/!bsd!linux @asulock/hurd @aculock/hurd ++@c do_sigpause @mtasurace:sigprocmask/!bsd!linux @asulock/hurd @aculock/hurd ++@c sigprocmask(0) dup @asulock/hurd @aculock/hurd [no @mtasurace:sigprocmask/bsd(SIG_UNBLOCK)] ++@c sigdelset dup ok ++@c sigset_set_old_mask dup ok ++@c sigsuspend dup @mtasurace:sigprocmask/!bsd!linux @asulock/hurd @aculock/hurd + This function is the equivalent of @code{sigsuspend} (@pxref{Waiting + for a Signal}): it sets the calling process's signal mask to @var{mask}, + and waits for a signal to arrive. On return the previous set of blocked +diff -urN glibc-2.17-c758a686/manual/socket.texi glibc-2.17-c758a686/manual/socket.texi +--- glibc-2.17-c758a686/manual/socket.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/socket.texi 2014-09-12 16:10:06.046792714 -0400 +@@ -394,6 +394,8 @@ + @comment sys/socket.h + @comment BSD + @deftypefun int bind (int @var{socket}, struct sockaddr *@var{addr}, socklen_t @var{length}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall, except on Hurd. + The @code{bind} function assigns an address to the socket + @var{socket}. The @var{addr} and @var{length} arguments specify the + address; the detailed format of the address depends on the namespace. +@@ -442,6 +444,9 @@ + @comment sys/socket.h + @comment BSD + @deftypefun int getsockname (int @var{socket}, struct sockaddr *@var{addr}, socklen_t *@var{length-ptr}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{@acsmem{/hurd}}} ++@c Direct syscall, except on Hurd, where it seems like it might leak ++@c VM if cancelled. + The @code{getsockname} function returns information about the + address of the socket @var{socket} in the locations specified by the + @var{addr} and @var{length-ptr} arguments. Note that the +@@ -501,6 +506,14 @@ + @comment net/if.h + @comment IPv6 basic API + @deftypefun {unsigned int} if_nametoindex (const char *@var{ifname}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} ++@c It opens a socket to use ioctl on the fd to get the index. ++@c opensock may call socket and access multiple times until it finds a ++@c socket family that works. The Linux implementation has a potential ++@c concurrency issue WRT last_type and last_family not being updated ++@c atomically, but it is harmless; the generic implementation, OTOH, ++@c takes a lock, which makes all callers AS- and AC-Unsafe. ++@c opensock @asulock @aculock @acsfd + This function yields the interface index corresponding to a particular + name. If no interface exists with the name given, it returns 0. + @end deftypefun +@@ -508,6 +521,9 @@ + @comment net/if.h + @comment IPv6 basic API + @deftypefun {char *} if_indextoname (unsigned int @var{ifindex}, char *@var{ifname}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} ++@c It opens a socket with opensock to use ioctl on the fd to get the ++@c name from the index. + This function maps an interface index to its corresponding name. The + returned name is placed in the buffer pointed to by @code{ifname}, which + must be at least @code{IFNAMSIZ} bytes in length. If the index was +@@ -534,6 +550,39 @@ + @comment net/if.h + @comment IPv6 basic API + @deftypefun {struct if_nameindex *} if_nameindex (void) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @asulock{/hurd}}@acunsafe{@aculock{/hurd} @acsfd{} @acsmem{}}} ++@c if_nameindex @ascuheap @asulock/hurd @aculock/hurd @acsfd @acsmem ++@c [linux] ++@c netlink_open @acsfd @acsmem/hurd ++@c socket dup @acsfd ++@c memset dup ok ++@c bind dup ok ++@c netlink_close dup @acsfd ++@c getsockname dup @acsmem/hurd ++@c netlink_request @ascuheap @acsmem ++@c getpagesize dup ok ++@c malloc dup @ascuheap @acsmem ++@c netlink_sendreq ok ++@c memset dup ok ++@c sendto dup ok ++@c recvmsg dup ok ++@c memcpy dup ok ++@c free dup @ascuheap @acsmem ++@c netlink_free_handle @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c netlink_close @acsfd ++@c close dup @acsfd ++@c malloc dup @asuheap @acsmem ++@c strndup @ascuheap @acsmem ++@c if_freenameindex @ascuheap @acsmem ++@c [hurd] ++@c opensock dup @asulock @aculock @acsfd ++@c hurd_socket_server ok ++@c pfinet_siocgifconf ok ++@c malloc @ascuheap @acsmem ++@c strdup @ascuheap @acsmem ++@c ioctl dup ok ++@c free @ascuheap @acsmem + This function returns an array of @code{if_nameindex} structures, one + for every interface that is present. The end of the list is indicated + by a structure with an interface of 0 and a null name pointer. If an +@@ -546,6 +595,9 @@ + @comment net/if.h + @comment IPv6 basic API + @deftypefun void if_freenameindex (struct if_nameindex *@var{ptr}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} ++@c if_freenameindex @ascuheap @acsmem ++@c free dup @ascuheap @acsmem + This function frees the structure returned by an earlier call to + @code{if_nameindex}. + @end deftypefun +@@ -660,6 +712,7 @@ + @comment sys/un.h + @comment BSD + @deftypefn {Macro} int SUN_LEN (@emph{struct sockaddr_un *} @var{ptr}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The macro computes the length of socket address in the local namespace. + @end deftypefn + +@@ -689,7 +742,7 @@ + To create a socket in the IPv4 Internet namespace, use the symbolic name + @code{PF_INET} of this namespace as the @var{namespace} argument to + @code{socket} or @code{socketpair}. For IPv6 addresses you need the +-macro @code{PF_INET6}. These macros are defined in @file{sys/socket.h}. ++macro @code{PF_INET6}. These macros are defined in @file{sys/socket.h}. + @pindex sys/socket.h + + @comment sys/socket.h +@@ -726,12 +779,12 @@ + * Internet Address Formats:: How socket addresses are specified in the + Internet namespace. + * Host Addresses:: All about host addresses of Internet host. +-* Protocols Database:: Referring to protocols by name. + * Ports:: Internet port numbers. + * Services Database:: Ports may have symbolic names. + * Byte Order:: Different hosts may use different byte + ordering conventions; you need to + canonicalize host address and port number. ++* Protocols Database:: Referring to protocols by name. + * Inet Example:: Putting it all together. + @end menu + +@@ -1035,6 +1088,13 @@ + @comment arpa/inet.h + @comment BSD + @deftypefun int inet_aton (const char *@var{name}, struct in_addr *@var{addr}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} ++@c inet_aton @mtslocale ++@c isdigit dup @mtslocale ++@c strtoul dup @mtslocale ++@c isascii dup @mtslocale ++@c isspace dup @mtslocale ++@c htonl dup ok + This function converts the IPv4 Internet host address @var{name} + from the standard numbers-and-dots notation into binary data and stores + it in the @code{struct in_addr} that @var{addr} points to. +@@ -1044,10 +1104,13 @@ + @comment arpa/inet.h + @comment BSD + @deftypefun {uint32_t} inet_addr (const char *@var{name}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} ++@c inet_addr @mtslocale ++@c inet_aton dup @mtslocale + This function converts the IPv4 Internet host address @var{name} from the + standard numbers-and-dots notation into binary data. If the input is + not valid, @code{inet_addr} returns @code{INADDR_NONE}. This is an +-obsolete interface to @code{inet_aton}, described immediately above. It ++obsolete interface to @code{inet_aton}, described immediately above. It + is obsolete because @code{INADDR_NONE} is a valid address + (255.255.255.255), and @code{inet_aton} provides a cleaner way to + indicate error return. +@@ -1056,9 +1119,15 @@ + @comment arpa/inet.h + @comment BSD + @deftypefun {uint32_t} inet_network (const char *@var{name}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} ++@c inet_network @mtslocale ++@c isdigit dup @mtslocale ++@c isxdigit dup @mtslocale ++@c tolower dup @mtslocale ++@c isspace dup @mtslocale + This function extracts the network number from the address @var{name}, +-given in the standard numbers-and-dots notation. The returned address is +-in host order. If the input is not valid, @code{inet_network} returns ++given in the standard numbers-and-dots notation. The returned address is ++in host order. If the input is not valid, @code{inet_network} returns + @code{-1}. + + The function works only with traditional IPv4 class A, B and C network +@@ -1069,6 +1138,10 @@ + @comment arpa/inet.h + @comment BSD + @deftypefun {char *} inet_ntoa (struct in_addr @var{addr}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asurace{}}@acsafe{}} ++@c inet_ntoa @mtslocale @asurace ++@c writes to a thread-local static buffer ++@c snprintf @mtslocale [no @ascuheap or @acsmem] + This function converts the IPv4 Internet host address @var{addr} to a + string in the standard numbers-and-dots notation. The return value is + a pointer into a statically-allocated buffer. Subsequent calls will +@@ -1087,6 +1160,9 @@ + @comment arpa/inet.h + @comment BSD + @deftypefun {struct in_addr} inet_makeaddr (uint32_t @var{net}, uint32_t @var{local}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c inet_makeaddr ok ++@c htonl dup ok + This function makes an IPv4 Internet host address by combining the network + number @var{net} with the local-address-within-network number + @var{local}. +@@ -1095,6 +1171,11 @@ + @comment arpa/inet.h + @comment BSD + @deftypefun uint32_t inet_lnaof (struct in_addr @var{addr}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c inet_lnaof ok ++@c ntohl dup ok ++@c IN_CLASSA ok ++@c IN_CLASSB ok + This function returns the local-address-within-network part of the + Internet host address @var{addr}. + +@@ -1106,6 +1187,11 @@ + @comment arpa/inet.h + @comment BSD + @deftypefun uint32_t inet_netof (struct in_addr @var{addr}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c inet_netof ok ++@c ntohl dup ok ++@c IN_CLASSA ok ++@c IN_CLASSB ok + This function returns the network number part of the Internet host + address @var{addr}. + +@@ -1117,6 +1203,16 @@ + @comment arpa/inet.h + @comment IPv6 basic API + @deftypefun int inet_pton (int @var{af}, const char *@var{cp}, void *@var{buf}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} ++@c inet_pton @mtslocale ++@c inet_pton4 ok ++@c memcpy dup ok ++@c inet_pton6 @mtslocale ++@c memset dup ok ++@c tolower dup @mtslocale ++@c strchr dup ok ++@c inet_pton4 dup ok ++@c memcpy dup ok + This function converts an Internet address (either IPv4 or IPv6) from + presentation (textual) to network (binary) format. @var{af} should be + either @code{AF_INET} or @code{AF_INET6}, as appropriate for the type of +@@ -1127,7 +1223,17 @@ + + @comment arpa/inet.h + @comment IPv6 basic API +-@deftypefun {const char *} inet_ntop (int @var{af}, const void *@var{cp}, char *@var{buf}, size_t @var{len}) ++@deftypefun {const char *} inet_ntop (int @var{af}, const void *@var{cp}, char *@var{buf}, socklen_t @var{len}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} ++@c inet_ntop @mtslocale ++@c inet_ntop4 @mtslocale ++@c sprintf dup @mtslocale [no @ascuheap or @acsmem] ++@c strcpy dup ok ++@c inet_ntop6 @mtslocale ++@c memset dup ok ++@c inet_ntop4 dup @mtslocale ++@c sprintf dup @mtslocale [no @ascuheap or @acsmem] ++@c strcpy dup ok + This function converts an Internet address (either IPv4 or IPv6) from + network (binary) to presentation (textual) form. @var{af} should be + either @code{AF_INET} or @code{AF_INET6}, as appropriate. @var{cp} is a +@@ -1211,6 +1317,71 @@ + @comment netdb.h + @comment BSD + @deftypefun {struct hostent *} gethostbyname (const char *@var{name}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:hostbyname} @mtsenv{} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @asucorrupt{} @ascuheap{} @asulock{}}@acunsafe{@aculock{} @acucorrupt{} @acsmem{} @acsfd{}}} ++@c gethostbyname @mtasurace:hostbyname @mtsenv @mtslocale @ascudlopen @ascuplugin @asucorrupt @ascuheap @asulock @aculock @acucorrupt @acsmem @acsfd ++@c libc_lock_lock dup @asulock @aculock ++@c malloc dup @ascuheap @acsmem ++@c nss_hostname_digits_dots @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c res_maybe_init(!preinit) @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c res_iclose @acsuheap @acsmem @acsfd ++@c close_not_cancel_no_status dup @acsfd ++@c free dup @acsuheap @acsmem ++@c res_vinit @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c res_randomid ok ++@c getpid dup ok ++@c getenv dup @mtsenv ++@c strncpy dup ok ++@c fopen dup @ascuheap @asulock @acsmem @acsfd @aculock ++@c fsetlocking dup ok [no concurrent uses] ++@c fgets_unlocked dup ok [no concurrent uses] ++@c MATCH ok ++@c strncmp dup ok ++@c strpbrk dup ok ++@c strchr dup ok ++@c inet_aton dup @mtslocale ++@c htons dup ++@c inet_pton dup @mtslocale ++@c malloc dup @ascuheap @acsmem ++@c IN6_IS_ADDR_LINKLOCAL ok ++@c htonl dup ok ++@c IN6_IS_ADDR_MC_LINKLOCAL ok ++@c if_nametoindex dup @asulock @aculock @acsfd ++@c strtoul dup @mtslocale ++@c ISSORTMASK ok ++@c strchr dup ok ++@c isascii dup @mtslocale ++@c isspace dup @mtslocale ++@c net_mask ok ++@c ntohl dup ok ++@c IN_CLASSA dup ok ++@c htonl dup ok ++@c IN_CLASSB dup ok ++@c res_setoptions @mtslocale ++@c strncmp dup ok ++@c atoi dup @mtslocale ++@c fclose dup @ascuheap @asulock @aculock @acsmem @acsfd ++@c inet_makeaddr dup ok ++@c gethostname dup ok ++@c strcpy dup ok ++@c rawmemchr dup ok ++@c res_ninit @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c res_vinit dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c isdigit dup @mtslocale ++@c isxdigit dup @mtslocale ++@c strlen dup ok ++@c realloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c memset dup ok ++@c inet_aton dup @mtslocale ++@c inet_pton dup @mtslocale ++@c strcpy dup ok ++@c memcpy dup ok ++@c strchr dup ok ++@c gethostbyname_r dup @mtsenv @mtslocale @ascudlopen @ascuplugin @asucorrupt @ascuheap @asulock @aculock @acucorrupt @acsmem @acsfd ++@c realloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c libc_lock_unlock dup @aculock ++@c set_h_errno ok + The @code{gethostbyname} function returns information about the host + named @var{name}. If the lookup fails, it returns a null pointer. + @end deftypefun +@@ -1218,6 +1389,16 @@ + @comment netdb.h + @comment IPv6 Basic API + @deftypefun {struct hostent *} gethostbyname2 (const char *@var{name}, int @var{af}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:hostbyname2} @mtsenv{} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @asucorrupt{} @ascuheap{} @asulock{}}@acunsafe{@aculock{} @acucorrupt{} @acsmem{} @acsfd{}}} ++@c gethostbyname2 @mtasurace:hostbyname2 @mtsenv @mtslocale @ascudlopen @ascuplugin @asucorrupt @ascuheap @asulock @aculock @acucorrupt @acsmem @acsfd ++@c libc_lock_lock dup @asulock @aculock ++@c malloc dup @ascuheap @acsmem ++@c nss_hostname_digits_dots dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c gethostbyname2_r dup @mtsenv @mtslocale @ascudlopen @ascuplugin @asucorrupt @ascuheap @asulock @aculock @acucorrupt @acsmem @acsfd ++@c realloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c libc_lock_unlock dup @aculock ++@c set_h_errno dup ok + The @code{gethostbyname2} function is like @code{gethostbyname}, but + allows the caller to specify the desired address family (e.g.@: + @code{AF_INET} or @code{AF_INET6}) of the result. +@@ -1225,11 +1406,20 @@ + + @comment netdb.h + @comment BSD +-@deftypefun {struct hostent *} gethostbyaddr (const char *@var{addr}, size_t @var{length}, int @var{format}) ++@deftypefun {struct hostent *} gethostbyaddr (const void *@var{addr}, socklen_t @var{length}, int @var{format}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:hostbyaddr} @mtsenv{} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @asucorrupt{} @ascuheap{} @asulock{}}@acunsafe{@aculock{} @acucorrupt{} @acsmem{} @acsfd{}}} ++@c gethostbyaddr @mtasurace:hostbyaddr @mtsenv @mtslocale @ascudlopen @ascuplugin @asucorrupt @ascuheap @asulock @aculock @acucorrupt @acsmem @acsfd ++@c libc_lock_lock dup @asulock @aculock ++@c malloc dup @ascuheap @acsmem ++@c gethostbyaddr_r dup @mtsenv @mtslocale @ascudlopen @ascuplugin @asucorrupt @ascuheap @asulock @aculock @acucorrupt @acsmem @acsfd ++@c realloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c libc_lock_unlock dup @aculock ++@c set_h_errno dup ok + The @code{gethostbyaddr} function returns information about the host + with Internet address @var{addr}. The parameter @var{addr} is not + really a pointer to char - it can be a pointer to an IPv4 or an IPv6 +-address. The @var{length} argument is the size (in bytes) of the address ++address. The @var{length} argument is the size (in bytes) of the address + at @var{addr}. @var{format} specifies the address format; for an IPv4 + Internet address, specify a value of @code{AF_INET}; for an IPv6 + Internet address, use @code{AF_INET6}. +@@ -1282,6 +1472,76 @@ + @comment netdb.h + @comment GNU + @deftypefun int gethostbyname_r (const char *restrict @var{name}, struct hostent *restrict @var{result_buf}, char *restrict @var{buf}, size_t @var{buflen}, struct hostent **restrict @var{result}, int *restrict @var{h_errnop}) ++@safety{@prelim{}@mtsafe{@mtsenv{} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @asucorrupt{} @ascuheap{} @asulock{}}@acunsafe{@aculock{} @acucorrupt{} @acsmem{} @acsfd{}}} ++@c gethostbyname_r @mtsenv @mtslocale @ascudlopen @ascuplugin @asucorrupt @ascuheap @asulock @aculock @acucorrupt @acsmem @acsfd ++@c nss_hostname_digits_dots dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c nscd_gethostbyname_r @mtsenv @ascuheap @acsfd @acsmem ++@c nscd_gethst_r @mtsenv @ascuheap @acsfd @acsmem ++@c getenv dup @mtsenv ++@c nscd_get_map_ref dup @ascuheap @acsfd @acsmem ++@c nscd_cache_search dup ok ++@c memcpy dup ok ++@c nscd_open_socket dup @acsfd ++@c readvall dup ok ++@c readall dup ok ++@c close_not_cancel_no_status dup @acsfd ++@c nscd_drop_map_ref dup @ascuheap @acsmem ++@c nscd_unmap dup @ascuheap @acsmem ++@c res_maybe_init(!preinit) dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c res_hconf_init @mtsenv @mtslocale @asucorrupt @ascuheap @aculock @acucorrupt @acsmem [no @asuinit:reshconf @acuinit:reshconf, conditionally called] ++@c res_hconf.c:do_init @mtsenv @mtslocale @asucorrupt @ascuheap @aculock @acucorrupt @acsmem ++@c memset dup ok ++@c getenv dup @mtsenv ++@c fopen dup @ascuheap @asulock @acsmem @acsfd @aculock ++@c fsetlocking dup ok [no concurrent uses] ++@c fgets_unlocked dup ok [no concurrent uses] ++@c strchrnul dup ok ++@c res_hconf.c:parse_line @mtslocale @asucorrupt @ascuheap @aculock @acucorrupt @acsmem ++@c skip_ws dup @mtslocale ++@c skip_string dup @mtslocale ++@c strncasecmp dup @mtslocale ++@c strlen dup ok ++@c asprintf dup @mtslocale @ascuheap @acsmem ++@c fxprintf dup @asucorrupt @aculock @acucorrupt ++@c free dup @ascuheap @acsmem ++@c arg_trimdomain_list dup @mtslocale @asucorrupt @ascuheap @aculock @acucorrupt @acsmem ++@c arg_spoof dup @mtslocale ++@c arg_bool dup @mtslocale @asucorrupt @ascuheap @aculock @acucorrupt @acsmem ++@c isspace dup @mtslocale ++@c fclose dup @ascuheap @asulock @acsmem @acsfd @aculock ++@c arg_spoof @mtslocale ++@c skip_string @mtslocale ++@c isspace dup @mtslocale ++@c strncasecmp dup @mtslocale ++@c arg_bool @mtslocale @asucorrupt @ascuheap @aculock @acucorrupt @acsmem ++@c strncasecmp dup @mtslocale ++@c asprintf dup @mtslocale @ascuheap @acsmem ++@c fxprintf dup @asucorrupt @aculock @acucorrupt ++@c free dup @ascuheap @acsmem ++@c arg_trimdomain_list @mtslocale @asucorrupt @ascuheap @aculock @acucorrupt @acsmem ++@c skip_string dup @mtslocale ++@c asprintf dup @mtslocale @ascuheap @acsmem ++@c fxprintf dup @asucorrupt @aculock @acucorrupt ++@c free dup @ascuheap @acsmem ++@c strndup dup @ascuheap @acsmem ++@c skip_ws @mtslocale ++@c isspace dup @mtslocale ++@c nss_hosts_lookup2 @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nss_database_lookup dup @mtslocale @ascuheap @asulock @acucorrupt @acsmem @acsfd @aculock ++@c nss_lookup dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.l -> _nss_*_gethostbyname_r @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c res_hconf_reorder_addrs @asulock @ascuheap @aculock @acsmem @acsfd ++@c socket dup @acsfd ++@c libc_lock_lock dup @asulock @aculock ++@c ifreq @ascuheap @acsmem ++@c malloc dup @ascuheap @acsmem ++@c if_nextreq dup ok ++@c ioctl dup ok ++@c realloc dup @ascuheap @acsmem ++@c if_freereq dup @acsmem ++@c libc_lock_unlock dup @aculock ++@c close dup @acsfd + The @code{gethostbyname_r} function returns information about the host + named @var{name}. The caller must pass a pointer to an object of type + @code{struct hostent} in the @var{result_buf} parameter. In addition +@@ -1290,37 +1550,42 @@ + parameters. + + A pointer to the buffer, in which the result is stored, is available in +-@code{*@var{result}} after the function call successfully returned. If +-an error occurs or if no entry is found, the pointer @code{*@var{result}} +-is a null pointer. Success is signalled by a zero return value. If the +-function failed the return value is an error number. In addition to the +-errors defined for @code{gethostbyname} it can also be @code{ERANGE}. +-In this case the call should be repeated with a larger buffer. +-Additional error information is not stored in the global variable +-@code{h_errno} but instead in the object pointed to by @var{h_errnop}. ++@code{*@var{result}} after the function call successfully returned. The ++buffer passed as the @var{buf} parameter can be freed only once the caller ++has finished with the result hostent struct, or has copied it including all ++the other memory that it points to. If an error occurs or if no entry is ++found, the pointer @code{*@var{result}} is a null pointer. Success is ++signalled by a zero return value. If the function failed the return value ++is an error number. In addition to the errors defined for ++@code{gethostbyname} it can also be @code{ERANGE}. In this case the call ++should be repeated with a larger buffer. Additional error information is ++not stored in the global variable @code{h_errno} but instead in the object ++pointed to by @var{h_errnop}. + + Here's a small example: + @smallexample + struct hostent * + gethostname (char *host) + @{ +- struct hostent hostbuf, *hp; ++ struct hostent *hostbuf, *hp; + size_t hstbuflen; + char *tmphstbuf; + int res; + int herr; + ++ hostbuf = malloc (sizeof (struct hostent)); + hstbuflen = 1024; +- /* Allocate buffer, remember to free it to avoid memory leakage. */ + tmphstbuf = malloc (hstbuflen); + +- while ((res = gethostbyname_r (host, &hostbuf, tmphstbuf, hstbuflen, ++ while ((res = gethostbyname_r (host, hostbuf, tmphstbuf, hstbuflen, + &hp, &herr)) == ERANGE) + @{ + /* Enlarge the buffer. */ + hstbuflen *= 2; + tmphstbuf = realloc (tmphstbuf, hstbuflen); + @} ++ ++ free (tmphstbuf); + /* Check for errors. */ + if (res || hp == NULL) + return NULL; +@@ -1332,6 +1597,17 @@ + @comment netdb.h + @comment GNU + @deftypefun int gethostbyname2_r (const char *@var{name}, int @var{af}, struct hostent *restrict @var{result_buf}, char *restrict @var{buf}, size_t @var{buflen}, struct hostent **restrict @var{result}, int *restrict @var{h_errnop}) ++@safety{@prelim{}@mtsafe{@mtsenv{} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @asucorrupt{} @ascuheap{} @asulock{}}@acunsafe{@aculock{} @acucorrupt{} @acsmem{} @acsfd{}}} ++@c gethostbyname2_r @mtsenv @mtslocale @ascudlopen @ascuplugin @asucorrupt @ascuheap @asulock @aculock @acucorrupt @acsmem @acsfd ++@c nss_hostname_digits_dots dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c nscd_gethostbyname2_r @mtsenv @ascuheap @asulock @aculock @acsfd @acsmem ++@c nscd_gethst_r dup @mtsenv @ascuheap @asulock @aculock @acsfd @acsmem ++@c res_maybe_init(!preinit) dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c res_hconf_init dup @mtsenv @mtslocale @asucorrupt @ascuheap @aculock @acucorrupt @acsmem [no @asuinit:reshconf @acuinit:reshconf, conditionally called] ++@c nss_hosts_lookup2 dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.l -> _nss_*_gethostbyname2_r @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c res_hconf_reorder_addrs dup @asulock @ascuheap @aculock @acsmem @acsfd + The @code{gethostbyname2_r} function is like @code{gethostbyname_r}, but + allows the caller to specify the desired address family (e.g.@: + @code{AF_INET} or @code{AF_INET6}) for the result. +@@ -1339,11 +1615,26 @@ + + @comment netdb.h + @comment GNU +-@deftypefun int gethostbyaddr_r (const char *@var{addr}, size_t @var{length}, int @var{format}, struct hostent *restrict @var{result_buf}, char *restrict @var{buf}, size_t @var{buflen}, struct hostent **restrict @var{result}, int *restrict @var{h_errnop}) ++@deftypefun int gethostbyaddr_r (const void *@var{addr}, socklen_t @var{length}, int @var{format}, struct hostent *restrict @var{result_buf}, char *restrict @var{buf}, size_t @var{buflen}, struct hostent **restrict @var{result}, int *restrict @var{h_errnop}) ++@safety{@prelim{}@mtsafe{@mtsenv{} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @asucorrupt{} @ascuheap{} @asulock{}}@acunsafe{@aculock{} @acucorrupt{} @acsmem{} @acsfd{}}} ++@c gethostbyaddr_r @mtsenv @mtslocale @ascudlopen @ascuplugin @asucorrupt @ascuheap @asulock @aculock @acucorrupt @acsmem @acsfd ++@c memcmp dup ok ++@c nscd_gethostbyaddr_r @mtsenv @ascuheap @asulock @aculock @acsfd @acsmem ++@c nscd_gethst_r dup @mtsenv @ascuheap @asulock @aculock @acsfd @acsmem ++@c res_maybe_init(!preinit) dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c res_hconf_init dup @mtsenv @mtslocale @asucorrupt @ascuheap @aculock @acucorrupt @acsmem [no @asuinit:reshconf @acuinit:reshconf, conditionally called] ++@c nss_hosts_lookup2 dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.l -> _nss_*_gethostbyaddr_r @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c res_hconf_reorder_addrs dup @asulock @ascuheap @aculock @acsmem @acsfd ++@c res_hconf_trim_domains @mtslocale ++@c res_hconf_trim_domain @mtslocale ++@c strlen dup ok ++@c strcasecmp dup @mtslocale + The @code{gethostbyaddr_r} function returns information about the host + with Internet address @var{addr}. The parameter @var{addr} is not + really a pointer to char - it can be a pointer to an IPv4 or an IPv6 +-address. The @var{length} argument is the size (in bytes) of the address ++address. The @var{length} argument is the size (in bytes) of the address + at @var{addr}. @var{format} specifies the address format; for an IPv4 + Internet address, specify a value of @code{AF_INET}; for an IPv6 + Internet address, use @code{AF_INET6}. +@@ -1362,6 +1653,18 @@ + @comment netdb.h + @comment BSD + @deftypefun void sethostent (int @var{stayopen}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:hostent} @mtsenv{} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c sethostent @mtasurace:hostent @mtsenv @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c nss_setent(nss_hosts_lookup2) @mtasurace:hostent @mtsenv @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c res_maybe_init(!preinit) dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c set_h_errno dup ok ++@c setup(nss_hosts_lookup2) @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *lookup_fct = nss_hosts_lookup2 dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nss_lookup dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.f @mtasurace:hostent @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_unlock dup @aculock + This function opens the hosts database to begin scanning it. You can + then call @code{gethostent} to read the entries. + +@@ -1377,6 +1680,27 @@ + @comment netdb.h + @comment BSD + @deftypefun {struct hostent *} gethostent (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:hostent} @mtasurace{:hostentbuf} @mtsenv{} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c gethostent @mtasurace:hostent @mtasurace:hostentbuf @mtsenv @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c nss_getent(gethostent_r) @mtasurace:hostent @mtsenv @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c malloc dup @ascuheap @acsmem ++@c *func = gethostent_r dup @mtasurace:hostent @mtsenv @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c realloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c libc_lock_unlock dup @aculock ++@c ++@c gethostent_r @mtasurace:hostent @mtsenv @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c nss_getent_r(nss_hosts_lookup2) @mtasurace:hostent @mtsenv @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c res_maybe_init(!preinit) dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c setup(nss_hosts_lookup2) dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.f @mtasurace:hostent @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nss_lookup dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *sfct.f @mtasurace:hostent @ascuplugin ++@c libc_lock_unlock dup @aculock ++ + This function returns the next entry in the hosts database. It + returns a null pointer if there are no more entries. + @end deftypefun +@@ -1384,6 +1708,15 @@ + @comment netdb.h + @comment BSD + @deftypefun void endhostent (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:hostent} @mtsenv{} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c endhostent @mtasurace:hostent @mtsenv @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock @asulock @aculock ++@c nss_endent(nss_hosts_lookup2) @mtasurace:hostent @mtsenv @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c res_maybe_init(!preinit) dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c setup(nss_passwd_lookup2) dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.f @mtasurace:hostent @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_unlock @aculock + This function closes the hosts database. + @end deftypefun + +@@ -1483,6 +1816,34 @@ + @comment netdb.h + @comment BSD + @deftypefun {struct servent *} getservbyname (const char *@var{name}, const char *@var{proto}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:servbyname} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c getservbyname =~ getpwuid @mtasurace:servbyname @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c malloc dup @ascuheap @acsmem ++@c getservbyname_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c realloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c libc_lock_unlock dup @aculock ++@c ++@c getservbyname_r =~ getpwuid_r @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nscd_getservbyname_r @ascuheap @acsfd @acsmem ++@c nscd_getserv_r @ascuheap @acsfd @acsmem ++@c nscd_get_map_ref dup @ascuheap @acsfd @acsmem ++@c strlen dup ok ++@c malloc dup @ascuheap @acsmem ++@c mempcpy dup ok ++@c memcpy dup ok ++@c nscd_cache_search dup ok ++@c nscd_open_socket dup @acsfd ++@c readvall dup ok ++@c readall dup ok ++@c close_not_cancel_no_status dup @acsfd ++@c nscd_drop_map_ref dup @ascuheap @acsmem ++@c nscd_unmap dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c nss_services_lookup2 =~ nss_passwd_lookup2 @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.l -> _nss_*_getservbyname_r @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem + The @code{getservbyname} function returns information about the + service named @var{name} using protocol @var{proto}. If it can't find + such a service, it returns a null pointer. +@@ -1494,6 +1855,21 @@ + @comment netdb.h + @comment BSD + @deftypefun {struct servent *} getservbyport (int @var{port}, const char *@var{proto}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:servbyport} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c getservbyport =~ getservbyname @mtasurace:servbyport @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c malloc dup @ascuheap @acsmem ++@c getservbyport_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c realloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c libc_lock_unlock dup @aculock ++@c ++@c getservbyport_r =~ getservbyname_r @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nscd_getservbyport_r @ascuheap @acsfd @acsmem ++@c nscd_getserv_r dup @ascuheap @acsfd @acsmem ++@c nss_services_lookup2 =~ nss_passwd_lookup2 @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.l -> _nss_*_getservbyport_r @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem + The @code{getservbyport} function returns information about the + service at port @var{port} using protocol @var{proto}. If it can't + find such a service, it returns a null pointer. +@@ -1507,6 +1883,16 @@ + @comment netdb.h + @comment BSD + @deftypefun void setservent (int @var{stayopen}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:servent} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c setservent @mtasurace:servent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c nss_setent(nss_services_lookup2) @mtasurace:servenv @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c setup(nss_services_lookup2) @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *lookup_fct = nss_services_lookup2 dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nss_lookup dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.f @mtasurace:servent @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_unlock dup @aculock + This function opens the services database to begin scanning it. + + If the @var{stayopen} argument is nonzero, this sets a flag so that +@@ -1519,6 +1905,25 @@ + @comment netdb.h + @comment BSD + @deftypefun {struct servent *} getservent (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:servent} @mtasurace{:serventbuf} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c getservent @mtasurace:servent @mtasurace:serventbuf @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c nss_getent(getservent_r) @mtasurace:servent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c malloc dup @ascuheap @acsmem ++@c *func = getservent_r dup @mtasurace:servent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c realloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c libc_lock_unlock dup @aculock ++@c ++@c getservent_r @mtasurace:servent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c nss_getent_r(nss_services_lookup2) @mtasurace:servent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c setup(nss_services_lookup2) dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.f @mtasurace:servent @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nss_lookup dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *sfct.f @mtasurace:servent @ascuplugin ++@c libc_lock_unlock dup @aculock + This function returns the next entry in the services database. If + there are no more entries, it returns a null pointer. + @end deftypefun +@@ -1526,6 +1931,14 @@ + @comment netdb.h + @comment BSD + @deftypefun void endservent (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:servent} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c endservent @mtasurace:servent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock @asulock @aculock ++@c nss_endent(nss_services_lookup2) @mtasurace:servent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c setup(nss_services_lookup2) dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.f @mtasurace:servent @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_unlock @aculock + This function closes the services database. + @end deftypefun + +@@ -1571,6 +1984,11 @@ + @comment netinet/in.h + @comment BSD + @deftypefun {uint16_t} htons (uint16_t @var{hostshort}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c htons ok ++@c bswap_16 ok ++@c bswap_constant_16 ok ++ + This function converts the @code{uint16_t} integer @var{hostshort} from + host byte order to network byte order. + @end deftypefun +@@ -1578,6 +1996,8 @@ + @comment netinet/in.h + @comment BSD + @deftypefun {uint16_t} ntohs (uint16_t @var{netshort}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Alias to htons. + This function converts the @code{uint16_t} integer @var{netshort} from + network byte order to host byte order. + @end deftypefun +@@ -1585,6 +2005,9 @@ + @comment netinet/in.h + @comment BSD + @deftypefun {uint32_t} htonl (uint32_t @var{hostlong}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c htonl ok ++@c bswap_32 dup ok + This function converts the @code{uint32_t} integer @var{hostlong} from + host byte order to network byte order. + +@@ -1594,6 +2017,8 @@ + @comment netinet/in.h + @comment BSD + @deftypefun {uint32_t} ntohl (uint32_t @var{netlong}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Alias to htonl. + This function converts the @code{uint32_t} integer @var{netlong} from + network byte order to host byte order. + +@@ -1658,6 +2083,20 @@ + @comment netdb.h + @comment BSD + @deftypefun {struct protoent *} getprotobyname (const char *@var{name}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:protobyname} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c getprotobyname =~ getpwuid @mtasurace:protobyname @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c malloc dup @ascuheap @acsmem ++@c getprotobyname_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c realloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c libc_lock_unlock dup @aculock ++@c ++@c getprotobyname_r =~ getpwuid_r @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c no nscd support ++@c nss_protocols_lookup2 =~ nss_passwd_lookup2 @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.l -> _nss_*_getprotobyname_r @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem + The @code{getprotobyname} function returns information about the + network protocol named @var{name}. If there is no such protocol, it + returns a null pointer. +@@ -1666,6 +2105,20 @@ + @comment netdb.h + @comment BSD + @deftypefun {struct protoent *} getprotobynumber (int @var{protocol}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:protobynumber} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c getprotobynumber =~ getpwuid @mtasurace:protobynumber @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c malloc dup @ascuheap @acsmem ++@c getprotobynumber_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c realloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c libc_lock_unlock dup @aculock ++@c ++@c getprotobynumber_r =~ getpwuid_r @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c no nscd support ++@c nss_protocols_lookup2 =~ nss_passwd_lookup2 @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.l -> _nss_*_getprotobynumber_r @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem + The @code{getprotobynumber} function returns information about the + network protocol with number @var{protocol}. If there is no such + protocol, it returns a null pointer. +@@ -1678,6 +2131,16 @@ + @comment netdb.h + @comment BSD + @deftypefun void setprotoent (int @var{stayopen}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:protoent} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c setprotoent @mtasurace:protoent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c nss_setent(nss_protocols_lookup2) @mtasurace:protoent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c setup(nss_protocols_lookup2) @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *lookup_fct = nss_protocols_lookup2 dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nss_lookup dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.f @mtasurace:protoent @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_unlock dup @aculock + This function opens the protocols database to begin scanning it. + + If the @var{stayopen} argument is nonzero, this sets a flag so that +@@ -1690,6 +2153,25 @@ + @comment netdb.h + @comment BSD + @deftypefun {struct protoent *} getprotoent (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:protoent} @mtasurace{:protoentbuf} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c getprotoent @mtasurace:protoent @mtasurace:protoentbuf @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c nss_getent(getprotoent_r) @mtasurace:protoent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c malloc dup @ascuheap @acsmem ++@c *func = getprotoent_r dup @mtasurace:protoent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c realloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c libc_lock_unlock dup @aculock ++@c ++@c getprotoent_r @mtasurace:protoent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c nss_getent_r(nss_protocols_lookup2) @mtasurace:protoent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c setup(nss_protocols_lookup2) dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.f @mtasurace:servent @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nss_lookup dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *sfct.f @mtasurace:protoent @ascuplugin ++@c libc_lock_unlock dup @aculock + This function returns the next entry in the protocols database. It + returns a null pointer if there are no more entries. + @end deftypefun +@@ -1697,6 +2179,14 @@ + @comment netdb.h + @comment BSD + @deftypefun void endprotoent (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:protoent} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c endprotoent @mtasurace:protoent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock @asulock @aculock ++@c nss_endent(nss_protocols_lookup2) @mtasurace:protoent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c setup(nss_protocols_lookup2) dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.f @mtasurace:protoent @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_unlock @aculock + This function closes the protocols database. + @end deftypefun + +@@ -1766,6 +2256,7 @@ + @comment sys/socket.h + @comment BSD + @deftypefun int socket (int @var{namespace}, int @var{style}, int @var{protocol}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{@acsfd{}}} + This function creates a socket and specifies communication style + @var{style}, which should be one of the socket styles listed in + @ref{Communication Styles}. The @var{namespace} argument specifies +@@ -1828,6 +2319,7 @@ + @comment sys/socket.h + @comment BSD + @deftypefun int shutdown (int @var{socket}, int @var{how}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{shutdown} function shuts down the connection of socket + @var{socket}. The argument @var{how} specifies what action to + perform: +@@ -1879,6 +2371,7 @@ + @comment sys/socket.h + @comment BSD + @deftypefun int socketpair (int @var{namespace}, int @var{style}, int @var{protocol}, int @var{filedes}@t{[2]}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{@acsfd{}}} + This function creates a socket pair, returning the file descriptors in + @code{@var{filedes}[0]} and @code{@var{filedes}[1]}. The socket pair + is a full-duplex communications channel, so that both reading and writing +@@ -1972,6 +2465,7 @@ + @comment sys/socket.h + @comment BSD + @deftypefun int connect (int @var{socket}, struct sockaddr *@var{addr}, socklen_t @var{length}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{connect} function initiates a connection from the socket + with file descriptor @var{socket} to the socket whose address is + specified by the @var{addr} and @var{length} arguments. (This socket +@@ -2071,6 +2565,7 @@ + @comment sys/socket.h + @comment BSD + @deftypefun int listen (int @var{socket}, int @var{n}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{@acsfd{}}} + The @code{listen} function enables the socket @var{socket} to accept + connections, thus making it a server socket. + +@@ -2123,6 +2618,7 @@ + @comment sys/socket.h + @comment BSD + @deftypefun int accept (int @var{socket}, struct sockaddr *@var{addr}, socklen_t *@var{length_ptr}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{@acsfd{}}} + This function is used to accept a connection request on the server + socket @var{socket}. + +@@ -2181,6 +2677,7 @@ + @comment sys/socket.h + @comment BSD + @deftypefun int getpeername (int @var{socket}, struct sockaddr *@var{addr}, socklen_t *@var{length-ptr}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{getpeername} function returns the address of the socket that + @var{socket} is connected to; it stores the address in the memory space + specified by @var{addr} and @var{length-ptr}. It stores the length of +@@ -2248,7 +2745,8 @@ + + @comment sys/socket.h + @comment BSD +-@deftypefun int send (int @var{socket}, void *@var{buffer}, size_t @var{size}, int @var{flags}) ++@deftypefun ssize_t send (int @var{socket}, const void *@var{buffer}, size_t @var{size}, int @var{flags}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{send} function is like @code{write}, but with the additional + flags @var{flags}. The possible values of @var{flags} are described + in @ref{Socket Data Options}. +@@ -2315,7 +2813,8 @@ + + @comment sys/socket.h + @comment BSD +-@deftypefun int recv (int @var{socket}, void *@var{buffer}, size_t @var{size}, int @var{flags}) ++@deftypefun ssize_t recv (int @var{socket}, void *@var{buffer}, size_t @var{size}, int @var{flags}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{recv} function is like @code{read}, but with the additional + flags @var{flags}. The possible values of @var{flags} are described + in @ref{Socket Data Options}. +@@ -2643,7 +3142,8 @@ + + @comment sys/socket.h + @comment BSD +-@deftypefun int sendto (int @var{socket}, void *@var{buffer}, size_t @var{size}, int @var{flags}, struct sockaddr *@var{addr}, socklen_t @var{length}) ++@deftypefun ssize_t sendto (int @var{socket}, const void *@var{buffer}, size_t @var{size}, int @var{flags}, struct sockaddr *@var{addr}, socklen_t @var{length}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{sendto} function transmits the data in the @var{buffer} + through the socket @var{socket} to the destination address specified + by the @var{addr} and @var{length} arguments. The @var{size} argument +@@ -2678,7 +3178,8 @@ + + @comment sys/socket.h + @comment BSD +-@deftypefun int recvfrom (int @var{socket}, void *@var{buffer}, size_t @var{size}, int @var{flags}, struct sockaddr *@var{addr}, socklen_t *@var{length-ptr}) ++@deftypefun ssize_t recvfrom (int @var{socket}, void *@var{buffer}, size_t @var{size}, int @var{flags}, struct sockaddr *@var{addr}, socklen_t *@var{length-ptr}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{recvfrom} function reads one packet from the socket + @var{socket} into the buffer @var{buffer}. The @var{size} argument + specifies the maximum number of bytes to be read. +@@ -2725,7 +3226,8 @@ + + @comment sys/socket.h + @comment BSD +-@deftypefun int sendmsg (int @var{socket}, const struct msghdr *@var{message}, int @var{flags}) ++@deftypefun ssize_t sendmsg (int @var{socket}, const struct msghdr *@var{message}, int @var{flags}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + + This function is defined as a cancellation point in multi-threaded + programs, so one has to be prepared for this and make sure that +@@ -2736,7 +3238,8 @@ + + @comment sys/socket.h + @comment BSD +-@deftypefun int recvmsg (int @var{socket}, struct msghdr *@var{message}, int @var{flags}) ++@deftypefun ssize_t recvmsg (int @var{socket}, struct msghdr *@var{message}, int @var{flags}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + + This function is defined as a cancellation point in multi-threaded + programs, so one has to be prepared for this and make sure that +@@ -2924,6 +3427,7 @@ + @comment sys/socket.h + @comment BSD + @deftypefun int getsockopt (int @var{socket}, int @var{level}, int @var{optname}, void *@var{optval}, socklen_t *@var{optlen-ptr}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{getsockopt} function gets information about the value of + option @var{optname} at level @var{level} for socket @var{socket}. + +@@ -2953,7 +3457,8 @@ + + @comment sys/socket.h + @comment BSD +-@deftypefun int setsockopt (int @var{socket}, int @var{level}, int @var{optname}, void *@var{optval}, socklen_t @var{optlen}) ++@deftypefun int setsockopt (int @var{socket}, int @var{level}, int @var{optname}, const void *@var{optval}, socklen_t @var{optlen}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function is used to set the socket option @var{optname} at level + @var{level} for socket @var{socket}. The value of the option is passed + in the buffer @var{optval} of size @var{optlen}. +@@ -3150,6 +3655,21 @@ + @comment netdb.h + @comment BSD + @deftypefun {struct netent *} getnetbyname (const char *@var{name}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:netbyname} @mtsenv{} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c getnetbyname =~ getpwuid @mtasurace:netbyname @mtsenv @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c malloc dup @ascuheap @acsmem ++@c getnetbyname_r dup @mtsenv @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c realloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c libc_lock_unlock dup @aculock ++@c ++@c getnetbyname_r =~ getpwuid_r @mtsenv @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c no nscd support ++@c res_maybe_init(!preinit) dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c nss_networks_lookup2 =~ nss_passwd_lookup2 @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.l -> _nss_*_getnetbyname_r @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem + The @code{getnetbyname} function returns information about the network + named @var{name}. It returns a null pointer if there is no such + network. +@@ -3157,7 +3677,21 @@ + + @comment netdb.h + @comment BSD +-@deftypefun {struct netent *} getnetbyaddr (unsigned long int @var{net}, int @var{type}) ++@deftypefun {struct netent *} getnetbyaddr (uint32_t @var{net}, int @var{type}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:netbyaddr} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c getnetbyaddr =~ getpwuid @mtasurace:netbyaddr @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c malloc dup @ascuheap @acsmem ++@c getnetbyaddr_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c realloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c libc_lock_unlock dup @aculock ++@c ++@c getnetbyaddr_r =~ getpwuid_r @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c no nscd support ++@c nss_networks_lookup2 =~ nss_passwd_lookup2 @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.l -> _nss_*_getnetbyaddr_r @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem + The @code{getnetbyaddr} function returns information about the network + of type @var{type} with number @var{net}. You should specify a value of + @code{AF_INET} for the @var{type} argument for Internet networks. +@@ -3173,6 +3707,17 @@ + @comment netdb.h + @comment BSD + @deftypefun void setnetent (int @var{stayopen}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:netent} @mtsenv{} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c setnetent @mtasurace:netent @mtsenv @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c nss_setent(nss_networks_lookup2) @mtasurace:netent @mtsenv @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c res_maybe_init(!preinit) dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c setup(nss_networks_lookup2) @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *lookup_fct = nss_networks_lookup2 dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nss_lookup dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.f @mtasurace:netent @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_unlock dup @aculock + This function opens and rewinds the networks database. + + If the @var{stayopen} argument is nonzero, this sets a flag so that +@@ -3185,6 +3730,26 @@ + @comment netdb.h + @comment BSD + @deftypefun {struct netent *} getnetent (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:netent} @mtasurace{:netentbuf} @mtsenv{} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c getnetent @mtasurace:netent @mtasurace:netentbuf @mtsenv @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c nss_getent(getnetent_r) @mtasurace:netent @mtsenv @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c malloc dup @ascuheap @acsmem ++@c *func = getnetent_r dup @mtasurace:netent @mtsenv @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c realloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c libc_lock_unlock dup @aculock ++@c ++@c getnetent_r @mtasurace:netent @mtsenv @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c nss_getent_r(nss_networks_lookup2) @mtasurace:netent @mtsenv @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c res_maybe_init(!preinit) dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c setup(nss_networks_lookup2) dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.f @mtasurace:servent @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nss_lookup dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *sfct.f @mtasurace:netent @ascuplugin ++@c libc_lock_unlock dup @aculock + This function returns the next entry in the networks database. It + returns a null pointer if there are no more entries. + @end deftypefun +@@ -3192,5 +3757,14 @@ + @comment netdb.h + @comment BSD + @deftypefun void endnetent (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:netent} @mtsenv{} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c endnetent @mtasurace:netent @mtsenv @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock @asulock @aculock ++@c nss_endent(nss_networks_lookup2) @mtasurace:netent @mtsenv @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c res_maybe_init(!preinit) dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c setup(nss_networks_lookup2) dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.f @mtasurace:netent @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_unlock @aculock + This function closes the networks database. + @end deftypefun +diff -urN glibc-2.17-c758a686/manual/startup.texi glibc-2.17-c758a686/manual/startup.texi +--- glibc-2.17-c758a686/manual/startup.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/startup.texi 2014-09-12 16:10:06.042792724 -0400 +@@ -41,7 +41,7 @@ + * Program Termination:: Telling the system you're done; return status + @end menu + +-@node Program Arguments ++@node Program Arguments, Environment Variables, , Program Basics + @section Program Arguments + @cindex program arguments + @cindex command line arguments +@@ -220,7 +220,12 @@ + available. + + @comment stdlib.h +-@deftypefun int getsubopt (char **@var{optionp}, const char* const *@var{tokens}, char **@var{valuep}) ++@deftypefun int getsubopt (char **@var{optionp}, char *const *@var{tokens}, char **@var{valuep}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c getsubopt ok ++@c strchrnul dup ok ++@c memchr dup ok ++@c strncmp dup ok + + The @var{optionp} parameter must be a pointer to a variable containing + the address of the string to process. When the function returns the +@@ -258,7 +263,7 @@ + @end smallexample + + +-@node Environment Variables ++@node Environment Variables, Auxiliary Vector, Program Arguments, Program Basics + @section Environment Variables + + @cindex environment variable +@@ -322,6 +327,8 @@ + @comment stdlib.h + @comment ISO + @deftypefun {char *} getenv (const char *@var{name}) ++@safety{@prelim{}@mtsafe{@mtsenv{}}@assafe{}@acsafe{}} ++@c Unguarded access to __environ. + This function returns a string that is the value of the environment + variable @var{name}. You must not modify this string. In some non-Unix + systems not using @theglibc{}, it might be overwritten by subsequent +@@ -333,6 +340,8 @@ + @comment stdlib.h + @comment GNU + @deftypefun {char *} secure_getenv (const char *@var{name}) ++@safety{@prelim{}@mtsafe{@mtsenv{}}@assafe{}@acsafe{}} ++@c Calls getenv unless secure mode is enabled. + This function is similar to @code{getenv}, but it returns a null + pointer if the environment is untrusted. This happens when the + program file has SUID or SGID bits set. General-purpose libraries +@@ -346,6 +355,13 @@ + @comment stdlib.h + @comment SVID + @deftypefun int putenv (char *@var{string}) ++@safety{@prelim{}@mtunsafe{@mtasuconst{:@mtsenv{}}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{}}} ++@c putenv @mtasuconst:@mtsenv @ascuheap @asulock @acucorrupt @aculock @acsmem ++@c strchr dup ok ++@c strndup dup @ascuheap @acsmem ++@c add_to_environ dup @mtasuconst:@mtsenv @ascuheap @asulock @acucorrupt @aculock @acsmem ++@c free dup @ascuheap @acsmem ++@c unsetenv dup @mtasuconst:@mtsenv @asulock @aculock + The @code{putenv} function adds or removes definitions from the environment. + If the @var{string} is of the form @samp{@var{name}=@var{value}}, the + definition is added to the environment. Otherwise, the @var{string} is +@@ -358,20 +374,37 @@ + The difference to the @code{setenv} function is that the exact string + given as the parameter @var{string} is put into the environment. If the + user should change the string after the @code{putenv} call this will +-reflect in automatically in the environment. This also requires that +-@var{string} is no automatic variable which scope is left before the ++reflect automatically in the environment. This also requires that ++@var{string} not be an automatic variable whose scope is left before the + variable is removed from the environment. The same applies of course to + dynamically allocated variables which are freed later. + +-This function is part of the extended Unix interface. Since it was also +-available in old SVID libraries you should define either +-@var{_XOPEN_SOURCE} or @var{_SVID_SOURCE} before including any header. ++This function is part of the extended Unix interface. You should define ++@var{_XOPEN_SOURCE} before including any header. + @end deftypefun + + + @comment stdlib.h + @comment BSD + @deftypefun int setenv (const char *@var{name}, const char *@var{value}, int @var{replace}) ++@safety{@prelim{}@mtunsafe{@mtasuconst{:@mtsenv{}}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{}}} ++@c setenv @mtasuconst:@mtsenv @ascuheap @asulock @acucorrupt @aculock @acsmem ++@c add_to_environ @mtasuconst:@mtsenv @ascuheap @asulock @acucorrupt @aculock @acsmem ++@c strlen dup ok ++@c libc_lock_lock @asulock @aculock ++@c strncmp dup ok ++@c realloc dup @ascuheap @acsmem ++@c libc_lock_unlock @aculock ++@c malloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c mempcpy dup ok ++@c memcpy dup ok ++@c KNOWN_VALUE ok ++@c tfind(strcmp) [no @mtsrace guarded access] ++@c strcmp dup ok ++@c STORE_VALUE @ascuheap @acucorrupt @acsmem ++@c tsearch(strcmp) @ascuheap @acucorrupt @acsmem [no @mtsrace or @asucorrupt guarded access makes for mtsafe and @asulock] ++@c strcmp dup ok + The @code{setenv} function can be used to add a new definition to the + environment. The entry with the name @var{name} is replaced by the + value @samp{@var{name}=@var{value}}. Please note that this is also true +@@ -395,6 +428,13 @@ + @comment stdlib.h + @comment BSD + @deftypefun int unsetenv (const char *@var{name}) ++@safety{@prelim{}@mtunsafe{@mtasuconst{:@mtsenv{}}}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} ++@c unsetenv @mtasuconst:@mtsenv @asulock @aculock ++@c strchr dup ok ++@c strlen dup ok ++@c libc_lock_lock @asulock @aculock ++@c strncmp dup ok ++@c libc_lock_unlock @aculock + Using this function one can remove an entry completely from the + environment. If the environment contains an entry with the key + @var{name} this whole entry is removed. A call to this function is +@@ -418,6 +458,11 @@ + @comment stdlib.h + @comment GNU + @deftypefun int clearenv (void) ++@safety{@prelim{}@mtunsafe{@mtasuconst{:@mtsenv{}}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsmem{}}} ++@c clearenv @mtasuconst:@mtsenv @ascuheap @asulock @aculock @acsmem ++@c libc_lock_lock @asulock @aculock ++@c free dup @ascuheap @acsmem ++@c libc_lock_unlock @aculock + The @code{clearenv} function removes all entries from the environment. + Using @code{putenv} and @code{setenv} new entries can be added again + later. +@@ -622,10 +667,13 @@ + @subsection Definition of @code{getauxval} + @comment sys/auxv.h + @deftypefun {unsigned long int} getauxval (unsigned long int @var{type}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Reads from hwcap or iterates over constant auxv. + This function is used to inquire about the entries in the auxiliary + vector. The @var{type} argument should be one of the @samp{AT_} symbols + defined in @file{elf.h}. If a matching entry is found, the value is +-returned; if the entry is not found, zero is returned. ++returned; if the entry is not found, zero is returned and @code{errno} is ++set to @code{ENOENT}. + @end deftypefun + + For some platforms, the key @code{AT_HWCAP} is the easiest way to inquire +@@ -677,6 +725,7 @@ + @comment unistd.h + @comment ??? + @deftypefun {long int} syscall (long int @var{sysno}, @dots{}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + + @code{syscall} performs a generic system call. + +@@ -782,6 +831,10 @@ + @comment stdlib.h + @comment ISO + @deftypefun void exit (int @var{status}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:exit}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}} ++@c Access to the atexit/on_exit list, the libc_atexit hook and tls dtors ++@c is not guarded. Streams must be flushed, and that triggers the usual ++@c AS and AC issues with streams. + The @code{exit} function tells the system that the program is done, which + causes it to terminate the process. + +@@ -898,6 +951,15 @@ + @comment stdlib.h + @comment ISO + @deftypefun int atexit (void (*@var{function}) (void)) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsmem{}}} ++@c atexit @ascuheap @asulock @aculock @acsmem ++@c cxa_atexit @ascuheap @asulock @aculock @acsmem ++@c __internal_atexit @ascuheap @asulock @aculock @acsmem ++@c __new_exitfn @ascuheap @asulock @aculock @acsmem ++@c __libc_lock_lock @asulock @aculock ++@c calloc dup @ascuheap @acsmem ++@c __libc_lock_unlock @aculock ++@c atomic_write_barrier dup ok + The @code{atexit} function registers the function @var{function} to be + called at normal program termination. The @var{function} is called with + no arguments. +@@ -909,6 +971,10 @@ + @comment stdlib.h + @comment SunOS + @deftypefun int on_exit (void (*@var{function})(int @var{status}, void *@var{arg}), void *@var{arg}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsmem{}}} ++@c on_exit @ascuheap @asulock @aculock @acsmem ++@c new_exitfn dup @ascuheap @asulock @aculock @acsmem ++@c atomic_write_barrier dup ok + This function is a somewhat more powerful variant of @code{atexit}. It + accepts two arguments, a function @var{function} and an arbitrary + pointer @var{arg}. At normal program termination, the @var{function} is +@@ -940,6 +1006,10 @@ + @comment stdlib.h + @comment ISO + @deftypefun void abort (void) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} ++@c The implementation takes a recursive lock and attempts to support ++@c calls from signal handlers, but if we're in the middle of flushing or ++@c using streams, we may encounter them in inconsistent states. + The @code{abort} function causes abnormal program termination. This + does not execute cleanup functions registered with @code{atexit} or + @code{on_exit}. +@@ -967,6 +1037,9 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun void _exit (int @var{status}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall (exit_group or exit); calls __task_terminate on hurd, ++@c and abort in the generic posix implementation. + The @code{_exit} function is the primitive for causing a process to + terminate with status @var{status}. Calling this function does not + execute cleanup functions registered with @code{atexit} or +@@ -976,6 +1049,8 @@ + @comment stdlib.h + @comment ISO + @deftypefun void _Exit (int @var{status}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Alias for _exit. + The @code{_Exit} function is the @w{ISO C} equivalent to @code{_exit}. + The @w{ISO C} committee members were not sure whether the definitions of + @code{_exit} and @code{_Exit} were compatible so they have not used the +diff -urN glibc-2.17-c758a686/manual/stdio.texi glibc-2.17-c758a686/manual/stdio.texi +--- glibc-2.17-c758a686/manual/stdio.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/stdio.texi 2014-09-12 16:10:06.043792722 -0400 +@@ -148,6 +148,8 @@ + @comment stdio.h + @comment ISO + @deftypefun {FILE *} fopen (const char *@var{filename}, const char *@var{opentype}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@acsmem{} @acsfd{} @aculock{}}} ++@c fopen may leak the list lock if cancelled within _IO_link_in. + The @code{fopen} function opens a stream for I/O to the file + @var{filename}, and returns a pointer to the stream. + +@@ -265,9 +267,10 @@ + @comment stdio.h + @comment Unix98 + @deftypefun {FILE *} fopen64 (const char *@var{filename}, const char *@var{opentype}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@acsmem{} @acsfd{} @aculock{}}} + This function is similar to @code{fopen} but the stream it returns a + pointer for is opened using @code{open64}. Therefore this stream can be +-used even on files larger then @math{2^31} bytes on 32 bit machines. ++used even on files larger than @math{2^31} bytes on 32 bit machines. + + Please note that the return type is still @code{FILE *}. There is no + special @code{FILE} type for the LFS interface. +@@ -294,6 +297,16 @@ + @comment stdio.h + @comment ISO + @deftypefun {FILE *} freopen (const char *@var{filename}, const char *@var{opentype}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @acsfd{}}} ++@c Like most I/O operations, this one is guarded by a recursive lock, ++@c released even upon cancellation, but cancellation may leak file ++@c descriptors and leave the stream in an inconsistent state (e.g., ++@c still bound to the closed descriptor). Also, if the stream is ++@c part-way through a significant update (say running freopen) when a ++@c signal handler calls freopen again on the same stream, the result is ++@c likely to be an inconsistent stream, and the possibility of closing ++@c twice file descriptor number that the stream used to use, the second ++@c time when it might have already been reused by another thread. + This function is like a combination of @code{fclose} and @code{fopen}. + It first closes the stream referred to by @var{stream}, ignoring any + errors that are detected in the process. (Because errors are ignored, +@@ -320,6 +333,7 @@ + @comment stdio.h + @comment Unix98 + @deftypefun {FILE *} freopen64 (const char *@var{filename}, const char *@var{opentype}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @acsfd{}}} + This function is similar to @code{freopen}. The only difference is that + on 32 bit machine the stream returned is able to read beyond the + @math{2^31} bytes limits imposed by the normal interface. It should be +@@ -341,6 +355,7 @@ + @comment stdio_ext.h + @comment GNU + @deftypefun int __freadable (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{__freadable} function determines whether the stream + @var{stream} was opened to allow reading. In this case the return value + is nonzero. For write-only streams the function returns zero. +@@ -351,6 +366,7 @@ + @comment stdio_ext.h + @comment GNU + @deftypefun int __fwritable (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{__fwritable} function determines whether the stream + @var{stream} was opened to allow writing. In this case the return value + is nonzero. For read-only streams the function returns zero. +@@ -364,6 +380,7 @@ + @comment stdio_ext.h + @comment GNU + @deftypefun int __freading (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{__freading} function determines whether the stream + @var{stream} was last read from or whether it is opened read-only. In + this case the return value is nonzero, otherwise it is zero. +@@ -377,6 +394,7 @@ + @comment stdio_ext.h + @comment GNU + @deftypefun int __fwriting (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{__fwriting} function determines whether the stream + @var{stream} was last written to or whether it is opened write-only. In + this case the return value is nonzero, otherwise it is zero. +@@ -396,6 +414,21 @@ + @comment stdio.h + @comment ISO + @deftypefun int fclose (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsmem{} @acsfd{}}} ++@c After fclose, it is undefined behavior to use the stream it points ++@c to. Therefore, one must only call fclose when the stream is ++@c otherwise unused. Concurrent uses started before will complete ++@c successfully because of the lock, which makes it MT-Safe. Calling it ++@c from a signal handler is perfectly safe if the stream is known to be ++@c no longer used, which is a precondition for fclose to be safe in the ++@c first place; since this is no further requirement, fclose is safe for ++@c use in async signals too. After calling fclose, you can no longer ++@c use the stream, not even to fclose it again, so its memory and file ++@c descriptor may leak if fclose is canceled before @c releasing them. ++@c That the stream must be unused and it becomes unused after the call ++@c is what would enable fclose to be AS- and AC-Safe while freopen ++@c isn't. However, because of the possibility of leaving __gconv_lock ++@c taken upon cancellation, AC-Safety is lost. + This function causes @var{stream} to be closed and the connection to + the corresponding file to be broken. Any buffered output is written + and any buffered input is discarded. The @code{fclose} function returns +@@ -418,6 +451,12 @@ + @comment stdio.h + @comment GNU + @deftypefun int fcloseall (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:streams}}@asunsafe{}@acsafe{}} ++@c Like fclose, using any previously-opened streams after fcloseall is ++@c undefined. However, the implementation of fcloseall isn't equivalent ++@c to calling fclose for all streams: it just flushes and unbuffers all ++@c streams, without any locking. It's the flushing without locking that ++@c makes it unsafe. + This function causes all open streams of the process to be closed and + the connection to corresponding files to be broken. All buffered data + is written and any buffered input is discarded. The @code{fcloseall} +@@ -474,6 +513,9 @@ + @comment stdio.h + @comment POSIX + @deftypefun void flockfile (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@aculock{}}} ++@c There's no way to tell whether the lock was acquired before or after ++@c cancellation so as to unlock only when appropriate. + The @code{flockfile} function acquires the internal locking object + associated with the stream @var{stream}. This ensures that no other + thread can explicitly through @code{flockfile}/@code{ftrylockfile} or +@@ -485,6 +527,7 @@ + @comment stdio.h + @comment POSIX + @deftypefun int ftrylockfile (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@aculock{}}} + The @code{ftrylockfile} function tries to acquire the internal locking + object associated with the stream @var{stream} just like + @code{flockfile}. But unlike @code{flockfile} this function does not +@@ -496,8 +539,9 @@ + @comment stdio.h + @comment POSIX + @deftypefun void funlockfile (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@aculock{}}} + The @code{funlockfile} function releases the internal locking object of +-the stream @var{stream}. The stream must have been locked before by a ++the stream @var{stream}. The stream must have been locked before by a + call to @code{flockfile} or a successful call of @code{ftrylockfile}. + The implicit locking performed by the stream operations do not count. + The @code{funlockfile} function does not return an error status and the +@@ -621,6 +665,15 @@ + @comment stdio_ext.h + @comment GNU + @deftypefun int __fsetlocking (FILE *@var{stream}, int @var{type}) ++@safety{@prelim{}@mtsafe{@mtsrace{:stream}}@asunsafe{@asulock{}}@acsafe{}} ++@c Changing the implicit-locking status of a stream while it's in use by ++@c another thread may cause a lock to be implicitly acquired and not ++@c released, or vice-versa. This function should probably hold the lock ++@c while changing this setting, to make sure we don't change it while ++@c there are any concurrent uses. Meanwhile, callers should acquire the ++@c lock themselves to be safe, and even concurrent uses with external ++@c locking will be fine, as long as functions that require external ++@c locking are not called without holding locks. + + The @code{__fsetlocking} function can be used to select whether the + stream operations will implicitly acquire the locking object of the +@@ -725,6 +778,10 @@ + @comment wchar.h + @comment ISO + @deftypefun int fwide (FILE *@var{stream}, int @var{mode}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{}}} ++@c Querying is always safe, but changing the stream when it's in use ++@c upthread may be problematic. Like most lock-acquiring functions, ++@c this one may leak the lock if canceled. + + The @code{fwide} function can be used to set and query the state of the + orientation of the stream @var{stream}. If the @var{mode} parameter has +@@ -811,6 +868,16 @@ + @comment stdio.h + @comment ISO + @deftypefun int fputc (int @var{c}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}} ++@c If the stream is in use when interrupted by a signal, the recursive ++@c lock won't help ensure the stream is consistent; indeed, if fputc ++@c gets a signal precisely before the post-incremented _IO_write_ptr ++@c value is stored, we may overwrite the interrupted write. Conversely, ++@c depending on compiler optimizations, the incremented _IO_write_ptr ++@c may be stored before the character is stored in the buffer, ++@c corrupting the stream if async cancel hits between the two stores. ++@c There may be other reasons for AS- and AC-unsafety in the overflow ++@c cases. + The @code{fputc} function converts the character @var{c} to type + @code{unsigned char}, and writes it to the stream @var{stream}. + @code{EOF} is returned if a write error occurs; otherwise the +@@ -820,6 +887,7 @@ + @comment wchar.h + @comment ISO + @deftypefun wint_t fputwc (wchar_t @var{wc}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}} + The @code{fputwc} function writes the wide character @var{wc} to the + stream @var{stream}. @code{WEOF} is returned if a write error occurs; + otherwise the character @var{wc} is returned. +@@ -828,13 +896,18 @@ + @comment stdio.h + @comment POSIX + @deftypefun int fputc_unlocked (int @var{c}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{@mtsrace{:stream}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} ++@c The unlocked functions can't possibly satisfy the MT-Safety ++@c requirements on their own, because they require external locking for ++@c safety. + The @code{fputc_unlocked} function is equivalent to the @code{fputc} + function except that it does not implicitly lock the stream. + @end deftypefun + + @comment wchar.h + @comment POSIX +-@deftypefun wint_t fputwc_unlocked (wint_t @var{wc}, FILE *@var{stream}) ++@deftypefun wint_t fputwc_unlocked (wchar_t @var{wc}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{@mtsrace{:stream}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} + The @code{fputwc_unlocked} function is equivalent to the @code{fputwc} + function except that it does not implicitly lock the stream. + +@@ -844,6 +917,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int putc (int @var{c}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}} + This is just like @code{fputc}, except that most systems implement it as + a macro, making it faster. One consequence is that it may evaluate the + @var{stream} argument more than once, which is an exception to the +@@ -854,6 +928,7 @@ + @comment wchar.h + @comment ISO + @deftypefun wint_t putwc (wchar_t @var{wc}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}} + This is just like @code{fputwc}, except that it can be implement as + a macro, making it faster. One consequence is that it may evaluate the + @var{stream} argument more than once, which is an exception to the +@@ -864,6 +939,7 @@ + @comment stdio.h + @comment POSIX + @deftypefun int putc_unlocked (int @var{c}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{@mtsrace{:stream}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} + The @code{putc_unlocked} function is equivalent to the @code{putc} + function except that it does not implicitly lock the stream. + @end deftypefun +@@ -871,6 +947,7 @@ + @comment wchar.h + @comment GNU + @deftypefun wint_t putwc_unlocked (wchar_t @var{wc}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{@mtsrace{:stream}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} + The @code{putwc_unlocked} function is equivalent to the @code{putwc} + function except that it does not implicitly lock the stream. + +@@ -880,6 +957,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int putchar (int @var{c}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}} + The @code{putchar} function is equivalent to @code{putc} with + @code{stdout} as the value of the @var{stream} argument. + @end deftypefun +@@ -887,6 +965,7 @@ + @comment wchar.h + @comment ISO + @deftypefun wint_t putwchar (wchar_t @var{wc}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}} + The @code{putwchar} function is equivalent to @code{putwc} with + @code{stdout} as the value of the @var{stream} argument. + @end deftypefun +@@ -894,6 +973,7 @@ + @comment stdio.h + @comment POSIX + @deftypefun int putchar_unlocked (int @var{c}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:stdout}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} + The @code{putchar_unlocked} function is equivalent to the @code{putchar} + function except that it does not implicitly lock the stream. + @end deftypefun +@@ -901,6 +981,7 @@ + @comment wchar.h + @comment GNU + @deftypefun wint_t putwchar_unlocked (wchar_t @var{wc}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:stdout}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} + The @code{putwchar_unlocked} function is equivalent to the @code{putwchar} + function except that it does not implicitly lock the stream. + +@@ -910,6 +991,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int fputs (const char *@var{s}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}} + The function @code{fputs} writes the string @var{s} to the stream + @var{stream}. The terminating null character is not written. + This function does @emph{not} add a newline character, either. +@@ -933,6 +1015,7 @@ + @comment wchar.h + @comment ISO + @deftypefun int fputws (const wchar_t *@var{ws}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}} + The function @code{fputws} writes the wide character string @var{ws} to + the stream @var{stream}. The terminating null character is not written. + This function does @emph{not} add a newline character, either. It +@@ -945,6 +1028,7 @@ + @comment stdio.h + @comment GNU + @deftypefun int fputs_unlocked (const char *@var{s}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{@mtsrace{:stream}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} + The @code{fputs_unlocked} function is equivalent to the @code{fputs} + function except that it does not implicitly lock the stream. + +@@ -954,6 +1038,7 @@ + @comment wchar.h + @comment GNU + @deftypefun int fputws_unlocked (const wchar_t *@var{ws}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{@mtsrace{:stream}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} + The @code{fputws_unlocked} function is equivalent to the @code{fputws} + function except that it does not implicitly lock the stream. + +@@ -963,6 +1048,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int puts (const char *@var{s}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + The @code{puts} function writes the string @var{s} to the stream + @code{stdout} followed by a newline. The terminating null character of + the string is not written. (Note that @code{fputs} does @emph{not} +@@ -982,6 +1068,7 @@ + @comment stdio.h + @comment SVID + @deftypefun int putw (int @var{w}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + This function writes the word @var{w} (that is, an @code{int}) to + @var{stream}. It is provided for compatibility with SVID, but we + recommend you use @code{fwrite} instead (@pxref{Block Input/Output}). +@@ -1014,6 +1101,11 @@ + @comment stdio.h + @comment ISO + @deftypefun int fgetc (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} ++@c Same caveats as fputc, but instead of losing a write in case of async ++@c signals, we may read the same character more than once, and the ++@c stream may be left in odd states due to cancellation in the underflow ++@c cases. + This function reads the next character as an @code{unsigned char} from + the stream @var{stream} and returns its value, converted to an + @code{int}. If an end-of-file condition or read error occurs, +@@ -1023,6 +1115,7 @@ + @comment wchar.h + @comment ISO + @deftypefun wint_t fgetwc (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + This function reads the next wide character from the stream @var{stream} + and returns its value. If an end-of-file condition or read error + occurs, @code{WEOF} is returned instead. +@@ -1031,6 +1124,7 @@ + @comment stdio.h + @comment POSIX + @deftypefun int fgetc_unlocked (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{@mtsrace{:stream}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} + The @code{fgetc_unlocked} function is equivalent to the @code{fgetc} + function except that it does not implicitly lock the stream. + @end deftypefun +@@ -1038,6 +1132,7 @@ + @comment wchar.h + @comment GNU + @deftypefun wint_t fgetwc_unlocked (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{@mtsrace{:stream}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} + The @code{fgetwc_unlocked} function is equivalent to the @code{fgetwc} + function except that it does not implicitly lock the stream. + +@@ -1047,6 +1142,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int getc (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + This is just like @code{fgetc}, except that it is permissible (and + typical) for it to be implemented as a macro that evaluates the + @var{stream} argument more than once. @code{getc} is often highly +@@ -1057,6 +1153,7 @@ + @comment wchar.h + @comment ISO + @deftypefun wint_t getwc (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + This is just like @code{fgetwc}, except that it is permissible for it to + be implemented as a macro that evaluates the @var{stream} argument more + than once. @code{getwc} can be highly optimized, so it is usually the +@@ -1066,6 +1163,7 @@ + @comment stdio.h + @comment POSIX + @deftypefun int getc_unlocked (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{@mtsrace{:stream}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} + The @code{getc_unlocked} function is equivalent to the @code{getc} + function except that it does not implicitly lock the stream. + @end deftypefun +@@ -1073,6 +1171,7 @@ + @comment wchar.h + @comment GNU + @deftypefun wint_t getwc_unlocked (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{@mtsrace{:stream}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} + The @code{getwc_unlocked} function is equivalent to the @code{getwc} + function except that it does not implicitly lock the stream. + +@@ -1082,6 +1181,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int getchar (void) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + The @code{getchar} function is equivalent to @code{getc} with @code{stdin} + as the value of the @var{stream} argument. + @end deftypefun +@@ -1089,6 +1189,7 @@ + @comment wchar.h + @comment ISO + @deftypefun wint_t getwchar (void) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + The @code{getwchar} function is equivalent to @code{getwc} with @code{stdin} + as the value of the @var{stream} argument. + @end deftypefun +@@ -1096,6 +1197,7 @@ + @comment stdio.h + @comment POSIX + @deftypefun int getchar_unlocked (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:stdin}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} + The @code{getchar_unlocked} function is equivalent to the @code{getchar} + function except that it does not implicitly lock the stream. + @end deftypefun +@@ -1103,6 +1205,7 @@ + @comment wchar.h + @comment GNU + @deftypefun wint_t getwchar_unlocked (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:stdin}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} + The @code{getwchar_unlocked} function is equivalent to the @code{getwchar} + function except that it does not implicitly lock the stream. + +@@ -1145,6 +1248,7 @@ + @comment stdio.h + @comment SVID + @deftypefun int getw (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + This function reads a word (that is, an @code{int}) from @var{stream}. + It's provided for compatibility with SVID. We recommend you use + @code{fread} instead (@pxref{Block Input/Output}). Unlike @code{getc}, +@@ -1173,6 +1277,12 @@ + @comment stdio.h + @comment GNU + @deftypefun ssize_t getline (char **@var{lineptr}, size_t *@var{n}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@aculock{} @acucorrupt{} @acsmem{}}} ++@c Besides the usual possibility of getting an inconsistent stream in a ++@c signal handler or leaving it inconsistent in case of cancellation, ++@c the possibility of leaving a dangling pointer upon cancellation ++@c between reallocing the buffer at *lineptr and updating the pointer ++@c brings about another case of @acucorrupt. + This function reads an entire line from @var{stream}, storing the text + (including the newline and a terminating null character) in a buffer + and storing the buffer address in @code{*@var{lineptr}}. +@@ -1188,7 +1298,8 @@ + + If you set @code{*@var{lineptr}} to a null pointer, and @code{*@var{n}} + to zero, before the call, then @code{getline} allocates the initial +-buffer for you by calling @code{malloc}. ++buffer for you by calling @code{malloc}. This buffer remains allocated ++even if @code{getline} encounters errors and is unable to read any bytes. + + In either case, when @code{getline} returns, @code{*@var{lineptr}} is + a @code{char *} which points to the text of the line. +@@ -1208,6 +1319,8 @@ + @comment stdio.h + @comment GNU + @deftypefun ssize_t getdelim (char **@var{lineptr}, size_t *@var{n}, int @var{delimiter}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@aculock{} @acucorrupt{} @acsmem{}}} ++@c See the getline @acucorrupt note. + This function is like @code{getline} except that the character which + tells it to stop reading is not necessarily newline. The argument + @var{delimiter} specifies the delimiter character; @code{getdelim} keeps +@@ -1232,6 +1345,7 @@ + @comment stdio.h + @comment ISO + @deftypefun {char *} fgets (char *@var{s}, int @var{count}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + The @code{fgets} function reads characters from the stream @var{stream} + up to and including a newline character and stores them in the string + @var{s}, adding a null character to mark the end of the string. You +@@ -1255,6 +1369,7 @@ + @comment wchar.h + @comment ISO + @deftypefun {wchar_t *} fgetws (wchar_t *@var{ws}, int @var{count}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + The @code{fgetws} function reads wide characters from the stream + @var{stream} up to and including a newline character and stores them in + the string @var{ws}, adding a null wide character to mark the end of the +@@ -1280,6 +1395,7 @@ + @comment stdio.h + @comment GNU + @deftypefun {char *} fgets_unlocked (char *@var{s}, int @var{count}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{@mtsrace{:stream}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} + The @code{fgets_unlocked} function is equivalent to the @code{fgets} + function except that it does not implicitly lock the stream. + +@@ -1289,6 +1405,7 @@ + @comment wchar.h + @comment GNU + @deftypefun {wchar_t *} fgetws_unlocked (wchar_t *@var{ws}, int @var{count}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{@mtsrace{:stream}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} + The @code{fgetws_unlocked} function is equivalent to the @code{fgetws} + function except that it does not implicitly lock the stream. + +@@ -1298,6 +1415,7 @@ + @comment stdio.h + @comment ISO + @deftypefn {Deprecated function} {char *} gets (char *@var{s}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + The function @code{gets} reads characters from the stream @code{stdin} + up to the next newline character, and stores them in the string @var{s}. + The newline character is discarded (note that this differs from the +@@ -1388,6 +1506,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int ungetc (int @var{c}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + The @code{ungetc} function pushes back the character @var{c} onto the + input stream @var{stream}. So the next input from @var{stream} will + read @var{c} before anything else. +@@ -1425,6 +1544,7 @@ + @comment wchar.h + @comment ISO + @deftypefun wint_t ungetwc (wint_t @var{wc}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + The @code{ungetwc} function behaves just like @code{ungetc} just that it + pushes back a wide character. + @end deftypefun +@@ -1483,6 +1603,7 @@ + @comment stdio.h + @comment ISO + @deftypefun size_t fread (void *@var{data}, size_t @var{size}, size_t @var{count}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + This function reads up to @var{count} objects of size @var{size} into + the array @var{data}, from the stream @var{stream}. It returns the + number of objects actually read, which might be less than @var{count} if +@@ -1498,6 +1619,7 @@ + @comment stdio.h + @comment GNU + @deftypefun size_t fread_unlocked (void *@var{data}, size_t @var{size}, size_t @var{count}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{@mtsrace{:stream}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} + The @code{fread_unlocked} function is equivalent to the @code{fread} + function except that it does not implicitly lock the stream. + +@@ -1507,6 +1629,7 @@ + @comment stdio.h + @comment ISO + @deftypefun size_t fwrite (const void *@var{data}, size_t @var{size}, size_t @var{count}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + This function writes up to @var{count} objects of size @var{size} from + the array @var{data}, to the stream @var{stream}. The return value is + normally @var{count}, if the call succeeds. Any other value indicates +@@ -1516,6 +1639,7 @@ + @comment stdio.h + @comment GNU + @deftypefun size_t fwrite_unlocked (const void *@var{data}, size_t @var{size}, size_t @var{count}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{@mtsrace{:stream}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} + The @code{fwrite_unlocked} function is equivalent to the @code{fwrite} + function except that it does not implicitly lock the stream. + +@@ -1670,7 +1794,7 @@ + + @defvr Macro NL_ARGMAX + The value of @code{NL_ARGMAX} is the maximum value allowed for the +-specification of an positional parameter in a @code{printf} call. The ++specification of a positional parameter in a @code{printf} call. The + actual value in effect at runtime can be retrieved by using + @code{sysconf} using the @code{_SC_NL_ARGMAX} parameter @pxref{Sysconf + Definition}. +@@ -2257,6 +2381,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int printf (const char *@var{template}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}} + The @code{printf} function prints the optional arguments under the + control of the template string @var{template} to the stream + @code{stdout}. It returns the number of characters printed, or a +@@ -2266,6 +2391,7 @@ + @comment wchar.h + @comment ISO + @deftypefun int wprintf (const wchar_t *@var{template}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}} + The @code{wprintf} function prints the optional arguments under the + control of the wide template string @var{template} to the stream + @code{stdout}. It returns the number of wide characters printed, or a +@@ -2275,6 +2401,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int fprintf (FILE *@var{stream}, const char *@var{template}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}} + This function is just like @code{printf}, except that the output is + written to the stream @var{stream} instead of @code{stdout}. + @end deftypefun +@@ -2282,6 +2409,7 @@ + @comment wchar.h + @comment ISO + @deftypefun int fwprintf (FILE *@var{stream}, const wchar_t *@var{template}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}} + This function is just like @code{wprintf}, except that the output is + written to the stream @var{stream} instead of @code{stdout}. + @end deftypefun +@@ -2289,6 +2417,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int sprintf (char *@var{s}, const char *@var{template}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + This is like @code{printf}, except that the output is stored in the character + array @var{s} instead of written to a stream. A null character is written + to mark the end of the string. +@@ -2313,6 +2442,7 @@ + @comment wchar.h + @comment GNU + @deftypefun int swprintf (wchar_t *@var{s}, size_t @var{size}, const wchar_t *@var{template}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + This is like @code{wprintf}, except that the output is stored in the + wide character array @var{ws} instead of written to a stream. A null + wide character is written to mark the end of the string. The @var{size} +@@ -2330,13 +2460,14 @@ + parameters. @code{swprintf} in fact corresponds to the @code{snprintf} + function. Since the @code{sprintf} function can be dangerous and should + be avoided the @w{ISO C} committee refused to make the same mistake +-again and decided to not define an function exactly corresponding to ++again and decided to not define a function exactly corresponding to + @code{sprintf}. + @end deftypefun + + @comment stdio.h + @comment GNU + @deftypefun int snprintf (char *@var{s}, size_t @var{size}, const char *@var{template}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + The @code{snprintf} function is similar to @code{sprintf}, except that + the @var{size} argument specifies the maximum number of characters to + produce. The trailing null character is counted towards this limit, so +@@ -2407,6 +2538,7 @@ + @comment stdio.h + @comment GNU + @deftypefun int asprintf (char **@var{ptr}, const char *@var{template}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + This function is similar to @code{sprintf}, except that it dynamically + allocates a string (as with @code{malloc}; @pxref{Unconstrained + Allocation}) to hold the output, instead of putting the output in a +@@ -2416,7 +2548,7 @@ + location. + + The return value is the number of characters allocated for the buffer, or +-less than zero if an error occurred. Usually this means that the buffer ++less than zero if an error occurred. Usually this means that the buffer + could not be allocated. + + Here is how to use @code{asprintf} to get the same result as the +@@ -2439,6 +2571,7 @@ + @comment stdio.h + @comment GNU + @deftypefun int obstack_printf (struct obstack *@var{obstack}, const char *@var{template}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtsrace{:obstack} @mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{}}} + This function is similar to @code{asprintf}, except that it uses the + obstack @var{obstack} to allocate the space. @xref{Obstacks}. + +@@ -2509,6 +2642,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int vprintf (const char *@var{template}, va_list @var{ap}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}} + This function is similar to @code{printf} except that, instead of taking + a variable number of arguments directly, it takes an argument list + pointer @var{ap}. +@@ -2517,6 +2651,7 @@ + @comment wchar.h + @comment ISO + @deftypefun int vwprintf (const wchar_t *@var{template}, va_list @var{ap}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}} + This function is similar to @code{wprintf} except that, instead of taking + a variable number of arguments directly, it takes an argument list + pointer @var{ap}. +@@ -2525,6 +2660,48 @@ + @comment stdio.h + @comment ISO + @deftypefun int vfprintf (FILE *@var{stream}, const char *@var{template}, va_list @var{ap}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}} ++@c Although vfprintf sets up a cleanup region to release the lock on the ++@c output stream, it doesn't use it to release args_value or string in ++@c case of cancellation. This doesn't make it unsafe, but cancelling it ++@c may leak memory. The unguarded use of __printf_function_table is ++@c also of concern for all callers. ++@c _itoa ok ++@c _udiv_qrnnd_preinv ok ++@c group_number ok ++@c _i18n_number_rewrite ++@c __wctrans ok ++@c __towctrans @mtslocale ++@c __wcrtomb ok? dup below ++@c outdigit_value ok ++@c outdigitwc_value ok ++@c outchar ok ++@c outstring ok ++@c PAD ok ++@c __printf_fp @mtslocale @ascuheap @acsmem ++@c __printf_fphex @mtslocale ++@c __readonly_area ++@c [GNU/Linux] fopen, strtoul, free ++@c __strerror_r ok if no translation, check otherwise ++@c __btowc ? gconv-modules ++@c __wcrtomb ok (not using internal state) gconv-modules ++@c ARGCHECK ++@c UNBUFFERED_P (tested before taking the stream lock) ++@c buffered_vfprintf ok ++@c __find_spec(wc|mb) ++@c read_int ++@c __libc_use_alloca ++@c process_arg ++@c process_string_arg ++@c extend_alloca ++@c __parse_one_spec(wc|mb) ++@c *__printf_arginfo_table unguarded ++@c __printf_va_arg_table-> unguarded ++@c *__printf_function_table unguarded ++@c done_add ++@c printf_unknown ++@c outchar ++@c _itoa_word + This is the equivalent of @code{fprintf} with the variable argument list + specified directly as for @code{vprintf}. + @end deftypefun +@@ -2532,6 +2709,7 @@ + @comment wchar.h + @comment ISO + @deftypefun int vfwprintf (FILE *@var{stream}, const wchar_t *@var{template}, va_list @var{ap}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}} + This is the equivalent of @code{fwprintf} with the variable argument list + specified directly as for @code{vwprintf}. + @end deftypefun +@@ -2539,6 +2717,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int vsprintf (char *@var{s}, const char *@var{template}, va_list @var{ap}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + This is the equivalent of @code{sprintf} with the variable argument list + specified directly as for @code{vprintf}. + @end deftypefun +@@ -2546,6 +2725,7 @@ + @comment wchar.h + @comment GNU + @deftypefun int vswprintf (wchar_t *@var{s}, size_t @var{size}, const wchar_t *@var{template}, va_list @var{ap}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + This is the equivalent of @code{swprintf} with the variable argument list + specified directly as for @code{vwprintf}. + @end deftypefun +@@ -2553,6 +2733,7 @@ + @comment stdio.h + @comment GNU + @deftypefun int vsnprintf (char *@var{s}, size_t @var{size}, const char *@var{template}, va_list @var{ap}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + This is the equivalent of @code{snprintf} with the variable argument list + specified directly as for @code{vprintf}. + @end deftypefun +@@ -2560,6 +2741,7 @@ + @comment stdio.h + @comment GNU + @deftypefun int vasprintf (char **@var{ptr}, const char *@var{template}, va_list @var{ap}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + The @code{vasprintf} function is the equivalent of @code{asprintf} with the + variable argument list specified directly as for @code{vprintf}. + @end deftypefun +@@ -2567,6 +2749,10 @@ + @comment stdio.h + @comment GNU + @deftypefun int obstack_vprintf (struct obstack *@var{obstack}, const char *@var{template}, va_list @var{ap}) ++@safety{@prelim{}@mtsafe{@mtsrace{:obstack} @mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{}}} ++@c The obstack is not guarded by mutexes, it might be at an inconsistent ++@c state within a signal handler, and it could be left at an ++@c inconsistent state in case of cancellation. + The @code{obstack_vprintf} function is the equivalent of + @code{obstack_printf} with the variable argument list specified directly + as for @code{vprintf}.@refill +@@ -2639,6 +2825,7 @@ + @comment printf.h + @comment GNU + @deftypefun size_t parse_printf_format (const char *@var{template}, size_t @var{n}, int *@var{argtypes}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + This function returns information about the number and types of + arguments expected by the @code{printf} template string @var{template}. + The information is stored in the array @var{argtypes}; each element of +@@ -2879,6 +3066,12 @@ + @comment printf.h + @comment GNU + @deftypefun int register_printf_function (int @var{spec}, printf_function @var{handler-function}, printf_arginfo_function @var{arginfo-function}) ++@safety{@prelim{}@mtunsafe{@mtasuconst{:printfext}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@acsmem{} @aculock{}}} ++@c This function is guarded by the global non-recursive libc lock, but ++@c users of the variables it sets aren't, and those should be MT-Safe, ++@c so we're ruling out the use of this extension with threads. Calling ++@c it from a signal handler may self-deadlock, and cancellation may ++@c leave the lock held, besides leaking allocated memory. + This function defines the conversion specifier character @var{spec}. + Thus, if @var{spec} is @code{'Y'}, it defines the conversion @samp{%Y}. + You can redefine the built-in conversions like @samp{%s}, but flag +@@ -3125,6 +3318,12 @@ + @comment printf.h + @comment GNU + @deftypefun int printf_size (FILE *@var{fp}, const struct printf_info *@var{info}, const void *const *@var{args}) ++@safety{@prelim{}@mtsafe{@mtsrace{:fp} @mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acsmem{} @acucorrupt{}}} ++@c This is meant to be called by vfprintf, that should hold the lock on ++@c the stream, but if this function is called directly, output will be ++@c racy, besides the uses of the global locale object while other ++@c threads may be changing it and the possbility of leaving the stream ++@c object in an inconsistent state in case of cancellation. + Print a given floating point number as for the format @code{%f} except + that there is a postfix character indicating the divisor for the + number to make this less than 1000. There are two possible divisors: +@@ -3183,6 +3382,7 @@ + @comment printf.h + @comment GNU + @deftypefun int printf_size_info (const struct printf_info *@var{info}, size_t @var{n}, int *@var{argtypes}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function will return in @var{argtypes} the information about the + used parameters in the way the @code{vfprintf} implementation expects + it. The format always takes one argument. +@@ -3672,7 +3872,7 @@ + To read in characters that belong to an arbitrary set of your choice, + use the @samp{%[} conversion. You specify the set between the @samp{[} + character and a following @samp{]} character, using the same syntax used +-in regular expressions. As special cases: ++in regular expressions for explicit sets of characters. As special cases: + + @itemize @bullet + @item +@@ -3692,6 +3892,10 @@ + The @samp{%[} conversion does not skip over initial whitespace + characters. + ++Note that the @dfn{character class} syntax available in character sets ++that appear inside regular expressions (such as @samp{[:alpha:]}) is ++@emph{not} available in the @samp{%[} conversion. ++ + Here are some examples of @samp{%[} conversions and what they mean: + + @table @samp +@@ -3799,6 +4003,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int scanf (const char *@var{template}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}} + The @code{scanf} function reads formatted input from the stream + @code{stdin} under the control of the template string @var{template}. + The optional arguments are pointers to the places which receive the +@@ -3813,6 +4018,7 @@ + @comment wchar.h + @comment ISO + @deftypefun int wscanf (const wchar_t *@var{template}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}} + The @code{wscanf} function reads formatted input from the stream + @code{stdin} under the control of the template string @var{template}. + The optional arguments are pointers to the places which receive the +@@ -3827,6 +4033,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int fscanf (FILE *@var{stream}, const char *@var{template}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}} + This function is just like @code{scanf}, except that the input is read + from the stream @var{stream} instead of @code{stdin}. + @end deftypefun +@@ -3834,6 +4041,7 @@ + @comment wchar.h + @comment ISO + @deftypefun int fwscanf (FILE *@var{stream}, const wchar_t *@var{template}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}} + This function is just like @code{wscanf}, except that the input is read + from the stream @var{stream} instead of @code{stdin}. + @end deftypefun +@@ -3841,6 +4049,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int sscanf (const char *@var{s}, const char *@var{template}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + This is like @code{scanf}, except that the characters are taken from the + null-terminated string @var{s} instead of from a stream. Reaching the + end of the string is treated as an end-of-file condition. +@@ -3853,7 +4062,8 @@ + + @comment wchar.h + @comment ISO +-@deftypefun int swscanf (const wchar_t *@var{ws}, const char *@var{template}, @dots{}) ++@deftypefun int swscanf (const wchar_t *@var{ws}, const wchar_t *@var{template}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + This is like @code{wscanf}, except that the characters are taken from the + null-terminated string @var{ws} instead of from a stream. Reaching the + end of the string is treated as an end-of-file condition. +@@ -3880,6 +4090,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int vscanf (const char *@var{template}, va_list @var{ap}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}} + This function is similar to @code{scanf}, but instead of taking + a variable number of arguments directly, it takes an argument list + pointer @var{ap} of type @code{va_list} (@pxref{Variadic Functions}). +@@ -3888,6 +4099,7 @@ + @comment wchar.h + @comment ISO + @deftypefun int vwscanf (const wchar_t *@var{template}, va_list @var{ap}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}} + This function is similar to @code{wscanf}, but instead of taking + a variable number of arguments directly, it takes an argument list + pointer @var{ap} of type @code{va_list} (@pxref{Variadic Functions}). +@@ -3896,6 +4108,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int vfscanf (FILE *@var{stream}, const char *@var{template}, va_list @var{ap}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}} + This is the equivalent of @code{fscanf} with the variable argument list + specified directly as for @code{vscanf}. + @end deftypefun +@@ -3903,6 +4116,7 @@ + @comment wchar.h + @comment ISO + @deftypefun int vfwscanf (FILE *@var{stream}, const wchar_t *@var{template}, va_list @var{ap}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}} + This is the equivalent of @code{fwscanf} with the variable argument list + specified directly as for @code{vwscanf}. + @end deftypefun +@@ -3910,6 +4124,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int vsscanf (const char *@var{s}, const char *@var{template}, va_list @var{ap}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + This is the equivalent of @code{sscanf} with the variable argument list + specified directly as for @code{vscanf}. + @end deftypefun +@@ -3917,6 +4132,7 @@ + @comment wchar.h + @comment ISO + @deftypefun int vswscanf (const wchar_t *@var{s}, const wchar_t *@var{template}, va_list @var{ap}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + This is the equivalent of @code{swscanf} with the variable argument list + specified directly as for @code{vwscanf}. + @end deftypefun +@@ -3966,6 +4182,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int feof (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@aculock{}}} + The @code{feof} function returns nonzero if and only if the end-of-file + indicator for the stream @var{stream} is set. + +@@ -3975,6 +4192,9 @@ + @comment stdio.h + @comment GNU + @deftypefun int feof_unlocked (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c There isn't much of a thread unsafety risk in reading a flag word and ++@c testing a bit in it. + The @code{feof_unlocked} function is equivalent to the @code{feof} + function except that it does not implicitly lock the stream. + +@@ -3986,6 +4206,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int ferror (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@aculock{}}} + The @code{ferror} function returns nonzero if and only if the error + indicator for the stream @var{stream} is set, indicating that an error + has occurred on a previous operation on the stream. +@@ -3996,6 +4217,7 @@ + @comment stdio.h + @comment GNU + @deftypefun int ferror_unlocked (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{ferror_unlocked} function is equivalent to the @code{ferror} + function except that it does not implicitly lock the stream. + +@@ -4023,6 +4245,7 @@ + @comment stdio.h + @comment ISO + @deftypefun void clearerr (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@aculock{}}} + This function clears the end-of-file and error indicators for the + stream @var{stream}. + +@@ -4033,6 +4256,7 @@ + @comment stdio.h + @comment GNU + @deftypefun void clearerr_unlocked (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{@mtsrace{:stream}}@assafe{}@acsafe{}} + The @code{clearerr_unlocked} function is equivalent to the @code{clearerr} + function except that it does not implicitly lock the stream. + +@@ -4146,6 +4370,7 @@ + @comment stdio.h + @comment ISO + @deftypefun {long int} ftell (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + This function returns the current file position of the stream + @var{stream}. + +@@ -4158,6 +4383,7 @@ + @comment stdio.h + @comment Unix98 + @deftypefun off_t ftello (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + The @code{ftello} function is similar to @code{ftell}, except that it + returns a value of type @code{off_t}. Systems which support this type + use it to describe all file positions, unlike the POSIX specification +@@ -4181,6 +4407,7 @@ + @comment stdio.h + @comment Unix98 + @deftypefun off64_t ftello64 (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + This function is similar to @code{ftello} with the only difference that + the return value is of type @code{off64_t}. This also requires that the + stream @var{stream} was opened using either @code{fopen64}, +@@ -4196,6 +4423,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int fseek (FILE *@var{stream}, long int @var{offset}, int @var{whence}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + The @code{fseek} function is used to change the file position of the + stream @var{stream}. The value of @var{whence} must be one of the + constants @code{SEEK_SET}, @code{SEEK_CUR}, or @code{SEEK_END}, to +@@ -4215,6 +4443,7 @@ + @comment stdio.h + @comment Unix98 + @deftypefun int fseeko (FILE *@var{stream}, off_t @var{offset}, int @var{whence}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + This function is similar to @code{fseek} but it corrects a problem with + @code{fseek} in a system with POSIX types. Using a value of type + @code{long int} for the offset is not compatible with POSIX. +@@ -4238,6 +4467,7 @@ + @comment stdio.h + @comment Unix98 + @deftypefun int fseeko64 (FILE *@var{stream}, off64_t @var{offset}, int @var{whence}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + This function is similar to @code{fseeko} with the only difference that + the @var{offset} parameter is of type @code{off64_t}. This also + requires that the stream @var{stream} was opened using either +@@ -4286,6 +4516,7 @@ + @comment stdio.h + @comment ISO + @deftypefun void rewind (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + The @code{rewind} function positions the stream @var{stream} at the + beginning of the file. It is equivalent to calling @code{fseek} or + @code{fseeko} on the @var{stream} with an @var{offset} argument of +@@ -4407,6 +4638,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int fgetpos (FILE *@var{stream}, fpos_t *@var{position}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + This function stores the value of the file position indicator for the + stream @var{stream} in the @code{fpos_t} object pointed to by + @var{position}. If successful, @code{fgetpos} returns zero; otherwise +@@ -4421,6 +4653,7 @@ + @comment stdio.h + @comment Unix98 + @deftypefun int fgetpos64 (FILE *@var{stream}, fpos64_t *@var{position}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + This function is similar to @code{fgetpos} but the file position is + returned in a variable of type @code{fpos64_t} to which @var{position} + points. +@@ -4433,6 +4666,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int fsetpos (FILE *@var{stream}, const fpos_t *@var{position}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + This function sets the file position indicator for the stream @var{stream} + to the position @var{position}, which must have been set by a previous + call to @code{fgetpos} on the same stream. If successful, @code{fsetpos} +@@ -4449,6 +4683,7 @@ + @comment stdio.h + @comment Unix98 + @deftypefun int fsetpos64 (FILE *@var{stream}, const fpos64_t *@var{position}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + This function is similar to @code{fsetpos} but the file position used + for positioning is provided in a variable of type @code{fpos64_t} to + which @var{position} points. +@@ -4560,6 +4795,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int fflush (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + This function causes any buffered output on @var{stream} to be delivered + to the file. If @var{stream} is a null pointer, then + @code{fflush} causes buffered output on @emph{all} open output streams +@@ -4572,6 +4808,7 @@ + @comment stdio.h + @comment POSIX + @deftypefun int fflush_unlocked (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{@mtsrace{:stream}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} + The @code{fflush_unlocked} function is equivalent to the @code{fflush} + function except that it does not implicitly lock the stream. + @end deftypefun +@@ -4588,6 +4825,7 @@ + @comment stdio_ext.h + @comment GNU + @deftypefun void _flushlbf (void) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + The @code{_flushlbf} function flushes all line buffered streams + currently opened. + +@@ -4609,6 +4847,7 @@ + @comment stdio_ext.h + @comment GNU + @deftypefun void __fpurge (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{@mtsrace{:stream}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} + The @code{__fpurge} function causes the buffer of the stream + @var{stream} to be emptied. If the stream is currently in read mode all + input in the buffer is lost. If the stream is in output mode the +@@ -4633,6 +4872,7 @@ + @comment stdio.h + @comment ISO + @deftypefun int setvbuf (FILE *@var{stream}, char *@var{buf}, int @var{mode}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + This function is used to specify that the stream @var{stream} should + have the buffering mode @var{mode}, which can be either @code{_IOFBF} + (for full buffering), @code{_IOLBF} (for line buffering), or +@@ -4710,6 +4950,7 @@ + @comment stdio.h + @comment ISO + @deftypefun void setbuf (FILE *@var{stream}, char *@var{buf}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + If @var{buf} is a null pointer, the effect of this function is + equivalent to calling @code{setvbuf} with a @var{mode} argument of + @code{_IONBF}. Otherwise, it is equivalent to calling @code{setvbuf} +@@ -4723,6 +4964,7 @@ + @comment stdio.h + @comment BSD + @deftypefun void setbuffer (FILE *@var{stream}, char *@var{buf}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + If @var{buf} is a null pointer, this function makes @var{stream} unbuffered. + Otherwise, it makes @var{stream} fully buffered using @var{buf} as the + buffer. The @var{size} argument specifies the length of @var{buf}. +@@ -4734,6 +4976,7 @@ + @comment stdio.h + @comment BSD + @deftypefun void setlinebuf (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} + This function makes @var{stream} be line buffered, and allocates the + buffer for you. + +@@ -4748,6 +4991,7 @@ + @comment stdio_ext.h + @comment GNU + @deftypefun int __flbf (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{__flbf} function will return a nonzero value in case the + stream @var{stream} is line buffered. Otherwise the return value is + zero. +@@ -4761,6 +5005,7 @@ + @comment stdio_ext.h + @comment GNU + @deftypefun size_t __fbufsize (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{@mtsrace{:stream}}@asunsafe{@asucorrupt{}}@acsafe{}} + The @code{__fbufsize} function return the size of the buffer in the + stream @var{stream}. This value can be used to optimize the use of the + stream. +@@ -4771,6 +5016,7 @@ + @comment stdio_ext.h + @comment GNU + @deftypefun size_t __fpending (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{@mtsrace{:stream}}@asunsafe{@asucorrupt{}}@acsafe{}} + The @code{__fpending} + function returns the number of bytes currently in the output buffer. + For wide-oriented stream the measuring unit is wide characters. This +@@ -4818,6 +5064,10 @@ + @comment stdio.h + @comment GNU + @deftypefun {FILE *} fmemopen (void *@var{buf}, size_t @var{size}, const char *@var{opentype}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@acsmem{} @aculock{}}} ++@c Unlike open_memstream, fmemopen does (indirectly) call _IO_link_in, ++@c bringing with it additional potential for async trouble with ++@c list_all_lock. + This function opens a stream that allows the access specified by the + @var{opentype} argument, that reads from or writes to the buffer specified + by the argument @var{buf}. This array must be at least @var{size} bytes long. +@@ -4870,6 +5120,7 @@ + @comment stdio.h + @comment GNU + @deftypefun {FILE *} open_memstream (char **@var{ptr}, size_t *@var{sizeloc}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + This function opens a stream for writing to a buffer. The buffer is + allocated dynamically and grown as necessary, using @code{malloc}. + After you've closed the stream, this buffer is your responsibility to +@@ -4985,6 +5236,7 @@ + @comment stdio.h + @comment GNU + @deftypefun {FILE *} fopencookie (void *@var{cookie}, const char *@var{opentype}, cookie_io_functions_t @var{io-functions}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@acsmem{} @aculock{}}} + This function actually creates the stream for communicating with the + @var{cookie} using the functions in the @var{io-functions} argument. + The @var{opentype} argument is interpreted as for @code{fopen}; +@@ -5053,26 +5305,26 @@ + + @comment stdio.h + @comment GNU +-@deftp {Data Type} cookie_read_function ++@deftp {Data Type} cookie_read_function_t + This is the data type that the read function for a custom stream should have. + If you declare the function as shown above, this is the type it will have. + @end deftp + + @comment stdio.h + @comment GNU +-@deftp {Data Type} cookie_write_function ++@deftp {Data Type} cookie_write_function_t + The data type of the write function for a custom stream. + @end deftp + + @comment stdio.h + @comment GNU +-@deftp {Data Type} cookie_seek_function ++@deftp {Data Type} cookie_seek_function_t + The data type of the seek function for a custom stream. + @end deftp + + @comment stdio.h + @comment GNU +-@deftp {Data Type} cookie_close_function ++@deftp {Data Type} cookie_close_function_t + The data type of the close function for a custom stream. + @end deftp + +@@ -5166,6 +5418,7 @@ + @comment fmtmsg.h + @comment XPG + @deftypefun int fmtmsg (long int @var{classification}, const char *@var{label}, int @var{severity}, const char *@var{text}, const char *@var{action}, const char *@var{tag}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acsafe{}} + Display a message described by its parameters on the device(s) specified + in the @var{classification} parameter. The @var{label} parameter + identifies the source of the message. The string should consist of two +@@ -5306,6 +5559,7 @@ + but this is toilsome. + + @deftypefun int addseverity (int @var{severity}, const char *@var{string}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsmem{}}} + This function allows the introduction of new severity classes which can be + addressed by the @var{severity} parameter of the @code{fmtmsg} function. + The @var{severity} parameter of @code{addseverity} must match the value +diff -urN glibc-2.17-c758a686/manual/string.texi glibc-2.17-c758a686/manual/string.texi +--- glibc-2.17-c758a686/manual/string.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/string.texi 2014-09-12 16:10:06.045792717 -0400 +@@ -200,7 +200,7 @@ + @cindex parameter promotion + Some of the memory and string functions take single characters as + arguments. Since a value of type @code{char} is automatically promoted +-into an value of type @code{int} when used as a parameter, the functions ++into a value of type @code{int} when used as a parameter, the functions + are declared with @code{int} as the type of the parameter in question. + In case of the wide character function the situation is similarly: the + parameter type for a single wide character is @code{wint_t} and not +@@ -219,6 +219,7 @@ + @comment string.h + @comment ISO + @deftypefun size_t strlen (const char *@var{s}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{strlen} function returns the length of the null-terminated + string @var{s} in bytes. (In other words, it returns the offset of the + terminating null character within the array.) +@@ -285,6 +286,7 @@ + @comment wchar.h + @comment ISO + @deftypefun size_t wcslen (const wchar_t *@var{ws}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{wcslen} function is the wide character equivalent to + @code{strlen}. The return value is the number of wide characters in the + wide character string pointed to by @var{ws} (this is also the offset of +@@ -300,6 +302,7 @@ + @comment string.h + @comment GNU + @deftypefun size_t strnlen (const char *@var{s}, size_t @var{maxlen}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{strnlen} function returns the length of the string @var{s} in + bytes if this length is smaller than @var{maxlen} bytes. Otherwise it + returns @var{maxlen}. Therefore this function is equivalent to +@@ -322,6 +325,7 @@ + @comment wchar.h + @comment GNU + @deftypefun size_t wcsnlen (const wchar_t *@var{ws}, size_t @var{maxlen}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + @code{wcsnlen} is the wide character equivalent to @code{strnlen}. The + @var{maxlen} parameter specifies the maximum number of wide characters. + +@@ -367,6 +371,7 @@ + @comment string.h + @comment ISO + @deftypefun {void *} memcpy (void *restrict @var{to}, const void *restrict @var{from}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{memcpy} function copies @var{size} bytes from the object + beginning at @var{from} into the object beginning at @var{to}. The + behavior of this function is undefined if the two arrays @var{to} and +@@ -388,6 +393,7 @@ + @comment wchar.h + @comment ISO + @deftypefun {wchar_t *} wmemcpy (wchar_t *restrict @var{wto}, const wchar_t *restrict @var{wfrom}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{wmemcpy} function copies @var{size} wide characters from the object + beginning at @var{wfrom} into the object beginning at @var{wto}. The + behavior of this function is undefined if the two arrays @var{wto} and +@@ -413,6 +419,7 @@ + @comment string.h + @comment GNU + @deftypefun {void *} mempcpy (void *restrict @var{to}, const void *restrict @var{from}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{mempcpy} function is nearly identical to the @code{memcpy} + function. It copies @var{size} bytes from the object beginning at + @code{from} into the object pointed to by @var{to}. But instead of +@@ -440,6 +447,7 @@ + @comment wchar.h + @comment GNU + @deftypefun {wchar_t *} wmempcpy (wchar_t *restrict @var{wto}, const wchar_t *restrict @var{wfrom}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{wmempcpy} function is nearly identical to the @code{wmemcpy} + function. It copies @var{size} wide characters from the object + beginning at @code{wfrom} into the object pointed to by @var{wto}. But +@@ -468,6 +476,7 @@ + @comment string.h + @comment ISO + @deftypefun {void *} memmove (void *@var{to}, const void *@var{from}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + @code{memmove} copies the @var{size} bytes at @var{from} into the + @var{size} bytes at @var{to}, even if those two blocks of space + overlap. In the case of overlap, @code{memmove} is careful to copy the +@@ -479,7 +488,8 @@ + + @comment wchar.h + @comment ISO +-@deftypefun {wchar_t *} wmemmove (wchar *@var{wto}, const wchar_t *@var{wfrom}, size_t @var{size}) ++@deftypefun {wchar_t *} wmemmove (wchar_t *@var{wto}, const wchar_t *@var{wfrom}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + @code{wmemmove} copies the @var{size} wide characters at @var{wfrom} + into the @var{size} wide characters at @var{wto}, even if those two + blocks of space overlap. In the case of overlap, @code{memmove} is +@@ -507,6 +517,7 @@ + @comment string.h + @comment SVID + @deftypefun {void *} memccpy (void *restrict @var{to}, const void *restrict @var{from}, int @var{c}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function copies no more than @var{size} bytes from @var{from} to + @var{to}, stopping if a byte matching @var{c} is found. The return + value is a pointer into @var{to} one byte past where @var{c} was copied, +@@ -517,6 +528,7 @@ + @comment string.h + @comment ISO + @deftypefun {void *} memset (void *@var{block}, int @var{c}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function copies the value of @var{c} (converted to an + @code{unsigned char}) into each of the first @var{size} bytes of the + object beginning at @var{block}. It returns the value of @var{block}. +@@ -525,6 +537,7 @@ + @comment wchar.h + @comment ISO + @deftypefun {wchar_t *} wmemset (wchar_t *@var{block}, wchar_t @var{wc}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function copies the value of @var{wc} into each of the first + @var{size} wide characters of the object beginning at @var{block}. It + returns the value of @var{block}. +@@ -533,6 +546,7 @@ + @comment string.h + @comment ISO + @deftypefun {char *} strcpy (char *restrict @var{to}, const char *restrict @var{from}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This copies characters from the string @var{from} (up to and including + the terminating null character) into the string @var{to}. Like + @code{memcpy}, this function has undefined results if the strings +@@ -542,6 +556,7 @@ + @comment wchar.h + @comment ISO + @deftypefun {wchar_t *} wcscpy (wchar_t *restrict @var{wto}, const wchar_t *restrict @var{wfrom}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This copies wide characters from the string @var{wfrom} (up to and + including the terminating null wide character) into the string + @var{wto}. Like @code{wmemcpy}, this function has undefined results if +@@ -551,6 +566,7 @@ + @comment string.h + @comment ISO + @deftypefun {char *} strncpy (char *restrict @var{to}, const char *restrict @var{from}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function is similar to @code{strcpy} but always copies exactly + @var{size} characters into @var{to}. + +@@ -576,6 +592,7 @@ + @comment wchar.h + @comment ISO + @deftypefun {wchar_t *} wcsncpy (wchar_t *restrict @var{wto}, const wchar_t *restrict @var{wfrom}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function is similar to @code{wcscpy} but always copies exactly + @var{size} wide characters into @var{wto}. + +@@ -602,6 +619,7 @@ + @comment string.h + @comment SVID + @deftypefun {char *} strdup (const char *@var{s}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + This function copies the null-terminated string @var{s} into a newly + allocated string. The string is allocated using @code{malloc}; see + @ref{Unconstrained Allocation}. If @code{malloc} cannot allocate space +@@ -612,6 +630,7 @@ + @comment wchar.h + @comment GNU + @deftypefun {wchar_t *} wcsdup (const wchar_t *@var{ws}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + This function copies the null-terminated wide character string @var{ws} + into a newly allocated string. The string is allocated using + @code{malloc}; see @ref{Unconstrained Allocation}. If @code{malloc} +@@ -625,6 +644,7 @@ + @comment string.h + @comment GNU + @deftypefun {char *} strndup (const char *@var{s}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + This function is similar to @code{strdup} but always copies at most + @var{size} characters into the newly allocated string. + +@@ -642,6 +662,7 @@ + @comment string.h + @comment Unknown origin + @deftypefun {char *} stpcpy (char *restrict @var{to}, const char *restrict @var{from}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function is like @code{strcpy}, except that it returns a pointer to + the end of the string @var{to} (that is, the address of the terminating + null character @code{to + strlen (from)}) rather than the beginning. +@@ -664,6 +685,7 @@ + @comment wchar.h + @comment GNU + @deftypefun {wchar_t *} wcpcpy (wchar_t *restrict @var{wto}, const wchar_t *restrict @var{wfrom}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function is like @code{wcscpy}, except that it returns a pointer to + the end of the string @var{wto} (that is, the address of the terminating + null character @code{wto + strlen (wfrom)}) rather than the beginning. +@@ -679,10 +701,11 @@ + @comment string.h + @comment GNU + @deftypefun {char *} stpncpy (char *restrict @var{to}, const char *restrict @var{from}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function is similar to @code{stpcpy} but copies always exactly + @var{size} characters into @var{to}. + +-If the length of @var{from} is more then @var{size}, then @code{stpncpy} ++If the length of @var{from} is more than @var{size}, then @code{stpncpy} + copies just the first @var{size} characters and returns a pointer to the + character directly following the one which was copied last. Note that in + this case there is no null terminator written into @var{to}. +@@ -704,10 +727,11 @@ + @comment wchar.h + @comment GNU + @deftypefun {wchar_t *} wcpncpy (wchar_t *restrict @var{wto}, const wchar_t *restrict @var{wfrom}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function is similar to @code{wcpcpy} but copies always exactly + @var{wsize} characters into @var{wto}. + +-If the length of @var{wfrom} is more then @var{size}, then ++If the length of @var{wfrom} is more than @var{size}, then + @code{wcpncpy} copies just the first @var{size} wide characters and + returns a pointer to the wide character directly following the last + non-null wide character which was copied last. Note that in this case +@@ -731,6 +755,7 @@ + @comment string.h + @comment GNU + @deftypefn {Macro} {char *} strdupa (const char *@var{s}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This macro is similar to @code{strdup} but allocates the new string + using @code{alloca} instead of @code{malloc} (@pxref{Variable Size + Automatic}). This means of course the returned string has the same +@@ -757,6 +782,7 @@ + @comment string.h + @comment GNU + @deftypefn {Macro} {char *} strndupa (const char *@var{s}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function is similar to @code{strndup} but like @code{strdupa} it + allocates the new string using @code{alloca} + @pxref{Variable Size Automatic}. The same advantages and limitations +@@ -772,6 +798,7 @@ + @comment string.h + @comment ISO + @deftypefun {char *} strcat (char *restrict @var{to}, const char *restrict @var{from}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{strcat} function is similar to @code{strcpy}, except that the + characters from @var{from} are concatenated or appended to the end of + @var{to}, instead of overwriting it. That is, the first character from +@@ -794,6 +821,7 @@ + @comment wchar.h + @comment ISO + @deftypefun {wchar_t *} wcscat (wchar_t *restrict @var{wto}, const wchar_t *restrict @var{wfrom}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{wcscat} function is similar to @code{wcscpy}, except that the + characters from @var{wfrom} are concatenated or appended to the end of + @var{wto}, instead of overwriting it. That is, the first character from +@@ -942,6 +970,7 @@ + @comment string.h + @comment ISO + @deftypefun {char *} strncat (char *restrict @var{to}, const char *restrict @var{from}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function is like @code{strcat} except that not more than @var{size} + characters from @var{from} are appended to the end of @var{to}. A + single null character is also always appended to @var{to}, so the total +@@ -955,8 +984,8 @@ + char * + strncat (char *to, const char *from, size_t size) + @{ +- to[strlen (to) + size] = '\0'; +- strncpy (to + strlen (to), from, size); ++ memcpy (to + strlen (to), from, strnlen (from, size)); ++ to[strlen (to) + strnlen (from, size)] = '\0'; + return to; + @} + @end group +@@ -968,6 +997,7 @@ + @comment wchar.h + @comment ISO + @deftypefun {wchar_t *} wcsncat (wchar_t *restrict @var{wto}, const wchar_t *restrict @var{wfrom}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function is like @code{wcscat} except that not more than @var{size} + characters from @var{from} are appended to the end of @var{to}. A + single null character is also always appended to @var{to}, so the total +@@ -982,8 +1012,8 @@ + wcsncat (wchar_t *restrict wto, const wchar_t *restrict wfrom, + size_t size) + @{ +- wto[wcslen (to) + size] = L'\0'; +- wcsncpy (wto + wcslen (wto), wfrom, size); ++ memcpy (wto + wcslen (wto), wfrom, wcsnlen (wfrom, size) * sizeof (wchar_t)); ++ wto[wcslen (to) + wcsnlen (wfrom, size)] = '\0'; + return wto; + @} + @end group +@@ -1012,6 +1042,7 @@ + @comment string.h + @comment BSD + @deftypefun void bcopy (const void *@var{from}, void *@var{to}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This is a partially obsolete alternative for @code{memmove}, derived from + BSD. Note that it is not quite equivalent to @code{memmove}, because the + arguments are not in the same order and there is no return value. +@@ -1020,6 +1051,7 @@ + @comment string.h + @comment BSD + @deftypefun void bzero (void *@var{block}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This is a partially obsolete alternative for @code{memset}, derived from + BSD. Note that it is not as general as @code{memset}, because the only + value it can store is zero. +@@ -1055,6 +1087,7 @@ + @comment string.h + @comment ISO + @deftypefun int memcmp (const void *@var{a1}, const void *@var{a2}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The function @code{memcmp} compares the @var{size} bytes of memory + beginning at @var{a1} against the @var{size} bytes of memory beginning + at @var{a2}. The value returned has the same sign as the difference +@@ -1065,9 +1098,10 @@ + @code{0}. + @end deftypefun + +-@comment wcjar.h ++@comment wchar.h + @comment ISO + @deftypefun int wmemcmp (const wchar_t *@var{a1}, const wchar_t *@var{a2}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The function @code{wmemcmp} compares the @var{size} wide characters + beginning at @var{a1} against the @var{size} wide characters beginning + at @var{a2}. The value returned is smaller than or larger than zero +@@ -1120,6 +1154,7 @@ + @comment string.h + @comment ISO + @deftypefun int strcmp (const char *@var{s1}, const char *@var{s2}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{strcmp} function compares the string @var{s1} against + @var{s2}, returning a value that has the same sign as the difference + between the first differing pair of characters (interpreted as +@@ -1139,6 +1174,7 @@ + @comment wchar.h + @comment ISO + @deftypefun int wcscmp (const wchar_t *@var{ws1}, const wchar_t *@var{ws2}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + + The @code{wcscmp} function compares the wide character string @var{ws1} + against @var{ws2}. The value returned is smaller than or larger than zero +@@ -1159,6 +1195,11 @@ + @comment string.h + @comment BSD + @deftypefun int strcasecmp (const char *@var{s1}, const char *@var{s2}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} ++@c Although this calls tolower multiple times, it's a macro, and ++@c strcasecmp is optimized so that the locale pointer is read only once. ++@c There are some asm implementations too, for which the single-read ++@c from locale TLS pointers also applies. + This function is like @code{strcmp}, except that differences in case are + ignored. How uppercase and lowercase characters are related is + determined by the currently selected locale. In the standard @code{"C"} +@@ -1171,7 +1212,10 @@ + + @comment wchar.h + @comment GNU +-@deftypefun int wcscasecmp (const wchar_t *@var{ws1}, const wchar_T *@var{ws2}) ++@deftypefun int wcscasecmp (const wchar_t *@var{ws1}, const wchar_t *@var{ws2}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} ++@c Since towlower is not a macro, the locale object may be read multiple ++@c times. + This function is like @code{wcscmp}, except that differences in case are + ignored. How uppercase and lowercase characters are related is + determined by the currently selected locale. In the standard @code{"C"} +@@ -1185,6 +1229,7 @@ + @comment string.h + @comment ISO + @deftypefun int strncmp (const char *@var{s1}, const char *@var{s2}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function is the similar to @code{strcmp}, except that no more than + @var{size} characters are compared. In other words, if the two + strings are the same in their first @var{size} characters, the +@@ -1194,6 +1239,7 @@ + @comment wchar.h + @comment ISO + @deftypefun int wcsncmp (const wchar_t *@var{ws1}, const wchar_t *@var{ws2}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function is the similar to @code{wcscmp}, except that no more than + @var{size} wide characters are compared. In other words, if the two + strings are the same in their first @var{size} wide characters, the +@@ -1203,6 +1249,7 @@ + @comment string.h + @comment BSD + @deftypefun int strncasecmp (const char *@var{s1}, const char *@var{s2}, size_t @var{n}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + This function is like @code{strncmp}, except that differences in case + are ignored. Like @code{strcasecmp}, it is locale dependent how + uppercase and lowercase characters are related. +@@ -1214,6 +1261,7 @@ + @comment wchar.h + @comment GNU + @deftypefun int wcsncasecmp (const wchar_t *@var{ws1}, const wchar_t *@var{s2}, size_t @var{n}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} + This function is like @code{wcsncmp}, except that differences in case + are ignored. Like @code{wcscasecmp}, it is locale dependent how + uppercase and lowercase characters are related. +@@ -1247,6 +1295,8 @@ + @comment string.h + @comment GNU + @deftypefun int strverscmp (const char *@var{s1}, const char *@var{s2}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} ++@c Calls isdigit multiple times, locale may change in between. + The @code{strverscmp} function compares the string @var{s1} against + @var{s2}, considering them as holding indices/version numbers. The + return value follows the same conventions as found in the +@@ -1258,7 +1308,7 @@ + mode, where each sequence of digits is taken as a whole. If we reach the + end of these two parts without noticing a difference, we return to the + standard comparison mode. There are two types of numeric parts: +-"integral" and "fractional" (those begin with a '0'). The types ++"integral" and "fractional" (those begin with a '0'). The types + of the numeric parts affect the way we sort them: + + @itemize @bullet +@@ -1297,6 +1347,7 @@ + @comment string.h + @comment BSD + @deftypefun int bcmp (const void *@var{a1}, const void *@var{a2}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This is an obsolete alias for @code{memcmp}, derived from BSD. + @end deftypefun + +@@ -1343,6 +1394,9 @@ + @comment string.h + @comment ISO + @deftypefun int strcoll (const char *@var{s1}, const char *@var{s2}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} ++@c Calls strcoll_l with the current locale, which dereferences only the ++@c LC_COLLATE data pointer. + The @code{strcoll} function is similar to @code{strcmp} but uses the + collating sequence of the current locale for collation (the + @code{LC_COLLATE} locale). +@@ -1351,6 +1405,8 @@ + @comment wchar.h + @comment ISO + @deftypefun int wcscoll (const wchar_t *@var{ws1}, const wchar_t *@var{ws2}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} ++@c Same as strcoll, but calling wcscoll_l. + The @code{wcscoll} function is similar to @code{wcscmp} but uses the + collating sequence of the current locale for collation (the + @code{LC_COLLATE} locale). +@@ -1370,7 +1426,7 @@ + compare_elements (const void *v1, const void *v2) + @{ + char * const *p1 = v1; +- char * const *p1 = v2; ++ char * const *p2 = v2; + + return strcoll (*p1, *p2); + @} +@@ -1391,6 +1447,7 @@ + @comment string.h + @comment ISO + @deftypefun size_t strxfrm (char *restrict @var{to}, const char *restrict @var{from}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + The function @code{strxfrm} transforms the string @var{from} using the + collation transformation determined by the locale currently selected for + collation, and stores the transformed string in the array @var{to}. Up +@@ -1420,6 +1477,7 @@ + @comment wchar.h + @comment ISO + @deftypefun size_t wcsxfrm (wchar_t *restrict @var{wto}, const wchar_t *@var{wfrom}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + The function @code{wcsxfrm} transforms wide character string @var{wfrom} + using the collation transformation determined by the locale currently + selected for collation, and stores the transformed string in the array +@@ -1514,8 +1572,8 @@ + @} + + /* @r{Sort @code{temp_array} by comparing transformed strings.} */ +- qsort (temp_array, sizeof (struct sorter), +- nstrings, compare_elements); ++ qsort (temp_array, nstrings, ++ sizeof (struct sorter), compare_elements); + + /* @r{Put the elements back in the permanent array} + @r{in their sorted order.} */ +@@ -1579,6 +1637,7 @@ + @comment string.h + @comment ISO + @deftypefun {void *} memchr (const void *@var{block}, int @var{c}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function finds the first occurrence of the byte @var{c} (converted + to an @code{unsigned char}) in the initial @var{size} bytes of the + object beginning at @var{block}. The return value is a pointer to the +@@ -1588,6 +1647,7 @@ + @comment wchar.h + @comment ISO + @deftypefun {wchar_t *} wmemchr (const wchar_t *@var{block}, wchar_t @var{wc}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function finds the first occurrence of the wide character @var{wc} + in the initial @var{size} wide characters of the object beginning at + @var{block}. The return value is a pointer to the located wide +@@ -1597,6 +1657,7 @@ + @comment string.h + @comment GNU + @deftypefun {void *} rawmemchr (const void *@var{block}, int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Often the @code{memchr} function is used with the knowledge that the + byte @var{c} is available in the memory block specified by the + parameters. But this means that the @var{size} parameter is not really +@@ -1627,6 +1688,7 @@ + @comment string.h + @comment GNU + @deftypefun {void *} memrchr (const void *@var{block}, int @var{c}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The function @code{memrchr} is like @code{memchr}, except that it searches + backwards from the end of the block defined by @var{block} and @var{size} + (instead of forwards from the front). +@@ -1637,6 +1699,7 @@ + @comment string.h + @comment ISO + @deftypefun {char *} strchr (const char *@var{string}, int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{strchr} function finds the first occurrence of the character + @var{c} (converted to a @code{char}) in the null-terminated string + beginning at @var{string}. The return value is a pointer to the located +@@ -1663,6 +1726,7 @@ + @comment wchar.h + @comment ISO + @deftypefun {wchar_t *} wcschr (const wchar_t *@var{wstring}, int @var{wc}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{wcschr} function finds the first occurrence of the wide + character @var{wc} in the null-terminated wide character string + beginning at @var{wstring}. The return value is a pointer to the +@@ -1678,6 +1742,7 @@ + @comment string.h + @comment GNU + @deftypefun {char *} strchrnul (const char *@var{string}, int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + @code{strchrnul} is the same as @code{strchr} except that if it does + not find the character, it returns a pointer to string's terminating + null character rather than a null pointer. +@@ -1688,6 +1753,7 @@ + @comment wchar.h + @comment GNU + @deftypefun {wchar_t *} wcschrnul (const wchar_t *@var{wstring}, wchar_t @var{wc}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + @code{wcschrnul} is the same as @code{wcschr} except that if it does not + find the wide character, it returns a pointer to wide character string's + terminating null wide character rather than a null pointer. +@@ -1723,6 +1789,7 @@ + @comment string.h + @comment ISO + @deftypefun {char *} strrchr (const char *@var{string}, int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The function @code{strrchr} is like @code{strchr}, except that it searches + backwards from the end of the string @var{string} (instead of forwards + from the front). +@@ -1737,6 +1804,7 @@ + @comment wchar.h + @comment ISO + @deftypefun {wchar_t *} wcsrchr (const wchar_t *@var{wstring}, wchar_t @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The function @code{wcsrchr} is like @code{wcschr}, except that it searches + backwards from the end of the string @var{wstring} (instead of forwards + from the front). +@@ -1745,6 +1813,7 @@ + @comment string.h + @comment ISO + @deftypefun {char *} strstr (const char *@var{haystack}, const char *@var{needle}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This is like @code{strchr}, except that it searches @var{haystack} for a + substring @var{needle} rather than just a single character. It + returns a pointer into the string @var{haystack} that is the first +@@ -1763,6 +1832,7 @@ + @comment wchar.h + @comment ISO + @deftypefun {wchar_t *} wcsstr (const wchar_t *@var{haystack}, const wchar_t *@var{needle}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This is like @code{wcschr}, except that it searches @var{haystack} for a + substring @var{needle} rather than just a single wide character. It + returns a pointer into the string @var{haystack} that is the first wide +@@ -1773,7 +1843,8 @@ + @comment wchar.h + @comment XPG + @deftypefun {wchar_t *} wcswcs (const wchar_t *@var{haystack}, const wchar_t *@var{needle}) +-@code{wcswcs} is an deprecated alias for @code{wcsstr}. This is the ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@code{wcswcs} is a deprecated alias for @code{wcsstr}. This is the + name originally used in the X/Open Portability Guide before the + @w{Amendment 1} to @w{ISO C90} was published. + @end deftypefun +@@ -1782,6 +1853,9 @@ + @comment string.h + @comment GNU + @deftypefun {char *} strcasestr (const char *@var{haystack}, const char *@var{needle}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} ++@c There may be multiple calls of strncasecmp, each accessing the locale ++@c object independently. + This is like @code{strstr}, except that it ignores case in searching for + the substring. Like @code{strcasecmp}, it is locale dependent how + uppercase and lowercase characters are related. +@@ -1800,6 +1874,7 @@ + @comment string.h + @comment GNU + @deftypefun {void *} memmem (const void *@var{haystack}, size_t @var{haystack-len},@*const void *@var{needle}, size_t @var{needle-len}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This is like @code{strstr}, but @var{needle} and @var{haystack} are byte + arrays rather than null-terminated strings. @var{needle-len} is the + length of @var{needle} and @var{haystack-len} is the length of +@@ -1811,6 +1886,7 @@ + @comment string.h + @comment ISO + @deftypefun size_t strspn (const char *@var{string}, const char *@var{skipset}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{strspn} (``string span'') function returns the length of the + initial substring of @var{string} that consists entirely of characters that + are members of the set specified by the string @var{skipset}. The order +@@ -1831,6 +1907,7 @@ + @comment wchar.h + @comment ISO + @deftypefun size_t wcsspn (const wchar_t *@var{wstring}, const wchar_t *@var{skipset}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{wcsspn} (``wide character string span'') function returns the + length of the initial substring of @var{wstring} that consists entirely + of wide characters that are members of the set specified by the string +@@ -1841,6 +1918,7 @@ + @comment string.h + @comment ISO + @deftypefun size_t strcspn (const char *@var{string}, const char *@var{stopset}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{strcspn} (``string complement span'') function returns the length + of the initial substring of @var{string} that consists entirely of characters + that are @emph{not} members of the set specified by the string @var{stopset}. +@@ -1862,6 +1940,7 @@ + @comment wchar.h + @comment ISO + @deftypefun size_t wcscspn (const wchar_t *@var{wstring}, const wchar_t *@var{stopset}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{wcscspn} (``wide character string complement span'') function + returns the length of the initial substring of @var{wstring} that + consists entirely of wide characters that are @emph{not} members of the +@@ -1873,6 +1952,7 @@ + @comment string.h + @comment ISO + @deftypefun {char *} strpbrk (const char *@var{string}, const char *@var{stopset}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{strpbrk} (``string pointer break'') function is related to + @code{strcspn}, except that it returns a pointer to the first character + in @var{string} that is a member of the set @var{stopset} instead of the +@@ -1897,6 +1977,7 @@ + @comment wchar.h + @comment ISO + @deftypefun {wchar_t *} wcspbrk (const wchar_t *@var{wstring}, const wchar_t *@var{stopset}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{wcspbrk} (``wide character string pointer break'') function is + related to @code{wcscspn}, except that it returns a pointer to the first + wide character in @var{wstring} that is a member of the set +@@ -1910,6 +1991,7 @@ + @comment string.h + @comment BSD + @deftypefun {char *} index (const char *@var{string}, int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + @code{index} is another name for @code{strchr}; they are exactly the same. + New code should always use @code{strchr} since this name is defined in + @w{ISO C} while @code{index} is a BSD invention which never was available +@@ -1919,6 +2001,7 @@ + @comment string.h + @comment BSD + @deftypefun {char *} rindex (const char *@var{string}, int @var{c}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + @code{rindex} is another name for @code{strrchr}; they are exactly the same. + New code should always use @code{strrchr} since this name is defined in + @w{ISO C} while @code{rindex} is a BSD invention which never was available +@@ -1940,6 +2023,7 @@ + @comment string.h + @comment ISO + @deftypefun {char *} strtok (char *restrict @var{newstring}, const char *restrict @var{delimiters}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:strtok}}@asunsafe{}@acsafe{}} + A string can be split into tokens by making a series of calls to the + function @code{strtok}. + +@@ -1978,7 +2062,8 @@ + + @comment wchar.h + @comment ISO +-@deftypefun {wchar_t *} wcstok (wchar_t *@var{newstring}, const char *@var{delimiters}) ++@deftypefun {wchar_t *} wcstok (wchar_t *@var{newstring}, const wchar_t *@var{delimiters}, wchar_t **@var{save_ptr}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + A string can be split into tokens by making a series of calls to the + function @code{wcstok}. + +@@ -1986,11 +2071,8 @@ + the first call only. The @code{wcstok} function uses this to set up + some internal state information. Subsequent calls to get additional + tokens from the same wide character string are indicated by passing a +-null pointer as the @var{newstring} argument. Calling @code{wcstok} +-with another non-null @var{newstring} argument reinitializes the state +-information. It is guaranteed that no other library function ever calls +-@code{wcstok} behind your back (which would mess up this internal state +-information). ++null pointer as the @var{newstring} argument, which causes the pointer ++previously stored in @var{save_ptr} to be used instead. + + The @var{delimiters} argument is a wide character string that specifies + a set of delimiters that may surround the token being extracted. All +@@ -1999,8 +2081,10 @@ + delimiters marks the beginning of the next token. The end of the token + is found by looking for the next wide character that is a member of the + delimiter set. This wide character in the original wide character +-string @var{newstring} is overwritten by a null wide character, and the +-pointer to the beginning of the token in @var{newstring} is returned. ++string @var{newstring} is overwritten by a null wide character, the ++pointer past the overwritten wide character is saved in @var{save_ptr}, ++and the pointer to the beginning of the token in @var{newstring} is ++returned. + + On the next call to @code{wcstok}, the searching begins at the next + wide character beyond the one that marked the end of the previous token. +@@ -2010,11 +2094,6 @@ + If the end of the wide character string @var{newstring} is reached, or + if the remainder of string consists only of delimiter wide characters, + @code{wcstok} returns a null pointer. +- +-Note that ``character'' is here used in the sense of byte. In a string +-using a multibyte character encoding (abstract) character consisting of +-more than one byte are not treated as an entity. Each byte is treated +-separately. The function is not locale-dependent. + @end deftypefun + + @strong{Warning:} Since @code{strtok} and @code{wcstok} alter the string +@@ -2039,7 +2118,7 @@ + structure, then it is error-prone to modify the data structure + temporarily. + +-The functions @code{strtok} and @code{wcstok} are not reentrant. ++The function @code{strtok} is not reentrant, whereas @code{wcstok} is. + @xref{Nonreentrancy}, for a discussion of where and why reentrancy is + important. + +@@ -2075,13 +2154,15 @@ + @comment string.h + @comment POSIX + @deftypefun {char *} strtok_r (char *@var{newstring}, const char *@var{delimiters}, char **@var{save_ptr}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Just like @code{strtok}, this function splits the string into several + tokens which can be accessed by successive calls to @code{strtok_r}. +-The difference is that the information about the next token is stored in +-the space pointed to by the third argument, @var{save_ptr}, which is a +-pointer to a string pointer. Calling @code{strtok_r} with a null +-pointer for @var{newstring} and leaving @var{save_ptr} between the calls +-unchanged does the job without hindering reentrancy. ++The difference is that, as in @code{wcstok}, the information about the ++next token is stored in the space pointed to by the third argument, ++@var{save_ptr}, which is a pointer to a string pointer. Calling ++@code{strtok_r} with a null pointer for @var{newstring} and leaving ++@var{save_ptr} between the calls unchanged does the job without ++hindering reentrancy. + + This function is defined in POSIX.1 and can be found on many systems + which support multi-threading. +@@ -2090,6 +2171,7 @@ + @comment string.h + @comment BSD + @deftypefun {char *} strsep (char **@var{string_ptr}, const char *@var{delimiter}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function has a similar functionality as @code{strtok_r} with the + @var{newstring} argument replaced by the @var{save_ptr} argument. The + initialization of the moving pointer has to be done by the user. +@@ -2141,6 +2223,7 @@ + @comment string.h + @comment GNU + @deftypefun {char *} basename (const char *@var{filename}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The GNU version of the @code{basename} function returns the last + component of the path in @var{filename}. This function is the preferred + usage, since it does not modify the argument, @var{filename}, and +@@ -2175,8 +2258,9 @@ + + @comment libgen.h + @comment XPG +-@deftypefun {char *} basename (char *@var{path}) +-This is the standard XPG defined @code{basename}. It is similar in ++@deftypefun {char *} basename (const char *@var{path}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++This is the standard XPG defined @code{basename}. It is similar in + spirit to the GNU version, but may modify the @var{path} by removing + trailing '/' characters. If the @var{path} is made up entirely of '/' + characters, then "/" will be returned. Also, if @var{path} is +@@ -2211,6 +2295,7 @@ + @comment libgen.h + @comment XPG + @deftypefun {char *} dirname (char *@var{path}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{dirname} function is the compliment to the XPG version of + @code{basename}. It returns the parent directory of the file specified + by @var{path}. If @var{path} is @code{NULL}, an empty string, or +@@ -2233,6 +2318,8 @@ + @comment string.h + @comment GNU + @deftypefun {char *} strfry (char *@var{string}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Calls initstate_r, time, getpid, strlen, and random_r. + + @code{strfry} creates a pseudorandom anagram of a string, replacing the + input with the anagram in place. For each position in the string, +@@ -2268,6 +2355,7 @@ + @comment string.h + @comment GNU + @deftypefun {void *} memfrob (void *@var{mem}, size_t @var{length}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + + @code{memfrob} transforms (frobnicates) each byte of the data structure + at @var{mem}, which is @var{length} bytes long, by bitwise exclusive +@@ -2291,13 +2379,14 @@ + + To store or transfer binary data in environments which only support text + one has to encode the binary data by mapping the input bytes to +-characters in the range allowed for storing or transfering. SVID ++characters in the range allowed for storing or transferring. SVID + systems (and nowadays XPG compliant systems) provide minimal support for + this task. + + @comment stdlib.h + @comment XPG + @deftypefun {char *} l64a (long int @var{n}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:l64a}}@asunsafe{}@acsafe{}} + This function encodes a 32-bit input value using characters from the + basic character set. It returns a pointer to a 7 character buffer which + contains an encoded version of @var{n}. To encode a series of bytes the +@@ -2373,6 +2462,7 @@ + @comment stdlib.h + @comment XPG + @deftypefun {long int} a64l (const char *@var{string}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The parameter @var{string} should contain a string which was produced by + a call to @code{l64a}. The function processes at least 6 characters of + this string, and decodes the characters it finds according to the table +@@ -2459,6 +2549,7 @@ + @comment argz.h + @comment GNU + @deftypefun {error_t} argz_create (char *const @var{argv}[], char **@var{argz}, size_t *@var{argz_len}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + The @code{argz_create} function converts the Unix-style argument vector + @var{argv} (a vector of pointers to normal C strings, terminated by + @code{(char *)0}; @pxref{Program Arguments}) into an argz vector with +@@ -2468,6 +2559,7 @@ + @comment argz.h + @comment GNU + @deftypefun {error_t} argz_create_sep (const char *@var{string}, int @var{sep}, char **@var{argz}, size_t *@var{argz_len}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + The @code{argz_create_sep} function converts the null-terminated string + @var{string} into an argz vector (returned in @var{argz} and + @var{argz_len}) by splitting it into elements at every occurrence of the +@@ -2477,13 +2569,15 @@ + @comment argz.h + @comment GNU + @deftypefun {size_t} argz_count (const char *@var{argz}, size_t @var{arg_len}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + Returns the number of elements in the argz vector @var{argz} and + @var{argz_len}. + @end deftypefun + + @comment argz.h + @comment GNU +-@deftypefun {void} argz_extract (char *@var{argz}, size_t @var{argz_len}, char **@var{argv}) ++@deftypefun {void} argz_extract (const char *@var{argz}, size_t @var{argz_len}, char **@var{argv}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{argz_extract} function converts the argz vector @var{argz} and + @var{argz_len} into a Unix-style argument vector stored in @var{argv}, + by putting pointers to every element in @var{argz} into successive +@@ -2501,6 +2595,7 @@ + @comment argz.h + @comment GNU + @deftypefun {void} argz_stringify (char *@var{argz}, size_t @var{len}, int @var{sep}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{argz_stringify} converts @var{argz} into a normal string with + the elements separated by the character @var{sep}, by replacing each + @code{'\0'} inside @var{argz} (except the last one, which terminates the +@@ -2511,6 +2606,8 @@ + @comment argz.h + @comment GNU + @deftypefun {error_t} argz_add (char **@var{argz}, size_t *@var{argz_len}, const char *@var{str}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} ++@c Calls strlen and argz_append. + The @code{argz_add} function adds the string @var{str} to the end of the + argz vector @code{*@var{argz}}, and updates @code{*@var{argz}} and + @code{*@var{argz_len}} accordingly. +@@ -2519,6 +2616,7 @@ + @comment argz.h + @comment GNU + @deftypefun {error_t} argz_add_sep (char **@var{argz}, size_t *@var{argz_len}, const char *@var{str}, int @var{delim}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + The @code{argz_add_sep} function is similar to @code{argz_add}, but + @var{str} is split into separate elements in the result at occurrences of + the character @var{delim}. This is useful, for instance, for +@@ -2529,6 +2627,7 @@ + @comment argz.h + @comment GNU + @deftypefun {error_t} argz_append (char **@var{argz}, size_t *@var{argz_len}, const char *@var{buf}, size_t @var{buf_len}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + The @code{argz_append} function appends @var{buf_len} bytes starting at + @var{buf} to the argz vector @code{*@var{argz}}, reallocating + @code{*@var{argz}} to accommodate it, and adding @var{buf_len} to +@@ -2538,6 +2637,8 @@ + @comment argz.h + @comment GNU + @deftypefun {void} argz_delete (char **@var{argz}, size_t *@var{argz_len}, char *@var{entry}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} ++@c Calls free if no argument is left. + If @var{entry} points to the beginning of one of the elements in the + argz vector @code{*@var{argz}}, the @code{argz_delete} function will + remove this entry and reallocate @code{*@var{argz}}, modifying +@@ -2549,6 +2650,8 @@ + @comment argz.h + @comment GNU + @deftypefun {error_t} argz_insert (char **@var{argz}, size_t *@var{argz_len}, char *@var{before}, const char *@var{entry}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} ++@c Calls argz_add or realloc and memmove. + The @code{argz_insert} function inserts the string @var{entry} into the + argz vector @code{*@var{argz}} at a point just before the existing + element pointed to by @var{before}, reallocating @code{*@var{argz}} and +@@ -2561,7 +2664,8 @@ + + @comment argz.h + @comment GNU +-@deftypefun {char *} argz_next (char *@var{argz}, size_t @var{argz_len}, const char *@var{entry}) ++@deftypefun {char *} argz_next (const char *@var{argz}, size_t @var{argz_len}, const char *@var{entry}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{argz_next} function provides a convenient way of iterating + over the elements in the argz vector @var{argz}. It returns a pointer + to the next element in @var{argz} after the element @var{entry}, or +@@ -2595,6 +2699,7 @@ + @comment argz.h + @comment GNU + @deftypefun error_t argz_replace (@w{char **@var{argz}, size_t *@var{argz_len}}, @w{const char *@var{str}, const char *@var{with}}, @w{unsigned *@var{replace_count}}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + Replace any occurrences of the string @var{str} in @var{argz} with + @var{with}, reallocating @var{argz} as necessary. If + @var{replace_count} is non-zero, @code{*@var{replace_count}} will be +@@ -2630,6 +2735,7 @@ + @comment envz.h + @comment GNU + @deftypefun {char *} envz_entry (const char *@var{envz}, size_t @var{envz_len}, const char *@var{name}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{envz_entry} function finds the entry in @var{envz} with the name + @var{name}, and returns a pointer to the whole entry---that is, the argz + element which begins with @var{name} followed by a @code{'='} character. If +@@ -2639,6 +2745,7 @@ + @comment envz.h + @comment GNU + @deftypefun {char *} envz_get (const char *@var{envz}, size_t @var{envz_len}, const char *@var{name}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{envz_get} function finds the entry in @var{envz} with the name + @var{name} (like @code{envz_entry}), and returns a pointer to the value + portion of that entry (following the @code{'='}). If there is no entry with +@@ -2648,6 +2755,9 @@ + @comment envz.h + @comment GNU + @deftypefun {error_t} envz_add (char **@var{envz}, size_t *@var{envz_len}, const char *@var{name}, const char *@var{value}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} ++@c Calls envz_remove, which calls enz_entry and argz_delete, and then ++@c argz_add or equivalent code that reallocs and appends name=value. + The @code{envz_add} function adds an entry to @code{*@var{envz}} + (updating @code{*@var{envz}} and @code{*@var{envz_len}}) with the name + @var{name}, and value @var{value}. If an entry with the same name +@@ -2659,6 +2769,7 @@ + @comment envz.h + @comment GNU + @deftypefun {error_t} envz_merge (char **@var{envz}, size_t *@var{envz_len}, const char *@var{envz2}, size_t @var{envz2_len}, int @var{override}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} + The @code{envz_merge} function adds each entry in @var{envz2} to @var{envz}, + as if with @code{envz_add}, updating @code{*@var{envz}} and + @code{*@var{envz_len}}. If @var{override} is true, then values in @var{envz2} +@@ -2672,6 +2783,10 @@ + @comment envz.h + @comment GNU + @deftypefun {void} envz_strip (char **@var{envz}, size_t *@var{envz_len}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{envz_strip} function removes any null entries from @var{envz}, + updating @code{*@var{envz}} and @code{*@var{envz_len}}. + @end deftypefun ++ ++@c FIXME this are undocumented: ++@c strcasecmp_l @safety{@mtsafe{}@assafe{}@acsafe{}} see strcasecmp +diff -urN glibc-2.17-c758a686/manual/summary.awk glibc-2.17-c758a686/manual/summary.awk +--- glibc-2.17-c758a686/manual/summary.awk 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/summary.awk 2014-09-12 16:10:06.042792724 -0400 +@@ -1,5 +1,5 @@ + # awk script to create summary.texinfo from the library texinfo files. +-# Copyright (C) 1992, 1993, 1997, 2001 Free Software Foundation, Inc. ++# Copyright (C) 1992-2014 Free Software Foundation, Inc. + # This file is part of the GNU C Library. + + # The GNU C Library is free software; you can redistribute it and/or +diff -urN glibc-2.17-c758a686/manual/sysinfo.texi glibc-2.17-c758a686/manual/sysinfo.texi +--- glibc-2.17-c758a686/manual/sysinfo.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/sysinfo.texi 2014-09-12 16:10:06.048792709 -0400 +@@ -91,6 +91,9 @@ + @comment unistd.h + @comment BSD + @deftypefun int gethostname (char *@var{name}, size_t @var{size}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall on unix; implemented in terms of uname on posix and of ++@c hurd_get_host_config on hurd. + This function returns the host name of the system on which it is called, + in the array @var{name}. The @var{size} argument specifies the size of + this array, in bytes. Note that this is @emph{not} the DNS hostname. +@@ -121,6 +124,9 @@ + @comment unistd.h + @comment BSD + @deftypefun int sethostname (const char *@var{name}, size_t @var{length}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall on unix; implemented in terms of hurd_set_host_config ++@c on hurd. + The @code{sethostname} function sets the host name of the system that + calls it to @var{name}, a string with length @var{length}. Only + privileged processes are permitted to do this. +@@ -145,6 +151,8 @@ + @comment unistd.h + @comment ??? + @deftypefun int getdomainnname (char *@var{name}, size_t @var{length}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Syscalls uname, then strlen and memcpy. + @cindex NIS domain name + @cindex YP domain name + +@@ -159,6 +167,8 @@ + @comment unistd.h + @comment ??? + @deftypefun int setdomainname (const char *@var{name}, size_t @var{length}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall. + @cindex NIS domain name + @cindex YP domain name + +@@ -173,6 +183,10 @@ + @comment unistd.h + @comment BSD + @deftypefun {long int} gethostid (void) ++@safety{@prelim{}@mtsafe{@mtshostid{} @mtsenv{} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @asucorrupt{} @ascuheap{} @asulock{}}@acunsafe{@aculock{} @acucorrupt{} @acsmem{} @acsfd{}}} ++@c On HURD, calls _hurd_get_host_config and strtol. On Linux, open ++@c HOSTIDFILE, reads an int32_t and closes; if that fails, it calls ++@c gethostname and gethostbyname_r to use the h_addr. + This function returns the ``host ID'' of the machine the program is + running on. By convention, this is usually the primary Internet IP address + of that machine, converted to a @w{@code{long int}}. However, on some +@@ -190,6 +204,7 @@ + @comment unistd.h + @comment BSD + @deftypefun int sethostid (long int @var{id}) ++@safety{@prelim{}@mtunsafe{@mtasuconst{:@mtshostid{}}}@asunsafe{}@acunsafe{@acucorrupt{} @acsfd{}}} + The @code{sethostid} function sets the ``host ID'' of the host machine + to @var{id}. Only privileged processes are permitted to do this. Usually + it happens just once, at system boot time. +@@ -226,7 +241,7 @@ + + As a bonus, @code{uname} also gives some information identifying the + particular system your program is running on. This is the same information +-which you can get with functions targetted to this purpose described in ++which you can get with functions targeted to this purpose described in + @ref{Host Identification}. + + +@@ -296,6 +311,10 @@ + @comment sys/utsname.h + @comment POSIX.1 + @deftypefun int uname (struct utsname *@var{info}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall on unix; the posix fallback is to call gethostname and ++@c then fills in the other fields with constants; on HURD, it calls ++@c proc_uname and then gethostname. + The @code{uname} function fills in the structure pointed to by + @var{info} with information about the operating system and host machine. + A non-negative value indicates that the data was successfully stored. +@@ -471,6 +490,12 @@ + @comment fstab.h + @comment BSD + @deftypefun int setfsent (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:fsent}}@asunsafe{@ascuheap{} @asucorrupt{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} ++@c setfsent @mtasurace:fsent @ascuheap @asucorrupt @asulock @acucorrupt @aculock @acsmem @acsfd ++@c fstab_init(1) @mtasurace:fsent @ascuheap @asucorrupt @asulock @acucorrupt @aculock @acsmem @acsfd ++@c malloc dup @ascuheap @acsmem ++@c rewind dup @asucorrupt @acucorrupt [no @aculock] ++@c setmntent dup @ascuheap @asulock @acsmem @acsfd @aculock + This function makes sure that the internal read pointer for the + @file{fstab} file is at the beginning of the file. This is done by + either opening the file or resetting the read pointer. +@@ -486,6 +511,9 @@ + @comment fstab.h + @comment BSD + @deftypefun void endfsent (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:fsent}}@asunsafe{@ascuheap{} @asucorrupt{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} ++@c endfsent @mtasurace:fsent @ascuheap @asucorrupt @asulock @acucorrupt @aculock @acsmem @acsfd ++@c endmntent dup @ascuheap @asulock @aculock @acsmem @acsfd + This function makes sure that all resources acquired by a prior call to + @code{setfsent} (explicitly or implicitly by calling @code{getfsent}) are + freed. +@@ -494,6 +522,13 @@ + @comment fstab.h + @comment BSD + @deftypefun {struct fstab *} getfsent (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:fsent} @mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{}}} ++@c getfsent @mtasurace:fsent @mtslocale @asucorrupt @ascuheap @asulock @acucorrupt @aculock @acsmem ++@c fstab_init(0) dup @mtasurace:fsent @ascuheap @asucorrupt @asulock @acucorrupt @aculock @acsmem @acsfd ++@c fstab_fetch @mtasurace:fsent @mtslocale @asucorrupt @ascuheap @acucorrupt @aculock @acsmem ++@c getmntent_r dup @mtslocale @asucorrupt @ascuheap @acucorrupt @aculock @acsmem ++@c fstab_convert @mtasurace:fsent ++@c hasmntopt dup ok + This function returns the next entry of the @file{fstab} file. If this + is the first call to any of the functions handling @file{fstab} since + program start or the last call of @code{endfsent}, the file will be +@@ -508,6 +543,12 @@ + @comment fstab.h + @comment BSD + @deftypefun {struct fstab *} getfsspec (const char *@var{name}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:fsent} @mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{}}} ++@c getffsspec @mtasurace:fsent @mtslocale @asucorrupt @ascuheap @asulock @acucorrupt @aculock @acsmem ++@c fstab_init(1) dup @mtasurace:fsent @ascuheap @asucorrupt @asulock @acucorrupt @aculock @acsmem @acsfd ++@c fstab_fetch dup @mtasurace:fsent @mtslocale @asucorrupt @ascuheap @acucorrupt @aculock @acsmem ++@c strcmp dup ok ++@c fstab_convert dup @mtasurace:fsent + This function returns the next entry of the @file{fstab} file which has + a string equal to @var{name} pointed to by the @code{fs_spec} element. + Since there is normally exactly one entry for each special device it +@@ -525,6 +566,12 @@ + @comment fstab.h + @comment BSD + @deftypefun {struct fstab *} getfsfile (const char *@var{name}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:fsent} @mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{}}} ++@c getffsfile @mtasurace:fsent @mtslocale @asucorrupt @ascuheap @asulock @acucorrupt @aculock @acsmem ++@c fstab_init(1) dup @mtasurace:fsent @ascuheap @asucorrupt @asulock @acucorrupt @aculock @acsmem @acsfd ++@c fstab_fetch dup @mtasurace:fsent @mtslocale @asucorrupt @ascuheap @acucorrupt @aculock @acsmem ++@c strcmp dup ok ++@c fstab_convert dup @mtasurace:fsent + This function returns the next entry of the @file{fstab} file which has + a string equal to @var{name} pointed to by the @code{fs_file} element. + Since there is normally exactly one entry for each mount point it +@@ -640,6 +687,13 @@ + @comment mntent.h + @comment BSD + @deftypefun {FILE *} setmntent (const char *@var{file}, const char *@var{mode}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@acsmem{} @acsfd{} @aculock{}}} ++@c setmntent @ascuheap @asulock @acsmem @acsfd @aculock ++@c strlen dup ok ++@c mempcpy dup ok ++@c memcpy dup ok ++@c fopen dup @ascuheap @asulock @acsmem @acsfd @aculock ++@c fsetlocking dup ok [no @mtasurace:stream @asulock: exclusive stream] + The @code{setmntent} function prepares the file named @var{FILE} which + must be in the format of a @file{fstab} and @file{mtab} file for the + upcoming processing through the other functions of the family. The +@@ -655,6 +709,9 @@ + @comment mntent.h + @comment BSD + @deftypefun int endmntent (FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsmem{} @acsfd{}}} ++@c endmntent @ascuheap @asulock @aculock @acsmem @acsfd ++@c fclose dup @ascuheap @asulock @aculock @acsmem @acsfd + This function takes for the @var{stream} parameter a file handle which + previously was returned from the @code{setmntent} call. + @code{endmntent} closes the stream and frees all resources. +@@ -666,6 +723,12 @@ + @comment mntent.h + @comment BSD + @deftypefun {struct mntent *} getmntent (FILE *@var{stream}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:mntentbuf} @mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{} @asuinit{}}@acunsafe{@acuinit{} @acucorrupt{} @aculock{} @acsmem{}}} ++@c getmntent @mtasurace:mntentbuf @mtslocale @asucorrupt @ascuheap @asuinit @acuinit @acucorrupt @aculock @acsmem ++@c libc_once @ascuheap @asuinit @acuinit @acsmem ++@c allocate @ascuheap @acsmem ++@c malloc dup @ascuheap @acsmem ++@c getmntent_r dup @mtslocale @asucorrupt @ascuheap @acucorrupt @aculock @acsmem + The @code{getmntent} function takes as the parameter a file handle + previously returned by successful call to @code{setmntent}. It returns + a pointer to a static variable of type @code{struct mntent} which is +@@ -691,7 +754,17 @@ + + @comment mntent.h + @comment BSD +-@deftypefun {struct mntent *} getmntent_r (FILE *@var{stream}, struct mentent *@var{result}, char *@var{buffer}, int @var{bufsize}) ++@deftypefun {struct mntent *} getmntent_r (FILE *@var{stream}, struct mntent *@var{result}, char *@var{buffer}, int @var{bufsize}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{}}} ++@c getmntent_r @mtslocale @asucorrupt @ascuheap @acucorrupt @aculock @acsmem ++@c flockfile dup @aculock ++@c fgets_unlocked dup @asucorrupt @acucorrupt [locked, so no @mtsrace:stream] ++@c funlockfile dup @aculock ++@c strchr dup ok ++@c strspn dup ok ++@c strsep dup ok ++@c decode_name ok ++@c sscanf dup @mtslocale @ascuheap @acsmem + The @code{getmntent_r} function is the reentrant variant of + @code{getmntent}. It also returns the next entry from the file and + returns a pointer. The actual variable the values are stored in is not +@@ -717,6 +790,12 @@ + @comment mntent.h + @comment BSD + @deftypefun int addmntent (FILE *@var{stream}, const struct mntent *@var{mnt}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:stream} @mtslocale{}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} ++@c addmntent @mtasurace:stream @mtslocale @asucorrupt @acucorrupt ++@c fseek dup @asucorrupt @acucorrupt [no @aculock] ++@c encode_name ok ++@c fprintf dup @mtslocale @asucorrupt @acucorrupt [no @ascuheap @acsmem, no @aculock] ++@c fflush dup @asucorrupt @acucorrupt [no @aculock] + The @code{addmntent} function allows adding a new entry to the file + previously opened with @code{setmntent}. The new entries are always + appended. I.e., even if the position of the file descriptor is not at +@@ -740,6 +819,11 @@ + @comment mntent.h + @comment BSD + @deftypefun {char *} hasmntopt (const struct mntent *@var{mnt}, const char *@var{opt}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c hasmntopt ok ++@c strlen dup ok ++@c strstr dup ok ++@c strchr dup ok + This function can be used to check whether the string pointed to by the + @code{mnt_opts} element of the variable pointed to by @var{mnt} contains + the option @var{opt}. If this is true a pointer to the beginning of the +@@ -778,6 +862,8 @@ + @comment sys/mount.h + @comment SVID, BSD + @deftypefun {int} mount (const char *@var{special_file}, const char *@var{dir}, const char *@var{fstype}, unsigned long int @var{options}, const void *@var{data}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall. + + @code{mount} mounts or remounts a filesystem. The two operations are + quite different and are merged rather unnaturally into this one function. +@@ -982,6 +1068,8 @@ + @comment sys/mount.h + @comment GNU + @deftypefun {int} umount2 (const char *@var{file}, int @var{flags}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall. + + @code{umount2} unmounts a filesystem. + +@@ -1047,6 +1135,8 @@ + @comment sys/mount.h + @comment SVID, GNU + @deftypefun {int} umount (const char *@var{file}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall or wrapper for umount2. + + @code{umount} does the same thing as @code{umount2} with @var{flags} set + to zeroes. It is more widely available than @code{umount2} but since it +@@ -1062,11 +1152,13 @@ + This section describes the @code{sysctl} function, which gets and sets + a variety of system parameters. + +-The symbols used in this section are declared in the file @file{sysctl.h}. ++The symbols used in this section are declared in the file @file{sys/sysctl.h}. + +-@comment sysctl.h ++@comment sys/sysctl.h + @comment BSD + @deftypefun int sysctl (int *@var{names}, int @var{nlen}, void *@var{oldval}, size_t *@var{oldlenp}, void *@var{newval}, size_t @var{newlen}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct syscall, Linux only. + + @code{sysctl} gets or sets a specified system parameter. There are so + many of these parameters that it is not practical to list them all here, +@@ -1090,7 +1182,7 @@ + a particular parameter, you specify a path through the structure in a + way analogous to specifying the pathname of a file. Each component of + the path is specified by an integer and each of these integers has a +-macro defined for it by @file{sysctl.h}. @var{names} is the path, in ++macro defined for it by @file{sys/sysctl.h}. @var{names} is the path, in + the form of an array of integers. Each component of the path is one + element of the array, in order. @var{nlen} is the number of components + in the path. +diff -urN glibc-2.17-c758a686/manual/syslog.texi glibc-2.17-c758a686/manual/syslog.texi +--- glibc-2.17-c758a686/manual/syslog.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/syslog.texi 2014-09-12 16:10:06.044792719 -0400 +@@ -147,6 +147,17 @@ + @comment syslog.h + @comment BSD + @deftypefun void openlog (const char *@var{ident}, int @var{option}, int @var{facility}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} ++@c openlog @asulock @aculock @acsfd ++@c libc_lock_lock @asulock @aculock ++@c openlog_internal @acsfd [always guarded by syslog_lock, so no race] ++@c strncpy dup ok ++@c socket dup @acsfd ++@c fcntl dup ok ++@c connect dup ok ++@c close dup @acsfd ++@c cancel_handler(NULL) @aculock ++@c libc_lock_unlock @aculock + + @code{openlog} opens or reopens a connection to Syslog in preparation + for submitting messages. +@@ -275,7 +286,39 @@ + @c syslog() is implemented as a call to vsyslog(). + @comment syslog.h + @comment BSD +-@deftypefun void syslog (int @var{facility_priority}, char *@var{format}, @dots{}) ++@deftypefun void syslog (int @var{facility_priority}, const char *@var{format}, @dots{}) ++@safety{@prelim{}@mtsafe{@mtsenv{} @mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} ++@c syslog @mtsenv @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c va_start dup ok ++@c vsyslog_chk @mtsenv @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c syslog(INTERNALLOG) dup @mtsenv @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c open_memstream @ascuheap @acsmem ++@c stpcpy dup ok ++@c getpid dup ok ++@c mempcpy dup ok ++@c fsetlocking [no @mtasurace:stream @asulock for exclusive stream] ++@c fprintf @mtslocale @ascuheap @acsmem [no @asucorrupt @aculock @acucorrupt on temp memstream] ++@c time dup ok ++@c localtime_r dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c strftime_l(C) dup @mtsenv @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c ftell dup ok [no @asucorrupt @aculock @acucorrupt on temp memstream] ++@c fputs_unlocked dup ok [no @mtasurace:stream @asucorrupt @acucorrupt on temp memstream] ++@c putc_unlocked dup ok [no @mtasurace:stream @asucorrupt @acucorrupt on temp memstream] ++@c vfprintf/vfprintf_chk dup @mtslocale @ascuheap @acsmem [no @mtasurace:stream @asucorrupt @acucorrupt on temp memstream] ++@c fclose dup @ascuheap @acsmem [no @asulock @aculock @acsfd on caller-locked memstream] ++@c writev dup ok ++@c libc_lock_lock dup @asulock @aculock ++@c memset dup ok ++@c sigemptyset dup ok ++@c sigaction(SIGPIPE) dup @mtasusig:PIPE @acusig:PIPE ++@c openlog_internal dup @acsfd ++@c send dup ok ++@c closelog_internal dup @acsfd ++@c open dup @acsfd ++@c dprintf dup ok ++@c libc_lock_unlock @asulock @aculock ++@c free dup @acsuheap @acsmem ++@c va_end dup ok + + @code{syslog} submits a message to the Syslog facility. It does this by + writing to the Unix domain socket @code{/dev/log}. +@@ -403,7 +446,10 @@ + + @comment syslog.h + @comment BSD +-@deftypefun void vsyslog (int @var{facility_priority}, char *@var{format}, va_list @var{arglist}) ++@deftypefun void vsyslog (int @var{facility_priority}, const char *@var{format}, va_list @var{arglist}) ++@safety{@prelim{}@mtsafe{@mtsenv{} @mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} ++@c vsyslog @mtsenv @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c vsyslog_chk dup @mtsenv @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd + + This is functionally identical to @code{syslog}, with the BSD style variable + length argument. +@@ -420,6 +466,13 @@ + @comment syslog.h + @comment BSD + @deftypefun void closelog (void) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} ++@c closelog @asulock @aculock @acsfd ++@c libc_lock_lock @asulock @aculock ++@c closelog_internal @acsfd [always guarded by syslog_lock, so no race] ++@c close dup@acsfd ++@c cancel_handler(NULL) @aculock ++@c libc_lock_unlock @aculock + + @code{closelog} closes the current Syslog connection, if there is one. + This includes closing the @file{/dev/log} socket, if it is open. +@@ -450,6 +503,10 @@ + @comment syslog.h + @comment BSD + @deftypefun int setlogmask (int @var{mask}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:LogMask}}@asunsafe{}@acsafe{}} ++@c Read and modify are not guarded by syslog_lock, so concurrent changes ++@c or even uses are undefined. This should use an atomic swap instead, ++@c at least for modifications. + + @code{setlogmask} sets a mask (the ``logmask'') that determines which + future @code{syslog} calls shall be ignored. If a program has not +diff -urN glibc-2.17-c758a686/manual/terminal.texi glibc-2.17-c758a686/manual/terminal.texi +--- glibc-2.17-c758a686/manual/terminal.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/terminal.texi 2014-09-12 16:10:06.047792712 -0400 +@@ -44,6 +44,9 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun int isatty (int @var{filedes}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c isatty ok ++@c tcgetattr dup ok + This function returns @code{1} if @var{filedes} is a file descriptor + associated with an open terminal device, and @math{0} otherwise. + @end deftypefun +@@ -55,6 +58,20 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun {char *} ttyname (int @var{filedes}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:ttyname}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} ++@c ttyname @mtasurace:ttyname @ascuheap @asulock @aculock @acsmem @acsfd ++@c isatty dup ok ++@c fstat dup ok ++@c memcpy dup ok ++@c getttyname @mtasurace:ttyname @ascuheap @asulock @aculock @acsmem @acsfd ++@c opendir @ascuheap @acsmem @acsfd ++@c readdir ok [protected by exclusive access] ++@c strcmp dup ok ++@c free dup @asulock @aculock @acsfd @acsmem ++@c malloc dup @asulock @aculock @acsfd @acsmem ++@c closedir @ascuheap @acsmem @acsfd ++@c mempcpy dup ok ++@c stat dup ok + If the file descriptor @var{filedes} is associated with a terminal + device, the @code{ttyname} function returns a pointer to a + statically-allocated, null-terminated string containing the file name of +@@ -65,6 +82,18 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun int ttyname_r (int @var{filedes}, char *@var{buf}, size_t @var{len}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{} @acsfd{}}} ++@c ttyname_r @ascuheap @acsmem @acsfd ++@c isatty dup ok ++@c fstat dup ok ++@c memcpy dup ok ++@c getttyname_r @ascuheap @acsmem @acsfd ++@c opendir @ascuheap @acsmem @acsfd ++@c readdir ok [protected by exclusive access] ++@c strcmp dup ok ++@c closedir @ascuheap @acsmem @acsfd ++@c stpncpy dup ok ++@c stat dup ok + The @code{ttyname_r} function is similar to the @code{ttyname} function + except that it places its result into the user-specified buffer starting + at @var{buf} with length @var{len}. +@@ -264,6 +293,9 @@ + @comment termios.h + @comment POSIX.1 + @deftypefun int tcgetattr (int @var{filedes}, struct termios *@var{termios-p}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Converting the kernel-returned termios data structure to the userland ++@c format does not ensure atomic or consistent writing. + This function is used to examine the attributes of the terminal + device with file descriptor @var{filedes}. The attributes are returned + in the structure that @var{termios-p} points to. +@@ -284,6 +316,9 @@ + @comment termios.h + @comment POSIX.1 + @deftypefun int tcsetattr (int @var{filedes}, int @var{when}, const struct termios *@var{termios-p}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Converting the incoming termios data structure to the kernel format ++@c does not ensure atomic or consistent reading. + This function sets the attributes of the terminal device with file + descriptor @var{filedes}. The new attributes are taken from the + structure that @var{termios-p} points to. +@@ -621,7 +656,7 @@ + of characters, carriage return followed by linefeed. + @end deftypevr + +-@comment termios.h ++@comment termios.h (optional) + @comment BSD + @deftypevr Macro tcflag_t OXTABS + If this bit is set, convert tab characters on output into the appropriate +@@ -630,7 +665,7 @@ + @gnulinuxsystems{} it is available as @code{XTABS}. + @end deftypevr + +-@comment termios.h ++@comment termios.h (optional) + @comment BSD + @deftypevr Macro tcflag_t ONOEOT + If this bit is set, discard @kbd{C-d} characters (code @code{004}) on +@@ -962,7 +997,7 @@ + While this bit is set, all output is discarded. @xref{Other Special}. + @end deftypevr + +-@comment termios.h ++@comment termios.h (optional) + @comment BSD + @deftypevr Macro tcflag_t NOKERNINFO + Setting this bit disables handling of the STATUS character. +@@ -1016,6 +1051,10 @@ + @comment termios.h + @comment POSIX.1 + @deftypefun speed_t cfgetospeed (const struct termios *@var{termios-p}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct access to a single termios field, except on Linux, where ++@c multiple accesses may take place. No worries either way, callers ++@c must ensure mutual exclusion on such non-opaque types. + This function returns the output line speed stored in the structure + @code{*@var{termios-p}}. + @end deftypefun +@@ -1023,6 +1062,7 @@ + @comment termios.h + @comment POSIX.1 + @deftypefun speed_t cfgetispeed (const struct termios *@var{termios-p}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function returns the input line speed stored in the structure + @code{*@var{termios-p}}. + @end deftypefun +@@ -1030,6 +1070,7 @@ + @comment termios.h + @comment POSIX.1 + @deftypefun int cfsetospeed (struct termios *@var{termios-p}, speed_t @var{speed}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function stores @var{speed} in @code{*@var{termios-p}} as the output + speed. The normal return value is @math{0}; a value of @math{-1} + indicates an error. If @var{speed} is not a speed, @code{cfsetospeed} +@@ -1039,6 +1080,7 @@ + @comment termios.h + @comment POSIX.1 + @deftypefun int cfsetispeed (struct termios *@var{termios-p}, speed_t @var{speed}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + This function stores @var{speed} in @code{*@var{termios-p}} as the input + speed. The normal return value is @math{0}; a value of @math{-1} + indicates an error. If @var{speed} is not a speed, @code{cfsetospeed} +@@ -1048,6 +1090,14 @@ + @comment termios.h + @comment BSD + @deftypefun int cfsetspeed (struct termios *@var{termios-p}, speed_t @var{speed}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c There's no guarantee that the two calls are atomic, but since this is ++@c not an opaque type, callers ought to ensure mutual exclusion to the ++@c termios object. ++ ++@c cfsetspeed ok ++@c cfsetispeed ok ++@c cfsetospeed ok + This function stores @var{speed} in @code{*@var{termios-p}} as both the + input and output speeds. The normal return value is @math{0}; a value + of @math{-1} indicates an error. If @var{speed} is not a speed, +@@ -1625,6 +1675,10 @@ + @comment termios.h + @comment BSD + @deftypefun void cfmakeraw (struct termios *@var{termios-p}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c There's no guarantee the changes are atomic, but since this is not an ++@c opaque type, callers ought to ensure mutual exclusion to the termios ++@c object. + This function provides an easy way to set up @code{*@var{termios-p}} for + what has traditionally been called ``raw mode'' in BSD. This uses + noncanonical input, and turns off most processing to give an unmodified +@@ -1678,6 +1732,8 @@ + @comment sgtty.h + @comment BSD + @deftypefun int gtty (int @var{filedes}, struct sgttyb *@var{attributes}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct ioctl, BSD only. + This function gets the attributes of a terminal. + + @code{gtty} sets *@var{attributes} to describe the terminal attributes +@@ -1686,7 +1742,9 @@ + + @comment sgtty.h + @comment BSD +-@deftypefun int stty (int @var{filedes}, struct sgttyb *@var{attributes}) ++@deftypefun int stty (int @var{filedes}, const struct sgttyb *@var{attributes}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct ioctl, BSD only. + + This function sets the attributes of a terminal. + +@@ -1710,6 +1768,12 @@ + @comment termios.h + @comment POSIX.1 + @deftypefun int tcsendbreak (int @var{filedes}, int @var{duration}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:tcattr(filedes)/bsd}}@asunsafe{}@acunsafe{@acucorrupt{/bsd}}} ++@c On Linux, this calls just one out of two ioctls; on BSD, it's two ++@c ioctls with a select (for the delay only) in between, the first ++@c setting and the latter clearing the break status. The BSD ++@c implementation may leave the break enabled if cancelled, and threads ++@c and signals may cause the break to be interrupted before requested. + This function generates a break condition by transmitting a stream of + zero bits on the terminal associated with the file descriptor + @var{filedes}. The duration of the break is controlled by the +@@ -1738,6 +1802,8 @@ + @comment termios.h + @comment POSIX.1 + @deftypefun int tcdrain (int @var{filedes}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct ioctl. + The @code{tcdrain} function waits until all queued + output to the terminal @var{filedes} has been transmitted. + +@@ -1772,6 +1838,8 @@ + @comment termios.h + @comment POSIX.1 + @deftypefun int tcflush (int @var{filedes}, int @var{queue}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Direct ioctl. + The @code{tcflush} function is used to clear the input and/or output + queues associated with the terminal file @var{filedes}. The @var{queue} + argument specifies which queue(s) to clear, and can be one of the +@@ -1822,6 +1890,11 @@ + @comment termios.h + @comment POSIX.1 + @deftypefun int tcflow (int @var{filedes}, int @var{action}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:tcattr(filedes)/bsd}}@asunsafe{}@acsafe{}} ++@c Direct ioctl on Linux. On BSD, the TCO* actions are a single ioctl, ++@c whereas the TCI actions first call tcgetattr and then write to the fd ++@c the c_cc character corresponding to the action; there's a window for ++@c another thread to change the xon/xoff characters. + The @code{tcflow} function is used to perform operations relating to + XON/XOFF flow control on the terminal file specified by @var{filedes}. + +@@ -1931,6 +2004,14 @@ + @comment stdlib.h + @comment GNU + @deftypefun int getpt (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{@acsfd{}}} ++@c On BSD, tries to open multiple potential pty names, returning on the ++@c first success. On Linux, try posix_openpt first, then fallback to ++@c the BSD implementation. The posix implementation opens the ptmx ++@c device, checks with statfs that /dev/pts is a devpts or that /dev is ++@c a devfs, and returns the fd; static variables devpts_mounted and ++@c have_no_dev_ptmx are safely initialized so as to avoid repeated ++@c tests. + The @code{getpt} function returns a new file descriptor for the next + available master pseudo-terminal. The normal return value from + @code{getpt} is a non-negative integer file descriptor. In the case of +@@ -1948,6 +2029,32 @@ + @comment stdlib.h + @comment SVID, XPG4.2 + @deftypefun int grantpt (int @var{filedes}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c grantpt @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c unix/grantpt:pts_name @acsuheap @acsmem ++@c ptsname_internal dup ok (but this is Linux-only!) ++@c memchr dup ok ++@c realloc dup @acsuheap @acsmem ++@c malloc dup @acsuheap @acsmem ++@c free dup @acsuheap @acsmem ++@c fcntl dup ok ++@c getuid dup ok ++@c chown dup ok ++@c sysconf(_SC_GETGR_R_SIZE_MAX) ok ++@c getgrnam_r @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c getgid dup ok ++@c chmod dup ok ++@c fork dup @aculock ++@c [child] ++@c setrlimit ++@c dup2 ++@c CLOSE_ALL_FDS ++@c execle ++@c _exit ++@c waitpid dup ok ++@c WIFEXITED dup ok ++@c WEXITSTATUS dup ok ++@c free dup @ascuheap @acsmem + The @code{grantpt} function changes the ownership and access permission + of the slave pseudo-terminal device corresponding to the master + pseudo-terminal device associated with the file descriptor +@@ -1985,6 +2092,13 @@ + @comment stdlib.h + @comment SVID, XPG4.2 + @deftypefun int unlockpt (int @var{filedes}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{/bsd}}@acunsafe{@acsmem{} @acsfd{}}} ++@c unlockpt @ascuheap/bsd @acsmem @acsfd ++@c /bsd ++@c ptsname_r dup @ascuheap @acsmem @acsfd ++@c revoke ok (syscall) ++@c /linux ++@c ioctl dup ok + The @code{unlockpt} function unlocks the slave pseudo-terminal device + corresponding to the master pseudo-terminal device associated with the + file descriptor @var{filedes}. On many systems, the slave can only be +@@ -2008,6 +2122,9 @@ + @comment stdlib.h + @comment SVID, XPG4.2 + @deftypefun {char *} ptsname (int @var{filedes}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:ptsname}}@asunsafe{@ascuheap{/bsd}}@acunsafe{@acsmem{} @acsfd{}}} ++@c ptsname @mtasurace:ptsname @ascuheap/bsd @acsmem @acsfd ++@c ptsname_r dup @ascuheap/bsd @acsmem @acsfd + If the file descriptor @var{filedes} is associated with a + master pseudo-terminal device, the @code{ptsname} function returns a + pointer to a statically-allocated, null-terminated string containing the +@@ -2018,6 +2135,37 @@ + @comment stdlib.h + @comment GNU + @deftypefun int ptsname_r (int @var{filedes}, char *@var{buf}, size_t @var{len}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{/bsd}}@acunsafe{@acsmem{} @acsfd{}}} ++@c ptsname_r @ascuheap/bsd @acsmem @acsfd ++@c /hurd ++@c term_get_peername ok ++@c strlen dup ok ++@c memcpy dup ok ++@c /bsd ++@c isatty dup ok ++@c strlen dup ok ++@c ttyname_r dup @ascuheap @acsmem @acsfd ++@c stat dup ok ++@c /linux ++@c ptsname_internal ok ++@c isatty dup ok ++@c ioctl dup ok ++@c strlen dup ok ++@c itoa_word dup ok ++@c stpcpy dup ok ++@c memcpy dup ok ++@c fxstat64 dup ok ++@c MASTER_P ok ++@c major ok ++@c gnu_dev_major ok ++@c minor ok ++@c gnu_dev_minor ok ++@c minor dup ok ++@c xstat64 dup ok ++@c S_ISCHR dup ok ++@c SLAVE_P ok ++@c major dup ok ++@c minor dup ok + The @code{ptsname_r} function is similar to the @code{ptsname} function + except that it places its result into the user-specified buffer starting + at @var{buf} with length @var{len}. +@@ -2083,6 +2231,22 @@ + @comment pty.h + @comment BSD + @deftypefun int openpty (int *@var{amaster}, int *@var{aslave}, char *@var{name}, const struct termios *@var{termp}, const struct winsize *@var{winp}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c openpty @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c getpt @acsfd ++@c grantpt @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c unlockpt dup @ascuheap/bsd @acsmem @acsfd ++@c openpty:pts_name @acsuheap @acsmem @acsfd ++@c ptsname_r dup @ascuheap/bsd @acsmem @acsfd ++@c realloc dup @acsuheap @acsmem ++@c malloc dup @acsuheap @acsmem ++@c free dup @acsuheap @acsmem ++@c open dup @acsfd ++@c free dup @acsuheap @acsmem ++@c tcsetattr dup ok ++@c ioctl dup ok ++@c strcpy dup ok ++@c close dup @acsfd + This function allocates and opens a pseudo-terminal pair, returning the + file descriptor for the master in @var{*amaster}, and the file + descriptor for the slave in @var{*aslave}. If the argument @var{name} +@@ -2114,6 +2278,16 @@ + @comment pty.h + @comment BSD + @deftypefun int forkpty (int *@var{amaster}, char *@var{name}, const struct termios *@var{termp}, const struct winsize *@var{winp}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c forkpty @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c openpty dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c fork dup @aculock ++@c close dup @acsfd ++@c /child ++@c close dup @acsfd ++@c login_tty dup @mtasurace:ttyname @ascuheap @asulock @aculock @acsmem @acsfd ++@c _exit dup ok ++@c close dup @acsfd + This function is similar to the @code{openpty} function, but in + addition, forks a new process (@pxref{Creating a Process}) and makes the + newly opened slave pseudo-terminal device the controlling terminal +diff -urN glibc-2.17-c758a686/manual/texinfo.tex glibc-2.17-c758a686/manual/texinfo.tex +--- glibc-2.17-c758a686/manual/texinfo.tex 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/texinfo.tex 2014-09-12 16:10:06.047792712 -0400 +@@ -3,11 +3,11 @@ + % Load plain if necessary, i.e., if running under initex. + \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi + % +-\def\texinfoversion{2012-01-19.16} ++\def\texinfoversion{2014-05-05.10} + % + % Copyright 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995, + % 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, +-% 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. ++% 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc. + % + % This texinfo.tex file is free software: you can redistribute it and/or + % modify it under the terms of the GNU General Public License as +@@ -24,13 +24,14 @@ + % + % As a special exception, when this file is read by TeX when processing + % a Texinfo source document, you may use the result without +-% restriction. (This has been our intent since Texinfo was invented.) ++% restriction. This Exception is an additional permission under section 7 ++% of the GNU General Public License, version 3 ("GPLv3"). + % + % Please try the latest version of texinfo.tex before submitting bug + % reports; you can get the latest version from: +-% http://www.gnu.org/software/texinfo/ (the Texinfo home page), or +-% ftp://tug.org/tex/texinfo.tex +-% (and all CTAN mirrors, see http://www.ctan.org). ++% http://ftp.gnu.org/gnu/texinfo/ (the Texinfo release area), or ++% http://ftpmirror.gnu.org/texinfo/ (same, via a mirror), or ++% http://www.gnu.org/software/texinfo/ (the Texinfo home page) + % The texinfo.tex in any given distribution could well be out + % of date, so if that's what you're using, please check. + % +@@ -280,9 +281,9 @@ + \toks6=\expandafter{\prevsectiondefs}% + \toks8=\expandafter{\lastcolordefs}% + \mark{% +- \the\toks0 \the\toks2 +- \noexpand\or \the\toks4 \the\toks6 +- \noexpand\else \the\toks8 ++ \the\toks0 \the\toks2 % 0: top marks (\last...) ++ \noexpand\or \the\toks4 \the\toks6 % 1: bottom marks (default, \prev...) ++ \noexpand\else \the\toks8 % 2: color marks + }% + } + % \topmark doesn't work for the very first chapter (after the title +@@ -321,10 +322,13 @@ + % + % Do this outside of the \shipout so @code etc. will be expanded in + % the headline as they should be, not taken literally (outputting ''code). ++ \def\commmonheadfootline{\let\hsize=\pagewidth \texinfochars} ++ % + \ifodd\pageno \getoddheadingmarks \else \getevenheadingmarks \fi +- \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}% ++ \global\setbox\headlinebox = \vbox{\commmonheadfootline \makeheadline}% ++ % + \ifodd\pageno \getoddfootingmarks \else \getevenfootingmarks \fi +- \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}% ++ \global\setbox\footlinebox = \vbox{\commmonheadfootline \makefootline}% + % + {% + % Have to do this stuff outside the \shipout because we want it to +@@ -594,7 +598,7 @@ + \def\:{\spacefactor=1000 } + + % @* forces a line break. +-\def\*{\hfil\break\hbox{}\ignorespaces} ++\def\*{\unskip\hfil\break\hbox{}\ignorespaces} + + % @/ allows a line break. + \let\/=\allowbreak +@@ -887,7 +891,7 @@ + \def\popthisfilestack{\errthisfilestackempty} + \def\errthisfilestackempty{\errmessage{Internal error: + the stack of filenames is empty.}} +- ++% + \def\thisfile{} + + % @center line +@@ -895,36 +899,46 @@ + % + \parseargdef\center{% + \ifhmode +- \let\next\centerH ++ \let\centersub\centerH + \else +- \let\next\centerV ++ \let\centersub\centerV + \fi +- \next{\hfil \ignorespaces#1\unskip \hfil}% ++ \centersub{\hfil \ignorespaces#1\unskip \hfil}% ++ \let\centersub\relax % don't let the definition persist, just in case + } +-\def\centerH#1{% +- {% +- \hfil\break +- \advance\hsize by -\leftskip +- \advance\hsize by -\rightskip +- \line{#1}% +- \break +- }% ++\def\centerH#1{{% ++ \hfil\break ++ \advance\hsize by -\leftskip ++ \advance\hsize by -\rightskip ++ \line{#1}% ++ \break ++}} ++% ++\newcount\centerpenalty ++\def\centerV#1{% ++ % The idea here is the same as in \startdefun, \cartouche, etc.: if ++ % @center is the first thing after a section heading, we need to wipe ++ % out the negative parskip inserted by \sectionheading, but still ++ % prevent a page break here. ++ \centerpenalty = \lastpenalty ++ \ifnum\centerpenalty>10000 \vskip\parskip \fi ++ \ifnum\centerpenalty>9999 \penalty\centerpenalty \fi ++ \line{\kern\leftskip #1\kern\rightskip}% + } +-\def\centerV#1{\line{\kern\leftskip #1\kern\rightskip}} + + % @sp n outputs n lines of vertical space +- ++% + \parseargdef\sp{\vskip #1\baselineskip} + + % @comment ...line which is ignored... + % @c is the same as @comment + % @ignore ... @end ignore is another way to write a comment +- ++% + \def\comment{\begingroup \catcode`\^^M=\other% + \catcode`\@=\other \catcode`\{=\other \catcode`\}=\other% + \commentxxx} + {\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}} +- ++% + \let\c=\comment + + % @paragraphindent NCHARS +@@ -1097,7 +1111,7 @@ + % for display in the outlines, and in other places. Thus, we have to + % double any backslashes. Otherwise, a name like "\node" will be + % interpreted as a newline (\n), followed by o, d, e. Not good. +-% ++% + % See http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html and + % related messages. The final outcome is that it is up to the TeX user + % to double the backslashes and otherwise make the string valid, so +@@ -1107,7 +1121,7 @@ + % #1 is a control sequence in which to do the replacements, + % which we \xdef. + \def\txiescapepdf#1{% +- \ifx\pdfescapestring\relax ++ \ifx\pdfescapestring\thisisundefined + % No primitive available; should we give a warning or log? + % Many times it won't matter. + \else +@@ -1124,10 +1138,12 @@ + + \ifpdf + % +- % Color manipulation macros based on pdfcolor.tex, ++ % Color manipulation macros using ideas from pdfcolor.tex, + % except using rgb instead of cmyk; the latter is said to render as a + % very dark gray on-screen and a very dark halftone in print, instead +- % of actual black. ++ % of actual black. The dark red here is dark enough to print on paper as ++ % nearly black, but still distinguishable for online viewing. We use ++ % black by default, though. + \def\rgbDarkRed{0.50 0.09 0.12} + \def\rgbBlack{0 0 0} + % +@@ -1173,8 +1189,8 @@ + % + % #1 is image name, #2 width (might be empty/whitespace), #3 height (ditto). + \def\dopdfimage#1#2#3{% +- \def\imagewidth{#2}\setbox0 = \hbox{\ignorespaces #2}% +- \def\imageheight{#3}\setbox2 = \hbox{\ignorespaces #3}% ++ \def\pdfimagewidth{#2}\setbox0 = \hbox{\ignorespaces #2}% ++ \def\pdfimageheight{#3}\setbox2 = \hbox{\ignorespaces #3}% + % + % pdftex (and the PDF format) support .pdf, .png, .jpg (among + % others). Let's try in that order, PDF first since if +@@ -1212,8 +1228,8 @@ + \else + \immediate\pdfximage + \fi +- \ifdim \wd0 >0pt width \imagewidth \fi +- \ifdim \wd2 >0pt height \imageheight \fi ++ \ifdim \wd0 >0pt width \pdfimagewidth \fi ++ \ifdim \wd2 >0pt height \pdfimageheight \fi + \ifnum\pdftexversion<13 + #1.\pdfimgext + \else +@@ -1237,10 +1253,9 @@ + % used to mark target names; must be expandable. + \def\pdfmkpgn#1{#1} + % +- % by default, use a color that is dark enough to print on paper as +- % nearly black, but still distinguishable for online viewing. +- \def\urlcolor{\rgbDarkRed} +- \def\linkcolor{\rgbDarkRed} ++ % by default, use black for everything. ++ \def\urlcolor{\rgbBlack} ++ \def\linkcolor{\rgbBlack} + \def\endlink{\setcolor{\maincolor}\pdfendlink} + % + % Adding outlines to PDF; macros for calculating structure of outlines +@@ -1357,12 +1372,17 @@ + \def\skipspaces#1{\def\PP{#1}\def\D{|}% + \ifx\PP\D\let\nextsp\relax + \else\let\nextsp\skipspaces +- \ifx\p\space\else\addtokens{\filename}{\PP}% +- \advance\filenamelength by 1 +- \fi ++ \addtokens{\filename}{\PP}% ++ \advance\filenamelength by 1 + \fi + \nextsp} +- \def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax} ++ \def\getfilename#1{% ++ \filenamelength=0 ++ % If we don't expand the argument now, \skipspaces will get ++ % snagged on things like "@value{foo}". ++ \edef\temp{#1}% ++ \expandafter\skipspaces\temp|\relax ++ } + \ifnum\pdftexversion < 14 + \let \startlink \pdfannotlink + \else +@@ -1459,9 +1479,6 @@ + \def\ttsl{\setfontstyle{ttsl}} + + +-% Default leading. +-\newdimen\textleading \textleading = 13.2pt +- + % Set the baselineskip to #1, and the lineskip and strut size + % correspondingly. There is no deep meaning behind these magic numbers + % used as factors; they just match (closely enough) what Knuth defined. +@@ -1473,6 +1490,7 @@ + % can get a sort of poor man's double spacing by redefining this. + \def\baselinefactor{1} + % ++\newdimen\textleading + \def\setleading#1{% + \dimen0 = #1\relax + \normalbaselineskip = \baselinefactor\dimen0 +@@ -1745,18 +1763,24 @@ + \fi\fi + + +-% Set the font macro #1 to the font named #2, adding on the +-% specified font prefix (normally `cm'). ++% Set the font macro #1 to the font named \fontprefix#2. + % #3 is the font's design size, #4 is a scale factor, #5 is the CMap +-% encoding (currently only OT1, OT1IT and OT1TT are allowed, pass +-% empty to omit). ++% encoding (only OT1, OT1IT and OT1TT are allowed, or empty to omit). ++% Example: ++% #1 = \textrm ++% #2 = \rmshape ++% #3 = 10 ++% #4 = \mainmagstep ++% #5 = OT1 ++% + \def\setfont#1#2#3#4#5{% + \font#1=\fontprefix#2#3 scaled #4 + \csname cmap#5\endcsname#1% + } + % This is what gets called when #5 of \setfont is empty. + \let\cmap\gobble +-% emacs-page end of cmaps ++% ++% (end of cmaps) + + % Use cm as the default font prefix. + % To specify the font prefix, you must define \fontprefix +@@ -1766,7 +1790,7 @@ + \fi + % Support font families that don't use the same naming scheme as CM. + \def\rmshape{r} +-\def\rmbshape{bx} %where the normal face is bold ++\def\rmbshape{bx} % where the normal face is bold + \def\bfshape{b} + \def\bxshape{bx} + \def\ttshape{tt} +@@ -1781,8 +1805,7 @@ + \def\scshape{csc} + \def\scbshape{csc} + +-% Definitions for a main text size of 11pt. This is the default in +-% Texinfo. ++% Definitions for a main text size of 11pt. (The default in Texinfo.) + % + \def\definetextfontsizexi{% + % Text fonts (11.2pt, magstep1). +@@ -1907,7 +1930,7 @@ + \textleading = 13.2pt % line spacing for 11pt CM + \textfonts % reset the current fonts + \rm +-} % end of 11pt text font size definitions ++} % end of 11pt text font size definitions, \definetextfontsizexi + + + % Definitions to make the main text be 10pt Computer Modern, with +@@ -2039,7 +2062,7 @@ + \textleading = 12pt % line spacing for 10pt CM + \textfonts % reset the current fonts + \rm +-} % end of 10pt text font size definitions ++} % end of 10pt text font size definitions, \definetextfontsizex + + + % We provide the user-level command +@@ -2123,7 +2146,7 @@ + \let\tenttsl=\secttsl + \def\curfontsize{sec}% + \def\lsize{subsec}\def\lllsize{reduced}% +- \resetmathfonts \setleading{16pt}} ++ \resetmathfonts \setleading{17pt}} + \def\subsecfonts{% + \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl + \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc +@@ -2254,8 +2277,6 @@ + + \gdef\markupsetcodequoteleft{\let`\codequoteleft} + \gdef\markupsetcodequoteright{\let'\codequoteright} +- +-\gdef\markupsetnoligaturesquoteleft{\let`\noligaturesquoteleft} + } + + \let\markupsetuplqcode \markupsetcodequoteleft +@@ -2264,6 +2285,9 @@ + \let\markupsetuplqexample \markupsetcodequoteleft + \let\markupsetuprqexample \markupsetcodequoteright + % ++\let\markupsetuplqkbd \markupsetcodequoteleft ++\let\markupsetuprqkbd \markupsetcodequoteright ++% + \let\markupsetuplqsamp \markupsetcodequoteleft + \let\markupsetuprqsamp \markupsetcodequoteright + % +@@ -2273,8 +2297,6 @@ + \let\markupsetuplqverbatim \markupsetcodequoteleft + \let\markupsetuprqverbatim \markupsetcodequoteright + +-\let\markupsetuplqkbd \markupsetnoligaturesquoteleft +- + % Allow an option to not use regular directed right quote/apostrophe + % (char 0x27), but instead the undirected quote from cmtt (char 0x0d). + % The undirected quote is ugly, so don't make it the default, but it +@@ -2359,13 +2381,14 @@ + \ifx\next,% + \else\ifx\next-% + \else\ifx\next.% ++ \else\ifx\next\.% ++ \else\ifx\next\comma% + \else\ptexslash +- \fi\fi\fi ++ \fi\fi\fi\fi\fi + \aftersmartic + } + +-% like \smartslanted except unconditionally uses \ttsl, and no ic. +-% @var is set to this for defun arguments. ++% Unconditional use \ttsl, and no ic. @var is set to this for defuns. + \def\ttslanted#1{{\ttsl #1}} + + % @cite is like \smartslanted except unconditionally use \sl. We never want +@@ -2430,34 +2453,12 @@ + % @samp. + \def\samp#1{{\setupmarkupstyle{samp}\lq\tclose{#1}\rq\null}} + +-% definition of @key that produces a lozenge. Doesn't adjust to text size. +-%\setfont\keyrm\rmshape{8}{1000}{OT1} +-%\font\keysy=cmsy9 +-%\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{% +-% \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{% +-% \vbox{\hrule\kern-0.4pt +-% \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}% +-% \kern-0.4pt\hrule}% +-% \kern-.06em\raise0.4pt\hbox{\angleright}}}} +- +-% definition of @key with no lozenge. If the current font is already +-% monospace, don't change it; that way, we respect @kbdinputstyle. But +-% if it isn't monospace, then use \tt. +-% +-\def\key#1{{\setupmarkupstyle{key}% +- \nohyphenation +- \ifmonospace\else\tt\fi +- #1}\null} +- +-% ctrl is no longer a Texinfo command. +-\def\ctrl #1{{\tt \rawbackslash \hat}#1} ++% @indicateurl is \samp, that is, with quotes. ++\let\indicateurl=\samp + +-% @file, @option are the same as @samp. +-\let\file=\samp +-\let\option=\samp +- +-% @code is a modification of @t, +-% which makes spaces the same size as normal in the surrounding text. ++% @code (and similar) prints in typewriter, but with spaces the same ++% size as normal in the surrounding text, without hyphenation, etc. ++% This is a subroutine for that. + \def\tclose#1{% + {% + % Change normal interword space to be same as for the current font. +@@ -2480,14 +2481,14 @@ + } + + % We *must* turn on hyphenation at `-' and `_' in @code. ++% (But see \codedashfinish below.) + % Otherwise, it is too hard to avoid overfull hboxes + % in the Emacs manual, the Library manual, etc. +- ++% + % Unfortunately, TeX uses one parameter (\hyphenchar) to control + % both hyphenation at - and hyphenation within words. + % We must therefore turn them both off (\tclose does that) +-% and arrange explicitly to hyphenate at a dash. +-% -- rms. ++% and arrange explicitly to hyphenate at a dash. -- rms. + { + \catcode`\-=\active \catcode`\_=\active + \catcode`\'=\active \catcode`\`=\active +@@ -2501,17 +2502,38 @@ + \let-\codedash + \let_\codeunder + \else +- \let-\realdash ++ \let-\normaldash + \let_\realunder + \fi ++ % Given -foo (with a single dash), we do not want to allow a break ++ % after the hyphen. ++ \global\let\codedashprev=\codedash ++ % + \codex + } ++ % ++ \gdef\codedash{\futurelet\next\codedashfinish} ++ \gdef\codedashfinish{% ++ \normaldash % always output the dash character itself. ++ % ++ % Now, output a discretionary to allow a line break, unless ++ % (a) the next character is a -, or ++ % (b) the preceding character is a -. ++ % E.g., given --posix, we do not want to allow a break after either -. ++ % Given --foo-bar, we do want to allow a break between the - and the b. ++ \ifx\next\codedash \else ++ \ifx\codedashprev\codedash ++ \else \discretionary{}{}{}\fi ++ \fi ++ % we need the space after the = for the case when \next itself is a ++ % space token; it would get swallowed otherwise. As in @code{- a}. ++ \global\let\codedashprev= \next ++ } + } +- ++\def\normaldash{-} ++% + \def\codex #1{\tclose{#1}\endgroup} + +-\def\realdash{-} +-\def\codedash{-\discretionary{}{}{}} + \def\codeunder{% + % this is all so @math{@code{var_name}+1} can work. In math mode, _ + % is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.) +@@ -2525,9 +2547,9 @@ + } + + % An additional complication: the above will allow breaks after, e.g., +-% each of the four underscores in __typeof__. This is undesirable in +-% some manuals, especially if they don't have long identifiers in +-% general. @allowcodebreaks provides a way to control this. ++% each of the four underscores in __typeof__. This is bad. ++% @allowcodebreaks provides a document-level way to turn breaking at - ++% and _ on and off. + % + \newif\ifallowcodebreaks \allowcodebreakstrue + +@@ -2546,37 +2568,28 @@ + \fi\fi + } + +-% @uref (abbreviation for `urlref') takes an optional (comma-separated) +-% second argument specifying the text to display and an optional third +-% arg as text to display instead of (rather than in addition to) the url +-% itself. First (mandatory) arg is the url. +-% (This \urefnobreak definition isn't used now, leaving it for a while +-% for comparison.) +-\def\urefnobreak#1{\dourefnobreak #1,,,\finish} +-\def\dourefnobreak#1,#2,#3,#4\finish{\begingroup +- \unsepspaces +- \pdfurl{#1}% +- \setbox0 = \hbox{\ignorespaces #3}% +- \ifdim\wd0 > 0pt +- \unhbox0 % third arg given, show only that +- \else +- \setbox0 = \hbox{\ignorespaces #2}% +- \ifdim\wd0 > 0pt +- \ifpdf +- \unhbox0 % PDF: 2nd arg given, show only it +- \else +- \unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url +- \fi +- \else +- \code{#1}% only url given, so show it +- \fi +- \fi +- \endlink +-\endgroup} ++% For @command, @env, @file, @option quotes seem unnecessary, ++% so use \code rather than \samp. ++\let\command=\code ++\let\env=\code ++\let\file=\code ++\let\option=\code + +-% This \urefbreak definition is the active one. ++% @uref (abbreviation for `urlref') aka @url takes an optional ++% (comma-separated) second argument specifying the text to display and ++% an optional third arg as text to display instead of (rather than in ++% addition to) the url itself. First (mandatory) arg is the url. ++ ++% TeX-only option to allow changing PDF output to show only the second ++% arg (if given), and not the url (which is then just the link target). ++\newif\ifurefurlonlylink ++ ++% The main macro is \urefbreak, which allows breaking at expected ++% places within the url. (There used to be another version, which ++% didn't support automatic breaking.) + \def\urefbreak{\begingroup \urefcatcodes \dourefbreak} + \let\uref=\urefbreak ++% + \def\dourefbreak#1{\urefbreakfinish #1,,,\finish} + \def\urefbreakfinish#1,#2,#3,#4\finish{% doesn't work in @example + \unsepspaces +@@ -2585,12 +2598,19 @@ + \ifdim\wd0 > 0pt + \unhbox0 % third arg given, show only that + \else +- \setbox0 = \hbox{\ignorespaces #2}% ++ \setbox0 = \hbox{\ignorespaces #2}% look for second arg + \ifdim\wd0 > 0pt + \ifpdf +- \unhbox0 % PDF: 2nd arg given, show only it ++ \ifurefurlonlylink ++ % PDF plus option to not display url, show just arg ++ \unhbox0 ++ \else ++ % PDF, normally display both arg and url for consistency, ++ % visibility, if the pdf is eventually used to print, etc. ++ \unhbox0\ (\urefcode{#1})% ++ \fi + \else +- \unhbox0\ (\urefcode{#1})% DVI: 2nd arg given, show both it and url ++ \unhbox0\ (\urefcode{#1})% DVI, always show arg and url + \fi + \else + \urefcode{#1}% only url given, so show it +@@ -2630,8 +2650,10 @@ + % we put a little stretch before and after the breakable chars, to help + % line breaking of long url's. The unequal skips make look better in + % cmtt at least, especially for dots. +-\def\urefprestretch{\urefprebreak \hskip0pt plus.13em } +-\def\urefpoststretch{\urefpostbreak \hskip0pt plus.1em } ++\def\urefprestretchamount{.13em} ++\def\urefpoststretchamount{.1em} ++\def\urefprestretch{\urefprebreak \hskip0pt plus\urefprestretchamount\relax} ++\def\urefpoststretch{\urefpostbreak \hskip0pt plus\urefprestretchamount\relax} + % + \def\urefcodeamp{\urefprestretch \&\urefpoststretch} + \def\urefcodedot{\urefprestretch .\urefpoststretch} +@@ -2692,10 +2714,6 @@ + \let\email=\uref + \fi + +-% @kbd is like @code, except that if the argument is just one @key command, +-% then @kbd has no effect. +-\def\kbd#1{{\setupmarkupstyle{kbd}\def\look{#1}\expandafter\kbdfoo\look??\par}} +- + % @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always), + % `example' (@kbd uses ttsl only inside of @example and friends), + % or `code' (@kbd uses normal tty font always). +@@ -2719,16 +2737,36 @@ + % Default is `distinct'. + \kbdinputstyle distinct + ++% @kbd is like @code, except that if the argument is just one @key command, ++% then @kbd has no effect. ++\def\kbd#1{{\def\look{#1}\expandafter\kbdsub\look??\par}} ++ + \def\xkey{\key} +-\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}% +-\ifx\one\xkey\ifx\threex\three \key{#2}% +-\else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi +-\else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi} ++\def\kbdsub#1#2#3\par{% ++ \def\one{#1}\def\three{#3}\def\threex{??}% ++ \ifx\one\xkey\ifx\threex\three \key{#2}% ++ \else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi ++ \else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi ++} + +-% For @indicateurl, @env, @command quotes seem unnecessary, so use \code. +-\let\indicateurl=\code +-\let\env=\code +-\let\command=\code ++% definition of @key that produces a lozenge. Doesn't adjust to text size. ++%\setfont\keyrm\rmshape{8}{1000}{OT1} ++%\font\keysy=cmsy9 ++%\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{% ++% \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{% ++% \vbox{\hrule\kern-0.4pt ++% \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}% ++% \kern-0.4pt\hrule}% ++% \kern-.06em\raise0.4pt\hbox{\angleright}}}} ++ ++% definition of @key with no lozenge. If the current font is already ++% monospace, don't change it; that way, we respect @kbdinputstyle. But ++% if it isn't monospace, then use \tt. ++% ++\def\key#1{{\setupmarkupstyle{key}% ++ \nohyphenation ++ \ifmonospace\else\tt\fi ++ #1}\null} + + % @clicksequence{File @click{} Open ...} + \def\clicksequence#1{\begingroup #1\endgroup} +@@ -2836,6 +2874,9 @@ + } + } + ++% ctrl is no longer a Texinfo command, but leave this definition for fun. ++\def\ctrl #1{{\tt \rawbackslash \hat}#1} ++ + % @inlinefmt{FMTNAME,PROCESSED-TEXT} and @inlineraw{FMTNAME,RAW-TEXT}. + % Ignore unless FMTNAME == tex; then it is like @iftex and @tex, + % except specified as a normal braced arg, so no newlines to worry about. +@@ -2847,6 +2888,15 @@ + \def\inlinefmtname{#1}% + \ifx\inlinefmtname\outfmtnametex \ignorespaces #2\fi + } ++% ++% @inlinefmtifelse{FMTNAME,THEN-TEXT,ELSE-TEXT} expands THEN-TEXT if ++% FMTNAME is tex, else ELSE-TEXT. ++\long\def\inlinefmtifelse#1{\doinlinefmtifelse #1,,,\finish} ++\long\def\doinlinefmtifelse#1,#2,#3,#4,\finish{% ++ \def\inlinefmtname{#1}% ++ \ifx\inlinefmtname\outfmtnametex \ignorespaces #2\else \ignorespaces #3\fi ++} ++% + % For raw, must switch into @tex before parsing the argument, to avoid + % setting catcodes prematurely. Doing it this way means that, for + % example, @inlineraw{html, foo{bar} gets a parse error instead of being +@@ -2863,6 +2913,23 @@ + \endgroup % close group opened by \tex. + } + ++% @inlineifset{VAR, TEXT} expands TEXT if VAR is @set. ++% ++\long\def\inlineifset#1{\doinlineifset #1,\finish} ++\long\def\doinlineifset#1,#2,\finish{% ++ \def\inlinevarname{#1}% ++ \expandafter\ifx\csname SET\inlinevarname\endcsname\relax ++ \else\ignorespaces#2\fi ++} ++ ++% @inlineifclear{VAR, TEXT} expands TEXT if VAR is not @set. ++% ++\long\def\inlineifclear#1{\doinlineifclear #1,\finish} ++\long\def\doinlineifclear#1,#2,\finish{% ++ \def\inlinevarname{#1}% ++ \expandafter\ifx\csname SET\inlinevarname\endcsname\relax \ignorespaces#2\fi ++} ++ + + \message{glyphs,} + % and logos. +@@ -3126,12 +3193,17 @@ + % hopefully nobody will notice/care. + \edef\ecsize{\csname\curfontsize ecsize\endcsname}% + \edef\nominalsize{\csname\curfontsize nominalsize\endcsname}% +- \ifx\curfontstyle\bfstylename +- % bold: +- \font\thisecfont = ecb\ifusingit{i}{x}\ecsize \space at \nominalsize +- \else +- % regular: +- \font\thisecfont = ec\ifusingit{ti}{rm}\ecsize \space at \nominalsize ++ \ifmonospace ++ % typewriter: ++ \font\thisecfont = ectt\ecsize \space at \nominalsize ++ \else ++ \ifx\curfontstyle\bfstylename ++ % bold: ++ \font\thisecfont = ecb\ifusingit{i}{x}\ecsize \space at \nominalsize ++ \else ++ % regular: ++ \font\thisecfont = ec\ifusingit{ti}{rm}\ecsize \space at \nominalsize ++ \fi + \fi + \thisecfont + } +@@ -3244,6 +3316,20 @@ + \finishedtitlepagetrue + } + ++% Settings used for typesetting titles: no hyphenation, no indentation, ++% don't worry much about spacing, ragged right. This should be used ++% inside a \vbox, and fonts need to be set appropriately first. Because ++% it is always used for titles, nothing else, we call \rmisbold. \par ++% should be specified before the end of the \vbox, since a vbox is a group. ++% ++\def\raggedtitlesettings{% ++ \rmisbold ++ \hyphenpenalty=10000 ++ \parindent=0pt ++ \tolerance=5000 ++ \ptexraggedright ++} ++ + % Macros to be used within @titlepage: + + \let\subtitlerm=\tenrm +@@ -3251,7 +3337,7 @@ + + \parseargdef\title{% + \checkenv\titlepage +- \leftline{\titlefonts\rmisbold #1} ++ \vbox{\titlefonts \raggedtitlesettings #1\par}% + % print a rule at the page bottom also. + \finishedtitlepagefalse + \vskip4pt \hrule height 4pt width \hsize \vskip4pt +@@ -3599,7 +3685,7 @@ + \parskip=\smallskipamount + \ifdim\parskip=0pt \parskip=2pt \fi + % +- % Try typesetting the item mark that if the document erroneously says ++ % Try typesetting the item mark so that if the document erroneously says + % something like @itemize @samp (intending @table), there's an error + % right away at the @itemize. It's not the best error message in the + % world, but it's better than leaving it to the @item. This means if +@@ -3850,18 +3936,22 @@ + + % multitable-only commands. + % +-% @headitem starts a heading row, which we typeset in bold. +-% Assignments have to be global since we are inside the implicit group +-% of an alignment entry. \everycr resets \everytab so we don't have to ++% @headitem starts a heading row, which we typeset in bold. Assignments ++% have to be global since we are inside the implicit group of an ++% alignment entry. \everycr below resets \everytab so we don't have to + % undo it ourselves. + \def\headitemfont{\b}% for people to use in the template row; not changeable + \def\headitem{% + \checkenv\multitable + \crcr ++ \gdef\headitemcrhook{\nobreak}% attempt to avoid page break after headings + \global\everytab={\bf}% can't use \headitemfont since the parsing differs + \the\everytab % for the first item + }% + % ++% default for tables with no headings. ++\let\headitemcrhook=\relax ++% + % A \tab used to include \hskip1sp. But then the space in a template + % line is not enough. That is bad. So let's go back to just `&' until + % we again encounter the problem the 1sp was intended to solve. +@@ -3892,15 +3982,15 @@ + % + \everycr = {% + \noalign{% +- \global\everytab={}% ++ \global\everytab={}% Reset from possible headitem. + \global\colcount=0 % Reset the column counter. +- % Check for saved footnotes, etc. ++ % ++ % Check for saved footnotes, etc.: + \checkinserts +- % Keeps underfull box messages off when table breaks over pages. +- %\filbreak +- % Maybe so, but it also creates really weird page breaks when the +- % table breaks over pages. Wouldn't \vfil be better? Wait until the +- % problem manifests itself, so it can be fixed for real --karl. ++ % ++ % Perhaps a \nobreak, then reset: ++ \headitemcrhook ++ \global\let\headitemcrhook=\relax + }% + }% + % +@@ -4139,7 +4229,7 @@ + \def\value{\begingroup\makevalueexpandable\valuexxx} + \def\valuexxx#1{\expandablevalue{#1}\endgroup} + { +- \catcode`\- = \active \catcode`\_ = \active ++ \catcode`\-=\active \catcode`\_=\active + % + \gdef\makevalueexpandable{% + \let\value = \expandablevalue +@@ -4148,7 +4238,7 @@ + % ..., but we might end up with active ones in the argument if + % we're called from @code, as @code{@value{foo-bar_}}, though. + % So \let them to their normal equivalents. +- \let-\realdash \let_\normalunderscore ++ \let-\normaldash \let_\normalunderscore + } + } + +@@ -4160,6 +4250,11 @@ + % it will fail (although perhaps we could fix that with sufficient work + % to do a one-level expansion on the result, instead of complete). + % ++% Unfortunately, this has the consequence that when _ is in the *value* ++% of an @set, it does not print properly in the roman fonts (get the cmr ++% dot accent at position 126 instead). No fix comes to mind, and it's ++% been this way since 2003 or earlier, so just ignore it. ++% + \def\expandablevalue#1{% + \expandafter\ifx\csname SET#1\endcsname\relax + {[No value for ``#1'']}% +@@ -4172,7 +4267,8 @@ + % @ifset VAR ... @end ifset reads the `...' iff VAR has been defined + % with @set. + % +-% To get special treatment of `@end ifset,' call \makeond and the redefine. ++% To get the special treatment we need for `@end ifset,' we call ++% \makecond and then redefine. + % + \makecond{ifset} + \def\ifset{\parsearg{\doifset{\let\next=\ifsetfail}}} +@@ -4188,7 +4284,7 @@ + } + \def\ifsetfail{\doignore{ifset}} + +-% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been ++% @ifclear VAR ... @end executes the `...' iff VAR has never been + % defined with @set, or has been undefined with @clear. + % + % The `\else' inside the `\doifset' parameter is a trick to reuse the +@@ -4199,6 +4295,35 @@ + \def\ifclear{\parsearg{\doifset{\else \let\next=\ifclearfail}}} + \def\ifclearfail{\doignore{ifclear}} + ++% @ifcommandisdefined CMD ... @end executes the `...' if CMD (written ++% without the @) is in fact defined. We can only feasibly check at the ++% TeX level, so something like `mathcode' is going to considered ++% defined even though it is not a Texinfo command. ++% ++\makecond{ifcommanddefined} ++\def\ifcommanddefined{\parsearg{\doifcmddefined{\let\next=\ifcmddefinedfail}}} ++% ++\def\doifcmddefined#1#2{{% ++ \makevalueexpandable ++ \let\next=\empty ++ \expandafter\ifx\csname #2\endcsname\relax ++ #1% If not defined, \let\next as above. ++ \fi ++ \expandafter ++ }\next ++} ++\def\ifcmddefinedfail{\doignore{ifcommanddefined}} ++ ++% @ifcommandnotdefined CMD ... handled similar to @ifclear above. ++\makecond{ifcommandnotdefined} ++\def\ifcommandnotdefined{% ++ \parsearg{\doifcmddefined{\else \let\next=\ifcmdnotdefinedfail}}} ++\def\ifcmdnotdefinedfail{\doignore{ifcommandnotdefined}} ++ ++% Set the `txicommandconditionals' variable, so documents have a way to ++% test if the @ifcommand...defined conditionals are available. ++\set txicommandconditionals ++ + % @dircategory CATEGORY -- specify a category of the dir file + % which this file should belong to. Ignore this in TeX. + \let\dircategory=\comment +@@ -4307,7 +4432,7 @@ + % complicated, when \tex is in effect and \{ is a \delimiter again. + % We can't use \lbracecmd and \rbracecmd because texindex assumes + % braces and backslashes are used only as delimiters. Perhaps we +- % should define @lbrace and @rbrace commands a la @comma. ++ % should use @lbracechar and @rbracechar? + \def\{{{\tt\char123}}% + \def\}{{\tt\char125}}% + % +@@ -4328,8 +4453,7 @@ + % @end macro + % ... + % @funindex commtest +- % +- % The above is not enough to reproduce the bug, but it gives the flavor. ++ % This is not enough to reproduce the bug, but it gives the flavor. + % + % Sample whatsit resulting: + % .@write3{\entry{xyz}{@folio }{@code {xyz@endinput }}} +@@ -4435,6 +4559,7 @@ + \definedummyword\guillemetright + \definedummyword\guilsinglleft + \definedummyword\guilsinglright ++ \definedummyword\lbracechar + \definedummyword\leq + \definedummyword\minus + \definedummyword\ogonek +@@ -4447,6 +4572,7 @@ + \definedummyword\quoteleft + \definedummyword\quoteright + \definedummyword\quotesinglbase ++ \definedummyword\rbracechar + \definedummyword\result + \definedummyword\textdegree + % +@@ -4498,6 +4624,7 @@ + \definedummyword\t + % + % Commands that take arguments. ++ \definedummyword\abbr + \definedummyword\acronym + \definedummyword\anchor + \definedummyword\cite +@@ -4509,7 +4636,9 @@ + \definedummyword\emph + \definedummyword\env + \definedummyword\file ++ \definedummyword\image + \definedummyword\indicateurl ++ \definedummyword\inforef + \definedummyword\kbd + \definedummyword\key + \definedummyword\math +@@ -4525,8 +4654,21 @@ + \definedummyword\verb + \definedummyword\w + \definedummyword\xref ++ % ++ % Consider: ++ % @macro mkind{arg1,arg2} ++ % @cindex \arg2\ ++ % @end macro ++ % @mkind{foo, bar} ++ % The space after the comma will end up in the temporary definition ++ % that we make for arg2 (see \parsemargdef ff.). We want all this to be ++ % expanded for the sake of the index, so we end up just seeing "bar". ++ \let\xeatspaces = \eatspaces + } + ++% For testing: output @{ and @} in index sort strings as \{ and \}. ++\newif\ifusebracesinindexes ++ + % \indexnofonts is used when outputting the strings to sort the index + % by, and when constructing control sequence names. It eliminates all + % control sequences and just writes whatever the best ASCII sort string +@@ -4555,8 +4697,16 @@ + % Unfortunately, texindex is not prepared to handle braces in the + % content at all. So for index sorting, we map @{ and @} to strings + % starting with |, since that ASCII character is between ASCII { and }. +- \def\{{|a}% +- \def\}{|b}% ++ \ifusebracesinindexes ++ \def\lbracechar{\lbracecmd}% ++ \def\rbracechar{\rbracecmd}% ++ \else ++ \def\lbracechar{|a}% ++ \def\rbracechar{|b}% ++ \fi ++ \let\{=\lbracechar ++ \let\}=\rbracechar ++ % + % + % Non-English letters. + \def\AA{AA}% +@@ -4732,10 +4882,9 @@ + % + % ..., ready, GO: + % +-\def\safewhatsit#1{% +-\ifhmode ++\def\safewhatsit#1{\ifhmode + #1% +-\else ++ \else + % \lastskip and \lastpenalty cannot both be nonzero simultaneously. + \whatsitskip = \lastskip + \edef\lastskipmacro{\the\lastskip}% +@@ -4759,7 +4908,6 @@ + % to re-insert the same penalty (values >10000 are used for various + % signals); since we just inserted a non-discardable item, any + % following glue (such as a \parskip) would be a breakpoint. For example: +- % + % @deffn deffn-whatever + % @vindex index-whatever + % Description. +@@ -4772,8 +4920,7 @@ + % (the whatsit from the \write), so we must insert a \nobreak. + \nobreak\vskip\whatsitskip + \fi +-\fi +-} ++\fi} + + % The index entry written in the file actually looks like + % \entry {sortstring}{page}{topic} +@@ -5520,14 +5667,6 @@ + + % Define @majorheading, @heading and @subheading + +-% NOTE on use of \vbox for chapter headings, section headings, and such: +-% 1) We use \vbox rather than the earlier \line to permit +-% overlong headings to fold. +-% 2) \hyphenpenalty is set to 10000 because hyphenation in a +-% heading is obnoxious; this forbids it. +-% 3) Likewise, headings look best if no \parindent is used, and +-% if justification is not attempted. Hence \raggedright. +- + \def\majorheading{% + {\advance\chapheadingskip by 10pt \chapbreak }% + \parsearg\chapheadingzzz +@@ -5535,10 +5674,8 @@ + + \def\chapheading{\chapbreak \parsearg\chapheadingzzz} + \def\chapheadingzzz#1{% +- {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 +- \parindent=0pt\ptexraggedright +- \rmisbold #1\hfill}}% +- \bigskip \par\penalty 200\relax ++ \vbox{\chapfonts \raggedtitlesettings #1\par}% ++ \nobreak\bigskip \nobreak + \suppressfirstparagraphindent + } + +@@ -5697,8 +5834,7 @@ + % + % Typeset the actual heading. + \nobreak % Avoid page breaks at the interline glue. +- \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \ptexraggedright +- \hangindent=\wd0 \centerparametersmaybe ++ \vbox{\raggedtitlesettings \hangindent=\wd0 \centerparametersmaybe + \unhbox0 #1\par}% + }% + \nobreak\bigskip % no page break after a chapter title +@@ -5720,18 +5856,18 @@ + \def\setchapterstyle #1 {\csname CHAPF#1\endcsname} + % + \def\unnchfopen #1{% +-\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 +- \parindent=0pt\ptexraggedright +- \rmisbold #1\hfill}}\bigskip \par\nobreak ++ \chapoddpage ++ \vbox{\chapfonts \raggedtitlesettings #1\par}% ++ \nobreak\bigskip\nobreak + } + \def\chfopen #1#2{\chapoddpage {\chapfonts + \vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% + \par\penalty 5000 % + } + \def\centerchfopen #1{% +-\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 +- \parindent=0pt +- \hfill {\rmisbold #1}\hfill}}\bigskip \par\nobreak ++ \chapoddpage ++ \vbox{\chapfonts \raggedtitlesettings \hfill #1\hfill}% ++ \nobreak\bigskip \nobreak + } + \def\CHAPFopen{% + \global\let\chapmacro=\chfopen +@@ -5822,7 +5958,7 @@ + % + % Now the second mark, after the heading break. No break points + % between here and the heading. +- \let\prevsectiondefs=\lastsectiondefs ++ \global\let\prevsectiondefs=\lastsectiondefs + \domark + % + % Only insert the space after the number if we have a section number. +@@ -5876,14 +6012,15 @@ + % + % We'll almost certainly start a paragraph next, so don't let that + % glue accumulate. (Not a breakpoint because it's preceded by a +- % discardable item.) ++ % discardable item.) However, when a paragraph is not started next ++ % (\startdefun, \cartouche, \center, etc.), this needs to be wiped out ++ % or the negative glue will cause weirdly wrong output, typically ++ % obscuring the section heading with something else. + \vskip-\parskip + % +- % This is purely so the last item on the list is a known \penalty > +- % 10000. This is so \startdefun can avoid allowing breakpoints after +- % section headings. Otherwise, it would insert a valid breakpoint between: +- % @section sec-whatever +- % @deffn def-whatever ++ % This is so the last item on the main vertical list is a known ++ % \penalty > 10000, so \startdefun, etc., can recognize the situation ++ % and do the needful. + \penalty 10001 + } + +@@ -6188,8 +6325,8 @@ + \catcode `\|=\other + \catcode `\<=\other + \catcode `\>=\other +- \catcode`\`=\other +- \catcode`\'=\other ++ \catcode `\`=\other ++ \catcode `\'=\other + \escapechar=`\\ + % + % ' is active in math mode (mathcode"8000). So reset it, and all our +@@ -6213,7 +6350,7 @@ + \let\/=\ptexslash + \let\*=\ptexstar + \let\t=\ptext +- \expandafter \let\csname top\endcsname=\ptextop % outer ++ \expandafter \let\csname top\endcsname=\ptextop % we've made it outer + \let\frenchspacing=\plainfrenchspacing + % + \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}% +@@ -6297,13 +6434,11 @@ + % side, and for 6pt waste from + % each corner char, and rule thickness + \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip +- % Flag to tell @lisp, etc., not to narrow margin. +- \let\nonarrowing = t% + % + % If this cartouche directly follows a sectioning command, we need the + % \parskip glue (backspaced over by default) or the cartouche can + % collide with the section heading. +- \ifnum\lastpenalty>10000 \vskip\parskip \fi ++ \ifnum\lastpenalty>10000 \vskip\parskip \penalty\lastpenalty \fi + % + \vbox\bgroup + \baselineskip=0pt\parskip=0pt\lineskip=0pt +@@ -6338,7 +6473,7 @@ + \newdimen\nonfillparindent + \def\nonfillstart{% + \aboveenvbreak +- \hfuzz = 12pt % Don't be fussy ++ \ifdim\hfuzz < 12pt \hfuzz = 12pt \fi % Don't be fussy + \sepspaces % Make spaces be word-separators rather than space tokens. + \let\par = \lisppar % don't ignore blank lines + \obeylines % each line of input is a line of output +@@ -6465,9 +6600,13 @@ + + + % @raggedright does more-or-less normal line breaking but no right +-% justification. From plain.tex. ++% justification. From plain.tex. Don't stretch around special ++% characters in urls in this environment, since the stretch at the right ++% should be enough. + \envdef\raggedright{% +- \rightskip0pt plus2em \spaceskip.3333em \xspaceskip.5em\relax ++ \rightskip0pt plus2.4em \spaceskip.3333em \xspaceskip.5em\relax ++ \def\urefprestretchamount{0pt}% ++ \def\urefpoststretchamount{0pt}% + } + \let\Eraggedright\par + +@@ -6496,16 +6635,9 @@ + \makedispenvdef{quotation}{\quotationstart} + % + \def\quotationstart{% +- {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip +- \parindent=0pt +- % +- % @cartouche defines \nonarrowing to inhibit narrowing at next level down. ++ \indentedblockstart % same as \indentedblock, but increase right margin too. + \ifx\nonarrowing\relax +- \advance\leftskip by \lispnarrowing + \advance\rightskip by \lispnarrowing +- \exdentamount = \lispnarrowing +- \else +- \let\nonarrowing = \relax + \fi + \parsearg\quotationlabel + } +@@ -6531,6 +6663,32 @@ + \fi + } + ++% @indentedblock is like @quotation, but indents only on the left and ++% has no optional argument. ++% ++\makedispenvdef{indentedblock}{\indentedblockstart} ++% ++\def\indentedblockstart{% ++ {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip ++ \parindent=0pt ++ % ++ % @cartouche defines \nonarrowing to inhibit narrowing at next level down. ++ \ifx\nonarrowing\relax ++ \advance\leftskip by \lispnarrowing ++ \exdentamount = \lispnarrowing ++ \else ++ \let\nonarrowing = \relax ++ \fi ++} ++ ++% Keep a nonzero parskip for the environment, since we're doing normal filling. ++% ++\def\Eindentedblock{% ++ \par ++ {\parskip=0pt \afterenvbreak}% ++} ++\def\Esmallindentedblock{\Eindentedblock} ++ + + % LaTeX-like @verbatim...@end verbatim and @verb{...} + % If we want to allow any as delimiter, +@@ -7009,7 +7167,10 @@ + \df \sl \hyphenchar\font=0 + % + % On the other hand, if an argument has two dashes (for instance), we +- % want a way to get ttsl. Let's try @var for that. ++ % want a way to get ttsl. We used to recommend @var for that, so ++ % leave the code in, but it's strange for @var to lead to typewriter. ++ % Nowadays we recommend @code, since the difference between a ttsl hyphen ++ % and a tt hyphen is pretty tiny. @code also disables ?` !`. + \def\var##1{{\setupmarkupstyle{var}\ttslanted{##1}}}% + #1% + \sl\hyphenchar\font=45 +@@ -7338,7 +7499,7 @@ + + % Parse the optional {params} list. Set up \paramno and \paramlist + % so \defmacro knows what to do. Define \macarg.BLAH for each BLAH +-% in the params list to some hook where the argument si to be expanded. If ++% in the params list to some hook where the argument is to be expanded. If + % there are less than 10 arguments that hook is to be replaced by ##N where N + % is the position in that list, that is to say the macro arguments are to be + % defined `a la TeX in the macro body. +@@ -7793,7 +7954,7 @@ + \fi\fi + } + +- ++% + % @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is + % the node name, #2 the name of the Info cross-reference, #3 the printed + % node name, #4 the name of the Info file, #5 the name of the printed +@@ -7803,16 +7964,21 @@ + \def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} + \def\ref#1{\xrefX[#1,,,,,,,]} + % +-\newbox\topbox ++\newbox\toprefbox + \newbox\printedrefnamebox ++\newbox\infofilenamebox + \newbox\printedmanualbox + % + \def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup + \unsepspaces + % ++ % Get args without leading/trailing spaces. + \def\printedrefname{\ignorespaces #3}% + \setbox\printedrefnamebox = \hbox{\printedrefname\unskip}% + % ++ \def\infofilename{\ignorespaces #4}% ++ \setbox\infofilenamebox = \hbox{\infofilename\unskip}% ++ % + \def\printedmanual{\ignorespaces #5}% + \setbox\printedmanualbox = \hbox{\printedmanual\unskip}% + % +@@ -7845,12 +8011,20 @@ + \ifpdf + {\indexnofonts + \turnoffactive ++ \makevalueexpandable + % This expands tokens, so do it after making catcode changes, so _ +- % etc. don't get their TeX definitions. ++ % etc. don't get their TeX definitions. This ignores all spaces in ++ % #4, including (wrongly) those in the middle of the filename. + \getfilename{#4}% + % ++ % This (wrongly) does not take account of leading or trailing ++ % spaces in #1, which should be ignored. + \edef\pdfxrefdest{#1}% +- \txiescapepdf\pdfxrefdest ++ \ifx\pdfxrefdest\empty ++ \def\pdfxrefdest{Top}% no empty targets ++ \else ++ \txiescapepdf\pdfxrefdest % escape PDF special chars ++ \fi + % + \leavevmode + \startlink attr{/Border [0 0 0]}% +@@ -7883,7 +8057,7 @@ + \printedrefname + \fi + % +- % if the user also gave the printed manual name (fifth arg), append ++ % If the user also gave the printed manual name (fifth arg), append + % "in MANUALNAME". + \ifdim \wd\printedmanualbox > 0pt + \space \putwordin{} \cite{\printedmanual}% +@@ -7898,32 +8072,20 @@ + % this is a loss. Therefore, we give the text of the node name + % again, so it is as if TeX is seeing it for the first time. + % +- % Cross-manual reference. Only include the "Section ``foo'' in" if +- % the foo is neither missing or Top. Thus, @xref{,,,foo,The Foo Manual} +- % outputs simply "see The Foo Manual". + \ifdim \wd\printedmanualbox > 0pt +- % What is the 7sp about? The idea is that we also want to omit +- % the Section part if we would be printing "Top", since they are +- % clearly trying to refer to the whole manual. But, this being +- % TeX, we can't easily compare strings while ignoring the possible +- % spaces before and after in the input. By adding the arbitrary +- % 7sp, we make it much less likely that a real node name would +- % happen to have the same width as "Top" (e.g., in a monospaced font). +- % I hope it will never happen in practice. ++ % Cross-manual reference with a printed manual name. + % +- % For the same basic reason, we retypeset the "Top" at every +- % reference, since the current font is indeterminate. ++ \crossmanualxref{\cite{\printedmanual\unskip}}% ++ % ++ \else\ifdim \wd\infofilenamebox > 0pt ++ % Cross-manual reference with only an info filename (arg 4), no ++ % printed manual name (arg 5). This is essentially the same as ++ % the case above; we output the filename, since we have nothing else. + % +- \setbox\topbox = \hbox{Top\kern7sp}% +- \setbox2 = \hbox{\ignorespaces \printedrefname \unskip \kern7sp}% +- \ifdim \wd2 > 7sp +- \ifdim \wd2 = \wd\topbox \else +- \putwordSection{} ``\printedrefname'' \putwordin{}\space +- \fi +- \fi +- \cite{\printedmanual}% ++ \crossmanualxref{\code{\infofilename\unskip}}% ++ % + \else +- % Reference in this manual. ++ % Reference within this manual. + % + % _ (for example) has to be the character _ for the purposes of the + % control sequence corresponding to the node, but it has to expand +@@ -7944,11 +8106,37 @@ + % + % output the `page 3'. + \turnoffactive \putwordpage\tie\refx{#1-pg}{}% +- \fi ++ \fi\fi + \fi + \endlink + \endgroup} + ++% Output a cross-manual xref to #1. Used just above (twice). ++% ++% Only include the text "Section ``foo'' in" if the foo is neither ++% missing or Top. Thus, @xref{,,,foo,The Foo Manual} outputs simply ++% "see The Foo Manual", the idea being to refer to the whole manual. ++% ++% But, this being TeX, we can't easily compare our node name against the ++% string "Top" while ignoring the possible spaces before and after in ++% the input. By adding the arbitrary 7sp below, we make it much less ++% likely that a real node name would have the same width as "Top" (e.g., ++% in a monospaced font). Hopefully it will never happen in practice. ++% ++% For the same basic reason, we retypeset the "Top" at every ++% reference, since the current font is indeterminate. ++% ++\def\crossmanualxref#1{% ++ \setbox\toprefbox = \hbox{Top\kern7sp}% ++ \setbox2 = \hbox{\ignorespaces \printedrefname \unskip \kern7sp}% ++ \ifdim \wd2 > 7sp % nonempty? ++ \ifdim \wd2 = \wd\toprefbox \else % same as Top? ++ \putwordSection{} ``\printedrefname'' \putwordin{}\space ++ \fi ++ \fi ++ #1% ++} ++ + % This macro is called from \xrefX for the `[nodename]' part of xref + % output. It's a separate macro only so it can be changed more easily, + % since square brackets don't work well in some documents. Particularly +@@ -8173,6 +8361,7 @@ + \gdef\footnote{% + \let\indent=\ptexindent + \let\noindent=\ptexnoindent ++ % + \global\advance\footnoteno by \@ne + \edef\thisfootno{$^{\the\footnoteno}$}% + % +@@ -8196,6 +8385,11 @@ + % + \gdef\dofootnote{% + \insert\footins\bgroup ++ % ++ % Nested footnotes are not supported in TeX, that would take a lot ++ % more work. (\startsavinginserts does not suffice.) ++ \let\footnote=\errfootnote ++ % + % We want to typeset this text as a normal paragraph, even if the + % footnote reference occurs in (for example) a display environment. + % So reset some parameters. +@@ -8233,13 +8427,19 @@ + } + }%end \catcode `\@=11 + ++\def\errfootnote{% ++ \errhelp=\EMsimple ++ \errmessage{Nested footnotes not supported in texinfo.tex, ++ even though they work in makeinfo; sorry} ++} ++ + % In case a @footnote appears in a vbox, save the footnote text and create + % the real \insert just after the vbox finished. Otherwise, the insertion + % would be lost. + % Similarly, if a @footnote appears inside an alignment, save the footnote + % text to a box and make the \insert when a row of the table is finished. + % And the same can be done for other insert classes. --kasal, 16nov03. +- ++% + % Replace the \insert primitive by a cheating macro. + % Deeper inside, just make sure that the saved insertions are not spilled + % out prematurely. +@@ -8316,7 +8516,7 @@ + it from ftp://tug.org/tex/epsf.tex.} + % + \def\image#1{% +- \ifx\epsfbox\thisiundefined ++ \ifx\epsfbox\thisisundefined + \ifwarnednoepsf \else + \errhelp = \noepsfhelp + \errmessage{epsf.tex not found, images will be ignored}% +@@ -8340,6 +8540,13 @@ + % If the image is by itself, center it. + \ifvmode + \imagevmodetrue ++ \else \ifx\centersub\centerV ++ % for @center @image, we need a vbox so we can have our vertical space ++ \imagevmodetrue ++ \vbox\bgroup % vbox has better behavior than vtop herev ++ \fi\fi ++ % ++ \ifimagevmode + \nobreak\medskip + % Usually we'll have text after the image which will insert + % \parskip glue, so insert it here too to equalize the space +@@ -8349,9 +8556,13 @@ + \fi + % + % Leave vertical mode so that indentation from an enclosing +- % environment such as @quotation is respected. On the other hand, if +- % it's at the top level, we don't want the normal paragraph indentation. +- \noindent ++ % environment such as @quotation is respected. ++ % However, if we're at the top level, we don't want the ++ % normal paragraph indentation. ++ % On the other hand, if we are in the case of @center @image, we don't ++ % want to start a paragraph, which will create a hsize-width box and ++ % eradicate the centering. ++ \ifx\centersub\centerV\else \noindent \fi + % + % Output the image. + \ifpdf +@@ -8363,7 +8574,10 @@ + \epsfbox{#1.eps}% + \fi + % +- \ifimagevmode \medskip \fi % space after the standalone image ++ \ifimagevmode ++ \medskip % space after a standalone image ++ \fi ++ \ifx\centersub\centerV \egroup \fi + \endgroup} + + +@@ -9793,11 +10007,9 @@ + \catcode`\"=\active + \def\activedoublequote{{\tt\char34}} + \let"=\activedoublequote +-\catcode`\~=\active +-\def~{{\tt\char126}} ++\catcode`\~=\active \def\activetilde{{\tt\char126}} \let~ = \activetilde + \chardef\hat=`\^ +-\catcode`\^=\active +-\def^{{\tt \hat}} ++\catcode`\^=\active \def\activehat{{\tt \hat}} \let^ = \activehat + + \catcode`\_=\active + \def_{\ifusingtt\normalunderscore\_} +@@ -9807,16 +10019,26 @@ + + \catcode`\|=\active + \def|{{\tt\char124}} ++ + \chardef \less=`\< +-\catcode`\<=\active +-\def<{{\tt \less}} ++\catcode`\<=\active \def\activeless{{\tt \less}}\let< = \activeless + \chardef \gtr=`\> +-\catcode`\>=\active +-\def>{{\tt \gtr}} +-\catcode`\+=\active +-\def+{{\tt \char 43}} +-\catcode`\$=\active +-\def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix ++\catcode`\>=\active \def\activegtr{{\tt \gtr}}\let> = \activegtr ++\catcode`\+=\active \def+{{\tt \char 43}} ++\catcode`\$=\active \def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix ++ ++% used for headline/footline in the output routine, in case the page ++% breaks in the middle of an @tex block. ++\def\texinfochars{% ++ \let< = \activeless ++ \let> = \activegtr ++ \let~ = \activetilde ++ \let^ = \activehat ++ \markupsetuplqdefault \markupsetuprqdefault ++ \let\b = \strong ++ \let\i = \smartitalic ++ % in principle, all other definitions in \tex have to be undone too. ++} + + % If a .fmt file is being used, characters that might appear in a file + % name cannot be active until we have parsed the command line. +@@ -9866,22 +10088,26 @@ + @gdef@otherbackslash{@let\=@realbackslash} + + % Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of +-% the literal character `\'. ++% the literal character `\'. Also revert - to its normal character, in ++% case the active - from code has slipped in. + % +-@def@normalturnoffactive{% +- @let"=@normaldoublequote +- @let$=@normaldollar %$ font-lock fix +- @let+=@normalplus +- @let<=@normalless +- @let>=@normalgreater +- @let\=@normalbackslash +- @let^=@normalcaret +- @let_=@normalunderscore +- @let|=@normalverticalbar +- @let~=@normaltilde +- @markupsetuplqdefault +- @markupsetuprqdefault +- @unsepspaces ++{@catcode`- = @active ++ @gdef@normalturnoffactive{% ++ @let-=@normaldash ++ @let"=@normaldoublequote ++ @let$=@normaldollar %$ font-lock fix ++ @let+=@normalplus ++ @let<=@normalless ++ @let>=@normalgreater ++ @let\=@normalbackslash ++ @let^=@normalcaret ++ @let_=@normalunderscore ++ @let|=@normalverticalbar ++ @let~=@normaltilde ++ @markupsetuplqdefault ++ @markupsetuprqdefault ++ @unsepspaces ++ } + } + + % Make _ and + \other characters, temporarily. +diff -urN glibc-2.17-c758a686/manual/threads.texi glibc-2.17-c758a686/manual/threads.texi +--- glibc-2.17-c758a686/manual/threads.texi 1969-12-31 19:00:00.000000000 -0500 ++++ glibc-2.17-c758a686/manual/threads.texi 2014-09-12 16:10:06.042792724 -0400 +@@ -0,0 +1,254 @@ ++@node POSIX Threads ++@c @node POSIX Threads, Internal Probes, Cryptographic Functions, Top ++@chapter POSIX Threads ++@c %MENU% POSIX Threads ++@cindex pthreads ++ ++This chapter describes the @glibcadj{} POSIX Thread implementation. ++ ++@menu ++* Thread-specific Data:: Support for creating and ++ managing thread-specific data ++* Non-POSIX Extensions:: Additional functions to extend ++ POSIX Thread functionality ++@end menu ++ ++@node Thread-specific Data ++@section Thread-specific Data ++ ++The @glibcadj{} implements functions to allow users to create and manage ++data specific to a thread. Such data may be destroyed at thread exit, ++if a destructor is provided. The following functions are defined: ++ ++@comment pthread.h ++@comment POSIX ++@deftypefun int pthread_key_create (pthread_key_t *@var{key}, void (*@var{destructor})(void*)) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c pthread_key_create ok ++@c KEY_UNUSED ok ++@c KEY_USABLE ok ++Create a thread-specific data key for the calling thread, referenced by ++@var{key}. ++ ++Objects declared with the C++11 @code{thread_local} keyword are destroyed ++before thread-specific data, so they should not be used in thread-specific ++data destructors or even as members of the thread-specific data, since the ++latter is passed as an argument to the destructor function. ++@end deftypefun ++ ++@comment pthread.h ++@comment POSIX ++@deftypefun int pthread_key_delete (pthread_key_t @var{key}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c pthread_key_delete ok ++@c This uses atomic compare and exchange to increment the seq number ++@c after testing it's not a KEY_UNUSED seq number. ++@c KEY_UNUSED dup ok ++Destroy the thread-specific data @var{key} in the calling thread. The ++destructor for the thread-specific data is not called during destruction, nor ++is it called during thread exit. ++@end deftypefun ++ ++@comment pthread.h ++@comment POSIX ++@deftypefun void *pthread_getspecific (pthread_key_t @var{key}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c pthread_getspecific ok ++Return the thread-specific data associated with @var{key} in the calling ++thread. ++@end deftypefun ++ ++@comment pthread.h ++@comment POSIX ++@deftypefun int pthread_setspecific (pthread_key_t @var{key}, const void *@var{value}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{}}} ++@c pthread_setspecific @asucorrupt @ascuheap @acucorrupt @acsmem ++@c a level2 block may be allocated by a signal handler after ++@c another call already made a decision to allocate it, thus losing ++@c the allocated value. the seq number is updated before the ++@c value, which might cause an earlier-generation value to seem ++@c current if setspecific is cancelled or interrupted by a signal ++@c KEY_UNUSED ok ++@c calloc dup @ascuheap @acsmem ++Associate the thread-specific @var{value} with @var{key} in the calling thread. ++@end deftypefun ++ ++ ++@node Non-POSIX Extensions ++@section Non-POSIX Extensions ++ ++In addition to implementing the POSIX API for threads, @theglibc{} provides ++additional functions and interfaces to provide functionality not specified in ++the standard. ++ ++@menu ++* Default Thread Attributes:: Setting default attributes for ++ threads in a process. ++@end menu ++ ++@node Default Thread Attributes ++@subsection Setting Process-wide defaults for thread attributes ++ ++@Theglibc{} provides non-standard API functions to set and get the default ++attributes used in the creation of threads in a process. ++ ++@comment pthread.h ++@comment GNU ++@deftypefun int pthread_getattr_default_np (pthread_attr_t *@var{attr}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} ++@c Takes lock around read from default_pthread_attr. ++Get the default attribute values and set @var{attr} to match. This ++function returns @math{0} on success and a non-zero error code on ++failure. ++@end deftypefun ++ ++@comment pthread.h ++@comment GNU ++@deftypefun int pthread_setattr_default_np (pthread_attr_t *@var{attr}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsmem{}}} ++@c pthread_setattr_default_np @ascuheap @asulock @aculock @acsmem ++@c check_sched_policy_attr ok ++@c check_sched_priority_attr ok ++@c sched_get_priority_min dup ok ++@c sched_get_priority_max dup ok ++@c check_cpuset_attr ok ++@c determine_cpumask_size ok ++@c check_stacksize_attr ok ++@c lll_lock @asulock @aculock ++@c free dup @ascuheap @acsmem ++@c realloc dup @ascuheap @acsmem ++@c memcpy dup ok ++@c lll_unlock @asulock @aculock ++Set the default attribute values to match the values in @var{attr}. The ++function returns @math{0} on success and a non-zero error code on failure. ++The following error codes are defined for this function: ++ ++@table @code ++@item EINVAL ++At least one of the values in @var{attr} does not qualify as valid for the ++attributes or the stack address is set in the attribute. ++@item ENOMEM ++The system does not have sufficient memory. ++@end table ++@end deftypefun ++ ++@c FIXME these are undocumented: ++@c pthread_atfork ++@c pthread_attr_destroy ++@c pthread_attr_getaffinity_np ++@c pthread_attr_getdetachstate ++@c pthread_attr_getguardsize ++@c pthread_attr_getinheritsched ++@c pthread_attr_getschedparam ++@c pthread_attr_getschedpolicy ++@c pthread_attr_getscope ++@c pthread_attr_getstack ++@c pthread_attr_getstackaddr ++@c pthread_attr_getstacksize ++@c pthread_attr_init ++@c pthread_attr_setaffinity_np ++@c pthread_attr_setdetachstate ++@c pthread_attr_setguardsize ++@c pthread_attr_setinheritsched ++@c pthread_attr_setschedparam ++@c pthread_attr_setschedpolicy ++@c pthread_attr_setscope ++@c pthread_attr_setstack ++@c pthread_attr_setstackaddr ++@c pthread_attr_setstacksize ++@c pthread_barrierattr_destroy ++@c pthread_barrierattr_getpshared ++@c pthread_barrierattr_init ++@c pthread_barrierattr_setpshared ++@c pthread_barrier_destroy ++@c pthread_barrier_init ++@c pthread_barrier_wait ++@c pthread_cancel ++@c pthread_cleanup_push ++@c pthread_cleanup_pop ++@c pthread_condattr_destroy ++@c pthread_condattr_getclock ++@c pthread_condattr_getpshared ++@c pthread_condattr_init ++@c pthread_condattr_setclock ++@c pthread_condattr_setpshared ++@c pthread_cond_broadcast ++@c pthread_cond_destroy ++@c pthread_cond_init ++@c pthread_cond_signal ++@c pthread_cond_timedwait ++@c pthread_cond_wait ++@c pthread_create ++@c pthread_detach ++@c pthread_equal ++@c pthread_exit ++@c pthread_getaffinity_np ++@c pthread_getattr_np ++@c pthread_getconcurrency ++@c pthread_getcpuclockid ++@c pthread_getname_np ++@c pthread_getschedparam ++@c pthread_join ++@c pthread_kill ++@c pthread_kill_other_threads_np ++@c pthread_mutexattr_destroy ++@c pthread_mutexattr_getkind_np ++@c pthread_mutexattr_getprioceiling ++@c pthread_mutexattr_getprotocol ++@c pthread_mutexattr_getpshared ++@c pthread_mutexattr_getrobust ++@c pthread_mutexattr_getrobust_np ++@c pthread_mutexattr_gettype ++@c pthread_mutexattr_init ++@c pthread_mutexattr_setkind_np ++@c pthread_mutexattr_setprioceiling ++@c pthread_mutexattr_setprotocol ++@c pthread_mutexattr_setpshared ++@c pthread_mutexattr_setrobust ++@c pthread_mutexattr_setrobust_np ++@c pthread_mutexattr_settype ++@c pthread_mutex_consistent ++@c pthread_mutex_consistent_np ++@c pthread_mutex_destroy ++@c pthread_mutex_getprioceiling ++@c pthread_mutex_init ++@c pthread_mutex_lock ++@c pthread_mutex_setprioceiling ++@c pthread_mutex_timedlock ++@c pthread_mutex_trylock ++@c pthread_mutex_unlock ++@c pthread_once ++@c pthread_rwlockattr_destroy ++@c pthread_rwlockattr_getkind_np ++@c pthread_rwlockattr_getpshared ++@c pthread_rwlockattr_init ++@c pthread_rwlockattr_setkind_np ++@c pthread_rwlockattr_setpshared ++@c pthread_rwlock_destroy ++@c pthread_rwlock_init ++@c pthread_rwlock_rdlock ++@c pthread_rwlock_timedrdlock ++@c pthread_rwlock_timedwrlock ++@c pthread_rwlock_tryrdlock ++@c pthread_rwlock_trywrlock ++@c pthread_rwlock_unlock ++@c pthread_rwlock_wrlock ++@c pthread_self ++@c pthread_setaffinity_np ++@c pthread_setcancelstate ++@c pthread_setcanceltype ++@c pthread_setconcurrency ++@c pthread_setname_np ++@c pthread_setschedparam ++@c pthread_setschedprio ++@c pthread_sigmask ++@c pthread_sigqueue ++@c pthread_spin_destroy ++@c pthread_spin_init ++@c pthread_spin_lock ++@c pthread_spin_trylock ++@c pthread_spin_unlock ++@c pthread_testcancel ++@c pthread_timedjoin_np ++@c pthread_tryjoin_np ++@c pthread_yield +diff -urN glibc-2.17-c758a686/manual/time.texi glibc-2.17-c758a686/manual/time.texi +--- glibc-2.17-c758a686/manual/time.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/time.texi 2014-09-12 16:10:06.044792719 -0400 +@@ -79,6 +79,7 @@ + @comment time.h + @comment ISO + @deftypefun double difftime (time_t @var{time1}, time_t @var{time0}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{difftime} function returns the number of seconds of elapsed + time between calendar time @var{time1} and calendar time @var{time0}, as + a value of type @code{double}. The difference ignores leap seconds +@@ -246,6 +247,12 @@ + @comment time.h + @comment ISO + @deftypefun clock_t clock (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c On Hurd, this calls task_info twice and adds user and system time ++@c from both basic and thread time info structs. On generic posix, ++@c calls times and adds utime and stime. On bsd, calls getrusage and ++@c safely converts stime and utime to clock. On linux, calls ++@c clock_gettime. + This function returns the calling process' current CPU time. If the CPU + time is not available or cannot be represented, @code{clock} returns the + value @code{(clock_t)(-1)}. +@@ -310,6 +317,12 @@ + @comment sys/times.h + @comment POSIX.1 + @deftypefun clock_t times (struct tms *@var{buffer}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c On HURD, this calls task_info twice, for basic and thread times info, ++@c adding user and system times into tms, and then gettimeofday, to ++@c compute the real time. On BSD, it calls getclktck, getrusage (twice) ++@c and time. On Linux, it's a syscall with special handling to account ++@c for clock_t counts that look like error values. + The @code{times} function stores the processor time information for + the calling process in @var{buffer}. + +@@ -409,6 +422,7 @@ + @comment time.h + @comment ISO + @deftypefun time_t time (time_t *@var{result}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{time} function returns the current calendar time as a value of + type @code{time_t}. If the argument @var{result} is not a null pointer, + the calendar time value is also stored in @code{*@var{result}}. If the +@@ -420,7 +434,9 @@ + @c Linux. + @comment time.h + @comment SVID, XPG +-@deftypefun int stime (time_t *@var{newtime}) ++@deftypefun int stime (const time_t *@var{newtime}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c On unix, this is implemented in terms of settimeofday. + @code{stime} sets the system clock, i.e., it tells the system that the + current calendar time is @var{newtime}, where @code{newtime} is + interpreted as described in the above definition of @code{time_t}. +@@ -475,6 +491,12 @@ + @comment sys/time.h + @comment BSD + @deftypefun int gettimeofday (struct timeval *@var{tp}, struct timezone *@var{tzp}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c On most GNU/Linux systems this is a direct syscall, but the posix/ ++@c implementation (not used on GNU/Linux or GNU/Hurd) relies on time and ++@c localtime_r, saving and restoring tzname in an unsafe manner. ++@c On some GNU/Linux variants, ifunc resolvers are used in shared libc ++@c for vdso resolution. ifunc-vdso-revisit. + The @code{gettimeofday} function returns the current calendar time as + the elapsed time since the epoch in the @code{struct timeval} structure + indicated by @var{tp}. (@pxref{Elapsed Time} for a description of +@@ -498,6 +520,9 @@ + @comment sys/time.h + @comment BSD + @deftypefun int settimeofday (const struct timeval *@var{tp}, const struct timezone *@var{tzp}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c On HURD, it calls host_set_time with a privileged port. On other ++@c unix systems, it's a syscall. + The @code{settimeofday} function sets the current calendar time in the + system clock according to the arguments. As for @code{gettimeofday}, + the calendar time is represented as the elapsed time since the epoch. +@@ -539,6 +564,10 @@ + @comment sys/time.h + @comment BSD + @deftypefun int adjtime (const struct timeval *@var{delta}, struct timeval *@var{olddelta}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c On hurd and mach, call host_adjust_time with a privileged port. On ++@c Linux, it's implemented in terms of adjtimex. On other unixen, it's ++@c a syscall. + This function speeds up or slows down the system clock in order to make + a gradual adjustment. This ensures that the calendar time reported by + the system clock is always monotonically increasing, which might not +@@ -577,6 +606,8 @@ + @comment sys/timex.h + @comment GNU + @deftypefun int adjtimex (struct timex *@var{timex}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c It's a syscall, only available on linux. + + @code{adjtimex} is functionally identical to @code{ntp_adjtime}. + @xref{High Accuracy Clock}. +@@ -674,6 +705,10 @@ + @comment time.h + @comment ISO + @deftypefun {struct tm *} localtime (const time_t *@var{time}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:tmbuf} @mtsenv{} @mtslocale{}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsmem{} @acsfd{}}} ++@c Calls tz_convert with a static buffer. ++@c localtime @mtasurace:tmbuf @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c tz_convert dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd + The @code{localtime} function converts the simple time pointed to by + @var{time} to broken-down time representation, expressed relative to the + user's specified time zone. +@@ -687,9 +722,8 @@ + as a broken-down time; typically this is because the year cannot fit into + an @code{int}. + +-Calling @code{localtime} has one other effect: it sets the variable +-@code{tzname} with information about the current time zone. @xref{Time +-Zone Functions}. ++Calling @code{localtime} also sets the current time zone as if ++@code{tzset} were called. @xref{Time Zone Functions}. + @end deftypefun + + Using the @code{localtime} function is a big problem in multi-threaded +@@ -699,6 +733,87 @@ + @comment time.h + @comment POSIX.1c + @deftypefun {struct tm *} localtime_r (const time_t *@var{time}, struct tm *@var{resultp}) ++@safety{@prelim{}@mtsafe{@mtsenv{} @mtslocale{}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsmem{} @acsfd{}}} ++@c localtime_r @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c tz_convert(use_localtime) @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c libc_lock_lock dup @asulock @aculock ++@c tzset_internal @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c always called with tzset_lock held ++@c sets static is_initialized before initialization; ++@c reads and sets old_tz; sets tz_rules. ++@c some of the issues only apply on the first call. ++@c subsequent calls only trigger these when called by localtime; ++@c otherwise, they're ok. ++@c getenv dup @mtsenv ++@c strcmp dup ok ++@c strdup @ascuheap ++@c tzfile_read @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c memcmp dup ok ++@c strstr dup ok ++@c getenv dup @mtsenv ++@c asprintf dup @mtslocale @ascuheap @acsmem ++@c stat64 dup ok ++@c fopen dup @ascuheap @asulock @acsmem @acsfd @aculock ++@c fileno dup ok ++@c fstat64 dup ok ++@c fclose dup @ascuheap @asulock @aculock @acsmem @acsfd ++@c free dup @ascuheap @acsmem ++@c fsetlocking dup ok [no @mtasurace:stream @asulock, exclusive] ++@c fread_unlocked dup ok [no @mtasurace:stream @asucorrupt @acucorrupt] ++@c memcpy dup ok ++@c decode ok ++@c bswap_32 dup ok ++@c fseek dup ok [no @mtasurace:stream @asucorrupt @acucorrupt] ++@c ftello dup ok [no @mtasurace:stream @asucorrupt @acucorrupt] ++@c malloc dup @ascuheap @acsmem ++@c decode64 ok ++@c bswap_64 dup ok ++@c getc_unlocked ok [no @mtasurace:stream @asucorrupt @acucorrupt] ++@c tzstring dup @ascuheap @acsmem ++@c compute_tzname_max dup ok [guarded by tzset_lock] ++@c memset dup ok ++@c update_vars ok [guarded by tzset_lock] ++@c sets daylight, timezone, tzname and tzname_cur_max; ++@c called only with tzset_lock held, unless tzset_parse_tz ++@c (internal, but not static) gets called by users; given the its ++@c double-underscore-prefixed name, this interface violation could ++@c be regarded as undefined behavior. ++@c strlen ok ++@c tzset_parse_tz @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c sscanf dup @mtslocale @ascuheap @acsmem ++@c isalnum dup @mtsenv ++@c tzstring @ascuheap @acsmem ++@c reads and changes tzstring_list without synchronization, but ++@c only called with tzset_lock held (save for interface violations) ++@c strlen dup ok ++@c malloc dup @ascuheap @acsmem ++@c strcpy dup ok ++@c isdigit dup @mtslocale ++@c compute_offset ok ++@c tzfile_default @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c sets tzname, timezone, types, zone_names, rule_*off, etc; no guards ++@c strlen dup ok ++@c tzfile_read dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c mempcpy dup ok ++@c compute_tzname_max ok [if guarded by tzset_lock] ++@c iterates over zone_names; no guards ++@c free dup @ascuheap @acsmem ++@c strtoul dup @mtslocale ++@c update_vars dup ok ++@c tzfile_compute(use_localtime) @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c sets tzname; no guards. with !use_localtime, as in gmtime, it's ok ++@c tzstring dup @acsuheap @acsmem ++@c tzset_parse_tz dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c offtime dup ok ++@c tz_compute dup ok ++@c strcmp dup ok ++@c offtime ok ++@c isleap dup ok ++@c tz_compute ok ++@c compute_change ok ++@c isleap ok ++@c libc_lock_unlock dup @aculock ++ + The @code{localtime_r} function works just like the @code{localtime} + function. It takes a pointer to a variable containing a simple time + and converts it to the broken-down time format. +@@ -715,6 +830,9 @@ + @comment time.h + @comment ISO + @deftypefun {struct tm *} gmtime (const time_t *@var{time}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:tmbuf} @mtsenv{} @mtslocale{}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsmem{} @acsfd{}}} ++@c gmtime @mtasurace:tmbuf @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c tz_convert dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd + This function is similar to @code{localtime}, except that the broken-down + time is expressed as Coordinated Universal Time (UTC) (formerly called + Greenwich Mean Time (GMT)) rather than relative to a local time zone. +@@ -728,6 +846,15 @@ + @comment time.h + @comment POSIX.1c + @deftypefun {struct tm *} gmtime_r (const time_t *@var{time}, struct tm *@var{resultp}) ++@safety{@prelim{}@mtsafe{@mtsenv{} @mtslocale{}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsmem{} @acsfd{}}} ++@c You'd think tz_convert could avoid some safety issues with ++@c !use_localtime, but no such luck: tzset_internal will always bring ++@c about all possible AS and AC problems when it's first called. ++@c Calling any of localtime,gmtime_r once would run the initialization ++@c and avoid the heap, mem and fd issues in gmtime* in subsequent calls, ++@c but the unsafe locking would remain. ++@c gmtime_r @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c tz_convert(gmtime_r) dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd + This function is similar to @code{localtime_r}, except that it converts + just like @code{gmtime} the given time as Coordinated Universal Time. + +@@ -739,30 +866,58 @@ + @comment time.h + @comment ISO + @deftypefun time_t mktime (struct tm *@var{brokentime}) +-The @code{mktime} function is used to convert a broken-down time structure +-to a simple time representation. It also ``normalizes'' the contents of +-the broken-down time structure, by filling in the day of week and day of +-year based on the other date and time components. ++@safety{@prelim{}@mtsafe{@mtsenv{} @mtslocale{}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsmem{} @acsfd{}}} ++@c mktime @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c passes a static localtime_offset to mktime_internal; it is read ++@c once, used as an initial guess, and updated at the end, but not ++@c used except as a guess for subsequent calls, so it should be safe. ++@c Even though a compiler might delay the load and perform it multiple ++@c times (bug 16346), there are at least two unconditional uses of the ++@c auto variable in which the first load is stored, separated by a ++@c call to an external function, and a conditional change of the ++@c variable before the external call, so refraining from allocating a ++@c local variable at the first load would be a very bad optimization. ++@c tzset dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c mktime_internal(localtime_r) @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c ydhms_diff ok ++@c ranged_convert(localtime_r) @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c *convert = localtime_r dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c time_t_avg dup ok ++@c guess_time_tm dup ok ++@c ydhms_diff dup ok ++@c time_t_add_ok ok ++@c time_t_avg ok ++@c isdst_differ ok ++@c time_t_int_add_ok ok ++The @code{mktime} function converts a broken-down time structure to a ++simple time representation. It also normalizes the contents of the ++broken-down time structure, and fills in some components based on the ++values of the others. + + The @code{mktime} function ignores the specified contents of the +-@code{tm_wday} and @code{tm_yday} members of the broken-down time ++@code{tm_wday}, @code{tm_yday}, @code{tm_gmtoff}, and @code{tm_zone} ++members of the broken-down time + structure. It uses the values of the other components to determine the + calendar time; it's permissible for these components to have + unnormalized values outside their normal ranges. The last thing that + @code{mktime} does is adjust the components of the @var{brokentime} +-structure (including the @code{tm_wday} and @code{tm_yday}). ++structure, including the members that were initially ignored. + + If the specified broken-down time cannot be represented as a simple time, + @code{mktime} returns a value of @code{(time_t)(-1)} and does not modify + the contents of @var{brokentime}. + +-Calling @code{mktime} also sets the variable @code{tzname} with +-information about the current time zone. @xref{Time Zone Functions}. ++Calling @code{mktime} also sets the current time zone as if ++@code{tzset} were called; @code{mktime} uses this information instead ++of @var{brokentime}'s initial @code{tm_gmtoff} and @code{tm_zone} ++members. @xref{Time Zone Functions}. + @end deftypefun + + @comment time.h + @comment ??? + @deftypefun time_t timelocal (struct tm *@var{brokentime}) ++@safety{@prelim{}@mtsafe{@mtsenv{} @mtslocale{}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsmem{} @acsfd{}}} ++@c Alias to mktime. + + @code{timelocal} is functionally identical to @code{mktime}, but more + mnemonically named. Note that it is the inverse of the @code{localtime} +@@ -776,6 +931,19 @@ + @comment time.h + @comment ??? + @deftypefun time_t timegm (struct tm *@var{brokentime}) ++@safety{@prelim{}@mtsafe{@mtsenv{} @mtslocale{}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsmem{} @acsfd{}}} ++@c timegm @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c gmtime_offset triggers the same caveats as localtime_offset in mktime. ++@c although gmtime_r, as called by mktime, might save some issues, ++@c tzset calls tzset_internal with always, which forces ++@c reinitialization, so all issues may arise. ++@c tzset dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c mktime_internal(gmtime_r) @asulock @aculock ++@c ..gmtime_r @asulock @aculock ++@c ... dup ok ++@c tz_convert(!use_localtime) @asulock @aculock ++@c ... dup @asulock @aculock ++@c tzfile_compute(!use_localtime) ok + + @code{timegm} is functionally identical to @code{mktime} except it + always takes the input values to be Coordinated Universal Time (UTC) +@@ -837,6 +1005,8 @@ + @comment sys/timex.h + @comment GNU + @deftypefun int ntp_gettime (struct ntptimeval *@var{tptr}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Wrapper for adjtimex. + The @code{ntp_gettime} function sets the structure pointed to by + @var{tptr} to current values. The elements of the structure afterwards + contain the values the timer implementation in the kernel assumes. They +@@ -954,6 +1124,8 @@ + @comment sys/timex.h + @comment GNU + @deftypefun int ntp_adjtime (struct timex *@var{tptr}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Alias to adjtimex syscall. + The @code{ntp_adjtime} function sets the structure specified by + @var{tptr} to current values. + +@@ -1008,6 +1180,13 @@ + @comment time.h + @comment ISO + @deftypefun {char *} asctime (const struct tm *@var{brokentime}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:asctime} @mtslocale{}}@asunsafe{}@acsafe{}} ++@c asctime @mtasurace:asctime @mtslocale ++@c Uses a static buffer. ++@c asctime_internal @mtslocale ++@c snprintf dup @mtslocale [no @acsuheap @acsmem] ++@c ab_day_name @mtslocale ++@c ab_month_name @mtslocale + The @code{asctime} function converts the broken-down time value that + @var{brokentime} points to into a string in a standard format: + +@@ -1031,6 +1210,9 @@ + @comment time.h + @comment POSIX.1c + @deftypefun {char *} asctime_r (const struct tm *@var{brokentime}, char *@var{buffer}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@assafe{}@acsafe{}} ++@c asctime_r @mtslocale ++@c asctime_internal dup @mtslocale + This function is similar to @code{asctime} but instead of placing the + result in a static buffer it writes the string in the buffer pointed to + by the parameter @var{buffer}. This buffer should have room +@@ -1045,6 +1227,10 @@ + @comment time.h + @comment ISO + @deftypefun {char *} ctime (const time_t *@var{time}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:tmbuf} @mtasurace{:asctime} @mtsenv{} @mtslocale{}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsmem{} @acsfd{}}} ++@c ctime @mtasurace:tmbuf @mtasurace:asctime @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c localtime dup @mtasurace:tmbuf @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c asctime dup @mtasurace:asctime @mtslocale + The @code{ctime} function is similar to @code{asctime}, except that you + specify the calendar time argument as a @code{time_t} simple time value + rather than in broken-down local time format. It is equivalent to +@@ -1053,13 +1239,17 @@ + asctime (localtime (@var{time})) + @end smallexample + +-@code{ctime} sets the variable @code{tzname}, because @code{localtime} +-does so. @xref{Time Zone Functions}. ++Calling @code{ctime} also sets the current time zone as if ++@code{tzset} were called. @xref{Time Zone Functions}. + @end deftypefun + + @comment time.h + @comment POSIX.1c + @deftypefun {char *} ctime_r (const time_t *@var{time}, char *@var{buffer}) ++@safety{@prelim{}@mtsafe{@mtsenv{} @mtslocale{}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsmem{} @acsfd{}}} ++@c ctime_r @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c localtime_r dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c asctime_r dup @mtslocale + This function is similar to @code{ctime}, but places the result in the + string pointed to by @var{buffer}. It is equivalent to (written using + gcc extensions, @pxref{Statement Exprs,,,gcc,Porting and Using gcc}): +@@ -1077,17 +1267,75 @@ + @comment time.h + @comment ISO + @deftypefun size_t strftime (char *@var{s}, size_t @var{size}, const char *@var{template}, const struct tm *@var{brokentime}) ++@safety{@prelim{}@mtsafe{@mtsenv{} @mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} ++@c strftime @mtsenv @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c strftime_l @mtsenv @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c strftime_internal @mtsenv @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c add ok ++@c memset_zero dup ok ++@c memset_space dup ok ++@c strlen dup ok ++@c mbrlen @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd [no @mtasurace:mbstate/!ps] ++@c mbsinit dup ok ++@c cpy ok ++@c add dup ok ++@c memcpy_lowcase ok ++@c TOLOWER ok ++@c tolower_l ok ++@c memcpy_uppcase ok ++@c TOUPPER ok ++@c toupper_l ok ++@c MEMCPY ok ++@c memcpy dup ok ++@c ISDIGIT ok ++@c STRLEN ok ++@c strlen dup ok ++@c strftime_internal dup @mtsenv @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c TOUPPER dup ok ++@c nl_get_era_entry @ascuheap @asulock @acsmem @aculock ++@c nl_init_era_entries @ascuheap @asulock @acsmem @aculock ++@c libc_rwlock_wrlock dup @asulock @aculock ++@c malloc dup @ascuheap @acsmem ++@c memset dup ok ++@c free dup @ascuheap @acsmem ++@c realloc dup @ascuheap @acsmem ++@c memcpy dup ok ++@c strchr dup ok ++@c wcschr dup ok ++@c libc_rwlock_unlock dup @asulock @aculock ++@c ERA_DATE_CMP ok ++@c DO_NUMBER ok ++@c DO_NUMBER_SPACEPAD ok ++@c nl_get_alt_digit @ascuheap @asulock @acsmem @aculock ++@c libc_rwlock_wrlock dup @asulock @aculock ++@c nl_init_alt_digit @ascuheap @acsmem ++@c malloc dup @ascuheap @acsmem ++@c memset dup ok ++@c strchr dup ok ++@c libc_rwlock_unlock dup @aculock ++@c memset_space ok ++@c memset dup ok ++@c memset_zero ok ++@c memset dup ok ++@c mktime dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c iso_week_days ok ++@c isleap ok ++@c tzset dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c localtime_r dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c gmtime_r dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c tm_diff ok + This function is similar to the @code{sprintf} function (@pxref{Formatted + Input}), but the conversion specifications that can appear in the format + template @var{template} are specialized for printing components of the date + and time @var{brokentime} according to the locale currently specified for +-time conversion (@pxref{Locales}). ++time conversion (@pxref{Locales}) and the current time zone ++(@pxref{Time Zone Functions}). + + Ordinary characters appearing in the @var{template} are copied to the + output string @var{s}; this can include multibyte character sequences. + Conversion specifiers are introduced by a @samp{%} character, followed + by an optional flag which can be one of the following. These flags +-are all GNU extensions. The first three affect only the output of ++are all GNU extensions. The first three affect only the output of + numbers: + + @table @code +@@ -1392,9 +1640,10 @@ + If @var{s} is a null pointer, @code{strftime} does not actually write + anything, but instead returns the number of characters it would have written. + +-According to POSIX.1 every call to @code{strftime} implies a call to +-@code{tzset}. So the contents of the environment variable @code{TZ} +-is examined before any output is produced. ++Calling @code{strftime} also sets the current time zone as if ++@code{tzset} were called; @code{strftime} uses this information ++instead of @var{brokentime}'s @code{tm_gmtoff} and @code{tm_zone} ++members. @xref{Time Zone Functions}. + + For an example of @code{strftime}, see @ref{Time Functions Example}. + @end deftypefun +@@ -1402,6 +1651,53 @@ + @comment time.h + @comment ISO/Amend1 + @deftypefun size_t wcsftime (wchar_t *@var{s}, size_t @var{size}, const wchar_t *@var{template}, const struct tm *@var{brokentime}) ++@safety{@prelim{}@mtsafe{@mtsenv{} @mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{} @asulock{} @ascudlopen{}}@acunsafe{@acucorrupt{} @aculock{} @acsmem{} @acsfd{}}} ++@c wcsftime @mtsenv @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c wcsftime_l @mtsenv @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c wcsftime_internal @mtsenv @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c add ok ++@c memset_zero dup ok ++@c memset_space dup ok ++@c wcslen dup ok ++@c cpy ok ++@c add dup ok ++@c memcpy_lowcase ok ++@c TOLOWER ok ++@c towlower_l dup ok ++@c memcpy_uppcase ok ++@c TOUPPER ok ++@c towupper_l dup ok ++@c MEMCPY ok ++@c wmemcpy dup ok ++@c widen @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c memset dup ok ++@c mbsrtowcs_l @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd [no @mtasurace:mbstate/!ps] ++@c ISDIGIT ok ++@c STRLEN ok ++@c wcslen dup ok ++@c wcsftime_internal dup @mtsenv @mtslocale @asucorrupt @ascuheap @asulock @ascudlopen @acucorrupt @aculock @acsmem @acsfd ++@c TOUPPER dup ok ++@c nl_get_era_entry dup @ascuheap @asulock @acsmem @aculock ++@c DO_NUMBER ok ++@c DO_NUMBER_SPACEPAD ok ++@c nl_get_walt_digit dup @ascuheap @asulock @acsmem @aculock ++@c libc_rwlock_wrlock dup @asulock @aculock ++@c nl_init_alt_digit dup @ascuheap @acsmem ++@c malloc dup @ascuheap @acsmem ++@c memset dup ok ++@c wcschr dup ok ++@c libc_rwlock_unlock dup @aculock ++@c memset_space ok ++@c wmemset dup ok ++@c memset_zero ok ++@c wmemset dup ok ++@c mktime dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c iso_week_days ok ++@c isleap ok ++@c tzset dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c localtime_r dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c gmtime_r dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c tm_diff ok + The @code{wcsftime} function is equivalent to the @code{strftime} + function with the difference that it operates on wide character + strings. The buffer where the result is stored, pointed to by @var{s}, +@@ -1452,6 +1748,32 @@ + @comment time.h + @comment XPG4 + @deftypefun {char *} strptime (const char *@var{s}, const char *@var{fmt}, struct tm *@var{tp}) ++@safety{@prelim{}@mtsafe{@mtsenv{} @mtslocale{}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsmem{} @acsfd{}}} ++@c strptime @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c strptime_internal @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c memset dup ok ++@c ISSPACE ok ++@c isspace_l dup ok ++@c match_char ok ++@c match_string ok ++@c strlen dup ok ++@c strncasecmp_l dup ok ++@c strcmp dup ok ++@c recursive @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c strptime_internal dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c get_number ok ++@c ISSPACE dup ok ++@c localtime_r dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c nl_select_era_entry @ascuheap @asulock @acsmem @aculock ++@c nl_init_era_entries dup @ascuheap @asulock @acsmem @aculock ++@c get_alt_number dup @ascuheap @asulock @acsmem @aculock ++@c nl_parse_alt_digit dup @ascuheap @asulock @acsmem @aculock ++@c libc_rwlock_wrlock dup @asulock @aculock ++@c nl_init_alt_digit dup @ascuheap @acsmem ++@c libc_rwlock_unlock dup @aculock ++@c get_number dup ok ++@c day_of_the_week ok ++@c day_of_the_year ok + The @code{strptime} function parses the input string @var{s} according + to the format string @var{fmt} and stores its results in the + structure @var{tp}. +@@ -1865,6 +2187,9 @@ + @comment time.h + @comment Unix98 + @deftypefun {struct tm *} getdate (const char *@var{string}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:getdate} @mtsenv{} @mtslocale{}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsmem{} @acsfd{}}} ++@c getdate @mtasurace:getdate @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c getdate_r dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd + The interface to @code{getdate} is the simplest possible for a function + to parse a string and return the value. @var{string} is the input + string and the result is returned in a statically-allocated variable. +@@ -1976,6 +2301,30 @@ + @comment time.h + @comment GNU + @deftypefun int getdate_r (const char *@var{string}, struct tm *@var{tp}) ++@safety{@prelim{}@mtsafe{@mtsenv{} @mtslocale{}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsmem{} @acsfd{}}} ++@c getdate_r @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c getenv dup @mtsenv ++@c stat64 dup ok ++@c access dup ok ++@c fopen dup @ascuheap @asulock @acsmem @acsfd @aculock ++@c fsetlocking dup ok [no @mtasurace:stream @asulock, exclusive] ++@c isspace dup @mtslocale ++@c strlen dup ok ++@c malloc dup @ascuheap @acsmem ++@c fclose dup @ascuheap @asulock @aculock @acsmem @acsfd ++@c memcpy dup ok ++@c getline dup @ascuheap @acsmem [no @asucorrupt @aculock @acucorrupt, exclusive] ++@c strptime dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c feof_unlocked dup ok ++@c free dup @ascuheap @acsmem ++@c ferror_unlocked dup dup ok ++@c time dup ok ++@c localtime_r dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c first_wday @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c memset dup ok ++@c mktime dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c check_mday ok ++@c mktime dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd + The @code{getdate_r} function is the reentrant counterpart of + @code{getdate}. It does not use the global variable @code{getdate_err} + to signal an error, but instead returns an error code. The same error +@@ -2037,7 +2386,7 @@ + [@code{+}|@code{-}]@var{hh}[@code{:}@var{mm}[@code{:}@var{ss}]]. This + is positive if the local time zone is west of the Prime Meridian and + negative if it is east. The hour must be between @code{0} and +-@code{23}, and the minute and seconds between @code{0} and @code{59}. ++@code{24}, and the minute and seconds between @code{0} and @code{59}. + + For example, here is how we would specify Eastern Standard Time, but + without any Daylight Saving Time alternative: +@@ -2082,17 +2431,51 @@ + + The @var{time} fields specify when, in the local time currently in + effect, the change to the other time occurs. If omitted, the default is +-@code{02:00:00}. +- +-For example, here is how you would specify the Eastern time zone in the +-United States, including the appropriate Daylight Saving Time and its dates +-of applicability. The normal offset from UTC is 5 hours; since this is ++@code{02:00:00}. The hours part of the time fields can range from ++@minus{}167 through 167; this is an extension to POSIX.1, which allows ++only the range 0 through 24. ++ ++Here are some example @code{TZ} values, including the appropriate ++Daylight Saving Time and its dates of applicability. In North ++American Eastern Standard Time (EST) and Eastern Daylight Time (EDT), ++the normal offset from UTC is 5 hours; since this is + west of the prime meridian, the sign is positive. Summer time begins on +-the first Sunday in April at 2:00am, and ends on the last Sunday in October ++March's second Sunday at 2:00am, and ends on November's first Sunday + at 2:00am. + + @smallexample +-EST+5EDT,M4.1.0/2,M10.5.0/2 ++EST+5EDT,M3.2.0/2,M11.1.0/2 ++@end smallexample ++ ++Israel Standard Time (IST) and Israel Daylight Time (IDT) are 2 hours ++ahead of the prime meridian in winter, springing forward an hour on ++March's fourth Thursday at 26:00 (i.e., 02:00 on the first Friday on or ++after March 23), and falling back on October's last Sunday at 02:00. ++ ++@smallexample ++IST-2IDT,M3.4.4/26,M10.5.0 ++@end smallexample ++ ++Western Argentina Summer Time (WARST) is 3 hours behind the prime ++meridian all year. There is a dummy fall-back transition on December ++31 at 25:00 daylight saving time (i.e., 24:00 standard time, ++equivalent to January 1 at 00:00 standard time), and a simultaneous ++spring-forward transition on January 1 at 00:00 standard time, so ++daylight saving time is in effect all year and the initial @code{WART} ++is a placeholder. ++ ++@smallexample ++WART4WARST,J1/0,J365/25 ++@end smallexample ++ ++Western Greenland Time (WGT) and Western Greenland Summer Time (WGST) ++are 3 hours behind UTC in the winter. Its clocks follow the European ++Union rules of springing forward by one hour on March's last Sunday at ++01:00 UTC (@minus{}02:00 local time) and falling back on October's ++last Sunday at 01:00 UTC (@minus{}01:00 local time). ++ ++@smallexample ++WGT3WGST,M3.5.0/-2,M10.5.0/-1 + @end smallexample + + The schedule of Daylight Saving Time in any particular jurisdiction has +@@ -2177,6 +2560,11 @@ + @comment time.h + @comment POSIX.1 + @deftypefun void tzset (void) ++@safety{@prelim{}@mtsafe{@mtsenv{} @mtslocale{}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsmem{} @acsfd{}}} ++@c tzset @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c libc_lock_lock dup @asulock @aculock ++@c tzset_internal dup @mtsenv @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c libc_lock_unlock dup @aculock + The @code{tzset} function initializes the @code{tzname} variable from + the value of the @code{TZ} environment variable. It is not usually + necessary for your program to call this function, because it is called +@@ -2314,7 +2702,16 @@ + + @comment sys/time.h + @comment BSD +-@deftypefun int setitimer (int @var{which}, struct itimerval *@var{new}, struct itimerval *@var{old}) ++@deftypefun int setitimer (int @var{which}, const struct itimerval *@var{new}, struct itimerval *@var{old}) ++@safety{@prelim{}@mtsafe{@mtstimer{}}@assafe{}@acsafe{}} ++@c This function is marked with @mtstimer because the same set of timers ++@c is shared by all threads of a process, so calling it in one thread ++@c may interfere with timers set by another thread. This interference ++@c is not regarded as destructive, because the interface specification ++@c makes this overriding while returning the previous value the expected ++@c behavior, and the kernel will serialize concurrent calls so that the ++@c last one prevails, with each call getting the timer information from ++@c the timer installed by the previous call in that serialization. + The @code{setitimer} function sets the timer specified by @var{which} + according to @var{new}. The @var{which} argument can have a value of + @code{ITIMER_REAL}, @code{ITIMER_VIRTUAL}, or @code{ITIMER_PROF}. +@@ -2335,6 +2732,7 @@ + @comment sys/time.h + @comment BSD + @deftypefun int getitimer (int @var{which}, struct itimerval *@var{old}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{getitimer} function stores information about the timer specified + by @var{which} in the structure pointed at by @var{old}. + +@@ -2367,6 +2765,8 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun {unsigned int} alarm (unsigned int @var{seconds}) ++@safety{@prelim{}@mtsafe{@mtstimer{}}@assafe{}@acsafe{}} ++@c Wrapper for setitimer. + The @code{alarm} function sets the real-time timer to expire in + @var{seconds} seconds. If you want to cancel any existing alarm, you + can do this by calling @code{alarm} with a @var{seconds} argument of +@@ -2426,6 +2826,10 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun {unsigned int} sleep (unsigned int @var{seconds}) ++@safety{@prelim{}@mtunsafe{@mtascusig{:SIGCHLD/linux}}@asunsafe{}@acunsafe{}} ++@c On Mach, it uses ports and calls time. On generic posix, it calls ++@c nanosleep. On Linux, it temporarily blocks SIGCHLD, which is MT- and ++@c AS-Unsafe, and in a way that makes it AC-Unsafe (C-unsafe, even!). + The @code{sleep} function waits for @var{seconds} or until a signal + is delivered, whichever happens first. + +@@ -2470,6 +2874,9 @@ + @comment time.h + @comment POSIX.1 + @deftypefun int nanosleep (const struct timespec *@var{requested_time}, struct timespec *@var{remaining}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c On Linux, it's a syscall. On Mach, it calls gettimeofday and uses ++@c ports. + If resolution to seconds is not enough the @code{nanosleep} function can + be used. As the name suggests the sleep interval can be specified in + nanoseconds. The actual elapsed time of the sleep interval might be +diff -urN glibc-2.17-c758a686/manual/tsort.awk glibc-2.17-c758a686/manual/tsort.awk +--- glibc-2.17-c758a686/manual/tsort.awk 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/tsort.awk 2014-09-12 16:10:06.043792722 -0400 +@@ -1,6 +1,6 @@ + #! /usr/bin/awk -f + # Generate topologically sorted list of manual chapters. +-# (C) Copyright 1998, 1999 Free Software Foundation, Inc. ++# Copyright (C) 1998-2014 Free Software Foundation, Inc. + # Written by Ulrich Drepper , 1998. + + BEGIN { +diff -urN glibc-2.17-c758a686/manual/users.texi glibc-2.17-c758a686/manual/users.texi +--- glibc-2.17-c758a686/manual/users.texi 2012-12-24 22:02:13.000000000 -0500 ++++ glibc-2.17-c758a686/manual/users.texi 2014-09-12 16:10:06.043792722 -0400 +@@ -71,7 +71,7 @@ + @cindex group ID + Users are classified in @dfn{groups}. Each user name belongs to one + @dfn{default group} and may also belong to any number of +-@dfn{supplementary groups}. Users who are members of the same group can ++@dfn{supplementary groups}. Users who are members of the same group can + share resources (such as files) that are not accessible to users who are + not a member of that group. Each group has a @dfn{group name} and + @dfn{group ID}. @xref{Group Database}, for how to find information +@@ -221,30 +221,37 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun uid_t getuid (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++@c Atomic syscall, except on hurd, where it takes a lock within a hurd ++@c critical section. + The @code{getuid} function returns the real user ID of the process. + @end deftypefun + + @comment unistd.h + @comment POSIX.1 + @deftypefun gid_t getgid (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{getgid} function returns the real group ID of the process. + @end deftypefun + + @comment unistd.h + @comment POSIX.1 + @deftypefun uid_t geteuid (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{geteuid} function returns the effective user ID of the process. + @end deftypefun + + @comment unistd.h + @comment POSIX.1 + @deftypefun gid_t getegid (void) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{getegid} function returns the effective group ID of the process. + @end deftypefun + + @comment unistd.h + @comment POSIX.1 + @deftypefun int getgroups (int @var{count}, gid_t *@var{groups}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + The @code{getgroups} function is used to inquire about the supplementary + group IDs of the process. Up to @var{count} of these group IDs are + stored in the array @var{groups}; the return value from the function is +@@ -291,6 +298,34 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun int seteuid (uid_t @var{neweuid}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} ++@c seteuid @asulock @aculock ++@c INLINE_SETXID_SYSCALL @asulock @aculock ++@c This may be just a unix syscall, or the ugliness below used by ++@c nptl to propagate the syscall to all cloned processes used to ++@c implement threads. ++@c nptl_setxid @asulock @aculock ++@c while holding the stack_alloc_lock, mark with SETXID_BITMASK all ++@c threads that are not exiting, signal them until no thread remains ++@c marked, clear the marks and run the syscall, then release the lock. ++@c lll_lock @asulock @aculock ++@c list_for_each ok ++@c list_entry ok ++@c setxid_mark_thread ok ++@c if a thread is initializing, wait for it to be cloned. ++@c mark it with SETXID_BITMASK if it's not exiting ++@c setxid_signal_thread ok ++@c if a thread is marked with SETXID_BITMASK, ++@c send it the SIGSETXID signal ++@c setxid_unmark_thread ok ++@c clear SETXID_BITMASK and release the futex if SETXID_BITMASK is ++@c set. ++@c ok ++@c lll_unlock @aculock ++@c ++@c sighandler_setxid ok ++@c issue the syscall, clear SETXID_BITMASK, release the futex, and ++@c wake up the signaller loop if the counter reached zero. + This function sets the effective user ID of a process to @var{neweuid}, + provided that the process is allowed to change its effective user ID. A + privileged process (effective user ID zero) can change its effective +@@ -318,6 +353,9 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun int setuid (uid_t @var{newuid}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} ++@c setuid @asulock @aculock ++@c INLINE_SETXID_SYSCALL dup @asulock @aculock + If the calling process is privileged, this function sets both the real + and effective user ID of the process to @var{newuid}. It also deletes + the file user ID of the process, if any. @var{newuid} may be any +@@ -334,6 +372,9 @@ + @comment unistd.h + @comment BSD + @deftypefun int setreuid (uid_t @var{ruid}, uid_t @var{euid}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} ++@c setreuid @asulock @aculock ++@c INLINE_SETXID_SYSCALL dup @asulock @aculock + This function sets the real user ID of the process to @var{ruid} and the + effective user ID to @var{euid}. If @var{ruid} is @code{-1}, it means + not to change the real user ID; likewise if @var{euid} is @code{-1}, it +@@ -369,6 +410,9 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun int setegid (gid_t @var{newgid}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} ++@c setegid @asulock @aculock ++@c INLINE_SETXID_SYSCALL dup @asulock @aculock + This function sets the effective group ID of the process to + @var{newgid}, provided that the process is allowed to change its group + ID. Just as with @code{seteuid}, if the process is privileged it may +@@ -388,6 +432,9 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun int setgid (gid_t @var{newgid}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} ++@c setgid @asulock @aculock ++@c INLINE_SETXID_SYSCALL dup @asulock @aculock + This function sets both the real and effective group ID of the process + to @var{newgid}, provided that the process is privileged. It also + deletes the file group ID, if any. +@@ -402,6 +449,9 @@ + @comment unistd.h + @comment BSD + @deftypefun int setregid (gid_t @var{rgid}, gid_t @var{egid}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} ++@c setregid @asulock @aculock ++@c INLINE_SETXID_SYSCALL dup @asulock @aculock + This function sets the real group ID of the process to @var{rgid} and + the effective group ID to @var{egid}. If @var{rgid} is @code{-1}, it + means not to change the real group ID; likewise if @var{egid} is +@@ -437,7 +487,10 @@ + + @comment grp.h + @comment BSD +-@deftypefun int setgroups (size_t @var{count}, gid_t *@var{groups}) ++@deftypefun int setgroups (size_t @var{count}, const gid_t *@var{groups}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} ++@c setgroups @asulock @aculock ++@c INLINE_SETXID_SYSCALL dup @asulock @aculock + This function sets the process's supplementary group IDs. It can only + be called from privileged processes. The @var{count} argument specifies + the number of group IDs in the array @var{groups}. +@@ -455,6 +508,36 @@ + @comment grp.h + @comment BSD + @deftypefun int initgroups (const char *@var{user}, gid_t @var{group}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @acsmem{} @acsfd{} @aculock{}}} ++@c initgroups @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c sysconf(_SC_NGROUPS_MAX) dup @acsfd ++@c MIN dup ok ++@c malloc @ascuheap @acsmem ++@c internal_getgrouplist @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nscd_getgrouplist @ascuheap @acsfd @acsmem ++@c nscd_get_map_ref dup @ascuheap @acsfd @acsmem ++@c nscd_cache_search dup ok ++@c nscd_open_socket dup @acsfd ++@c realloc dup @ascuheap @acsmem ++@c readall dup ok ++@c memcpy dup ok ++@c close_not_cancel_no_status dup @acsfd ++@c nscd_drop_map_ref dup @ascuheap @acsmem ++@c nscd_unmap dup @ascuheap @acsmem ++@c nss_database_lookup dup @mtslocale @ascuheap @asulock @acucorrupt @acsmem @acsfd @aculock ++@c nss_lookup_function dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c compat_call @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c sysconf(_SC_GETGR_R_SIZE_MAX) ok ++@c nss_lookup_function dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *getgrent_fct @ascuplugin ++@c *setgrent_fct @ascuplugin ++@c *endgrent_fct @ascuplugin ++@c realloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c *initgroups_dyn_fct @ascuplugin ++@c nss_next_action dup ok ++@c setgroups dup @asulock @aculock ++@c free dup @ascuheap @acsmem + The @code{initgroups} function sets the process's supplementary group + IDs to be the normal default for the user name @var{user}. The group + @var{group} is automatically included. +@@ -476,6 +559,13 @@ + @comment grp.h + @comment BSD + @deftypefun int getgrouplist (const char *@var{user}, gid_t @var{group}, gid_t *@var{groups}, int *@var{ngroups}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @acsmem{} @acsfd{} @aculock{}}} ++@c getgrouplist @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c MAX dup ok ++@c malloc dup @ascuheap @acsmem ++@c internal_getgrouplist dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c memcpy dup ok ++@c free dup @ascuheap @acsmem + The @code{getgrouplist} function scans the group database for all the + groups @var{user} belongs to. Up to *@var{ngroups} group IDs + corresponding to these groups are stored in the array @var{groups}; the +@@ -740,7 +830,7 @@ + Be cautious about using the @code{exec} functions in combination with + changing the effective user ID. Don't let users of your program execute + arbitrary programs under a changed user ID. Executing a shell is +-especially bad news. Less obviously, the @code{execlp} and @code{execvp} ++especially bad news. Less obviously, the @code{execlp} and @code{execvp} + functions are a potential risk (since the program they execute depends + on the user's @code{PATH} environment variable). + +@@ -792,6 +882,41 @@ + @comment unistd.h + @comment POSIX.1 + @deftypefun {char *} getlogin (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:getlogin} @mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c getlogin (linux) @mtasurace:getlogin @mtasurace:utent @mtascusig:ALRM @mtascutimer @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c getlogin_r_loginuid dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c getlogin_fd0 (unix) @mtasurace:getlogin @mtasurace:utent @mtascusig:ALRM @mtascutimer @ascuheap @asulock @aculock @acsfd @acsmem ++@c uses static buffer name => @mtasurace:getlogin ++@c ttyname_r dup @ascuheap @acsmem @acsfd ++@c strncpy dup ok ++@c setutent dup @mtasurace:utent @asulock @aculock @acsfd ++@c getutline_r dup @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd ++@c endutent dup @mtasurace:utent @asulock @aculock ++@c libc_lock_unlock dup ok ++@c strlen dup ok ++@c memcpy dup ok ++@c ++@c getlogin_r (linux) @mtasurace:utent @mtascusig:ALRM @mtascutimer @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c getlogin_r_loginuid @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c open_not_cancel_2 dup @acsfd ++@c read_not_cancel dup ok ++@c close_not_cancel_no_status dup @acsfd ++@c strtoul @mtslocale ++@c getpwuid_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c realloc dup @asulock @aculock @acsfd @acsmem ++@c strlen dup ok ++@c memcpy dup ok ++@c free dup @asulock @aculock @acsfd @acsmem ++@c getlogin_r_fd0 (unix) @mtasurace:utent @mtascusig:ALRM @mtascutimer @ascuheap @asulock @aculock @acsmem @acsfd ++@c ttyname_r dup @ascuheap @acsmem @acsfd ++@c strncpy dup ok ++@c libc_lock_lock dup @asulock @aculock ++@c *libc_utmp_jump_table->setutent dup @mtasurace:utent @acsfd ++@c *libc_utmp_jump_table->getutline_r dup @mtasurace:utent @mtascusig:ALRM @mtascutimer ++@c *libc_utmp_jump_table->endutent dup @mtasurace:utent @asulock @aculock ++@c libc_lock_unlock dup ok ++@c strlen dup ok ++@c memcpy dup ok + The @code{getlogin} function returns a pointer to a string containing the + name of the user logged in on the controlling terminal of the process, + or a null pointer if this information cannot be determined. The string +@@ -802,6 +927,11 @@ + @comment stdio.h + @comment POSIX.1 + @deftypefun {char *} cuserid (char *@var{string}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c cuserid @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c geteuid dup ok ++@c getpwuid_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c strncpy dup ok + The @code{cuserid} function returns a pointer to a string containing a + user name associated with the effective ID of the process. If + @var{string} is not a null pointer, it should be an array that can hold +@@ -1013,6 +1143,22 @@ + @comment utmp.h + @comment SVID + @deftypefun void setutent (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:utent}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} ++@c Besides the static variables in utmp_file.c, there's the jump_table. ++@c They're both modified while holding a lock, but other threads may ++@c cause the variables to be modified between calling this function and ++@c others that rely on the internal state it sets up. ++ ++@c setutent @mtasurace:utent @asulock @aculock @acsfd ++@c libc_lock_lock dup @asulock @aculock ++@c *libc_utmp_jump_table->setutent @mtasurace:utent @acsfd ++@c setutent_unknown @mtasurace:utent @acsfd ++@c *libc_utmp_file_functions.setutent = setutent_file @mtasurace:utent @acsfd ++@c open_not_cancel_2 dup @acsfd ++@c fcntl_not_cancel dup ok ++@c close_not_cancel_no_status dup @acsfd ++@c lseek64 dup ok ++@c libc_lock_unlock dup ok + This function opens the user accounting database to begin scanning it. + You can then call @code{getutent}, @code{getutid} or @code{getutline} to + read entries and @code{pututline} to write entries. +@@ -1024,6 +1170,14 @@ + @comment utmp.h + @comment SVID + @deftypefun {struct utmp *} getutent (void) ++@safety{@prelim{}@mtunsafe{@mtuinit{} @mtasurace{:utent} @mtasurace{:utentbuf} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} ++@c The static buffer that holds results is allocated with malloc at ++@c the first call; the test is not thread-safe, so multiple concurrent ++@c calls could malloc multiple buffers. ++ ++@c getutent @mtuinit @mtasurace:utent @mtasurace:utentbuf @mtascusig:ALRM @mtascutimer @ascuheap @asulock @aculock @acsfd @acsmem ++@c malloc @asulock @aculock @acsfd @acsmem ++@c getutent_r dup @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd + The @code{getutent} function reads the next entry from the user + accounting database. It returns a pointer to the entry, which is + statically allocated and may be overwritten by subsequent calls to +@@ -1037,12 +1191,27 @@ + @comment utmp.h + @comment SVID + @deftypefun void endutent (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:utent}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} ++@c endutent @mtasurace:utent @asulock @aculock @acsfd ++@c libc_lock_lock dup @asulock @aculock ++@c *libc_utmp_jump_table->endutent @mtasurace:utent @acsfd ++@c endutent_unknown ok ++@c endutent_file @mtasurace:utent @acsfd ++@c close_not_cancel_no_status dup @acsfd ++@c libc_lock_unlock dup ok + This function closes the user accounting database. + @end deftypefun + + @comment utmp.h + @comment SVID + @deftypefun {struct utmp *} getutid (const struct utmp *@var{id}) ++@safety{@prelim{}@mtunsafe{@mtuinit{} @mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsmem{} @acsfd{}}} ++@c Same caveats as getutline. ++@c ++@c getutid @mtuinit @mtasurace:utent @mtascusig:ALRM @mtascutimer @ascuheap @asulock @aculock @acsmem @acsfd ++@c uses a static buffer malloced on the first call ++@c malloc dup @ascuheap @acsmem ++@c getutid_r dup @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd + This function searches forward from the current point in the database + for an entry that matches @var{id}. If the @code{ut_type} member of the + @var{id} structure is one of @code{RUN_LVL}, @code{BOOT_TIME}, +@@ -1073,6 +1242,14 @@ + @comment utmp.h + @comment SVID + @deftypefun {struct utmp *} getutline (const struct utmp *@var{line}) ++@safety{@prelim{}@mtunsafe{@mtuinit{} @mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} ++@c The static buffer that holds results is allocated with malloc at ++@c the first call; the test is not thread-safe, so multiple concurrent ++@c calls could malloc multiple buffers. ++ ++@c getutline @mtuinit @mtasurace:utent @mtascusig:ALRM @mtascutimer @ascuheap @asulock @aculock @acsfd @acsmem ++@c malloc @asulock @aculock @acsfd @acsmem ++@c getutline_r dup @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd + This function searches forward from the current point in the database + until it finds an entry whose @code{ut_type} value is + @code{LOGIN_PROCESS} or @code{USER_PROCESS}, and whose @code{ut_line} +@@ -1095,6 +1272,29 @@ + @comment utmp.h + @comment SVID + @deftypefun {struct utmp *} pututline (const struct utmp *@var{utmp}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} ++@c pututline @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd ++@c libc_lock_lock dup @asulock @aculock ++@c *libc_utmp_jump_table->pututline @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd ++@c pututline_unknown @mtasurace:utent @acsfd ++@c setutent_unknown dup @mtasurace:utent @acsfd ++@c pututline_file @mtascusig:ALRM @mtascutimer @acsfd ++@c TRANSFORM_UTMP_FILE_NAME ok ++@c strcmp dup ok ++@c acesss dup ok ++@c open_not_cancel_2 dup @acsfd ++@c fcntl_not_cancel dup ok ++@c close_not_cancel_no_status dup @acsfd ++@c llseek dup ok ++@c dup2 dup ok ++@c utmp_equal dup ok ++@c internal_getut_r dup @mtascusig:ALRM @mtascutimer ++@c LOCK_FILE dup @mtascusig:ALRM @mtasctimer ++@c LOCKING_FAILED dup ok ++@c ftruncate64 dup ok ++@c write_not_cancel dup ok ++@c UNLOCK_FILE dup @mtasctimer ++@c libc_lock_unlock dup @aculock + The @code{pututline} function inserts the entry @code{*@var{utmp}} at + the appropriate place in the user accounting database. If it finds that + it is not already at the correct place in the database, it uses +@@ -1125,6 +1325,27 @@ + @comment utmp.h + @comment GNU + @deftypefun int getutent_r (struct utmp *@var{buffer}, struct utmp **@var{result}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} ++@c getutent_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd ++@c libc_lock_lock dup @asulock @aculock ++@c *libc_utmp_jump_table->getutent_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd ++@c getutent_r_unknown @mtasurace:utent @acsfd ++@c setutent_unknown dup @mtasurace:utent @acsfd ++@c getutent_r_file @mtasurace:utent @mtascusig:ALRM @mtascutimer ++@c LOCK_FILE @mtascusig:ALRM @mtascutimer ++@c alarm dup @mtascutimer ++@c sigemptyset dup ok ++@c sigaction dup ok ++@c memset dup ok ++@c fcntl_not_cancel dup ok ++@c LOCKING_FAILED ok ++@c read_not_cancel dup ok ++@c UNLOCK_FILE @mtascutimer ++@c fcntl_not_cancel dup ok ++@c alarm dup @mtascutimer ++@c sigaction dup ok ++@c memcpy dup ok ++@c libc_lock_unlock dup ok + The @code{getutent_r} is equivalent to the @code{getutent} function. It + returns the next entry from the database. But instead of storing the + information in a static buffer it stores it in the buffer pointed to by +@@ -1142,6 +1363,22 @@ + @comment utmp.h + @comment GNU + @deftypefun int getutid_r (const struct utmp *@var{id}, struct utmp *@var{buffer}, struct utmp **@var{result}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} ++@c getutid_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd ++@c libc_lock_lock dup @asulock @aculock ++@c *libc_utmp_jump_table->getutid_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd ++@c getutid_r_unknown @mtasurace:utent @acsfd ++@c setutent_unknown dup @mtasurace:utent @acsfd ++@c getutid_r_file @mtascusig:ALRM @mtascutimer ++@c internal_getut_r @mtascusig:ALRM @mtascutimer ++@c LOCK_FILE dup @mtascusig:ALRM @mtascutimer ++@c LOCKING_FAILED dup ok ++@c read_not_cancel dup ok ++@c utmp_equal ok ++@c strncmp dup ok ++@c UNLOCK_FILE dup @mtascutimer ++@c memcpy dup ok ++@c libc_lock_unlock dup @aculock + This function retrieves just like @code{getutid} the next entry matching + the information stored in @var{id}. But the result is stored in the + buffer pointed to by the parameter @var{buffer}. +@@ -1157,6 +1394,28 @@ + @comment utmp.h + @comment GNU + @deftypefun int getutline_r (const struct utmp *@var{line}, struct utmp *@var{buffer}, struct utmp **@var{result}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} ++@c getutline_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd ++@c libc_lock_lock dup @asulock @aculock ++@c *libc_utmp_jump_table->getutline_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd ++@c getutline_r_unknown @mtasurace:utent @acsfd ++@c setutent_unknown dup @mtasurace:utent @acsfd ++@c getutline_r_file @mtasurace:utent @mtascusig:ALRM @mtascutimer ++@c LOCK_FILE @mtascusig:ALRM @mtascutimer ++@c alarm dup @mtascutimer ++@c sigemptyset dup ok ++@c sigaction dup ok ++@c memset dup ok ++@c fcntl_not_cancel dup ok ++@c LOCKING_FAILED ok ++@c read_not_cancel dup ok ++@c strncmp dup ok ++@c UNLOCK_FILE @mtascutimer ++@c fcntl_not_cancel dup ok ++@c alarm dup @mtascutimer ++@c sigaction dup ok ++@c memcpy dup ok ++@c libc_lock_unlock dup ok + This function retrieves just like @code{getutline} the next entry + matching the information stored in @var{line}. But the result is stored + in the buffer pointed to by the parameter @var{buffer}. +@@ -1180,6 +1439,14 @@ + @comment utmp.h + @comment SVID + @deftypefun int utmpname (const char *@var{file}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:utent}}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsmem{}}} ++@c utmpname @mtasurace:utent @asulock @ascuheap @aculock @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c *libc_utmp_jump_table->endutent dup @mtasurace:utent ++@c strcmp dup ok ++@c free dup @ascuheap @acsmem ++@c strdup dup @ascuheap @acsmem ++@c libc_lock_unlock dup @aculock + The @code{utmpname} function changes the name of the database to be + examined to @var{file}, and closes any previously opened database. By + default @code{getutent}, @code{getutid}, @code{getutline} and +@@ -1208,6 +1475,18 @@ + @comment utmp.h + @comment SVID + @deftypefun void updwtmp (const char *@var{wtmp_file}, const struct utmp *@var{utmp}) ++@safety{@prelim{}@mtunsafe{@mtascusig{:ALRM} @mtascutimer{}}@asunsafe{}@acunsafe{@acsfd{}}} ++@c updwtmp @mtascusig:ALRM @mtascutimer @acsfd ++@c TRANSFORM_UTMP_FILE_NAME dup ok ++@c *libc_utmp_file_functions->updwtmp = updwtmp_file @mtascusig:ALRM @mtascutimer @acsfd ++@c open_not_cancel_2 dup @acsfd ++@c LOCK_FILE dup @mtascusig:ALRM @mtascutimer ++@c LOCKING_FAILED dup ok ++@c lseek64 dup ok ++@c ftruncate64 dup ok ++@c write_not_cancel dup ok ++@c UNLOCK_FILE dup @mtascutimer ++@c close_not_cancel_no_status dup @acsfd + The @code{updwtmp} function appends the entry *@var{utmp} to the + database specified by @var{wtmp_file}. For possible values for the + @var{wtmp_file} argument see the @code{utmpname} function. +@@ -1330,6 +1609,7 @@ + @comment utmpx.h + @comment XPG4.2 + @deftypefun void setutxent (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:utent}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} + This function is similar to @code{setutent}. In @theglibc{} it is + simply an alias for @code{setutent}. + @end deftypefun +@@ -1337,6 +1617,7 @@ + @comment utmpx.h + @comment XPG4.2 + @deftypefun {struct utmpx *} getutxent (void) ++@safety{@prelim{}@mtunsafe{@mtuinit{} @mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} + The @code{getutxent} function is similar to @code{getutent}, but returns + a pointer to a @code{struct utmpx} instead of @code{struct utmp}. In + @theglibc{} it simply is an alias for @code{getutent}. +@@ -1345,6 +1626,7 @@ + @comment utmpx.h + @comment XPG4.2 + @deftypefun void endutxent (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:utent}}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} + This function is similar to @code{endutent}. In @theglibc{} it is + simply an alias for @code{endutent}. + @end deftypefun +@@ -1352,6 +1634,7 @@ + @comment utmpx.h + @comment XPG4.2 + @deftypefun {struct utmpx *} getutxid (const struct utmpx *@var{id}) ++@safety{@prelim{}@mtunsafe{@mtuinit{} @mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsmem{} @acsfd{}}} + This function is similar to @code{getutid}, but uses @code{struct utmpx} + instead of @code{struct utmp}. In @theglibc{} it is simply an alias + for @code{getutid}. +@@ -1360,6 +1643,7 @@ + @comment utmpx.h + @comment XPG4.2 + @deftypefun {struct utmpx *} getutxline (const struct utmpx *@var{line}) ++@safety{@prelim{}@mtunsafe{@mtuinit{} @mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} + This function is similar to @code{getutid}, but uses @code{struct utmpx} + instead of @code{struct utmp}. In @theglibc{} it is simply an alias + for @code{getutline}. +@@ -1368,6 +1652,7 @@ + @comment utmpx.h + @comment XPG4.2 + @deftypefun {struct utmpx *} pututxline (const struct utmpx *@var{utmp}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} + The @code{pututxline} function is functionally identical to + @code{pututline}, but uses @code{struct utmpx} instead of @code{struct + utmp}. In @theglibc{}, @code{pututxline} is simply an alias for +@@ -1377,6 +1662,7 @@ + @comment utmpx.h + @comment XPG4.2 + @deftypefun int utmpxname (const char *@var{file}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:utent}}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsmem{}}} + The @code{utmpxname} function is functionally identical to + @code{utmpname}. In @theglibc{}, @code{utmpxname} is simply an + alias for @code{utmpname}. +@@ -1391,6 +1677,7 @@ + @comment utmp.h + @comment GNU + @deftypefun int getutmp (const struct utmpx *@var{utmpx}, struct utmp *@var{utmp}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + @code{getutmp} copies the information, insofar as the structures are + compatible, from @var{utmpx} to @var{utmp}. + @end deftypefun +@@ -1399,6 +1686,7 @@ + @comment utmp.h + @comment GNU + @deftypefun int getutmpx (const struct utmp *@var{utmp}, struct utmpx *@var{utmpx}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + @code{getutmpx} copies the information, insofar as the structures are + compatible, from @var{utmp} to @var{utmpx}. + @end deftypefun +@@ -1418,6 +1706,17 @@ + @comment utmp.h + @comment BSD + @deftypefun int login_tty (int @var{filedes}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:ttyname}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} ++@c If this function is canceled, it may have succeeded in redirecting ++@c only some of the standard streams to the newly opened terminal. ++@c Should there be a safety annotation for this? ++@c login_tty @mtasurace:ttyname @ascuheap @asulock @aculock @acsmem @acsfd ++@c setsid dup ok ++@c ioctl dup ok ++@c ttyname dup @mtasurace:ttyname @ascuheap @asulock @aculock @acsmem @acsfd ++@c close dup @acsfd ++@c open dup @acsfd ++@c dup2 dup ok + This function makes @var{filedes} the controlling terminal of the + current process, redirects standard input, standard output and + standard error output to this terminal, and closes @var{filedes}. +@@ -1429,6 +1728,24 @@ + @comment utmp.h + @comment BSD + @deftypefun void login (const struct utmp *@var{entry}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acucorrupt{} @acsfd{} @acsmem{}}} ++@c login @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @ascuheap @aculock @acucorrupt @acsfd @acsmem ++@c getpid dup ok ++@c tty_name @ascuheap @acucorrupt @acsmem @acsfd ++@c ttyname_r dup @ascuheap @acsmem @acsfd ++@c memchr dup ok ++@c realloc dup @ascuheap @acsmem ++@c malloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c strncmp dup ok ++@c basename dup ok ++@c strncpy dup ok ++@c utmpname dup @mtasurace:utent @asulock @ascuheap @aculock @acsmem ++@c setutent dup @mtasurace:utent @asulock @aculock @acsfd ++@c pututline dup @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd ++@c endutent dup @mtasurace:utent @asulock @aculock ++@c free dup @ascuheap @acsmem ++@c updwtmp dup @mtascusig:ALRM @mtascutimer @acsfd + The @code{login} functions inserts an entry into the user accounting + database. The @code{ut_line} member is set to the name of the terminal + on standard input. If standard input is not a terminal @code{login} +@@ -1444,6 +1761,17 @@ + @comment utmp.h + @comment BSD + @deftypefun int logout (const char *@var{ut_line}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} ++@c logout @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @ascuheap @aculock @acsfd @acsmem ++@c utmpname dup @mtasurace:utent @asulock @ascuheap @aculock @acsmem ++@c setutent dup @mtasurace:utent @asulock @aculock @acsfd ++@c strncpy dup ok ++@c getutline_r dup @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd ++@c bzero dup ok ++@c gettimeofday dup ok ++@c time dup ok ++@c pututline dup @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd ++@c endutent dup @mtasurace:utent @asulock @aculock + This function modifies the user accounting database to indicate that the + user on @var{ut_line} has logged out. + +@@ -1454,6 +1782,14 @@ + @comment utmp.h + @comment BSD + @deftypefun void logwtmp (const char *@var{ut_line}, const char *@var{ut_name}, const char *@var{ut_host}) ++@safety{@prelim{}@mtunsafe{@mtascusig{:ALRM} @mtascutimer{}}@asunsafe{}@acunsafe{@acsfd{}}} ++@c logwtmp @mtascusig:ALRM @mtascutimer @acsfd ++@c memset dup ok ++@c getpid dup ok ++@c strncpy dup ok ++@c gettimeofday dup ok ++@c time dup ok ++@c updwtmp dup @mtascusig:ALRM @mtascutimer @acsfd + The @code{logwtmp} function appends an entry to the user accounting log + file, for the current time and the information provided in the + @var{ut_line}, @var{ut_name} and @var{ut_host} arguments. +@@ -1535,6 +1871,14 @@ + @comment pwd.h + @comment POSIX.1 + @deftypefun {struct passwd *} getpwuid (uid_t @var{uid}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:pwuid} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c getpwuid @mtasurace:pwuid @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c malloc dup @ascuheap @acsmem ++@c getpwuid_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c realloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c libc_lock_unlock dup @aculock + This function returns a pointer to a statically-allocated structure + containing information about the user whose user ID is @var{uid}. This + structure may be overwritten on subsequent calls to @code{getpwuid}. +@@ -1546,6 +1890,208 @@ + @comment pwd.h + @comment POSIX.1c + @deftypefun int getpwuid_r (uid_t @var{uid}, struct passwd *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct passwd **@var{result}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c getpwuid_r @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nscd_getpwuid_r @ascuheap @acsfd @acsmem ++@c itoa_word dup ok ++@c nscd_getpw_r @ascuheap @acsfd @acsmem ++@c nscd_get_map_ref @ascuheap @acsfd @acsmem ++@c nscd_acquire_maplock ok ++@c nscd_get_mapping @ascuheap @acsfd @acsmem ++@c open_socket dup @acsfd ++@c memset dup ok ++@c wait_on_socket dup ok ++@c recvmsg dup ok ++@c strcmp dup ok ++@c fstat64 dup ok ++@c mmap dup @acsmem ++@c munmap dup @acsmem ++@c malloc dup @ascuheap @acsmem ++@c close dup ok ++@c nscd_unmap dup @ascuheap @acsmem ++@c nscd_cache_search ok ++@c nis_hash ok ++@c memcmp dup ok ++@c nscd_open_socket @acsfd ++@c open_socket @acsfd ++@c socket dup @acsfd ++@c fcntl dup ok ++@c strcpy dup ok ++@c connect dup ok ++@c send dup ok ++@c gettimeofday dup ok ++@c poll dup ok ++@c close_not_cancel_no_status dup @acsfd ++@c wait_on_socket dup ok ++@c read dup ok ++@c close_not_cancel_no_status dup @acsfd ++@c readall ok ++@c read dup ok ++@c wait_on_socket ok ++@c poll dup ok ++@c gettimeofday dup ok ++@c memcpy dup ok ++@c close_not_cancel_no_status dup @acsfd ++@c nscd_drop_map_ref @ascuheap @acsmem ++@c nscd_unmap dup @ascuheap @acsmem ++@c nscd_unmap @ascuheap @acsmem ++@c munmap dup ok ++@c free dup @ascuheap @acsmem ++@c nss_passwd_lookup2 @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nss_database_lookup @mtslocale @ascuheap @asulock @acucorrupt @acsmem @acsfd @aculock ++@c libc_lock_lock @asulock @aculock ++@c libc_lock_unlock @aculock ++@c nss_parse_file @mtslocale @ascuheap @asulock @acucorrupt @acsmem @acsfd @aculock ++@c fopen dup @ascuheap @asulock @acsmem @acsfd @aculock ++@c fsetlocking dup ok [no concurrent uses] ++@c malloc dup @asulock @aculock @acsfd @acsmem ++@c fclose dup @ascuheap @asulock @acsmem @acsfd @aculock ++@c getline dup @ascuheap @aculock @acucorrupt @acsmem ++@c strchrnul dup ok ++@c nss_getline @mtslocale @ascuheap @acsmem ++@c isspace @mtslocale^^ ++@c strlen dup ok ++@c malloc dup @asulock @aculock @acsfd @acsmem ++@c memcpy dup ok ++@c nss_parse_service_list dup @mtslocale^, @ascuheap @acsmem ++@c feof_unlocked dup ok ++@c free dup @asulock @aculock @acsfd @acsmem ++@c strcmp dup ok ++@c nss_parse_service_list @mtslocale^, @ascuheap @acsmem ++@c isspace @mtslocale^^ ++@c malloc dup @asulock @aculock @acsfd @acsmem ++@c mempcpy dup ok ++@c strncasecmp dup ok ++@c free dup @asulock @aculock @acsfd @acsmem ++@c malloc dup @asulock @aculock @acsfd @acsmem ++@c nss_lookup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nss_lookup_function @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock @asulock @aculock ++@c tsearch @ascuheap @acucorrupt @acsmem [no @mtsrace or @asucorrupt due to locking] ++@c known_compare ok ++@c strcmp dup ok ++@c malloc dup @ascuheap @acsmem ++@c tdelete @ascuheap @acucorrupt @acsmem [no @mtsrace or @asucorrupt due to locking] ++@c free dup @ascuheap @acsmem ++@c nss_load_library @ascudlopen @ascuplugin @ascuheap @asulock @aculock @acsfd @acsmem ++@c nss_new_service @ascuheap @acsmem ++@c strcmp dup ok ++@c malloc dup @ascuheap @acsmem ++@c strlen dup ok ++@c stpcpy dup ok ++@c libc_dlopen @ascudlopen @ascuheap @asulock @aculock @acsfd @acsmem ++@c libc_dlsym dup @asulock @aculock @acsfd @acsmem ++@c *ifct(*nscd_init_cb) @ascuplugin ++@c stpcpy dup ok ++@c libc_dlsym dup @asulock @aculock @acsfd @acsmem ++@c libc_lock_unlock dup ok ++@c nss_next_action ok ++@c *fct.l -> _nss_*_getpwuid_r @ascuplugin ++@c nss_next2 @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nss_next_action dup ok ++@c nss_lookup_function dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++ ++@c _nss_files_getpwuid_r @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c libc_lock_lock dup @asulock @aculock ++@c internal_setent @ascuheap @asulock @aculock @acsmem @acsfd ++@c fopen dup @ascuheap @asulock @acsmem @acsfd @aculock ++@c fileno dup ok ++@c fcntl dup ok ++@c fclose dup @ascuheap @asulock @aculock @acsmem @acsfd ++@c rewind dup @aculock [stream guarded by non-recursive pwent lock] ++@c internal_getent @mtslocale^ ++@c fgets_unlocked dup ok [stream guarded by non-recursive pwent lock] ++@c isspace dup @mtslocale^^ ++@c _nss_files_parse_pwent = parse_line ok ++@c strpbrk dup ok ++@c internal_endent @ascuheap @asulock @aculock @acsmem @acsfd ++@c fclose dup @ascuheap @asulock @aculock @acsmem @acsfd ++@c libc_lock_unlock dup @aculock ++ ++@c _nss_nis_getpwuid_r ... not fully reviewed (assumed) @asuinit @asulock @acucorrupt @aculock ++@c yp_get_default_domain @asulock @aculock ++@c libc_lock_lock dup @asulock @aculock ++@c getdomainname dup ok ++@c strcmp dup ok ++@c libc_lock_unlock dup @aculock ++@c snprintf dup @ascuheap @acsmem ++@c yp_match ++@c do_ypcall_tr(xdr_ypreq_key,xdr_ypresp_val) ++@c do_ypcall(xdr_ypreq_key,xdr_ypresp_val) ++@c libc_lock_lock @asulock @aculock ++@c strcmp ++@c yp_bind ++@c ypclnt_call ++@c clnt_call ++@c clnt_perror ++@c libc_lock_unlock @aculock ++@c yp_unbind_locked ++@c yp_unbind ++@c strcmp dup ok ++@c calloc dup @asulock @aculock @acsfd @acsmem ++@c yp_bind_file ++@c strlen dup ok ++@c snprintf dup @ascuheap @acsmem ++@c open dup @acsfd [cancelpt] ++@c pread dup [cancelpt] ++@c yp_bind_client_create ++@c close dup @acsfd [cancelpt] ++@c yp_bind_ypbindprog ++@c clnttcp_create ++@c clnt_destroy ++@c clnt_call(xdr_domainname,xdr_ypbind_resp) ++@c memset dup ok ++@c yp_bind_client_create ++@c free dup @asulock @aculock @acsfd @acsmem ++@c calloc dup @asulock @aculock @acsfd @acsmem ++@c free dup @asulock @aculock @acsfd @acsmem ++@c ypprot_err ++@c memcpy dup ok ++@c xdr_free(xdr_ypresp_val) ++@c xdr_ypresp_val ++@c xdr_ypstat ++@c xdr_enum ++@c XDR_PUTLONG ++@c *x_putlong ++@c XDR_GETLONG ++@c *x_getlong ++@c xdr_long ++@c XDR_PUTLONG dup ++@c XDR_GETLONG dup ++@c xdr_short ++@c XDR_PUTLONG dup ++@c XDR_GETLONG dup ++@c xdr_valdat ++@c xdr_bytes ++@c xdr_u_int ++@c XDR_PUTLONG dup ++@c XDR_GETLONG dup ++@c mem_alloc @ascuheap @acsmem ++@c malloc dup @ascuheap @acsmem ++@c xdr_opaque ++@c XDR_GETBYTES ++@c *x_getbytes ++@c XDR_PUTBYTES ++@c *x_putbytes ++@c mem_free @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c yperr2nss ok ++@c strchr dup ok ++@c _nls_default_nss @asuinit @ascuheap @asulock @acucorrupt @acsmem @acsfd @aculock ++@c init @asuinit^, @ascuheap @asulock @acucorrupt @acsmem @acsfd @aculock ++@c fopen dup @ascuheap @asulock @acsmem @acsfd @aculock ++@c fsetlocking ok [no concurrent uses] ++@c feof_unlocked dup ok ++@c getline dup @ascuheap @aculock @acucorrupt @acsmem ++@c isspace dup @mtslocale^^ ++@c strncmp dup ok ++@c free dup @asulock @acsmem @acsfd @aculock ++@c fclose dup @ascuheap @asulock @aculock @acsmem @acsfd ++@c free dup @asulock @acsmem @acsfd @aculock ++@c mempcpy dup ok ++@c strncpy dup ok ++@c isspace dup @mtslocale^^ ++@c _nss_files_parse_pwent ok + This function is similar to @code{getpwuid} in that it returns + information about the user whose user ID is @var{uid}. However, it + fills the user supplied structure pointed to by @var{result_buf} with +@@ -1568,6 +2114,14 @@ + @comment pwd.h + @comment POSIX.1 + @deftypefun {struct passwd *} getpwnam (const char *@var{name}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:pwnam} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c getpwnam @mtasurace:pwnam @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c malloc dup @ascuheap @acsmem ++@c getpwnam_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c realloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c libc_lock_unlock dup @aculock + This function returns a pointer to a statically-allocated structure + containing information about the user whose user name is @var{name}. + This structure may be overwritten on subsequent calls to +@@ -1579,6 +2133,25 @@ + @comment pwd.h + @comment POSIX.1c + @deftypefun int getpwnam_r (const char *@var{name}, struct passwd *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct passwd **@var{result}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c getpwnam_r @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nscd_getpwnam_r @ascuheap @asulock @aculock @acsfd @acsmem ++@c strlen dup ok ++@c nscd_getpw_r dup @ascuheap @asulock @aculock @acsfd @acsmem ++@c nss_passwd_lookup2 dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.l @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c ++@c _nss_files_getpwnam_r @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd ++@c libc_lock_lock dup @asulock @aculock ++@c internal_setent dup @ascuheap @asulock @aculock @acsmem @acsfd ++@c internal_getent dup @mtslocale^ ++@c strcmp dup ok ++@c internal_endent dup @ascuheap @asulock @aculock @acsmem @acsfd ++@c libc_lock_unlock dup @aculock ++@c ++@c _nss_*_getpwnam_r (assumed) @asuinit @asulock @acucorrupt @aculock ++ + This function is similar to @code{getpwnam} in that is returns + information about the user whose user name is @var{name}. However, like + @code{getpwuid_r}, it fills the user supplied buffers in +@@ -1603,6 +2176,16 @@ + @comment pwd.h + @comment SVID + @deftypefun {struct passwd *} fgetpwent (FILE *@var{stream}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:fpwent}}@asunsafe{@asucorrupt{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{}}} ++@c fgetpwent @mtasurace:fpwent @asucorrupt @asulock @acucorrupt @aculock ++@c fgetpos dup @asucorrupt @aculock @acucorrupt ++@c libc_lock_lock dup @asulock @aculock ++@c malloc dup @ascuheap @acsmem ++@c fgetpwent_r dup @asucorrupt @acucorrupt @aculock ++@c realloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c fsetpos dup @asucorrupt @aculock @acucorrupt ++@c libc_lock_unlock dup @aculock + This function reads the next user entry from @var{stream} and returns a + pointer to the entry. The structure is statically allocated and is + rewritten on subsequent calls to @code{fgetpwent}. You must copy the +@@ -1615,6 +2198,14 @@ + @comment pwd.h + @comment GNU + @deftypefun int fgetpwent_r (FILE *@var{stream}, struct passwd *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct passwd **@var{result}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}} ++@c fgetpwent_r @asucorrupt @acucorrupt @aculock ++@c flockfile dup @aculock ++@c fgets_unlocked @asucorrupt @acucorrupt [no @mtsrace due to explicit locking] ++@c feof_unlocked dup ok ++@c funlockfile dup @aculock ++@c isspace dup @mtslocale^^ ++@c parse_line dup ok + This function is similar to @code{fgetpwent} in that it reads the next + user entry from @var{stream}. But the result is returned in the + structure pointed to by @var{result_buf}. The +@@ -1637,6 +2228,17 @@ + @comment pwd.h + @comment SVID, BSD + @deftypefun void setpwent (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:pwent} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c setpwent @mtasurace:pwent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock @asulock @aculock ++@c nss_setent(nss_passwd_lookup2) @mtasurace:pwent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c ** resolv's res_maybe_init not called here ++@c setup(nss_passwd_lookup2) @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *lookup_fct = nss_passwd_lookup2 dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nss_lookup dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.f @mtasurace:pwent @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_unlock @aculock + This function initializes a stream which @code{getpwent} and + @code{getpwent_r} use to read the user database. + @end deftypefun +@@ -1644,6 +2246,15 @@ + @comment pwd.h + @comment POSIX.1 + @deftypefun {struct passwd *} getpwent (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:pwent} @mtasurace{:pwentbuf} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c getpwent @mtasurace:pwent @mtasurace:pwentbuf @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c nss_getent(getpwent_r) @mtasurace:pwent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c malloc dup @ascuheap @acsmem ++@c *func = getpwent_r dup @mtasurace:pwent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c realloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c libc_lock_unlock dup @aculock + The @code{getpwent} function reads the next entry from the stream + initialized by @code{setpwent}. It returns a pointer to the entry. The + structure is statically allocated and is rewritten on subsequent calls +@@ -1655,7 +2266,21 @@ + + @comment pwd.h + @comment GNU +-@deftypefun int getpwent_r (struct passwd *@var{result_buf}, char *@var{buffer}, int @var{buflen}, struct passwd **@var{result}) ++@deftypefun int getpwent_r (struct passwd *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct passwd **@var{result}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:pwent} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c The static buffer here is not the result_buf, but rather the ++@c variables that keep track of what nss backend we've last used, and ++@c whatever internal state the nss backend uses to keep track of the ++@c last read entry. ++@c getpwent_r @mtasurace:pwent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c nss_getent_r(nss_passwd_lookup2) @mtasurace:pwent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c setup(nss_passwd_lookup2) dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.f @mtasurace:pwent @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nss_lookup dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *sfct.f @mtasurace:pwent @ascuplugin ++@c libc_lock_unlock dup @aculock + This function is similar to @code{getpwent} in that it returns the next + entry from the stream initialized by @code{setpwent}. Like + @code{fgetpwent_r}, it uses the user-supplied buffers in +@@ -1668,6 +2293,15 @@ + @comment pwd.h + @comment SVID, BSD + @deftypefun void endpwent (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:pwent} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c endpwent @mtasurace:pwent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock @asulock @aculock ++@c nss_endent(nss_passwd_lookup2) @mtasurace:pwent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c ** resolv's res_maybe_init not called here ++@c setup(nss_passwd_lookup2) dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.f @mtasurace:pwent @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_unlock @aculock + This function closes the internal stream used by @code{getpwent} or + @code{getpwent_r}. + @end deftypefun +@@ -1678,6 +2312,9 @@ + @comment pwd.h + @comment SVID + @deftypefun int putpwent (const struct passwd *@var{p}, FILE *@var{stream}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} ++@c putpwent @mtslocale @asucorrupt @aculock @acucorrupt ++@c fprintf dup @mtslocale @asucorrupt @aculock @acucorrupt [no @ascuheap @acsmem] + This function writes the user entry @code{*@var{p}} to the stream + @var{stream}, in the format used for the standard user database + file. The return value is zero on success and nonzero on failure. +@@ -1751,6 +2388,9 @@ + @comment grp.h + @comment POSIX.1 + @deftypefun {struct group *} getgrgid (gid_t @var{gid}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:grgid} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c getgrgid =~ getpwuid dup @mtasurace:grgid @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c getgrgid_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem + This function returns a pointer to a statically-allocated structure + containing information about the group whose group ID is @var{gid}. + This structure may be overwritten by subsequent calls to +@@ -1762,6 +2402,26 @@ + @comment grp.h + @comment POSIX.1c + @deftypefun int getgrgid_r (gid_t @var{gid}, struct group *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct group **@var{result}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c getgrgid_r =~ getpwuid_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nscd_getgrgid_r @ascuheap @acsfd @acsmem ++@c itoa_word dup ok ++@c nscd_getgr_r @ascuheap @acsfd @acsmem ++@c nscd_get_map_ref dup @ascuheap @acsfd @acsmem ++@c nscd_cache_search dup ok ++@c nscd_open_socket dup @acsfd ++@c readvall ok ++@c readv dup ok ++@c memcpy dup ok ++@c wait_on_socket dup ok ++@c memcpy dup ok ++@c readall dup ok ++@c close_not_cancel_no_status dup @acsfd ++@c nscd_drop_map_ref dup @ascuheap @acsmem ++@c nscd_unmap dup @ascuheap @acsmem ++@c nss_group_lookup2 =~ nss_passwd_lookup2 dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.l -> _nss_*_getgrgid_r @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem + This function is similar to @code{getgrgid} in that it returns + information about the group whose group ID is @var{gid}. However, it + fills the user supplied structure pointed to by @var{result_buf} with +@@ -1783,6 +2443,9 @@ + @comment grp.h + @comment SVID, BSD + @deftypefun {struct group *} getgrnam (const char *@var{name}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:grnam} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c getgrnam =~ getpwnam dup @mtasurace:grnam @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c getgrnam_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem + This function returns a pointer to a statically-allocated structure + containing information about the group whose group name is @var{name}. + This structure may be overwritten by subsequent calls to +@@ -1794,6 +2457,14 @@ + @comment grp.h + @comment POSIX.1c + @deftypefun int getgrnam_r (const char *@var{name}, struct group *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct group **@var{result}) ++@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c getgrnam_r =~ getpwnam_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nscd_getgrnam_r @ascuheap @asulock @aculock @acsfd @acsmem ++@c strlen dup ok ++@c nscd_getgr_r dup @ascuheap @asulock @aculock @acsfd @acsmem ++@c nss_group_lookup2 dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.l @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem + This function is similar to @code{getgrnam} in that is returns + information about the group whose group name is @var{name}. Like + @code{getgrgid_r}, it uses the user supplied buffers in +@@ -1817,6 +2488,16 @@ + @comment grp.h + @comment SVID + @deftypefun {struct group *} fgetgrent (FILE *@var{stream}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:fgrent}}@asunsafe{@asucorrupt{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{}}} ++@c fgetgrent @mtasurace:fgrent @asucorrupt @asulock @acucorrupt @aculock ++@c fgetpos dup @asucorrupt @aculock @acucorrupt ++@c libc_lock_lock dup @asulock @aculock ++@c malloc dup @ascuheap @acsmem ++@c fgetgrent_r dup @asucorrupt @acucorrupt @aculock ++@c realloc dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c fsetpos dup @asucorrupt @aculock @acucorrupt ++@c libc_lock_unlock dup @aculock + The @code{fgetgrent} function reads the next entry from @var{stream}. + It returns a pointer to the entry. The structure is statically + allocated and is overwritten on subsequent calls to @code{fgetgrent}. You +@@ -1830,6 +2511,14 @@ + @comment grp.h + @comment GNU + @deftypefun int fgetgrent_r (FILE *@var{stream}, struct group *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct group **@var{result}) ++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}} ++@c fgetgrent_r @asucorrupt @acucorrupt @aculock ++@c flockfile dup @aculock ++@c fgets_unlocked @asucorrupt @acucorrupt [no @mtsrace due to explicit locking] ++@c feof_unlocked dup ok ++@c funlockfile dup @aculock ++@c isspace dup @mtslocale^^ ++@c parse_line dup ok + This function is similar to @code{fgetgrent} in that it reads the next + user entry from @var{stream}. But the result is returned in the + structure pointed to by @var{result_buf}. The first @var{buflen} bytes +@@ -1852,6 +2541,9 @@ + @comment grp.h + @comment SVID, BSD + @deftypefun void setgrent (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:grent} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c setgrent =~ setpwent dup @mtasurace:grent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c ...*lookup_fct = nss_group_lookup2 dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem + This function initializes a stream for reading from the group data base. + You use this stream by calling @code{getgrent} or @code{getgrent_r}. + @end deftypefun +@@ -1859,6 +2551,9 @@ + @comment grp.h + @comment SVID, BSD + @deftypefun {struct group *} getgrent (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:grent} @mtasurace{:grentbuf} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c getgrent =~ getpwent dup @mtasurace:grent @mtasurace:grentbuf @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *func = getgrent_r dup @mtasurace:grent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem + The @code{getgrent} function reads the next entry from the stream + initialized by @code{setgrent}. It returns a pointer to the entry. The + structure is statically allocated and is overwritten on subsequent calls +@@ -1869,6 +2564,8 @@ + @comment grp.h + @comment GNU + @deftypefun int getgrent_r (struct group *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct group **@var{result}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:grent} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c getgrent_r =~ getpwent_r dup @mtasurace:grent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem + This function is similar to @code{getgrent} in that it returns the next + entry from the stream initialized by @code{setgrent}. Like + @code{fgetgrent_r}, it places the result in user-supplied buffers +@@ -1882,6 +2579,8 @@ + @comment grp.h + @comment SVID, BSD + @deftypefun void endgrent (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:grent} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c endgrent =~ endpwent dup @mtasurace:grent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem + This function closes the internal stream used by @code{getgrent} or + @code{getgrent_r}. + @end deftypefun +@@ -1966,6 +2665,40 @@ + @comment netdb.h + @comment BSD + @deftypefun int setnetgrent (const char *@var{netgroup}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:netgrent} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c setnetgrent @mtasurace:netgrent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c nscd_setnetgrent @ascuheap @acsfd @acsmem ++@c __nscd_setnetgrent @ascuheap @acsfd @acsmem ++@c strlen dup ok ++@c nscd_get_map_ref dup @ascuheap @acsfd @acsmem ++@c nscd_cache_search dup ok ++@c nscd_open_socket dup @acsfd ++@c malloc dup @ascuheap @acsmem ++@c readall dup ok ++@c free dup @ascuheap @acsmem ++@c close_not_cancel_no_status dup @acsfd ++@c nscd_drop_map_ref dup @ascuheap @acsmem ++@c nscd_unmap dup @ascuheap @acsmem ++@c internal_setnetgrent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c free_memory dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c internal_setnetgrent_reuse @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c endnetgrent_hook dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nss_lookup_function dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *endfct @ascuplugin ++@c (netgroup::)setup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nss_netgroup_lookup dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nss_netgroup_lookup2 =~ nss_passwd_lookup2 dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nss_lookup dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct.f @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nss_lookup_function dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *endfct @ascuplugin ++@c strlen dup ok ++@c malloc dup @ascuheap @acsmem ++@c memcpy dup ok ++@c libc_lock_unlock dup @aculock + A call to this function initializes the internal state of the library to + allow following calls of the @code{getnetgrent} to iterate over all entries + in the netgroup with name @var{netgroup}. +@@ -1991,6 +2724,12 @@ + @comment netdb.h + @comment BSD + @deftypefun int getnetgrent (char **@var{hostp}, char **@var{userp}, char **@var{domainp}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:netgrent} @mtasurace{:netgrentbuf} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c getnetgrent @mtasurace:netgrent @mtasurace:netgrentbuf @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c uses unsafely a static buffer allocated within a libc_once call ++@c allocate (libc_once) @ascuheap @acsmem ++@c malloc dup @ascuheap @acsmem ++@c getnetgrent_r dup @mtasurace:netgrent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem + This function returns the next unprocessed entry of the currently + selected netgroup. The string pointers, in which addresses are passed in + the arguments @var{hostp}, @var{userp}, and @var{domainp}, will contain +@@ -2005,7 +2744,20 @@ + + @comment netdb.h + @comment GNU +-@deftypefun int getnetgrent_r (char **@var{hostp}, char **@var{userp}, char **@var{domainp}, char *@var{buffer}, int @var{buflen}) ++@deftypefun int getnetgrent_r (char **@var{hostp}, char **@var{userp}, char **@var{domainp}, char *@var{buffer}, size_t @var{buflen}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:netgrent} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c getnetgrent_r @mtasurace:netgrent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c internal_getnetgrent_r @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nss_lookup_function dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *fct @ascuplugin ++@c nscd_getnetgrent ok ++@c rawmemchr dup ok ++@c internal_setnetgrent_reuse dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c strcmp dup ok ++@c malloc dup @ascuheap @acsmem ++@c memcpy dup ok ++@c libc_lock_unlock dup @aculock + This function is similar to @code{getnetgrent} with only one exception: + the strings the three string pointers @var{hostp}, @var{userp}, and + @var{domainp} point to, are placed in the buffer of @var{buflen} bytes +@@ -2024,6 +2776,13 @@ + @comment netdb.h + @comment BSD + @deftypefun void endnetgrent (void) ++@safety{@prelim{}@mtunsafe{@mtasurace{:netgrent}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c endnetgrent @mtasurace:netgrent @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c libc_lock_lock dup @asulock @aculock ++@c internal_endnetgrent @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c endnetgrent_hook dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c free_memory dup @ascuheap @acsmem ++@c libc_lock_unlock dup @aculock + This function frees all buffers which were allocated to process the last + selected netgroup. As a result all string pointers returned by calls + to @code{getnetgrent} are invalid afterwards. +@@ -2039,6 +2798,37 @@ + @comment netdb.h + @comment BSD + @deftypefun int innetgr (const char *@var{netgroup}, const char *@var{host}, const char *@var{user}, const char *@var{domain}) ++@safety{@prelim{}@mtunsafe{@mtasurace{:netgrent} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} ++@c This function does not use the static data structure that the ++@c *netgrent* ones do, but since each nss must maintains internal state ++@c to support iteration and concurrent iteration will interfere ++@c destructively, we regard this internal state as a static buffer. ++@c getnetgrent_r iteration in each nss backend. ++@c innetgr @mtasurace:netgrent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c nscd_innetgr @ascuheap @acsfd @acsmem ++@c strlen dup ok ++@c malloc dup @ascuheap @acsmem ++@c stpcpy dup ok ++@c nscd_get_map_ref dup @ascuheap @acsfd @acsmem ++@c nscd_cache_search dup ok ++@c nscd_open_socket dup @acsfd ++@c close_not_cancel_no_status dup @acsfd ++@c nscd_drop_map_ref dup @ascuheap @acsmem ++@c nscd_unmap dup @ascuheap @acsmem ++@c free dup @ascuheap @acsmem ++@c memset dup ok ++@c (netgroup::)setup dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *setfct.f @ascuplugin ++@c nss_lookup_function dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c *getfct @ascuplugin ++@c strcmp dup ok ++@c strlen dup ok ++@c malloc dup @ascuheap @acsmem ++@c memcpy dup ok ++@c strcasecmp dup ++@c *endfct @ascuplugin ++@c nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem ++@c free_memory dup @ascuheap @acsmem + This function tests whether the triple specified by the parameters + @var{hostp}, @var{userp}, and @var{domainp} is part of the netgroup + @var{netgroup}. Using this function has the advantage that +@@ -2062,3 +2852,7 @@ + itself is not found, the netgroup does not contain the triple or + internal errors occurred. + @end deftypefun ++ ++@c FIXME these are undocumented: ++@c setresgid ++@c setresuid diff --git a/SOURCES/glibc-powerpc-ldbl_high.patch b/SOURCES/glibc-powerpc-ldbl_high.patch new file mode 100644 index 0000000..68faeee --- /dev/null +++ b/SOURCES/glibc-powerpc-ldbl_high.patch @@ -0,0 +1,13 @@ +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h 2014-05-27 19:59:00.000000000 -0500 +@@ -190,6 +190,9 @@ + # define ldbl_unpack default_ldbl_unpack + #endif + ++/* Extract high double. */ ++#define ldbl_high(x) ((double) x) ++ + /* Convert a finite long double to canonical form. + Does not handle +/-Inf properly. */ + static inline void diff --git a/SOURCES/glibc-ppc64le-01.patch b/SOURCES/glibc-ppc64le-01.patch new file mode 100644 index 0000000..e2a86d7 --- /dev/null +++ b/SOURCES/glibc-ppc64le-01.patch @@ -0,0 +1,83 @@ +# commit 1695c7737655241e1773bdddc93e82c22d8d1584 +# Author: Adhemerval Zanella +# Date: Tue Feb 4 09:48:47 2014 -0200 +# +# abilist-pattern configurability +# +# This patch creates implicit rules to match the abifiles if +# abilist-pattern is defined in the architecture Makefile. This allows +# machine specific Makefiles to define different abifiles names +# (for instance *-le.abilist for powerpc64le). +# +diff -urN glibc-2.17-c758a686/Makerules glibc-2.17-c758a686/Makerules +--- glibc-2.17-c758a686/Makerules 2014-06-02 15:29:42.000000000 +0000 ++++ glibc-2.17-c758a686/Makerules 2014-06-02 15:25:21.000000000 +0000 +@@ -1152,6 +1152,14 @@ + LC_ALL=C $(OBJDUMP) --dynamic-syms $< > $@T + mv -f $@T $@ + ++# A sysdeps/.../Makefile can set abilist-pattern to something like ++# %-foo.abilist to look for libc-foo.abilist instead of libc.abilist. ++# This makes sense if multiple ABIs can be most cleanly supported by a ++# configuration without using separate sysdeps directories for each. ++ifdef abilist-pattern ++vpath $(abilist-pattern) $(+sysdep_dirs) ++endif ++ + vpath %.abilist $(+sysdep_dirs) + + # The .PRECIOUS rule prevents the files built by an implicit rule whose +@@ -1161,18 +1169,42 @@ + .PRECIOUS: %.symlist + generated += $(extra-libs:=.symlist) + ++ifdef abilist-pattern ++check-abi-%: $(common-objpfx)config.make $(abilist-pattern) $(objpfx)%.symlist ++ $(check-abi-pattern) ++check-abi-%: $(common-objpfx)config.make $(abilist-pattern) \ ++ $(common-objpfx)%.symlist ++ $(check-abi-pattern) ++endif + check-abi-%: $(common-objpfx)config.make %.abilist $(objpfx)%.symlist + $(check-abi) + check-abi-%: $(common-objpfx)config.make %.abilist $(common-objpfx)%.symlist + $(check-abi) ++define check-abi-pattern ++ diff -p -U 0 $(filter $(abilist-pattern),$^) $(filter %.symlist,$^) ++endef + define check-abi + diff -p -U 0 $(filter %.abilist,$^) $(filter %.symlist,$^) + endef + ++ifdef abilist-pattern ++update-abi-%: $(objpfx)%.symlist $(abilist-pattern) ++ $(update-abi-pattern) ++update-abi-%: $(common-objpfx)%.symlist $(abilist-pattern) ++ $(update-abi-pattern) ++endif + update-abi-%: $(objpfx)%.symlist %.abilist + $(update-abi) + update-abi-%: $(common-objpfx)%.symlist %.abilist + $(update-abi) ++define update-abi-pattern ++@if cmp -s $^ 2> /dev/null; \ ++ then \ ++ echo '+++ $(filter $(abilist-pattern),$^) is unchanged'; \ ++ else cp -f $^; \ ++ echo '*** Now check $(filter $(abilist-pattern),$^) changes for correctness ***'; \ ++ fi ++endef + define update-abi + @if cmp -s $^ 2> /dev/null; \ + then \ +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/Makefile glibc-2.17-c758a686/sysdeps/powerpc/Makefile +--- glibc-2.17-c758a686/sysdeps/powerpc/Makefile 2014-06-02 15:29:42.000000000 +0000 ++++ glibc-2.17-c758a686/sysdeps/powerpc/Makefile 2014-06-02 15:25:21.000000000 +0000 +@@ -27,3 +27,7 @@ + sysdep_headers += sys/platform/ppc.h + tests += test-gettimebase + endif ++ ++ifneq (,$(filter %le,$(config-machine))) ++abilist-pattern = %-le.abilist ++endif diff --git a/SOURCES/glibc-ppc64le-02.patch b/SOURCES/glibc-ppc64le-02.patch new file mode 100644 index 0000000..3878826 --- /dev/null +++ b/SOURCES/glibc-ppc64le-02.patch @@ -0,0 +1,3197 @@ +# co`mmit c01603f763003cec55234ac757c7a934652caa55 +# Author: Adhemerval Zanella +# Date: Tue Feb 4 09:49:34 2014 -0200 +# +# PowerPC: powerpc64le abilist for 2.17 +# +# This patch is the abifiles for powerpc64le based on GLIBC 2.17. +# +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/ld-le.abilist glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/ld-le.abilist +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/ld-le.abilist 1970-01-01 00:00:00.000000000 +0000 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/ld-le.abilist 2014-06-02 15:22:40.000000000 +0000 +@@ -0,0 +1,11 @@ ++GLIBC_2.17 ++ GLIBC_2.17 A ++ __libc_memalign F ++ __libc_stack_end D 0x8 ++ __tls_get_addr F ++ _dl_mcount F ++ _r_debug D 0x28 ++ calloc F ++ free F ++ malloc F ++ realloc F +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libBrokenLocale-le.abilist glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libBrokenLocale-le.abilist +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libBrokenLocale-le.abilist 1970-01-01 00:00:00.000000000 +0000 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libBrokenLocale-le.abilist 2014-06-02 15:22:40.000000000 +0000 +@@ -0,0 +1,3 @@ ++GLIBC_2.17 ++ GLIBC_2.17 A ++ __ctype_get_mb_cur_max F +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libanl-le.abilist glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libanl-le.abilist +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libanl-le.abilist 1970-01-01 00:00:00.000000000 +0000 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libanl-le.abilist 2014-06-02 15:22:40.000000000 +0000 +@@ -0,0 +1,6 @@ ++GLIBC_2.17 ++ GLIBC_2.17 A ++ gai_cancel F ++ gai_error F ++ gai_suspend F ++ getaddrinfo_a F +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libc-le.abilist glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libc-le.abilist +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libc-le.abilist 1970-01-01 00:00:00.000000000 +0000 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libc-le.abilist 2014-06-02 15:22:40.000000000 +0000 +@@ -0,0 +1,2168 @@ ++GLIBC_2.17 ++ GLIBC_2.17 A ++ _Exit F ++ _IO_2_1_stderr_ D 0xe0 ++ _IO_2_1_stdin_ D 0xe0 ++ _IO_2_1_stdout_ D 0xe0 ++ _IO_adjust_column F ++ _IO_adjust_wcolumn F ++ _IO_default_doallocate F ++ _IO_default_finish F ++ _IO_default_pbackfail F ++ _IO_default_uflow F ++ _IO_default_xsgetn F ++ _IO_default_xsputn F ++ _IO_do_write F ++ _IO_doallocbuf F ++ _IO_fclose F ++ _IO_fdopen F ++ _IO_feof F ++ _IO_ferror F ++ _IO_fflush F ++ _IO_fgetpos F ++ _IO_fgetpos64 F ++ _IO_fgets F ++ _IO_file_attach F ++ _IO_file_close F ++ _IO_file_close_it F ++ _IO_file_doallocate F ++ _IO_file_finish F ++ _IO_file_fopen F ++ _IO_file_init F ++ _IO_file_jumps D 0xa8 ++ _IO_file_open F ++ _IO_file_overflow F ++ _IO_file_read F ++ _IO_file_seek F ++ _IO_file_seekoff F ++ _IO_file_setbuf F ++ _IO_file_stat F ++ _IO_file_sync F ++ _IO_file_underflow F ++ _IO_file_write F ++ _IO_file_xsputn F ++ _IO_flockfile F ++ _IO_flush_all F ++ _IO_flush_all_linebuffered F ++ _IO_fopen F ++ _IO_fprintf F ++ _IO_fputs F ++ _IO_fread F ++ _IO_free_backup_area F ++ _IO_free_wbackup_area F ++ _IO_fsetpos F ++ _IO_fsetpos64 F ++ _IO_ftell F ++ _IO_ftrylockfile F ++ _IO_funlockfile F ++ _IO_fwrite F ++ _IO_getc F ++ _IO_getline F ++ _IO_getline_info F ++ _IO_gets F ++ _IO_init F ++ _IO_init_marker F ++ _IO_init_wmarker F ++ _IO_iter_begin F ++ _IO_iter_end F ++ _IO_iter_file F ++ _IO_iter_next F ++ _IO_least_wmarker F ++ _IO_link_in F ++ _IO_list_all D 0x8 ++ _IO_list_lock F ++ _IO_list_resetlock F ++ _IO_list_unlock F ++ _IO_marker_delta F ++ _IO_marker_difference F ++ _IO_padn F ++ _IO_peekc_locked F ++ _IO_popen F ++ _IO_printf F ++ _IO_proc_close F ++ _IO_proc_open F ++ _IO_putc F ++ _IO_puts F ++ _IO_remove_marker F ++ _IO_seekmark F ++ _IO_seekoff F ++ _IO_seekpos F ++ _IO_seekwmark F ++ _IO_setb F ++ _IO_setbuffer F ++ _IO_setvbuf F ++ _IO_sgetn F ++ _IO_sprintf F ++ _IO_sputbackc F ++ _IO_sputbackwc F ++ _IO_sscanf F ++ _IO_str_init_readonly F ++ _IO_str_init_static F ++ _IO_str_overflow F ++ _IO_str_pbackfail F ++ _IO_str_seekoff F ++ _IO_str_underflow F ++ _IO_sungetc F ++ _IO_sungetwc F ++ _IO_switch_to_get_mode F ++ _IO_switch_to_main_wget_area F ++ _IO_switch_to_wbackup_area F ++ _IO_switch_to_wget_mode F ++ _IO_un_link F ++ _IO_ungetc F ++ _IO_unsave_markers F ++ _IO_unsave_wmarkers F ++ _IO_vfprintf F ++ _IO_vfscanf F ++ _IO_vsprintf F ++ _IO_wdefault_doallocate F ++ _IO_wdefault_finish F ++ _IO_wdefault_pbackfail F ++ _IO_wdefault_uflow F ++ _IO_wdefault_xsgetn F ++ _IO_wdefault_xsputn F ++ _IO_wdo_write F ++ _IO_wdoallocbuf F ++ _IO_wfile_jumps D 0xa8 ++ _IO_wfile_overflow F ++ _IO_wfile_seekoff F ++ _IO_wfile_sync F ++ _IO_wfile_underflow F ++ _IO_wfile_xsputn F ++ _IO_wmarker_delta F ++ _IO_wsetb F ++ __adjtimex F ++ __after_morecore_hook D 0x8 ++ __argz_count F ++ __argz_next F ++ __argz_stringify F ++ __asprintf F ++ __asprintf_chk F ++ __assert F ++ __assert_fail F ++ __assert_perror_fail F ++ __backtrace F ++ __backtrace_symbols F ++ __backtrace_symbols_fd F ++ __bsd_getpgrp F ++ __bzero F ++ __check_rhosts_file D 0x4 ++ __chk_fail F ++ __clone F ++ __close F ++ __cmsg_nxthdr F ++ __confstr_chk F ++ __connect F ++ __ctype_b_loc F ++ __ctype_get_mb_cur_max F ++ __ctype_tolower_loc F ++ __ctype_toupper_loc F ++ __curbrk D 0x8 ++ __cxa_at_quick_exit F ++ __cxa_atexit F ++ __cxa_finalize F ++ __cyg_profile_func_enter F ++ __cyg_profile_func_exit F ++ __daylight D 0x4 ++ __dcgettext F ++ __default_morecore F ++ __dgettext F ++ __dprintf_chk F ++ __dup2 F ++ __duplocale F ++ __endmntent F ++ __environ D 0x8 ++ __errno_location F ++ __fbufsize F ++ __fcntl F ++ __fdelt_chk F ++ __fdelt_warn F ++ __ffs F ++ __fgets_chk F ++ __fgets_unlocked_chk F ++ __fgetws_chk F ++ __fgetws_unlocked_chk F ++ __finite F ++ __finitef F ++ __finitel F ++ __flbf F ++ __fork F ++ __fpending F ++ __fprintf_chk F ++ __fpu_control D 0x4 ++ __fpurge F ++ __fread_chk F ++ __fread_unlocked_chk F ++ __freadable F ++ __freading F ++ __free_hook D 0x8 ++ __freelocale F ++ __fsetlocking F ++ __fwprintf_chk F ++ __fwritable F ++ __fwriting F ++ __fxstat F ++ __fxstat64 F ++ __fxstatat F ++ __fxstatat64 F ++ __getauxval F ++ __getcwd_chk F ++ __getdelim F ++ __getdomainname_chk F ++ __getgroups_chk F ++ __gethostname_chk F ++ __getlogin_r_chk F ++ __getmntent_r F ++ __getpagesize F ++ __getpgid F ++ __getpid F ++ __gets_chk F ++ __gettimeofday F ++ __getwd_chk F ++ __gmtime_r F ++ __h_errno_location F ++ __isalnum_l F ++ __isalpha_l F ++ __isascii_l F ++ __isblank_l F ++ __iscntrl_l F ++ __isctype F ++ __isdigit_l F ++ __isgraph_l F ++ __isinf F ++ __isinff F ++ __isinfl F ++ __islower_l F ++ __isnan F ++ __isnanf F ++ __isnanl F ++ __isoc99_fscanf F ++ __isoc99_fwscanf F ++ __isoc99_scanf F ++ __isoc99_sscanf F ++ __isoc99_swscanf F ++ __isoc99_vfscanf F ++ __isoc99_vfwscanf F ++ __isoc99_vscanf F ++ __isoc99_vsscanf F ++ __isoc99_vswscanf F ++ __isoc99_vwscanf F ++ __isoc99_wscanf F ++ __isprint_l F ++ __ispunct_l F ++ __isspace_l F ++ __isupper_l F ++ __iswalnum_l F ++ __iswalpha_l F ++ __iswblank_l F ++ __iswcntrl_l F ++ __iswctype F ++ __iswctype_l F ++ __iswdigit_l F ++ __iswgraph_l F ++ __iswlower_l F ++ __iswprint_l F ++ __iswpunct_l F ++ __iswspace_l F ++ __iswupper_l F ++ __iswxdigit_l F ++ __isxdigit_l F ++ __ivaliduser F ++ __key_decryptsession_pk_LOCAL D 0x8 ++ __key_encryptsession_pk_LOCAL D 0x8 ++ __key_gendes_LOCAL D 0x8 ++ __libc_allocate_rtsig F ++ __libc_calloc F ++ __libc_current_sigrtmax F ++ __libc_current_sigrtmin F ++ __libc_free F ++ __libc_freeres F ++ __libc_init_first F ++ __libc_mallinfo F ++ __libc_malloc F ++ __libc_mallopt F ++ __libc_memalign F ++ __libc_pvalloc F ++ __libc_realloc F ++ __libc_sa_len F ++ __libc_start_main F ++ __libc_valloc F ++ __longjmp_chk F ++ __lseek F ++ __lxstat F ++ __lxstat64 F ++ __malloc_hook D 0x8 ++ __malloc_initialize_hook D 0x8 ++ __mbrlen F ++ __mbrtowc F ++ __mbsnrtowcs_chk F ++ __mbsrtowcs_chk F ++ __mbstowcs_chk F ++ __memalign_hook D 0x8 ++ __memcpy_chk F ++ __memmove_chk F ++ __mempcpy F ++ __mempcpy_chk F ++ __mempcpy_small F ++ __memset_chk F ++ __monstartup F ++ __morecore D 0x8 ++ __nanosleep F ++ __newlocale F ++ __nl_langinfo_l F ++ __nldbl__IO_fprintf F ++ __nldbl__IO_printf F ++ __nldbl__IO_sprintf F ++ __nldbl__IO_sscanf F ++ __nldbl__IO_vfprintf F ++ __nldbl__IO_vfscanf F ++ __nldbl__IO_vsprintf F ++ __nldbl___asprintf F ++ __nldbl___asprintf_chk F ++ __nldbl___dprintf_chk F ++ __nldbl___fprintf_chk F ++ __nldbl___fwprintf_chk F ++ __nldbl___isoc99_fscanf F ++ __nldbl___isoc99_fwscanf F ++ __nldbl___isoc99_scanf F ++ __nldbl___isoc99_sscanf F ++ __nldbl___isoc99_swscanf F ++ __nldbl___isoc99_vfscanf F ++ __nldbl___isoc99_vfwscanf F ++ __nldbl___isoc99_vscanf F ++ __nldbl___isoc99_vsscanf F ++ __nldbl___isoc99_vswscanf F ++ __nldbl___isoc99_vwscanf F ++ __nldbl___isoc99_wscanf F ++ __nldbl___obstack_printf_chk F ++ __nldbl___obstack_vprintf_chk F ++ __nldbl___printf_chk F ++ __nldbl___printf_fp F ++ __nldbl___snprintf_chk F ++ __nldbl___sprintf_chk F ++ __nldbl___strfmon_l F ++ __nldbl___swprintf_chk F ++ __nldbl___syslog_chk F ++ __nldbl___vasprintf_chk F ++ __nldbl___vdprintf_chk F ++ __nldbl___vfprintf_chk F ++ __nldbl___vfscanf F ++ __nldbl___vfwprintf_chk F ++ __nldbl___vprintf_chk F ++ __nldbl___vsnprintf F ++ __nldbl___vsnprintf_chk F ++ __nldbl___vsprintf_chk F ++ __nldbl___vsscanf F ++ __nldbl___vstrfmon F ++ __nldbl___vstrfmon_l F ++ __nldbl___vswprintf_chk F ++ __nldbl___vsyslog_chk F ++ __nldbl___vwprintf_chk F ++ __nldbl___wprintf_chk F ++ __nldbl_asprintf F ++ __nldbl_dprintf F ++ __nldbl_fprintf F ++ __nldbl_fscanf F ++ __nldbl_fwprintf F ++ __nldbl_fwscanf F ++ __nldbl_obstack_printf F ++ __nldbl_obstack_vprintf F ++ __nldbl_printf F ++ __nldbl_printf_size F ++ __nldbl_scanf F ++ __nldbl_snprintf F ++ __nldbl_sprintf F ++ __nldbl_sscanf F ++ __nldbl_strfmon F ++ __nldbl_strfmon_l F ++ __nldbl_swprintf F ++ __nldbl_swscanf F ++ __nldbl_syslog F ++ __nldbl_vasprintf F ++ __nldbl_vdprintf F ++ __nldbl_vfprintf F ++ __nldbl_vfscanf F ++ __nldbl_vfwprintf F ++ __nldbl_vfwscanf F ++ __nldbl_vprintf F ++ __nldbl_vscanf F ++ __nldbl_vsnprintf F ++ __nldbl_vsprintf F ++ __nldbl_vsscanf F ++ __nldbl_vswprintf F ++ __nldbl_vswscanf F ++ __nldbl_vsyslog F ++ __nldbl_vwprintf F ++ __nldbl_vwscanf F ++ __nldbl_wprintf F ++ __nldbl_wscanf F ++ __nss_configure_lookup F ++ __nss_database_lookup F ++ __nss_group_lookup F ++ __nss_hostname_digits_dots F ++ __nss_hosts_lookup F ++ __nss_next F ++ __nss_passwd_lookup F ++ __obstack_printf_chk F ++ __obstack_vprintf_chk F ++ __open F ++ __open64 F ++ __open64_2 F ++ __open_2 F ++ __openat64_2 F ++ __openat_2 F ++ __overflow F ++ __pipe F ++ __poll F ++ __poll_chk F ++ __posix_getopt F ++ __ppc_get_timebase_freq F ++ __ppoll_chk F ++ __pread64 F ++ __pread64_chk F ++ __pread_chk F ++ __printf_chk F ++ __printf_fp F ++ __profile_frequency F ++ __progname D 0x8 ++ __progname_full D 0x8 ++ __ptsname_r_chk F ++ __pwrite64 F ++ __rawmemchr F ++ __rcmd_errstr D 0x8 ++ __read F ++ __read_chk F ++ __readlink_chk F ++ __readlinkat_chk F ++ __realloc_hook D 0x8 ++ __realpath_chk F ++ __recv_chk F ++ __recvfrom_chk F ++ __register_atfork F ++ __res_init F ++ __res_nclose F ++ __res_ninit F ++ __res_randomid F ++ __res_state F ++ __rpc_thread_createerr F ++ __rpc_thread_svc_fdset F ++ __rpc_thread_svc_max_pollfd F ++ __rpc_thread_svc_pollfd F ++ __sbrk F ++ __sched_cpualloc F ++ __sched_cpucount F ++ __sched_cpufree F ++ __sched_get_priority_max F ++ __sched_get_priority_min F ++ __sched_getparam F ++ __sched_getscheduler F ++ __sched_setscheduler F ++ __sched_yield F ++ __select F ++ __send F ++ __setmntent F ++ __setpgid F ++ __sigaction F ++ __sigaddset F ++ __sigdelset F ++ __sigismember F ++ __signbit F ++ __signbitf F ++ __signbitl F ++ __sigpause F ++ __sigsetjmp F ++ __sigsuspend F ++ __snprintf_chk F ++ __sprintf_chk F ++ __stack_chk_fail F ++ __statfs F ++ __stpcpy F ++ __stpcpy_chk F ++ __stpcpy_small F ++ __stpncpy F ++ __stpncpy_chk F ++ __strcasecmp F ++ __strcasecmp_l F ++ __strcasestr F ++ __strcat_chk F ++ __strcoll_l F ++ __strcpy_chk F ++ __strcpy_small F ++ __strcspn_c1 F ++ __strcspn_c2 F ++ __strcspn_c3 F ++ __strdup F ++ __strerror_r F ++ __strfmon_l F ++ __strftime_l F ++ __strncasecmp_l F ++ __strncat_chk F ++ __strncpy_chk F ++ __strndup F ++ __strpbrk_c2 F ++ __strpbrk_c3 F ++ __strsep_1c F ++ __strsep_2c F ++ __strsep_3c F ++ __strsep_g F ++ __strspn_c1 F ++ __strspn_c2 F ++ __strspn_c3 F ++ __strtod_internal F ++ __strtod_l F ++ __strtof_internal F ++ __strtof_l F ++ __strtok_r F ++ __strtok_r_1c F ++ __strtol_internal F ++ __strtol_l F ++ __strtold_internal F ++ __strtold_l F ++ __strtoll_internal F ++ __strtoll_l F ++ __strtoul_internal F ++ __strtoul_l F ++ __strtoull_internal F ++ __strtoull_l F ++ __strverscmp F ++ __strxfrm_l F ++ __swprintf_chk F ++ __sysconf F ++ __sysctl F ++ __syslog_chk F ++ __sysv_signal F ++ __timezone D 0x8 ++ __toascii_l F ++ __tolower_l F ++ __toupper_l F ++ __towctrans F ++ __towctrans_l F ++ __towlower_l F ++ __towupper_l F ++ __ttyname_r_chk F ++ __tzname D 0x10 ++ __uflow F ++ __underflow F ++ __uselocale F ++ __vasprintf_chk F ++ __vdprintf_chk F ++ __vfork F ++ __vfprintf_chk F ++ __vfscanf F ++ __vfwprintf_chk F ++ __vprintf_chk F ++ __vsnprintf F ++ __vsnprintf_chk F ++ __vsprintf_chk F ++ __vsscanf F ++ __vswprintf_chk F ++ __vsyslog_chk F ++ __vwprintf_chk F ++ __wait F ++ __waitpid F ++ __wcpcpy_chk F ++ __wcpncpy_chk F ++ __wcrtomb_chk F ++ __wcscasecmp_l F ++ __wcscat_chk F ++ __wcscoll_l F ++ __wcscpy_chk F ++ __wcsftime_l F ++ __wcsncasecmp_l F ++ __wcsncat_chk F ++ __wcsncpy_chk F ++ __wcsnrtombs_chk F ++ __wcsrtombs_chk F ++ __wcstod_internal F ++ __wcstod_l F ++ __wcstof_internal F ++ __wcstof_l F ++ __wcstol_internal F ++ __wcstol_l F ++ __wcstold_internal F ++ __wcstold_l F ++ __wcstoll_internal F ++ __wcstoll_l F ++ __wcstombs_chk F ++ __wcstoul_internal F ++ __wcstoul_l F ++ __wcstoull_internal F ++ __wcstoull_l F ++ __wcsxfrm_l F ++ __wctomb_chk F ++ __wctrans_l F ++ __wctype_l F ++ __wmemcpy_chk F ++ __wmemmove_chk F ++ __wmempcpy_chk F ++ __wmemset_chk F ++ __woverflow F ++ __wprintf_chk F ++ __write F ++ __wuflow F ++ __wunderflow F ++ __xmknod F ++ __xmknodat F ++ __xpg_basename F ++ __xpg_sigpause F ++ __xpg_strerror_r F ++ __xstat F ++ __xstat64 F ++ _authenticate F ++ _dl_mcount_wrapper F ++ _dl_mcount_wrapper_check F ++ _environ D 0x8 ++ _exit F ++ _flushlbf F ++ _libc_intl_domainname D 0x5 ++ _longjmp F ++ _mcleanup F ++ _mcount F ++ _nl_default_dirname D 0x12 ++ _nl_domain_bindings D 0x8 ++ _nl_msg_cat_cntr D 0x4 ++ _null_auth D 0x18 ++ _obstack_allocated_p F ++ _obstack_begin F ++ _obstack_begin_1 F ++ _obstack_free F ++ _obstack_memory_used F ++ _obstack_newchunk F ++ _res D 0x238 ++ _res_hconf D 0x48 ++ _rpc_dtablesize F ++ _seterr_reply F ++ _setjmp F ++ _sys_errlist D 0x438 ++ _sys_nerr D 0x4 ++ _sys_siglist D 0x208 ++ _tolower F ++ _toupper F ++ a64l F ++ abort F ++ abs F ++ accept F ++ accept4 F ++ access F ++ acct F ++ addmntent F ++ addseverity F ++ adjtime F ++ adjtimex F ++ advance F ++ alarm F ++ aligned_alloc F ++ alphasort F ++ alphasort64 F ++ argp_err_exit_status D 0x4 ++ argp_error F ++ argp_failure F ++ argp_help F ++ argp_parse F ++ argp_program_bug_address D 0x8 ++ argp_program_version D 0x8 ++ argp_program_version_hook D 0x8 ++ argp_state_help F ++ argp_usage F ++ argz_add F ++ argz_add_sep F ++ argz_append F ++ argz_count F ++ argz_create F ++ argz_create_sep F ++ argz_delete F ++ argz_extract F ++ argz_insert F ++ argz_next F ++ argz_replace F ++ argz_stringify F ++ asctime F ++ asctime_r F ++ asprintf F ++ atof F ++ atoi F ++ atol F ++ atoll F ++ authdes_create F ++ authdes_getucred F ++ authdes_pk_create F ++ authnone_create F ++ authunix_create F ++ authunix_create_default F ++ backtrace F ++ backtrace_symbols F ++ backtrace_symbols_fd F ++ basename F ++ bcmp F ++ bcopy F ++ bdflush F ++ bind F ++ bind_textdomain_codeset F ++ bindresvport F ++ bindtextdomain F ++ brk F ++ bsd_signal F ++ bsearch F ++ btowc F ++ bzero F ++ c16rtomb F ++ c32rtomb F ++ calloc F ++ callrpc F ++ canonicalize_file_name F ++ capget F ++ capset F ++ catclose F ++ catgets F ++ catopen F ++ cbc_crypt F ++ cfgetispeed F ++ cfgetospeed F ++ cfmakeraw F ++ cfree F ++ cfsetispeed F ++ cfsetospeed F ++ cfsetspeed F ++ chdir F ++ chflags F ++ chmod F ++ chown F ++ chroot F ++ clearenv F ++ clearerr F ++ clearerr_unlocked F ++ clnt_broadcast F ++ clnt_create F ++ clnt_pcreateerror F ++ clnt_perrno F ++ clnt_perror F ++ clnt_spcreateerror F ++ clnt_sperrno F ++ clnt_sperror F ++ clntraw_create F ++ clnttcp_create F ++ clntudp_bufcreate F ++ clntudp_create F ++ clntunix_create F ++ clock F ++ clock_adjtime F ++ clock_getcpuclockid F ++ clock_getres F ++ clock_gettime F ++ clock_nanosleep F ++ clock_settime F ++ clone F ++ close F ++ closedir F ++ closelog F ++ confstr F ++ connect F ++ copysign F ++ copysignf F ++ copysignl F ++ creat F ++ creat64 F ++ create_module F ++ ctermid F ++ ctime F ++ ctime_r F ++ cuserid F ++ daemon F ++ daylight D 0x4 ++ dcgettext F ++ dcngettext F ++ delete_module F ++ des_setparity F ++ dgettext F ++ difftime F ++ dirfd F ++ dirname F ++ div F ++ dl_iterate_phdr F ++ dngettext F ++ dprintf F ++ drand48 F ++ drand48_r F ++ dup F ++ dup2 F ++ dup3 F ++ duplocale F ++ dysize F ++ eaccess F ++ ecb_crypt F ++ ecvt F ++ ecvt_r F ++ endaliasent F ++ endfsent F ++ endgrent F ++ endhostent F ++ endmntent F ++ endnetent F ++ endnetgrent F ++ endprotoent F ++ endpwent F ++ endrpcent F ++ endservent F ++ endsgent F ++ endspent F ++ endttyent F ++ endusershell F ++ endutent F ++ endutxent F ++ environ D 0x8 ++ envz_add F ++ envz_entry F ++ envz_get F ++ envz_merge F ++ envz_remove F ++ envz_strip F ++ epoll_create F ++ epoll_create1 F ++ epoll_ctl F ++ epoll_pwait F ++ epoll_wait F ++ erand48 F ++ erand48_r F ++ err F ++ error F ++ error_at_line F ++ error_message_count D 0x4 ++ error_one_per_line D 0x4 ++ error_print_progname D 0x8 ++ errx F ++ ether_aton F ++ ether_aton_r F ++ ether_hostton F ++ ether_line F ++ ether_ntoa F ++ ether_ntoa_r F ++ ether_ntohost F ++ euidaccess F ++ eventfd F ++ eventfd_read F ++ eventfd_write F ++ execl F ++ execle F ++ execlp F ++ execv F ++ execve F ++ execvp F ++ execvpe F ++ exit F ++ faccessat F ++ fallocate F ++ fallocate64 F ++ fanotify_init F ++ fanotify_mark F ++ fattach F ++ fchdir F ++ fchflags F ++ fchmod F ++ fchmodat F ++ fchown F ++ fchownat F ++ fclose F ++ fcloseall F ++ fcntl F ++ fcvt F ++ fcvt_r F ++ fdatasync F ++ fdetach F ++ fdopen F ++ fdopendir F ++ feof F ++ feof_unlocked F ++ ferror F ++ ferror_unlocked F ++ fexecve F ++ fflush F ++ fflush_unlocked F ++ ffs F ++ ffsl F ++ ffsll F ++ fgetc F ++ fgetc_unlocked F ++ fgetgrent F ++ fgetgrent_r F ++ fgetpos F ++ fgetpos64 F ++ fgetpwent F ++ fgetpwent_r F ++ fgets F ++ fgets_unlocked F ++ fgetsgent F ++ fgetsgent_r F ++ fgetspent F ++ fgetspent_r F ++ fgetwc F ++ fgetwc_unlocked F ++ fgetws F ++ fgetws_unlocked F ++ fgetxattr F ++ fileno F ++ fileno_unlocked F ++ finite F ++ finitef F ++ finitel F ++ flistxattr F ++ flock F ++ flockfile F ++ fmemopen F ++ fmtmsg F ++ fnmatch F ++ fopen F ++ fopen64 F ++ fopencookie F ++ fork F ++ fpathconf F ++ fprintf F ++ fputc F ++ fputc_unlocked F ++ fputs F ++ fputs_unlocked F ++ fputwc F ++ fputwc_unlocked F ++ fputws F ++ fputws_unlocked F ++ fread F ++ fread_unlocked F ++ free F ++ freeaddrinfo F ++ freeifaddrs F ++ freelocale F ++ fremovexattr F ++ freopen F ++ freopen64 F ++ frexp F ++ frexpf F ++ frexpl F ++ fscanf F ++ fseek F ++ fseeko F ++ fseeko64 F ++ fsetpos F ++ fsetpos64 F ++ fsetxattr F ++ fstatfs F ++ fstatfs64 F ++ fstatvfs F ++ fstatvfs64 F ++ fsync F ++ ftell F ++ ftello F ++ ftello64 F ++ ftime F ++ ftok F ++ ftruncate F ++ ftruncate64 F ++ ftrylockfile F ++ fts_children F ++ fts_close F ++ fts_open F ++ fts_read F ++ fts_set F ++ ftw F ++ ftw64 F ++ funlockfile F ++ futimens F ++ futimes F ++ futimesat F ++ fwide F ++ fwprintf F ++ fwrite F ++ fwrite_unlocked F ++ fwscanf F ++ gai_strerror F ++ gcvt F ++ get_avphys_pages F ++ get_current_dir_name F ++ get_kernel_syms F ++ get_myaddress F ++ get_nprocs F ++ get_nprocs_conf F ++ get_phys_pages F ++ getaddrinfo F ++ getaliasbyname F ++ getaliasbyname_r F ++ getaliasent F ++ getaliasent_r F ++ getauxval F ++ getc F ++ getc_unlocked F ++ getchar F ++ getchar_unlocked F ++ getcontext F ++ getcwd F ++ getdate F ++ getdate_err D 0x4 ++ getdate_r F ++ getdelim F ++ getdirentries F ++ getdirentries64 F ++ getdomainname F ++ getdtablesize F ++ getegid F ++ getenv F ++ geteuid F ++ getfsent F ++ getfsfile F ++ getfsspec F ++ getgid F ++ getgrent F ++ getgrent_r F ++ getgrgid F ++ getgrgid_r F ++ getgrnam F ++ getgrnam_r F ++ getgrouplist F ++ getgroups F ++ gethostbyaddr F ++ gethostbyaddr_r F ++ gethostbyname F ++ gethostbyname2 F ++ gethostbyname2_r F ++ gethostbyname_r F ++ gethostent F ++ gethostent_r F ++ gethostid F ++ gethostname F ++ getifaddrs F ++ getipv4sourcefilter F ++ getitimer F ++ getline F ++ getloadavg F ++ getlogin F ++ getlogin_r F ++ getmntent F ++ getmntent_r F ++ getmsg F ++ getnameinfo F ++ getnetbyaddr F ++ getnetbyaddr_r F ++ getnetbyname F ++ getnetbyname_r F ++ getnetent F ++ getnetent_r F ++ getnetgrent F ++ getnetgrent_r F ++ getnetname F ++ getopt F ++ getopt_long F ++ getopt_long_only F ++ getpagesize F ++ getpass F ++ getpeername F ++ getpgid F ++ getpgrp F ++ getpid F ++ getpmsg F ++ getppid F ++ getpriority F ++ getprotobyname F ++ getprotobyname_r F ++ getprotobynumber F ++ getprotobynumber_r F ++ getprotoent F ++ getprotoent_r F ++ getpt F ++ getpublickey F ++ getpw F ++ getpwent F ++ getpwent_r F ++ getpwnam F ++ getpwnam_r F ++ getpwuid F ++ getpwuid_r F ++ getresgid F ++ getresuid F ++ getrlimit F ++ getrlimit64 F ++ getrpcbyname F ++ getrpcbyname_r F ++ getrpcbynumber F ++ getrpcbynumber_r F ++ getrpcent F ++ getrpcent_r F ++ getrpcport F ++ getrusage F ++ gets F ++ getsecretkey F ++ getservbyname F ++ getservbyname_r F ++ getservbyport F ++ getservbyport_r F ++ getservent F ++ getservent_r F ++ getsgent F ++ getsgent_r F ++ getsgnam F ++ getsgnam_r F ++ getsid F ++ getsockname F ++ getsockopt F ++ getsourcefilter F ++ getspent F ++ getspent_r F ++ getspnam F ++ getspnam_r F ++ getsubopt F ++ gettext F ++ gettimeofday F ++ getttyent F ++ getttynam F ++ getuid F ++ getusershell F ++ getutent F ++ getutent_r F ++ getutid F ++ getutid_r F ++ getutline F ++ getutline_r F ++ getutmp F ++ getutmpx F ++ getutxent F ++ getutxid F ++ getutxline F ++ getw F ++ getwc F ++ getwc_unlocked F ++ getwchar F ++ getwchar_unlocked F ++ getwd F ++ getxattr F ++ glob F ++ glob64 F ++ glob_pattern_p F ++ globfree F ++ globfree64 F ++ gmtime F ++ gmtime_r F ++ gnu_dev_major F ++ gnu_dev_makedev F ++ gnu_dev_minor F ++ gnu_get_libc_release F ++ gnu_get_libc_version F ++ grantpt F ++ group_member F ++ gsignal F ++ gtty F ++ h_errlist D 0x28 ++ h_nerr D 0x4 ++ hasmntopt F ++ hcreate F ++ hcreate_r F ++ hdestroy F ++ hdestroy_r F ++ herror F ++ host2netname F ++ hsearch F ++ hsearch_r F ++ hstrerror F ++ htonl F ++ htons F ++ iconv F ++ iconv_close F ++ iconv_open F ++ if_freenameindex F ++ if_indextoname F ++ if_nameindex F ++ if_nametoindex F ++ imaxabs F ++ imaxdiv F ++ in6addr_any D 0x10 ++ in6addr_loopback D 0x10 ++ index F ++ inet6_opt_append F ++ inet6_opt_find F ++ inet6_opt_finish F ++ inet6_opt_get_val F ++ inet6_opt_init F ++ inet6_opt_next F ++ inet6_opt_set_val F ++ inet6_option_alloc F ++ inet6_option_append F ++ inet6_option_find F ++ inet6_option_init F ++ inet6_option_next F ++ inet6_option_space F ++ inet6_rth_add F ++ inet6_rth_getaddr F ++ inet6_rth_init F ++ inet6_rth_reverse F ++ inet6_rth_segments F ++ inet6_rth_space F ++ inet_addr F ++ inet_aton F ++ inet_lnaof F ++ inet_makeaddr F ++ inet_netof F ++ inet_network F ++ inet_nsap_addr F ++ inet_nsap_ntoa F ++ inet_ntoa F ++ inet_ntop F ++ inet_pton F ++ init_module F ++ initgroups F ++ initstate F ++ initstate_r F ++ innetgr F ++ inotify_add_watch F ++ inotify_init F ++ inotify_init1 F ++ inotify_rm_watch F ++ insque F ++ ioctl F ++ iruserok F ++ iruserok_af F ++ isalnum F ++ isalnum_l F ++ isalpha F ++ isalpha_l F ++ isascii F ++ isastream F ++ isatty F ++ isblank F ++ isblank_l F ++ iscntrl F ++ iscntrl_l F ++ isctype F ++ isdigit F ++ isdigit_l F ++ isfdtype F ++ isgraph F ++ isgraph_l F ++ isinf F ++ isinff F ++ isinfl F ++ islower F ++ islower_l F ++ isnan F ++ isnanf F ++ isnanl F ++ isprint F ++ isprint_l F ++ ispunct F ++ ispunct_l F ++ isspace F ++ isspace_l F ++ isupper F ++ isupper_l F ++ iswalnum F ++ iswalnum_l F ++ iswalpha F ++ iswalpha_l F ++ iswblank F ++ iswblank_l F ++ iswcntrl F ++ iswcntrl_l F ++ iswctype F ++ iswctype_l F ++ iswdigit F ++ iswdigit_l F ++ iswgraph F ++ iswgraph_l F ++ iswlower F ++ iswlower_l F ++ iswprint F ++ iswprint_l F ++ iswpunct F ++ iswpunct_l F ++ iswspace F ++ iswspace_l F ++ iswupper F ++ iswupper_l F ++ iswxdigit F ++ iswxdigit_l F ++ isxdigit F ++ isxdigit_l F ++ jrand48 F ++ jrand48_r F ++ key_decryptsession F ++ key_decryptsession_pk F ++ key_encryptsession F ++ key_encryptsession_pk F ++ key_gendes F ++ key_get_conv F ++ key_secretkey_is_set F ++ key_setnet F ++ key_setsecret F ++ kill F ++ killpg F ++ klogctl F ++ l64a F ++ labs F ++ lchmod F ++ lchown F ++ lckpwdf F ++ lcong48 F ++ lcong48_r F ++ ldexp F ++ ldexpf F ++ ldexpl F ++ ldiv F ++ lfind F ++ lgetxattr F ++ link F ++ linkat F ++ listen F ++ listxattr F ++ llabs F ++ lldiv F ++ llistxattr F ++ llseek F ++ loc1 D 0x8 ++ loc2 D 0x8 ++ localeconv F ++ localtime F ++ localtime_r F ++ lockf F ++ lockf64 F ++ locs D 0x8 ++ longjmp F ++ lrand48 F ++ lrand48_r F ++ lremovexattr F ++ lsearch F ++ lseek F ++ lseek64 F ++ lsetxattr F ++ lutimes F ++ madvise F ++ makecontext F ++ mallinfo F ++ malloc F ++ malloc_get_state F ++ malloc_info F ++ malloc_set_state F ++ malloc_stats F ++ malloc_trim F ++ malloc_usable_size F ++ mallopt F ++ mallwatch D 0x8 ++ mblen F ++ mbrlen F ++ mbrtoc16 F ++ mbrtoc32 F ++ mbrtowc F ++ mbsinit F ++ mbsnrtowcs F ++ mbsrtowcs F ++ mbstowcs F ++ mbtowc F ++ mcheck F ++ mcheck_check_all F ++ mcheck_pedantic F ++ memalign F ++ memccpy F ++ memchr F ++ memcmp F ++ memcpy F ++ memfrob F ++ memmem F ++ memmove F ++ mempcpy F ++ memrchr F ++ memset F ++ mincore F ++ mkdir F ++ mkdirat F ++ mkdtemp F ++ mkfifo F ++ mkfifoat F ++ mkostemp F ++ mkostemp64 F ++ mkostemps F ++ mkostemps64 F ++ mkstemp F ++ mkstemp64 F ++ mkstemps F ++ mkstemps64 F ++ mktemp F ++ mktime F ++ mlock F ++ mlockall F ++ mmap F ++ mmap64 F ++ modf F ++ modff F ++ modfl F ++ moncontrol F ++ monstartup F ++ mount F ++ mprobe F ++ mprotect F ++ mrand48 F ++ mrand48_r F ++ mremap F ++ msgctl F ++ msgget F ++ msgrcv F ++ msgsnd F ++ msync F ++ mtrace F ++ munlock F ++ munlockall F ++ munmap F ++ muntrace F ++ name_to_handle_at F ++ nanosleep F ++ netname2host F ++ netname2user F ++ newlocale F ++ nfsservctl F ++ nftw F ++ nftw64 F ++ ngettext F ++ nice F ++ nl_langinfo F ++ nl_langinfo_l F ++ nrand48 F ++ nrand48_r F ++ ntohl F ++ ntohs F ++ ntp_adjtime F ++ ntp_gettime F ++ ntp_gettimex F ++ obstack_alloc_failed_handler D 0x8 ++ obstack_exit_failure D 0x4 ++ obstack_free F ++ obstack_printf F ++ obstack_vprintf F ++ on_exit F ++ open F ++ open64 F ++ open_by_handle_at F ++ open_memstream F ++ open_wmemstream F ++ openat F ++ openat64 F ++ opendir F ++ openlog F ++ optarg D 0x8 ++ opterr D 0x4 ++ optind D 0x4 ++ optopt D 0x4 ++ parse_printf_format F ++ passwd2des F ++ pathconf F ++ pause F ++ pclose F ++ perror F ++ personality F ++ pipe F ++ pipe2 F ++ pivot_root F ++ pmap_getmaps F ++ pmap_getport F ++ pmap_rmtcall F ++ pmap_set F ++ pmap_unset F ++ poll F ++ popen F ++ posix_fadvise F ++ posix_fadvise64 F ++ posix_fallocate F ++ posix_fallocate64 F ++ posix_madvise F ++ posix_memalign F ++ posix_openpt F ++ posix_spawn F ++ posix_spawn_file_actions_addclose F ++ posix_spawn_file_actions_adddup2 F ++ posix_spawn_file_actions_addopen F ++ posix_spawn_file_actions_destroy F ++ posix_spawn_file_actions_init F ++ posix_spawnattr_destroy F ++ posix_spawnattr_getflags F ++ posix_spawnattr_getpgroup F ++ posix_spawnattr_getschedparam F ++ posix_spawnattr_getschedpolicy F ++ posix_spawnattr_getsigdefault F ++ posix_spawnattr_getsigmask F ++ posix_spawnattr_init F ++ posix_spawnattr_setflags F ++ posix_spawnattr_setpgroup F ++ posix_spawnattr_setschedparam F ++ posix_spawnattr_setschedpolicy F ++ posix_spawnattr_setsigdefault F ++ posix_spawnattr_setsigmask F ++ posix_spawnp F ++ ppoll F ++ prctl F ++ pread F ++ pread64 F ++ preadv F ++ preadv64 F ++ printf F ++ printf_size F ++ printf_size_info F ++ prlimit F ++ prlimit64 F ++ process_vm_readv F ++ process_vm_writev F ++ profil F ++ program_invocation_name D 0x8 ++ program_invocation_short_name D 0x8 ++ pselect F ++ psiginfo F ++ psignal F ++ pthread_attr_destroy F ++ pthread_attr_getdetachstate F ++ pthread_attr_getinheritsched F ++ pthread_attr_getschedparam F ++ pthread_attr_getschedpolicy F ++ pthread_attr_getscope F ++ pthread_attr_init F ++ pthread_attr_setdetachstate F ++ pthread_attr_setinheritsched F ++ pthread_attr_setschedparam F ++ pthread_attr_setschedpolicy F ++ pthread_attr_setscope F ++ pthread_cond_broadcast F ++ pthread_cond_destroy F ++ pthread_cond_init F ++ pthread_cond_signal F ++ pthread_cond_timedwait F ++ pthread_cond_wait F ++ pthread_condattr_destroy F ++ pthread_condattr_init F ++ pthread_equal F ++ pthread_exit F ++ pthread_getschedparam F ++ pthread_mutex_destroy F ++ pthread_mutex_init F ++ pthread_mutex_lock F ++ pthread_mutex_unlock F ++ pthread_self F ++ pthread_setcancelstate F ++ pthread_setcanceltype F ++ pthread_setschedparam F ++ ptrace F ++ ptsname F ++ ptsname_r F ++ putc F ++ putc_unlocked F ++ putchar F ++ putchar_unlocked F ++ putenv F ++ putgrent F ++ putmsg F ++ putpmsg F ++ putpwent F ++ puts F ++ putsgent F ++ putspent F ++ pututline F ++ pututxline F ++ putw F ++ putwc F ++ putwc_unlocked F ++ putwchar F ++ putwchar_unlocked F ++ pvalloc F ++ pwrite F ++ pwrite64 F ++ pwritev F ++ pwritev64 F ++ qecvt F ++ qecvt_r F ++ qfcvt F ++ qfcvt_r F ++ qgcvt F ++ qsort F ++ qsort_r F ++ query_module F ++ quick_exit F ++ quotactl F ++ raise F ++ rand F ++ rand_r F ++ random F ++ random_r F ++ rawmemchr F ++ rcmd F ++ rcmd_af F ++ re_comp F ++ re_compile_fastmap F ++ re_compile_pattern F ++ re_exec F ++ re_match F ++ re_match_2 F ++ re_search F ++ re_search_2 F ++ re_set_registers F ++ re_set_syntax F ++ re_syntax_options D 0x8 ++ read F ++ readahead F ++ readdir F ++ readdir64 F ++ readdir64_r F ++ readdir_r F ++ readlink F ++ readlinkat F ++ readv F ++ realloc F ++ realpath F ++ reboot F ++ recv F ++ recvfrom F ++ recvmmsg F ++ recvmsg F ++ regcomp F ++ regerror F ++ regexec F ++ regfree F ++ register_printf_function F ++ register_printf_modifier F ++ register_printf_specifier F ++ register_printf_type F ++ registerrpc F ++ remap_file_pages F ++ remove F ++ removexattr F ++ remque F ++ rename F ++ renameat F ++ revoke F ++ rewind F ++ rewinddir F ++ rexec F ++ rexec_af F ++ rexecoptions D 0x4 ++ rindex F ++ rmdir F ++ rpc_createerr D 0x20 ++ rpmatch F ++ rresvport F ++ rresvport_af F ++ rtime F ++ ruserok F ++ ruserok_af F ++ ruserpass F ++ sbrk F ++ scalbn F ++ scalbnf F ++ scalbnl F ++ scandir F ++ scandir64 F ++ scandirat F ++ scandirat64 F ++ scanf F ++ sched_get_priority_max F ++ sched_get_priority_min F ++ sched_getaffinity F ++ sched_getcpu F ++ sched_getparam F ++ sched_getscheduler F ++ sched_rr_get_interval F ++ sched_setaffinity F ++ sched_setparam F ++ sched_setscheduler F ++ sched_yield F ++ secure_getenv F ++ seed48 F ++ seed48_r F ++ seekdir F ++ select F ++ semctl F ++ semget F ++ semop F ++ semtimedop F ++ send F ++ sendfile F ++ sendfile64 F ++ sendmmsg F ++ sendmsg F ++ sendto F ++ setaliasent F ++ setbuf F ++ setbuffer F ++ setcontext F ++ setdomainname F ++ setegid F ++ setenv F ++ seteuid F ++ setfsent F ++ setfsgid F ++ setfsuid F ++ setgid F ++ setgrent F ++ setgroups F ++ sethostent F ++ sethostid F ++ sethostname F ++ setipv4sourcefilter F ++ setitimer F ++ setjmp F ++ setlinebuf F ++ setlocale F ++ setlogin F ++ setlogmask F ++ setmntent F ++ setnetent F ++ setnetgrent F ++ setns F ++ setpgid F ++ setpgrp F ++ setpriority F ++ setprotoent F ++ setpwent F ++ setregid F ++ setresgid F ++ setresuid F ++ setreuid F ++ setrlimit F ++ setrlimit64 F ++ setrpcent F ++ setservent F ++ setsgent F ++ setsid F ++ setsockopt F ++ setsourcefilter F ++ setspent F ++ setstate F ++ setstate_r F ++ settimeofday F ++ setttyent F ++ setuid F ++ setusershell F ++ setutent F ++ setutxent F ++ setvbuf F ++ setxattr F ++ sgetsgent F ++ sgetsgent_r F ++ sgetspent F ++ sgetspent_r F ++ shmat F ++ shmctl F ++ shmdt F ++ shmget F ++ shutdown F ++ sigaction F ++ sigaddset F ++ sigaltstack F ++ sigandset F ++ sigblock F ++ sigdelset F ++ sigemptyset F ++ sigfillset F ++ siggetmask F ++ sighold F ++ sigignore F ++ siginterrupt F ++ sigisemptyset F ++ sigismember F ++ siglongjmp F ++ signal F ++ signalfd F ++ sigorset F ++ sigpause F ++ sigpending F ++ sigprocmask F ++ sigqueue F ++ sigrelse F ++ sigreturn F ++ sigset F ++ sigsetmask F ++ sigstack F ++ sigsuspend F ++ sigtimedwait F ++ sigvec F ++ sigwait F ++ sigwaitinfo F ++ sleep F ++ snprintf F ++ sockatmark F ++ socket F ++ socketpair F ++ splice F ++ sprintf F ++ sprofil F ++ srand F ++ srand48 F ++ srand48_r F ++ srandom F ++ srandom_r F ++ sscanf F ++ ssignal F ++ sstk F ++ statfs F ++ statfs64 F ++ statvfs F ++ statvfs64 F ++ stderr D 0x8 ++ stdin D 0x8 ++ stdout D 0x8 ++ step F ++ stime F ++ stpcpy F ++ stpncpy F ++ strcasecmp F ++ strcasecmp_l F ++ strcasestr F ++ strcat F ++ strchr F ++ strchrnul F ++ strcmp F ++ strcoll F ++ strcoll_l F ++ strcpy F ++ strcspn F ++ strdup F ++ strerror F ++ strerror_l F ++ strerror_r F ++ strfmon F ++ strfmon_l F ++ strfry F ++ strftime F ++ strftime_l F ++ strlen F ++ strncasecmp F ++ strncasecmp_l F ++ strncat F ++ strncmp F ++ strncpy F ++ strndup F ++ strnlen F ++ strpbrk F ++ strptime F ++ strptime_l F ++ strrchr F ++ strsep F ++ strsignal F ++ strspn F ++ strstr F ++ strtod F ++ strtod_l F ++ strtof F ++ strtof_l F ++ strtoimax F ++ strtok F ++ strtok_r F ++ strtol F ++ strtol_l F ++ strtold F ++ strtold_l F ++ strtoll F ++ strtoll_l F ++ strtoq F ++ strtoul F ++ strtoul_l F ++ strtoull F ++ strtoull_l F ++ strtoumax F ++ strtouq F ++ strverscmp F ++ strxfrm F ++ strxfrm_l F ++ stty F ++ svc_exit F ++ svc_fdset D 0x80 ++ svc_getreq F ++ svc_getreq_common F ++ svc_getreq_poll F ++ svc_getreqset F ++ svc_max_pollfd D 0x4 ++ svc_pollfd D 0x8 ++ svc_register F ++ svc_run F ++ svc_sendreply F ++ svc_unregister F ++ svcauthdes_stats D 0x18 ++ svcerr_auth F ++ svcerr_decode F ++ svcerr_noproc F ++ svcerr_noprog F ++ svcerr_progvers F ++ svcerr_systemerr F ++ svcerr_weakauth F ++ svcfd_create F ++ svcraw_create F ++ svctcp_create F ++ svcudp_bufcreate F ++ svcudp_create F ++ svcudp_enablecache F ++ svcunix_create F ++ svcunixfd_create F ++ swab F ++ swapcontext F ++ swapoff F ++ swapon F ++ swprintf F ++ swscanf F ++ symlink F ++ symlinkat F ++ sync F ++ sync_file_range F ++ syncfs F ++ sys_errlist D 0x438 ++ sys_nerr D 0x4 ++ sys_sigabbrev D 0x208 ++ sys_siglist D 0x208 ++ syscall F ++ sysconf F ++ sysctl F ++ sysinfo F ++ syslog F ++ system F ++ sysv_signal F ++ tcdrain F ++ tcflow F ++ tcflush F ++ tcgetattr F ++ tcgetpgrp F ++ tcgetsid F ++ tcsendbreak F ++ tcsetattr F ++ tcsetpgrp F ++ tdelete F ++ tdestroy F ++ tee F ++ telldir F ++ tempnam F ++ textdomain F ++ tfind F ++ time F ++ timegm F ++ timelocal F ++ timerfd_create F ++ timerfd_gettime F ++ timerfd_settime F ++ times F ++ timespec_get F ++ timezone D 0x8 ++ tmpfile F ++ tmpfile64 F ++ tmpnam F ++ tmpnam_r F ++ toascii F ++ tolower F ++ tolower_l F ++ toupper F ++ toupper_l F ++ towctrans F ++ towctrans_l F ++ towlower F ++ towlower_l F ++ towupper F ++ towupper_l F ++ tr_break F ++ truncate F ++ truncate64 F ++ tsearch F ++ ttyname F ++ ttyname_r F ++ ttyslot F ++ twalk F ++ tzname D 0x10 ++ tzset F ++ ualarm F ++ ulckpwdf F ++ ulimit F ++ umask F ++ umount F ++ umount2 F ++ uname F ++ ungetc F ++ ungetwc F ++ unlink F ++ unlinkat F ++ unlockpt F ++ unsetenv F ++ unshare F ++ updwtmp F ++ updwtmpx F ++ uselib F ++ uselocale F ++ user2netname F ++ usleep F ++ ustat F ++ utime F ++ utimensat F ++ utimes F ++ utmpname F ++ utmpxname F ++ valloc F ++ vasprintf F ++ vdprintf F ++ verr F ++ verrx F ++ versionsort F ++ versionsort64 F ++ vfork F ++ vfprintf F ++ vfscanf F ++ vfwprintf F ++ vfwscanf F ++ vhangup F ++ vlimit F ++ vmsplice F ++ vprintf F ++ vscanf F ++ vsnprintf F ++ vsprintf F ++ vsscanf F ++ vswprintf F ++ vswscanf F ++ vsyslog F ++ vtimes F ++ vwarn F ++ vwarnx F ++ vwprintf F ++ vwscanf F ++ wait F ++ wait3 F ++ wait4 F ++ waitid F ++ waitpid F ++ warn F ++ warnx F ++ wcpcpy F ++ wcpncpy F ++ wcrtomb F ++ wcscasecmp F ++ wcscasecmp_l F ++ wcscat F ++ wcschr F ++ wcschrnul F ++ wcscmp F ++ wcscoll F ++ wcscoll_l F ++ wcscpy F ++ wcscspn F ++ wcsdup F ++ wcsftime F ++ wcsftime_l F ++ wcslen F ++ wcsncasecmp F ++ wcsncasecmp_l F ++ wcsncat F ++ wcsncmp F ++ wcsncpy F ++ wcsnlen F ++ wcsnrtombs F ++ wcspbrk F ++ wcsrchr F ++ wcsrtombs F ++ wcsspn F ++ wcsstr F ++ wcstod F ++ wcstod_l F ++ wcstof F ++ wcstof_l F ++ wcstoimax F ++ wcstok F ++ wcstol F ++ wcstol_l F ++ wcstold F ++ wcstold_l F ++ wcstoll F ++ wcstoll_l F ++ wcstombs F ++ wcstoq F ++ wcstoul F ++ wcstoul_l F ++ wcstoull F ++ wcstoull_l F ++ wcstoumax F ++ wcstouq F ++ wcswcs F ++ wcswidth F ++ wcsxfrm F ++ wcsxfrm_l F ++ wctob F ++ wctomb F ++ wctrans F ++ wctrans_l F ++ wctype F ++ wctype_l F ++ wcwidth F ++ wmemchr F ++ wmemcmp F ++ wmemcpy F ++ wmemmove F ++ wmempcpy F ++ wmemset F ++ wordexp F ++ wordfree F ++ wprintf F ++ write F ++ writev F ++ wscanf F ++ xdecrypt F ++ xdr_accepted_reply F ++ xdr_array F ++ xdr_authdes_cred F ++ xdr_authdes_verf F ++ xdr_authunix_parms F ++ xdr_bool F ++ xdr_bytes F ++ xdr_callhdr F ++ xdr_callmsg F ++ xdr_char F ++ xdr_cryptkeyarg F ++ xdr_cryptkeyarg2 F ++ xdr_cryptkeyres F ++ xdr_des_block F ++ xdr_double F ++ xdr_enum F ++ xdr_float F ++ xdr_free F ++ xdr_getcredres F ++ xdr_hyper F ++ xdr_int F ++ xdr_int16_t F ++ xdr_int32_t F ++ xdr_int64_t F ++ xdr_int8_t F ++ xdr_key_netstarg F ++ xdr_key_netstres F ++ xdr_keybuf F ++ xdr_keystatus F ++ xdr_long F ++ xdr_longlong_t F ++ xdr_netnamestr F ++ xdr_netobj F ++ xdr_opaque F ++ xdr_opaque_auth F ++ xdr_pmap F ++ xdr_pmaplist F ++ xdr_pointer F ++ xdr_quad_t F ++ xdr_reference F ++ xdr_rejected_reply F ++ xdr_replymsg F ++ xdr_rmtcall_args F ++ xdr_rmtcallres F ++ xdr_short F ++ xdr_sizeof F ++ xdr_string F ++ xdr_u_char F ++ xdr_u_hyper F ++ xdr_u_int F ++ xdr_u_long F ++ xdr_u_longlong_t F ++ xdr_u_quad_t F ++ xdr_u_short F ++ xdr_uint16_t F ++ xdr_uint32_t F ++ xdr_uint64_t F ++ xdr_uint8_t F ++ xdr_union F ++ xdr_unixcred F ++ xdr_vector F ++ xdr_void F ++ xdr_wrapstring F ++ xdrmem_create F ++ xdrrec_create F ++ xdrrec_endofrecord F ++ xdrrec_eof F ++ xdrrec_skiprecord F ++ xdrstdio_create F ++ xencrypt F ++ xprt_register F ++ xprt_unregister F +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libcrypt-le.abilist glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libcrypt-le.abilist +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libcrypt-le.abilist 1970-01-01 00:00:00.000000000 +0000 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libcrypt-le.abilist 2014-06-02 15:22:40.000000000 +0000 +@@ -0,0 +1,9 @@ ++GLIBC_2.17 ++ GLIBC_2.17 A ++ crypt F ++ crypt_r F ++ encrypt F ++ encrypt_r F ++ fcrypt F ++ setkey F ++ setkey_r F +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libdl-le.abilist glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libdl-le.abilist +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libdl-le.abilist 1970-01-01 00:00:00.000000000 +0000 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libdl-le.abilist 2014-06-02 15:22:40.000000000 +0000 +@@ -0,0 +1,11 @@ ++GLIBC_2.17 ++ GLIBC_2.17 A ++ dladdr F ++ dladdr1 F ++ dlclose F ++ dlerror F ++ dlinfo F ++ dlmopen F ++ dlopen F ++ dlsym F ++ dlvsym F +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libm-le.abilist glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libm-le.abilist +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libm-le.abilist 1970-01-01 00:00:00.000000000 +0000 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libm-le.abilist 2014-06-02 15:22:40.000000000 +0000 +@@ -0,0 +1,402 @@ ++GLIBC_2.17 ++ GLIBC_2.17 A ++ _LIB_VERSION D 0x4 ++ __acos_finite F ++ __acosf_finite F ++ __acosh_finite F ++ __acoshf_finite F ++ __acoshl_finite F ++ __acosl_finite F ++ __asin_finite F ++ __asinf_finite F ++ __asinl_finite F ++ __atan2_finite F ++ __atan2f_finite F ++ __atan2l_finite F ++ __atanh_finite F ++ __atanhf_finite F ++ __atanhl_finite F ++ __clog10 F ++ __clog10f F ++ __clog10l F ++ __cosh_finite F ++ __coshf_finite F ++ __coshl_finite F ++ __exp10_finite F ++ __exp10f_finite F ++ __exp10l_finite F ++ __exp2_finite F ++ __exp2f_finite F ++ __exp2l_finite F ++ __exp_finite F ++ __expf_finite F ++ __expl_finite F ++ __fe_dfl_env D 0x8 ++ __fe_enabled_env D 0x8 ++ __fe_nomask_env F ++ __fe_nonieee_env D 0x8 ++ __finite F ++ __finitef F ++ __finitel F ++ __fmod_finite F ++ __fmodf_finite F ++ __fmodl_finite F ++ __fpclassify F ++ __fpclassifyf F ++ __fpclassifyl F ++ __gamma_r_finite F ++ __gammaf_r_finite F ++ __gammal_r_finite F ++ __hypot_finite F ++ __hypotf_finite F ++ __hypotl_finite F ++ __j0_finite F ++ __j0f_finite F ++ __j0l_finite F ++ __j1_finite F ++ __j1f_finite F ++ __j1l_finite F ++ __jn_finite F ++ __jnf_finite F ++ __jnl_finite F ++ __lgamma_r_finite F ++ __lgammaf_r_finite F ++ __lgammal_r_finite F ++ __log10_finite F ++ __log10f_finite F ++ __log10l_finite F ++ __log2_finite F ++ __log2f_finite F ++ __log2l_finite F ++ __log_finite F ++ __logf_finite F ++ __logl_finite F ++ __nldbl_nexttowardf F ++ __pow_finite F ++ __powf_finite F ++ __powl_finite F ++ __remainder_finite F ++ __remainderf_finite F ++ __remainderl_finite F ++ __scalb_finite F ++ __scalbf_finite F ++ __scalbl_finite F ++ __signbit F ++ __signbitf F ++ __signbitl F ++ __sinh_finite F ++ __sinhf_finite F ++ __sinhl_finite F ++ __sqrt_finite F ++ __sqrtf_finite F ++ __sqrtl_finite F ++ __y0_finite F ++ __y0f_finite F ++ __y0l_finite F ++ __y1_finite F ++ __y1f_finite F ++ __y1l_finite F ++ __yn_finite F ++ __ynf_finite F ++ __ynl_finite F ++ acos F ++ acosf F ++ acosh F ++ acoshf F ++ acoshl F ++ acosl F ++ asin F ++ asinf F ++ asinh F ++ asinhf F ++ asinhl F ++ asinl F ++ atan F ++ atan2 F ++ atan2f F ++ atan2l F ++ atanf F ++ atanh F ++ atanhf F ++ atanhl F ++ atanl F ++ cabs F ++ cabsf F ++ cabsl F ++ cacos F ++ cacosf F ++ cacosh F ++ cacoshf F ++ cacoshl F ++ cacosl F ++ carg F ++ cargf F ++ cargl F ++ casin F ++ casinf F ++ casinh F ++ casinhf F ++ casinhl F ++ casinl F ++ catan F ++ catanf F ++ catanh F ++ catanhf F ++ catanhl F ++ catanl F ++ cbrt F ++ cbrtf F ++ cbrtl F ++ ccos F ++ ccosf F ++ ccosh F ++ ccoshf F ++ ccoshl F ++ ccosl F ++ ceil F ++ ceilf F ++ ceill F ++ cexp F ++ cexpf F ++ cexpl F ++ cimag F ++ cimagf F ++ cimagl F ++ clog F ++ clog10 F ++ clog10f F ++ clog10l F ++ clogf F ++ clogl F ++ conj F ++ conjf F ++ conjl F ++ copysign F ++ copysignf F ++ copysignl F ++ cos F ++ cosf F ++ cosh F ++ coshf F ++ coshl F ++ cosl F ++ cpow F ++ cpowf F ++ cpowl F ++ cproj F ++ cprojf F ++ cprojl F ++ creal F ++ crealf F ++ creall F ++ csin F ++ csinf F ++ csinh F ++ csinhf F ++ csinhl F ++ csinl F ++ csqrt F ++ csqrtf F ++ csqrtl F ++ ctan F ++ ctanf F ++ ctanh F ++ ctanhf F ++ ctanhl F ++ ctanl F ++ drem F ++ dremf F ++ dreml F ++ erf F ++ erfc F ++ erfcf F ++ erfcl F ++ erff F ++ erfl F ++ exp F ++ exp10 F ++ exp10f F ++ exp10l F ++ exp2 F ++ exp2f F ++ exp2l F ++ expf F ++ expl F ++ expm1 F ++ expm1f F ++ expm1l F ++ fabs F ++ fabsf F ++ fabsl F ++ fdim F ++ fdimf F ++ fdiml F ++ feclearexcept F ++ fedisableexcept F ++ feenableexcept F ++ fegetenv F ++ fegetexcept F ++ fegetexceptflag F ++ fegetround F ++ feholdexcept F ++ feraiseexcept F ++ fesetenv F ++ fesetexceptflag F ++ fesetround F ++ fetestexcept F ++ feupdateenv F ++ finite F ++ finitef F ++ finitel F ++ floor F ++ floorf F ++ floorl F ++ fma F ++ fmaf F ++ fmal F ++ fmax F ++ fmaxf F ++ fmaxl F ++ fmin F ++ fminf F ++ fminl F ++ fmod F ++ fmodf F ++ fmodl F ++ frexp F ++ frexpf F ++ frexpl F ++ gamma F ++ gammaf F ++ gammal F ++ hypot F ++ hypotf F ++ hypotl F ++ ilogb F ++ ilogbf F ++ ilogbl F ++ j0 F ++ j0f F ++ j0l F ++ j1 F ++ j1f F ++ j1l F ++ jn F ++ jnf F ++ jnl F ++ ldexp F ++ ldexpf F ++ ldexpl F ++ lgamma F ++ lgamma_r F ++ lgammaf F ++ lgammaf_r F ++ lgammal F ++ lgammal_r F ++ llrint F ++ llrintf F ++ llrintl F ++ llround F ++ llroundf F ++ llroundl F ++ log F ++ log10 F ++ log10f F ++ log10l F ++ log1p F ++ log1pf F ++ log1pl F ++ log2 F ++ log2f F ++ log2l F ++ logb F ++ logbf F ++ logbl F ++ logf F ++ logl F ++ lrint F ++ lrintf F ++ lrintl F ++ lround F ++ lroundf F ++ lroundl F ++ matherr F ++ modf F ++ modff F ++ modfl F ++ nan F ++ nanf F ++ nanl F ++ nearbyint F ++ nearbyintf F ++ nearbyintl F ++ nextafter F ++ nextafterf F ++ nextafterl F ++ nexttoward F ++ nexttowardf F ++ nexttowardl F ++ pow F ++ pow10 F ++ pow10f F ++ pow10l F ++ powf F ++ powl F ++ remainder F ++ remainderf F ++ remainderl F ++ remquo F ++ remquof F ++ remquol F ++ rint F ++ rintf F ++ rintl F ++ round F ++ roundf F ++ roundl F ++ scalb F ++ scalbf F ++ scalbl F ++ scalbln F ++ scalblnf F ++ scalblnl F ++ scalbn F ++ scalbnf F ++ scalbnl F ++ signgam D 0x4 ++ significand F ++ significandf F ++ significandl F ++ sin F ++ sincos F ++ sincosf F ++ sincosl F ++ sinf F ++ sinh F ++ sinhf F ++ sinhl F ++ sinl F ++ sqrt F ++ sqrtf F ++ sqrtl F ++ tan F ++ tanf F ++ tanh F ++ tanhf F ++ tanhl F ++ tanl F ++ tgamma F ++ tgammaf F ++ tgammal F ++ trunc F ++ truncf F ++ truncl F ++ y0 F ++ y0f F ++ y0l F ++ y1 F ++ y1f F ++ y1l F ++ yn F ++ ynf F ++ ynl F +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libnsl-le.abilist glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libnsl-le.abilist +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libnsl-le.abilist 1970-01-01 00:00:00.000000000 +0000 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libnsl-le.abilist 2014-06-02 15:22:40.000000000 +0000 +@@ -0,0 +1,123 @@ ++GLIBC_2.17 ++ GLIBC_2.17 A ++ __free_fdresult F ++ __nis_default_access F ++ __nis_default_group F ++ __nis_default_owner F ++ __nis_default_ttl F ++ __nis_finddirectory F ++ __nis_hash F ++ __nisbind_connect F ++ __nisbind_create F ++ __nisbind_destroy F ++ __nisbind_next F ++ __yp_check F ++ nis_add F ++ nis_add_entry F ++ nis_addmember F ++ nis_checkpoint F ++ nis_clone_directory F ++ nis_clone_object F ++ nis_clone_result F ++ nis_creategroup F ++ nis_destroy_object F ++ nis_destroygroup F ++ nis_dir_cmp F ++ nis_domain_of F ++ nis_domain_of_r F ++ nis_first_entry F ++ nis_free_directory F ++ nis_free_object F ++ nis_free_request F ++ nis_freenames F ++ nis_freeresult F ++ nis_freeservlist F ++ nis_freetags F ++ nis_getnames F ++ nis_getservlist F ++ nis_ismember F ++ nis_leaf_of F ++ nis_leaf_of_r F ++ nis_lerror F ++ nis_list F ++ nis_local_directory F ++ nis_local_group F ++ nis_local_host F ++ nis_local_principal F ++ nis_lookup F ++ nis_mkdir F ++ nis_modify F ++ nis_modify_entry F ++ nis_name_of F ++ nis_name_of_r F ++ nis_next_entry F ++ nis_perror F ++ nis_ping F ++ nis_print_directory F ++ nis_print_entry F ++ nis_print_group F ++ nis_print_group_entry F ++ nis_print_link F ++ nis_print_object F ++ nis_print_result F ++ nis_print_rights F ++ nis_print_table F ++ nis_read_obj F ++ nis_remove F ++ nis_remove_entry F ++ nis_removemember F ++ nis_rmdir F ++ nis_servstate F ++ nis_sperrno F ++ nis_sperror F ++ nis_sperror_r F ++ nis_stats F ++ nis_verifygroup F ++ nis_write_obj F ++ readColdStartFile F ++ writeColdStartFile F ++ xdr_cback_data F ++ xdr_domainname F ++ xdr_keydat F ++ xdr_mapname F ++ xdr_obj_p F ++ xdr_peername F ++ xdr_valdat F ++ xdr_yp_buf F ++ xdr_ypall F ++ xdr_ypbind_binding F ++ xdr_ypbind_resp F ++ xdr_ypbind_resptype F ++ xdr_ypbind_setdom F ++ xdr_ypdelete_args F ++ xdr_ypmap_parms F ++ xdr_ypmaplist F ++ xdr_yppush_status F ++ xdr_yppushresp_xfr F ++ xdr_ypreq_key F ++ xdr_ypreq_nokey F ++ xdr_ypreq_xfr F ++ xdr_ypresp_all F ++ xdr_ypresp_key_val F ++ xdr_ypresp_maplist F ++ xdr_ypresp_master F ++ xdr_ypresp_order F ++ xdr_ypresp_val F ++ xdr_ypresp_xfr F ++ xdr_ypstat F ++ xdr_ypupdate_args F ++ xdr_ypxfrstat F ++ yp_all F ++ yp_bind F ++ yp_first F ++ yp_get_default_domain F ++ yp_maplist F ++ yp_master F ++ yp_match F ++ yp_next F ++ yp_order F ++ yp_unbind F ++ yp_update F ++ ypbinderr_string F ++ yperr_string F ++ ypprot_err F +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libpthread-le.abilist glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libpthread-le.abilist +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libpthread-le.abilist 1970-01-01 00:00:00.000000000 +0000 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libpthread-le.abilist 2014-06-02 15:22:40.000000000 +0000 +@@ -0,0 +1,224 @@ ++GLIBC_2.17 ++ GLIBC_2.17 A ++ _IO_flockfile F ++ _IO_ftrylockfile F ++ _IO_funlockfile F ++ __close F ++ __connect F ++ __errno_location F ++ __fcntl F ++ __fork F ++ __h_errno_location F ++ __libc_allocate_rtsig F ++ __libc_current_sigrtmax F ++ __libc_current_sigrtmin F ++ __lseek F ++ __nanosleep F ++ __open F ++ __open64 F ++ __pread64 F ++ __pthread_cleanup_routine F ++ __pthread_getspecific F ++ __pthread_key_create F ++ __pthread_mutex_destroy F ++ __pthread_mutex_init F ++ __pthread_mutex_lock F ++ __pthread_mutex_trylock F ++ __pthread_mutex_unlock F ++ __pthread_mutexattr_destroy F ++ __pthread_mutexattr_init F ++ __pthread_mutexattr_settype F ++ __pthread_once F ++ __pthread_register_cancel F ++ __pthread_register_cancel_defer F ++ __pthread_rwlock_destroy F ++ __pthread_rwlock_init F ++ __pthread_rwlock_rdlock F ++ __pthread_rwlock_tryrdlock F ++ __pthread_rwlock_trywrlock F ++ __pthread_rwlock_unlock F ++ __pthread_rwlock_wrlock F ++ __pthread_setspecific F ++ __pthread_unregister_cancel F ++ __pthread_unregister_cancel_restore F ++ __pthread_unwind_next F ++ __pwrite64 F ++ __read F ++ __res_state F ++ __send F ++ __sigaction F ++ __vfork F ++ __wait F ++ __write F ++ _pthread_cleanup_pop F ++ _pthread_cleanup_pop_restore F ++ _pthread_cleanup_push F ++ _pthread_cleanup_push_defer F ++ accept F ++ close F ++ connect F ++ fcntl F ++ flockfile F ++ fork F ++ fsync F ++ ftrylockfile F ++ funlockfile F ++ longjmp F ++ lseek F ++ lseek64 F ++ msync F ++ nanosleep F ++ open F ++ open64 F ++ pause F ++ pread F ++ pread64 F ++ pthread_attr_destroy F ++ pthread_attr_getaffinity_np F ++ pthread_attr_getdetachstate F ++ pthread_attr_getguardsize F ++ pthread_attr_getinheritsched F ++ pthread_attr_getschedparam F ++ pthread_attr_getschedpolicy F ++ pthread_attr_getscope F ++ pthread_attr_getstack F ++ pthread_attr_getstackaddr F ++ pthread_attr_getstacksize F ++ pthread_attr_init F ++ pthread_attr_setaffinity_np F ++ pthread_attr_setdetachstate F ++ pthread_attr_setguardsize F ++ pthread_attr_setinheritsched F ++ pthread_attr_setschedparam F ++ pthread_attr_setschedpolicy F ++ pthread_attr_setscope F ++ pthread_attr_setstack F ++ pthread_attr_setstackaddr F ++ pthread_attr_setstacksize F ++ pthread_barrier_destroy F ++ pthread_barrier_init F ++ pthread_barrier_wait F ++ pthread_barrierattr_destroy F ++ pthread_barrierattr_getpshared F ++ pthread_barrierattr_init F ++ pthread_barrierattr_setpshared F ++ pthread_cancel F ++ pthread_cond_broadcast F ++ pthread_cond_destroy F ++ pthread_cond_init F ++ pthread_cond_signal F ++ pthread_cond_timedwait F ++ pthread_cond_wait F ++ pthread_condattr_destroy F ++ pthread_condattr_getclock F ++ pthread_condattr_getpshared F ++ pthread_condattr_init F ++ pthread_condattr_setclock F ++ pthread_condattr_setpshared F ++ pthread_create F ++ pthread_detach F ++ pthread_equal F ++ pthread_exit F ++ pthread_getaffinity_np F ++ pthread_getattr_np F ++ pthread_getconcurrency F ++ pthread_getcpuclockid F ++ pthread_getname_np F ++ pthread_getschedparam F ++ pthread_getspecific F ++ pthread_join F ++ pthread_key_create F ++ pthread_key_delete F ++ pthread_kill F ++ pthread_kill_other_threads_np F ++ pthread_mutex_consistent F ++ pthread_mutex_consistent_np F ++ pthread_mutex_destroy F ++ pthread_mutex_getprioceiling F ++ pthread_mutex_init F ++ pthread_mutex_lock F ++ pthread_mutex_setprioceiling F ++ pthread_mutex_timedlock F ++ pthread_mutex_trylock F ++ pthread_mutex_unlock F ++ pthread_mutexattr_destroy F ++ pthread_mutexattr_getkind_np F ++ pthread_mutexattr_getprioceiling F ++ pthread_mutexattr_getprotocol F ++ pthread_mutexattr_getpshared F ++ pthread_mutexattr_getrobust F ++ pthread_mutexattr_getrobust_np F ++ pthread_mutexattr_gettype F ++ pthread_mutexattr_init F ++ pthread_mutexattr_setkind_np F ++ pthread_mutexattr_setprioceiling F ++ pthread_mutexattr_setprotocol F ++ pthread_mutexattr_setpshared F ++ pthread_mutexattr_setrobust F ++ pthread_mutexattr_setrobust_np F ++ pthread_mutexattr_settype F ++ pthread_once F ++ pthread_rwlock_destroy F ++ pthread_rwlock_init F ++ pthread_rwlock_rdlock F ++ pthread_rwlock_timedrdlock F ++ pthread_rwlock_timedwrlock F ++ pthread_rwlock_tryrdlock F ++ pthread_rwlock_trywrlock F ++ pthread_rwlock_unlock F ++ pthread_rwlock_wrlock F ++ pthread_rwlockattr_destroy F ++ pthread_rwlockattr_getkind_np F ++ pthread_rwlockattr_getpshared F ++ pthread_rwlockattr_init F ++ pthread_rwlockattr_setkind_np F ++ pthread_rwlockattr_setpshared F ++ pthread_self F ++ pthread_setaffinity_np F ++ pthread_setcancelstate F ++ pthread_setcanceltype F ++ pthread_setconcurrency F ++ pthread_setname_np F ++ pthread_setschedparam F ++ pthread_setschedprio F ++ pthread_setspecific F ++ pthread_sigmask F ++ pthread_sigqueue F ++ pthread_spin_destroy F ++ pthread_spin_init F ++ pthread_spin_lock F ++ pthread_spin_trylock F ++ pthread_spin_unlock F ++ pthread_testcancel F ++ pthread_timedjoin_np F ++ pthread_tryjoin_np F ++ pthread_yield F ++ pwrite F ++ pwrite64 F ++ raise F ++ read F ++ recv F ++ recvfrom F ++ recvmsg F ++ sem_close F ++ sem_destroy F ++ sem_getvalue F ++ sem_init F ++ sem_open F ++ sem_post F ++ sem_timedwait F ++ sem_trywait F ++ sem_unlink F ++ sem_wait F ++ send F ++ sendmsg F ++ sendto F ++ sigaction F ++ siglongjmp F ++ sigwait F ++ system F ++ tcdrain F ++ vfork F ++ wait F ++ waitpid F ++ write F +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libresolv-le.abilist glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libresolv-le.abilist +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libresolv-le.abilist 1970-01-01 00:00:00.000000000 +0000 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libresolv-le.abilist 2014-06-02 15:22:40.000000000 +0000 +@@ -0,0 +1,93 @@ ++GLIBC_2.17 ++ GLIBC_2.17 A ++ __b64_ntop F ++ __b64_pton F ++ __dn_comp F ++ __dn_count_labels F ++ __dn_expand F ++ __dn_skipname F ++ __fp_nquery F ++ __fp_query F ++ __fp_resstat F ++ __hostalias F ++ __loc_aton F ++ __loc_ntoa F ++ __p_cdname F ++ __p_cdnname F ++ __p_class F ++ __p_class_syms D 0xa8 ++ __p_fqname F ++ __p_fqnname F ++ __p_option F ++ __p_query F ++ __p_rcode F ++ __p_secstodate F ++ __p_time F ++ __p_type F ++ __p_type_syms D 0x450 ++ __putlong F ++ __putshort F ++ __res_close F ++ __res_dnok F ++ __res_hnok F ++ __res_hostalias F ++ __res_isourserver F ++ __res_mailok F ++ __res_mkquery F ++ __res_nameinquery F ++ __res_nmkquery F ++ __res_nquery F ++ __res_nquerydomain F ++ __res_nsearch F ++ __res_nsend F ++ __res_ownok F ++ __res_queriesmatch F ++ __res_query F ++ __res_querydomain F ++ __res_search F ++ __res_send F ++ __sym_ntop F ++ __sym_ntos F ++ __sym_ston F ++ _gethtbyaddr F ++ _gethtbyname F ++ _gethtbyname2 F ++ _gethtent F ++ _getlong F ++ _getshort F ++ _res_opcodes D 0x80 ++ _sethtent F ++ inet_net_ntop F ++ inet_net_pton F ++ inet_neta F ++ ns_datetosecs F ++ ns_format_ttl F ++ ns_get16 F ++ ns_get32 F ++ ns_initparse F ++ ns_makecanon F ++ ns_msg_getflag F ++ ns_name_compress F ++ ns_name_ntol F ++ ns_name_ntop F ++ ns_name_pack F ++ ns_name_pton F ++ ns_name_rollback F ++ ns_name_skip F ++ ns_name_uncompress F ++ ns_name_unpack F ++ ns_parse_ttl F ++ ns_parserr F ++ ns_put16 F ++ ns_put32 F ++ ns_samedomain F ++ ns_samename F ++ ns_skiprr F ++ ns_sprintrr F ++ ns_sprintrrf F ++ ns_subdomain F ++ res_gethostbyaddr F ++ res_gethostbyname F ++ res_gethostbyname2 F ++ res_send_setqhook F ++ res_send_setrhook F +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/librt-le.abilist glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/librt-le.abilist +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/librt-le.abilist 1970-01-01 00:00:00.000000000 +0000 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/librt-le.abilist 2014-06-02 15:22:40.000000000 +0000 +@@ -0,0 +1,37 @@ ++GLIBC_2.17 ++ GLIBC_2.17 A ++ __mq_open_2 F ++ aio_cancel F ++ aio_cancel64 F ++ aio_error F ++ aio_error64 F ++ aio_fsync F ++ aio_fsync64 F ++ aio_init F ++ aio_read F ++ aio_read64 F ++ aio_return F ++ aio_return64 F ++ aio_suspend F ++ aio_suspend64 F ++ aio_write F ++ aio_write64 F ++ lio_listio F ++ lio_listio64 F ++ mq_close F ++ mq_getattr F ++ mq_notify F ++ mq_open F ++ mq_receive F ++ mq_send F ++ mq_setattr F ++ mq_timedreceive F ++ mq_timedsend F ++ mq_unlink F ++ shm_open F ++ shm_unlink F ++ timer_create F ++ timer_delete F ++ timer_getoverrun F ++ timer_gettime F ++ timer_settime F +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libthread_db-le.abilist glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libthread_db-le.abilist +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libthread_db-le.abilist 1970-01-01 00:00:00.000000000 +0000 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libthread_db-le.abilist 2014-06-02 15:22:40.000000000 +0000 +@@ -0,0 +1,42 @@ ++GLIBC_2.17 ++ GLIBC_2.17 A ++ td_init F ++ td_log F ++ td_symbol_list F ++ td_ta_clear_event F ++ td_ta_delete F ++ td_ta_enable_stats F ++ td_ta_event_addr F ++ td_ta_event_getmsg F ++ td_ta_get_nthreads F ++ td_ta_get_ph F ++ td_ta_get_stats F ++ td_ta_map_id2thr F ++ td_ta_map_lwp2thr F ++ td_ta_new F ++ td_ta_reset_stats F ++ td_ta_set_event F ++ td_ta_setconcurrency F ++ td_ta_thr_iter F ++ td_ta_tsd_iter F ++ td_thr_clear_event F ++ td_thr_dbresume F ++ td_thr_dbsuspend F ++ td_thr_event_enable F ++ td_thr_event_getmsg F ++ td_thr_get_info F ++ td_thr_getfpregs F ++ td_thr_getgregs F ++ td_thr_getxregs F ++ td_thr_getxregsize F ++ td_thr_set_event F ++ td_thr_setfpregs F ++ td_thr_setgregs F ++ td_thr_setprio F ++ td_thr_setsigpending F ++ td_thr_setxregs F ++ td_thr_sigsetmask F ++ td_thr_tls_get_addr F ++ td_thr_tlsbase F ++ td_thr_tsd F ++ td_thr_validate F +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libutil-le.abilist glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libutil-le.abilist +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libutil-le.abilist 1970-01-01 00:00:00.000000000 +0000 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libutil-le.abilist 2014-06-02 15:22:40.000000000 +0000 +@@ -0,0 +1,8 @@ ++GLIBC_2.17 ++ GLIBC_2.17 A ++ forkpty F ++ login F ++ login_tty F ++ logout F ++ logwtmp F ++ openpty F diff --git a/SOURCES/glibc-ppc64le-03.patch b/SOURCES/glibc-ppc64le-03.patch new file mode 100644 index 0000000..40b6e71 --- /dev/null +++ b/SOURCES/glibc-ppc64le-03.patch @@ -0,0 +1,1617 @@ +# commit 9e54314bb06aace405553552f7e7b7d8c172968c +# Author: Joseph Myers +# Date: Thu Jun 6 19:02:09 2013 +0000 +# +# Update miscellaneous scripts from upstream. +# +diff -urN glibc-2.17-c758a686/scripts/config.guess glibc-2.17-c758a686/scripts/config.guess +--- glibc-2.17-c758a686/scripts/config.guess 2014-05-26 15:59:45.000000000 -0500 ++++ glibc-2.17-c758a686/scripts/config.guess 2014-05-26 16:01:00.000000000 -0500 +@@ -1,14 +1,12 @@ + #! /bin/sh + # Attempt to guess a canonical system name. +-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +-# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +-# 2011, 2012 Free Software Foundation, Inc. ++# Copyright 1992-2013 Free Software Foundation, Inc. + +-timestamp='2012-09-25' ++timestamp='2013-11-29' + + # This file is free software; you can redistribute it and/or modify it + # under the terms of the GNU General Public License as published by +-# the Free Software Foundation; either version 2 of the License, or ++# the Free Software Foundation; either version 3 of the License, or + # (at your option) any later version. + # + # This program is distributed in the hope that it will be useful, but +@@ -22,19 +20,17 @@ + # As a special exception to the GNU General Public License, if you + # distribute this file as part of a program that contains a + # configuration script generated by Autoconf, you may include it under +-# the same distribution terms that you use for the rest of that program. +- +- +-# Originally written by Per Bothner. Please send patches (context +-# diff format) to and include a ChangeLog +-# entry. ++# the same distribution terms that you use for the rest of that ++# program. This Exception is an additional permission under section 7 ++# of the GNU General Public License, version 3 ("GPLv3"). + # +-# This script attempts to guess a canonical system name similar to +-# config.sub. If it succeeds, it prints the system name on stdout, and +-# exits with 0. Otherwise, it exits with 1. ++# Originally written by Per Bothner. + # + # You can get the latest version of this script from: + # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD ++# ++# Please send patches with a ChangeLog entry to config-patches@gnu.org. ++ + + me=`echo "$0" | sed -e 's,.*/,,'` + +@@ -54,9 +50,7 @@ + GNU config.guess ($timestamp) + + Originally written by Per Bothner. +-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +-Free Software Foundation, Inc. ++Copyright 1992-2013 Free Software Foundation, Inc. + + This is free software; see the source for copying conditions. There is NO + warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." +@@ -138,6 +132,27 @@ + UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown + UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + ++case "${UNAME_SYSTEM}" in ++Linux|GNU|GNU/*) ++ # If the system lacks a compiler, then just pick glibc. ++ # We could probably try harder. ++ LIBC=gnu ++ ++ eval $set_cc_for_build ++ cat <<-EOF > $dummy.c ++ #include ++ #if defined(__UCLIBC__) ++ LIBC=uclibc ++ #elif defined(__dietlibc__) ++ LIBC=dietlibc ++ #else ++ LIBC=gnu ++ #endif ++ EOF ++ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` ++ ;; ++esac ++ + # Note: order is significant - the case branches are not exclusive. + + case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in +@@ -859,21 +874,21 @@ + exit ;; + *:GNU:*:*) + # the GNU system +- echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` ++ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland +- echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu ++ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in +@@ -886,59 +901,54 @@ + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 +- if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi +- echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ++ if test "$?" = 0 ; then LIBC="gnulibc1" ; fi ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} ++ exit ;; ++ arc:Linux:*:* | arceb:Linux:*:*) ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then +- echo ${UNAME_MACHINE}-unknown-linux-gnueabi ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + else +- echo ${UNAME_MACHINE}-unknown-linux-gnueabihf ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + cris:Linux:*:*) +- echo ${UNAME_MACHINE}-axis-linux-gnu ++ echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + crisv32:Linux:*:*) +- echo ${UNAME_MACHINE}-axis-linux-gnu ++ echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + frv:Linux:*:*) +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + hexagon:Linux:*:*) +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:Linux:*:*) +- LIBC=gnu +- eval $set_cc_for_build +- sed 's/^ //' << EOF >$dummy.c +- #ifdef __dietlibc__ +- LIBC=dietlibc +- #endif +-EOF +- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` +- echo "${UNAME_MACHINE}-pc-linux-${LIBC}" ++ echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + ia64:Linux:*:*) +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m32r*:Linux:*:*) +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m68*:Linux:*:*) +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build +@@ -957,54 +967,63 @@ + #endif + EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` +- test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ++ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + ;; ++ or1k:Linux:*:*) ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} ++ exit ;; + or32:Linux:*:*) +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + padre:Linux:*:*) +- echo sparc-unknown-linux-gnu ++ echo sparc-unknown-linux-${LIBC} + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) +- echo hppa64-unknown-linux-gnu ++ echo hppa64-unknown-linux-${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in +- PA7*) echo hppa1.1-unknown-linux-gnu ;; +- PA8*) echo hppa2.0-unknown-linux-gnu ;; +- *) echo hppa-unknown-linux-gnu ;; ++ PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; ++ PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; ++ *) echo hppa-unknown-linux-${LIBC} ;; + esac + exit ;; + ppc64:Linux:*:*) +- echo powerpc64-unknown-linux-gnu ++ echo powerpc64-unknown-linux-${LIBC} + exit ;; + ppc:Linux:*:*) +- echo powerpc-unknown-linux-gnu ++ echo powerpc-unknown-linux-${LIBC} ++ exit ;; ++ ppc64le:Linux:*:*) ++ echo powerpc64le-unknown-linux-${LIBC} ++ exit ;; ++ ppcle:Linux:*:*) ++ echo powerpcle-unknown-linux-${LIBC} + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) +- echo ${UNAME_MACHINE}-ibm-linux ++ echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + exit ;; + sh64*:Linux:*:*) +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sh*:Linux:*:*) +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + tile*:Linux:*:*) +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + vax:Linux:*:*) +- echo ${UNAME_MACHINE}-dec-linux-gnu ++ echo ${UNAME_MACHINE}-dec-linux-${LIBC} + exit ;; + x86_64:Linux:*:*) +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + xtensa*:Linux:*:*) +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. +@@ -1237,19 +1256,31 @@ + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown +- case $UNAME_PROCESSOR in +- i386) +- eval $set_cc_for_build +- if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then +- if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ +- (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ +- grep IS_64BIT_ARCH >/dev/null +- then +- UNAME_PROCESSOR="x86_64" +- fi +- fi ;; +- unknown) UNAME_PROCESSOR=powerpc ;; +- esac ++ eval $set_cc_for_build ++ if test "$UNAME_PROCESSOR" = unknown ; then ++ UNAME_PROCESSOR=powerpc ++ fi ++ if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then ++ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then ++ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ ++ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ ++ grep IS_64BIT_ARCH >/dev/null ++ then ++ case $UNAME_PROCESSOR in ++ i386) UNAME_PROCESSOR=x86_64 ;; ++ powerpc) UNAME_PROCESSOR=powerpc64 ;; ++ esac ++ fi ++ fi ++ elif test "$UNAME_PROCESSOR" = i386 ; then ++ # Avoid executing cc on OS X 10.9, as it ships with a stub ++ # that puts up a graphical alert prompting to install ++ # developer tools. Any system running Mac OS X 10.7 or ++ # later (Darwin 11 and later) is required to have a 64-bit ++ # processor. This is not true of the ARM version of Darwin ++ # that Apple uses in portable devices. ++ UNAME_PROCESSOR=x86_64 ++ fi + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) +diff -urN glibc-2.17-c758a686/scripts/config.sub glibc-2.17-c758a686/scripts/config.sub +--- glibc-2.17-c758a686/scripts/config.sub 2014-05-26 15:59:45.000000000 -0500 ++++ glibc-2.17-c758a686/scripts/config.sub 2014-05-26 16:00:52.000000000 -0500 +@@ -1,24 +1,18 @@ + #! /bin/sh + # Configuration validation subroutine script. +-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +-# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +-# 2011, 2012 Free Software Foundation, Inc. +- +-timestamp='2012-08-18' +- +-# This file is (in principle) common to ALL GNU software. +-# The presence of a machine in this file suggests that SOME GNU software +-# can handle that machine. It does not imply ALL GNU software can. +-# +-# This file is free software; you can redistribute it and/or modify +-# it under the terms of the GNU General Public License as published by +-# the Free Software Foundation; either version 2 of the License, or ++# Copyright 1992-2013 Free Software Foundation, Inc. ++ ++timestamp='2013-10-01' ++ ++# This file is free software; you can redistribute it and/or modify it ++# under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or + # (at your option) any later version. + # +-# This program is distributed in the hope that it will be useful, +-# but WITHOUT ANY WARRANTY; without even the implied warranty of +-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-# GNU General Public License for more details. ++# This program is distributed in the hope that it will be useful, but ++# WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++# General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program; if not, see . +@@ -26,11 +20,12 @@ + # As a special exception to the GNU General Public License, if you + # distribute this file as part of a program that contains a + # configuration script generated by Autoconf, you may include it under +-# the same distribution terms that you use for the rest of that program. ++# the same distribution terms that you use for the rest of that ++# program. This Exception is an additional permission under section 7 ++# of the GNU General Public License, version 3 ("GPLv3"). + + +-# Please send patches to . Submit a context +-# diff and a properly formatted GNU ChangeLog entry. ++# Please send patches with a ChangeLog entry to config-patches@gnu.org. + # + # Configuration subroutine to validate and canonicalize a configuration type. + # Supply the specified configuration type as an argument. +@@ -73,9 +68,7 @@ + version="\ + GNU config.sub ($timestamp) + +-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +-Free Software Foundation, Inc. ++Copyright 1992-2013 Free Software Foundation, Inc. + + This is free software; see the source for copying conditions. There is NO + warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." +@@ -156,7 +149,7 @@ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ +- -apple | -axis | -knuth | -cray | -microblaze) ++ -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; +@@ -259,10 +252,12 @@ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ +- | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ +- | be32 | be64 \ ++ | arc | arceb \ ++ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ ++ | avr | avr32 \ ++ | be32 | be64 \ + | bfin \ +- | c4x | clipper \ ++ | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | epiphany \ + | fido | fr30 | frv \ +@@ -270,10 +265,11 @@ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ ++ | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ +- | maxq | mb | microblaze | mcore | mep | metag \ ++ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ +@@ -291,16 +287,17 @@ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ ++ | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ +- | nios | nios2 \ ++ | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 \ +- | or32 \ ++ | or1k | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ +@@ -328,7 +325,7 @@ + c6x) + basic_machine=tic6x-unknown + ;; +- m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) ++ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; +@@ -370,13 +367,13 @@ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ +- | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ ++ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ +- | clipper-* | craynv-* | cydra-* \ ++ | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ +@@ -385,11 +382,13 @@ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ ++ | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ +- | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ ++ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ ++ | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ +@@ -407,12 +406,13 @@ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ ++ | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ +- | nios-* | nios2-* \ ++ | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | orion-* \ +@@ -788,7 +788,7 @@ + basic_machine=ns32k-utek + os=-sysv + ;; +- microblaze) ++ microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) +@@ -796,7 +796,7 @@ + os=-mingw64 + ;; + mingw32) +- basic_machine=i386-pc ++ basic_machine=i686-pc + os=-mingw32 + ;; + mingw32ce) +@@ -832,7 +832,7 @@ + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) +- basic_machine=i386-pc ++ basic_machine=i686-pc + os=-msys + ;; + mvs) +@@ -1023,7 +1023,11 @@ + basic_machine=i586-unknown + os=-pw32 + ;; +- rdos) ++ rdos | rdos64) ++ basic_machine=x86_64-pc ++ os=-rdos ++ ;; ++ rdos32) + basic_machine=i386-pc + os=-rdos + ;; +@@ -1350,7 +1354,7 @@ + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ +- | -sym* | -kopensolaris* \ ++ | -sym* | -kopensolaris* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ +@@ -1496,9 +1500,6 @@ + -aros*) + os=-aros + ;; +- -kaos*) +- os=-kaos +- ;; + -zvmoe) + os=-zvmoe + ;; +@@ -1547,6 +1548,9 @@ + c4x-* | tic4x-*) + os=-coff + ;; ++ c8051-*) ++ os=-elf ++ ;; + hexagon-*) + os=-elf + ;; +@@ -1590,6 +1594,9 @@ + mips*-*) + os=-elf + ;; ++ or1k-*) ++ os=-elf ++ ;; + or32-*) + os=-coff + ;; +diff -urN glibc-2.17-c758a686/scripts/install-sh glibc-2.17-c758a686/scripts/install-sh +--- glibc-2.17-c758a686/scripts/install-sh 2014-05-26 15:59:45.000000000 -0500 ++++ glibc-2.17-c758a686/scripts/install-sh 2014-05-26 16:00:34.000000000 -0500 +@@ -1,250 +1,527 @@ +-#! /bin/sh +-# ++#!/bin/sh + # install - install a program, script, or datafile +-# This comes from X11R5 (mit/util/scripts/install.sh). ++ ++scriptversion=2011-11-20.07; # UTC ++ ++# This originates from X11R5 (mit/util/scripts/install.sh), which was ++# later released in X11R6 (xc/config/util/install.sh) with the ++# following copyright and license. ++# ++# Copyright (C) 1994 X Consortium ++# ++# Permission is hereby granted, free of charge, to any person obtaining a copy ++# of this software and associated documentation files (the "Software"), to ++# deal in the Software without restriction, including without limitation the ++# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++# sell copies of the Software, and to permit persons to whom the Software is ++# furnished to do so, subject to the following conditions: ++# ++# The above copyright notice and this permission notice shall be included in ++# all copies or substantial portions of the Software. ++# ++# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN ++# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- ++# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++# ++# Except as contained in this notice, the name of the X Consortium shall not ++# be used in advertising or otherwise to promote the sale, use or other deal- ++# ings in this Software without prior written authorization from the X Consor- ++# tium. + # +-# Copyright 1991 by the Massachusetts Institute of Technology + # +-# Permission to use, copy, modify, distribute, and sell this software and its +-# documentation for any purpose is hereby granted without fee, provided that +-# the above copyright notice appear in all copies and that both that +-# copyright notice and this permission notice appear in supporting +-# documentation, and that the name of M.I.T. not be used in advertising or +-# publicity pertaining to distribution of the software without specific, +-# written prior permission. M.I.T. makes no representations about the +-# suitability of this software for any purpose. It is provided "as is" +-# without express or implied warranty. ++# FSF changes to this file are in the public domain. + # + # Calling this script install-sh is preferred over install.sh, to prevent +-# `make' implicit rules from creating a file called install from it ++# 'make' implicit rules from creating a file called install from it + # when there is no Makefile. + # + # This script is compatible with the BSD install script, but was written +-# from scratch. It can only install one file at a time, a restriction +-# shared with many OS's install programs. ++# from scratch. + ++nl=' ++' ++IFS=" "" $nl" + + # set DOITPROG to echo to test this script + + # Don't use :- since 4.3BSD and earlier shells don't like it. +-doit="${DOITPROG-}" +- +- +-# put in absolute paths if you don't have them in your path; or use env. vars. +- +-mvprog="${MVPROG-mv}" +-cpprog="${CPPROG-cp}" +-chmodprog="${CHMODPROG-chmod}" +-chownprog="${CHOWNPROG-chown}" +-chgrpprog="${CHGRPPROG-chgrp}" +-stripprog="${STRIPPROG-strip}" +-rmprog="${RMPROG-rm}" +-mkdirprog="${MKDIRPROG-mkdir}" +- +-transformbasename="" +-transform_arg="" +-instcmd="$mvprog" +-chmodcmd="$chmodprog 0755" +-chowncmd="" +-chgrpcmd="" +-stripcmd="" +-rmcmd="$rmprog -f" +-mvcmd="$mvprog" +-src="" +-dst="" +-dir_arg="" +- +-while [ x"$1" != x ]; do +- case $1 in +- -c) instcmd="$cpprog" +- shift +- continue;; +- +- -d) dir_arg=true +- shift +- continue;; +- +- -m) chmodcmd="$chmodprog $2" +- shift +- shift +- continue;; +- +- -o) chowncmd="$chownprog $2" +- shift +- shift +- continue;; +- +- -g) chgrpcmd="$chgrpprog $2" +- shift +- shift +- continue;; +- +- -s) stripcmd="$stripprog" +- shift +- continue;; +- +- -t=*) transformarg=`echo $1 | sed 's/-t=//'` +- shift +- continue;; +- +- -b=*) transformbasename=`echo $1 | sed 's/-b=//'` +- shift +- continue;; +- +- *) if [ x"$src" = x ] +- then +- src=$1 +- else +- # this colon is to work around a 386BSD /bin/sh bug +- : +- dst=$1 +- fi +- shift +- continue;; +- esac +-done +- +-if [ x"$src" = x ] +-then +- echo "install: no input file specified" +- exit 1 ++doit=${DOITPROG-} ++if test -z "$doit"; then ++ doit_exec=exec + else +- true ++ doit_exec=$doit + fi + +-if [ x"$dir_arg" != x ]; then +- dst=$src +- src="" +- +- if [ -d $dst ]; then +- instcmd=: +- else +- instcmd=mkdir +- fi +-else ++# Put in absolute file names if you don't have them in your path; ++# or use environment vars. + +-# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +-# might cause directories to be created, which would be especially bad +-# if $src (and thus $dsttmp) contains '*'. +- +- if [ -f $src -o -d $src ] +- then +- true +- else +- echo "install: $src does not exist" +- exit 1 +- fi +- +- if [ x"$dst" = x ] +- then +- echo "install: no destination specified" +- exit 1 +- else +- true +- fi +- +-# If destination is a directory, append the input filename; if your system +-# does not like double slashes in filenames, you may need to add some logic +- +- if [ -d $dst ] +- then +- dst="$dst"/`basename $src` +- else +- true +- fi +-fi +- +-## this sed command emulates the dirname command +-dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` ++chgrpprog=${CHGRPPROG-chgrp} ++chmodprog=${CHMODPROG-chmod} ++chownprog=${CHOWNPROG-chown} ++cmpprog=${CMPPROG-cmp} ++cpprog=${CPPROG-cp} ++mkdirprog=${MKDIRPROG-mkdir} ++mvprog=${MVPROG-mv} ++rmprog=${RMPROG-rm} ++stripprog=${STRIPPROG-strip} ++ ++posix_glob='?' ++initialize_posix_glob=' ++ test "$posix_glob" != "?" || { ++ if (set -f) 2>/dev/null; then ++ posix_glob= ++ else ++ posix_glob=: ++ fi ++ } ++' + +-# Make sure that the destination directory exists. +-# this part is taken from Noah Friedman's mkinstalldirs script ++posix_mkdir= + +-# Skip lots of stat calls in the usual case. +-if [ ! -d "$dstdir" ]; then +-defaultIFS=' +-' +-IFS="${IFS-${defaultIFS}}" ++# Desired mode of installed file. ++mode=0755 + +-oIFS="${IFS}" +-# Some sh's can't handle IFS=/ for some reason. +-IFS='%' +-set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +-IFS="${oIFS}" +- +-pathcomp='' +- +-while [ $# -ne 0 ] ; do +- pathcomp="${pathcomp}${1}" +- shift +- +- if [ ! -d "${pathcomp}" ] ; +- then +- $mkdirprog "${pathcomp}" +- else +- true +- fi ++chgrpcmd= ++chmodcmd=$chmodprog ++chowncmd= ++mvcmd=$mvprog ++rmcmd="$rmprog -f" ++stripcmd= + +- pathcomp="${pathcomp}/" ++src= ++dst= ++dir_arg= ++dst_arg= ++ ++copy_on_change=false ++no_target_directory= ++ ++usage="\ ++Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE ++ or: $0 [OPTION]... SRCFILES... DIRECTORY ++ or: $0 [OPTION]... -t DIRECTORY SRCFILES... ++ or: $0 [OPTION]... -d DIRECTORIES... ++ ++In the 1st form, copy SRCFILE to DSTFILE. ++In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. ++In the 4th, create DIRECTORIES. ++ ++Options: ++ --help display this help and exit. ++ --version display version info and exit. ++ ++ -c (ignored) ++ -C install only if different (preserve the last data modification time) ++ -d create directories instead of installing files. ++ -g GROUP $chgrpprog installed files to GROUP. ++ -m MODE $chmodprog installed files to MODE. ++ -o USER $chownprog installed files to USER. ++ -s $stripprog installed files. ++ -t DIRECTORY install into DIRECTORY. ++ -T report an error if DSTFILE is a directory. ++ ++Environment variables override the default commands: ++ CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG ++ RMPROG STRIPPROG ++" ++ ++while test $# -ne 0; do ++ case $1 in ++ -c) ;; ++ ++ -C) copy_on_change=true;; ++ ++ -d) dir_arg=true;; ++ ++ -g) chgrpcmd="$chgrpprog $2" ++ shift;; ++ ++ --help) echo "$usage"; exit $?;; ++ ++ -m) mode=$2 ++ case $mode in ++ *' '* | *' '* | *' ++'* | *'*'* | *'?'* | *'['*) ++ echo "$0: invalid mode: $mode" >&2 ++ exit 1;; ++ esac ++ shift;; ++ ++ -o) chowncmd="$chownprog $2" ++ shift;; ++ ++ -s) stripcmd=$stripprog;; ++ ++ -t) dst_arg=$2 ++ # Protect names problematic for 'test' and other utilities. ++ case $dst_arg in ++ -* | [=\(\)!]) dst_arg=./$dst_arg;; ++ esac ++ shift;; ++ ++ -T) no_target_directory=true;; ++ ++ --version) echo "$0 $scriptversion"; exit $?;; ++ ++ --) shift ++ break;; ++ ++ -*) echo "$0: invalid option: $1" >&2 ++ exit 1;; ++ ++ *) break;; ++ esac ++ shift + done ++ ++if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then ++ # When -d is used, all remaining arguments are directories to create. ++ # When -t is used, the destination is already specified. ++ # Otherwise, the last argument is the destination. Remove it from $@. ++ for arg ++ do ++ if test -n "$dst_arg"; then ++ # $@ is not empty: it contains at least $arg. ++ set fnord "$@" "$dst_arg" ++ shift # fnord ++ fi ++ shift # arg ++ dst_arg=$arg ++ # Protect names problematic for 'test' and other utilities. ++ case $dst_arg in ++ -* | [=\(\)!]) dst_arg=./$dst_arg;; ++ esac ++ done + fi + +-if [ x"$dir_arg" != x ] +-then +- $doit $instcmd $dst && +- +- if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && +- if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && +- if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && +- if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +-else ++if test $# -eq 0; then ++ if test -z "$dir_arg"; then ++ echo "$0: no input file specified." >&2 ++ exit 1 ++ fi ++ # It's OK to call 'install-sh -d' without argument. ++ # This can happen when creating conditional directories. ++ exit 0 ++fi + +-# If we're going to rename the final executable, determine the name now. ++if test -z "$dir_arg"; then ++ do_exit='(exit $ret); exit $ret' ++ trap "ret=129; $do_exit" 1 ++ trap "ret=130; $do_exit" 2 ++ trap "ret=141; $do_exit" 13 ++ trap "ret=143; $do_exit" 15 ++ ++ # Set umask so as not to create temps with too-generous modes. ++ # However, 'strip' requires both read and write access to temps. ++ case $mode in ++ # Optimize common cases. ++ *644) cp_umask=133;; ++ *755) cp_umask=22;; ++ ++ *[0-7]) ++ if test -z "$stripcmd"; then ++ u_plus_rw= ++ else ++ u_plus_rw='% 200' ++ fi ++ cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; ++ *) ++ if test -z "$stripcmd"; then ++ u_plus_rw= ++ else ++ u_plus_rw=,u+rw ++ fi ++ cp_umask=$mode$u_plus_rw;; ++ esac ++fi + +- if [ x"$transformarg" = x ] +- then +- dstfile=`basename $dst` ++for src ++do ++ # Protect names problematic for 'test' and other utilities. ++ case $src in ++ -* | [=\(\)!]) src=./$src;; ++ esac ++ ++ if test -n "$dir_arg"; then ++ dst=$src ++ dstdir=$dst ++ test -d "$dstdir" ++ dstdir_status=$? ++ else ++ ++ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command ++ # might cause directories to be created, which would be especially bad ++ # if $src (and thus $dsttmp) contains '*'. ++ if test ! -f "$src" && test ! -d "$src"; then ++ echo "$0: $src does not exist." >&2 ++ exit 1 ++ fi ++ ++ if test -z "$dst_arg"; then ++ echo "$0: no destination specified." >&2 ++ exit 1 ++ fi ++ dst=$dst_arg ++ ++ # If destination is a directory, append the input filename; won't work ++ # if double slashes aren't ignored. ++ if test -d "$dst"; then ++ if test -n "$no_target_directory"; then ++ echo "$0: $dst_arg: Is a directory" >&2 ++ exit 1 ++ fi ++ dstdir=$dst ++ dst=$dstdir/`basename "$src"` ++ dstdir_status=0 ++ else ++ # Prefer dirname, but fall back on a substitute if dirname fails. ++ dstdir=` ++ (dirname "$dst") 2>/dev/null || ++ expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ ++ X"$dst" : 'X\(//\)[^/]' \| \ ++ X"$dst" : 'X\(//\)$' \| \ ++ X"$dst" : 'X\(/\)' \| . 2>/dev/null || ++ echo X"$dst" | ++ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ ++ s//\1/ ++ q ++ } ++ /^X\(\/\/\)[^/].*/{ ++ s//\1/ ++ q ++ } ++ /^X\(\/\/\)$/{ ++ s//\1/ ++ q ++ } ++ /^X\(\/\).*/{ ++ s//\1/ ++ q ++ } ++ s/.*/./; q' ++ ` ++ ++ test -d "$dstdir" ++ dstdir_status=$? ++ fi ++ fi ++ ++ obsolete_mkdir_used=false ++ ++ if test $dstdir_status != 0; then ++ case $posix_mkdir in ++ '') ++ # Create intermediate dirs using mode 755 as modified by the umask. ++ # This is like FreeBSD 'install' as of 1997-10-28. ++ umask=`umask` ++ case $stripcmd.$umask in ++ # Optimize common cases. ++ *[2367][2367]) mkdir_umask=$umask;; ++ .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; ++ ++ *[0-7]) ++ mkdir_umask=`expr $umask + 22 \ ++ - $umask % 100 % 40 + $umask % 20 \ ++ - $umask % 10 % 4 + $umask % 2 ++ `;; ++ *) mkdir_umask=$umask,go-w;; ++ esac ++ ++ # With -d, create the new directory with the user-specified mode. ++ # Otherwise, rely on $mkdir_umask. ++ if test -n "$dir_arg"; then ++ mkdir_mode=-m$mode + else +- dstfile=`basename $dst $transformbasename | +- sed $transformarg`$transformbasename ++ mkdir_mode= + fi + +-# don't allow the sed command to completely eliminate the filename ++ posix_mkdir=false ++ case $umask in ++ *[123567][0-7][0-7]) ++ # POSIX mkdir -p sets u+wx bits regardless of umask, which ++ # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ++ ;; ++ *) ++ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ ++ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 ++ ++ if (umask $mkdir_umask && ++ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 ++ then ++ if test -z "$dir_arg" || { ++ # Check for POSIX incompatibilities with -m. ++ # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or ++ # other-writable bit of parent directory when it shouldn't. ++ # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ++ ls_ld_tmpdir=`ls -ld "$tmpdir"` ++ case $ls_ld_tmpdir in ++ d????-?r-*) different_mode=700;; ++ d????-?--*) different_mode=755;; ++ *) false;; ++ esac && ++ $mkdirprog -m$different_mode -p -- "$tmpdir" && { ++ ls_ld_tmpdir_1=`ls -ld "$tmpdir"` ++ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" ++ } ++ } ++ then posix_mkdir=: ++ fi ++ rmdir "$tmpdir/d" "$tmpdir" ++ else ++ # Remove any dirs left behind by ancient mkdir implementations. ++ rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null ++ fi ++ trap '' 0;; ++ esac;; ++ esac + +- if [ x"$dstfile" = x ] +- then +- dstfile=`basename $dst` ++ if ++ $posix_mkdir && ( ++ umask $mkdir_umask && ++ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ++ ) ++ then : ++ else ++ ++ # The umask is ridiculous, or mkdir does not conform to POSIX, ++ # or it failed possibly due to a race condition. Create the ++ # directory the slow way, step by step, checking for races as we go. ++ ++ case $dstdir in ++ /*) prefix='/';; ++ [-=\(\)!]*) prefix='./';; ++ *) prefix='';; ++ esac ++ ++ eval "$initialize_posix_glob" ++ ++ oIFS=$IFS ++ IFS=/ ++ $posix_glob set -f ++ set fnord $dstdir ++ shift ++ $posix_glob set +f ++ IFS=$oIFS ++ ++ prefixes= ++ ++ for d ++ do ++ test X"$d" = X && continue ++ ++ prefix=$prefix$d ++ if test -d "$prefix"; then ++ prefixes= + else +- true ++ if $posix_mkdir; then ++ (umask=$mkdir_umask && ++ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break ++ # Don't fail if two instances are running concurrently. ++ test -d "$prefix" || exit 1 ++ else ++ case $prefix in ++ *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; ++ *) qprefix=$prefix;; ++ esac ++ prefixes="$prefixes '$qprefix'" ++ fi + fi ++ prefix=$prefix/ ++ done + +-# Make a temp file name in the proper directory. +- +- dsttmp=$dstdir/#inst.$$# +- +-# Move or copy the file name to the temp name +- +- $doit $instcmd $src $dsttmp && +- +- trap "rm -f ${dsttmp}" 0 && +- +-# and set any options; do chmod last to preserve setuid bits +- +-# If any of these fail, we abort the whole thing. If we want to +-# ignore errors from any of these, just make sure not to ignore +-# errors from the above "$doit $instcmd $src $dsttmp" command. +- +- if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && +- if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && +- if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && +- if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && +- +-# Now rename the file to the real destination. +- +- $doit $rmcmd -f $dstdir/$dstfile && +- $doit $mvcmd $dsttmp $dstdir/$dstfile +- +-fi && ++ if test -n "$prefixes"; then ++ # Don't fail if two instances are running concurrently. ++ (umask $mkdir_umask && ++ eval "\$doit_exec \$mkdirprog $prefixes") || ++ test -d "$dstdir" || exit 1 ++ obsolete_mkdir_used=true ++ fi ++ fi ++ fi ++ ++ if test -n "$dir_arg"; then ++ { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && ++ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && ++ { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || ++ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 ++ else ++ ++ # Make a couple of temp file names in the proper directory. ++ dsttmp=$dstdir/_inst.$$_ ++ rmtmp=$dstdir/_rm.$$_ ++ ++ # Trap to clean up those temp files at exit. ++ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 ++ ++ # Copy the file name to the temp name. ++ (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && ++ ++ # and set any options; do chmod last to preserve setuid bits. ++ # ++ # If any of these fail, we abort the whole thing. If we want to ++ # ignore errors from any of these, just make sure not to ignore ++ # errors from the above "$doit $cpprog $src $dsttmp" command. ++ # ++ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && ++ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && ++ { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && ++ { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && ++ ++ # If -C, don't bother to copy if it wouldn't change the file. ++ if $copy_on_change && ++ old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && ++ new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && ++ ++ eval "$initialize_posix_glob" && ++ $posix_glob set -f && ++ set X $old && old=:$2:$4:$5:$6 && ++ set X $new && new=:$2:$4:$5:$6 && ++ $posix_glob set +f && ++ ++ test "$old" = "$new" && ++ $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 ++ then ++ rm -f "$dsttmp" ++ else ++ # Rename the file to the real destination. ++ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || ++ ++ # The rename failed, perhaps because mv can't rename something else ++ # to itself, or perhaps because mv is so ancient that it does not ++ # support -f. ++ { ++ # Now remove or move aside any old file at destination location. ++ # We try this two ways since rm can't unlink itself on some ++ # systems and the destination file might be busy for other ++ # reasons. In this case, the final cleanup might fail but the new ++ # file should still install successfully. ++ { ++ test ! -f "$dst" || ++ $doit $rmcmd -f "$dst" 2>/dev/null || ++ { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && ++ { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } ++ } || ++ { echo "$0: cannot unlink or rename $dst" >&2 ++ (exit 1); exit 1 ++ } ++ } && ++ ++ # Now rename the file to the real destination. ++ $doit $mvcmd "$dsttmp" "$dst" ++ } ++ fi || exit 1 + ++ trap '' 0 ++ fi ++done + +-exit 0 ++# Local variables: ++# eval: (add-hook 'write-file-hooks 'time-stamp) ++# time-stamp-start: "scriptversion=" ++# time-stamp-format: "%:y-%02m-%02d.%02H" ++# time-stamp-time-zone: "UTC" ++# time-stamp-end: "; # UTC" ++# End: +diff -urN glibc-2.17-c758a686/scripts/mkinstalldirs glibc-2.17-c758a686/scripts/mkinstalldirs +--- glibc-2.17-c758a686/scripts/mkinstalldirs 2014-05-26 15:59:45.000000000 -0500 ++++ glibc-2.17-c758a686/scripts/mkinstalldirs 2014-05-26 16:00:34.000000000 -0500 +@@ -1,38 +1,162 @@ + #! /bin/sh + # mkinstalldirs --- make directory hierarchy +-# Author: Noah Friedman +-# Created: 1993-05-16 +-# Public domain + ++scriptversion=2009-04-28.21; # UTC ++ ++# Original author: Noah Friedman ++# Created: 1993-05-16 ++# Public domain. ++# ++# This file is maintained in Automake, please report ++# bugs to or send patches to ++# . ++ ++nl=' ++' ++IFS=" "" $nl" + errstatus=0 ++dirmode= ++ ++usage="\ ++Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ... ++ ++Create each directory DIR (with mode MODE, if specified), including all ++leading file name components. ++ ++Report bugs to ." ++ ++# process command line arguments ++while test $# -gt 0 ; do ++ case $1 in ++ -h | --help | --h*) # -h for help ++ echo "$usage" ++ exit $? ++ ;; ++ -m) # -m PERM arg ++ shift ++ test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } ++ dirmode=$1 ++ shift ++ ;; ++ --version) ++ echo "$0 $scriptversion" ++ exit $? ++ ;; ++ --) # stop option processing ++ shift ++ break ++ ;; ++ -*) # unknown option ++ echo "$usage" 1>&2 ++ exit 1 ++ ;; ++ *) # first non-opt arg ++ break ++ ;; ++ esac ++done + + for file + do +- set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` +- shift ++ if test -d "$file"; then ++ shift ++ else ++ break ++ fi ++done ++ ++case $# in ++ 0) exit 0 ;; ++esac ++ ++# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and ++# mkdir -p a/c at the same time, both will detect that a is missing, ++# one will create a, then the other will try to create a and die with ++# a "File exists" error. This is a problem when calling mkinstalldirs ++# from a parallel make. We use --version in the probe to restrict ++# ourselves to GNU mkdir, which is thread-safe. ++case $dirmode in ++ '') ++ if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then ++ echo "mkdir -p -- $*" ++ exec mkdir -p -- "$@" ++ else ++ # On NextStep and OpenStep, the 'mkdir' command does not ++ # recognize any option. It will interpret all options as ++ # directories to create, and then abort because '.' already ++ # exists. ++ test -d ./-p && rmdir ./-p ++ test -d ./--version && rmdir ./--version ++ fi ++ ;; ++ *) ++ if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 && ++ test ! -d ./--version; then ++ echo "mkdir -m $dirmode -p -- $*" ++ exec mkdir -m "$dirmode" -p -- "$@" ++ else ++ # Clean up after NextStep and OpenStep mkdir. ++ for d in ./-m ./-p ./--version "./$dirmode"; ++ do ++ test -d $d && rmdir $d ++ done ++ fi ++ ;; ++esac + +- pathcomp= +- for d +- do +- pathcomp="$pathcomp$d" +- case "$pathcomp" in +- -* ) pathcomp=./$pathcomp ;; +- esac +- +- if test ! -d "$pathcomp"; then +- echo "mkdir $pathcomp" 1>&2 +- +- mkdir "$pathcomp" || lasterr=$? +- +- if test ! -d "$pathcomp"; then +- errstatus=$lasterr +- fi +- fi ++for file ++do ++ case $file in ++ /*) pathcomp=/ ;; ++ *) pathcomp= ;; ++ esac ++ oIFS=$IFS ++ IFS=/ ++ set fnord $file ++ shift ++ IFS=$oIFS ++ ++ for d ++ do ++ test "x$d" = x && continue ++ ++ pathcomp=$pathcomp$d ++ case $pathcomp in ++ -*) pathcomp=./$pathcomp ;; ++ esac ++ ++ if test ! -d "$pathcomp"; then ++ echo "mkdir $pathcomp" ++ ++ mkdir "$pathcomp" || lasterr=$? ++ ++ if test ! -d "$pathcomp"; then ++ errstatus=$lasterr ++ else ++ if test ! -z "$dirmode"; then ++ echo "chmod $dirmode $pathcomp" ++ lasterr= ++ chmod "$dirmode" "$pathcomp" || lasterr=$? ++ ++ if test ! -z "$lasterr"; then ++ errstatus=$lasterr ++ fi ++ fi ++ fi ++ fi + +- pathcomp="$pathcomp/" +- done ++ pathcomp=$pathcomp/ ++ done + done + + exit $errstatus + +-# mkinstalldirs ends here ++# Local Variables: ++# mode: shell-script ++# sh-indentation: 2 ++# eval: (add-hook 'write-file-hooks 'time-stamp) ++# time-stamp-start: "scriptversion=" ++# time-stamp-format: "%:y-%02m-%02d.%02H" ++# time-stamp-time-zone: "UTC" ++# time-stamp-end: "; # UTC" ++# End: +diff -urN glibc-2.17-c758a686/scripts/move-if-change glibc-2.17-c758a686/scripts/move-if-change +--- glibc-2.17-c758a686/scripts/move-if-change 2014-05-26 15:59:45.000000000 -0500 ++++ glibc-2.17-c758a686/scripts/move-if-change 2014-05-26 16:00:34.000000000 -0500 +@@ -1,17 +1,83 @@ + #!/bin/sh + # Like mv $1 $2, but if the files are the same, just delete $1. +-# Status is 0 if $2 is changed, 1 otherwise. +-if +-test -r $2 +-then +-if +-cmp -s $1 $2 +-then +-echo $2 is unchanged +-rm -f $1 ++# Status is zero if successful, nonzero otherwise. ++ ++VERSION='2012-01-06 07:23'; # UTC ++# The definition above must lie within the first 8 lines in order ++# for the Emacs time-stamp write hook (at end) to update it. ++# If you change this file with Emacs, please let the write hook ++# do its job. Otherwise, update this string manually. ++ ++# Copyright (C) 2002-2013 Free Software Foundation, Inc. ++ ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++ ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++ ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++usage="usage: $0 SOURCE DEST" ++ ++help="$usage ++ or: $0 OPTION ++If SOURCE is different than DEST, then move it to DEST; else remove SOURCE. ++ ++ --help display this help and exit ++ --version output version information and exit ++ ++The variable CMPPROG can be used to specify an alternative to 'cmp'. ++ ++Report bugs to ." ++ ++version=`expr "$VERSION" : '\([^ ]*\)'` ++version="move-if-change (gnulib) $version ++Copyright (C) 2011 Free Software Foundation, Inc. ++License GPLv3+: GNU GPL version 3 or later ++This is free software: you are free to change and redistribute it. ++There is NO WARRANTY, to the extent permitted by law." ++ ++cmpprog=${CMPPROG-cmp} ++ ++for arg ++do ++ case $arg in ++ --help | --hel | --he | --h) ++ exec echo "$help" ;; ++ --version | --versio | --versi | --vers | --ver | --ve | --v) ++ exec echo "$version" ;; ++ --) ++ shift ++ break ;; ++ -*) ++ echo "$0: invalid option: $arg" >&2 ++ exit 1 ;; ++ *) ++ break ;; ++ esac ++done ++ ++test $# -eq 2 || { echo "$0: $usage" >&2; exit 1; } ++ ++if test -r "$2" && $cmpprog -- "$1" "$2" >/dev/null; then ++ rm -f -- "$1" + else +-mv -f $1 $2 +-fi +-else +-mv -f $1 $2 ++ if mv -f -- "$1" "$2"; then :; else ++ # Ignore failure due to a concurrent move-if-change. ++ test -r "$2" && $cmpprog -- "$1" "$2" >/dev/null && rm -f -- "$1" ++ fi + fi ++ ++## Local Variables: ++## eval: (add-hook 'write-file-hooks 'time-stamp) ++## time-stamp-start: "VERSION='" ++## time-stamp-format: "%:y-%02m-%02d %02H:%02M" ++## time-stamp-time-zone: "UTC" ++## time-stamp-end: "'; # UTC" ++## End: diff --git a/SOURCES/glibc-ppc64le-04.patch b/SOURCES/glibc-ppc64le-04.patch new file mode 100644 index 0000000..8f6840b --- /dev/null +++ b/SOURCES/glibc-ppc64le-04.patch @@ -0,0 +1,676 @@ +# commit 9605ca6c085a749f29b6866a3e00bce1ba1a2698 +# Author: Alan Modra +# Date: Sat Aug 17 18:12:56 2013 +0930 +# +# IBM long double mechanical changes to support little-endian +# http://sourceware.org/ml/libc-alpha/2013-07/msg00001.html +# +# This patch starts the process of supporting powerpc64 little-endian +# long double in glibc. IBM long double is an array of two ieee +# doubles, so making union ibm_extended_long_double reflect this fact is +# the correct way to access fields of the doubles. +# +# * sysdeps/ieee754/ldbl-128ibm/ieee754.h +# (union ibm_extended_long_double): Define as an array of ieee754_double. +# (IBM_EXTENDED_LONG_DOUBLE_BIAS): Delete. +# * sysdeps/ieee754/ldbl-128ibm/printf_fphex.c: Update all references +# to ibm_extended_long_double and IBM_EXTENDED_LONG_DOUBLE_BIAS. +# * sysdeps/ieee754/ldbl-128ibm/e_exp10l.c: Likewise. +# * sysdeps/ieee754/ldbl-128ibm/e_expl.c: Likewise. +# * sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c: Likewise. +# * sysdeps/ieee754/ldbl-128ibm/math_ldbl.h: Likewise. +# * sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c: Likewise. +# * sysdeps/ieee754/ldbl-128ibm/s_nearbyintl.c: Likewise. +# * sysdeps/ieee754/ldbl-128ibm/strtold_l.c: Likewise. +# * sysdeps/ieee754/ldbl-128ibm/x2y2m1l.c: Likewise. +# +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_exp10l.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_exp10l.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_exp10l.c 2014-05-26 21:08:01.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_exp10l.c 2014-05-26 21:08:10.000000000 -0500 +@@ -36,9 +36,9 @@ + else if (arg > LDBL_MAX_10_EXP + 1) + return LDBL_MAX * LDBL_MAX; + +- u.d = arg; +- arg_high = u.dd[0]; +- arg_low = u.dd[1]; ++ u.ld = arg; ++ arg_high = u.d[0].d; ++ arg_low = u.d[1].d; + exp_high = arg_high * log10_high; + exp_low = arg_high * log10_low + arg_low * M_LN10l; + return __ieee754_expl (exp_high) * __ieee754_expl (exp_low); +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_expl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_expl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_expl.c 2014-05-26 21:08:01.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_expl.c 2014-05-26 21:08:10.000000000 -0500 +@@ -162,39 +162,39 @@ + x = x + xl; + + /* Compute ex2 = 2^n_0 e^(argtable[tval1]) e^(argtable[tval2]). */ +- ex2_u.d = __expl_table[T_EXPL_RES1 + tval1] +- * __expl_table[T_EXPL_RES2 + tval2]; ++ ex2_u.ld = (__expl_table[T_EXPL_RES1 + tval1] ++ * __expl_table[T_EXPL_RES2 + tval2]); + n_i = (int)n; + /* 'unsafe' is 1 iff n_1 != 0. */ + unsafe = fabsl(n_i) >= -LDBL_MIN_EXP - 1; +- ex2_u.ieee.exponent += n_i >> unsafe; ++ ex2_u.d[0].ieee.exponent += n_i >> unsafe; + /* Fortunately, there are no subnormal lowpart doubles in + __expl_table, only normal values and zeros. + But after scaling it can be subnormal. */ +- exponent2 = ex2_u.ieee.exponent2 + (n_i >> unsafe); +- if (ex2_u.ieee.exponent2 == 0) +- /* assert ((ex2_u.ieee.mantissa2|ex2_u.ieee.mantissa3) == 0) */; ++ exponent2 = ex2_u.d[1].ieee.exponent + (n_i >> unsafe); ++ if (ex2_u.d[1].ieee.exponent == 0) ++ /* assert ((ex2_u.d[1].ieee.mantissa0|ex2_u.d[1].ieee.mantissa1) == 0) */; + else if (exponent2 > 0) +- ex2_u.ieee.exponent2 = exponent2; ++ ex2_u.d[1].ieee.exponent = exponent2; + else if (exponent2 <= -54) + { +- ex2_u.ieee.exponent2 = 0; +- ex2_u.ieee.mantissa2 = 0; +- ex2_u.ieee.mantissa3 = 0; ++ ex2_u.d[1].ieee.exponent = 0; ++ ex2_u.d[1].ieee.mantissa0 = 0; ++ ex2_u.d[1].ieee.mantissa1 = 0; + } + else + { + static const double + two54 = 1.80143985094819840000e+16, /* 4350000000000000 */ + twom54 = 5.55111512312578270212e-17; /* 3C90000000000000 */ +- ex2_u.dd[1] *= two54; +- ex2_u.ieee.exponent2 += n_i >> unsafe; +- ex2_u.dd[1] *= twom54; ++ ex2_u.d[1].d *= two54; ++ ex2_u.d[1].ieee.exponent += n_i >> unsafe; ++ ex2_u.d[1].d *= twom54; + } + + /* Compute scale = 2^n_1. */ +- scale_u.d = 1.0L; +- scale_u.ieee.exponent += n_i - (n_i >> unsafe); ++ scale_u.ld = 1.0L; ++ scale_u.d[0].ieee.exponent += n_i - (n_i >> unsafe); + + /* Approximate e^x2 - 1, using a seventh-degree polynomial, + with maximum error in [-2^-16-2^-53,2^-16+2^-53] +@@ -204,7 +204,7 @@ + /* Return result. */ + fesetenv (&oldenv); + +- result = x22 * ex2_u.d + ex2_u.d; ++ result = x22 * ex2_u.ld + ex2_u.ld; + + /* Now we can test whether the result is ultimate or if we are unsure. + In the later case we should probably call a mpn based routine to give +@@ -238,7 +238,7 @@ + if (!unsafe) + return result; + else +- return result * scale_u.d; ++ return result * scale_u.ld; + } + /* Exceptional cases: */ + else if (isless (x, himark)) +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/ieee754.h glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/ieee754.h +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/ieee754.h 2014-05-26 21:08:01.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/ieee754.h 2014-05-26 21:08:10.000000000 -0500 +@@ -180,29 +180,9 @@ + + union ibm_extended_long_double + { +- long double d; +- double dd[2]; +- +- /* This is the IBM extended format long double. */ +- struct +- { /* Big endian. There is no other. */ +- +- unsigned int negative:1; +- unsigned int exponent:11; +- /* Together Mantissa0-3 comprise the mantissa. */ +- unsigned int mantissa0:20; +- unsigned int mantissa1:32; +- +- unsigned int negative2:1; +- unsigned int exponent2:11; +- /* There is an implied 1 here? */ +- /* Together these comprise the mantissa. */ +- unsigned int mantissa2:20; +- unsigned int mantissa3:32; +- } ieee; +- }; +- +-#define IBM_EXTENDED_LONG_DOUBLE_BIAS 0x3ff /* Added to exponent. */ ++ long double ld; ++ union ieee754_double d[2]; ++ }; + + __END_DECLS + +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c 2014-05-26 21:08:01.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c 2014-05-26 21:08:10.000000000 -0500 +@@ -36,22 +36,22 @@ + union ibm_extended_long_double u; + unsigned long long hi, lo; + int ediff; +- u.d = value; ++ u.ld = value; + +- *is_neg = u.ieee.negative; +- *expt = (int) u.ieee.exponent - IBM_EXTENDED_LONG_DOUBLE_BIAS; ++ *is_neg = u.d[0].ieee.negative; ++ *expt = (int) u.d[0].ieee.exponent - IEEE754_DOUBLE_BIAS; + +- lo = ((long long) u.ieee.mantissa2 << 32) | u.ieee.mantissa3; +- hi = ((long long) u.ieee.mantissa0 << 32) | u.ieee.mantissa1; ++ lo = ((long long) u.d[1].ieee.mantissa0 << 32) | u.d[1].ieee.mantissa1; ++ hi = ((long long) u.d[0].ieee.mantissa0 << 32) | u.d[0].ieee.mantissa1; + /* If the lower double is not a denomal or zero then set the hidden + 53rd bit. */ +- if (u.ieee.exponent2 > 0) ++ if (u.d[1].ieee.exponent > 0) + { + lo |= 1LL << 52; + + /* The lower double is normalized separately from the upper. We may + need to adjust the lower manitissa to reflect this. */ +- ediff = u.ieee.exponent - u.ieee.exponent2; ++ ediff = u.d[0].ieee.exponent - u.d[1].ieee.exponent; + if (ediff > 53) + lo = lo >> (ediff-53); + } +@@ -59,8 +59,8 @@ + difference between the long double and the rounded high double + value. This is indicated by a differnce between the signs of the + high and low doubles. */ +- if ((u.ieee.negative != u.ieee.negative2) +- && ((u.ieee.exponent2 != 0) && (lo != 0L))) ++ if ((u.d[0].ieee.negative != u.d[1].ieee.negative) ++ && ((u.d[1].ieee.exponent != 0) && (lo != 0L))) + { + lo = (1ULL << 53) - lo; + if (hi == 0LL) +@@ -92,7 +92,7 @@ + #define NUM_LEADING_ZEROS (BITS_PER_MP_LIMB \ + - (LDBL_MANT_DIG - ((N - 1) * BITS_PER_MP_LIMB))) + +- if (u.ieee.exponent == 0) ++ if (u.d[0].ieee.exponent == 0) + { + /* A biased exponent of zero is a special case. + Either it is a zero or it is a denormal number. */ +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h 2014-05-26 21:08:01.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h 2014-05-26 21:08:10.000000000 -0500 +@@ -14,28 +14,28 @@ + as bit 53 of the mantissa. */ + uint64_t hi, lo; + int ediff; +- union ibm_extended_long_double eldbl; +- eldbl.d = x; +- *exp = eldbl.ieee.exponent - IBM_EXTENDED_LONG_DOUBLE_BIAS; ++ union ibm_extended_long_double u; ++ u.ld = x; ++ *exp = u.d[0].ieee.exponent - IEEE754_DOUBLE_BIAS; + +- lo = ((int64_t)eldbl.ieee.mantissa2 << 32) | eldbl.ieee.mantissa3; +- hi = ((int64_t)eldbl.ieee.mantissa0 << 32) | eldbl.ieee.mantissa1; ++ lo = ((uint64_t)u.d[1].ieee.mantissa0 << 32) | u.d[1].ieee.mantissa1; ++ hi = ((uint64_t)u.d[0].ieee.mantissa0 << 32) | u.d[0].ieee.mantissa1; + /* If the lower double is not a denomal or zero then set the hidden + 53rd bit. */ +- if (eldbl.ieee.exponent2 > 0x001) ++ if (u.d[1].ieee.exponent > 0x001) + { + lo |= (1ULL << 52); + lo = lo << 7; /* pre-shift lo to match ieee854. */ + /* The lower double is normalized separately from the upper. We + may need to adjust the lower manitissa to reflect this. */ +- ediff = eldbl.ieee.exponent - eldbl.ieee.exponent2; ++ ediff = u.d[0].ieee.exponent - u.d[1].ieee.exponent; + if (ediff > 53) + lo = lo >> (ediff-53); + hi |= (1ULL << 52); + } + +- if ((eldbl.ieee.negative != eldbl.ieee.negative2) +- && ((eldbl.ieee.exponent2 != 0) && (lo != 0LL))) ++ if ((u.d[0].ieee.negative != u.d[1].ieee.negative) ++ && ((u.d[1].ieee.exponent != 0) && (lo != 0LL))) + { + hi--; + lo = (1ULL << 60) - lo; +@@ -58,10 +58,10 @@ + unsigned long hidden2, lzcount; + unsigned long long hi, lo; + +- u.ieee.negative = sign; +- u.ieee.negative2 = sign; +- u.ieee.exponent = exp + IBM_EXTENDED_LONG_DOUBLE_BIAS; +- u.ieee.exponent2 = exp-53 + IBM_EXTENDED_LONG_DOUBLE_BIAS; ++ u.d[0].ieee.negative = sign; ++ u.d[1].ieee.negative = sign; ++ u.d[0].ieee.exponent = exp + IEEE754_DOUBLE_BIAS; ++ u.d[1].ieee.exponent = exp-53 + IEEE754_DOUBLE_BIAS; + /* Expect 113 bits (112 bits + hidden) right justified in two longs. + The low order 53 bits (52 + hidden) go into the lower double */ + lo = (lo64 >> 7)& ((1ULL << 53) - 1); +@@ -78,7 +78,7 @@ + if (hidden2) + { + hi++; +- u.ieee.negative2 = !sign; ++ u.d[1].ieee.negative = !sign; + lo = (1ULL << 53) - lo; + } + /* The hidden bit of the lo mantissa is zero so we need to +@@ -94,32 +94,32 @@ + lzcount = lzcount - 11; + if (lzcount > 0) + { +- int expnt2 = u.ieee.exponent2 - lzcount; ++ int expnt2 = u.d[1].ieee.exponent - lzcount; + if (expnt2 >= 1) + { + /* Not denormal. Normalize and set low exponent. */ + lo = lo << lzcount; +- u.ieee.exponent2 = expnt2; ++ u.d[1].ieee.exponent = expnt2; + } + else + { + /* Is denormal. */ + lo = lo << (lzcount + expnt2); +- u.ieee.exponent2 = 0; ++ u.d[1].ieee.exponent = 0; + } + } + } + else + { +- u.ieee.negative2 = 0; +- u.ieee.exponent2 = 0; ++ u.d[1].ieee.negative = 0; ++ u.d[1].ieee.exponent = 0; + } + +- u.ieee.mantissa3 = lo & ((1ULL << 32) - 1); +- u.ieee.mantissa2 = (lo >> 32) & ((1ULL << 20) - 1); +- u.ieee.mantissa1 = hi & ((1ULL << 32) - 1); +- u.ieee.mantissa0 = (hi >> 32) & ((1ULL << 20) - 1); +- return u.d; ++ u.d[1].ieee.mantissa1 = lo & ((1ULL << 32) - 1); ++ u.d[1].ieee.mantissa0 = (lo >> 32) & ((1ULL << 20) - 1); ++ u.d[0].ieee.mantissa1 = hi & ((1ULL << 32) - 1); ++ u.d[0].ieee.mantissa0 = (hi >> 32) & ((1ULL << 20) - 1); ++ return u.ld; + } + + /* Handy utility functions to pack/unpack/cononicalize and find the nearbyint +@@ -128,18 +128,18 @@ + default_ldbl_pack (double a, double aa) + { + union ibm_extended_long_double u; +- u.dd[0] = a; +- u.dd[1] = aa; +- return u.d; ++ u.d[0].d = a; ++ u.d[1].d = aa; ++ return u.ld; + } + + static inline void + default_ldbl_unpack (long double l, double *a, double *aa) + { + union ibm_extended_long_double u; +- u.d = l; +- *a = u.dd[0]; +- *aa = u.dd[1]; ++ u.ld = l; ++ *a = u.d[0].d; ++ *aa = u.d[1].d; + } + + #ifndef ldbl_pack +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c 2014-05-26 21:08:01.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c 2014-05-26 21:08:10.000000000 -0500 +@@ -34,11 +34,11 @@ + unsigned long long hi, lo; + int exponent2; + +- u.ieee.negative = sign; +- u.ieee.negative2 = sign; +- u.ieee.exponent = expt + IBM_EXTENDED_LONG_DOUBLE_BIAS; +- u.ieee.exponent2 = 0; +- exponent2 = expt - 53 + IBM_EXTENDED_LONG_DOUBLE_BIAS; ++ u.d[0].ieee.negative = sign; ++ u.d[1].ieee.negative = sign; ++ u.d[0].ieee.exponent = expt + IEEE754_DOUBLE_BIAS; ++ u.d[1].ieee.exponent = 0; ++ exponent2 = expt - 53 + IEEE754_DOUBLE_BIAS; + + #if BITS_PER_MP_LIMB == 32 + /* The low order 53 bits (52 + hidden) go into the lower double */ +@@ -74,15 +74,15 @@ + else + lzcount = lzcount + 42; + +- if (lzcount > u.ieee.exponent) ++ if (lzcount > u.d[0].ieee.exponent) + { +- lzcount = u.ieee.exponent; +- u.ieee.exponent = 0; ++ lzcount = u.d[0].ieee.exponent; ++ u.d[0].ieee.exponent = 0; + exponent2 -= lzcount; + } + else + { +- u.ieee.exponent -= (lzcount - 1); ++ u.d[0].ieee.exponent -= (lzcount - 1); + exponent2 -= (lzcount - 1); + } + +@@ -112,9 +112,9 @@ + { + if ((hi & (1LL << 53)) != 0) + hi -= 1LL << 52; +- u.ieee.exponent++; ++ u.d[0].ieee.exponent++; + } +- u.ieee.negative2 = !sign; ++ u.d[1].ieee.negative = !sign; + lo = (1LL << 53) - lo; + } + +@@ -135,17 +135,17 @@ + exponent2 = exponent2 - lzcount; + } + if (exponent2 > 0) +- u.ieee.exponent2 = exponent2; ++ u.d[1].ieee.exponent = exponent2; + else + lo >>= 1 - exponent2; + } + else +- u.ieee.negative2 = 0; ++ u.d[1].ieee.negative = 0; + +- u.ieee.mantissa3 = lo & 0xffffffffLL; +- u.ieee.mantissa2 = (lo >> 32) & 0xfffff; +- u.ieee.mantissa1 = hi & 0xffffffffLL; +- u.ieee.mantissa0 = (hi >> 32) & ((1LL << (LDBL_MANT_DIG - 86)) - 1); ++ u.d[1].ieee.mantissa1 = lo & 0xffffffffLL; ++ u.d[1].ieee.mantissa0 = (lo >> 32) & 0xfffff; ++ u.d[0].ieee.mantissa1 = hi & 0xffffffffLL; ++ u.d[0].ieee.mantissa0 = (hi >> 32) & ((1LL << (LDBL_MANT_DIG - 86)) - 1); + +- return u.d; ++ return u.ld; + } +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c 2014-05-26 21:08:01.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c 2014-05-26 21:08:10.000000000 -0500 +@@ -27,31 +27,31 @@ + unsigned long long int num0, num1; \ + unsigned long long hi, lo; \ + int ediff; \ +- union ibm_extended_long_double eldbl; \ +- eldbl.d = fpnum.ldbl.d; \ ++ union ibm_extended_long_double u; \ ++ u.ld = fpnum.ldbl.d; \ + \ + assert (sizeof (long double) == 16); \ + \ +- lo = ((long long)eldbl.ieee.mantissa2 << 32) | eldbl.ieee.mantissa3; \ +- hi = ((long long)eldbl.ieee.mantissa0 << 32) | eldbl.ieee.mantissa1; \ ++ lo = ((long long)u.d[1].ieee.mantissa0 << 32) | u.d[1].ieee.mantissa1; \ ++ hi = ((long long)u.d[0].ieee.mantissa0 << 32) | u.d[0].ieee.mantissa1; \ + lo <<= 7; /* pre-shift lo to match ieee854. */ \ + /* If the lower double is not a denomal or zero then set the hidden \ + 53rd bit. */ \ +- if (eldbl.ieee.exponent2 != 0) \ ++ if (u.d[1].ieee.exponent != 0) \ + lo |= (1ULL << (52 + 7)); \ + else \ + lo <<= 1; \ + /* The lower double is normalized separately from the upper. We \ + may need to adjust the lower manitissa to reflect this. */ \ +- ediff = eldbl.ieee.exponent - eldbl.ieee.exponent2; \ ++ ediff = u.d[0].ieee.exponent - u.d[1].ieee.exponent; \ + if (ediff > 53 + 63) \ + lo = 0; \ + else if (ediff > 53) \ + lo = lo >> (ediff - 53); \ +- else if (eldbl.ieee.exponent2 == 0 && ediff < 53) \ ++ else if (u.d[1].ieee.exponent == 0 && ediff < 53) \ + lo = lo << (53 - ediff); \ +- if (eldbl.ieee.negative != eldbl.ieee.negative2 \ +- && (eldbl.ieee.exponent2 != 0 || lo != 0L)) \ ++ if (u.d[0].ieee.negative != u.d[1].ieee.negative \ ++ && (u.d[1].ieee.exponent != 0 || lo != 0L)) \ + { \ + lo = (1ULL << 60) - lo; \ + if (hi == 0L) \ +@@ -59,7 +59,7 @@ + /* we have a borrow from the hidden bit, so shift left 1. */ \ + hi = 0xffffffffffffeLL | (lo >> 59); \ + lo = 0xfffffffffffffffLL & (lo << 1); \ +- eldbl.ieee.exponent--; \ ++ u.d[0].ieee.exponent--; \ + } \ + else \ + hi--; \ +@@ -110,9 +110,9 @@ + *--wnumstr = L'0'; \ + } \ + \ +- leading = eldbl.ieee.exponent == 0 ? '0' : '1'; \ ++ leading = u.d[0].ieee.exponent == 0 ? '0' : '1'; \ + \ +- exponent = eldbl.ieee.exponent; \ ++ exponent = u.d[0].ieee.exponent; \ + \ + if (exponent == 0) \ + { \ +@@ -122,18 +122,18 @@ + { \ + /* This is a denormalized number. */ \ + expnegative = 1; \ +- exponent = IBM_EXTENDED_LONG_DOUBLE_BIAS - 1; \ ++ exponent = IEEE754_DOUBLE_BIAS - 1; \ + } \ + } \ +- else if (exponent >= IBM_EXTENDED_LONG_DOUBLE_BIAS) \ ++ else if (exponent >= IEEE754_DOUBLE_BIAS) \ + { \ + expnegative = 0; \ +- exponent -= IBM_EXTENDED_LONG_DOUBLE_BIAS; \ ++ exponent -= IEEE754_DOUBLE_BIAS; \ + } \ + else \ + { \ + expnegative = 1; \ +- exponent = -(exponent - IBM_EXTENDED_LONG_DOUBLE_BIAS); \ ++ exponent = -(exponent - IEEE754_DOUBLE_BIAS); \ + } \ + } while (0) + +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_nearbyintl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_nearbyintl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_nearbyintl.c 2014-05-26 21:08:01.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_nearbyintl.c 2014-05-26 21:08:10.000000000 -0500 +@@ -33,11 +33,11 @@ + fenv_t env; + static const long double TWO52 = 4503599627370496.0L; + union ibm_extended_long_double u; +- u.d = x; ++ u.ld = x; + +- if (fabs (u.dd[0]) < TWO52) ++ if (fabs (u.d[0].d) < TWO52) + { +- double high = u.dd[0]; ++ double high = u.d[0].d; + feholdexcept (&env); + if (high > 0.0) + { +@@ -51,11 +51,11 @@ + high += TWO52; + if (high == 0.0) high = -0.0; + } +- u.dd[0] = high; +- u.dd[1] = 0.0; ++ u.d[0].d = high; ++ u.d[1].d = 0.0; + fesetenv (&env); + } +- else if (fabs (u.dd[1]) < TWO52 && u.dd[1] != 0.0) ++ else if (fabs (u.d[1].d) < TWO52 && u.d[1].d != 0.0) + { + double high, low, tau; + /* In this case we have to round the low double and handle any +@@ -64,55 +64,55 @@ + may already be rounded and the low double may have the + opposite sign to compensate. */ + feholdexcept (&env); +- if (u.dd[0] > 0.0) ++ if (u.d[0].d > 0.0) + { +- if (u.dd[1] > 0.0) ++ if (u.d[1].d > 0.0) + { + /* If the high/low doubles are the same sign then simply + round the low double. */ +- high = u.dd[0]; +- low = u.dd[1]; ++ high = u.d[0].d; ++ low = u.d[1].d; + } +- else if (u.dd[1] < 0.0) ++ else if (u.d[1].d < 0.0) + { + /* Else the high double is pre rounded and we need to + adjust for that. */ + +- tau = __nextafter (u.dd[0], 0.0); +- tau = (u.dd[0] - tau) * 2.0; +- high = u.dd[0] - tau; +- low = u.dd[1] + tau; ++ tau = __nextafter (u.d[0].d, 0.0); ++ tau = (u.d[0].d - tau) * 2.0; ++ high = u.d[0].d - tau; ++ low = u.d[1].d + tau; + } + low += TWO52; + low -= TWO52; + } +- else if (u.dd[0] < 0.0) ++ else if (u.d[0].d < 0.0) + { +- if (u.dd[1] < 0.0) ++ if (u.d[1].d < 0.0) + { + /* If the high/low doubles are the same sign then simply + round the low double. */ +- high = u.dd[0]; +- low = u.dd[1]; ++ high = u.d[0].d; ++ low = u.d[1].d; + } +- else if (u.dd[1] > 0.0) ++ else if (u.d[1].d > 0.0) + { + /* Else the high double is pre rounded and we need to + adjust for that. */ +- tau = __nextafter (u.dd[0], 0.0); +- tau = (u.dd[0] - tau) * 2.0; +- high = u.dd[0] - tau; +- low = u.dd[1] + tau; ++ tau = __nextafter (u.d[0].d, 0.0); ++ tau = (u.d[0].d - tau) * 2.0; ++ high = u.d[0].d - tau; ++ low = u.d[1].d + tau; + } + low = TWO52 - low; + low = -(low - TWO52); + } +- u.dd[0] = high + low; +- u.dd[1] = high - u.dd[0] + low; ++ u.d[0].d = high + low; ++ u.d[1].d = high - u.d[0].d + low; + fesetenv (&env); + } + +- return u.d; ++ return u.ld; + } + + long_double_symbol (libm, __nearbyintl, nearbyintl); +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/strtold_l.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/strtold_l.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/strtold_l.c 2014-05-26 21:08:01.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/strtold_l.c 2014-05-26 21:12:01.000000000 -0500 +@@ -43,12 +43,11 @@ + #define FLOAT_HUGE_VAL HUGE_VALL + # define SET_MANTISSA(flt, mant) \ + do { union ibm_extended_long_double u; \ +- u.d = (flt); \ +- if ((mant & 0xfffffffffffffULL) == 0) \ +- mant = 0x8000000000000ULL; \ +- u.ieee.mantissa0 = ((mant) >> 32) & 0xfffff; \ +- u.ieee.mantissa1 = (mant) & 0xffffffff; \ +- (flt) = u.d; \ ++ u.ld = (flt); \ ++ u.d[0].ieee_nan.mantissa0 = (mant) >> 32; \ ++ u.d[0].ieee_nan.mantissa1 = (mant); \ ++ if ((u.d[0].ieee.mantissa0 | u.d[0].ieee.mantissa1) != 0) \ ++ (flt) = u.ld; \ + } while (0) + + #include +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/x2y2m1l.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/x2y2m1l.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/x2y2m1l.c 2014-05-26 21:08:01.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/x2y2m1l.c 2014-05-26 21:08:10.000000000 -0500 +@@ -89,23 +89,23 @@ + double vals[12]; + SET_RESTORE_ROUND (FE_TONEAREST); + union ibm_extended_long_double xu, yu; +- xu.d = x; +- yu.d = y; +- if (fabs (xu.dd[1]) < 0x1p-500) +- xu.dd[1] = 0.0; +- if (fabs (yu.dd[1]) < 0x1p-500) +- yu.dd[1] = 0.0; +- mul_split (&vals[1], &vals[0], xu.dd[0], xu.dd[0]); +- mul_split (&vals[3], &vals[2], xu.dd[0], xu.dd[1]); ++ xu.ld = x; ++ yu.ld = y; ++ if (fabs (xu.d[1].d) < 0x1p-500) ++ xu.d[1].d = 0.0; ++ if (fabs (yu.d[1].d) < 0x1p-500) ++ yu.d[1].d = 0.0; ++ mul_split (&vals[1], &vals[0], xu.d[0].d, xu.d[0].d); ++ mul_split (&vals[3], &vals[2], xu.d[0].d, xu.d[1].d); + vals[2] *= 2.0; + vals[3] *= 2.0; +- mul_split (&vals[5], &vals[4], xu.dd[1], xu.dd[1]); +- mul_split (&vals[7], &vals[6], yu.dd[0], yu.dd[0]); +- mul_split (&vals[9], &vals[8], yu.dd[0], yu.dd[1]); ++ mul_split (&vals[5], &vals[4], xu.d[1].d, xu.d[1].d); ++ mul_split (&vals[7], &vals[6], yu.d[0].d, yu.d[0].d); ++ mul_split (&vals[9], &vals[8], yu.d[0].d, yu.d[1].d); + vals[8] *= 2.0; + vals[9] *= 2.0; +- mul_split (&vals[11], &vals[10], yu.dd[1], yu.dd[1]); +- if (xu.dd[0] >= 0.75) ++ mul_split (&vals[11], &vals[10], yu.d[1].d, yu.d[1].d); ++ if (xu.d[0].d >= 0.75) + vals[1] -= 1.0; + else + { diff --git a/SOURCES/glibc-ppc64le-05.patch b/SOURCES/glibc-ppc64le-05.patch new file mode 100644 index 0000000..d089fda --- /dev/null +++ b/SOURCES/glibc-ppc64le-05.patch @@ -0,0 +1,486 @@ +# commit 4cf69995e26e16005d4e3843ad4d18c75cf21a04 +# Author: Alan Modra +# Date: Sat Aug 17 18:19:44 2013 +0930 +# +# Fix for [BZ #15680] IBM long double inaccuracy +# http://sourceware.org/ml/libc-alpha/2013-06/msg00919.html +# +# I discovered a number of places where denormals and other corner cases +# were being handled wrongly. +# +# - printf_fphex.c: Testing for the low double exponent being zero is +# unnecessary. If the difference in exponents is less than 53 then the +# high double exponent must be nearing the low end of its range, and the +# low double exponent hit rock bottom. +# +# - ldbl2mpn.c: A denormal (ie. exponent of zero) value is treated as +# if the exponent was one, so shift mantissa left by one. Code handling +# normalisation of the low double mantissa lacked a test for shift count +# greater than bits in type being shifted, and lacked anything to handle +# the case where the difference in exponents is less than 53 as in +# printf_fphex.c. +# +# - math_ldbl.h (ldbl_extract_mantissa): Same as above, but worse, with +# code testing for exponent > 1 for some reason, probably a typo for >= 1. +# +# - math_ldbl.h (ldbl_insert_mantissa): Round the high double as per +# mpn2ldbl.c (hi is odd or explicit mantissas non-zero) so that the +# number we return won't change when applying ldbl_canonicalize(). +# Add missing overflow checks and normalisation of high mantissa. +# Correct misleading comment: "The hidden bit of the lo mantissa is +# zero" is not always true as can be seen from the code rounding the hi +# mantissa. Also by inspection, lzcount can never be less than zero so +# remove that test. Lastly, masking bitfields to their widths can be +# left to the compiler. +# +# - mpn2ldbl.c: The overflow checks here on rounding of high double were +# just plain wrong. Incrementing the exponent must be accompanied by a +# shift right of the mantissa to keep the value unchanged. Above notes +# for ldbl_insert_mantissa are also relevant. +# +# [BZ #15680] +# * sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c: Comment fix. +# * sysdeps/ieee754/ldbl-128ibm/printf_fphex.c +# (PRINT_FPHEX_LONG_DOUBLE): Tidy code by moving -53 into ediff +# calculation. Remove unnecessary test for denormal exponent. +# * sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c (__mpn_extract_long_double): +# Correct handling of denormals. Avoid undefined shift behaviour. +# Correct normalisation of low mantissa when low double is denormal. +# * sysdeps/ieee754/ldbl-128ibm/math_ldbl.h +# (ldbl_extract_mantissa): Likewise. Comment. Use uint64_t* for hi64. +# (ldbl_insert_mantissa): Make both hi64 and lo64 parms uint64_t. +# Correct normalisation of low mantissa. Test for overflow of high +# mantissa and normalise. +# (ldbl_nearbyint): Use more readable constant for two52. +# * sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c +# (__mpn_construct_long_double): Fix test for overflow of high +# mantissa and correct normalisation. Avoid undefined shift. +# +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c 2014-05-27 19:13:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c 2014-05-27 19:14:45.000000000 -0500 +@@ -243,7 +243,7 @@ + We split the 113 bits of the mantissa into 5 24bit integers + stored in a double array. */ + /* Make the IBM extended format 105 bit mantissa look like the ieee854 112 +- bit mantissa so the next operatation will give the correct result. */ ++ bit mantissa so the next operation will give the correct result. */ + ldbl_extract_mantissa (&ixd, &lxd, &exp, x); + exp = exp - 23; + /* This is faster than doing this in floating point, because we +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c 2014-05-27 19:13:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c 2014-05-27 19:14:45.000000000 -0500 +@@ -36,6 +36,7 @@ + union ibm_extended_long_double u; + unsigned long long hi, lo; + int ediff; ++ + u.ld = value; + + *is_neg = u.d[0].ieee.negative; +@@ -43,27 +44,36 @@ + + lo = ((long long) u.d[1].ieee.mantissa0 << 32) | u.d[1].ieee.mantissa1; + hi = ((long long) u.d[0].ieee.mantissa0 << 32) | u.d[0].ieee.mantissa1; +- /* If the lower double is not a denomal or zero then set the hidden ++ ++ /* If the lower double is not a denormal or zero then set the hidden + 53rd bit. */ +- if (u.d[1].ieee.exponent > 0) +- { +- lo |= 1LL << 52; ++ if (u.d[1].ieee.exponent != 0) ++ lo |= 1ULL << 52; ++ else ++ lo = lo << 1; + +- /* The lower double is normalized separately from the upper. We may +- need to adjust the lower manitissa to reflect this. */ +- ediff = u.d[0].ieee.exponent - u.d[1].ieee.exponent; +- if (ediff > 53) +- lo = lo >> (ediff-53); ++ /* The lower double is normalized separately from the upper. We may ++ need to adjust the lower manitissa to reflect this. */ ++ ediff = u.d[0].ieee.exponent - u.d[1].ieee.exponent - 53; ++ if (ediff > 0) ++ { ++ if (ediff < 64) ++ lo = lo >> ediff; ++ else ++ lo = 0; + } ++ else if (ediff < 0) ++ lo = lo << -ediff; ++ + /* The high double may be rounded and the low double reflects the + difference between the long double and the rounded high double + value. This is indicated by a differnce between the signs of the + high and low doubles. */ +- if ((u.d[0].ieee.negative != u.d[1].ieee.negative) +- && ((u.d[1].ieee.exponent != 0) && (lo != 0L))) ++ if (u.d[0].ieee.negative != u.d[1].ieee.negative ++ && lo != 0) + { + lo = (1ULL << 53) - lo; +- if (hi == 0LL) ++ if (hi == 0) + { + /* we have a borrow from the hidden bit, so shift left 1. */ + hi = 0x0ffffffffffffeLL | (lo >> 51); +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h 2014-05-27 19:13:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h 2014-05-27 19:51:13.000000000 -0500 +@@ -13,77 +13,118 @@ + the number before the decimal point and the second implicit bit + as bit 53 of the mantissa. */ + uint64_t hi, lo; +- int ediff; + union ibm_extended_long_double u; ++ + u.ld = x; + *exp = u.d[0].ieee.exponent - IEEE754_DOUBLE_BIAS; + + lo = ((uint64_t)u.d[1].ieee.mantissa0 << 32) | u.d[1].ieee.mantissa1; + hi = ((uint64_t)u.d[0].ieee.mantissa0 << 32) | u.d[0].ieee.mantissa1; +- /* If the lower double is not a denomal or zero then set the hidden +- 53rd bit. */ +- if (u.d[1].ieee.exponent > 0x001) +- { +- lo |= (1ULL << 52); +- lo = lo << 7; /* pre-shift lo to match ieee854. */ +- /* The lower double is normalized separately from the upper. We +- may need to adjust the lower manitissa to reflect this. */ +- ediff = u.d[0].ieee.exponent - u.d[1].ieee.exponent; +- if (ediff > 53) +- lo = lo >> (ediff-53); +- hi |= (1ULL << 52); +- } + +- if ((u.d[0].ieee.negative != u.d[1].ieee.negative) +- && ((u.d[1].ieee.exponent != 0) && (lo != 0LL))) ++ if (u.d[0].ieee.exponent != 0) + { +- hi--; +- lo = (1ULL << 60) - lo; +- if (hi < (1ULL << 52)) ++ int ediff; ++ ++ /* If not a denormal or zero then we have an implicit 53rd bit. */ ++ hi |= (uint64_t) 1 << 52; ++ ++ if (u.d[1].ieee.exponent != 0) ++ lo |= (uint64_t) 1 << 52; ++ else ++ /* A denormal is to be interpreted as having a biased exponent ++ of 1. */ ++ lo = lo << 1; ++ ++ /* We are going to shift 4 bits out of hi later, because we only ++ want 48 bits in *hi64. That means we want 60 bits in lo, but ++ we currently only have 53. Shift the value up. */ ++ lo = lo << 7; ++ ++ /* The lower double is normalized separately from the upper. ++ We may need to adjust the lower mantissa to reflect this. ++ The difference between the exponents can be larger than 53 ++ when the low double is much less than 1ULP of the upper ++ (in which case there are significant bits, all 0's or all ++ 1's, between the two significands). The difference between ++ the exponents can be less than 53 when the upper double ++ exponent is nearing its minimum value (in which case the low ++ double is denormal ie. has an exponent of zero). */ ++ ediff = u.d[0].ieee.exponent - u.d[1].ieee.exponent - 53; ++ if (ediff > 0) + { +- /* we have a borrow from the hidden bit, so shift left 1. */ +- hi = (hi << 1) | (lo >> 59); +- lo = 0xfffffffffffffffLL & (lo << 1); +- *exp = *exp - 1; ++ if (ediff < 64) ++ lo = lo >> ediff; ++ else ++ lo = 0; ++ } ++ else if (ediff < 0) ++ lo = lo << -ediff; ++ ++ if (u.d[0].ieee.negative != u.d[1].ieee.negative ++ && lo != 0) ++ { ++ hi--; ++ lo = ((uint64_t) 1 << 60) - lo; ++ if (hi < (uint64_t) 1 << 52) ++ { ++ /* We have a borrow from the hidden bit, so shift left 1. */ ++ hi = (hi << 1) | (lo >> 59); ++ lo = (((uint64_t) 1 << 60) - 1) & (lo << 1); ++ *exp = *exp - 1; ++ } + } + } ++ else ++ /* If the larger magnitude double is denormal then the smaller ++ one must be zero. */ ++ hi = hi << 1; ++ + *lo64 = (hi << 60) | lo; + *hi64 = hi >> 4; + } + + static inline long double +-ldbl_insert_mantissa (int sign, int exp, int64_t hi64, u_int64_t lo64) ++ldbl_insert_mantissa (int sign, int exp, int64_t hi64, uint64_t lo64) + { + union ibm_extended_long_double u; +- unsigned long hidden2, lzcount; +- unsigned long long hi, lo; ++ int expnt2; ++ uint64_t hi, lo; + + u.d[0].ieee.negative = sign; + u.d[1].ieee.negative = sign; + u.d[0].ieee.exponent = exp + IEEE754_DOUBLE_BIAS; +- u.d[1].ieee.exponent = exp-53 + IEEE754_DOUBLE_BIAS; ++ u.d[1].ieee.exponent = 0; ++ expnt2 = exp - 53 + IEEE754_DOUBLE_BIAS; ++ + /* Expect 113 bits (112 bits + hidden) right justified in two longs. + The low order 53 bits (52 + hidden) go into the lower double */ +- lo = (lo64 >> 7)& ((1ULL << 53) - 1); +- hidden2 = (lo64 >> 59) & 1ULL; ++ lo = (lo64 >> 7) & (((uint64_t) 1 << 53) - 1); + /* The high order 53 bits (52 + hidden) go into the upper double */ +- hi = (lo64 >> 60) & ((1ULL << 11) - 1); +- hi |= (hi64 << 4); ++ hi = lo64 >> 60; ++ hi |= hi64 << 4; + +- if (lo != 0LL) ++ if (lo != 0) + { +- /* hidden2 bit of low double controls rounding of the high double. +- If hidden2 is '1' then round up hi and adjust lo (2nd mantissa) ++ int lzcount; ++ ++ /* hidden bit of low double controls rounding of the high double. ++ If hidden is '1' and either the explicit mantissa is non-zero ++ or hi is odd, then round up hi and adjust lo (2nd mantissa) + plus change the sign of the low double to compensate. */ +- if (hidden2) ++ if ((lo & ((uint64_t) 1 << 52)) != 0 ++ && ((hi & 1) != 0 || (lo & (((uint64_t) 1 << 52) - 1)) != 0)) + { + hi++; ++ if ((hi & ((uint64_t) 1 << 53)) != 0) ++ { ++ hi = hi >> 1; ++ u.d[0].ieee.exponent++; ++ } + u.d[1].ieee.negative = !sign; +- lo = (1ULL << 53) - lo; ++ lo = ((uint64_t) 1 << 53) - lo; + } +- /* The hidden bit of the lo mantissa is zero so we need to +- normalize the it for the low double. Shift it left until the +- hidden bit is '1' then adjust the 2nd exponent accordingly. */ ++ /* Normalize the low double. Shift the mantissa left until ++ the hidden bit is '1' and adjust the exponent accordingly. */ + + if (sizeof (lo) == sizeof (long)) + lzcount = __builtin_clzl (lo); +@@ -91,34 +132,30 @@ + lzcount = __builtin_clzl ((long) (lo >> 32)); + else + lzcount = __builtin_clzl ((long) lo) + 32; +- lzcount = lzcount - 11; +- if (lzcount > 0) ++ lzcount = lzcount - (64 - 53); ++ lo <<= lzcount; ++ expnt2 -= lzcount; ++ ++ if (expnt2 >= 1) ++ /* Not denormal. */ ++ u.d[1].ieee.exponent = expnt2; ++ else + { +- int expnt2 = u.d[1].ieee.exponent - lzcount; +- if (expnt2 >= 1) +- { +- /* Not denormal. Normalize and set low exponent. */ +- lo = lo << lzcount; +- u.d[1].ieee.exponent = expnt2; +- } ++ /* Is denormal. Note that biased exponent of 0 is treated ++ as if it was 1, hence the extra shift. */ ++ if (expnt2 > -53) ++ lo >>= 1 - expnt2; + else +- { +- /* Is denormal. */ +- lo = lo << (lzcount + expnt2); +- u.d[1].ieee.exponent = 0; +- } ++ lo = 0; + } + } + else +- { +- u.d[1].ieee.negative = 0; +- u.d[1].ieee.exponent = 0; +- } ++ u.d[1].ieee.negative = 0; + +- u.d[1].ieee.mantissa1 = lo & ((1ULL << 32) - 1); +- u.d[1].ieee.mantissa0 = (lo >> 32) & ((1ULL << 20) - 1); +- u.d[0].ieee.mantissa1 = hi & ((1ULL << 32) - 1); +- u.d[0].ieee.mantissa0 = (hi >> 32) & ((1ULL << 20) - 1); ++ u.d[1].ieee.mantissa1 = lo; ++ u.d[1].ieee.mantissa0 = lo >> 32; ++ u.d[0].ieee.mantissa1 = hi; ++ u.d[0].ieee.mantissa0 = hi >> 32; + return u.ld; + } + +@@ -133,6 +170,10 @@ + return u.ld; + } + ++/* To suit our callers we return *hi64 and *lo64 as if they came from ++ an ieee854 112 bit mantissa, that is, 48 bits in *hi64 (plus one ++ implicit bit) and 64 bits in *lo64. */ ++ + static inline void + default_ldbl_unpack (long double l, double *a, double *aa) + { +@@ -162,13 +203,13 @@ + *aa = xl; + } + +-/* Simple inline nearbyint (double) function . ++/* Simple inline nearbyint (double) function. + Only works in the default rounding mode + but is useful in long double rounding functions. */ + static inline double + ldbl_nearbyint (double a) + { +- double two52 = 0x10000000000000LL; ++ double two52 = 0x1p52; + + if (__builtin_expect ((__builtin_fabs (a) < two52), 1)) + { +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c 2014-05-27 19:13:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c 2014-05-27 19:14:45.000000000 -0500 +@@ -70,9 +70,9 @@ + else + lzcount = __builtin_clzl ((long) val) + 32; + if (hi) +- lzcount = lzcount - 11; ++ lzcount = lzcount - (64 - 53); + else +- lzcount = lzcount + 42; ++ lzcount = lzcount + 53 - (64 - 53); + + if (lzcount > u.d[0].ieee.exponent) + { +@@ -98,29 +98,27 @@ + } + } + +- if (lo != 0L) ++ if (lo != 0) + { +- /* hidden2 bit of low double controls rounding of the high double. +- If hidden2 is '1' and either the explicit mantissa is non-zero ++ /* hidden bit of low double controls rounding of the high double. ++ If hidden is '1' and either the explicit mantissa is non-zero + or hi is odd, then round up hi and adjust lo (2nd mantissa) + plus change the sign of the low double to compensate. */ + if ((lo & (1LL << 52)) != 0 +- && ((hi & 1) != 0 || (lo & ((1LL << 52) - 1)))) ++ && ((hi & 1) != 0 || (lo & ((1LL << 52) - 1)) != 0)) + { + hi++; +- if ((hi & ((1LL << 52) - 1)) == 0) ++ if ((hi & (1LL << 53)) != 0) + { +- if ((hi & (1LL << 53)) != 0) +- hi -= 1LL << 52; ++ hi >>= 1; + u.d[0].ieee.exponent++; + } + u.d[1].ieee.negative = !sign; + lo = (1LL << 53) - lo; + } + +- /* The hidden bit of the lo mantissa is zero so we need to normalize +- it for the low double. Shift it left until the hidden bit is '1' +- then adjust the 2nd exponent accordingly. */ ++ /* Normalize the low double. Shift the mantissa left until ++ the hidden bit is '1' and adjust the exponent accordingly. */ + + if (sizeof (lo) == sizeof (long)) + lzcount = __builtin_clzl (lo); +@@ -128,24 +126,24 @@ + lzcount = __builtin_clzl ((long) (lo >> 32)); + else + lzcount = __builtin_clzl ((long) lo) + 32; +- lzcount = lzcount - 11; +- if (lzcount > 0) +- { +- lo = lo << lzcount; +- exponent2 = exponent2 - lzcount; +- } ++ lzcount = lzcount - (64 - 53); ++ lo <<= lzcount; ++ exponent2 -= lzcount; ++ + if (exponent2 > 0) + u.d[1].ieee.exponent = exponent2; +- else ++ else if (exponent2 > -53) + lo >>= 1 - exponent2; ++ else ++ lo = 0; + } + else + u.d[1].ieee.negative = 0; + +- u.d[1].ieee.mantissa1 = lo & 0xffffffffLL; +- u.d[1].ieee.mantissa0 = (lo >> 32) & 0xfffff; +- u.d[0].ieee.mantissa1 = hi & 0xffffffffLL; +- u.d[0].ieee.mantissa0 = (hi >> 32) & ((1LL << (LDBL_MANT_DIG - 86)) - 1); ++ u.d[1].ieee.mantissa1 = lo; ++ u.d[1].ieee.mantissa0 = lo >> 32; ++ u.d[0].ieee.mantissa1 = hi; ++ u.d[0].ieee.mantissa0 = hi >> 32; + + return u.ld; + } +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c 2014-05-27 19:13:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c 2014-05-27 19:14:45.000000000 -0500 +@@ -43,15 +43,15 @@ + lo <<= 1; \ + /* The lower double is normalized separately from the upper. We \ + may need to adjust the lower manitissa to reflect this. */ \ +- ediff = u.d[0].ieee.exponent - u.d[1].ieee.exponent; \ +- if (ediff > 53 + 63) \ ++ ediff = u.d[0].ieee.exponent - u.d[1].ieee.exponent - 53; \ ++ if (ediff > 63) \ + lo = 0; \ +- else if (ediff > 53) \ +- lo = lo >> (ediff - 53); \ +- else if (u.d[1].ieee.exponent == 0 && ediff < 53) \ +- lo = lo << (53 - ediff); \ ++ else if (ediff > 0) \ ++ lo = lo >> ediff; \ ++ else if (ediff < 0) \ ++ lo = lo << -ediff; \ + if (u.d[0].ieee.negative != u.d[1].ieee.negative \ +- && (u.d[1].ieee.exponent != 0 || lo != 0L)) \ ++ && lo != 0) \ + { \ + lo = (1ULL << 60) - lo; \ + if (hi == 0L) \ diff --git a/SOURCES/glibc-ppc64le-06.patch b/SOURCES/glibc-ppc64le-06.patch new file mode 100644 index 0000000..fe7cf61 --- /dev/null +++ b/SOURCES/glibc-ppc64le-06.patch @@ -0,0 +1,652 @@ +# commit 1b6adf888de14675bc3207578dcb7132ed5f8ecc +# Author: Alan Modra +# Date: Sat Aug 17 18:21:58 2013 +0930 +# +# PowerPC floating point little-endian [1 of 15] +# http://sourceware.org/ml/libc-alpha/2013-08/msg00081.html +# +# This is the first of a series of patches to ban ieee854_long_double +# and the ieee854_long_double macros when using IBM long double. union +# ieee854_long_double just isn't correct for IBM long double, especially +# when little-endian, and pretending it is OK has allowed a number of +# bugs to remain undetected in sysdeps/ieee754/ldbl-128ibm/. +# +# This changes the few places in generic code that use it. +# +# * stdio-common/printf_size.c (__printf_size): Don't use +# union ieee854_long_double in fpnum union. +# * stdio-common/printf_fphex.c (__printf_fphex): Likewise. Use +# signbit macro to retrieve sign from long double. +# * stdio-common/printf_fp.c (___printf_fp): Use signbit macro to +# retrieve sign from long double. +# * sysdeps/ieee754/ldbl-128ibm/printf_fphex.c: Adjust for fpnum change. +# * sysdeps/ieee754/ldbl-128/printf_fphex.c: Likewise. +# * sysdeps/ieee754/ldbl-96/printf_fphex.c: Likewise. +# * sysdeps/x86_64/fpu/printf_fphex.c: Likewise. +# * math/test-misc.c (main): Don't use union ieee854_long_double. +# ports/ +# * sysdeps/ia64/fpu/printf_fphex.c: Adjust for fpnum change. +# +diff -urN glibc-2.17-c758a686/math/test-misc.c glibc-2.17-c758a686/math/test-misc.c +--- glibc-2.17-c758a686/math/test-misc.c 2014-05-27 19:53:22.000000000 -0500 ++++ glibc-2.17-c758a686/math/test-misc.c 2014-05-27 19:53:45.000000000 -0500 +@@ -721,300 +721,161 @@ + + #ifndef NO_LONG_DOUBLE + { +- union ieee854_long_double v1; +- union ieee854_long_double v2; +- long double ld; ++ long double v1, v2; + +- v1.d = ld = LDBL_MIN; +- if (fpclassify (ld) != FP_NORMAL) ++ v1 = LDBL_MIN; ++ if (fpclassify (v1) != FP_NORMAL) + { +- printf ("fpclassify (LDBL_MIN) failed: %d\n", fpclassify (ld)); ++ printf ("fpclassify (LDBL_MIN) failed: %d (%La)\n", ++ fpclassify (v1), v1); + result = 1; + } +- ld = nextafterl (ld, LDBL_MIN / 2.0); +- if (fpclassify (ld) != FP_SUBNORMAL) ++ v2 = nextafterl (v1, LDBL_MIN / 2.0); ++ if (fpclassify (v2) != FP_SUBNORMAL) + { + printf ("fpclassify (LDBL_MIN-epsilon) failed: %d (%La)\n", +- fpclassify (ld), ld); ++ fpclassify (v2), v2); + result = 1; + } +- v2.d = ld = nextafterl (ld, LDBL_MIN); +- if (fpclassify (ld) != FP_NORMAL) ++ v2 = nextafterl (v2, LDBL_MIN); ++ if (fpclassify (v2) != FP_NORMAL) + { + printf ("fpclassify (LDBL_MIN-epsilon+epsilon) failed: %d (%La)\n", +- fpclassify (ld), ld); ++ fpclassify (v2), v2); + result = 1; + } + +- if (v1.ieee.mantissa0 != v2.ieee.mantissa0) ++ if (v1 != v2) + { +- printf ("LDBL_MIN: mantissa0 differs: %8x vs %8x\n", +- v1.ieee.mantissa0, v2.ieee.mantissa0); +- result = 1; +- } +- if (v1.ieee.mantissa1 != v2.ieee.mantissa1) +- { +- printf ("LDBL_MIN: mantissa1 differs: %8x vs %8x\n", +- v1.ieee.mantissa1, v2.ieee.mantissa1); +- result = 1; +- } +- if (v1.ieee.exponent != v2.ieee.exponent) +- { +- printf ("LDBL_MIN: exponent differs: %4x vs %4x\n", +- v1.ieee.exponent, v2.ieee.exponent); +- result = 1; +- } +- if (v1.ieee.negative != v2.ieee.negative) +- { +- printf ("LDBL_MIN: negative differs: %d vs %d\n", +- v1.ieee.negative, v2.ieee.negative); ++ printf ("LDBL_MIN-epsilon+epsilon != LDBL_MIN: %La vs %La\n", v2, v1); + result = 1; + } + +- v1.d = ld = -LDBL_MIN; +- if (fpclassify (ld) != FP_NORMAL) ++ v1 = -LDBL_MIN; ++ if (fpclassify (v1) != FP_NORMAL) + { +- printf ("fpclassify (-LDBL_MIN) failed: %d\n", fpclassify (ld)); ++ printf ("fpclassify (-LDBL_MIN) failed: %d (%La)\n", ++ fpclassify (v1), v1); + result = 1; + } +- ld = nextafterl (ld, -LDBL_MIN / 2.0); +- if (fpclassify (ld) != FP_SUBNORMAL) ++ v2 = nextafterl (v1, -LDBL_MIN / 2.0); ++ if (fpclassify (v2) != FP_SUBNORMAL) + { + printf ("fpclassify (-LDBL_MIN-epsilon) failed: %d (%La)\n", +- fpclassify (ld), ld); ++ fpclassify (v2), v2); + result = 1; + } +- v2.d = ld = nextafterl (ld, -LDBL_MIN); +- if (fpclassify (ld) != FP_NORMAL) ++ v2 = nextafterl (v2, -LDBL_MIN); ++ if (fpclassify (v2) != FP_NORMAL) + { + printf ("fpclassify (-LDBL_MIN-epsilon+epsilon) failed: %d (%La)\n", +- fpclassify (ld), ld); ++ fpclassify (v2), v2); + result = 1; + } + +- if (v1.ieee.mantissa0 != v2.ieee.mantissa0) ++ if (v1 != v2) + { +- printf ("-LDBL_MIN: mantissa0 differs: %8x vs %8x\n", +- v1.ieee.mantissa0, v2.ieee.mantissa0); +- result = 1; +- } +- if (v1.ieee.mantissa1 != v2.ieee.mantissa1) +- { +- printf ("-LDBL_MIN: mantissa1 differs: %8x vs %8x\n", +- v1.ieee.mantissa1, v2.ieee.mantissa1); +- result = 1; +- } +- if (v1.ieee.exponent != v2.ieee.exponent) +- { +- printf ("-LDBL_MIN: exponent differs: %4x vs %4x\n", +- v1.ieee.exponent, v2.ieee.exponent); +- result = 1; +- } +- if (v1.ieee.negative != v2.ieee.negative) +- { +- printf ("-LDBL_MIN: negative differs: %d vs %d\n", +- v1.ieee.negative, v2.ieee.negative); ++ printf ("-LDBL_MIN-epsilon+epsilon != -LDBL_MIN: %La vs %La\n", v2, v1); + result = 1; + } + +- ld = LDBL_MAX; +- if (fpclassify (ld) != FP_NORMAL) ++ v1 = LDBL_MAX; ++ if (fpclassify (v1) != FP_NORMAL) + { +- printf ("fpclassify (LDBL_MAX) failed: %d\n", fpclassify (ld)); ++ printf ("fpclassify (LDBL_MAX) failed: %d (%La)\n", ++ fpclassify (v1), v1); + result = 1; + } +- ld = nextafterl (ld, INFINITY); +- if (fpclassify (ld) != FP_INFINITE) ++ v2 = nextafterl (v1, INFINITY); ++ if (fpclassify (v2) != FP_INFINITE) + { +- printf ("fpclassify (LDBL_MAX+epsilon) failed: %d\n", fpclassify (ld)); ++ printf ("fpclassify (LDBL_MAX+epsilon) failed: %d (%La)\n", ++ fpclassify (v2), v2); + result = 1; + } + +- ld = -LDBL_MAX; +- if (fpclassify (ld) != FP_NORMAL) ++ v1 = -LDBL_MAX; ++ if (fpclassify (v1) != FP_NORMAL) + { +- printf ("fpclassify (-LDBL_MAX) failed: %d\n", fpclassify (ld)); ++ printf ("fpclassify (-LDBL_MAX) failed: %d (%La)\n", ++ fpclassify (v1), v1); + result = 1; + } +- ld = nextafterl (ld, -INFINITY); +- if (fpclassify (ld) != FP_INFINITE) ++ v2 = nextafterl (v1, -INFINITY); ++ if (fpclassify (v2) != FP_INFINITE) + { +- printf ("fpclassify (-LDBL_MAX-epsilon) failed: %d\n", +- fpclassify (ld)); ++ printf ("fpclassify (-LDBL_MAX-epsilon) failed: %d (%La)\n", ++ fpclassify (v2), v2); + result = 1; + } + +- v1.d = ld = 0.0625; +- ld = nextafterl (ld, 0.0); +- v2.d = ld = nextafterl (ld, 1.0); ++ v1 = 0.0625; ++ v2 = nextafterl (v1, 0.0); ++ v2 = nextafterl (v2, 1.0); + +- if (v1.ieee.mantissa0 != v2.ieee.mantissa0) +- { +- printf ("0.0625L down: mantissa0 differs: %8x vs %8x\n", +- v1.ieee.mantissa0, v2.ieee.mantissa0); +- result = 1; +- } +- if (v1.ieee.mantissa1 != v2.ieee.mantissa1) +- { +- printf ("0.0625L down: mantissa1 differs: %8x vs %8x\n", +- v1.ieee.mantissa1, v2.ieee.mantissa1); +- result = 1; +- } +- if (v1.ieee.exponent != v2.ieee.exponent) +- { +- printf ("0.0625L down: exponent differs: %4x vs %4x\n", +- v1.ieee.exponent, v2.ieee.exponent); +- result = 1; +- } +- if (v1.ieee.negative != v2.ieee.negative) ++ if (v1 != v2) + { +- printf ("0.0625L down: negative differs: %d vs %d\n", +- v1.ieee.negative, v2.ieee.negative); ++ printf ("0.0625L-epsilon+epsilon != 0.0625L: %La vs %La\n", v2, v1); + result = 1; + } + +- v1.d = ld = 0.0625; +- ld = nextafterl (ld, 1.0); +- v2.d = ld = nextafterl (ld, 0.0); ++ v1 = 0.0625; ++ v2 = nextafterl (v1, 1.0); ++ v2 = nextafterl (v2, 0.0); + +- if (v1.ieee.mantissa0 != v2.ieee.mantissa0) +- { +- printf ("0.0625L up: mantissa0 differs: %8x vs %8x\n", +- v1.ieee.mantissa0, v2.ieee.mantissa0); +- result = 1; +- } +- if (v1.ieee.mantissa1 != v2.ieee.mantissa1) +- { +- printf ("0.0625L up: mantissa1 differs: %8x vs %8x\n", +- v1.ieee.mantissa1, v2.ieee.mantissa1); +- result = 1; +- } +- if (v1.ieee.exponent != v2.ieee.exponent) ++ if (v1 != v2) + { +- printf ("0.0625L up: exponent differs: %4x vs %4x\n", +- v1.ieee.exponent, v2.ieee.exponent); +- result = 1; +- } +- if (v1.ieee.negative != v2.ieee.negative) +- { +- printf ("0.0625L up: negative differs: %d vs %d\n", +- v1.ieee.negative, v2.ieee.negative); ++ printf ("0.0625L+epsilon-epsilon != 0.0625L: %La vs %La\n", v2, v1); + result = 1; + } + +- v1.d = ld = -0.0625; +- ld = nextafterl (ld, 0.0); +- v2.d = ld = nextafterl (ld, -1.0); ++ v1 = -0.0625; ++ v2 = nextafterl (v1, 0.0); ++ v2 = nextafterl (v2, -1.0); + +- if (v1.ieee.mantissa0 != v2.ieee.mantissa0) +- { +- printf ("-0.0625L up: mantissa0 differs: %8x vs %8x\n", +- v1.ieee.mantissa0, v2.ieee.mantissa0); +- result = 1; +- } +- if (v1.ieee.mantissa1 != v2.ieee.mantissa1) +- { +- printf ("-0.0625L up: mantissa1 differs: %8x vs %8x\n", +- v1.ieee.mantissa1, v2.ieee.mantissa1); +- result = 1; +- } +- if (v1.ieee.exponent != v2.ieee.exponent) ++ if (v1 != v2) + { +- printf ("-0.0625L up: exponent differs: %4x vs %4x\n", +- v1.ieee.exponent, v2.ieee.exponent); +- result = 1; +- } +- if (v1.ieee.negative != v2.ieee.negative) +- { +- printf ("-0.0625L up: negative differs: %d vs %d\n", +- v1.ieee.negative, v2.ieee.negative); ++ printf ("-0.0625L+epsilon-epsilon != -0.0625L: %La vs %La\n", v2, v1); + result = 1; + } + +- v1.d = ld = -0.0625; +- ld = nextafterl (ld, -1.0); +- v2.d = ld = nextafterl (ld, 0.0); ++ v1 = -0.0625; ++ v2 = nextafterl (v1, -1.0); ++ v2 = nextafterl (v2, 0.0); + +- if (v1.ieee.mantissa0 != v2.ieee.mantissa0) +- { +- printf ("-0.0625L down: mantissa0 differs: %8x vs %8x\n", +- v1.ieee.mantissa0, v2.ieee.mantissa0); +- result = 1; +- } +- if (v1.ieee.mantissa1 != v2.ieee.mantissa1) ++ if (v1 != v2) + { +- printf ("-0.0625L down: mantissa1 differs: %8x vs %8x\n", +- v1.ieee.mantissa1, v2.ieee.mantissa1); +- result = 1; +- } +- if (v1.ieee.exponent != v2.ieee.exponent) +- { +- printf ("-0.0625L down: exponent differs: %4x vs %4x\n", +- v1.ieee.exponent, v2.ieee.exponent); +- result = 1; +- } +- if (v1.ieee.negative != v2.ieee.negative) +- { +- printf ("-0.0625L down: negative differs: %d vs %d\n", +- v1.ieee.negative, v2.ieee.negative); ++ printf ("-0.0625L-epsilon+epsilon != -0.0625L: %La vs %La\n", v2, v1); + result = 1; + } + +- v1.d = ld = 0.0; +- ld = nextafterl (ld, 1.0); +- v2.d = nextafterl (ld, -1.0); ++ v1 = 0.0; ++ v2 = nextafterl (v1, 1.0); ++ v2 = nextafterl (v2, -1.0); + +- if (v1.ieee.mantissa0 != v2.ieee.mantissa0) +- { +- printf ("0.0L up: mantissa0 differs: %8x vs %8x\n", +- v1.ieee.mantissa0, v2.ieee.mantissa0); +- result = 1; +- } +- if (v1.ieee.mantissa1 != v2.ieee.mantissa1) +- { +- printf ("0.0L up: mantissa1 differs: %8x vs %8x\n", +- v1.ieee.mantissa1, v2.ieee.mantissa1); +- result = 1; +- } +- if (v1.ieee.exponent != v2.ieee.exponent) ++ if (v1 != v2) + { +- printf ("0.0L up: exponent differs: %4x vs %4x\n", +- v1.ieee.exponent, v2.ieee.exponent); ++ printf ("0.0+epsilon-epsilon != 0.0L: %La vs %La\n", v2, v1); + result = 1; + } +- if (0 != v2.ieee.negative) ++ if (signbit (v2)) + { +- printf ("0.0L up: negative differs: 0 vs %d\n", +- v2.ieee.negative); ++ printf ("0.0+epsilon-epsilon is negative\n"); + result = 1; + } + +- v1.d = ld = 0.0; +- ld = nextafterl (ld, -1.0); +- v2.d = nextafterl (ld, 1.0); ++ v1 = 0.0; ++ v2 = nextafterl (v1, -1.0); ++ v2 = nextafterl (v2, 1.0); + +- if (v1.ieee.mantissa0 != v2.ieee.mantissa0) +- { +- printf ("0.0L down: mantissa0 differs: %8x vs %8x\n", +- v1.ieee.mantissa0, v2.ieee.mantissa0); +- result = 1; +- } +- if (v1.ieee.mantissa1 != v2.ieee.mantissa1) +- { +- printf ("0.0L down: mantissa1 differs: %8x vs %8x\n", +- v1.ieee.mantissa1, v2.ieee.mantissa1); +- result = 1; +- } +- if (v1.ieee.exponent != v2.ieee.exponent) ++ if (v1 != v2) + { +- printf ("0.0L down: exponent differs: %4x vs %4x\n", +- v1.ieee.exponent, v2.ieee.exponent); ++ printf ("0.0-epsilon+epsilon != 0.0L: %La vs %La\n", v2, v1); + result = 1; + } +- if (1 != v2.ieee.negative) ++ if (!signbit (v2)) + { +- printf ("0.0L down: negative differs: 1 vs %d\n", +- v2.ieee.negative); ++ printf ("0.0-epsilon+epsilon is positive\n"); + result = 1; + } + +diff -urN glibc-2.17-c758a686/ports/sysdeps/ia64/fpu/printf_fphex.c glibc-2.17-c758a686/ports/sysdeps/ia64/fpu/printf_fphex.c +--- glibc-2.17-c758a686/ports/sysdeps/ia64/fpu/printf_fphex.c 2014-05-27 19:53:21.000000000 -0500 ++++ glibc-2.17-c758a686/ports/sysdeps/ia64/fpu/printf_fphex.c 2014-05-27 19:53:45.000000000 -0500 +@@ -25,9 +25,11 @@ + /* The "strange" 80 bit format on ia64 has an explicit \ + leading digit in the 64 bit mantissa. */ \ + unsigned long long int num; \ ++ union ieee854_long_double u; \ ++ u.d = fpnum.ldbl; \ + \ +- num = (((unsigned long long int) fpnum.ldbl.ieee.mantissa0) << 32 \ +- | fpnum.ldbl.ieee.mantissa1); \ ++ num = (((unsigned long long int) u.ieee.mantissa0) << 32 \ ++ | u.ieee.mantissa1); \ + \ + zero_mantissa = num == 0; \ + \ +@@ -49,8 +51,8 @@ + \ + /* We have 3 bits from the mantissa in the leading nibble. \ + Therefore we are here using `IEEE854_LONG_DOUBLE_BIAS + 3'. */ \ +- exponent = fpnum.ldbl.ieee.exponent; \ +- \ ++ exponent = u.ieee.exponent; \ ++ \ + if (exponent == 0) \ + { \ + if (zero_mantissa) \ +diff -urN glibc-2.17-c758a686/stdio-common/printf_fp.c glibc-2.17-c758a686/stdio-common/printf_fp.c +--- glibc-2.17-c758a686/stdio-common/printf_fp.c 2014-05-27 19:53:22.000000000 -0500 ++++ glibc-2.17-c758a686/stdio-common/printf_fp.c 2014-05-27 19:53:45.000000000 -0500 +@@ -335,8 +335,7 @@ + int res; + if (__isnanl (fpnum.ldbl)) + { +- union ieee854_long_double u = { .d = fpnum.ldbl }; +- is_neg = u.ieee.negative != 0; ++ is_neg = signbit (fpnum.ldbl); + if (isupper (info->spec)) + { + special = "NAN"; +diff -urN glibc-2.17-c758a686/stdio-common/printf_fphex.c glibc-2.17-c758a686/stdio-common/printf_fphex.c +--- glibc-2.17-c758a686/stdio-common/printf_fphex.c 2014-05-27 19:53:22.000000000 -0500 ++++ glibc-2.17-c758a686/stdio-common/printf_fphex.c 2014-05-27 19:53:45.000000000 -0500 +@@ -93,7 +93,7 @@ + union + { + union ieee754_double dbl; +- union ieee854_long_double ldbl; ++ long double ldbl; + } + fpnum; + +@@ -162,12 +162,11 @@ + #ifndef __NO_LONG_DOUBLE_MATH + if (info->is_long_double && sizeof (long double) > sizeof (double)) + { +- fpnum.ldbl.d = *(const long double *) args[0]; ++ fpnum.ldbl = *(const long double *) args[0]; + + /* Check for special values: not a number or infinity. */ +- if (__isnanl (fpnum.ldbl.d)) ++ if (__isnanl (fpnum.ldbl)) + { +- negative = fpnum.ldbl.ieee.negative != 0; + if (isupper (info->spec)) + { + special = "NAN"; +@@ -181,8 +180,7 @@ + } + else + { +- int res = __isinfl (fpnum.ldbl.d); +- if (res) ++ if (__isinfl (fpnum.ldbl)) + { + if (isupper (info->spec)) + { +@@ -194,11 +192,9 @@ + special = "inf"; + wspecial = L"inf"; + } +- negative = res < 0; + } +- else +- negative = signbit (fpnum.ldbl.d); + } ++ negative = signbit (fpnum.ldbl); + } + else + #endif /* no long double */ +diff -urN glibc-2.17-c758a686/stdio-common/printf_size.c glibc-2.17-c758a686/stdio-common/printf_size.c +--- glibc-2.17-c758a686/stdio-common/printf_size.c 2014-05-27 19:53:22.000000000 -0500 ++++ glibc-2.17-c758a686/stdio-common/printf_size.c 2014-05-27 19:53:45.000000000 -0500 +@@ -103,7 +103,7 @@ + union + { + union ieee754_double dbl; +- union ieee854_long_double ldbl; ++ long double ldbl; + } + fpnum; + const void *ptr = &fpnum; +@@ -123,25 +123,25 @@ + #ifndef __NO_LONG_DOUBLE_MATH + if (info->is_long_double && sizeof (long double) > sizeof (double)) + { +- fpnum.ldbl.d = *(const long double *) args[0]; ++ fpnum.ldbl = *(const long double *) args[0]; + + /* Check for special values: not a number or infinity. */ +- if (__isnanl (fpnum.ldbl.d)) ++ if (__isnanl (fpnum.ldbl)) + { + special = "nan"; + wspecial = L"nan"; + // fpnum_sign = 0; Already zero + } +- else if ((res = __isinfl (fpnum.ldbl.d))) ++ else if ((res = __isinfl (fpnum.ldbl))) + { + fpnum_sign = res; + special = "inf"; + wspecial = L"inf"; + } + else +- while (fpnum.ldbl.d >= divisor && tag[1] != '\0') ++ while (fpnum.ldbl >= divisor && tag[1] != '\0') + { +- fpnum.ldbl.d /= divisor; ++ fpnum.ldbl /= divisor; + ++tag; + } + } +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128/printf_fphex.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128/printf_fphex.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128/printf_fphex.c 2014-05-27 19:53:20.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128/printf_fphex.c 2014-05-27 19:53:45.000000000 -0500 +@@ -24,13 +24,15 @@ + digits we use only the implicit digits for the number before \ + the decimal point. */ \ + unsigned long long int num0, num1; \ ++ union ieee854_long_double u; \ ++ u.d = fpnum.ldbl; \ + \ + assert (sizeof (long double) == 16); \ + \ +- num0 = (((unsigned long long int) fpnum.ldbl.ieee.mantissa0) << 32 \ +- | fpnum.ldbl.ieee.mantissa1); \ +- num1 = (((unsigned long long int) fpnum.ldbl.ieee.mantissa2) << 32 \ +- | fpnum.ldbl.ieee.mantissa3); \ ++ num0 = (((unsigned long long int) u.ieee.mantissa0) << 32 \ ++ | u.ieee.mantissa1); \ ++ num1 = (((unsigned long long int) u.ieee.mantissa2) << 32 \ ++ | u.ieee.mantissa3); \ + \ + zero_mantissa = (num0|num1) == 0; \ + \ +@@ -75,9 +77,9 @@ + *--wnumstr = L'0'; \ + } \ + \ +- leading = fpnum.ldbl.ieee.exponent == 0 ? '0' : '1'; \ ++ leading = u.ieee.exponent == 0 ? '0' : '1'; \ + \ +- exponent = fpnum.ldbl.ieee.exponent; \ ++ exponent = u.ieee.exponent; \ + \ + if (exponent == 0) \ + { \ +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c 2014-05-27 19:53:20.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c 2014-05-27 19:53:45.000000000 -0500 +@@ -28,14 +28,14 @@ + unsigned long long hi, lo; \ + int ediff; \ + union ibm_extended_long_double u; \ +- u.ld = fpnum.ldbl.d; \ ++ u.ld = fpnum.ldbl; \ + \ + assert (sizeof (long double) == 16); \ + \ + lo = ((long long)u.d[1].ieee.mantissa0 << 32) | u.d[1].ieee.mantissa1; \ + hi = ((long long)u.d[0].ieee.mantissa0 << 32) | u.d[0].ieee.mantissa1; \ + lo <<= 7; /* pre-shift lo to match ieee854. */ \ +- /* If the lower double is not a denomal or zero then set the hidden \ ++ /* If the lower double is not a denormal or zero then set the hidden \ + 53rd bit. */ \ + if (u.d[1].ieee.exponent != 0) \ + lo |= (1ULL << (52 + 7)); \ +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-96/printf_fphex.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-96/printf_fphex.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-96/printf_fphex.c 2014-05-27 19:53:20.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-96/printf_fphex.c 2014-05-27 19:53:45.000000000 -0500 +@@ -25,11 +25,13 @@ + /* The "strange" 80 bit format on ix86 and m68k has an explicit \ + leading digit in the 64 bit mantissa. */ \ + unsigned long long int num; \ ++ union ieee854_long_double u; \ ++ u.d = fpnum.ldbl; \ + \ + assert (sizeof (long double) == 12); \ + \ +- num = (((unsigned long long int) fpnum.ldbl.ieee.mantissa0) << 32 \ +- | fpnum.ldbl.ieee.mantissa1); \ ++ num = (((unsigned long long int) u.ieee.mantissa0) << 32 \ ++ | u.ieee.mantissa1); \ + \ + zero_mantissa = num == 0; \ + \ +@@ -62,7 +64,7 @@ + \ + /* We have 3 bits from the mantissa in the leading nibble. \ + Therefore we are here using `IEEE854_LONG_DOUBLE_BIAS + 3'. */ \ +- exponent = fpnum.ldbl.ieee.exponent; \ ++ exponent = u.ieee.exponent; \ + \ + if (exponent == 0) \ + { \ +diff -urN glibc-2.17-c758a686/sysdeps/x86_64/fpu/printf_fphex.c glibc-2.17-c758a686/sysdeps/x86_64/fpu/printf_fphex.c +--- glibc-2.17-c758a686/sysdeps/x86_64/fpu/printf_fphex.c 2014-05-27 19:53:20.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/x86_64/fpu/printf_fphex.c 2014-05-27 19:53:45.000000000 -0500 +@@ -25,10 +25,11 @@ + /* The "strange" 80 bit format on ix86 and m68k has an explicit \ + leading digit in the 64 bit mantissa. */ \ + unsigned long long int num; \ ++ union ieee854_long_double u; \ ++ u.d = fpnum.ldbl; \ + \ +- \ +- num = (((unsigned long long int) fpnum.ldbl.ieee.mantissa0) << 32 \ +- | fpnum.ldbl.ieee.mantissa1); \ ++ num = (((unsigned long long int) u.ieee.mantissa0) << 32 \ ++ | u.ieee.mantissa1); \ + \ + zero_mantissa = num == 0; \ + \ +@@ -61,7 +62,7 @@ + \ + /* We have 3 bits from the mantissa in the leading nibble. \ + Therefore we are here using `IEEE854_LONG_DOUBLE_BIAS + 3'. */ \ +- exponent = fpnum.ldbl.ieee.exponent; \ ++ exponent = u.ieee.exponent; \ + \ + if (exponent == 0) \ + { \ diff --git a/SOURCES/glibc-ppc64le-07.patch b/SOURCES/glibc-ppc64le-07.patch new file mode 100644 index 0000000..120576e --- /dev/null +++ b/SOURCES/glibc-ppc64le-07.patch @@ -0,0 +1,651 @@ +# commit 4ebd120cd983c8d2ac7a234884b3ac6805d82973 +# Author: Alan Modra +# Date: Sat Aug 17 18:24:05 2013 +0930 +# +# PowerPC floating point little-endian [2 of 15] +# http://sourceware.org/ml/libc-alpha/2013-08/msg00082.html +# +# This patch replaces occurrences of GET_LDOUBLE_* and SET_LDOUBLE_* +# macros, and union ieee854_long_double_shape_type in ldbl-128ibm/, +# and a stray one in the 32-bit fpu support. These files have no +# significant changes apart from rewriting the long double bit access. +# +# * sysdeps/ieee754/ldbl-128ibm/math_ldbl.h (ldbl_high): Define. +# * sysdeps/ieee754/ldbl-128ibm/e_acoshl.c (__ieee754_acoshl): Rewrite +# all uses of ieee854 long double macros and unions. +# * sysdeps/ieee754/ldbl-128ibm/e_acosl.c (__ieee754_acosl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/e_asinl.c (__ieee754_asinl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/e_atanhl.c (__ieee754_atanhl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/e_coshl.c (__ieee754_coshl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/e_log2l.c (__ieee754_log2l): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c (__ieee754_rem_pio2l): +# Likewise. +# * sysdeps/ieee754/ldbl-128ibm/e_sinhl.c (__ieee754_sinhl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/k_cosl.c (__kernel_cosl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/k_sincosl.c (__kernel_sincosl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/k_sinl.c (__kernel_sinl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/s_asinhl.c (__asinhl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/s_atanl.c (__atanl): Likewise. +# Simplify sign and nan test too. +# * sysdeps/ieee754/ldbl-128ibm/s_cosl.c (__cosl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/s_fabsl.c (__fabsl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/s_finitel.c (___finitel): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/s_fpclassifyl.c (___fpclassifyl): +# Likewise. +# * sysdeps/ieee754/ldbl-128ibm/s_isnanl.c (___isnanl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/s_issignalingl.c (__issignalingl): +# Likewise. +# * sysdeps/ieee754/ldbl-128ibm/s_logbl.c (__logbl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/s_signbitl.c (___signbitl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/s_sincosl.c (__sincosl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/s_sinl.c (__sinl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/s_tanl.c (__tanl): Likewise. +# * sysdeps/powerpc/powerpc32/power7/fpu/s_logbl.c (__logbl): Likewise. +# +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_acoshl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_acoshl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_acoshl.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_acoshl.c 2014-05-27 19:59:00.000000000 -0500 +@@ -36,8 +36,12 @@ + { + long double t; + int64_t hx; +- u_int64_t lx; +- GET_LDOUBLE_WORDS64(hx,lx,x); ++ uint64_t lx; ++ double xhi, xlo; ++ ++ ldbl_unpack (x, &xhi, &xlo); ++ EXTRACT_WORDS64 (hx, xhi); ++ EXTRACT_WORDS64 (lx, xlo); + if(hx<0x3ff0000000000000LL) { /* x < 1 */ + return (x-x)/(x-x); + } else if(hx >=0x41b0000000000000LL) { /* x > 2**28 */ +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_acosl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_acosl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_acosl.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_acosl.c 2014-05-27 19:59:00.000000000 -0500 +@@ -151,26 +151,25 @@ + long double + __ieee754_acosl (long double x) + { +- long double z, r, w, p, q, s, t, f2; +- ieee854_long_double_shape_type u; ++ long double a, z, r, w, p, q, s, t, f2; + +- u.value = __builtin_fabsl (x); +- if (u.value == 1.0L) ++ a = __builtin_fabsl (x); ++ if (a == 1.0L) + { + if (x > 0.0L) + return 0.0; /* acos(1) = 0 */ + else + return (2.0 * pio2_hi) + (2.0 * pio2_lo); /* acos(-1)= pi */ + } +- else if (u.value > 1.0L) ++ else if (a > 1.0L) + { + return (x - x) / (x - x); /* acos(|x| > 1) is NaN */ + } +- if (u.value < 0.5L) ++ if (a < 0.5L) + { +- if (u.value < 6.938893903907228e-18L) /* |x| < 2**-57 */ ++ if (a < 6.938893903907228e-18L) /* |x| < 2**-57 */ + return pio2_hi + pio2_lo; +- if (u.value < 0.4375L) ++ if (a < 0.4375L) + { + /* Arcsine of x. */ + z = x * x; +@@ -199,7 +198,7 @@ + return z; + } + /* .4375 <= |x| < .5 */ +- t = u.value - 0.4375L; ++ t = a - 0.4375L; + p = ((((((((((P10 * t + + P9) * t + + P8) * t +@@ -230,9 +229,9 @@ + r = acosr4375 + r; + return r; + } +- else if (u.value < 0.625L) ++ else if (a < 0.625L) + { +- t = u.value - 0.5625L; ++ t = a - 0.5625L; + p = ((((((((((rS10 * t + + rS9) * t + + rS8) * t +@@ -264,7 +263,9 @@ + } + else + { /* |x| >= .625 */ +- z = (one - u.value) * 0.5; ++ double shi, slo; ++ ++ z = (one - a) * 0.5; + s = __ieee754_sqrtl (z); + /* Compute an extended precision square root from + the Newton iteration s -> 0.5 * (s + z / s). +@@ -273,12 +274,11 @@ + Express s = f1 + f2 where f1 * f1 is exactly representable. + w = (z - s^2)/2s = (z - f1^2 - 2 f1 f2 - f2^2)/2s . + s + w has extended precision. */ +- u.value = s; +- u.parts32.w2 = 0; +- u.parts32.w3 = 0; +- f2 = s - u.value; +- w = z - u.value * u.value; +- w = w - 2.0 * u.value * f2; ++ ldbl_unpack (s, &shi, &slo); ++ a = shi; ++ f2 = slo; ++ w = z - a * a; ++ w = w - 2.0 * a * f2; + w = w - f2 * f2; + w = w / (2.0 * s); + /* Arcsine of s. */ +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_asinl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_asinl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_asinl.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_asinl.c 2014-05-27 19:59:00.000000000 -0500 +@@ -131,19 +131,18 @@ + long double + __ieee754_asinl (long double x) + { +- long double t, w, p, q, c, r, s; ++ long double a, t, w, p, q, c, r, s; + int flag; +- ieee854_long_double_shape_type u; + + flag = 0; +- u.value = __builtin_fabsl (x); +- if (u.value == 1.0L) /* |x|>= 1 */ ++ a = __builtin_fabsl (x); ++ if (a == 1.0L) /* |x|>= 1 */ + return x * pio2_hi + x * pio2_lo; /* asin(1)=+-pi/2 with inexact */ +- else if (u.value >= 1.0L) ++ else if (a >= 1.0L) + return (x - x) / (x - x); /* asin(|x|>1) is NaN */ +- else if (u.value < 0.5L) ++ else if (a < 0.5L) + { +- if (u.value < 6.938893903907228e-18L) /* |x| < 2**-57 */ ++ if (a < 6.938893903907228e-18L) /* |x| < 2**-57 */ + { + if (huge + x > one) + return x; /* return x with inexact if x!=0 */ +@@ -155,9 +154,9 @@ + flag = 1; + } + } +- else if (u.value < 0.625L) ++ else if (a < 0.625L) + { +- t = u.value - 0.5625; ++ t = a - 0.5625; + p = ((((((((((rS10 * t + + rS9) * t + + rS8) * t +@@ -190,7 +189,7 @@ + else + { + /* 1 > |x| >= 0.625 */ +- w = one - u.value; ++ w = one - a; + t = w * 0.5; + } + +@@ -223,17 +222,14 @@ + } + + s = __ieee754_sqrtl (t); +- if (u.value > 0.975L) ++ if (a > 0.975L) + { + w = p / q; + t = pio2_hi - (2.0 * (s + s * w) - pio2_lo); + } + else + { +- u.value = s; +- u.parts32.w3 = 0; +- u.parts32.w2 = 0; +- w = u.value; ++ w = ldbl_high (s); + c = (t - w * w) / (s + w); + r = p / q; + p = 2.0 * s * r - (pio2_lo - 2.0 * c); +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_atanhl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_atanhl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_atanhl.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_atanhl.c 2014-05-27 19:59:00.000000000 -0500 +@@ -40,8 +40,10 @@ + { + long double t; + int64_t hx,ix; +- u_int64_t lx __attribute__ ((unused)); +- GET_LDOUBLE_WORDS64(hx,lx,x); ++ double xhi; ++ ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (hx, xhi); + ix = hx&0x7fffffffffffffffLL; + if (ix >= 0x3ff0000000000000LL) { /* |x|>=1 */ + if (ix > 0x3ff0000000000000LL) +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_coshl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_coshl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_coshl.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_coshl.c 2014-05-27 19:59:00.000000000 -0500 +@@ -41,9 +41,11 @@ + { + long double t,w; + int64_t ix; ++ double xhi; + + /* High word of |x|. */ +- GET_LDOUBLE_MSW64(ix,x); ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (ix, xhi); + ix &= 0x7fffffffffffffffLL; + + /* x is INF or NaN */ +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_log2l.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_log2l.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_log2l.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_log2l.c 2014-05-27 19:59:00.000000000 -0500 +@@ -177,11 +177,13 @@ + long double z; + long double y; + int e; +- int64_t hx, lx; ++ int64_t hx; ++ double xhi; + + /* Test for domain */ +- GET_LDOUBLE_WORDS64 (hx, lx, x); +- if (((hx & 0x7fffffffffffffffLL) | (lx & 0x7fffffffffffffffLL)) == 0) ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (hx, xhi); ++ if ((hx & 0x7fffffffffffffffLL) == 0) + return (-1.0L / (x - x)); + if (hx < 0) + return (x - x) / (x - x); +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c 2014-05-27 19:59:00.000000000 -0500 +@@ -200,10 +200,11 @@ + double tx[8]; + int exp; + int64_t n, ix, hx, ixd; +- u_int64_t lx __attribute__ ((unused)); + u_int64_t lxd; ++ double xhi; + +- GET_LDOUBLE_WORDS64 (hx, lx, x); ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (hx, xhi); + ix = hx & 0x7fffffffffffffffLL; + if (ix <= 0x3fe921fb54442d10LL) /* x in <-pi/4, pi/4> */ + { +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_sinhl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_sinhl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_sinhl.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_sinhl.c 2014-05-27 19:59:00.000000000 -0500 +@@ -38,9 +38,11 @@ + { + long double t,w,h; + int64_t ix,jx; ++ double xhi; + + /* High word of |x|. */ +- GET_LDOUBLE_MSW64(jx,x); ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (jx, xhi); + ix = jx&0x7fffffffffffffffLL; + + /* x is INF or NaN */ +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/k_cosl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/k_cosl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/k_cosl.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/k_cosl.c 2014-05-27 19:59:00.000000000 -0500 +@@ -81,8 +81,11 @@ + { + long double h, l, z, sin_l, cos_l_m1; + int64_t ix; +- u_int32_t tix, hix, index; +- GET_LDOUBLE_MSW64 (ix, x); ++ uint32_t tix, hix, index; ++ double xhi, hhi; ++ ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (ix, xhi); + tix = ((u_int64_t)ix) >> 32; + tix &= ~0x80000000; /* tix = |x|'s high 32 bits */ + if (tix < 0x3fc30000) /* |x| < 0.1484375 */ +@@ -136,7 +139,8 @@ + case 2: index = (hix - 0x3fc30000) >> 14; break; + } + */ +- SET_LDOUBLE_WORDS64(h, ((u_int64_t)hix) << 32, 0); ++ INSERT_WORDS64 (hhi, ((uint64_t)hix) << 32); ++ h = hhi; + l = y - (h - x); + z = l * l; + sin_l = l*(ONE+z*(SSIN1+z*(SSIN2+z*(SSIN3+z*(SSIN4+z*SSIN5))))); +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/k_sincosl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/k_sincosl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/k_sincosl.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/k_sincosl.c 2014-05-27 19:59:00.000000000 -0500 +@@ -100,9 +100,12 @@ + { + long double h, l, z, sin_l, cos_l_m1; + int64_t ix; +- u_int32_t tix, hix, index; +- GET_LDOUBLE_MSW64 (ix, x); +- tix = ((u_int64_t)ix) >> 32; ++ uint32_t tix, hix, index; ++ double xhi, hhi; ++ ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (ix, xhi); ++ tix = ((uint64_t)ix) >> 32; + tix &= ~0x80000000; /* tix = |x|'s high 32 bits */ + if (tix < 0x3fc30000) /* |x| < 0.1484375 */ + { +@@ -164,7 +167,8 @@ + case 2: index = (hix - 0x3fc30000) >> 14; break; + } + */ +- SET_LDOUBLE_WORDS64(h, ((u_int64_t)hix) << 32, 0); ++ INSERT_WORDS64 (hhi, ((uint64_t)hix) << 32); ++ h = hhi; + if (iy) + l = y - (h - x); + else +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/k_sinl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/k_sinl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/k_sinl.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/k_sinl.c 2014-05-27 19:59:00.000000000 -0500 +@@ -82,7 +82,10 @@ + long double h, l, z, sin_l, cos_l_m1; + int64_t ix; + u_int32_t tix, hix, index; +- GET_LDOUBLE_MSW64 (ix, x); ++ double xhi, hhi; ++ ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (ix, xhi); + tix = ((u_int64_t)ix) >> 32; + tix &= ~0x80000000; /* tix = |x|'s high 32 bits */ + if (tix < 0x3fc30000) /* |x| < 0.1484375 */ +@@ -132,7 +135,8 @@ + case 2: index = (hix - 0x3fc30000) >> 14; break; + } + */ +- SET_LDOUBLE_WORDS64(h, ((u_int64_t)hix) << 32, 0); ++ INSERT_WORDS64 (hhi, ((uint64_t)hix) << 32); ++ h = hhi; + if (iy) + l = (ix < 0 ? -y : y) - (h - x); + else +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_asinhl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_asinhl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_asinhl.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_asinhl.c 2014-05-27 19:59:00.000000000 -0500 +@@ -38,7 +38,10 @@ + { + long double t,w; + int64_t hx,ix; +- GET_LDOUBLE_MSW64(hx,x); ++ double xhi; ++ ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (hx, xhi); + ix = hx&0x7fffffffffffffffLL; + if(ix>=0x7ff0000000000000LL) return x+x; /* x is inf or NaN */ + if(ix< 0x3e20000000000000LL) { /* |x|<2**-29 */ +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_atanl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_atanl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_atanl.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_atanl.c 2014-05-27 19:59:00.000000000 -0500 +@@ -173,23 +173,20 @@ + long double + __atanl (long double x) + { +- int k, sign; ++ int32_t k, sign, lx; + long double t, u, p, q; +- ieee854_long_double_shape_type s; ++ double xhi; + +- s.value = x; +- k = s.parts32.w0; +- if (k & 0x80000000) +- sign = 1; +- else +- sign = 0; ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS (k, lx, xhi); ++ sign = k & 0x80000000; + + /* Check for IEEE special cases. */ + k &= 0x7fffffff; + if (k >= 0x7ff00000) + { + /* NaN. */ +- if ((k & 0xfffff) | s.parts32.w1 ) ++ if (((k - 0x7ff00000) | lx) != 0) + return (x + x); + + /* Infinity. */ +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_cosl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_cosl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_cosl.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_cosl.c 2014-05-27 19:59:00.000000000 -0500 +@@ -53,9 +53,11 @@ + { + long double y[2],z=0.0L; + int64_t n, ix; ++ double xhi; + + /* High word of x. */ +- GET_LDOUBLE_MSW64(ix,x); ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (ix, xhi); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffffffffffffLL; +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_fabsl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_fabsl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_fabsl.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_fabsl.c 2014-05-27 19:59:00.000000000 -0500 +@@ -29,10 +29,16 @@ + long double __fabsl(long double x) + { + u_int64_t hx, lx; +- GET_LDOUBLE_WORDS64(hx,lx,x); ++ double xhi, xlo; ++ ++ ldbl_unpack (x, &xhi, &xlo); ++ EXTRACT_WORDS64 (hx, xhi); ++ EXTRACT_WORDS64 (lx, xlo); + lx = lx ^ ( hx & 0x8000000000000000LL ); + hx = hx & 0x7fffffffffffffffLL; +- SET_LDOUBLE_WORDS64(x,hx,lx); ++ INSERT_WORDS64 (xhi, hx); ++ INSERT_WORDS64 (xlo, lx); ++ x = ldbl_pack (xhi, xlo); + return x; + } + long_double_symbol (libm, __fabsl, fabsl); +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_finitel.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_finitel.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_finitel.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_finitel.c 2014-05-27 19:59:00.000000000 -0500 +@@ -29,10 +29,14 @@ + int + ___finitel (long double x) + { +- int64_t hx; +- GET_LDOUBLE_MSW64(hx,x); +- return (int)((u_int64_t)((hx&0x7fffffffffffffffLL) +- -0x7ff0000000000000LL)>>63); ++ uint64_t hx; ++ double xhi; ++ ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (hx, xhi); ++ hx &= 0x7fffffffffffffffLL; ++ hx -= 0x7ff0000000000000LL; ++ return hx >> 63; + } + hidden_ver (___finitel, __finitel) + weak_alias (___finitel, ____finitel) +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_fpclassifyl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_fpclassifyl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_fpclassifyl.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_fpclassifyl.c 2014-05-27 19:59:00.000000000 -0500 +@@ -46,8 +46,10 @@ + { + u_int64_t hx, lx; + int retval = FP_NORMAL; ++ double xhi, xlo; + +- GET_LDOUBLE_WORDS64 (hx, lx, x); ++ ldbl_unpack (x, &xhi, &xlo); ++ EXTRACT_WORDS64 (hx, xhi); + if ((hx & 0x7ff0000000000000ULL) == 0x7ff0000000000000ULL) { + /* +/-NaN or +/-Inf */ + if (hx & 0x000fffffffffffffULL) { +@@ -65,6 +67,7 @@ + retval = FP_NORMAL; + } else { + if ((hx & 0x7ff0000000000000ULL) == 0x0360000000000000ULL) { ++ EXTRACT_WORDS64 (lx, xlo); + if ((lx & 0x7fffffffffffffff) /* lower is non-zero */ + && ((lx^hx) & 0x8000000000000000ULL)) { /* and sign differs */ + /* +/- denormal */ +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_isnanl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_isnanl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_isnanl.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_isnanl.c 2014-05-27 19:59:00.000000000 -0500 +@@ -29,12 +29,14 @@ + int + ___isnanl (long double x) + { +- int64_t hx; +- int64_t lx __attribute__ ((unused)); +- GET_LDOUBLE_WORDS64(hx,lx,x); +- hx &= 0x7fffffffffffffffLL; +- hx = 0x7ff0000000000000LL - hx; +- return (int)((u_int64_t)hx>>63); ++ uint64_t hx; ++ double xhi; ++ ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (hx, xhi); ++ hx &= 0x7fffffffffffffffLL; ++ hx = 0x7ff0000000000000LL - hx; ++ return (int) (hx >> 63); + } + hidden_ver (___isnanl, __isnanl) + #ifndef IS_IN_libm +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_logbl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_logbl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_logbl.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_logbl.c 2014-05-27 19:59:19.000000000 -0500 +@@ -27,9 +27,10 @@ + __logbl (long double x) + { + int64_t hx, rhx; +- int64_t lx __attribute__ ((unused)); ++ double xhi; + +- GET_LDOUBLE_WORDS64 (hx, lx, x); ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (hx, xhi); + hx &= 0x7fffffffffffffffLL; /* high |x| */ + if (hx == 0) + return -1.0 / fabs (x); +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_signbitl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_signbitl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_signbitl.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_signbitl.c 2014-05-27 19:59:19.000000000 -0500 +@@ -25,8 +25,10 @@ + ___signbitl (long double x) + { + int64_t e; ++ double xhi; + +- GET_LDOUBLE_MSW64 (e, x); ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (e, xhi); + return e < 0; + } + #ifdef IS_IN_libm +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_sincosl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_sincosl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_sincosl.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_sincosl.c 2014-05-27 19:59:19.000000000 -0500 +@@ -27,9 +27,11 @@ + __sincosl (long double x, long double *sinx, long double *cosx) + { + int64_t ix; ++ double xhi; + + /* High word of x. */ +- GET_LDOUBLE_MSW64 (ix, x); ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (ix, xhi); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffffffffffffLL; +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_sinl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_sinl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_sinl.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_sinl.c 2014-05-27 19:59:19.000000000 -0500 +@@ -53,9 +53,11 @@ + { + long double y[2],z=0.0L; + int64_t n, ix; ++ double xhi; + + /* High word of x. */ +- GET_LDOUBLE_MSW64(ix,x); ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (ix, xhi); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffffffffffffLL; +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_tanl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_tanl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_tanl.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_tanl.c 2014-05-27 19:59:19.000000000 -0500 +@@ -53,9 +53,11 @@ + { + long double y[2],z=0.0L; + int64_t n, ix; ++ double xhi; + + /* High word of x. */ +- GET_LDOUBLE_MSW64(ix,x); ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (ix, xhi); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffffffffffffLL; +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/fpu/s_logbl.c glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/fpu/s_logbl.c +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/fpu/s_logbl.c 2014-05-27 19:58:07.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/fpu/s_logbl.c 2014-05-27 19:59:19.000000000 -0500 +@@ -35,14 +35,14 @@ + long double + __logbl (long double x) + { +- double xh, xl; ++ double xh; + double ret; + + if (__builtin_expect (x == 0.0L, 0)) + /* Raise FE_DIVBYZERO and return -HUGE_VAL[LF]. */ + return -1.0L / __builtin_fabsl (x); + +- ldbl_unpack (x, &xh, &xl); ++ xh = ldbl_high (x); + /* ret = x & 0x7ff0000000000000; */ + asm ( + "xxland %x0,%x1,%x2\n" +@@ -58,9 +58,9 @@ + { + /* POSIX specifies that denormal number is treated as + though it were normalized. */ +- int64_t lx, hx; ++ int64_t hx; + +- GET_LDOUBLE_WORDS64 (hx, lx, x); ++ EXTRACT_WORDS64 (hx, xh); + return (long double) (-1023 - (__builtin_clzll (hx) - 12)); + } + /* Test to avoid logb_downward (0.0) == -0.0. */ diff --git a/SOURCES/glibc-ppc64le-08.patch b/SOURCES/glibc-ppc64le-08.patch new file mode 100644 index 0000000..5f79844 --- /dev/null +++ b/SOURCES/glibc-ppc64le-08.patch @@ -0,0 +1,1235 @@ +# commit 765714cafcad7e6168518c61111f07bd955a9fee +# Author: Alan Modra +# Date: Sat Aug 17 18:24:58 2013 +0930 +# +# PowerPC floating point little-endian [3 of 15] +# http://sourceware.org/ml/libc-alpha/2013-08/msg00083.html +# +# Further replacement of ieee854 macros and unions. These files also +# have some optimisations for comparison against 0.0L, infinity and nan. +# Since the ABI specifies that the high double of an IBM long double +# pair is the value rounded to double, a high double of 0.0 means the +# low double must also be 0.0. The ABI also says that infinity and +# nan are encoded in the high double, with the low double unspecified. +# This means that tests for 0.0L, +/-Infinity and +/-NaN need only check +# the high double. +# +# * sysdeps/ieee754/ldbl-128ibm/e_atan2l.c (__ieee754_atan2l): Rewrite +# all uses of ieee854 long double macros and unions. Simplify tests +# for long doubles that are fully specified by the high double. +# * sysdeps/ieee754/ldbl-128ibm/e_gammal_r.c (__ieee754_gammal_r): +# Likewise. +# * sysdeps/ieee754/ldbl-128ibm/e_ilogbl.c (__ieee754_ilogbl): Likewise. +# Remove dead code too. +# * sysdeps/ieee754/ldbl-128ibm/e_jnl.c (__ieee754_jnl): Likewise. +# (__ieee754_ynl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/e_log10l.c (__ieee754_log10l): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/e_logl.c (__ieee754_logl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/e_powl.c (__ieee754_powl): Likewise. +# Remove dead code too. +# * sysdeps/ieee754/ldbl-128ibm/k_tanl.c (__kernel_tanl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/s_expm1l.c (__expm1l): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/s_frexpl.c (__frexpl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/s_isinf_nsl.c (__isinf_nsl): Likewise. +# Simplify. +# * sysdeps/ieee754/ldbl-128ibm/s_isinfl.c (___isinfl): Likewise. +# Simplify. +# * sysdeps/ieee754/ldbl-128ibm/s_log1pl.c (__log1pl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/s_modfl.c (__modfl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/s_nextafterl.c (__nextafterl): Likewise. +# Comment on variable precision. +# * sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c (__nexttoward): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c (__nexttowardf): +# Likewise. +# * sysdeps/ieee754/ldbl-128ibm/s_remquol.c (__remquol): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/s_scalblnl.c (__scalblnl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/s_scalbnl.c (__scalbnl): Likewise. +# * sysdeps/ieee754/ldbl-128ibm/s_tanhl.c (__tanhl): Likewise. +# * sysdeps/powerpc/fpu/libm-test-ulps: Adjust tan_towardzero ulps. +# +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_atan2l.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_atan2l.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_atan2l.c 2014-05-27 23:05:51.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_atan2l.c 2014-05-27 23:05:55.000000000 -0500 +@@ -56,11 +56,15 @@ + { + long double z; + int64_t k,m,hx,hy,ix,iy; +- u_int64_t lx,ly; ++ uint64_t lx; ++ double xhi, xlo, yhi; + +- GET_LDOUBLE_WORDS64(hx,lx,x); ++ ldbl_unpack (x, &xhi, &xlo); ++ EXTRACT_WORDS64 (hx, xhi); ++ EXTRACT_WORDS64 (lx, xlo); + ix = hx&0x7fffffffffffffffLL; +- GET_LDOUBLE_WORDS64(hy,ly,y); ++ yhi = ldbl_high (y); ++ EXTRACT_WORDS64 (hy, yhi); + iy = hy&0x7fffffffffffffffLL; + if(((ix)>0x7ff0000000000000LL)|| + ((iy)>0x7ff0000000000000LL)) /* x or y is NaN */ +@@ -70,7 +74,7 @@ + m = ((hy>>63)&1)|((hx>>62)&2); /* 2*sign(x)+sign(y) */ + + /* when y = 0 */ +- if((iy|(ly&0x7fffffffffffffffLL))==0) { ++ if(iy==0) { + switch(m) { + case 0: + case 1: return y; /* atan(+-0,+anything)=+-0 */ +@@ -79,7 +83,7 @@ + } + } + /* when x = 0 */ +- if((ix|(lx&0x7fffffffffffffff))==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; ++ if(ix==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; + + /* when x is INF */ + if(ix==0x7ff0000000000000LL) { +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_gammal_r.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_gammal_r.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_gammal_r.c 2014-05-27 23:05:51.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_gammal_r.c 2014-05-27 23:05:55.000000000 -0500 +@@ -29,11 +29,12 @@ + and the exp function. But due to the required boundary + conditions we must check some values separately. */ + int64_t hx; +- u_int64_t lx; ++ double xhi; + +- GET_LDOUBLE_WORDS64 (hx, lx, x); ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (hx, xhi); + +- if (((hx | lx) & 0x7fffffffffffffffLL) == 0) ++ if ((hx & 0x7fffffffffffffffLL) == 0) + { + /* Return value for x == 0 is Inf with divide by zero exception. */ + *signgamp = 0; +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_ilogbl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_ilogbl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_ilogbl.c 2014-05-27 23:05:51.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_ilogbl.c 2014-05-27 23:05:55.000000000 -0500 +@@ -31,26 +31,24 @@ + + int __ieee754_ilogbl(long double x) + { +- int64_t hx,lx; ++ int64_t hx; + int ix; ++ double xhi; + +- GET_LDOUBLE_WORDS64(hx,lx,x); ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (hx, xhi); + hx &= 0x7fffffffffffffffLL; + if(hx <= 0x0010000000000000LL) { +- if((hx|(lx&0x7fffffffffffffffLL))==0) ++ if(hx==0) + return FP_ILOGB0; /* ilogbl(0) = FP_ILOGB0 */ + else /* subnormal x */ +- if(hx==0) { +- for (ix = -1043; lx>0; lx<<=1) ix -=1; +- } else { +- for (ix = -1022, hx<<=11; hx>0; hx<<=1) ix -=1; +- } ++ for (ix = -1022, hx<<=11; hx>0; hx<<=1) ix -=1; + return ix; + } + else if (hx<0x7ff0000000000000LL) return (hx>>52)-0x3ff; + else if (FP_ILOGBNAN != INT_MAX) { + /* ISO C99 requires ilogbl(+-Inf) == INT_MAX. */ +- if (((hx^0x7ff0000000000000LL)|lx) == 0) ++ if (hx==0x7ff0000000000000LL) + return INT_MAX; + } + return FP_ILOGBNAN; +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_jnl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_jnl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_jnl.c 2014-05-27 23:05:51.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_jnl.c 2014-05-27 23:05:55.000000000 -0500 +@@ -70,26 +70,25 @@ + long double + __ieee754_jnl (int n, long double x) + { +- u_int32_t se; ++ uint32_t se, lx; + int32_t i, ix, sgn; + long double a, b, temp, di; + long double z, w; +- ieee854_long_double_shape_type u; ++ double xhi; + + + /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x) + * Thus, J(-n,x) = J(n,-x) + */ + +- u.value = x; +- se = u.parts32.w0; ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS (se, lx, xhi); + ix = se & 0x7fffffff; + + /* if J(n,NaN) is NaN */ + if (ix >= 0x7ff00000) + { +- if ((u.parts32.w0 & 0xfffff) | u.parts32.w1 +- | (u.parts32.w2 & 0x7fffffff) | u.parts32.w3) ++ if (((ix - 0x7ff00000) | lx) != 0) + return x + x; + } + +@@ -298,21 +297,20 @@ + long double + __ieee754_ynl (int n, long double x) + { +- u_int32_t se; ++ uint32_t se, lx; + int32_t i, ix; + int32_t sign; + long double a, b, temp; +- ieee854_long_double_shape_type u; ++ double xhi; + +- u.value = x; +- se = u.parts32.w0; ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS (se, lx, xhi); + ix = se & 0x7fffffff; + + /* if Y(n,NaN) is NaN */ + if (ix >= 0x7ff00000) + { +- if ((u.parts32.w0 & 0xfffff) | u.parts32.w1 +- | (u.parts32.w2 & 0x7fffffff) | u.parts32.w3) ++ if (((ix - 0x7ff00000) | lx) != 0) + return x + x; + } + if (x <= 0.0L) +@@ -377,14 +375,16 @@ + a = __ieee754_y0l (x); + b = __ieee754_y1l (x); + /* quit if b is -inf */ +- u.value = b; +- se = u.parts32.w0 & 0xfff00000; ++ xhi = ldbl_high (b); ++ GET_HIGH_WORD (se, xhi); ++ se &= 0xfff00000; + for (i = 1; i < n && se != 0xfff00000; i++) + { + temp = b; + b = ((long double) (i + i) / x) * b - a; +- u.value = b; +- se = u.parts32.w0 & 0xfff00000; ++ xhi = ldbl_high (b); ++ GET_HIGH_WORD (se, xhi); ++ se &= 0xfff00000; + a = temp; + } + } +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_log10l.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_log10l.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_log10l.c 2014-05-27 23:05:51.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_log10l.c 2014-05-27 23:05:55.000000000 -0500 +@@ -182,11 +182,13 @@ + long double z; + long double y; + int e; +- int64_t hx, lx; ++ int64_t hx; ++ double xhi; + + /* Test for domain */ +- GET_LDOUBLE_WORDS64 (hx, lx, x); +- if (((hx & 0x7fffffffffffffffLL) | (lx & 0x7fffffffffffffffLL)) == 0) ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (hx, xhi); ++ if ((hx & 0x7fffffffffffffffLL) == 0) + return (-1.0L / (x - x)); + if (hx < 0) + return (x - x) / (x - x); +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_logl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_logl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_logl.c 2014-05-27 23:05:51.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_logl.c 2014-05-27 23:05:55.000000000 -0500 +@@ -185,18 +185,20 @@ + long double + __ieee754_logl(long double x) + { +- long double z, y, w; +- ieee854_long_double_shape_type u, t; ++ long double z, y, w, t; + unsigned int m; + int k, e; ++ double xhi; ++ uint32_t hx, lx; + +- u.value = x; +- m = u.parts32.w0; ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS (hx, lx, xhi); ++ m = hx; + + /* Check for IEEE special cases. */ + k = m & 0x7fffffff; + /* log(0) = -infinity. */ +- if ((k | u.parts32.w1 | (u.parts32.w2 & 0x7fffffff) | u.parts32.w3) == 0) ++ if ((k | lx) == 0) + { + return -0.5L / ZERO; + } +@@ -216,7 +218,7 @@ + { + z = x - 1.0L; + k = 64; +- t.value = 1.0L; ++ t = 1.0L; + e = 0; + } + else +@@ -233,10 +235,8 @@ + k = (m - 0xff000) >> 13; + /* t is the argument 0.5 + (k+26)/128 + of the nearest item to u in the lookup table. */ +- t.parts32.w0 = 0x3ff00000 + (k << 13); +- t.parts32.w1 = 0; +- t.parts32.w2 = 0; +- t.parts32.w3 = 0; ++ INSERT_WORDS (xhi, 0x3ff00000 + (k << 13), 0); ++ t = xhi; + w0 += 0x100000; + e -= 1; + k += 64; +@@ -244,17 +244,15 @@ + else + { + k = (m - 0xfe000) >> 14; +- t.parts32.w0 = 0x3fe00000 + (k << 14); +- t.parts32.w1 = 0; +- t.parts32.w2 = 0; +- t.parts32.w3 = 0; ++ INSERT_WORDS (xhi, 0x3fe00000 + (k << 14), 0); ++ t = xhi; + } +- u.value = __scalbnl (u.value, ((int) ((w0 - u.parts32.w0) * 2)) >> 21); ++ x = __scalbnl (x, ((int) ((w0 - hx) * 2)) >> 21); + /* log(u) = log( t u/t ) = log(t) + log(u/t) + log(t) is tabulated in the lookup table. + Express log(u/t) = log(1+z), where z = u/t - 1 = (u-t)/t. + cf. Cody & Waite. */ +- z = (u.value - t.value) / t.value; ++ z = (x - t) / t; + } + /* Series expansion of log(1+z). */ + w = z * z; +@@ -275,7 +273,7 @@ + y += e * ln2b; /* Base 2 exponent offset times ln(2). */ + y += z; + y += logtbl[k-26]; /* log(t) - (t-1) */ +- y += (t.value - 1.0L); ++ y += (t - 1.0L); + y += e * ln2a; + return y; + } +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_powl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_powl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_powl.c 2014-05-27 23:05:51.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_powl.c 2014-05-27 23:05:55.000000000 -0500 +@@ -151,37 +151,32 @@ + long double y1, t1, t2, r, s, t, u, v, w; + long double s2, s_h, s_l, t_h, t_l, ay; + int32_t i, j, k, yisint, n; +- u_int32_t ix, iy; +- int32_t hx, hy; +- ieee854_long_double_shape_type o, p, q; ++ uint32_t ix, iy; ++ int32_t hx, hy, hax; ++ double ohi, xhi, xlo, yhi, ylo; ++ uint32_t lx, ly, lj; + +- p.value = x; +- hx = p.parts32.w0; ++ ldbl_unpack (x, &xhi, &xlo); ++ EXTRACT_WORDS (hx, lx, xhi); + ix = hx & 0x7fffffff; + +- q.value = y; +- hy = q.parts32.w0; ++ ldbl_unpack (y, &yhi, &ylo); ++ EXTRACT_WORDS (hy, ly, yhi); + iy = hy & 0x7fffffff; + +- + /* y==zero: x**0 = 1 */ +- if ((iy | q.parts32.w1 | (q.parts32.w2 & 0x7fffffff) | q.parts32.w3) == 0) ++ if ((iy | ly) == 0) + return one; + + /* 1.0**y = 1; -1.0**+-Inf = 1 */ + if (x == one) + return one; +- if (x == -1.0L && iy == 0x7ff00000 +- && (q.parts32.w1 | (q.parts32.w2 & 0x7fffffff) | q.parts32.w3) == 0) ++ if (x == -1.0L && ((iy - 0x7ff00000) | ly) == 0) + return one; + + /* +-NaN return x+y */ +- if ((ix > 0x7ff00000) +- || ((ix == 0x7ff00000) +- && ((p.parts32.w1 | (p.parts32.w2 & 0x7fffffff) | p.parts32.w3) != 0)) +- || (iy > 0x7ff00000) +- || ((iy == 0x7ff00000) +- && ((q.parts32.w1 | (q.parts32.w2 & 0x7fffffff) | q.parts32.w3) != 0))) ++ if ((ix >= 0x7ff00000 && ((ix - 0x7ff00000) | lx) != 0) ++ || (iy >= 0x7ff00000 && ((iy - 0x7ff00000) | ly) != 0)) + return x + y; + + /* determine if y is an odd int when x < 0 +@@ -192,7 +187,10 @@ + yisint = 0; + if (hx < 0) + { +- if ((q.parts32.w2 & 0x7fffffff) >= 0x43400000) /* Low part >= 2^53 */ ++ uint32_t low_ye; ++ ++ GET_HIGH_WORD (low_ye, ylo); ++ if ((low_ye & 0x7fffffff) >= 0x43400000) /* Low part >= 2^53 */ + yisint = 2; /* even integer y */ + else if (iy >= 0x3ff00000) /* 1.0 */ + { +@@ -207,42 +205,43 @@ + } + } + ++ ax = fabsl (x); ++ + /* special value of y */ +- if ((q.parts32.w1 | (q.parts32.w2 & 0x7fffffff) | q.parts32.w3) == 0) ++ if (ly == 0) + { +- if (iy == 0x7ff00000 && q.parts32.w1 == 0) /* y is +-inf */ ++ if (iy == 0x7ff00000) /* y is +-inf */ + { +- if (((ix - 0x3ff00000) | p.parts32.w1 +- | (p.parts32.w2 & 0x7fffffff) | p.parts32.w3) == 0) +- return y - y; /* inf**+-1 is NaN */ +- else if (ix > 0x3ff00000 || fabsl (x) > 1.0L) ++ if (ax > one) + /* (|x|>1)**+-inf = inf,0 */ + return (hy >= 0) ? y : zero; + else + /* (|x|<1)**-,+inf = inf,0 */ + return (hy < 0) ? -y : zero; + } +- if (iy == 0x3ff00000) +- { /* y is +-1 */ +- if (hy < 0) +- return one / x; +- else +- return x; +- } +- if (hy == 0x40000000) +- return x * x; /* y is 2 */ +- if (hy == 0x3fe00000) +- { /* y is 0.5 */ +- if (hx >= 0) /* x >= +0 */ +- return __ieee754_sqrtl (x); ++ if (ylo == 0.0) ++ { ++ if (iy == 0x3ff00000) ++ { /* y is +-1 */ ++ if (hy < 0) ++ return one / x; ++ else ++ return x; ++ } ++ if (hy == 0x40000000) ++ return x * x; /* y is 2 */ ++ if (hy == 0x3fe00000) ++ { /* y is 0.5 */ ++ if (hx >= 0) /* x >= +0 */ ++ return __ieee754_sqrtl (x); ++ } + } + } + +- ax = fabsl (x); + /* special value of x */ +- if ((p.parts32.w1 | (p.parts32.w2 & 0x7fffffff) | p.parts32.w3) == 0) ++ if (lx == 0) + { +- if (ix == 0x7ff00000 || ix == 0 || ix == 0x3ff00000) ++ if (ix == 0x7ff00000 || ix == 0 || (ix == 0x3ff00000 && xlo == 0.0)) + { + z = ax; /*x is +-0,+-inf,+-1 */ + if (hy < 0) +@@ -294,8 +293,8 @@ + { + ax *= two113; + n -= 113; +- o.value = ax; +- ix = o.parts32.w0; ++ ohi = ldbl_high (ax); ++ GET_HIGH_WORD (ix, ohi); + } + n += ((ix) >> 20) - 0x3ff; + j = ix & 0x000fffff; +@@ -312,26 +311,19 @@ + ix -= 0x00100000; + } + +- o.value = ax; +- o.value = __scalbnl (o.value, ((int) ((ix - o.parts32.w0) * 2)) >> 21); +- ax = o.value; ++ ohi = ldbl_high (ax); ++ GET_HIGH_WORD (hax, ohi); ++ ax = __scalbnl (ax, ((int) ((ix - hax) * 2)) >> 21); + + /* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */ + u = ax - bp[k]; /* bp[0]=1.0, bp[1]=1.5 */ + v = one / (ax + bp[k]); + s = u * v; +- s_h = s; ++ s_h = ldbl_high (s); + +- o.value = s_h; +- o.parts32.w3 = 0; +- o.parts32.w2 = 0; +- s_h = o.value; + /* t_h=ax+bp[k] High */ + t_h = ax + bp[k]; +- o.value = t_h; +- o.parts32.w3 = 0; +- o.parts32.w2 = 0; +- t_h = o.value; ++ t_h = ldbl_high (t_h); + t_l = ax - (t_h - bp[k]); + s_l = v * ((u - s_h * t_h) - s_h * t_l); + /* compute log(ax) */ +@@ -342,30 +334,21 @@ + r += s_l * (s_h + s); + s2 = s_h * s_h; + t_h = 3.0 + s2 + r; +- o.value = t_h; +- o.parts32.w3 = 0; +- o.parts32.w2 = 0; +- t_h = o.value; ++ t_h = ldbl_high (t_h); + t_l = r - ((t_h - 3.0) - s2); + /* u+v = s*(1+...) */ + u = s_h * t_h; + v = s_l * t_h + t_l * s; + /* 2/(3log2)*(s+...) */ + p_h = u + v; +- o.value = p_h; +- o.parts32.w3 = 0; +- o.parts32.w2 = 0; +- p_h = o.value; ++ p_h = ldbl_high (p_h); + p_l = v - (p_h - u); + z_h = cp_h * p_h; /* cp_h+cp_l = 2/(3*log2) */ + z_l = cp_l * p_h + p_l * cp + dp_l[k]; + /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */ + t = (long double) n; + t1 = (((z_h + z_l) + dp_h[k]) + t); +- o.value = t1; +- o.parts32.w3 = 0; +- o.parts32.w2 = 0; +- t1 = o.value; ++ t1 = ldbl_high (t1); + t2 = z_l - (((t1 - t) - dp_h[k]) - z_h); + + /* s (sign of result -ve**odd) = -1 else = 1 */ +@@ -374,21 +357,16 @@ + s = -one; /* (-ve)**(odd int) */ + + /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ +- y1 = y; +- o.value = y1; +- o.parts32.w3 = 0; +- o.parts32.w2 = 0; +- y1 = o.value; ++ y1 = ldbl_high (y); + p_l = (y - y1) * t1 + y * t2; + p_h = y1 * t1; + z = p_l + p_h; +- o.value = z; +- j = o.parts32.w0; ++ ohi = ldbl_high (z); ++ EXTRACT_WORDS (j, lj, ohi); + if (j >= 0x40d00000) /* z >= 16384 */ + { + /* if z > 16384 */ +- if (((j - 0x40d00000) | o.parts32.w1 +- | (o.parts32.w2 & 0x7fffffff) | o.parts32.w3) != 0) ++ if (((j - 0x40d00000) | lj) != 0) + return s * huge * huge; /* overflow */ + else + { +@@ -399,8 +377,7 @@ + else if ((j & 0x7fffffff) >= 0x40d01b90) /* z <= -16495 */ + { + /* z < -16495 */ +- if (((j - 0xc0d01bc0) | o.parts32.w1 +- | (o.parts32.w2 & 0x7fffffff) | o.parts32.w3) != 0) ++ if (((j - 0xc0d01bc0) | lj) != 0) + return s * tiny * tiny; /* underflow */ + else + { +@@ -419,10 +396,7 @@ + p_h -= t; + } + t = p_l + p_h; +- o.value = t; +- o.parts32.w3 = 0; +- o.parts32.w2 = 0; +- t = o.value; ++ t = ldbl_high (t); + u = t * lg2_h; + v = (p_l - (t - p_h)) * lg2 + t * lg2_l; + z = u + v; +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/k_tanl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/k_tanl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/k_tanl.c 2014-05-27 23:05:51.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/k_tanl.c 2014-05-27 23:05:55.000000000 -0500 +@@ -85,17 +85,17 @@ + __kernel_tanl (long double x, long double y, int iy) + { + long double z, r, v, w, s; +- int32_t ix, sign; +- ieee854_long_double_shape_type u, u1; ++ int32_t ix, sign, hx, lx; ++ double xhi; + +- u.value = x; +- ix = u.parts32.w0 & 0x7fffffff; ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS (hx, lx, xhi); ++ ix = hx & 0x7fffffff; + if (ix < 0x3c600000) /* x < 2**-57 */ + { +- if ((int) x == 0) +- { /* generate inexact */ +- if ((ix | u.parts32.w1 | (u.parts32.w2 & 0x7fffffff) | u.parts32.w3 +- | (iy + 1)) == 0) ++ if ((int) x == 0) /* generate inexact */ ++ { ++ if ((ix | lx | (iy + 1)) == 0) + return one / fabs (x); + else + return (iy == 1) ? x : -one / x; +@@ -103,7 +103,7 @@ + } + if (ix >= 0x3fe59420) /* |x| >= 0.6743316650390625 */ + { +- if ((u.parts32.w0 & 0x80000000) != 0) ++ if ((hx & 0x80000000) != 0) + { + x = -x; + y = -y; +@@ -139,15 +139,13 @@ + { /* if allow error up to 2 ulp, + simply return -1.0/(x+r) here */ + /* compute -1.0/(x+r) accurately */ +- u1.value = w; +- u1.parts32.w2 = 0; +- u1.parts32.w3 = 0; +- v = r - (u1.value - x); /* u1+v = r+x */ ++ long double u1, z1; ++ ++ u1 = ldbl_high (w); ++ v = r - (u1 - x); /* u1+v = r+x */ + z = -1.0 / w; +- u.value = z; +- u.parts32.w2 = 0; +- u.parts32.w3 = 0; +- s = 1.0 + u.value * u1.value; +- return u.value + z * (s + u.value * v); ++ z1 = ldbl_high (z); ++ s = 1.0 + z1 * u1; ++ return z1 + z * (s + z1 * v); + } + } +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_expm1l.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_expm1l.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_expm1l.c 2014-05-27 23:05:51.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_expm1l.c 2014-05-27 23:05:55.000000000 -0500 +@@ -92,19 +92,19 @@ + __expm1l (long double x) + { + long double px, qx, xx; +- int32_t ix, sign; +- ieee854_long_double_shape_type u; ++ int32_t ix, lx, sign; + int k; ++ double xhi; + + /* Detect infinity and NaN. */ +- u.value = x; +- ix = u.parts32.w0; ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS (ix, lx, xhi); + sign = ix & 0x80000000; + ix &= 0x7fffffff; + if (ix >= 0x7ff00000) + { + /* Infinity. */ +- if (((ix & 0xfffff) | u.parts32.w1 | (u.parts32.w2&0x7fffffff) | u.parts32.w3) == 0) ++ if (((ix - 0x7ff00000) | lx) == 0) + { + if (sign) + return -1.0L; +@@ -116,7 +116,7 @@ + } + + /* expm1(+- 0) = +- 0. */ +- if ((ix == 0) && (u.parts32.w1 | (u.parts32.w2&0x7fffffff) | u.parts32.w3) == 0) ++ if ((ix | lx) == 0) + return x; + + /* Overflow. */ +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_frexpl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_frexpl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_frexpl.c 2014-05-27 23:05:51.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_frexpl.c 2014-05-27 23:05:55.000000000 -0500 +@@ -36,16 +36,21 @@ + + long double __frexpl(long double x, int *eptr) + { +- u_int64_t hx, lx, ix, ixl; ++ uint64_t hx, lx, ix, ixl; + int64_t explo; +- GET_LDOUBLE_WORDS64(hx,lx,x); ++ double xhi, xlo; ++ ++ ldbl_unpack (x, &xhi, &xlo); ++ EXTRACT_WORDS64 (hx, xhi); ++ EXTRACT_WORDS64 (lx, xlo); + ixl = 0x7fffffffffffffffULL&lx; + ix = 0x7fffffffffffffffULL&hx; + *eptr = 0; +- if(ix>=0x7ff0000000000000ULL||((ix|ixl)==0)) return x; /* 0,inf,nan */ ++ if(ix>=0x7ff0000000000000ULL||ix==0) return x; /* 0,inf,nan */ + if (ix<0x0010000000000000ULL) { /* subnormal */ + x *= two107; +- GET_LDOUBLE_MSW64(hx,x); ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (hx, xhi); + ix = hx&0x7fffffffffffffffULL; + *eptr = -107; + } +@@ -54,7 +59,7 @@ + if (ixl != 0ULL) { + explo = (ixl>>52) - (ix>>52) + 0x3fe; + if ((ixl&0x7ff0000000000000ULL) == 0LL) { +- /* the lower double is a denomal so we need to correct its ++ /* the lower double is a denormal so we need to correct its + mantissa and perhaps its exponent. */ + int cnt; + +@@ -73,7 +78,9 @@ + lx = 0ULL; + + hx = (hx&0x800fffffffffffffULL) | 0x3fe0000000000000ULL; +- SET_LDOUBLE_WORDS64(x,hx,lx); ++ INSERT_WORDS64 (xhi, hx); ++ INSERT_WORDS64 (xlo, lx); ++ x = ldbl_pack (xhi, xlo); + return x; + } + #ifdef IS_IN_libm +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_isinf_nsl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_isinf_nsl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_isinf_nsl.c 2014-05-27 23:05:51.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_isinf_nsl.c 2014-05-27 23:05:55.000000000 -0500 +@@ -1,6 +1,7 @@ + /* + * __isinf_nsl(x) returns != 0 if x is ±inf, else 0; + * no branching! ++ * slightly dodgy in relying on signed shift right copying sign bit + */ + + #include +@@ -9,8 +10,14 @@ + int + __isinf_nsl (long double x) + { +- int64_t hx,lx; +- GET_LDOUBLE_WORDS64(hx,lx,x); +- return !((lx & 0x7fffffffffffffffLL) +- | ((hx & 0x7fffffffffffffffLL) ^ 0x7ff0000000000000LL)); ++ double xhi; ++ int64_t hx, mask; ++ ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (hx, xhi); ++ ++ mask = (hx & 0x7fffffffffffffffLL) ^ 0x7ff0000000000000LL; ++ mask |= -mask; ++ mask >>= 63; ++ return ~mask; + } +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_isinfl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_isinfl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_isinfl.c 2014-05-27 23:05:51.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_isinfl.c 2014-05-27 23:05:55.000000000 -0500 +@@ -11,6 +11,7 @@ + /* + * isinfl(x) returns 1 if x is inf, -1 if x is -inf, else 0; + * no branching! ++ * slightly dodgy in relying on signed shift right copying sign bit + */ + + #include +@@ -20,12 +21,16 @@ + int + ___isinfl (long double x) + { +- int64_t hx,lx; +- GET_LDOUBLE_WORDS64(hx,lx,x); +- lx = (lx & 0x7fffffffffffffffLL); +- lx |= (hx & 0x7fffffffffffffffLL) ^ 0x7ff0000000000000LL; +- lx |= -lx; +- return ~(lx >> 63) & (hx >> 62); ++ double xhi; ++ int64_t hx, mask; ++ ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (hx, xhi); ++ ++ mask = (hx & 0x7fffffffffffffffLL) ^ 0x7ff0000000000000LL; ++ mask |= -mask; ++ mask >>= 63; ++ return ~mask & (hx >> 62); + } + hidden_ver (___isinfl, __isinfl) + #ifndef IS_IN_libm +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_log1pl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_log1pl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_log1pl.c 2014-05-27 23:05:51.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_log1pl.c 2014-05-27 23:05:55.000000000 -0500 +@@ -126,19 +126,18 @@ + __log1pl (long double xm1) + { + long double x, y, z, r, s; +- ieee854_long_double_shape_type u; +- int32_t hx; ++ double xhi; ++ int32_t hx, lx; + int e; + + /* Test for NaN or infinity input. */ +- u.value = xm1; +- hx = u.parts32.w0; ++ xhi = ldbl_high (xm1); ++ EXTRACT_WORDS (hx, lx, xhi); + if (hx >= 0x7ff00000) + return xm1; + + /* log1p(+- 0) = +- 0. */ +- if (((hx & 0x7fffffff) == 0) +- && (u.parts32.w1 | (u.parts32.w2 & 0x7fffffff) | u.parts32.w3) == 0) ++ if (((hx & 0x7fffffff) | lx) == 0) + return xm1; + + x = xm1 + 1.0L; +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_modfl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_modfl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_modfl.c 2014-05-27 23:05:51.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_modfl.c 2014-05-27 23:05:55.000000000 -0500 +@@ -37,43 +37,54 @@ + { + int64_t i0,i1,j0; + u_int64_t i; +- GET_LDOUBLE_WORDS64(i0,i1,x); ++ double xhi, xlo; ++ ++ ldbl_unpack (x, &xhi, &xlo); ++ EXTRACT_WORDS64 (i0, xhi); ++ EXTRACT_WORDS64 (i1, xlo); + i1 &= 0x000fffffffffffffLL; + j0 = ((i0>>52)&0x7ff)-0x3ff; /* exponent of x */ + if(j0<52) { /* integer part in high x */ + if(j0<0) { /* |x|<1 */ + /* *iptr = +-0 */ +- SET_LDOUBLE_WORDS64(*iptr,i0&0x8000000000000000ULL,0); ++ INSERT_WORDS64 (xhi, i0&0x8000000000000000ULL); ++ *iptr = xhi; + return x; + } else { + i = (0x000fffffffffffffLL)>>j0; + if(((i0&i)|(i1&0x7fffffffffffffffLL))==0) { /* x is integral */ + *iptr = x; + /* return +-0 */ +- SET_LDOUBLE_WORDS64(x,i0&0x8000000000000000ULL,0); ++ INSERT_WORDS64 (xhi, i0&0x8000000000000000ULL); ++ x = xhi; + return x; + } else { +- SET_LDOUBLE_WORDS64(*iptr,i0&(~i),0); ++ INSERT_WORDS64 (xhi, i0&(~i)); ++ *iptr = xhi; + return x - *iptr; + } + } + } else if (j0>103) { /* no fraction part */ + *iptr = x*one; + /* We must handle NaNs separately. */ +- if (j0 == 0x400 && ((i0 & 0x000fffffffffffffLL) | i1)) ++ if ((i0 & 0x7fffffffffffffffLL) > 0x7ff0000000000000LL) + return x*one; + /* return +-0 */ +- SET_LDOUBLE_WORDS64(x,i0&0x8000000000000000ULL,0); ++ INSERT_WORDS64 (xhi, i0&0x8000000000000000ULL); ++ x = xhi; + return x; + } else { /* fraction part in low x */ + i = -1ULL>>(j0-52); + if((i1&i)==0) { /* x is integral */ + *iptr = x; + /* return +-0 */ +- SET_LDOUBLE_WORDS64(x,i0&0x8000000000000000ULL,0); ++ INSERT_WORDS64 (xhi, i0&0x8000000000000000ULL); ++ x = xhi; + return x; + } else { +- SET_LDOUBLE_WORDS64(*iptr,i0,i1&(~i)); ++ INSERT_WORDS64 (xhi, i0); ++ INSERT_WORDS64 (xlo, i1&(~i)); ++ *iptr = ldbl_pack (xhi, xlo); + return x - *iptr; + } + } +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_nextafterl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_nextafterl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_nextafterl.c 2014-05-27 23:05:51.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_nextafterl.c 2014-05-27 23:05:55.000000000 -0500 +@@ -30,27 +30,28 @@ + + long double __nextafterl(long double x, long double y) + { +- int64_t hx,hy,ihx,ihy,ilx; +- u_int64_t lx; +- u_int64_t ly __attribute__ ((unused)); ++ int64_t hx,hy,ihx,ihy; ++ uint64_t lx; ++ double xhi, xlo, yhi; + +- GET_LDOUBLE_WORDS64(hx,lx,x); +- GET_LDOUBLE_WORDS64(hy,ly,y); ++ ldbl_unpack (x, &xhi, &xlo); ++ EXTRACT_WORDS64 (hx, xhi); ++ EXTRACT_WORDS64 (lx, xlo); ++ yhi = ldbl_high (y); ++ EXTRACT_WORDS64 (hy, yhi); + ihx = hx&0x7fffffffffffffffLL; /* |hx| */ +- ilx = lx&0x7fffffffffffffffLL; /* |lx| */ + ihy = hy&0x7fffffffffffffffLL; /* |hy| */ + +- if((((ihx&0x7ff0000000000000LL)==0x7ff0000000000000LL)&& +- ((ihx&0x000fffffffffffffLL)!=0)) || /* x is nan */ +- (((ihy&0x7ff0000000000000LL)==0x7ff0000000000000LL)&& +- ((ihy&0x000fffffffffffffLL)!=0))) /* y is nan */ ++ if((ihx>0x7ff0000000000000LL) || /* x is nan */ ++ (ihy>0x7ff0000000000000LL)) /* y is nan */ + return x+y; /* signal the nan */ + if(x==y) + return y; /* x=y, return y */ +- if(ihx == 0 && ilx == 0) { /* x == 0 */ +- long double u; ++ if(ihx == 0) { /* x == 0 */ ++ long double u; /* return +-minsubnormal */ + hy = (hy & 0x8000000000000000ULL) | 1; +- SET_LDOUBLE_WORDS64(x,hy,0ULL);/* return +-minsubnormal */ ++ INSERT_WORDS64 (yhi, hy); ++ x = yhi; + u = math_opt_barrier (x); + u = u * u; + math_force_eval (u); /* raise underflow flag */ +@@ -59,10 +60,16 @@ + + long double u; + if(x > y) { /* x > y, x -= ulp */ ++ /* This isn't the largest magnitude correctly rounded ++ long double as you can see from the lowest mantissa ++ bit being zero. It is however the largest magnitude ++ long double with a 106 bit mantissa, and nextafterl ++ is insane with variable precision. So to make ++ nextafterl sane we assume 106 bit precision. */ + if((hx==0xffefffffffffffffLL)&&(lx==0xfc8ffffffffffffeLL)) + return x+x; /* overflow, return -inf */ + if (hx >= 0x7ff0000000000000LL) { +- SET_LDOUBLE_WORDS64(u,0x7fefffffffffffffLL,0x7c8ffffffffffffeLL); ++ u = 0x1.fffffffffffff7ffffffffffff8p+1023L; + return u; + } + if(ihx <= 0x0360000000000000LL) { /* x <= LDBL_MIN */ +@@ -77,16 +84,19 @@ + return x; + } + if (ihx < 0x06a0000000000000LL) { /* ulp will denormal */ +- SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL),0ULL); ++ INSERT_WORDS64 (yhi, hx & (0x7ffLL<<52)); ++ u = yhi; + u *= 0x1.0000000000000p-105L; +- } else +- SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL)-0x0690000000000000LL,0ULL); ++ } else { ++ INSERT_WORDS64 (yhi, (hx & (0x7ffLL<<52))-(0x069LL<<52)); ++ u = yhi; ++ } + return x - u; + } else { /* x < y, x += ulp */ + if((hx==0x7fefffffffffffffLL)&&(lx==0x7c8ffffffffffffeLL)) + return x+x; /* overflow, return +inf */ +- if ((u_int64_t) hx >= 0xfff0000000000000ULL) { +- SET_LDOUBLE_WORDS64(u,0xffefffffffffffffLL,0xfc8ffffffffffffeLL); ++ if ((uint64_t) hx >= 0xfff0000000000000ULL) { ++ u = -0x1.fffffffffffff7ffffffffffff8p+1023L; + return u; + } + if(ihx <= 0x0360000000000000LL) { /* x <= LDBL_MIN */ +@@ -103,10 +113,13 @@ + return x; + } + if (ihx < 0x06a0000000000000LL) { /* ulp will denormal */ +- SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL),0ULL); ++ INSERT_WORDS64 (yhi, hx & (0x7ffLL<<52)); ++ u = yhi; + u *= 0x1.0000000000000p-105L; +- } else +- SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL)-0x0690000000000000LL,0ULL); ++ } else { ++ INSERT_WORDS64 (yhi, (hx & (0x7ffLL<<52))-(0x069LL<<52)); ++ u = yhi; ++ } + return x + u; + } + } +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c 2014-05-27 23:05:51.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c 2014-05-27 23:10:26.000000000 -0500 +@@ -34,23 +34,23 @@ + { + int32_t hx,ix; + int64_t hy,iy; +- u_int32_t lx; +- u_int64_t ly,uly; ++ uint32_t lx; ++ double yhi; ++ + + EXTRACT_WORDS(hx,lx,x); +- GET_LDOUBLE_WORDS64(hy,ly,y); ++ yhi = ldbl_high (y); ++ EXTRACT_WORDS64(hy,yhi); + ix = hx&0x7fffffff; /* |x| */ + iy = hy&0x7fffffffffffffffLL; /* |y| */ +- uly = ly&0x7fffffffffffffffLL; /* |y| */ + + if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || /* x is nan */ +- ((iy>=0x7ff0000000000000LL)&&((iy-0x7ff0000000000000LL)|uly)!=0)) +- /* y is nan */ ++ iy>0x7ff0000000000000LL) /* y is nan */ + return x+y; + if((long double) x==y) return y; /* x=y, return y */ + if((ix|lx)==0) { /* x == 0 */ + double u; +- INSERT_WORDS(x,(u_int32_t)((hy>>32)&0x80000000),1);/* return +-minsub */ ++ INSERT_WORDS(x,(uint32_t)((hy>>32)&0x80000000),1);/* return +-minsub */ + u = math_opt_barrier (x); + u = u * u; + math_force_eval (u); /* raise underflow flag */ +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c 2014-05-27 23:05:51.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c 2014-05-27 23:05:55.000000000 -0500 +@@ -27,16 +27,16 @@ + { + int32_t hx,ix; + int64_t hy,iy; +- u_int64_t ly, uly; ++ double yhi; + + GET_FLOAT_WORD(hx,x); +- GET_LDOUBLE_WORDS64(hy,ly,y); ++ yhi = ldbl_high (y); ++ EXTRACT_WORDS64 (hy, yhi); + ix = hx&0x7fffffff; /* |x| */ + iy = hy&0x7fffffffffffffffLL; /* |y| */ +- uly = ly&0x7fffffffffffffffLL; /* |y| */ + + if((ix>0x7f800000) || /* x is nan */ +- ((iy>=0x7ff0000000000000LL)&&((iy-0x7ff0000000000000LL)|uly)!=0)) ++ (iy>0x7ff0000000000000LL)) + /* y is nan */ + return x+y; + if((long double) x==y) return y; /* x=y, return y */ +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_remquol.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_remquol.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_remquol.c 2014-05-27 23:05:51.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_remquol.c 2014-05-27 23:05:55.000000000 -0500 +@@ -33,20 +33,24 @@ + int64_t hx,hy; + u_int64_t sx,lx,ly,qs; + int cquo; ++ double xhi, xlo, yhi, ylo; + +- GET_LDOUBLE_WORDS64 (hx, lx, x); +- GET_LDOUBLE_WORDS64 (hy, ly, y); ++ ldbl_unpack (x, &xhi, &xlo); ++ EXTRACT_WORDS64 (hx, xhi); ++ EXTRACT_WORDS64 (lx, xlo); ++ ldbl_unpack (y, &yhi, &ylo); ++ EXTRACT_WORDS64 (hy, yhi); ++ EXTRACT_WORDS64 (ly, ylo); + sx = hx & 0x8000000000000000ULL; + qs = sx ^ (hy & 0x8000000000000000ULL); + hy &= 0x7fffffffffffffffLL; + hx &= 0x7fffffffffffffffLL; + + /* Purge off exception values. */ +- if ((hy | (ly & 0x7fffffffffffffff)) == 0) ++ if (hy == 0) + return (x * y) / (x * y); /* y = 0 */ + if ((hx >= 0x7ff0000000000000LL) /* x not finite */ +- || ((hy >= 0x7ff0000000000000LL) /* y is NaN */ +- && (((hy - 0x7ff0000000000000LL) | ly) != 0))) ++ || (hy > 0x7ff0000000000000LL)) /* y is NaN */ + return (x * y) / (x * y); + + if (hy <= 0x7fbfffffffffffffLL) +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_scalblnl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_scalblnl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_scalblnl.c 2014-05-27 23:05:51.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_scalblnl.c 2014-05-27 23:15:30.000000000 -0500 +@@ -41,11 +41,15 @@ + { + int64_t k,l,hx,lx; + union { int64_t i; double d; } u; +- GET_LDOUBLE_WORDS64(hx,lx,x); ++ double xhi, xlo; ++ ++ ldbl_unpack (x, &xhi, &xlo); ++ EXTRACT_WORDS64 (hx, xhi); ++ EXTRACT_WORDS64 (lx, xlo); + k = (hx>>52)&0x7ff; /* extract exponent */ + l = (lx>>52)&0x7ff; + if (k==0) { /* 0 or subnormal x */ +- if (((hx|lx)&0x7fffffffffffffffULL)==0) return x; /* +-0 */ ++ if ((hx&0x7fffffffffffffffULL)==0) return x; /* +-0 */ + u.i = hx; + u.d *= two54; + hx = u.i; +@@ -61,7 +65,9 @@ + if (k > 0) { /* normal result */ + hx = (hx&0x800fffffffffffffULL)|(k<<52); + if ((lx & 0x7fffffffffffffffULL) == 0) { /* low part +-0 */ +- SET_LDOUBLE_WORDS64(x,hx,lx); ++ INSERT_WORDS64 (xhi, hx); ++ INSERT_WORDS64 (xlo, lx); ++ x = ldbl_pack (xhi, xlo); + return x; + } + if (l == 0) { /* low part subnormal */ +@@ -81,14 +87,19 @@ + u.d *= twom54; + lx = u.i; + } +- SET_LDOUBLE_WORDS64(x,hx,lx); ++ INSERT_WORDS64 (xhi, hx); ++ INSERT_WORDS64 (xlo, lx); ++ x = ldbl_pack (xhi, xlo); + return x; + } + if (k <= -54) + return tiny*__copysignl(tiny,x); /*underflow*/ + k += 54; /* subnormal result */ + lx &= 0x8000000000000000ULL; +- SET_LDOUBLE_WORDS64(x,(hx&0x800fffffffffffffULL)|(k<<52),lx); ++ hx &= 0x800fffffffffffffULL; ++ INSERT_WORDS64 (xhi, hx|(k<<52)); ++ INSERT_WORDS64 (xlo, lx); ++ x = ldbl_pack (xhi, xlo); + return x*twolm54; + } + long_double_symbol (libm, __scalblnl, scalblnl); +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_scalbnl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_scalbnl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_scalbnl.c 2014-05-27 23:05:51.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_scalbnl.c 2014-05-27 23:16:25.000000000 -0500 +@@ -41,11 +41,15 @@ + { + int64_t k,l,hx,lx; + union { int64_t i; double d; } u; +- GET_LDOUBLE_WORDS64(hx,lx,x); ++ double xhi, xlo; ++ ++ ldbl_unpack (x, &xhi, &xlo); ++ EXTRACT_WORDS64 (hx, xhi); ++ EXTRACT_WORDS64 (lx, xlo); + k = (hx>>52)&0x7ff; /* extract exponent */ + l = (lx>>52)&0x7ff; + if (k==0) { /* 0 or subnormal x */ +- if (((hx|lx)&0x7fffffffffffffffULL)==0) return x; /* +-0 */ ++ if ((hx&0x7fffffffffffffffULL)==0) return x; /* +-0 */ + u.i = hx; + u.d *= two54; + hx = u.i; +@@ -61,7 +65,9 @@ + if (k > 0) { /* normal result */ + hx = (hx&0x800fffffffffffffULL)|(k<<52); + if ((lx & 0x7fffffffffffffffULL) == 0) { /* low part +-0 */ +- SET_LDOUBLE_WORDS64(x,hx,lx); ++ INSERT_WORDS64 (xhi, hx); ++ INSERT_WORDS64 (xlo, lx); ++ x = ldbl_pack (xhi, xlo); + return x; + } + if (l == 0) { /* low part subnormal */ +@@ -81,14 +87,19 @@ + u.d *= twom54; + lx = u.i; + } +- SET_LDOUBLE_WORDS64(x,hx,lx); ++ INSERT_WORDS64 (xhi, hx); ++ INSERT_WORDS64 (xlo, lx); ++ x = ldbl_pack (xhi, xlo); + return x; + } + if (k <= -54) + return tiny*__copysignl(tiny,x); /*underflow*/ + k += 54; /* subnormal result */ + lx &= 0x8000000000000000ULL; +- SET_LDOUBLE_WORDS64(x,(hx&0x800fffffffffffffULL)|(k<<52),lx); ++ hx &= 0x800fffffffffffffULL; ++ INSERT_WORDS64 (xhi, hx|(k<<52)); ++ INSERT_WORDS64 (xlo, lx); ++ x = ldbl_pack (xhi, xlo); + return x*twolm54; + } + #ifdef IS_IN_libm +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_tanhl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_tanhl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_tanhl.c 2014-05-27 23:05:51.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_tanhl.c 2014-05-27 23:05:55.000000000 -0500 +@@ -47,10 +47,12 @@ + long double __tanhl(long double x) + { + long double t,z; +- int64_t jx,ix,lx; ++ int64_t jx,ix; ++ double xhi; + + /* High word of |x|. */ +- GET_LDOUBLE_WORDS64(jx,lx,x); ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (jx, xhi); + ix = jx&0x7fffffffffffffffLL; + + /* x is INF or NaN */ +@@ -61,7 +63,7 @@ + + /* |x| < 22 */ + if (ix < 0x4036000000000000LL) { /* |x|<22 */ +- if ((ix | (lx&0x7fffffffffffffffLL)) == 0) ++ if (ix == 0) + return x; /* x == +-0 */ + if (ix<0x3c60000000000000LL) /* |x|<2**-57 */ + return x*(one+x); /* tanh(small) = small */ +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/fpu/libm-test-ulps glibc-2.17-c758a686/sysdeps/powerpc/fpu/libm-test-ulps +--- glibc-2.17-c758a686/sysdeps/powerpc/fpu/libm-test-ulps 2014-05-27 23:05:51.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/fpu/libm-test-ulps 2014-05-27 23:08:26.000000000 -0500 +@@ -2641,6 +2641,9 @@ + ifloat: 1 + ildouble: 2 + ldouble: 2 ++Test "tan_towardzero (2)": ++ildouble: 1 ++ldouble: 1 + Test "tan_towardzero (3) == -0.1425465430742778052956354105339134932261": + float: 1 + ifloat: 1 diff --git a/SOURCES/glibc-ppc64le-09.patch b/SOURCES/glibc-ppc64le-09.patch new file mode 100644 index 0000000..969d3a1 --- /dev/null +++ b/SOURCES/glibc-ppc64le-09.patch @@ -0,0 +1,567 @@ +# commit 650ef4bd7976e36831cba22d838b567d3b5f6e8f +# Author: Alan Modra +# Date: Sat Aug 17 18:25:51 2013 +0930 +# +# PowerPC floating point little-endian [4 of 15] +# http://sourceware.org/ml/libc-alpha/2013-08/msg00084.html +# +# Another batch of ieee854 macros and union replacement. These four +# files also have bugs fixed with this patch. The fact that the two +# doubles in an IBM long double may have different signs means that +# negation and absolute value operations can't just twiddle one sign bit +# as you can with ieee864 style extended double. fmodl, remainderl, +# erfl and erfcl all had errors of this type. erfl also returned +1 for +# large magnitude negative input where it should return -1. The hypotl +# error is innocuous since the value adjusted twice is only used as a +# flag. The e_hypotl.c tests for large "a" and small "b" are mutually +# exclusive because we've already exited when x/y > 2**120. That allows +# some further small simplifications. +# +# [BZ #15734], [BZ #15735] +# * sysdeps/ieee754/ldbl-128ibm/e_fmodl.c (__ieee754_fmodl): Rewrite +# all uses of ieee875 long double macros and unions. Simplify test +# for 0.0L. Correct |x|<|y| and |x|=|y| test. Use +# ldbl_extract_mantissa value for ix,iy exponents. Properly +# normalize after ldbl_extract_mantissa, and don't add hidden bit +# already handled. Don't treat low word of ieee854 mantissa like +# low word of IBM long double and mask off bit when testing for +# zero. +# * sysdeps/ieee754/ldbl-128ibm/e_hypotl.c (__ieee754_hypotl): Rewrite +# all uses of ieee875 long double macros and unions. Simplify tests +# for 0.0L and inf. Correct double adjustment of k. Delete dead code +# adjusting ha,hb. Simplify code setting kld. Delete two600 and +# two1022, instead use their values. Recognise that tests for large +# "a" and small "b" are mutually exclusive. Rename vars. Comment. +# * sysdeps/ieee754/ldbl-128ibm/e_remainderl.c (__ieee754_remainderl): +# Rewrite all uses of ieee875 long double macros and unions. Simplify +# test for 0.0L and nan. Correct negation. +# * sysdeps/ieee754/ldbl-128ibm/s_erfl.c (__erfl): Rewrite all uses of +# ieee875 long double macros and unions. Correct output for large +# magnitude x. Correct absolute value calculation. +# (__erfcl): Likewise. +# * math/libm-test.inc: Add tests for errors discovered in IBM long +# double versions of fmodl, remainderl, erfl and erfcl. +# +diff -urN glibc-2.17-c758a686/math/libm-test.inc glibc-2.17-c758a686/math/libm-test.inc +--- glibc-2.17-c758a686/math/libm-test.inc 2014-05-27 20:02:29.000000000 -0500 ++++ glibc-2.17-c758a686/math/libm-test.inc 2014-05-27 20:09:59.000000000 -0500 +@@ -4040,6 +4040,10 @@ + TEST_f_f (erf, 2.0L, 0.995322265018952734162069256367252929L); + TEST_f_f (erf, 4.125L, 0.999999994576599200434933994687765914L); + TEST_f_f (erf, 27.0L, 1.0L); ++#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 54 ++ /* The input is not exactly representable as a double. */ ++ TEST_f_f (erf, -0x1.fffffffffffff8p-2L, -0.5204998778130465132916303345518417673509L); ++#endif + + END (erf); + } +@@ -4071,6 +4075,10 @@ + TEST_f_f (erfc, 0x1.ffa002p+2L, 1.233585992097580296336099501489175967033e-29L); + TEST_f_f (erfc, 0x1.ffffc8p+2L, 1.122671365033056305522366683719541099329e-29L); + #ifdef TEST_LDOUBLE ++# if LDBL_MANT_DIG >= 54 ++ /* The input is not exactly representable as a double. */ ++ TEST_f_f (erfc, -0x1.fffffffffffff8p-2L, 1.52049987781304651329163033455184176735L); ++# endif + /* The result can only be represented in long double. */ + # if LDBL_MIN_10_EXP < -319 + TEST_f_f (erfc, 27.0L, 0.523704892378925568501606768284954709e-318L); +@@ -5634,6 +5642,13 @@ + #if defined TEST_LDOUBLE && LDBL_MIN_EXP <= -16381 + TEST_ff_f (fmod, 0x0.fffffffffffffffep-16382L, 0x1p-16445L, plus_zero); + #endif ++#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 56 ++ TEST_ff_f (fmod, -0x1.00000000000004p+0L, 0x1.fffffffffffff8p-1L, -0x1p-53L); ++ TEST_ff_f (fmod, 0x1.fffffffffffffap-1L, 0x1.fffffffffffff8p-1L, 0x1p-56L); ++ TEST_ff_f (fmod, -0x1.fffffffffffffap-1L, 0x1.fffffffffffff8p-1L, -0x1p-56L); ++ TEST_ff_f (fmod, 0x1.fffffffffffffap-1L, -0x1.fffffffffffff8p-1L, 0x1p-56L); ++ TEST_ff_f (fmod, -0x1.fffffffffffffap-1L, -0x1.fffffffffffff8p-1L, -0x1p-56L); ++#endif + + END (fmod); + } +@@ -8642,6 +8657,9 @@ + TEST_ff_f (remainder, -1.625, -1.0, 0.375); + TEST_ff_f (remainder, 5.0, 2.0, 1.0); + TEST_ff_f (remainder, 3.0, 2.0, -1.0); ++#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 56 ++ TEST_ff_f (remainder, -0x1.80000000000002p1L, 2.0, 0x1.fffffffffffff8p-1L); ++#endif + + END (remainder); + } +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_fmodl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_fmodl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_fmodl.c 2014-05-27 20:02:27.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_fmodl.c 2014-05-27 20:04:08.000000000 -0500 +@@ -27,76 +27,83 @@ + long double + __ieee754_fmodl (long double x, long double y) + { +- int64_t n,hx,hy,hz,ix,iy,sx, i; +- u_int64_t lx,ly,lz; +- int temp; +- +- GET_LDOUBLE_WORDS64(hx,lx,x); +- GET_LDOUBLE_WORDS64(hy,ly,y); ++ int64_t hx, hy, hz, sx, sy; ++ uint64_t lx, ly, lz; ++ int n, ix, iy; ++ double xhi, xlo, yhi, ylo; ++ ++ ldbl_unpack (x, &xhi, &xlo); ++ EXTRACT_WORDS64 (hx, xhi); ++ EXTRACT_WORDS64 (lx, xlo); ++ ldbl_unpack (y, &yhi, &ylo); ++ EXTRACT_WORDS64 (hy, yhi); ++ EXTRACT_WORDS64 (ly, ylo); + sx = hx&0x8000000000000000ULL; /* sign of x */ +- hx ^=sx; /* |x| */ +- hy &= 0x7fffffffffffffffLL; /* |y| */ ++ hx ^= sx; /* |x| */ ++ sy = hy&0x8000000000000000ULL; /* sign of y */ ++ hy ^= sy; /* |y| */ + + /* purge off exception values */ +- if(__builtin_expect((hy|(ly&0x7fffffffffffffff))==0 || ++ if(__builtin_expect(hy==0 || + (hx>=0x7ff0000000000000LL)|| /* y=0,or x not finite */ + (hy>0x7ff0000000000000LL),0)) /* or y is NaN */ + return (x*y)/(x*y); +- if(__builtin_expect(hx<=hy,0)) { +- if((hx>63]; /* |x|=|y| return x*0*/ ++ if (__builtin_expect (hx <= hy, 0)) ++ { ++ /* If |x| < |y| return x. */ ++ if (hx < hy) ++ return x; ++ /* At this point the absolute value of the high doubles of ++ x and y must be equal. */ ++ /* If the low double of y is the same sign as the high ++ double of y (ie. the low double increases |y|)... */ ++ if (((ly ^ sy) & 0x8000000000000000LL) == 0 ++ /* ... then a different sign low double to high double ++ for x or same sign but lower magnitude... */ ++ && (int64_t) (lx ^ sx) < (int64_t) (ly ^ sy)) ++ /* ... means |x| < |y|. */ ++ return x; ++ /* If the low double of x differs in sign to the high ++ double of x (ie. the low double decreases |x|)... */ ++ if (((lx ^ sx) & 0x8000000000000000LL) != 0 ++ /* ... then a different sign low double to high double ++ for y with lower magnitude (we've already caught ++ the same sign for y case above)... */ ++ && (int64_t) (lx ^ sx) > (int64_t) (ly ^ sy)) ++ /* ... means |x| < |y|. */ ++ return x; ++ /* If |x| == |y| return x*0. */ ++ if ((lx ^ sx) == (ly ^ sy)) ++ return Zero[(uint64_t) sx >> 63]; + } + +- /* determine ix = ilogb(x) */ +- if(__builtin_expect(hx<0x0010000000000000LL,0)) { /* subnormal x */ +- if(hx==0) { +- for (ix = -1043, i=lx; i>0; i<<=1) ix -=1; +- } else { +- for (ix = -1022, i=(hx<<11); i>0; i<<=1) ix -=1; +- } +- } else ix = (hx>>52)-0x3ff; +- +- /* determine iy = ilogb(y) */ +- if(__builtin_expect(hy<0x0010000000000000LL,0)) { /* subnormal y */ +- if(hy==0) { +- for (iy = -1043, i=ly; i>0; i<<=1) iy -=1; +- } else { +- for (iy = -1022, i=(hy<<11); i>0; i<<=1) iy -=1; +- } +- } else iy = (hy>>52)-0x3ff; +- + /* Make the IBM extended format 105 bit mantissa look like the ieee854 112 + bit mantissa so the following operations will give the correct + result. */ +- ldbl_extract_mantissa(&hx, &lx, &temp, x); +- ldbl_extract_mantissa(&hy, &ly, &temp, y); ++ ldbl_extract_mantissa(&hx, &lx, &ix, x); ++ ldbl_extract_mantissa(&hy, &ly, &iy, y); + +- /* set up {hx,lx}, {hy,ly} and align y to x */ +- if(__builtin_expect(ix >= -1022, 1)) +- hx = 0x0001000000000000LL|(0x0000ffffffffffffLL&hx); +- else { /* subnormal x, shift x to normal */ +- n = -1022-ix; +- if(n<=63) { +- hx = (hx<>(64-n)); +- lx <<= n; +- } else { +- hx = lx<<(n-64); +- lx = 0; +- } +- } +- if(__builtin_expect(iy >= -1022, 1)) +- hy = 0x0001000000000000LL|(0x0000ffffffffffffLL&hy); +- else { /* subnormal y, shift y to normal */ +- n = -1022-iy; +- if(n<=63) { +- hy = (hy<>(64-n)); +- ly <<= n; +- } else { +- hy = ly<<(n-64); +- ly = 0; +- } +- } ++ if (__builtin_expect (ix == -IEEE754_DOUBLE_BIAS, 0)) ++ { ++ /* subnormal x, shift x to normal. */ ++ while ((hx & (1LL << 48)) == 0) ++ { ++ hx = (hx << 1) | (lx >> 63); ++ lx = lx << 1; ++ ix -= 1; ++ } ++ } ++ ++ if (__builtin_expect (iy == -IEEE754_DOUBLE_BIAS, 0)) ++ { ++ /* subnormal y, shift y to normal. */ ++ while ((hy & (1LL << 48)) == 0) ++ { ++ hy = (hy << 1) | (ly >> 63); ++ ly = ly << 1; ++ iy -= 1; ++ } ++ } + + /* fix point fmod */ + n = ix - iy; +@@ -104,7 +111,7 @@ + hz=hx-hy;lz=lx-ly; if(lx>63); lx = lx+lx;} + else { +- if((hz|(lz&0x7fffffffffffffff))==0) /* return sign(x)*0 */ ++ if((hz|lz)==0) /* return sign(x)*0 */ + return Zero[(u_int64_t)sx>>63]; + hx = hz+hz+(lz>>63); lx = lz+lz; + } +@@ -113,7 +120,7 @@ + if(hz>=0) {hx=hz;lx=lz;} + + /* convert back to floating value and restore the sign */ +- if((hx|(lx&0x7fffffffffffffff))==0) /* return sign(x)*0 */ ++ if((hx|lx)==0) /* return sign(x)*0 */ + return Zero[(u_int64_t)sx>>63]; + while(hx<0x0001000000000000LL) { /* normalize x */ + hx = hx+hx+(lx>>63); lx = lx+lx; +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_hypotl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_hypotl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_hypotl.c 2014-05-27 20:02:27.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_hypotl.c 2014-05-27 20:04:08.000000000 -0500 +@@ -45,76 +45,84 @@ + #include + #include + +-static const long double two600 = 0x1.0p+600L; +-static const long double two1022 = 0x1.0p+1022L; +- + long double + __ieee754_hypotl(long double x, long double y) + { +- long double a,b,t1,t2,y1,y2,w,kld; ++ long double a,b,a1,a2,b1,b2,w,kld; + int64_t j,k,ha,hb; ++ double xhi, yhi, hi, lo; + +- GET_LDOUBLE_MSW64(ha,x); ++ xhi = ldbl_high (x); ++ EXTRACT_WORDS64 (ha, xhi); ++ yhi = ldbl_high (y); ++ EXTRACT_WORDS64 (hb, yhi); + ha &= 0x7fffffffffffffffLL; +- GET_LDOUBLE_MSW64(hb,y); + hb &= 0x7fffffffffffffffLL; + if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;} + a = fabsl(a); /* a <- |a| */ + b = fabsl(b); /* b <- |b| */ +- if((ha-hb)>0x780000000000000LL) {return a+b;} /* x/y > 2**120 */ ++ if((ha-hb)>0x0780000000000000LL) {return a+b;} /* x/y > 2**120 */ + k=0; + kld = 1.0L; + if(ha > 0x5f30000000000000LL) { /* a>2**500 */ + if(ha >= 0x7ff0000000000000LL) { /* Inf or NaN */ +- u_int64_t low; + w = a+b; /* for sNaN */ +- GET_LDOUBLE_LSW64(low,a); +- if(((ha&0xfffffffffffffLL)|(low&0x7fffffffffffffffLL))==0) ++ if(ha == 0x7ff0000000000000LL) + w = a; +- GET_LDOUBLE_LSW64(low,b); +- if(((hb^0x7ff0000000000000LL)|(low&0x7fffffffffffffffLL))==0) ++ if(hb == 0x7ff0000000000000LL) + w = b; + return w; + } + /* scale a and b by 2**-600 */ +- ha -= 0x2580000000000000LL; hb -= 0x2580000000000000LL; k += 600; +- a /= two600; +- b /= two600; +- k += 600; +- kld = two600; ++ a *= 0x1p-600L; ++ b *= 0x1p-600L; ++ k = 600; ++ kld = 0x1p+600L; + } +- if(hb < 0x23d0000000000000LL) { /* b < 2**-450 */ ++ else if(hb < 0x23d0000000000000LL) { /* b < 2**-450 */ + if(hb <= 0x000fffffffffffffLL) { /* subnormal b or 0 */ +- u_int64_t low; +- GET_LDOUBLE_LSW64(low,b); +- if((hb|(low&0x7fffffffffffffffLL))==0) return a; +- t1=two1022; /* t1=2^1022 */ +- b *= t1; +- a *= t1; +- k -= 1022; +- kld = kld / two1022; ++ if(hb==0) return a; ++ a *= 0x1p+1022L; ++ b *= 0x1p+1022L; ++ k = -1022; ++ kld = 0x1p-1022L; + } else { /* scale a and b by 2^600 */ +- ha += 0x2580000000000000LL; /* a *= 2^600 */ +- hb += 0x2580000000000000LL; /* b *= 2^600 */ +- k -= 600; +- a *= two600; +- b *= two600; +- kld = kld / two600; ++ a *= 0x1p+600L; ++ b *= 0x1p+600L; ++ k = -600; ++ kld = 0x1p-600L; + } + } + /* medium size a and b */ + w = a-b; + if (w>b) { +- SET_LDOUBLE_WORDS64(t1,ha,0); +- t2 = a-t1; +- w = __ieee754_sqrtl(t1*t1-(b*(-b)-t2*(a+t1))); ++ ldbl_unpack (a, &hi, &lo); ++ a1 = hi; ++ a2 = lo; ++ /* a*a + b*b ++ = (a1+a2)*a + b*b ++ = a1*a + a2*a + b*b ++ = a1*(a1+a2) + a2*a + b*b ++ = a1*a1 + a1*a2 + a2*a + b*b ++ = a1*a1 + a2*(a+a1) + b*b */ ++ w = __ieee754_sqrtl(a1*a1-(b*(-b)-a2*(a+a1))); + } else { + a = a+a; +- SET_LDOUBLE_WORDS64(y1,hb,0); +- y2 = b - y1; +- SET_LDOUBLE_WORDS64(t1,ha+0x0010000000000000LL,0); +- t2 = a - t1; +- w = __ieee754_sqrtl(t1*y1-(w*(-w)-(t1*y2+t2*b))); ++ ldbl_unpack (b, &hi, &lo); ++ b1 = hi; ++ b2 = lo; ++ ldbl_unpack (a, &hi, &lo); ++ a1 = hi; ++ a2 = lo; ++ /* a*a + b*b ++ = a*a + (a-b)*(a-b) - (a-b)*(a-b) + b*b ++ = a*a + w*w - (a*a - 2*a*b + b*b) + b*b ++ = w*w + 2*a*b ++ = w*w + (a1+a2)*b ++ = w*w + a1*b + a2*b ++ = w*w + a1*(b1+b2) + a2*b ++ = w*w + a1*b1 + a1*b2 + a2*b */ ++ w = __ieee754_sqrtl(a1*b1-(w*(-w)-(a1*b2+a2*b))); + } + if(k!=0) + return w*kld; +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_remainderl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_remainderl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_remainderl.c 2014-05-27 20:02:27.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_remainderl.c 2014-05-27 20:04:08.000000000 -0500 +@@ -33,18 +33,22 @@ + int64_t hx,hp; + u_int64_t sx,lx,lp; + long double p_half; ++ double xhi, xlo, phi, plo; + +- GET_LDOUBLE_WORDS64(hx,lx,x); +- GET_LDOUBLE_WORDS64(hp,lp,p); ++ ldbl_unpack (x, &xhi, &xlo); ++ EXTRACT_WORDS64 (hx, xhi); ++ EXTRACT_WORDS64 (lx, xlo); ++ ldbl_unpack (p, &phi, &plo); ++ EXTRACT_WORDS64 (hp, phi); ++ EXTRACT_WORDS64 (lp, plo); + sx = hx&0x8000000000000000ULL; + hp &= 0x7fffffffffffffffLL; + hx &= 0x7fffffffffffffffLL; + + /* purge off exception values */ +- if((hp|(lp&0x7fffffffffffffff))==0) return (x*p)/(x*p); /* p = 0 */ ++ if(hp==0) return (x*p)/(x*p); /* p = 0 */ + if((hx>=0x7ff0000000000000LL)|| /* x not finite */ +- ((hp>=0x7ff0000000000000LL)&& /* p is NaN */ +- (((hp-0x7ff0000000000000LL)|lp)!=0))) ++ (hp>0x7ff0000000000000LL)) /* p is NaN */ + return (x*p)/(x*p); + + +@@ -64,8 +68,8 @@ + if(x>=p_half) x -= p; + } + } +- GET_LDOUBLE_MSW64(hx,x); +- SET_LDOUBLE_MSW64(x,hx^sx); ++ if (sx) ++ x = -x; + return x; + } + strong_alias (__ieee754_remainderl, __remainderl_finite) +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_erfl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_erfl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_erfl.c 2014-05-27 20:02:27.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/s_erfl.c 2014-05-27 20:04:08.000000000 -0500 +@@ -760,16 +760,16 @@ + __erfl (long double x) + { + long double a, y, z; +- int32_t i, ix, sign; +- ieee854_long_double_shape_type u; ++ int32_t i, ix, hx; ++ double xhi; + +- u.value = x; +- sign = u.parts32.w0; +- ix = sign & 0x7fffffff; ++ xhi = ldbl_high (x); ++ GET_HIGH_WORD (hx, xhi); ++ ix = hx & 0x7fffffff; + + if (ix >= 0x7ff00000) + { /* erf(nan)=nan */ +- i = ((sign & 0xfff00000) >> 31) << 1; ++ i = ((uint32_t) hx >> 31) << 1; + return (long double) (1 - i) + one / x; /* erf(+-inf)=+-1 */ + } + +@@ -778,7 +778,7 @@ + if (ix >= 0x4039A0DE) + { + /* __erfcl (x) underflows if x > 25.6283 */ +- if (sign) ++ if ((hx & 0x80000000) == 0) + return one-tiny; + else + return tiny-one; +@@ -789,8 +789,9 @@ + return (one - y); + } + } +- u.parts32.w0 = ix; +- a = u.value; ++ a = x; ++ if ((hx & 0x80000000) != 0) ++ a = -a; + z = x * x; + if (ix < 0x3fec0000) /* a < 0.875 */ + { +@@ -814,7 +815,7 @@ + y = erf_const + neval (a, TN2, NTN2) / deval (a, TD2, NTD2); + } + +- if (sign & 0x80000000) /* x < 0 */ ++ if (hx & 0x80000000) /* x < 0 */ + y = -y; + return( y ); + } +@@ -824,18 +825,18 @@ + __erfcl (long double x) + { + long double y, z, p, r; +- int32_t i, ix, sign; +- ieee854_long_double_shape_type u; +- +- u.value = x; +- sign = u.parts32.w0; +- ix = sign & 0x7fffffff; +- u.parts32.w0 = ix; ++ int32_t i, ix; ++ uint32_t hx; ++ double xhi; ++ ++ xhi = ldbl_high (x); ++ GET_HIGH_WORD (hx, xhi); ++ ix = hx & 0x7fffffff; + + if (ix >= 0x7ff00000) + { /* erfc(nan)=nan */ + /* erfc(+-inf)=0,2 */ +- return (long double) (((u_int32_t) sign >> 31) << 1) + one / x; ++ return (long double) ((hx >> 31) << 1) + one / x; + } + + if (ix < 0x3fd00000) /* |x| <1/4 */ +@@ -846,7 +847,8 @@ + } + if (ix < 0x3ff40000) /* 1.25 */ + { +- x = u.value; ++ if ((hx & 0x80000000) != 0) ++ x = -x; + i = 8.0 * x; + switch (i) + { +@@ -891,7 +893,7 @@ + y += C20a; + break; + } +- if (sign & 0x80000000) ++ if (hx & 0x80000000) + y = 2.0L - y; + return y; + } +@@ -899,10 +901,11 @@ + if (ix < 0x405ac000) + { + /* x < -9 */ +- if ((ix >= 0x40220000) && (sign & 0x80000000)) ++ if (hx >= 0xc0220000) + return two - tiny; + +- x = fabsl (x); ++ if ((hx & 0x80000000) != 0) ++ x = -x; + z = one / (x * x); + i = 8.0 / x; + switch (i) +@@ -933,21 +936,17 @@ + p = neval (z, RNr8, NRNr8) / deval (z, RDr8, NRDr8); + break; + } +- u.value = x; +- u.parts32.w3 = 0; +- u.parts32.w2 = 0; +- u.parts32.w1 &= 0xf8000000; +- z = u.value; ++ z = (float) x; + r = __ieee754_expl (-z * z - 0.5625) * + __ieee754_expl ((z - x) * (z + x) + p); +- if ((sign & 0x80000000) == 0) ++ if ((hx & 0x80000000) == 0) + return r / x; + else + return two - r / x; + } + else + { +- if ((sign & 0x80000000) == 0) ++ if ((hx & 0x80000000) == 0) + return tiny * tiny; + else + return two - tiny; diff --git a/SOURCES/glibc-ppc64le-10.patch b/SOURCES/glibc-ppc64le-10.patch new file mode 100644 index 0000000..ae80fe6 --- /dev/null +++ b/SOURCES/glibc-ppc64le-10.patch @@ -0,0 +1,91 @@ +# commit 32c301dfc9b786453e59b61fe4a821a89e1a206b +# Author: Alan Modra +# Date: Sat Aug 17 18:26:39 2013 +0930 +# +# PowerPC floating point little-endian [5 of 15] +# http://sourceware.org/ml/libc-alpha/2013-08/msg00085.html +# +# Rid ourselves of ieee854. +# +# * sysdeps/ieee754/ldbl-128ibm/ieee754.h (union ieee854_long_double): +# Delete. +# (IEEE854_LONG_DOUBLE_BIAS): Delete. +# * sysdeps/ieee754/ldbl-128ibm/math_ldbl.h: Don't include ieee854 +# version of math_ldbl.h. +# +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/ieee754.h glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/ieee754.h +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/ieee754.h 2014-05-27 22:10:43.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/ieee754.h 2014-05-27 22:11:10.000000000 -0500 +@@ -112,61 +112,6 @@ + #define IEEE754_DOUBLE_BIAS 0x3ff /* Added to exponent. */ + + +-union ieee854_long_double +- { +- long double d; +- +- /* This is the IEEE 854 quad-precision format. */ +- struct +- { +-#if __BYTE_ORDER == __BIG_ENDIAN +- unsigned int negative:1; +- unsigned int exponent:15; +- /* Together these comprise the mantissa. */ +- unsigned int mantissa0:16; +- unsigned int mantissa1:32; +- unsigned int mantissa2:32; +- unsigned int mantissa3:32; +-#endif /* Big endian. */ +-#if __BYTE_ORDER == __LITTLE_ENDIAN +- /* Together these comprise the mantissa. */ +- unsigned int mantissa3:32; +- unsigned int mantissa2:32; +- unsigned int mantissa1:32; +- unsigned int mantissa0:16; +- unsigned int exponent:15; +- unsigned int negative:1; +-#endif /* Little endian. */ +- } ieee; +- +- /* This format makes it easier to see if a NaN is a signalling NaN. */ +- struct +- { +-#if __BYTE_ORDER == __BIG_ENDIAN +- unsigned int negative:1; +- unsigned int exponent:15; +- unsigned int quiet_nan:1; +- /* Together these comprise the mantissa. */ +- unsigned int mantissa0:15; +- unsigned int mantissa1:32; +- unsigned int mantissa2:32; +- unsigned int mantissa3:32; +-#else +- /* Together these comprise the mantissa. */ +- unsigned int mantissa3:32; +- unsigned int mantissa2:32; +- unsigned int mantissa1:32; +- unsigned int mantissa0:15; +- unsigned int quiet_nan:1; +- unsigned int exponent:15; +- unsigned int negative:1; +-#endif +- } ieee_nan; +- }; +- +-#define IEEE854_LONG_DOUBLE_BIAS 0x3fff /* Added to exponent. */ +- +- + /* IBM extended format for long double. + + Each long double is made up of two IEEE doubles. The value of the +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h 2014-05-27 22:10:43.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h 2014-05-27 22:11:10.000000000 -0500 +@@ -2,7 +2,6 @@ + #error "Never use directly; include instead." + #endif + +-#include + #include + + static inline void diff --git a/SOURCES/glibc-ppc64le-11.patch b/SOURCES/glibc-ppc64le-11.patch new file mode 100644 index 0000000..ec12797 --- /dev/null +++ b/SOURCES/glibc-ppc64le-11.patch @@ -0,0 +1,113 @@ +# commit 62a728aeff93507ce5975f245a5f1d2046fb4503 +# Author: Alan Modra +# Date: Sat Aug 17 18:27:19 2013 +0930 +# +# PowerPC floating point little-endian [6 of 15] +# http://sourceware.org/ml/libc-alpha/2013-07/msg00197.html +# +# A rewrite to make this code correct for little-endian. +# +# * sysdeps/ieee754/ldbl-128ibm/e_sqrtl.c (mynumber): Replace +# union 32-bit int array member with 64-bit int array. +# (t515, tm256): Double rather than long double. +# (__ieee754_sqrtl): Rewrite using 64-bit arithmetic. +# +diff -urN glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_sqrtl.c glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_sqrtl.c +--- glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_sqrtl.c 2014-05-27 22:20:12.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/ieee754/ldbl-128ibm/e_sqrtl.c 2014-05-27 22:21:39.000000000 -0500 +@@ -34,15 +34,13 @@ + + #include + +-typedef unsigned int int4; +-typedef union {int4 i[4]; long double x; double d[2]; } mynumber; ++typedef union {int64_t i[2]; long double x; double d[2]; } mynumber; + +-static const mynumber +- t512 = {{0x5ff00000, 0x00000000, 0x00000000, 0x00000000 }}, /* 2^512 */ +- tm256 = {{0x2ff00000, 0x00000000, 0x00000000, 0x00000000 }}; /* 2^-256 */ + static const double +-two54 = 1.80143985094819840000e+16, /* 0x4350000000000000 */ +-twom54 = 5.55111512312578270212e-17; /* 0x3C90000000000000 */ ++ t512 = 0x1p512, ++ tm256 = 0x1p-256, ++ two54 = 0x1p54, /* 0x4350000000000000 */ ++ twom54 = 0x1p-54; /* 0x3C90000000000000 */ + + /*********************************************************************/ + /* An ultimate sqrt routine. Given an IEEE double machine number x */ +@@ -54,56 +52,53 @@ + static const long double big = 134217728.0, big1 = 134217729.0; + long double t,s,i; + mynumber a,c; +- int4 k, l, m; +- int n; ++ uint64_t k, l; ++ int64_t m, n; + double d; + + a.x=x; +- k=a.i[0] & 0x7fffffff; ++ k=a.i[0] & INT64_C(0x7fffffffffffffff); + /*----------------- 2^-1022 <= | x |< 2^1024 -----------------*/ +- if (k>0x000fffff && k<0x7ff00000) { ++ if (k>INT64_C(0x000fffff00000000) && k> 21; +- m = (a.i[2] >> 20) & 0x7ff; ++ l = (k&INT64_C(0x001fffffffffffff))|INT64_C(0x3fe0000000000000); ++ if ((a.i[1] & INT64_C(0x7fffffffffffffff)) != 0) { ++ n = (int64_t) ((l - k) * 2) >> 53; ++ m = (a.i[1] >> 52) & 0x7ff; + if (m == 0) { + a.d[1] *= two54; +- m = ((a.i[2] >> 20) & 0x7ff) - 54; ++ m = ((a.i[1] >> 52) & 0x7ff) - 54; + } + m += n; +- if ((int) m > 0) +- a.i[2] = (a.i[2] & 0x800fffff) | (m << 20); +- else if ((int) m <= -54) { +- a.i[2] &= 0x80000000; +- a.i[3] = 0; ++ if (m > 0) ++ a.i[1] = (a.i[1] & INT64_C(0x800fffffffffffff)) | (m << 52); ++ else if (m <= -54) { ++ a.i[1] &= INT64_C(0x8000000000000000); + } else { + m += 54; +- a.i[2] = (a.i[2] & 0x800fffff) | (m << 20); ++ a.i[1] = (a.i[1] & INT64_C(0x800fffffffffffff)) | (m << 52); + a.d[1] *= twom54; + } + } + a.i[0] = l; + s = a.x; + d = __ieee754_sqrt (a.d[0]); +- c.i[0] = 0x20000000+((k&0x7fe00000)>>1); ++ c.i[0] = INT64_C(0x2000000000000000)+((k&INT64_C(0x7fe0000000000000))>>1); + c.i[1] = 0; +- c.i[2] = 0; +- c.i[3] = 0; + i = d; + t = 0.5L * (i + s / i); + i = 0.5L * (t + s / t); + return c.x * i; + } + else { +- if (k>=0x7ff00000) { +- if (a.i[0] == 0xfff00000 && a.i[1] == 0) ++ if (k>=INT64_C(0x7ff0000000000000)) { ++ if (a.i[0] == INT64_C(0xfff0000000000000)) + return (big1-big1)/(big-big); /* sqrt (-Inf) = NaN. */ + return x; /* sqrt (NaN) = NaN, sqrt (+Inf) = +Inf. */ + } + if (x == 0) return x; + if (x < 0) return (big1-big1)/(big-big); +- return tm256.x*__ieee754_sqrtl(x*t512.x); ++ return tm256*__ieee754_sqrtl(x*t512); + } + } + strong_alias (__ieee754_sqrtl, __sqrtl_finite) diff --git a/SOURCES/glibc-ppc64le-12.patch b/SOURCES/glibc-ppc64le-12.patch new file mode 100644 index 0000000..5e2d378 --- /dev/null +++ b/SOURCES/glibc-ppc64le-12.patch @@ -0,0 +1,75 @@ +# commit 2ca85d2bbbaa60b9c83bf1f57a2801c84e0a3625 +# Author: Anton Blanchard +# Date: Sat Aug 17 18:28:06 2013 +0930 +# +# PowerPC floating point little-endian [7 of 15] +# http://sourceware.org/ml/libc-alpha/2013-08/msg00086.html +# +# * sysdeps/powerpc/bits/mathinline.h (__signbitf): Use builtin. +# (__signbit): Likewise. Correct for little-endian. +# (__signbitl): Call __signbit. +# (lrint): Correct for little-endian. +# (lrintf): Call lrint. +# +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/fpu/bits/mathinline.h glibc-2.17-c758a686/sysdeps/powerpc/fpu/bits/mathinline.h +--- glibc-2.17-c758a686/sysdeps/powerpc/fpu/bits/mathinline.h 2014-05-27 22:28:12.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/fpu/bits/mathinline.h 2014-05-27 22:28:37.000000000 -0500 +@@ -62,21 +62,28 @@ + __MATH_INLINE int + __NTH (__signbitf (float __x)) + { ++#if __GNUC_PREREQ (4, 0) ++ return __builtin_signbitf (__x); ++#else + __extension__ union { float __f; int __i; } __u = { __f: __x }; + return __u.__i < 0; ++#endif + } + __MATH_INLINE int + __NTH (__signbit (double __x)) + { +- __extension__ union { double __d; int __i[2]; } __u = { __d: __x }; +- return __u.__i[0] < 0; ++#if __GNUC_PREREQ (4, 0) ++ return __builtin_signbit (__x); ++#else ++ __extension__ union { double __d; long long __i; } __u = { __d: __x }; ++ return __u.__i < 0; ++#endif + } + # ifdef __LONG_DOUBLE_128__ + __MATH_INLINE int + __NTH (__signbitl (long double __x)) + { +- __extension__ union { long double __d; int __i[4]; } __u = { __d: __x }; +- return __u.__i[0] < 0; ++ return __signbit ((double) __x); + } + # endif + # endif +@@ -93,22 +100,17 @@ + { + union { + double __d; +- int __ll[2]; ++ long long __ll; + } __u; + __asm__ ("fctiw %0,%1" : "=f"(__u.__d) : "f"(__x)); +- return __u.__ll[1]; ++ return __u.__ll; + } + + __MATH_INLINE long int lrintf (float __x) __THROW; + __MATH_INLINE long int + __NTH (lrintf (float __x)) + { +- union { +- double __d; +- int __ll[2]; +- } __u; +- __asm__ ("fctiw %0,%1" : "=f"(__u.__d) : "f"(__x)); +- return __u.__ll[1]; ++ return lrint ((double) __x); + } + # endif + diff --git a/SOURCES/glibc-ppc64le-13.patch b/SOURCES/glibc-ppc64le-13.patch new file mode 100644 index 0000000..52830a1 --- /dev/null +++ b/SOURCES/glibc-ppc64le-13.patch @@ -0,0 +1,283 @@ +# commit 4a28b3ca4bc52d9a3ac0d9edb53d3de510e1b77c +# Author: Anton Blanchard +# Date: Sat Aug 17 18:28:55 2013 +0930 +# +# PowerPC floating point little-endian [8 of 15] +# http://sourceware.org/ml/libc-alpha/2013-07/msg00199.html +# +# Corrects floating-point environment code for little-endian. +# +# * sysdeps/powerpc/fpu/fenv_libc.h (fenv_union_t): Replace int +# array with long long. +# * sysdeps/powerpc/fpu/e_sqrt.c (__slow_ieee754_sqrt): Adjust. +# * sysdeps/powerpc/fpu/e_sqrtf.c (__slow_ieee754_sqrtf): Adjust. +# * sysdeps/powerpc/fpu/fclrexcpt.c (__feclearexcept): Adjust. +# * sysdeps/powerpc/fpu/fedisblxcpt.c (fedisableexcept): Adjust. +# * sysdeps/powerpc/fpu/feenablxcpt.c (feenableexcept): Adjust. +# * sysdeps/powerpc/fpu/fegetexcept.c (__fegetexcept): Adjust. +# * sysdeps/powerpc/fpu/feholdexcpt.c (feholdexcept): Adjust. +# * sysdeps/powerpc/fpu/fesetenv.c (__fesetenv): Adjust. +# * sysdeps/powerpc/fpu/feupdateenv.c (__feupdateenv): Adjust. +# * sysdeps/powerpc/fpu/fgetexcptflg.c (__fegetexceptflag): Adjust. +# * sysdeps/powerpc/fpu/fraiseexcpt.c (__feraiseexcept): Adjust. +# * sysdeps/powerpc/fpu/fsetexcptflg.c (__fesetexceptflag): Adjust. +# * sysdeps/powerpc/fpu/ftestexcept.c (fetestexcept): Adjust. +# +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/fpu/e_sqrt.c glibc-2.17-c758a686/sysdeps/powerpc/fpu/e_sqrt.c +--- glibc-2.17-c758a686/sysdeps/powerpc/fpu/e_sqrt.c 2014-05-27 22:31:42.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/fpu/e_sqrt.c 2014-05-27 22:31:43.000000000 -0500 +@@ -145,7 +145,7 @@ + feraiseexcept (FE_INVALID_SQRT); + + fenv_union_t u = { .fenv = fegetenv_register () }; +- if ((u.l[1] & FE_INVALID) == 0) ++ if ((u.l & FE_INVALID) == 0) + #endif + feraiseexcept (FE_INVALID); + x = a_nan.value; +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/fpu/e_sqrtf.c glibc-2.17-c758a686/sysdeps/powerpc/fpu/e_sqrtf.c +--- glibc-2.17-c758a686/sysdeps/powerpc/fpu/e_sqrtf.c 2014-05-27 22:31:42.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/fpu/e_sqrtf.c 2014-05-27 22:31:43.000000000 -0500 +@@ -121,7 +121,7 @@ + feraiseexcept (FE_INVALID_SQRT); + + fenv_union_t u = { .fenv = fegetenv_register () }; +- if ((u.l[1] & FE_INVALID) == 0) ++ if ((u.l & FE_INVALID) == 0) + #endif + feraiseexcept (FE_INVALID); + x = a_nan.value; +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/fpu/fclrexcpt.c glibc-2.17-c758a686/sysdeps/powerpc/fpu/fclrexcpt.c +--- glibc-2.17-c758a686/sysdeps/powerpc/fpu/fclrexcpt.c 2014-05-27 22:31:42.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/fpu/fclrexcpt.c 2014-05-27 22:31:43.000000000 -0500 +@@ -28,8 +28,8 @@ + u.fenv = fegetenv_register (); + + /* Clear the relevant bits. */ +- u.l[1] = u.l[1] & ~((-(excepts >> (31 - FPSCR_VX) & 1) & FE_ALL_INVALID) +- | (excepts & FPSCR_STICKY_BITS)); ++ u.l = u.l & ~((-(excepts >> (31 - FPSCR_VX) & 1) & FE_ALL_INVALID) ++ | (excepts & FPSCR_STICKY_BITS)); + + /* Put the new state in effect. */ + fesetenv_register (u.fenv); +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/fpu/fedisblxcpt.c glibc-2.17-c758a686/sysdeps/powerpc/fpu/fedisblxcpt.c +--- glibc-2.17-c758a686/sysdeps/powerpc/fpu/fedisblxcpt.c 2014-05-27 22:31:42.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/fpu/fedisblxcpt.c 2014-05-27 22:31:43.000000000 -0500 +@@ -32,15 +32,15 @@ + + fe.fenv = fegetenv_register (); + if (excepts & FE_INEXACT) +- fe.l[1] &= ~(1 << (31 - FPSCR_XE)); ++ fe.l &= ~(1 << (31 - FPSCR_XE)); + if (excepts & FE_DIVBYZERO) +- fe.l[1] &= ~(1 << (31 - FPSCR_ZE)); ++ fe.l &= ~(1 << (31 - FPSCR_ZE)); + if (excepts & FE_UNDERFLOW) +- fe.l[1] &= ~(1 << (31 - FPSCR_UE)); ++ fe.l &= ~(1 << (31 - FPSCR_UE)); + if (excepts & FE_OVERFLOW) +- fe.l[1] &= ~(1 << (31 - FPSCR_OE)); ++ fe.l &= ~(1 << (31 - FPSCR_OE)); + if (excepts & FE_INVALID) +- fe.l[1] &= ~(1 << (31 - FPSCR_VE)); ++ fe.l &= ~(1 << (31 - FPSCR_VE)); + fesetenv_register (fe.fenv); + + new = __fegetexcept (); +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/fpu/feenablxcpt.c glibc-2.17-c758a686/sysdeps/powerpc/fpu/feenablxcpt.c +--- glibc-2.17-c758a686/sysdeps/powerpc/fpu/feenablxcpt.c 2014-05-27 22:31:42.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/fpu/feenablxcpt.c 2014-05-27 22:31:43.000000000 -0500 +@@ -32,15 +32,15 @@ + + fe.fenv = fegetenv_register (); + if (excepts & FE_INEXACT) +- fe.l[1] |= (1 << (31 - FPSCR_XE)); ++ fe.l |= (1 << (31 - FPSCR_XE)); + if (excepts & FE_DIVBYZERO) +- fe.l[1] |= (1 << (31 - FPSCR_ZE)); ++ fe.l |= (1 << (31 - FPSCR_ZE)); + if (excepts & FE_UNDERFLOW) +- fe.l[1] |= (1 << (31 - FPSCR_UE)); ++ fe.l |= (1 << (31 - FPSCR_UE)); + if (excepts & FE_OVERFLOW) +- fe.l[1] |= (1 << (31 - FPSCR_OE)); ++ fe.l |= (1 << (31 - FPSCR_OE)); + if (excepts & FE_INVALID) +- fe.l[1] |= (1 << (31 - FPSCR_VE)); ++ fe.l |= (1 << (31 - FPSCR_VE)); + fesetenv_register (fe.fenv); + + new = __fegetexcept (); +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/fpu/fegetexcept.c glibc-2.17-c758a686/sysdeps/powerpc/fpu/fegetexcept.c +--- glibc-2.17-c758a686/sysdeps/powerpc/fpu/fegetexcept.c 2014-05-27 22:31:42.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/fpu/fegetexcept.c 2014-05-27 22:31:43.000000000 -0500 +@@ -27,15 +27,15 @@ + + fe.fenv = fegetenv_register (); + +- if (fe.l[1] & (1 << (31 - FPSCR_XE))) ++ if (fe.l & (1 << (31 - FPSCR_XE))) + result |= FE_INEXACT; +- if (fe.l[1] & (1 << (31 - FPSCR_ZE))) ++ if (fe.l & (1 << (31 - FPSCR_ZE))) + result |= FE_DIVBYZERO; +- if (fe.l[1] & (1 << (31 - FPSCR_UE))) ++ if (fe.l & (1 << (31 - FPSCR_UE))) + result |= FE_UNDERFLOW; +- if (fe.l[1] & (1 << (31 - FPSCR_OE))) ++ if (fe.l & (1 << (31 - FPSCR_OE))) + result |= FE_OVERFLOW; +- if (fe.l[1] & (1 << (31 - FPSCR_VE))) ++ if (fe.l & (1 << (31 - FPSCR_VE))) + result |= FE_INVALID; + + return result; +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/fpu/feholdexcpt.c glibc-2.17-c758a686/sysdeps/powerpc/fpu/feholdexcpt.c +--- glibc-2.17-c758a686/sysdeps/powerpc/fpu/feholdexcpt.c 2014-05-27 22:31:42.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/fpu/feholdexcpt.c 2014-05-27 22:33:09.000000000 -0500 +@@ -30,13 +30,12 @@ + + /* Clear everything except for the rounding modes and non-IEEE arithmetic + flag. */ +- new.l[1] = old.l[1] & 7; +- new.l[0] = old.l[0]; ++ new.l = old.l & 0xffffffff00000007LL; + + /* If the old env had any eabled exceptions, then mask SIGFPE in the + MSR FE0/FE1 bits. This may allow the FPU to run faster because it + always takes the default action and can not generate SIGFPE. */ +- if ((old.l[1] & _FPU_MASK_ALL) != 0) ++ if ((old.l & _FPU_MASK_ALL) != 0) + (void)__fe_mask_env (); + + /* Put the new state in effect. */ +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/fpu/fenv_libc.h glibc-2.17-c758a686/sysdeps/powerpc/fpu/fenv_libc.h +--- glibc-2.17-c758a686/sysdeps/powerpc/fpu/fenv_libc.h 2014-05-27 22:31:42.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/fpu/fenv_libc.h 2014-05-27 22:31:43.000000000 -0500 +@@ -69,7 +69,7 @@ + typedef union + { + fenv_t fenv; +- unsigned int l[2]; ++ unsigned long long l; + } fenv_union_t; + + +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/fpu/fesetenv.c glibc-2.17-c758a686/sysdeps/powerpc/fpu/fesetenv.c +--- glibc-2.17-c758a686/sysdeps/powerpc/fpu/fesetenv.c 2014-05-27 22:31:42.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/fpu/fesetenv.c 2014-05-27 22:35:18.000000000 -0500 +@@ -36,14 +36,14 @@ + exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put the + hardware into "precise mode" and may cause the FPU to run slower on some + hardware. */ +- if ((old.l[1] & _FPU_MASK_ALL) == 0 && (new.l[1] & _FPU_MASK_ALL) != 0) ++ if ((old.l & _FPU_MASK_ALL) == 0 && (new.l & _FPU_MASK_ALL) != 0) + (void)__fe_nomask_env (); + + /* If the old env had any enabled exceptions and the new env has no enabled + exceptions, then mask SIGFPE in the MSR FE0/FE1 bits. This may allow the + FPU to run faster because it always takes the default action and can not + generate SIGFPE. */ +- if ((old.l[1] & _FPU_MASK_ALL) != 0 && (new.l[1] & _FPU_MASK_ALL) == 0) ++ if ((old.l & _FPU_MASK_ALL) != 0 && (new.l & _FPU_MASK_ALL) == 0) + (void)__fe_mask_env (); + + fesetenv_register (*envp); +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/fpu/feupdateenv.c glibc-2.17-c758a686/sysdeps/powerpc/fpu/feupdateenv.c +--- glibc-2.17-c758a686/sysdeps/powerpc/fpu/feupdateenv.c 2014-05-27 22:31:42.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/fpu/feupdateenv.c 2014-05-27 22:34:23.000000000 -0500 +@@ -36,20 +36,20 @@ + /* Restore rounding mode and exception enable from *envp and merge + exceptions. Leave fraction rounded/inexact and FP result/CC bits + unchanged. */ +- new.l[1] = (old.l[1] & 0x1FFFFF00) | (new.l[1] & 0x1FF80FFF); ++ new.l = (old.l & 0xffffffff1fffff00LL) | (new.l & 0x1ff80fff); + + /* If the old env has no eabled exceptions and the new env has any enabled + exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put + the hardware into "precise mode" and may cause the FPU to run slower on + some hardware. */ +- if ((old.l[1] & _FPU_MASK_ALL) == 0 && (new.l[1] & _FPU_MASK_ALL) != 0) ++ if ((old.l & _FPU_MASK_ALL) == 0 && (new.l & _FPU_MASK_ALL) != 0) + (void)__fe_nomask_env (); + + /* If the old env had any eabled exceptions and the new env has no enabled + exceptions, then mask SIGFPE in the MSR FE0/FE1 bits. This may allow the + FPU to run faster because it always takes the default action and can not + generate SIGFPE. */ +- if ((old.l[1] & _FPU_MASK_ALL) != 0 && (new.l[1] & _FPU_MASK_ALL) == 0) ++ if ((old.l & _FPU_MASK_ALL) != 0 && (new.l & _FPU_MASK_ALL) == 0) + (void)__fe_mask_env (); + + /* Atomically enable and raise (if appropriate) exceptions set in `new'. */ +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/fpu/fgetexcptflg.c glibc-2.17-c758a686/sysdeps/powerpc/fpu/fgetexcptflg.c +--- glibc-2.17-c758a686/sysdeps/powerpc/fpu/fgetexcptflg.c 2014-05-27 22:31:42.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/fpu/fgetexcptflg.c 2014-05-27 22:31:43.000000000 -0500 +@@ -28,7 +28,7 @@ + u.fenv = fegetenv_register (); + + /* Return (all of) it. */ +- *flagp = u.l[1] & excepts & FE_ALL_EXCEPT; ++ *flagp = u.l & excepts & FE_ALL_EXCEPT; + + /* Success. */ + return 0; +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/fpu/fraiseexcpt.c glibc-2.17-c758a686/sysdeps/powerpc/fpu/fraiseexcpt.c +--- glibc-2.17-c758a686/sysdeps/powerpc/fpu/fraiseexcpt.c 2014-05-27 22:31:42.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/fpu/fraiseexcpt.c 2014-05-27 22:31:43.000000000 -0500 +@@ -34,11 +34,11 @@ + u.fenv = fegetenv_register (); + + /* Add the exceptions */ +- u.l[1] = (u.l[1] +- | (excepts & FPSCR_STICKY_BITS) +- /* Turn FE_INVALID into FE_INVALID_SOFTWARE. */ +- | (excepts >> ((31 - FPSCR_VX) - (31 - FPSCR_VXSOFT)) +- & FE_INVALID_SOFTWARE)); ++ u.l = (u.l ++ | (excepts & FPSCR_STICKY_BITS) ++ /* Turn FE_INVALID into FE_INVALID_SOFTWARE. */ ++ | (excepts >> ((31 - FPSCR_VX) - (31 - FPSCR_VXSOFT)) ++ & FE_INVALID_SOFTWARE)); + + /* Store the new status word (along with the rest of the environment), + triggering any appropriate exceptions. */ +@@ -50,7 +50,7 @@ + don't have FE_INVALID_SOFTWARE implemented. Detect this + case and raise FE_INVALID_SNAN instead. */ + u.fenv = fegetenv_register (); +- if ((u.l[1] & FE_INVALID) == 0) ++ if ((u.l & FE_INVALID) == 0) + set_fpscr_bit (FPSCR_VXSNAN); + } + +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/fpu/fsetexcptflg.c glibc-2.17-c758a686/sysdeps/powerpc/fpu/fsetexcptflg.c +--- glibc-2.17-c758a686/sysdeps/powerpc/fpu/fsetexcptflg.c 2014-05-27 22:31:42.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/fpu/fsetexcptflg.c 2014-05-27 22:31:43.000000000 -0500 +@@ -32,10 +32,10 @@ + flag = *flagp & excepts; + + /* Replace the exception status */ +- u.l[1] = ((u.l[1] & ~(FPSCR_STICKY_BITS & excepts)) +- | (flag & FPSCR_STICKY_BITS) +- | (flag >> ((31 - FPSCR_VX) - (31 - FPSCR_VXSOFT)) +- & FE_INVALID_SOFTWARE)); ++ u.l = ((u.l & ~(FPSCR_STICKY_BITS & excepts)) ++ | (flag & FPSCR_STICKY_BITS) ++ | (flag >> ((31 - FPSCR_VX) - (31 - FPSCR_VXSOFT)) ++ & FE_INVALID_SOFTWARE)); + + /* Store the new status word (along with the rest of the environment). + This may cause floating-point exceptions if the restored state +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/fpu/ftestexcept.c glibc-2.17-c758a686/sysdeps/powerpc/fpu/ftestexcept.c +--- glibc-2.17-c758a686/sysdeps/powerpc/fpu/ftestexcept.c 2014-05-27 22:31:42.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/fpu/ftestexcept.c 2014-05-27 22:31:43.000000000 -0500 +@@ -28,6 +28,6 @@ + + /* The FE_INVALID bit is dealt with correctly by the hardware, so we can + just: */ +- return u.l[1] & excepts; ++ return u.l & excepts; + } + libm_hidden_def (fetestexcept) diff --git a/SOURCES/glibc-ppc64le-14.patch b/SOURCES/glibc-ppc64le-14.patch new file mode 100644 index 0000000..9025fd7 --- /dev/null +++ b/SOURCES/glibc-ppc64le-14.patch @@ -0,0 +1,120 @@ +# commit 603e84104cdc709c8e7dcbac54b9a585bf8dff78 +# Author: Alan Modra +# Date: Sat Aug 17 18:29:43 2013 +0930 +# +# PowerPC floating point little-endian [9 of 15] +# http://sourceware.org/ml/libc-alpha/2013-07/msg00200.html +# +# This works around the fact that vsx is disabled in current +# little-endian gcc. Also, float constants take 4 bytes in memory +# vs. 16 bytes for vector constants, and we don't need to write one lot +# of masks for double (register format) and another for float (mem +# format). +# +# * sysdeps/powerpc/fpu/s_float_bitwise.h (__float_and_test28): Don't +# use vector int constants. +# (__float_and_test24, __float_and8, __float_get_exp): Likewise. +# +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/fpu/s_float_bitwise.h glibc-2.17-c758a686/sysdeps/powerpc/fpu/s_float_bitwise.h +--- glibc-2.17-c758a686/sysdeps/powerpc/fpu/s_float_bitwise.h 2014-05-27 22:37:18.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/fpu/s_float_bitwise.h 2014-05-27 22:37:20.000000000 -0500 +@@ -23,18 +23,19 @@ + #include + + /* Returns (int)(num & 0x7FFFFFF0 == value) */ +-static inline +-int __float_and_test28 (float num, float value) ++static inline int ++__float_and_test28 (float num, float value) + { + float ret; + #ifdef _ARCH_PWR7 +- vector int mask = (vector int) { +- 0x7ffffffe, 0x00000000, 0x00000000, 0x0000000 +- }; ++ union { ++ int i; ++ float f; ++ } mask = { .i = 0x7ffffff0 }; + __asm__ ( +- /* the 'f' constrain is use on mask because we just need ++ /* the 'f' constraint is used on mask because we just need + * to compare floats, not full vector */ +- "xxland %x0,%x1,%x2" : "=f" (ret) : "f" (num), "f" (mask) ++ "xxland %x0,%x1,%x2" : "=f" (ret) : "f" (num), "f" (mask.f) + ); + #else + int32_t inum; +@@ -46,16 +47,17 @@ + } + + /* Returns (int)(num & 0x7FFFFF00 == value) */ +-static inline +-int __float_and_test24 (float num, float value) ++static inline int ++__float_and_test24 (float num, float value) + { + float ret; + #ifdef _ARCH_PWR7 +- vector int mask = (vector int) { +- 0x7fffffe0, 0x00000000, 0x00000000, 0x0000000 +- }; ++ union { ++ int i; ++ float f; ++ } mask = { .i = 0x7fffff00 }; + __asm__ ( +- "xxland %x0,%x1,%x2" : "=f" (ret) : "f" (num), "f" (mask) ++ "xxland %x0,%x1,%x2" : "=f" (ret) : "f" (num), "f" (mask.f) + ); + #else + int32_t inum; +@@ -67,16 +69,17 @@ + } + + /* Returns (float)(num & 0x7F800000) */ +-static inline +-float __float_and8 (float num) ++static inline float ++__float_and8 (float num) + { + float ret; + #ifdef _ARCH_PWR7 +- vector int mask = (vector int) { +- 0x7ff00000, 0x00000000, 0x00000000, 0x00000000 +- }; ++ union { ++ int i; ++ float f; ++ } mask = { .i = 0x7f800000 }; + __asm__ ( +- "xxland %x0,%x1,%x2" : "=f" (ret) : "f" (num), "f" (mask) ++ "xxland %x0,%x1,%x2" : "=f" (ret) : "f" (num), "f" (mask.f) + ); + #else + int32_t inum; +@@ -88,17 +91,18 @@ + } + + /* Returns ((int32_t)(num & 0x7F800000) >> 23) */ +-static inline +-int32_t __float_get_exp (float num) ++static inline int32_t ++__float_get_exp (float num) + { + int32_t inum; + #ifdef _ARCH_PWR7 + float ret; +- vector int mask = (vector int) { +- 0x7ff00000, 0x00000000, 0x00000000, 0x00000000 +- }; ++ union { ++ int i; ++ float f; ++ } mask = { .i = 0x7f800000 }; + __asm__ ( +- "xxland %x0,%x1,%x2" : "=f" (ret) : "f" (num), "f" (mask) ++ "xxland %x0,%x1,%x2" : "=f" (ret) : "f" (num), "f" (mask.f) + ); + GET_FLOAT_WORD(inum, ret); + #else diff --git a/SOURCES/glibc-ppc64le-15.patch b/SOURCES/glibc-ppc64le-15.patch new file mode 100644 index 0000000..29b3b54 --- /dev/null +++ b/SOURCES/glibc-ppc64le-15.patch @@ -0,0 +1,119 @@ +# commit da13146da10360436941e843834c90a9aef5fd7a +# Author: Alan Modra +# Date: Sat Aug 17 18:30:23 2013 +0930 +# +# PowerPC floating point little-endian [10 of 15] +# http://sourceware.org/ml/libc-alpha/2013-07/msg00201.html +# +# These two functions oddly test x+1>0 when a double x is >= 0.0, and +# similarly when x is negative. I don't see the point of that since the +# test should always be true. I also don't see any need to convert x+1 +# to integer rather than simply using xr+1. Note that the standard +# allows these functions to return any value when the input is outside +# the range of long long, but it's not too hard to prevent xr+1 +# overflowing so that's what I've done. +# +# (With rounding mode FE_UPWARD, x+1 can be a lot more than what you +# might naively expect, but perhaps that situation was covered by the +# x - xrf < 1.0 test.) +# +# * sysdeps/powerpc/fpu/s_llround.c (__llround): Rewrite. +# * sysdeps/powerpc/fpu/s_llroundf.c (__llroundf): Rewrite. +# +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/fpu/s_llround.c glibc-2.17-c758a686/sysdeps/powerpc/fpu/s_llround.c +--- glibc-2.17-c758a686/sysdeps/powerpc/fpu/s_llround.c 2014-05-27 22:38:55.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/fpu/s_llround.c 2014-05-27 22:38:58.000000000 -0500 +@@ -19,29 +19,28 @@ + #include + #include + +-/* I think that what this routine is supposed to do is round a value +- to the nearest integer, with values exactly on the boundary rounded +- away from zero. */ +-/* This routine relies on (long long)x, when x is out of range of a long long, +- clipping to MAX_LLONG or MIN_LLONG. */ ++/* Round to the nearest integer, with values exactly on a 0.5 boundary ++ rounded away from zero, regardless of the current rounding mode. ++ If (long long)x, when x is out of range of a long long, clips at ++ LLONG_MAX or LLONG_MIN, then this implementation also clips. */ + + long long int + __llround (double x) + { +- double xrf; +- long long int xr; +- xr = (long long int) x; +- xrf = (double) xr; ++ long long xr = (long long) x; ++ double xrf = (double) xr; ++ + if (x >= 0.0) +- if (x - xrf >= 0.5 && x - xrf < 1.0 && x+1 > 0) +- return x+1; +- else +- return x; ++ { ++ if (x - xrf >= 0.5) ++ xr += (long long) ((unsigned long long) xr + 1) > 0; ++ } + else +- if (xrf - x >= 0.5 && xrf - x < 1.0 && x-1 < 0) +- return x-1; +- else +- return x; ++ { ++ if (xrf - x >= 0.5) ++ xr -= (long long) ((unsigned long long) xr - 1) < 0; ++ } ++ return xr; + } + weak_alias (__llround, llround) + #ifdef NO_LONG_DOUBLE +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/fpu/s_llroundf.c glibc-2.17-c758a686/sysdeps/powerpc/fpu/s_llroundf.c +--- glibc-2.17-c758a686/sysdeps/powerpc/fpu/s_llroundf.c 2014-05-27 22:38:55.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/fpu/s_llroundf.c 2014-05-27 22:38:58.000000000 -0500 +@@ -18,28 +18,27 @@ + + #include + +-/* I think that what this routine is supposed to do is round a value +- to the nearest integer, with values exactly on the boundary rounded +- away from zero. */ +-/* This routine relies on (long long)x, when x is out of range of a long long, +- clipping to MAX_LLONG or MIN_LLONG. */ ++/* Round to the nearest integer, with values exactly on a 0.5 boundary ++ rounded away from zero, regardless of the current rounding mode. ++ If (long long)x, when x is out of range of a long long, clips at ++ LLONG_MAX or LLONG_MIN, then this implementation also clips. */ + + long long int + __llroundf (float x) + { +- float xrf; +- long long int xr; +- xr = (long long int) x; +- xrf = (float) xr; ++ long long xr = (long long) x; ++ float xrf = (float) xr; ++ + if (x >= 0.0) +- if (x - xrf >= 0.5 && x - xrf < 1.0 && x+1 > 0) +- return x+1; +- else +- return x; ++ { ++ if (x - xrf >= 0.5) ++ xr += (long long) ((unsigned long long) xr + 1) > 0; ++ } + else +- if (xrf - x >= 0.5 && xrf - x < 1.0 && x-1 < 0) +- return x-1; +- else +- return x; ++ { ++ if (xrf - x >= 0.5) ++ xr -= (long long) ((unsigned long long) xr - 1) < 0; ++ } ++ return xr; + } + weak_alias (__llroundf, llroundf) diff --git a/SOURCES/glibc-ppc64le-16.patch b/SOURCES/glibc-ppc64le-16.patch new file mode 100644 index 0000000..0da0865 --- /dev/null +++ b/SOURCES/glibc-ppc64le-16.patch @@ -0,0 +1,163 @@ +# commit 9c008155b7d5d1bd81d909497850a2ece28aec50 +# Author: Alan Modra +# Date: Sat Aug 17 18:31:05 2013 +0930 +# +# PowerPC floating point little-endian [11 of 15] +# http://sourceware.org/ml/libc-alpha/2013-07/msg00202.html +# +# Another little-endian fix. +# +# * sysdeps/powerpc/fpu_control.h (_FPU_GETCW): Rewrite using +# 64-bit int/double union. +# (_FPU_SETCW): Likewise. +# * sysdeps/powerpc/fpu/tst-setcontext-fpscr.c (_GET_DI_FPSCR): Likewise. +# (_SET_DI_FPSCR, _GET_SI_FPSCR, _SET_SI_FPSCR): Likewise. +# +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/fpu/fpu_control.h glibc-2.17-c758a686/sysdeps/powerpc/fpu/fpu_control.h +--- glibc-2.17-c758a686/sysdeps/powerpc/fpu/fpu_control.h 2014-05-27 22:40:18.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/fpu/fpu_control.h 2014-05-27 22:43:40.000000000 -0500 +@@ -45,22 +45,26 @@ + #define _FPU_IEEE 0x000000f0 + + /* Type of the control word. */ +-typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__))); ++typedef unsigned int fpu_control_t; + + /* Macros for accessing the hardware control word. */ +-#define _FPU_GETCW(__cw) ( { \ +- union { double d; fpu_control_t cw[2]; } \ +- tmp __attribute__ ((__aligned__(8))); \ +- __asm__ ("mffs 0; stfd%U0 0,%0" : "=m" (tmp.d) : : "fr0"); \ +- (__cw)=tmp.cw[1]; \ +- tmp.cw[1]; } ) +-#define _FPU_SETCW(__cw) { \ +- union { double d; fpu_control_t cw[2]; } \ +- tmp __attribute__ ((__aligned__(8))); \ +- tmp.cw[0] = 0xFFF80000; /* More-or-less arbitrary; this is a QNaN. */ \ +- tmp.cw[1] = __cw; \ +- __asm__ ("lfd%U0 0,%0; mtfsf 255,0" : : "m" (tmp.d) : "fr0"); \ +-} ++#define _FPU_GETCW(cw) \ ++ ({union { double __d; unsigned long long __ll; } __u; \ ++ register double __fr; \ ++ __asm__ ("mffs %0" : "=f" (__fr)); \ ++ __u.__d = __fr; \ ++ (cw) = (fpu_control_t) __u.__ll; \ ++ (fpu_control_t) __u.__ll; \ ++ }) ++ ++#define _FPU_SETCW(cw) \ ++ { union { double __d; unsigned long long __ll; } __u; \ ++ register double __fr; \ ++ __u.__ll = 0xfff80000LL << 32; /* This is a QNaN. */ \ ++ __u.__ll |= (cw) & 0xffffffffLL; \ ++ __fr = __u.__d; \ ++ __asm__ ("mtfsf 255,%0" : : "f" (__fr)); \ ++ } + + /* Default control word set at startup. */ + extern fpu_control_t __fpu_control; +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/fpu/tst-setcontext-fpscr.c glibc-2.17-c758a686/sysdeps/powerpc/fpu/tst-setcontext-fpscr.c +--- glibc-2.17-c758a686/sysdeps/powerpc/fpu/tst-setcontext-fpscr.c 2014-05-27 22:40:18.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/fpu/tst-setcontext-fpscr.c 2014-05-27 22:40:21.000000000 -0500 +@@ -83,7 +83,7 @@ + return 0; + } + +-typedef unsigned long long di_fpscr_t __attribute__ ((__mode__ (__DI__))); ++typedef unsigned int di_fpscr_t __attribute__ ((__mode__ (__DI__))); + typedef unsigned int si_fpscr_t __attribute__ ((__mode__ (__SI__))); + + #define _FPSCR_RESERVED 0xfffffff8ffffff04ULL +@@ -95,50 +95,51 @@ + #define _FPSCR_TEST1_RN 0x0000000000000002ULL + + /* Macros for accessing the hardware control word on Power6[x]. */ +-# define _GET_DI_FPSCR(__fpscr) ({ \ +- union { double d; \ +- di_fpscr_t fpscr; } \ +- tmp __attribute__ ((__aligned__(8))); \ +- __asm__ ("mffs 0; stfd%U0 0,%0" : "=m" (tmp.d) : : "fr0"); \ +- (__fpscr)=tmp.fpscr; \ +- tmp.fpscr; }) ++#define _GET_DI_FPSCR(__fpscr) \ ++ ({union { double d; di_fpscr_t fpscr; } u; \ ++ register double fr; \ ++ __asm__ ("mffs %0" : "=f" (fr)); \ ++ u.d = fr; \ ++ (__fpscr) = u.fpscr; \ ++ u.fpscr; \ ++ }) + +-/* We make sure to zero fp0 after we use it in order to prevent stale data ++/* We make sure to zero fp after we use it in order to prevent stale data + in an fp register from making a test-case pass erroneously. */ +-# define _SET_DI_FPSCR(__fpscr) { \ +- union { double d; di_fpscr_t fpscr; } \ +- tmp __attribute__ ((__aligned__(8))); \ +- tmp.fpscr = __fpscr; \ +- /* Set the entire 64-bit FPSCR. */ \ +- __asm__ ("lfd%U0 0,%0; " \ +- ".machine push; " \ +- ".machine \"power6\"; " \ +- "mtfsf 255,0,1,0; " \ +- ".machine pop" : : "m" (tmp.d) : "fr0"); \ +- tmp.d = 0; \ +- __asm__("lfd%U0 0,%0" : : "m" (tmp.d) : "fr0"); \ +-} +- +-# define _GET_SI_FPSCR(__fpscr) ({ \ +- union { double d; \ +- si_fpscr_t cw[2]; } \ +- tmp __attribute__ ((__aligned__(8))); \ +- __asm__ ("mffs 0; stfd%U0 0,%0" : "=m" (tmp.d) : : "fr0"); \ +- (__fpscr)=tmp.cw[1]; \ +- tmp.cw[0]; }) ++# define _SET_DI_FPSCR(__fpscr) \ ++ { union { double d; di_fpscr_t fpscr; } u; \ ++ register double fr; \ ++ u.fpscr = __fpscr; \ ++ fr = u.d; \ ++ /* Set the entire 64-bit FPSCR. */ \ ++ __asm__ (".machine push; " \ ++ ".machine \"power6\"; " \ ++ "mtfsf 255,%0,1,0; " \ ++ ".machine pop" : : "f" (fr)); \ ++ fr = 0.0; \ ++ } ++ ++# define _GET_SI_FPSCR(__fpscr) \ ++ ({union { double d; di_fpscr_t fpscr; } u; \ ++ register double fr; \ ++ __asm__ ("mffs %0" : "=f" (fr)); \ ++ u.d = fr; \ ++ (__fpscr) = (si_fpscr_t) u.fpscr; \ ++ (si_fpscr_t) u.fpscr; \ ++ }) + +-/* We make sure to zero fp0 after we use it in order to prevent stale data ++/* We make sure to zero fp after we use it in order to prevent stale data + in an fp register from making a test-case pass erroneously. */ +-# define _SET_SI_FPSCR(__fpscr) { \ +- union { double d; si_fpscr_t fpscr[2]; } \ +- tmp __attribute__ ((__aligned__(8))); \ +- /* More-or-less arbitrary; this is a QNaN. */ \ +- tmp.fpscr[0] = 0xFFF80000; \ +- tmp.fpscr[1] = __fpscr; \ +- __asm__ ("lfd%U0 0,%0; mtfsf 255,0" : : "m" (tmp.d) : "fr0"); \ +- tmp.d = 0; \ +- __asm__("lfd%U0 0,%0" : : "m" (tmp.d) : "fr0"); \ +-} ++# define _SET_SI_FPSCR(__fpscr) \ ++ { union { double d; di_fpscr_t fpscr; } u; \ ++ register double fr; \ ++ /* More-or-less arbitrary; this is a QNaN. */ \ ++ u.fpscr = 0xfff80000ULL << 32; \ ++ u.fpscr |= __fpscr & 0xffffffffULL; \ ++ fr = u.d; \ ++ __asm__ ("mtfsf 255,%0" : : "f" (fr)); \ ++ fr = 0.0; \ ++ } + + void prime_special_regs(int which) + { diff --git a/SOURCES/glibc-ppc64le-17.patch b/SOURCES/glibc-ppc64le-17.patch new file mode 100644 index 0000000..5ed69a9 --- /dev/null +++ b/SOURCES/glibc-ppc64le-17.patch @@ -0,0 +1,312 @@ +# commit 7b88401f3b25325b1381798a0eccb3efe7751fec +# Author: Alan Modra +# Date: Sat Aug 17 18:31:45 2013 +0930 +# +# PowerPC floating point little-endian [12 of 15] +# http://sourceware.org/ml/libc-alpha/2013-08/msg00087.html +# +# Fixes for little-endian in 32-bit assembly. +# +# * sysdeps/powerpc/sysdep.h (LOWORD, HIWORD, HISHORT): Define. +# * sysdeps/powerpc/powerpc32/fpu/s_copysign.S: Load little-endian +# words of double from correct stack offsets. +# * sysdeps/powerpc/powerpc32/fpu/s_copysignl.S: Likewise. +# * sysdeps/powerpc/powerpc32/fpu/s_lrint.S: Likewise. +# * sysdeps/powerpc/powerpc32/fpu/s_lround.S: Likewise. +# * sysdeps/powerpc/powerpc32/power4/fpu/s_llrint.S: Likewise. +# * sysdeps/powerpc/powerpc32/power4/fpu/s_llrintf.S: Likewise. +# * sysdeps/powerpc/powerpc32/power5+/fpu/s_llround.S: Likewise. +# * sysdeps/powerpc/powerpc32/power5+/fpu/s_lround.S: Likewise. +# * sysdeps/powerpc/powerpc32/power5/fpu/s_isnan.S: Likewise. +# * sysdeps/powerpc/powerpc32/power6/fpu/s_isnan.S: Likewise. +# * sysdeps/powerpc/powerpc32/power6/fpu/s_llrint.S: Likewise. +# * sysdeps/powerpc/powerpc32/power6/fpu/s_llrintf.S: Likewise. +# * sysdeps/powerpc/powerpc32/power6/fpu/s_llround.S: Likewise. +# * sysdeps/powerpc/powerpc32/power7/fpu/s_finite.S: Likewise. +# * sysdeps/powerpc/powerpc32/power7/fpu/s_isinf.S: Likewise. +# * sysdeps/powerpc/powerpc32/power7/fpu/s_isnan.S: Likewise. +# * sysdeps/powerpc/powerpc64/power7/fpu/s_finite.S: Use HISHORT. +# * sysdeps/powerpc/powerpc64/power7/fpu/s_isinf.S: Likewise. +# +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/s_copysign.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/s_copysign.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/s_copysign.S 2014-05-27 22:45:44.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/s_copysign.S 2014-05-27 22:45:46.000000000 -0500 +@@ -29,7 +29,7 @@ + stwu r1,-16(r1) + cfi_adjust_cfa_offset (16) + stfd fp2,8(r1) +- lwz r3,8(r1) ++ lwz r3,8+HIWORD(r1) + cmpwi r3,0 + addi r1,r1,16 + cfi_adjust_cfa_offset (-16) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/s_copysignl.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/s_copysignl.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/s_copysignl.S 2014-05-27 22:45:44.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/s_copysignl.S 2014-05-27 22:45:46.000000000 -0500 +@@ -30,7 +30,7 @@ + fmr fp0,fp1 + fabs fp1,fp1 + fcmpu cr7,fp0,fp1 +- lwz r3,8(r1) ++ lwz r3,8+HIWORD(r1) + cmpwi cr6,r3,0 + addi r1,r1,16 + cfi_adjust_cfa_offset (-16) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/s_lrint.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/s_lrint.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/s_lrint.S 2014-05-27 22:45:44.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/s_lrint.S 2014-05-27 22:45:46.000000000 -0500 +@@ -24,10 +24,10 @@ + stwu r1,-16(r1) + fctiw fp13,fp1 + stfd fp13,8(r1) +- nop /* Insure the following load is in a different dispatch group */ ++ nop /* Ensure the following load is in a different dispatch group */ + nop /* to avoid pipe stall on POWER4&5. */ + nop +- lwz r3,12(r1) ++ lwz r3,8+LOWORD(r1) + addi r1,r1,16 + blr + END (__lrint) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/s_lround.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/s_lround.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/s_lround.S 2014-05-27 22:45:44.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/s_lround.S 2014-05-27 22:45:46.000000000 -0500 +@@ -67,7 +67,7 @@ + nop /* Ensure the following load is in a different dispatch */ + nop /* group to avoid pipe stall on POWER4&5. */ + nop +- lwz r3,12(r1) /* Load return as integer. */ ++ lwz r3,8+LOWORD(r1) /* Load return as integer. */ + .Lout: + addi r1,r1,16 + blr +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/fpu/s_llrint.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/fpu/s_llrint.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/fpu/s_llrint.S 2014-05-27 22:45:44.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/fpu/s_llrint.S 2014-05-27 22:48:09.000000000 -0500 +@@ -29,8 +29,8 @@ + nop /* Insure the following load is in a different dispatch group */ + nop /* to avoid pipe stall on POWER4&5. */ + nop +- lwz r3,8(r1) +- lwz r4,12(r1) ++ lwz r3,8+HIWORD(r1) ++ lwz r4,8+LOWORD(r1) + addi r1,r1,16 + blr + END (__llrint) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/fpu/s_llrintf.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/fpu/s_llrintf.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/fpu/s_llrintf.S 2014-05-27 22:45:44.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/fpu/s_llrintf.S 2014-05-27 22:48:44.000000000 -0500 +@@ -28,8 +28,8 @@ + nop /* Insure the following load is in a different dispatch group */ + nop /* to avoid pipe stall on POWER4&5. */ + nop +- lwz r3,8(r1) +- lwz r4,12(r1) ++ lwz r3,8+HIWORD(r1) ++ lwz r4,8+LOWORD(r1) + addi r1,r1,16 + blr + END (__llrintf) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power5/fpu/s_isnan.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power5/fpu/s_isnan.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power5/fpu/s_isnan.S 2014-05-27 22:45:44.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power5/fpu/s_isnan.S 2014-05-27 22:45:46.000000000 -0500 +@@ -27,8 +27,8 @@ + ori r1,r1,0 + stfd fp1,24(r1) /* copy FPR to GPR */ + ori r1,r1,0 +- lwz r4,24(r1) +- lwz r5,28(r1) ++ lwz r4,24+HIWORD(r1) ++ lwz r5,24+LOWORD(r1) + lis r0,0x7ff0 /* const long r0 0x7ff00000 00000000 */ + clrlwi r4,r4,1 /* x = fabs(x) */ + cmpw cr7,r4,r0 /* if (fabs(x) =< inf) */ +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power5+/fpu/s_llround.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power5+/fpu/s_llround.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power5+/fpu/s_llround.S 2014-05-27 22:45:44.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power5+/fpu/s_llround.S 2014-05-27 22:45:46.000000000 -0500 +@@ -39,8 +39,8 @@ + nop /* Ensure the following load is in a different dispatch */ + nop /* group to avoid pipe stall on POWER4&5. */ + nop +- lwz r4,12(r1) +- lwz r3,8(r1) ++ lwz r3,8+HIWORD(r1) ++ lwz r4,8+LOWORD(r1) + addi r1,r1,16 + blr + END (__llround) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power5+/fpu/s_lround.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power5+/fpu/s_lround.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power5+/fpu/s_lround.S 2014-05-27 22:45:44.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power5+/fpu/s_lround.S 2014-05-27 22:45:46.000000000 -0500 +@@ -38,7 +38,7 @@ + nop /* Ensure the following load is in a different dispatch */ + nop /* group to avoid pipe stall on POWER4&5. */ + nop +- lwz r3,12(r1) ++ lwz r3,8+LOWORD(r1) + addi r1,r1,16 + blr + END (__lround) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/fpu/s_isnan.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/fpu/s_isnan.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/fpu/s_isnan.S 2014-05-27 22:45:44.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/fpu/s_isnan.S 2014-05-27 22:45:46.000000000 -0500 +@@ -27,8 +27,8 @@ + ori r1,r1,0 + stfd fp1,24(r1) /* copy FPR to GPR */ + ori r1,r1,0 +- lwz r4,24(r1) +- lwz r5,28(r1) ++ lwz r4,24+HIWORD(r1) ++ lwz r5,24+LOWORD(r1) + lis r0,0x7ff0 /* const long r0 0x7ff00000 00000000 */ + clrlwi r4,r4,1 /* x = fabs(x) */ + cmpw cr7,r4,r0 /* if (fabs(x) =< inf) */ +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/fpu/s_llrint.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/fpu/s_llrint.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/fpu/s_llrint.S 2014-05-27 22:45:44.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/fpu/s_llrint.S 2014-05-27 22:46:52.000000000 -0500 +@@ -29,8 +29,8 @@ + /* Insure the following load is in a different dispatch group by + inserting "group ending nop". */ + ori r1,r1,0 +- lwz r3,8(r1) +- lwz r4,12(r1) ++ lwz r3,8+HIWORD(r1) ++ lwz r4,8+LOWORD(r1) + addi r1,r1,16 + blr + END (__llrint) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/fpu/s_llrintf.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/fpu/s_llrintf.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/fpu/s_llrintf.S 2014-05-27 22:45:44.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/fpu/s_llrintf.S 2014-05-27 22:47:29.000000000 -0500 +@@ -28,8 +28,8 @@ + /* Insure the following load is in a different dispatch group by + inserting "group ending nop". */ + ori r1,r1,0 +- lwz r3,8(r1) +- lwz r4,12(r1) ++ lwz r3,8+HIWORD(r1) ++ lwz r4,8+LOWORD(r1) + addi r1,r1,16 + blr + END (__llrintf) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/fpu/s_llround.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/fpu/s_llround.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/fpu/s_llround.S 2014-05-27 22:45:44.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/fpu/s_llround.S 2014-05-27 22:45:46.000000000 -0500 +@@ -39,8 +39,8 @@ + /* Insure the following load is in a different dispatch group by + inserting "group ending nop". */ + ori r1,r1,0 +- lwz r4,12(r1) +- lwz r3,8(r1) ++ lwz r3,8+HIWORD(r1) ++ lwz r4,8+LOWORD(r1) + addi r1,r1,16 + blr + END (__llround) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/fpu/s_finite.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/fpu/s_finite.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/fpu/s_finite.S 2014-05-27 22:45:44.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/fpu/s_finite.S 2014-05-27 22:45:46.000000000 -0500 +@@ -54,9 +54,8 @@ + stfd fp1,8(r1) /* Transfer FP to GPR's. */ + + ori 2,2,0 /* Force a new dispatch group. */ +- lhz r0,8(r1) /* Fetch the upper portion of the high word of +- the FP value (where the exponent and sign bits +- are). */ ++ lhz r0,8+HISHORT(r1) /* Fetch the upper 16 bits of the FP value ++ (biased exponent and sign bit). */ + clrlwi r0,r0,17 /* r0 = abs(r0). */ + addi r1,r1,16 /* Reset the stack pointer. */ + cmpwi cr7,r0,0x7ff0 /* r4 == 0x7ff0?. */ +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/fpu/s_isinf.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/fpu/s_isinf.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/fpu/s_isinf.S 2014-05-27 22:45:44.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/fpu/s_isinf.S 2014-05-27 22:45:46.000000000 -0500 +@@ -48,14 +48,13 @@ + li r3,0 + bflr 29 /* If not INF, return. */ + +- /* Either we have -INF/+INF or a denormal. */ ++ /* Either we have +INF or -INF. */ + + stwu r1,-16(r1) /* Allocate stack space. */ + stfd fp1,8(r1) /* Transfer FP to GPR's. */ + ori 2,2,0 /* Force a new dispatch group. */ +- lhz r4,8(r1) /* Fetch the upper portion of the high word of +- the FP value (where the exponent and sign bits +- are). */ ++ lhz r4,8+HISHORT(r1) /* Fetch the upper 16 bits of the FP value ++ (biased exponent and sign bit). */ + addi r1,r1,16 /* Reset the stack pointer. */ + cmpwi cr7,r4,0x7ff0 /* r4 == 0x7ff0? */ + li r3,1 +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/fpu/s_isnan.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/fpu/s_isnan.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/fpu/s_isnan.S 2014-05-27 22:45:44.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/fpu/s_isnan.S 2014-05-27 22:45:46.000000000 -0500 +@@ -53,8 +53,8 @@ + stwu r1,-16(r1) /* Allocate stack space. */ + stfd fp1,8(r1) /* Transfer FP to GPR's. */ + ori 2,2,0 /* Force a new dispatch group. */ +- lwz r4,8(r1) /* Load the upper half of the FP value. */ +- lwz r5,12(r1) /* Load the lower half of the FP value. */ ++ lwz r4,8+HIWORD(r1) /* Load the upper half of the FP value. */ ++ lwz r5,8+LOWORD(r1) /* Load the lower half of the FP value. */ + addi r1,r1,16 /* Reset the stack pointer. */ + lis r0,0x7ff0 /* Load the upper portion for an INF/NaN. */ + clrlwi r4,r4,1 /* r4 = abs(r4). */ +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/fpu/s_finite.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/fpu/s_finite.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/fpu/s_finite.S 2014-05-27 22:45:44.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/fpu/s_finite.S 2014-05-27 22:45:46.000000000 -0500 +@@ -39,10 +39,8 @@ + + stfd fp1,-16(r1) /* Transfer FP to GPR's. */ + ori 2,2,0 /* Force a new dispatch group. */ +- +- lhz r4,-16(r1) /* Fetch the upper portion of the high word of +- the FP value (where the exponent and sign bits +- are). */ ++ lhz r4,-16+HISHORT(r1) /* Fetch the upper 16 bits of the FP value ++ (biased exponent and sign bit). */ + clrlwi r4,r4,17 /* r4 = abs(r4). */ + cmpwi cr7,r4,0x7ff0 /* r4 == 0x7ff0? */ + bltlr cr7 /* LT means finite, other non-finite. */ +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/fpu/s_isinf.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/fpu/s_isinf.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/fpu/s_isinf.S 2014-05-27 22:45:44.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/fpu/s_isinf.S 2014-05-27 22:45:46.000000000 -0500 +@@ -38,9 +38,8 @@ + + stfd fp1,-16(r1) /* Transfer FP to GPR's. */ + ori 2,2,0 /* Force a new dispatch group. */ +- lhz r4,-16(r1) /* Fetch the upper portion of the high word of +- the FP value (where the exponent and sign bits +- are). */ ++ lhz r4,-16+HISHORT(r1) /* Fetch the upper 16 bits of the FP value ++ (biased exponent and sign bit). */ + cmpwi cr7,r4,0x7ff0 /* r4 == 0x7ff0? */ + li r3,1 + beqlr cr7 /* EQ means INF, otherwise -INF. */ +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/sysdep.h glibc-2.17-c758a686/sysdeps/powerpc/sysdep.h +--- glibc-2.17-c758a686/sysdeps/powerpc/sysdep.h 2014-05-27 22:45:44.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/sysdep.h 2014-05-27 22:45:46.000000000 -0500 +@@ -144,6 +144,21 @@ + + #define VRSAVE 256 + ++/* The 32-bit words of a 64-bit dword are at these offsets in memory. */ ++#if defined __LITTLE_ENDIAN__ || defined _LITTLE_ENDIAN ++# define LOWORD 0 ++# define HIWORD 4 ++#else ++# define LOWORD 4 ++# define HIWORD 0 ++#endif ++ ++/* The high 16-bit word of a 64-bit dword is at this offset in memory. */ ++#if defined __LITTLE_ENDIAN__ || defined _LITTLE_ENDIAN ++# define HISHORT 6 ++#else ++# define HISHORT 0 ++#endif + + /* This seems to always be the case on PPC. */ + #define ALIGNARG(log2) log2 diff --git a/SOURCES/glibc-ppc64le-18.patch b/SOURCES/glibc-ppc64le-18.patch new file mode 100644 index 0000000..f5e327e --- /dev/null +++ b/SOURCES/glibc-ppc64le-18.patch @@ -0,0 +1,81 @@ +# commit 6a31fe7f9cce72b69fce8fe499a2c6ad492c2311 +# Author: Alan Modra +# Date: Sat Aug 17 18:32:18 2013 +0930 +# +# PowerPC floating point little-endian [13 of 15] +# http://sourceware.org/ml/libc-alpha/2013-08/msg00088.html +# +# * sysdeps/powerpc/powerpc32/fpu/s_roundf.S: Increase alignment of +# constants to usual value for .cst8 section, and remove redundant +# high address load. +# * sysdeps/powerpc/powerpc32/power4/fpu/s_llround.S: Use float +# constant for 0x1p52. Load little-endian words of double from +# correct stack offsets. +# +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/s_roundf.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/s_roundf.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/s_roundf.S 2014-05-27 22:50:13.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/s_roundf.S 2014-05-27 22:50:13.000000000 -0500 +@@ -19,7 +19,7 @@ + #include + + .section .rodata.cst8,"aM",@progbits,8 +- .align 2 ++ .align 3 + .LC0: /* 2**23 */ + .long 0x4b000000 + .LC1: /* 0.5 */ +@@ -60,7 +60,6 @@ + #ifdef SHARED + lfs fp10,.LC1-.LC0(r9) + #else +- lis r9,.LC1@ha + lfs fp10,.LC1@l(r9) + #endif + ble- cr6,.L4 +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/fpu/s_llround.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/fpu/s_llround.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/fpu/s_llround.S 2014-05-27 22:50:13.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/fpu/s_llround.S 2014-05-27 22:50:13.000000000 -0500 +@@ -19,12 +19,10 @@ + #include + #include + +- .section .rodata.cst12,"aM",@progbits,12 ++ .section .rodata.cst8,"aM",@progbits,8 + .align 3 +- .LC0: /* 0x1.0000000000000p+52 == 2^52 */ +- .long 0x43300000 +- .long 0x00000000 +- .long 0x3f000000 /* Use this for 0.5 */ ++ .LC0: .long (52+127)<<23 /* 0x1p+52 */ ++ .long (-1+127)<<23 /* 0.5 */ + + .section ".text" + +@@ -57,12 +55,12 @@ + addi r9,r9,.LC0-got_label@l + mtlr r11 + cfi_same_value (lr) +- lfd fp9,0(r9) +- lfs fp10,8(r9) ++ lfs fp9,0(r9) ++ lfs fp10,4(r9) + #else + lis r9,.LC0@ha +- lfd fp9,.LC0@l(r9) /* Load 2^52 into fpr9. */ +- lfs fp10,.LC0@l+8(r9) /* Load 0.5 into fpr10. */ ++ lfs fp9,.LC0@l(r9) /* Load 2^52 into fpr9. */ ++ lfs fp10,.LC0@l+4(r9) /* Load 0.5 into fpr10. */ + #endif + fabs fp2,fp1 /* Get the absolute value of x. */ + fsub fp12,fp10,fp10 /* Compute 0.0 into fpr12. */ +@@ -80,8 +78,8 @@ + nop + nop + nop +- lwz r4,12(r1) /* Load return as integer. */ +- lwz r3,8(r1) ++ lwz r3,8+HIWORD(r1) /* Load return as integer. */ ++ lwz r4,8+LOWORD(r1) + .Lout: + addi r1,r1,16 + blr diff --git a/SOURCES/glibc-ppc64le-19.patch b/SOURCES/glibc-ppc64le-19.patch new file mode 100644 index 0000000..bbf7228 --- /dev/null +++ b/SOURCES/glibc-ppc64le-19.patch @@ -0,0 +1,110 @@ +# commit 76a66d510a3737674563133a420f4fd22da42c1b +# Author: Anton Blanchard +# Date: Sat Aug 17 18:33:02 2013 +0930 +# +# PowerPC floating point little-endian [14 of 15] +# http://sourceware.org/ml/libc-alpha/2013-07/msg00205.html +# +# These all wrongly specified float constants in a 64-bit word. +# +# * sysdeps/powerpc/powerpc64/fpu/s_ceilf.S: Correct float constants +# for little-endian. +# * sysdeps/powerpc/powerpc64/fpu/s_floorf.S: Likewise. +# * sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S: Likewise. +# * sysdeps/powerpc/powerpc64/fpu/s_rintf.S: Likewise. +# * sysdeps/powerpc/powerpc64/fpu/s_roundf.S: Likewise. +# * sysdeps/powerpc/powerpc64/fpu/s_truncf.S: Likewise. +# +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_ceilf.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_ceilf.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_ceilf.S 2014-05-27 22:52:12.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_ceilf.S 2014-05-27 22:52:18.000000000 -0500 +@@ -19,8 +19,10 @@ + #include + + .section ".toc","aw" ++ .p2align 3 + .LC0: /* 2**23 */ +- .tc FD_4b000000_0[TC],0x4b00000000000000 ++ .long 0x4b000000 ++ .long 0x0 + .section ".text" + + EALIGN (__ceilf, 4, 0) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_floorf.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_floorf.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_floorf.S 2014-05-27 22:52:12.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_floorf.S 2014-05-27 22:52:18.000000000 -0500 +@@ -19,8 +19,10 @@ + #include + + .section ".toc","aw" ++ .p2align 3 + .LC0: /* 2**23 */ +- .tc FD_4b000000_0[TC],0x4b00000000000000 ++ .long 0x4b000000 ++ .long 0x0 + .section ".text" + + EALIGN (__floorf, 4, 0) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S 2014-05-27 22:52:12.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S 2014-05-27 22:52:18.000000000 -0500 +@@ -26,8 +26,10 @@ + /* float [fp1] nearbyintf(float [fp1]) */ + + .section ".toc","aw" ++ .p2align 3 + .LC0: /* 2**23 */ +- .tc FD_4b000000_0[TC],0x4b00000000000000 ++ .long 0x4b000000 ++ .long 0x0 + .section ".text" + + EALIGN (__nearbyintf, 4, 0) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_rintf.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_rintf.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_rintf.S 2014-05-27 22:52:12.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_rintf.S 2014-05-27 22:52:18.000000000 -0500 +@@ -19,8 +19,10 @@ + #include + + .section ".toc","aw" ++ .p2align 3 + .LC0: /* 2**23 */ +- .tc FD_4b000000_0[TC],0x4b00000000000000 ++ .long 0x4b000000 ++ .long 0x0 + .section ".text" + + EALIGN (__rintf, 4, 0) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_roundf.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_roundf.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_roundf.S 2014-05-27 22:52:12.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_roundf.S 2014-05-27 22:52:18.000000000 -0500 +@@ -19,10 +19,12 @@ + #include + + .section ".toc","aw" ++ .p2align 3 + .LC0: /* 2**23 */ +- .tc FD_4b000000_0[TC],0x4b00000000000000 ++ .long 0x4b000000 + .LC1: /* 0.5 */ +- .tc FD_3f000000_0[TC],0x3f00000000000000 ++ .long 0x3f000000 ++ + .section ".text" + + /* float [fp1] roundf (float x [fp1]) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_truncf.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_truncf.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_truncf.S 2014-05-27 22:52:12.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_truncf.S 2014-05-27 22:52:18.000000000 -0500 +@@ -19,8 +19,10 @@ + #include + + .section ".toc","aw" ++ .p2align 3 + .LC0: /* 2**23 */ +- .tc FD_4b000000_0[TC],0x4b00000000000000 ++ .long 0x4b000000 ++ .long 0x0 + .section ".text" + + /* float [fp1] truncf (float x [fp1]) diff --git a/SOURCES/glibc-ppc64le-20.patch b/SOURCES/glibc-ppc64le-20.patch new file mode 100644 index 0000000..1342f97 --- /dev/null +++ b/SOURCES/glibc-ppc64le-20.patch @@ -0,0 +1,43 @@ +# commit fef13a78ea30d4c26d6bab48d731ebe864ee31b0 +# Author: Alan Modra +# Date: Sat Aug 17 18:33:45 2013 +0930 +# +# PowerPC floating point little-endian [15 of 15] +# http://sourceware.org/ml/libc-alpha/2013-07/msg00206.html +# +# The union loses when little-endian. +# +# * sysdeps/powerpc/powerpc32/power4/hp-timing.h (HP_TIMING_NOW): +# Don't use a union to pack hi/low value. +# +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/hp-timing.h glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/hp-timing.h +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/hp-timing.h 2014-05-27 22:53:37.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/hp-timing.h 2014-05-27 22:53:39.000000000 -0500 +@@ -87,18 +87,15 @@ + + #define HP_TIMING_NOW(Var) \ + do { \ +- union { long long ll; long ii[2]; } _var; \ +- long tmp; \ +- __asm__ __volatile__ ( \ +- "1: mfspr %0,269;" \ +- " mfspr %1,268;" \ +- " mfspr %2,269;" \ +- " cmpw %0,%2;" \ +- " bne 1b;" \ +- : "=r" (_var.ii[0]), "=r" (_var.ii[1]) , "=r" (tmp) \ +- : : "cr0" \ +- ); \ +- Var = _var.ll; \ ++ unsigned int hi, lo, tmp; \ ++ __asm__ __volatile__ ("1: mfspr %0,269;" \ ++ " mfspr %1,268;" \ ++ " mfspr %2,269;" \ ++ " cmpw %0,%2;" \ ++ " bne 1b;" \ ++ : "=&r" (hi), "=&r" (lo), "=&r" (tmp) \ ++ : : "cr0"); \ ++ Var = ((hp_timing_t) hi << 32) | lo; \ + } while (0) + + diff --git a/SOURCES/glibc-ppc64le-21.patch b/SOURCES/glibc-ppc64le-21.patch new file mode 100644 index 0000000..a945404 --- /dev/null +++ b/SOURCES/glibc-ppc64le-21.patch @@ -0,0 +1,294 @@ +# commit be1e5d311342e08ae1f8013342df27b7ded2c156 +# Author: Anton Blanchard +# Date: Sat Aug 17 18:34:40 2013 +0930 +# +# PowerPC LE setjmp/longjmp +# http://sourceware.org/ml/libc-alpha/2013-08/msg00089.html +# +# Little-endian fixes for setjmp/longjmp. When writing these I noticed +# the setjmp code corrupts the non volatile VMX registers when using an +# unaligned buffer. Anton fixed this, and also simplified it quite a +# bit. +# +# The current code uses boilerplate for the case where we want to store +# 16 bytes to an unaligned address. For that we have to do a +# read/modify/write of two aligned 16 byte quantities. In our case we +# are storing a bunch of back to back data (consective VMX registers), +# and only the start and end of the region need the read/modify/write. +# +# [BZ #15723] +# * sysdeps/powerpc/jmpbuf-offsets.h: Comment fix. +# * sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S: Correct +# _dl_hwcap access for little-endian. +# * sysdeps/powerpc/powerpc32/fpu/setjmp-common.S: Likewise. Don't +# destroy vmx regs when saving unaligned. +# * sysdeps/powerpc/powerpc64/__longjmp-common.S: Correct CR load. +# * sysdeps/powerpc/powerpc64/setjmp-common.S: Likewise CR save. Don't +# destroy vmx regs when saving unaligned. +# +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/jmpbuf-offsets.h glibc-2.17-c758a686/sysdeps/powerpc/jmpbuf-offsets.h +--- glibc-2.17-c758a686/sysdeps/powerpc/jmpbuf-offsets.h 2014-05-27 22:55:23.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/jmpbuf-offsets.h 2014-05-27 22:55:27.000000000 -0500 +@@ -21,12 +21,10 @@ + #define JB_LR 2 /* The address we will return to */ + #if __WORDSIZE == 64 + # define JB_GPRS 3 /* GPRs 14 through 31 are saved, 18*2 words total. */ +-# define JB_CR 21 /* Condition code registers with the VRSAVE at */ +- /* offset 172 (low half of the double word. */ ++# define JB_CR 21 /* Shared dword with VRSAVE. CR word at offset 172. */ + # define JB_FPRS 22 /* FPRs 14 through 31 are saved, 18*2 words total. */ + # define JB_SIZE (64 * 8) /* As per PPC64-VMX ABI. */ +-# define JB_VRSAVE 21 /* VRSAVE shares a double word with the CR at offset */ +- /* 168 (high half of the double word). */ ++# define JB_VRSAVE 21 /* Shared dword with CR. VRSAVE word at offset 168. */ + # define JB_VRS 40 /* VRs 20 through 31 are saved, 12*4 words total. */ + #else + # define JB_GPRS 3 /* GPRs 14 through 31 are saved, 18 in total. */ +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S 2014-05-27 22:55:23.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S 2014-05-27 22:55:27.000000000 -0500 +@@ -46,16 +46,16 @@ + # endif + mtlr r6 + cfi_same_value (lr) +- lwz r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+4(r5) ++ lwz r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r5) + # else + lwz r5,_dl_hwcap@got(r5) + mtlr r6 + cfi_same_value (lr) +- lwz r5,4(r5) ++ lwz r5,LOWORD(r5) + # endif + # else +- lis r5,(_dl_hwcap+4)@ha +- lwz r5,(_dl_hwcap+4)@l(r5) ++ lis r5,(_dl_hwcap+LOWORD)@ha ++ lwz r5,(_dl_hwcap+LOWORD)@l(r5) + # endif + andis. r5,r5,(PPC_FEATURE_HAS_ALTIVEC >> 16) + beq L(no_vmx) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/setjmp-common.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/setjmp-common.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/setjmp-common.S 2014-05-27 22:55:23.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/setjmp-common.S 2014-05-27 22:55:27.000000000 -0500 +@@ -97,14 +97,14 @@ + # else + lwz r5,_rtld_global_ro@got(r5) + # endif +- lwz r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+4(r5) ++ lwz r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r5) + # else + lwz r5,_dl_hwcap@got(r5) +- lwz r5,4(r5) ++ lwz r5,LOWORD(r5) + # endif + # else +- lis r6,(_dl_hwcap+4)@ha +- lwz r5,(_dl_hwcap+4)@l(r6) ++ lis r6,(_dl_hwcap+LOWORD)@ha ++ lwz r5,(_dl_hwcap+LOWORD)@l(r6) + # endif + andis. r5,r5,(PPC_FEATURE_HAS_ALTIVEC >> 16) + beq L(no_vmx) +@@ -114,44 +114,43 @@ + stw r0,((JB_VRSAVE)*4)(3) + addi r6,r5,16 + beq+ L(aligned_save_vmx) ++ + lvsr v0,0,r5 +- vspltisb v1,-1 /* set v1 to all 1's */ +- vspltisb v2,0 /* set v2 to all 0's */ +- vperm v3,v2,v1,v0 /* v3 contains shift mask with num all 1 bytes on left = misalignment */ +- +- +- /* Special case for v20 we need to preserve what is in save area below v20 before obliterating it */ +- lvx v5,0,r5 +- vperm v20,v20,v20,v0 +- vsel v5,v5,v20,v3 +- vsel v20,v20,v2,v3 +- stvx v5,0,r5 +- +-#define save_2vmx_partial(savevr,prev_savevr,hivr,shiftvr,maskvr,savegpr,addgpr) \ +- addi addgpr,addgpr,32; \ +- vperm savevr,savevr,savevr,shiftvr; \ +- vsel hivr,prev_savevr,savevr,maskvr; \ +- stvx hivr,0,savegpr; +- +- save_2vmx_partial(v21,v20,v5,v0,v3,r6,r5) +- save_2vmx_partial(v22,v21,v5,v0,v3,r5,r6) +- save_2vmx_partial(v23,v22,v5,v0,v3,r6,r5) +- save_2vmx_partial(v24,v23,v5,v0,v3,r5,r6) +- save_2vmx_partial(v25,v24,v5,v0,v3,r6,r5) +- save_2vmx_partial(v26,v25,v5,v0,v3,r5,r6) +- save_2vmx_partial(v27,v26,v5,v0,v3,r6,r5) +- save_2vmx_partial(v28,v27,v5,v0,v3,r5,r6) +- save_2vmx_partial(v29,v28,v5,v0,v3,r6,r5) +- save_2vmx_partial(v30,v29,v5,v0,v3,r5,r6) +- +- /* Special case for r31 we need to preserve what is in save area above v31 before obliterating it */ +- addi r5,r5,32 +- vperm v31,v31,v31,v0 +- lvx v4,0,r5 +- vsel v5,v30,v31,v3 +- stvx v5,0,r6 +- vsel v4,v31,v4,v3 +- stvx v4,0,r5 ++ lvsl v1,0,r5 ++ addi r6,r5,-16 ++ ++# define save_misaligned_vmx(savevr,prevvr,shiftvr,tmpvr,savegpr,addgpr) \ ++ addi addgpr,addgpr,32; \ ++ vperm tmpvr,prevvr,savevr,shiftvr; \ ++ stvx tmpvr,0,savegpr ++ ++ /* ++ * We have to be careful not to corrupt the data below v20 and ++ * above v31. To keep things simple we just rotate both ends in ++ * the opposite direction to our main permute so we can use ++ * the common macro. ++ */ ++ ++ /* load and rotate data below v20 */ ++ lvx v2,0,r5 ++ vperm v2,v2,v2,v1 ++ save_misaligned_vmx(v20,v2,v0,v3,r5,r6) ++ save_misaligned_vmx(v21,v20,v0,v3,r6,r5) ++ save_misaligned_vmx(v22,v21,v0,v3,r5,r6) ++ save_misaligned_vmx(v23,v22,v0,v3,r6,r5) ++ save_misaligned_vmx(v24,v23,v0,v3,r5,r6) ++ save_misaligned_vmx(v25,v24,v0,v3,r6,r5) ++ save_misaligned_vmx(v26,v25,v0,v3,r5,r6) ++ save_misaligned_vmx(v27,v26,v0,v3,r6,r5) ++ save_misaligned_vmx(v28,v27,v0,v3,r5,r6) ++ save_misaligned_vmx(v29,v28,v0,v3,r6,r5) ++ save_misaligned_vmx(v30,v29,v0,v3,r5,r6) ++ save_misaligned_vmx(v31,v30,v0,v3,r6,r5) ++ /* load and rotate data above v31 */ ++ lvx v2,0,r6 ++ vperm v2,v2,v2,v1 ++ save_misaligned_vmx(v2,v31,v0,v3,r5,r6) ++ + b L(no_vmx) + + L(aligned_save_vmx): +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/__longjmp-common.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/__longjmp-common.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/__longjmp-common.S 2014-05-27 22:55:23.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/__longjmp-common.S 2014-05-27 22:55:27.000000000 -0500 +@@ -60,7 +60,7 @@ + beq L(no_vmx) + la r5,((JB_VRS)*8)(3) + andi. r6,r5,0xf +- lwz r0,((JB_VRSAVE)*8)(3) ++ lwz r0,((JB_VRSAVE)*8)(3) /* 32-bit VRSAVE. */ + mtspr VRSAVE,r0 + beq+ L(aligned_restore_vmx) + addi r6,r5,16 +@@ -156,7 +156,7 @@ + lfd fp21,((JB_FPRS+7)*8)(r3) + ld r22,((JB_GPRS+8)*8)(r3) + lfd fp22,((JB_FPRS+8)*8)(r3) +- ld r0,(JB_CR*8)(r3) ++ lwz r0,((JB_CR*8)+4)(r3) /* 32-bit CR. */ + ld r23,((JB_GPRS+9)*8)(r3) + lfd fp23,((JB_FPRS+9)*8)(r3) + ld r24,((JB_GPRS+10)*8)(r3) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S 2014-05-27 22:55:23.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S 2014-05-27 22:55:27.000000000 -0500 +@@ -98,7 +98,7 @@ + mfcr r0 + std r16,((JB_GPRS+2)*8)(3) + stfd fp16,((JB_FPRS+2)*8)(3) +- std r0,(JB_CR*8)(3) ++ stw r0,((JB_CR*8)+4)(3) /* 32-bit CR. */ + std r17,((JB_GPRS+3)*8)(3) + stfd fp17,((JB_FPRS+3)*8)(3) + std r18,((JB_GPRS+4)*8)(3) +@@ -142,50 +142,46 @@ + la r5,((JB_VRS)*8)(3) + andi. r6,r5,0xf + mfspr r0,VRSAVE +- stw r0,((JB_VRSAVE)*8)(3) ++ stw r0,((JB_VRSAVE)*8)(3) /* 32-bit VRSAVE. */ + addi r6,r5,16 + beq+ L(aligned_save_vmx) ++ + lvsr v0,0,r5 +- vspltisb v1,-1 /* set v1 to all 1's */ +- vspltisb v2,0 /* set v2 to all 0's */ +- vperm v3,v2,v1,v0 /* v3 contains shift mask with num all 1 bytes +- on left = misalignment */ +- +- +- /* Special case for v20 we need to preserve what is in save area +- below v20 before obliterating it */ +- lvx v5,0,r5 +- vperm v20,v20,v20,v0 +- vsel v5,v5,v20,v3 +- vsel v20,v20,v2,v3 +- stvx v5,0,r5 +- +-# define save_2vmx_partial(savevr,prev_savevr,hivr,shiftvr,maskvr,savegpr,addgpr) \ +- addi addgpr,addgpr,32; \ +- vperm savevr,savevr,savevr,shiftvr; \ +- vsel hivr,prev_savevr,savevr,maskvr; \ +- stvx hivr,0,savegpr; +- +- save_2vmx_partial(v21,v20,v5,v0,v3,r6,r5) +- save_2vmx_partial(v22,v21,v5,v0,v3,r5,r6) +- save_2vmx_partial(v23,v22,v5,v0,v3,r6,r5) +- save_2vmx_partial(v24,v23,v5,v0,v3,r5,r6) +- save_2vmx_partial(v25,v24,v5,v0,v3,r6,r5) +- save_2vmx_partial(v26,v25,v5,v0,v3,r5,r6) +- save_2vmx_partial(v27,v26,v5,v0,v3,r6,r5) +- save_2vmx_partial(v28,v27,v5,v0,v3,r5,r6) +- save_2vmx_partial(v29,v28,v5,v0,v3,r6,r5) +- save_2vmx_partial(v30,v29,v5,v0,v3,r5,r6) +- +- /* Special case for r31 we need to preserve what is in save area +- above v31 before obliterating it */ +- addi r5,r5,32 +- vperm v31,v31,v31,v0 +- lvx v4,0,r5 +- vsel v5,v30,v31,v3 +- stvx v5,0,r6 +- vsel v4,v31,v4,v3 +- stvx v4,0,r5 ++ lvsl v1,0,r5 ++ addi r6,r5,-16 ++ ++# define save_misaligned_vmx(savevr,prevvr,shiftvr,tmpvr,savegpr,addgpr) \ ++ addi addgpr,addgpr,32; \ ++ vperm tmpvr,prevvr,savevr,shiftvr; \ ++ stvx tmpvr,0,savegpr ++ ++ /* ++ * We have to be careful not to corrupt the data below v20 and ++ * above v31. To keep things simple we just rotate both ends in ++ * the opposite direction to our main permute so we can use ++ * the common macro. ++ */ ++ ++ /* load and rotate data below v20 */ ++ lvx v2,0,r5 ++ vperm v2,v2,v2,v1 ++ save_misaligned_vmx(v20,v2,v0,v3,r5,r6) ++ save_misaligned_vmx(v21,v20,v0,v3,r6,r5) ++ save_misaligned_vmx(v22,v21,v0,v3,r5,r6) ++ save_misaligned_vmx(v23,v22,v0,v3,r6,r5) ++ save_misaligned_vmx(v24,v23,v0,v3,r5,r6) ++ save_misaligned_vmx(v25,v24,v0,v3,r6,r5) ++ save_misaligned_vmx(v26,v25,v0,v3,r5,r6) ++ save_misaligned_vmx(v27,v26,v0,v3,r6,r5) ++ save_misaligned_vmx(v28,v27,v0,v3,r5,r6) ++ save_misaligned_vmx(v29,v28,v0,v3,r6,r5) ++ save_misaligned_vmx(v30,v29,v0,v3,r5,r6) ++ save_misaligned_vmx(v31,v30,v0,v3,r6,r5) ++ /* load and rotate data above v31 */ ++ lvx v2,0,r6 ++ vperm v2,v2,v2,v1 ++ save_misaligned_vmx(v2,v31,v0,v3,r5,r6) ++ + b L(no_vmx) + + L(aligned_save_vmx): diff --git a/SOURCES/glibc-ppc64le-22.patch b/SOURCES/glibc-ppc64le-22.patch new file mode 100644 index 0000000..12a0ff0 --- /dev/null +++ b/SOURCES/glibc-ppc64le-22.patch @@ -0,0 +1,228 @@ +# commit 9b874b2f1eb2550e39d3e9c38772e64a767e9de2 +# Author: Alan Modra +# Date: Sat Aug 17 18:35:40 2013 +0930 +# +# PowerPC ugly symbol versioning +# http://sourceware.org/ml/libc-alpha/2013-08/msg00090.html +# +# This patch fixes symbol versioning in setjmp/longjmp. The existing +# code uses raw versions, which results in wrong symbol versioning when +# you want to build glibc with a base version of 2.19 for LE. +# +# Note that the merging the 64-bit and 32-bit versions in novmx-lonjmp.c +# and pt-longjmp.c doesn't result in GLIBC_2.0 versions for 64-bit, due +# to the base in shlib_versions. +# +# * sysdeps/powerpc/longjmp.c: Use proper symbol versioning macros. +# * sysdeps/powerpc/novmx-longjmp.c: Likewise. +# * sysdeps/powerpc/powerpc32/bsd-_setjmp.S: Likewise. +# * sysdeps/powerpc/powerpc32/bsd-setjmp.S: Likewise. +# * sysdeps/powerpc/powerpc32/fpu/__longjmp.S: Likewise. +# * sysdeps/powerpc/powerpc32/fpu/setjmp.S: Likewise. +# * sysdeps/powerpc/powerpc32/mcount.c: Likewise. +# * sysdeps/powerpc/powerpc32/setjmp.S: Likewise. +# * sysdeps/powerpc/powerpc64/setjmp.S: Likewise. +# * nptl/sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c: Likewise. +# +diff -urN glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c +--- glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c 2014-05-27 23:22:12.000000000 -0500 ++++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c 2014-05-27 23:23:44.000000000 -0500 +@@ -41,13 +41,8 @@ + __novmx__libc_longjmp (env, val); + } + +-# if __WORDSIZE == 64 +-symbol_version (__novmx_longjmp,longjmp,GLIBC_2.3); +-symbol_version (__novmx_siglongjmp,siglongjmp,GLIBC_2.3); +-# else +-symbol_version (__novmx_longjmp,longjmp,GLIBC_2.0); +-symbol_version (__novmx_siglongjmp,siglongjmp,GLIBC_2.0); +-# endif ++compat_symbol (libpthread, __novmx_longjmp, longjmp, GLIBC_2_0); ++compat_symbol (libpthread, __novmx_siglongjmp, siglongjmp, GLIBC_2_0); + #endif /* defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)) */ + + void +@@ -62,5 +57,5 @@ + __libc_siglongjmp (env, val); + } + +-versioned_symbol (libc, __vmx_longjmp, longjmp, GLIBC_2_3_4); +-versioned_symbol (libc, __vmx_siglongjmp, siglongjmp, GLIBC_2_3_4); ++versioned_symbol (libpthread, __vmx_longjmp, longjmp, GLIBC_2_3_4); ++versioned_symbol (libpthread, __vmx_siglongjmp, siglongjmp, GLIBC_2_3_4); +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/longjmp.c glibc-2.17-c758a686/sysdeps/powerpc/longjmp.c +--- glibc-2.17-c758a686/sysdeps/powerpc/longjmp.c 2014-05-27 23:22:10.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/longjmp.c 2014-05-27 23:22:12.000000000 -0500 +@@ -56,6 +56,6 @@ + + default_symbol_version (__vmx__libc_longjmp, __libc_longjmp, GLIBC_PRIVATE); + default_symbol_version (__vmx__libc_siglongjmp, __libc_siglongjmp, GLIBC_PRIVATE); +-default_symbol_version (__vmx_longjmp, _longjmp, GLIBC_2.3.4); +-default_symbol_version (__vmxlongjmp, longjmp, GLIBC_2.3.4); +-default_symbol_version (__vmxsiglongjmp, siglongjmp, GLIBC_2.3.4); ++versioned_symbol (libc, __vmx_longjmp, _longjmp, GLIBC_2_3_4); ++versioned_symbol (libc, __vmxlongjmp, longjmp, GLIBC_2_3_4); ++versioned_symbol (libc, __vmxsiglongjmp, siglongjmp, GLIBC_2_3_4); +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/novmx-longjmp.c glibc-2.17-c758a686/sysdeps/powerpc/novmx-longjmp.c +--- glibc-2.17-c758a686/sysdeps/powerpc/novmx-longjmp.c 2014-05-27 23:22:10.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/novmx-longjmp.c 2014-05-27 23:22:12.000000000 -0500 +@@ -51,13 +51,7 @@ + weak_alias (__novmx__libc_siglongjmp, __novmxlongjmp) + weak_alias (__novmx__libc_siglongjmp, __novmxsiglongjmp) + +-# if __WORDSIZE == 64 +-symbol_version (__novmx_longjmp,_longjmp,GLIBC_2.3); +-symbol_version (__novmxlongjmp,longjmp,GLIBC_2.3); +-symbol_version (__novmxsiglongjmp,siglongjmp,GLIBC_2.3); +-# else +-symbol_version (__novmx_longjmp,_longjmp,GLIBC_2.0); +-symbol_version (__novmxlongjmp,longjmp,GLIBC_2.0); +-symbol_version (__novmxsiglongjmp,siglongjmp,GLIBC_2.0); +-# endif ++compat_symbol (libc, __novmx_longjmp, _longjmp, GLIBC_2_0); ++compat_symbol (libc, __novmxlongjmp, longjmp, GLIBC_2_0); ++compat_symbol (libc, __novmxsiglongjmp, siglongjmp, GLIBC_2_0); + #endif /* defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)) */ +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/bsd-_setjmp.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/bsd-_setjmp.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/bsd-_setjmp.S 2014-05-27 23:22:10.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/bsd-_setjmp.S 2014-05-27 23:22:12.000000000 -0500 +@@ -32,7 +32,7 @@ + /* Build a versioned object for libc. */ + + # if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) +-symbol_version (__novmx_setjmp,_setjmp,GLIBC_2.0); ++compat_symbol (libc, __novmx_setjmp, _setjmp, GLIBC_2_0); + + ENTRY (BP_SYM (__novmx_setjmp)) + li r4,0 /* Set second argument to 0. */ +@@ -41,7 +41,7 @@ + libc_hidden_def (__novmx_setjmp) + # endif /* defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) */ + +-default_symbol_version (__vmx_setjmp,_setjmp,GLIBC_2.3.4) ++versioned_symbol (libc, __vmx_setjmp, _setjmp, GLIBC_2_3_4) + /* __GI__setjmp prototype is needed for ntpl i.e. _setjmp is defined + as a libc_hidden_proto & is used in sysdeps/generic/libc-start.c + if HAVE_CLEANUP_JMP_BUF is defined */ +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/bsd-setjmp.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/bsd-setjmp.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/bsd-setjmp.S 2014-05-27 23:22:10.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/bsd-setjmp.S 2014-05-27 23:22:12.000000000 -0500 +@@ -27,7 +27,7 @@ + b __novmx__sigsetjmp@local + END (__novmxsetjmp) + strong_alias (__novmxsetjmp, __novmx__setjmp) +-symbol_version (__novmxsetjmp, setjmp, GLIBC_2.0) ++compat_symbol (libc, __novmxsetjmp, setjmp, GLIBC_2_0) + + #endif /* defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) ) */ + +@@ -37,4 +37,4 @@ + END (__vmxsetjmp) + strong_alias (__vmxsetjmp, __vmx__setjmp) + strong_alias (__vmx__setjmp, __setjmp) +-default_symbol_version (__vmxsetjmp,setjmp,GLIBC_2.3.4) ++versioned_symbol (libc, __vmxsetjmp, setjmp, GLIBC_2_3_4) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/__longjmp.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/__longjmp.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/__longjmp.S 2014-05-27 23:22:10.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/__longjmp.S 2014-05-27 23:22:12.000000000 -0500 +@@ -26,14 +26,14 @@ + + #else /* !NOT_IN_libc */ + /* Build a versioned object for libc. */ +-default_symbol_version (__vmx__longjmp,__longjmp,GLIBC_2.3.4); ++versioned_symbol (libc, __vmx__longjmp, __longjmp, GLIBC_2_3_4); + # define __longjmp __vmx__longjmp + # include "__longjmp-common.S" + + # if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) + # define __NO_VMX__ + # undef JB_SIZE +-symbol_version (__novmx__longjmp,__longjmp,GLIBC_2.0); ++compat_symbol (libc, __novmx__longjmp, __longjmp, GLIBC_2_0); + # undef __longjmp + # define __longjmp __novmx__longjmp + # include "__longjmp-common.S" +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/setjmp.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/setjmp.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/setjmp.S 2014-05-27 23:22:10.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/setjmp.S 2014-05-27 23:22:12.000000000 -0500 +@@ -26,7 +26,7 @@ + + #else /* !NOT_IN_libc */ + /* Build a versioned object for libc. */ +-default_symbol_version (__vmx__sigsetjmp,__sigsetjmp,GLIBC_2.3.4) ++versioned_symbol (libc, __vmx__sigsetjmp, __sigsetjmp, GLIBC_2_3_4) + # define __sigsetjmp __vmx__sigsetjmp + # define __sigjmp_save __vmx__sigjmp_save + # include "setjmp-common.S" +@@ -36,7 +36,7 @@ + # undef __sigsetjmp + # undef __sigjmp_save + # undef JB_SIZE +-symbol_version (__novmx__sigsetjmp,__sigsetjmp,GLIBC_2.0) ++compat_symbol (libc, __novmx__sigsetjmp, __sigsetjmp, GLIBC_2_0) + # define __sigsetjmp __novmx__sigsetjmp + # define __sigjmp_save __novmx__sigjmp_save + # include "setjmp-common.S" +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/mcount.c glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/mcount.c +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/mcount.c 2014-05-27 23:22:10.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/mcount.c 2014-05-27 23:22:12.000000000 -0500 +@@ -9,7 +9,7 @@ + /* __mcount_internal was added in glibc 2.15 with version GLIBC_PRIVATE, + but it should have been put in version GLIBC_2.15. Mark the + GLIBC_PRIVATE version obsolete and add it to GLIBC_2.16 instead. */ +-default_symbol_version (___mcount_internal, __mcount_internal, GLIBC_2.16); ++versioned_symbol (libc, ___mcount_internal, __mcount_internal, GLIBC_2_16); + + #if SHLIB_COMPAT (libc, GLIBC_2_15, GLIBC_2_16) + strong_alias (___mcount_internal, ___mcount_internal_private); +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/setjmp.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/setjmp.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/setjmp.S 2014-05-27 23:22:10.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/setjmp.S 2014-05-27 23:22:12.000000000 -0500 +@@ -25,7 +25,7 @@ + + #else /* !NOT_IN_libc */ + /* Build a versioned object for libc. */ +-default_symbol_version (__vmx__sigsetjmp,__sigsetjmp,GLIBC_2.3.4) ++versioned_symbol (libc, __vmx__sigsetjmp, __sigsetjmp, GLIBC_2_3_4) + # define __sigsetjmp __vmx__sigsetjmp + # define __sigjmp_save __vmx__sigjmp_save + # include "setjmp-common.S" +@@ -35,7 +35,7 @@ + # undef __sigsetjmp + # undef __sigjmp_save + # undef JB_SIZE +-symbol_version (__novmx__sigsetjmp,__sigsetjmp,GLIBC_2.0) ++compat_symbol (libc, __novmx__sigsetjmp, __sigsetjmp, GLIBC_2_0) + # define __sigsetjmp __novmx__sigsetjmp + # define __sigjmp_save __novmx__sigjmp_save + # include "setjmp-common.S" +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp.S 2014-05-27 23:22:10.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp.S 2014-05-27 23:22:12.000000000 -0500 +@@ -26,9 +26,9 @@ + + #else /* !NOT_IN_libc */ + /* Build a versioned object for libc. */ +-default_symbol_version (__vmxsetjmp, setjmp, GLIBC_2.3.4) +-default_symbol_version (__vmx_setjmp,_setjmp,GLIBC_2.3.4) +-default_symbol_version (__vmx__sigsetjmp,__sigsetjmp,GLIBC_2.3.4) ++versioned_symbol (libc, __vmxsetjmp, setjmp, GLIBC_2_3_4) ++versioned_symbol (libc, __vmx_setjmp, _setjmp, GLIBC_2_3_4) ++versioned_symbol (libc, __vmx__sigsetjmp, __sigsetjmp, GLIBC_2_3_4) + # define setjmp __vmxsetjmp + # define _setjmp __vmx_setjmp + # define __sigsetjmp __vmx__sigsetjmp +@@ -44,9 +44,9 @@ + # undef __sigjmp_save + # undef JB_SIZE + # define __NO_VMX__ +-symbol_version (__novmxsetjmp, setjmp, GLIBC_2.3) +-symbol_version (__novmx_setjmp,_setjmp,GLIBC_2.3); +-symbol_version (__novmx__sigsetjmp,__sigsetjmp,GLIBC_2.3) ++compat_symbol (libc, __novmxsetjmp, setjmp, GLIBC_2_3) ++compat_symbol (libc, __novmx_setjmp,_setjmp, GLIBC_2_3); ++compat_symbol (libc, __novmx__sigsetjmp,__sigsetjmp, GLIBC_2_3) + # define setjmp __novmxsetjmp + # define _setjmp __novmx_setjmp + # define __sigsetjmp __novmx__sigsetjmp diff --git a/SOURCES/glibc-ppc64le-23.patch b/SOURCES/glibc-ppc64le-23.patch new file mode 100644 index 0000000..00288b9 --- /dev/null +++ b/SOURCES/glibc-ppc64le-23.patch @@ -0,0 +1,102 @@ +# commit 02f04a6c7fea2b474b026bbce721d8c658d71fda +# Author: Alan Modra +# Date: Sat Aug 17 18:36:11 2013 +0930 +# +# PowerPC LE _dl_hwcap access +# http://sourceware.org/ml/libc-alpha/2013-08/msg00091.html +# +# More LE support, correcting word accesses to _dl_hwcap. +# +# * sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S: Use +# HIWORD/LOWORD. +# * sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S: Ditto. +# * sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S: Ditto. +# +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S 2014-05-27 23:25:35.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S 2014-05-27 23:25:38.000000000 -0500 +@@ -151,15 +151,15 @@ + # ifdef SHARED + lwz r7,_rtld_global_ro@got(r7) + mtlr r8 +- lwz r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+4(r7) ++ lwz r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r7) + # else + lwz r7,_dl_hwcap@got(r7) + mtlr r8 +- lwz r7,4(r7) ++ lwz r7,LOWORD(r7) + # endif + # else +- lis r7,(_dl_hwcap+4)@ha +- lwz r7,(_dl_hwcap+4)@l(r7) ++ lis r7,(_dl_hwcap+LOWORD)@ha ++ lwz r7,(_dl_hwcap+LOWORD)@l(r7) + # endif + andis. r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16) + +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S 2014-05-27 23:25:35.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S 2014-05-27 23:25:38.000000000 -0500 +@@ -79,15 +79,15 @@ + # ifdef SHARED + lwz r7,_rtld_global_ro@got(r7) + mtlr r8 +- lwz r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+4(r7) ++ lwz r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r7) + # else + lwz r7,_dl_hwcap@got(r7) + mtlr r8 +- lwz r7,4(r7) ++ lwz r7,LOWORD(r7) + # endif + #else +- lis r7,(_dl_hwcap+4)@ha +- lwz r7,(_dl_hwcap+4)@l(r7) ++ lis r7,(_dl_hwcap+LOWORD)@ha ++ lwz r7,(_dl_hwcap+LOWORD)@l(r7) + #endif + + #ifdef __CONTEXT_ENABLE_FPRS +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S 2014-05-27 23:25:35.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S 2014-05-27 23:25:38.000000000 -0500 +@@ -152,15 +152,15 @@ + # ifdef SHARED + lwz r7,_rtld_global_ro@got(r7) + mtlr r8 +- lwz r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+4(r7) ++ lwz r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r7) + # else + lwz r7,_dl_hwcap@got(r7) + mtlr r8 +- lwz r7,4(r7) ++ lwz r7,LOWORD(r7) + # endif + # else +- lis r7,(_dl_hwcap+4)@ha +- lwz r7,(_dl_hwcap+4)@l(r7) ++ lis r7,(_dl_hwcap+LOWORD)@ha ++ lwz r7,(_dl_hwcap+LOWORD)@l(r7) + # endif + + # ifdef __CONTEXT_ENABLE_VRS +@@ -308,14 +308,14 @@ + mtlr r8 + # ifdef SHARED + lwz r7,_rtld_global_ro@got(r7) +- lwz r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+4(r7) ++ lwz r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r7) + # else + lwz r7,_dl_hwcap@got(r7) +- lwz r7,4(r7) ++ lwz r7,LOWORD(r7) + # endif + # else +- lis r7,(_dl_hwcap+4)@ha +- lwz r7,(_dl_hwcap+4)@l(r7) ++ lis r7,(_dl_hwcap+LOWORD)@ha ++ lwz r7,(_dl_hwcap+LOWORD)@l(r7) + # endif + andis. r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16) + la r10,(_UC_VREGS)(r31) diff --git a/SOURCES/glibc-ppc64le-24.patch b/SOURCES/glibc-ppc64le-24.patch new file mode 100644 index 0000000..5870d4f --- /dev/null +++ b/SOURCES/glibc-ppc64le-24.patch @@ -0,0 +1,55 @@ +# commit 0b2c2ace3601d5d59cf89130b16840e7f132f7a6 +# Author: Alan Modra +# Date: Sat Aug 17 18:36:45 2013 +0930 +# +# PowerPC makecontext +# http://sourceware.org/ml/libc-alpha/2013-08/msg00092.html +# +# Use conditional form of branch and link to avoid destroying the cpu +# link stack used to predict blr return addresses. +# +# * sysdeps/unix/sysv/linux/powerpc/powerpc32/makecontext.S: Use +# conditional form of branch and link when obtaining pc. +# * sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S: Likewise. +# +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc32/makecontext.S glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc32/makecontext.S +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc32/makecontext.S 2014-05-28 12:25:49.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc32/makecontext.S 2014-05-28 12:25:51.000000000 -0500 +@@ -47,7 +47,9 @@ + #ifdef PIC + mflr r0 + cfi_register(lr,r0) +- bl 1f ++ /* Use this conditional form of branch and link to avoid destroying ++ the cpu link stack used to predict blr return addresses. */ ++ bcl 20,31,1f + 1: mflr r6 + addi r6,r6,L(exitcode)-1b + mtlr r0 +@@ -136,7 +138,9 @@ + #ifdef PIC + mflr r0 + cfi_register(lr,r0) +- bl 1f ++ /* Use this conditional form of branch and link to avoid destroying ++ the cpu link stack used to predict blr return addresses. */ ++ bcl 20,31,1f + 1: mflr r6 + addi r6,r6,L(novec_exitcode)-1b + mtlr r0 +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S 2014-05-28 12:25:49.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S 2014-05-28 12:25:51.000000000 -0500 +@@ -124,8 +124,10 @@ + + /* If the target function returns we need to do some cleanup. We use a + code trick to get the address of our cleanup function into the link +- register. Do not add any code between here and L(exitcode). */ +- bl L(gotexitcodeaddr); ++ register. Do not add any code between here and L(exitcode). ++ Use this conditional form of branch and link to avoid destroying ++ the cpu link stack used to predict blr return addresses. */ ++ bcl 20,31,L(gotexitcodeaddr); + + /* This is the helper code which gets called if a function which + is registered with 'makecontext' returns. In this case we diff --git a/SOURCES/glibc-ppc64le-25.patch b/SOURCES/glibc-ppc64le-25.patch new file mode 100644 index 0000000..144d3f3 --- /dev/null +++ b/SOURCES/glibc-ppc64le-25.patch @@ -0,0 +1,411 @@ +# commit db9b4570c5dc550074140ac1d1677077fba29a26 +# Author: Alan Modra +# Date: Sat Aug 17 18:40:11 2013 +0930 +# +# PowerPC LE strlen +# http://sourceware.org/ml/libc-alpha/2013-08/msg00097.html +# +# This is the first of nine patches adding little-endian support to the +# existing optimised string and memory functions. I did spend some +# time with a power7 simulator looking at cycle by cycle behaviour for +# memchr, but most of these patches have not been run on cpu simulators +# to check that we are going as fast as possible. I'm sure PowerPC can +# do better. However, the little-endian support mostly leaves main +# loops unchanged, so I'm banking on previous authors having done a +# good job on big-endian.. As with most code you stare at long enough, +# I found some improvements for big-endian too. +# +# Little-endian support for strlen. Like most of the string functions, +# I leave the main word or multiple-word loops substantially unchanged, +# just needing to modify the tail. +# +# Removing the branch in the power7 functions is just a tidy. .align +# produces a branch anyway. Modifying regs in the non-power7 functions +# is to suit the new little-endian tail. +# +# * sysdeps/powerpc/powerpc64/power7/strlen.S (strlen): Add little-endian +# support. Don't branch over align. +# * sysdeps/powerpc/powerpc32/power7/strlen.S: Likewise. +# * sysdeps/powerpc/powerpc64/strlen.S (strlen): Add little-endian support. +# Rearrange tmp reg use to suit. Comment. +# * sysdeps/powerpc/powerpc32/strlen.S: Likewise. +# +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strlen.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strlen.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strlen.S 2014-05-28 12:28:44.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strlen.S 2014-05-28 12:28:45.000000000 -0500 +@@ -31,7 +31,11 @@ + li r0,0 /* Word with null chars to use with cmpb. */ + li r5,-1 /* MASK = 0xffffffffffffffff. */ + lwz r12,0(r4) /* Load word from memory. */ ++#ifdef __LITTLE_ENDIAN__ ++ slw r5,r5,r6 ++#else + srw r5,r5,r6 /* MASK = MASK >> padding. */ ++#endif + orc r9,r12,r5 /* Mask bits that are not part of the string. */ + cmpb r10,r9,r0 /* Check for null bytes in WORD1. */ + cmpwi cr7,r10,0 /* If r10 == 0, no null's have been found. */ +@@ -49,9 +53,6 @@ + cmpb r10,r12,r0 + cmpwi cr7,r10,0 + bne cr7,L(done) +- b L(loop) /* We branch here (rather than falling through) +- to skip the nops due to heavy alignment +- of the loop below. */ + + /* Main loop to look for the end of the string. Since it's a + small loop (< 8 instructions), align it to 32-bytes. */ +@@ -88,9 +89,15 @@ + 0xff in the same position as the null byte in the original + word from the string. Use that to calculate the length. */ + L(done): +- cntlzw r0,r10 /* Count leading zeroes before the match. */ ++#ifdef __LITTLE_ENDIAN__ ++ addi r9, r10, -1 /* Form a mask from trailing zeros. */ ++ andc r9, r9, r10 ++ popcntw r0, r9 /* Count the bits in the mask. */ ++#else ++ cntlzw r0,r10 /* Count leading zeros before the match. */ ++#endif + subf r5,r3,r4 +- srwi r0,r0,3 /* Convert leading zeroes to bytes. */ ++ srwi r0,r0,3 /* Convert leading zeros to bytes. */ + add r3,r5,r0 /* Compute final length. */ + blr + END (BP_SYM (strlen)) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/strlen.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/strlen.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/strlen.S 2014-05-28 12:28:44.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/strlen.S 2014-05-28 12:32:24.000000000 -0500 +@@ -31,7 +31,12 @@ + 1 is subtracted you get a value in the range 0x00-0x7f, none of which + have their high bit set. The expression here is + (x + 0xfefefeff) & ~(x | 0x7f7f7f7f), which gives 0x00000000 when +- there were no 0x00 bytes in the word. ++ there were no 0x00 bytes in the word. You get 0x80 in bytes that ++ match, but possibly false 0x80 matches in the next more significant ++ byte to a true match due to carries. For little-endian this is ++ of no consequence since the least significant match is the one ++ we're interested in, but big-endian needs method 2 to find which ++ byte matches. + + 2) Given a word 'x', we can test to see _which_ byte was zero by + calculating ~(((x & 0x7f7f7f7f) + 0x7f7f7f7f) | x | 0x7f7f7f7f). +@@ -74,7 +79,7 @@ + + ENTRY (BP_SYM (strlen)) + +-#define rTMP1 r0 ++#define rTMP4 r0 + #define rRTN r3 /* incoming STR arg, outgoing result */ + #define rSTR r4 /* current string position */ + #define rPADN r5 /* number of padding bits we prepend to the +@@ -84,9 +89,9 @@ + #define rWORD1 r8 /* current string word */ + #define rWORD2 r9 /* next string word */ + #define rMASK r9 /* mask for first string word */ +-#define rTMP2 r10 +-#define rTMP3 r11 +-#define rTMP4 r12 ++#define rTMP1 r10 ++#define rTMP2 r11 ++#define rTMP3 r12 + + CHECK_BOUNDS_LOW (rRTN, rTMP1, rTMP2) + +@@ -96,15 +101,20 @@ + lwz rWORD1, 0(rSTR) + li rMASK, -1 + addi r7F7F, r7F7F, 0x7f7f +-/* That's the setup done, now do the first pair of words. +- We make an exception and use method (2) on the first two words, to reduce +- overhead. */ ++/* We use method (2) on the first two words, because rFEFE isn't ++ required which reduces setup overhead. Also gives a faster return ++ for small strings on big-endian due to needing to recalculate with ++ method (2) anyway. */ ++#ifdef __LITTLE_ENDIAN__ ++ slw rMASK, rMASK, rPADN ++#else + srw rMASK, rMASK, rPADN ++#endif + and rTMP1, r7F7F, rWORD1 + or rTMP2, r7F7F, rWORD1 + add rTMP1, rTMP1, r7F7F +- nor rTMP1, rTMP2, rTMP1 +- and. rWORD1, rTMP1, rMASK ++ nor rTMP3, rTMP2, rTMP1 ++ and. rTMP3, rTMP3, rMASK + mtcrf 0x01, rRTN + bne L(done0) + lis rFEFE, -0x101 +@@ -113,11 +123,12 @@ + bt 29, L(loop) + + /* Handle second word of pair. */ ++/* Perhaps use method (1) here for little-endian, saving one instruction? */ + lwzu rWORD1, 4(rSTR) + and rTMP1, r7F7F, rWORD1 + or rTMP2, r7F7F, rWORD1 + add rTMP1, rTMP1, r7F7F +- nor. rWORD1, rTMP2, rTMP1 ++ nor. rTMP3, rTMP2, rTMP1 + bne L(done0) + + /* The loop. */ +@@ -131,29 +142,53 @@ + add rTMP3, rFEFE, rWORD2 + nor rTMP4, r7F7F, rWORD2 + bne L(done1) +- and. rTMP1, rTMP3, rTMP4 ++ and. rTMP3, rTMP3, rTMP4 + beq L(loop) + ++#ifndef __LITTLE_ENDIAN__ + and rTMP1, r7F7F, rWORD2 + add rTMP1, rTMP1, r7F7F +- andc rWORD1, rTMP4, rTMP1 ++ andc rTMP3, rTMP4, rTMP1 + b L(done0) + + L(done1): + and rTMP1, r7F7F, rWORD1 + subi rSTR, rSTR, 4 + add rTMP1, rTMP1, r7F7F +- andc rWORD1, rTMP2, rTMP1 ++ andc rTMP3, rTMP2, rTMP1 + + /* When we get to here, rSTR points to the first word in the string that +- contains a zero byte, and the most significant set bit in rWORD1 is in that +- byte. */ ++ contains a zero byte, and rTMP3 has 0x80 for bytes that are zero, ++ and 0x00 otherwise. */ + L(done0): +- cntlzw rTMP3, rWORD1 ++ cntlzw rTMP3, rTMP3 + subf rTMP1, rRTN, rSTR + srwi rTMP3, rTMP3, 3 + add rRTN, rTMP1, rTMP3 + /* GKM FIXME: check high bound. */ + blr ++#else ++ ++L(done0): ++ addi rTMP1, rTMP3, -1 /* Form a mask from trailing zeros. */ ++ andc rTMP1, rTMP1, rTMP3 ++ cntlzw rTMP1, rTMP1 /* Count bits not in the mask. */ ++ subf rTMP3, rRTN, rSTR ++ subfic rTMP1, rTMP1, 32-7 ++ srwi rTMP1, rTMP1, 3 ++ add rRTN, rTMP1, rTMP3 ++ blr ++ ++L(done1): ++ addi rTMP3, rTMP1, -1 ++ andc rTMP3, rTMP3, rTMP1 ++ cntlzw rTMP3, rTMP3 ++ subf rTMP1, rRTN, rSTR ++ subfic rTMP3, rTMP3, 32-7-32 ++ srawi rTMP3, rTMP3, 3 ++ add rRTN, rTMP1, rTMP3 ++ blr ++#endif ++ + END (BP_SYM (strlen)) + libc_hidden_builtin_def (strlen) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strlen.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strlen.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strlen.S 2014-05-28 12:28:44.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strlen.S 2014-05-28 12:28:45.000000000 -0500 +@@ -32,7 +32,11 @@ + with cmpb. */ + li r5,-1 /* MASK = 0xffffffffffffffff. */ + ld r12,0(r4) /* Load doubleword from memory. */ ++#ifdef __LITTLE_ENDIAN__ ++ sld r5,r5,r6 ++#else + srd r5,r5,r6 /* MASK = MASK >> padding. */ ++#endif + orc r9,r12,r5 /* Mask bits that are not part of the string. */ + cmpb r10,r9,r0 /* Check for null bytes in DWORD1. */ + cmpdi cr7,r10,0 /* If r10 == 0, no null's have been found. */ +@@ -50,9 +54,6 @@ + cmpb r10,r12,r0 + cmpdi cr7,r10,0 + bne cr7,L(done) +- b L(loop) /* We branch here (rather than falling through) +- to skip the nops due to heavy alignment +- of the loop below. */ + + /* Main loop to look for the end of the string. Since it's a + small loop (< 8 instructions), align it to 32-bytes. */ +@@ -89,9 +90,15 @@ + 0xff in the same position as the null byte in the original + doubleword from the string. Use that to calculate the length. */ + L(done): +- cntlzd r0,r10 /* Count leading zeroes before the match. */ ++#ifdef __LITTLE_ENDIAN__ ++ addi r9, r10, -1 /* Form a mask from trailing zeros. */ ++ andc r9, r9, r10 ++ popcntd r0, r9 /* Count the bits in the mask. */ ++#else ++ cntlzd r0,r10 /* Count leading zeros before the match. */ ++#endif + subf r5,r3,r4 +- srdi r0,r0,3 /* Convert leading zeroes to bytes. */ ++ srdi r0,r0,3 /* Convert leading/trailing zeros to bytes. */ + add r3,r5,r0 /* Compute final length. */ + blr + END (BP_SYM (strlen)) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/strlen.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/strlen.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/strlen.S 2014-05-28 12:28:44.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/strlen.S 2014-05-28 12:38:17.000000000 -0500 +@@ -31,7 +31,12 @@ + 1 is subtracted you get a value in the range 0x00-0x7f, none of which + have their high bit set. The expression here is + (x + 0xfefefeff) & ~(x | 0x7f7f7f7f), which gives 0x00000000 when +- there were no 0x00 bytes in the word. ++ there were no 0x00 bytes in the word. You get 0x80 in bytes that ++ match, but possibly false 0x80 matches in the next more significant ++ byte to a true match due to carries. For little-endian this is ++ of no consequence since the least significant match is the one ++ we're interested in, but big-endian needs method 2 to find which ++ byte matches. + + 2) Given a word 'x', we can test to see _which_ byte was zero by + calculating ~(((x & 0x7f7f7f7f) + 0x7f7f7f7f) | x | 0x7f7f7f7f). +@@ -64,7 +69,7 @@ + Answer: + 1) Added a Data Cache Block Touch early to prefetch the first 128 + byte cache line. Adding dcbt instructions to the loop would not be +- effective since most strings will be shorter than the cache line.*/ ++ effective since most strings will be shorter than the cache line. */ + + /* Some notes on register usage: Under the SVR4 ABI, we can use registers + 0 and 3 through 12 (so long as we don't call any procedures) without +@@ -80,7 +85,7 @@ + ENTRY (BP_SYM (strlen)) + CALL_MCOUNT 1 + +-#define rTMP1 r0 ++#define rTMP4 r0 + #define rRTN r3 /* incoming STR arg, outgoing result */ + #define rSTR r4 /* current string position */ + #define rPADN r5 /* number of padding bits we prepend to the +@@ -90,9 +95,9 @@ + #define rWORD1 r8 /* current string doubleword */ + #define rWORD2 r9 /* next string doubleword */ + #define rMASK r9 /* mask for first string doubleword */ +-#define rTMP2 r10 +-#define rTMP3 r11 +-#define rTMP4 r12 ++#define rTMP1 r10 ++#define rTMP2 r11 ++#define rTMP3 r12 + + /* Note: The Bounded pointer support in this code is broken. This code + was inherited from PPC32 and that support was never completed. +@@ -109,30 +114,36 @@ + addi r7F7F, r7F7F, 0x7f7f + li rMASK, -1 + insrdi r7F7F, r7F7F, 32, 0 +-/* That's the setup done, now do the first pair of doublewords. +- We make an exception and use method (2) on the first two doublewords, +- to reduce overhead. */ +- srd rMASK, rMASK, rPADN ++/* We use method (2) on the first two doublewords, because rFEFE isn't ++ required which reduces setup overhead. Also gives a faster return ++ for small strings on big-endian due to needing to recalculate with ++ method (2) anyway. */ ++#ifdef __LITTLE_ENDIAN__ ++ sld rMASK, rMASK, rPADN ++#else ++ srd rMASK, rMASK, rPADN ++#endif + and rTMP1, r7F7F, rWORD1 + or rTMP2, r7F7F, rWORD1 + lis rFEFE, -0x101 + add rTMP1, rTMP1, r7F7F + addi rFEFE, rFEFE, -0x101 +- nor rTMP1, rTMP2, rTMP1 +- and. rWORD1, rTMP1, rMASK ++ nor rTMP3, rTMP2, rTMP1 ++ and. rTMP3, rTMP3, rMASK + mtcrf 0x01, rRTN + bne L(done0) +- sldi rTMP1, rFEFE, 32 +- add rFEFE, rFEFE, rTMP1 ++ sldi rTMP1, rFEFE, 32 ++ add rFEFE, rFEFE, rTMP1 + /* Are we now aligned to a doubleword boundary? */ + bt 28, L(loop) + + /* Handle second doubleword of pair. */ ++/* Perhaps use method (1) here for little-endian, saving one instruction? */ + ldu rWORD1, 8(rSTR) + and rTMP1, r7F7F, rWORD1 + or rTMP2, r7F7F, rWORD1 + add rTMP1, rTMP1, r7F7F +- nor. rWORD1, rTMP2, rTMP1 ++ nor. rTMP3, rTMP2, rTMP1 + bne L(done0) + + /* The loop. */ +@@ -146,29 +157,53 @@ + add rTMP3, rFEFE, rWORD2 + nor rTMP4, r7F7F, rWORD2 + bne L(done1) +- and. rTMP1, rTMP3, rTMP4 ++ and. rTMP3, rTMP3, rTMP4 + beq L(loop) + ++#ifndef __LITTLE_ENDIAN__ + and rTMP1, r7F7F, rWORD2 + add rTMP1, rTMP1, r7F7F +- andc rWORD1, rTMP4, rTMP1 ++ andc rTMP3, rTMP4, rTMP1 + b L(done0) + + L(done1): + and rTMP1, r7F7F, rWORD1 + subi rSTR, rSTR, 8 + add rTMP1, rTMP1, r7F7F +- andc rWORD1, rTMP2, rTMP1 ++ andc rTMP3, rTMP2, rTMP1 + + /* When we get to here, rSTR points to the first doubleword in the string that +- contains a zero byte, and the most significant set bit in rWORD1 is in that +- byte. */ ++ contains a zero byte, and rTMP3 has 0x80 for bytes that are zero, and 0x00 ++ otherwise. */ + L(done0): +- cntlzd rTMP3, rWORD1 ++ cntlzd rTMP3, rTMP3 + subf rTMP1, rRTN, rSTR + srdi rTMP3, rTMP3, 3 + add rRTN, rTMP1, rTMP3 + /* GKM FIXME: check high bound. */ + blr ++#else ++ ++L(done0): ++ addi rTMP1, rTMP3, -1 /* Form a mask from trailing zeros. */ ++ andc rTMP1, rTMP1, rTMP3 ++ cntlzd rTMP1, rTMP1 /* Count bits not in the mask. */ ++ subf rTMP3, rRTN, rSTR ++ subfic rTMP1, rTMP1, 64-7 ++ srdi rTMP1, rTMP1, 3 ++ add rRTN, rTMP1, rTMP3 ++ blr ++ ++L(done1): ++ addi rTMP3, rTMP1, -1 ++ andc rTMP3, rTMP3, rTMP1 ++ cntlzd rTMP3, rTMP3 ++ subf rTMP1, rRTN, rSTR ++ subfic rTMP3, rTMP3, 64-7-64 ++ sradi rTMP3, rTMP3, 3 ++ add rRTN, rTMP1, rTMP3 ++ blr ++#endif ++ + END (BP_SYM (strlen)) + libc_hidden_builtin_def (strlen) diff --git a/SOURCES/glibc-ppc64le-26.patch b/SOURCES/glibc-ppc64le-26.patch new file mode 100644 index 0000000..93fd255 --- /dev/null +++ b/SOURCES/glibc-ppc64le-26.patch @@ -0,0 +1,379 @@ +# commit 33ee81de05e83ce12f32a491270bb4c1611399c7 +# Author: Alan Modra +# Date: Sat Aug 17 18:40:48 2013 +0930 +# +# PowerPC LE strnlen +# http://sourceware.org/ml/libc-alpha/2013-08/msg00098.html +# +# The existing strnlen code has a number of defects, so this patch is more +# than just adding little-endian support. The changes here are similar to +# those for memchr. +# +# * sysdeps/powerpc/powerpc64/power7/strnlen.S (strnlen): Add +# little-endian support. Remove unnecessary "are we done" tests. +# Handle "s" wrapping around zero and extremely large "size". +# Correct main loop count. Handle single left-over word from main +# loop inline rather than by using small_loop. Correct comments. +# Delete "zero" tail, use "end_max" instead. +# * sysdeps/powerpc/powerpc32/power7/strnlen.S: Likewise. +# +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strnlen.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strnlen.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strnlen.S 2014-05-28 12:40:17.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strnlen.S 2014-05-28 12:44:52.000000000 -0500 +@@ -30,51 +30,47 @@ + add r7,r3,r4 /* Calculate the last acceptable address. */ + cmplwi r4,16 + li r0,0 /* Word with null chars. */ ++ addi r7,r7,-1 + ble L(small_range) + +- cmplw cr7,r3,r7 /* Is the address equal or less than r3? If +- it's equal or less, it means size is either 0 +- or a negative number. */ +- ble cr7,L(proceed) +- +- li r7,-1 /* Make r11 the biggest if r4 <= 0. */ +-L(proceed): + rlwinm r6,r3,3,27,28 /* Calculate padding. */ + lwz r12,0(r8) /* Load word from memory. */ + cmpb r10,r12,r0 /* Check for null bytes in DWORD1. */ ++#ifdef __LITTLE_ENDIAN__ ++ srw r10,r10,r6 ++ slw r10,r10,r6 ++#else + slw r10,r10,r6 + srw r10,r10,r6 ++#endif + cmplwi cr7,r10,0 /* If r10 == 0, no null's have been found. */ + bne cr7,L(done) + +- /* Are we done already? */ +- addi r9,r8,4 +- cmplw cr6,r9,r7 +- bge cr6,L(end_max) +- ++ clrrwi r7,r7,2 /* Address of last word. */ + mtcrf 0x01,r8 + /* Are we now aligned to a doubleword boundary? If so, skip to + the main loop. Otherwise, go through the alignment code. */ + + bt 29,L(loop_setup) + +- /* Handle DWORD2 of pair. */ ++ /* Handle WORD2 of pair. */ + lwzu r12,4(r8) + cmpb r10,r12,r0 + cmplwi cr7,r10,0 + bne cr7,L(done) + +- /* Are we done already? */ +- addi r9,r8,4 +- cmplw cr6,r9,r7 +- bge cr6,L(end_max) +- + L(loop_setup): +- sub r5,r7,r9 ++ /* The last word we want to read in the loop below is the one ++ containing the last byte of the string, ie. the word at ++ (s + size - 1) & ~3, or r7. The first word read is at ++ r8 + 4, we read 2 * cnt words, so the last word read will ++ be at r8 + 4 + 8 * cnt - 4. Solving for cnt gives ++ cnt = (r7 - r8) / 8 */ ++ sub r5,r7,r8 + srwi r6,r5,3 /* Number of loop iterations. */ + mtctr r6 /* Setup the counter. */ +- b L(loop) +- /* Main loop to look for the null byte backwards in the string. Since ++ ++ /* Main loop to look for the null byte in the string. Since + it's a small loop (< 8 instructions), align it to 32-bytes. */ + .p2align 5 + L(loop): +@@ -90,15 +86,18 @@ + cmplwi cr7,r5,0 + bne cr7,L(found) + bdnz L(loop) +- /* We're here because the counter reached 0, and that means we +- didn't have any matches for null in the whole range. Just return +- the original size. */ +- addi r9,r8,4 +- cmplw cr6,r9,r7 +- blt cr6,L(loop_small) ++ ++ /* We may have one more word to read. */ ++ cmplw cr6,r8,r7 ++ beq cr6,L(end_max) ++ ++ lwzu r12,4(r8) ++ cmpb r10,r12,r0 ++ cmplwi cr6,r10,0 ++ bne cr6,L(done) + + L(end_max): +- sub r3,r7,r3 ++ mr r3,r4 + blr + + /* OK, one (or both) of the words contains a null byte. Check +@@ -123,49 +122,56 @@ + We need to make sure the null char is *before* the end of the + range. */ + L(done): +- cntlzw r0,r10 /* Count leading zeroes before the match. */ +- srwi r0,r0,3 /* Convert leading zeroes to bytes. */ +- add r9,r8,r0 +- sub r6,r9,r3 /* Length until the match. */ +- cmplw r9,r7 +- bgt L(end_max) +- mr r3,r6 +- blr +- +- .align 4 +-L(zero): +- li r3,0 ++#ifdef __LITTLE_ENDIAN__ ++ addi r0,r10,-1 ++ andc r0,r0,r10 ++ popcntw r0,r0 ++#else ++ cntlzw r0,r10 /* Count leading zeros before the match. */ ++#endif ++ sub r3,r8,r3 ++ srwi r0,r0,3 /* Convert leading/trailing zeros to bytes. */ ++ add r3,r3,r0 /* Length until the match. */ ++ cmplw r3,r4 ++ blelr ++ mr r3,r4 + blr + +-/* Deals with size <= 32. */ ++/* Deals with size <= 16. */ + .align 4 + L(small_range): + cmplwi r4,0 +- beq L(zero) ++ beq L(end_max) ++ ++ clrrwi r7,r7,2 /* Address of last word. */ + + rlwinm r6,r3,3,27,28 /* Calculate padding. */ + lwz r12,0(r8) /* Load word from memory. */ + cmpb r10,r12,r0 /* Check for null bytes in WORD1. */ ++#ifdef __LITTLE_ENDIAN__ ++ srw r10,r10,r6 ++ slw r10,r10,r6 ++#else + slw r10,r10,r6 + srw r10,r10,r6 ++#endif + cmplwi cr7,r10,0 + bne cr7,L(done) + +- addi r9,r8,4 +- cmplw r9,r7 +- bge L(end_max) +- b L(loop_small) ++ cmplw r8,r7 ++ beq L(end_max) + + .p2align 5 + L(loop_small): + lwzu r12,4(r8) + cmpb r10,r12,r0 +- addi r9,r8,4 + cmplwi cr6,r10,0 + bne cr6,L(done) +- cmplw r9,r7 +- bge L(end_max) +- b L(loop_small) ++ cmplw r8,r7 ++ bne L(loop_small) ++ mr r3,r4 ++ blr ++ + END (BP_SYM (__strnlen)) + weak_alias (BP_SYM (__strnlen), BP_SYM(strnlen)) + libc_hidden_builtin_def (strnlen) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strnlen.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strnlen.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strnlen.S 2014-05-28 12:40:17.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strnlen.S 2014-05-28 13:24:41.000000000 -0500 +@@ -26,33 +26,29 @@ + ENTRY (BP_SYM (__strnlen)) + CALL_MCOUNT 2 + dcbt 0,r3 +- clrrdi r8,r3,3 ++ clrrdi r8,r3,3 + add r7,r3,r4 /* Calculate the last acceptable address. */ + cmpldi r4,32 + li r0,0 /* Doubleword with null chars. */ ++ addi r7,r7,-1 ++ + /* If we have less than 33 bytes to search, skip to a faster code. */ + ble L(small_range) + +- cmpld cr7,r3,r7 /* Is the address equal or less than r3? If +- it's equal or less, it means size is either 0 +- or a negative number. */ +- ble cr7,L(proceed) +- +- li r7,-1 /* Make r11 the biggest if r4 <= 0. */ +-L(proceed): + rlwinm r6,r3,3,26,28 /* Calculate padding. */ + ld r12,0(r8) /* Load doubleword from memory. */ + cmpb r10,r12,r0 /* Check for null bytes in DWORD1. */ ++#ifdef __LITTLE_ENDIAN__ ++ srd r10,r10,r6 ++ sld r10,r10,r6 ++#else + sld r10,r10,r6 + srd r10,r10,r6 ++#endif + cmpldi cr7,r10,0 /* If r10 == 0, no null's have been found. */ + bne cr7,L(done) + +- /* Are we done already? */ +- addi r9,r8,8 +- cmpld cr6,r9,r7 +- bge cr6,L(end_max) +- ++ clrrdi r7,r7,3 /* Address of last doubleword. */ + mtcrf 0x01,r8 + /* Are we now aligned to a quadword boundary? If so, skip to + the main loop. Otherwise, go through the alignment code. */ +@@ -65,17 +61,18 @@ + cmpldi cr7,r10,0 + bne cr7,L(done) + +- /* Are we done already? */ +- addi r9,r8,8 +- cmpld cr6,r9,r7 +- bge cr6,L(end_max) +- + L(loop_setup): +- sub r5,r7,r9 ++ /* The last dword we want to read in the loop below is the one ++ containing the last byte of the string, ie. the dword at ++ (s + size - 1) & ~7, or r7. The first dword read is at ++ r8 + 8, we read 2 * cnt dwords, so the last dword read will ++ be at r8 + 8 + 16 * cnt - 8. Solving for cnt gives ++ cnt = (r7 - r8) / 16 */ ++ sub r5,r7,r8 + srdi r6,r5,4 /* Number of loop iterations. */ + mtctr r6 /* Setup the counter. */ +- b L(loop) +- /* Main loop to look for the null byte backwards in the string. Since ++ ++ /* Main loop to look for the null byte in the string. Since + it's a small loop (< 8 instructions), align it to 32-bytes. */ + .p2align 5 + L(loop): +@@ -91,15 +88,18 @@ + cmpldi cr7,r5,0 + bne cr7,L(found) + bdnz L(loop) +- /* We're here because the counter reached 0, and that means we +- didn't have any matches for null in the whole range. Just return +- the original size. */ +- addi r9,r8,8 +- cmpld cr6,r9,r7 +- blt cr6,L(loop_small) ++ ++ /* We may have one more dword to read. */ ++ cmpld cr6,r8,r7 ++ beq cr6,L(end_max) ++ ++ ldu r12,8(r8) ++ cmpb r10,r12,r0 ++ cmpldi cr6,r10,0 ++ bne cr6,L(done) + + L(end_max): +- sub r3,r7,r3 ++ mr r3,r4 + blr + + /* OK, one (or both) of the doublewords contains a null byte. Check +@@ -121,52 +121,59 @@ + /* r10 has the output of the cmpb instruction, that is, it contains + 0xff in the same position as the null byte in the original + doubleword from the string. Use that to calculate the length. +- We need to make sure the null char is *before* the start of the +- range (since we're going backwards). */ ++ We need to make sure the null char is *before* the end of the ++ range. */ + L(done): +- cntlzd r0,r10 /* Count leading zeroes before the match. */ +- srdi r0,r0,3 /* Convert leading zeroes to bytes. */ +- add r9,r8,r0 +- sub r6,r9,r3 /* Length until the match. */ +- cmpld r9,r7 +- bgt L(end_max) +- mr r3,r6 +- blr +- +- .align 4 +-L(zero): +- li r3,0 ++#ifdef __LITTLE_ENDIAN__ ++ addi r0,r10,-1 ++ andc r0,r0,r10 ++ popcntd r0,r0 ++#else ++ cntlzd r0,r10 /* Count leading zeros before the match. */ ++#endif ++ sub r3,r8,r3 ++ srdi r0,r0,3 /* Convert leading/trailing zeros to bytes. */ ++ add r3,r3,r0 /* Length until the match. */ ++ cmpld r3,r4 ++ blelr ++ mr r3,r4 + blr + + /* Deals with size <= 32. */ + .align 4 + L(small_range): + cmpldi r4,0 +- beq L(zero) ++ beq L(end_max) ++ ++ clrrdi r7,r7,3 /* Address of last doubleword. */ + + rlwinm r6,r3,3,26,28 /* Calculate padding. */ +- ld r12,0(r8) /* Load word from memory. */ ++ ld r12,0(r8) /* Load doubleword from memory. */ + cmpb r10,r12,r0 /* Check for null bytes in DWORD1. */ ++#ifdef __LITTLE_ENDIAN__ ++ srd r10,r10,r6 ++ sld r10,r10,r6 ++#else + sld r10,r10,r6 + srd r10,r10,r6 ++#endif + cmpldi cr7,r10,0 + bne cr7,L(done) + +- addi r9,r8,8 +- cmpld r9,r7 +- bge L(end_max) +- b L(loop_small) ++ cmpld r8,r7 ++ beq L(end_max) + + .p2align 5 + L(loop_small): + ldu r12,8(r8) + cmpb r10,r12,r0 +- addi r9,r8,8 + cmpldi cr6,r10,0 + bne cr6,L(done) +- cmpld r9,r7 +- bge L(end_max) +- b L(loop_small) ++ cmpld r8,r7 ++ bne L(loop_small) ++ mr r3,r4 ++ blr ++ + END (BP_SYM (__strnlen)) + weak_alias (BP_SYM (__strnlen), BP_SYM(strnlen)) + libc_hidden_builtin_def (strnlen) diff --git a/SOURCES/glibc-ppc64le-27.patch b/SOURCES/glibc-ppc64le-27.patch new file mode 100644 index 0000000..83ca794 --- /dev/null +++ b/SOURCES/glibc-ppc64le-27.patch @@ -0,0 +1,861 @@ +# commit 8a7413f9b036da83ffde491a37d9d2340bc321a7 +# Author: Alan Modra +# Date: Sat Aug 17 18:41:17 2013 +0930 +# +# PowerPC LE strcmp and strncmp +# http://sourceware.org/ml/libc-alpha/2013-08/msg00099.html +# +# More little-endian support. I leave the main strcmp loops unchanged, +# (well, except for renumbering rTMP to something other than r0 since +# it's needed in an addi insn) and modify the tail for little-endian. +# +# I noticed some of the big-endian tail code was a little untidy so have +# cleaned that up too. +# +# * sysdeps/powerpc/powerpc64/strcmp.S (rTMP2): Define as r0. +# (rTMP): Define as r11. +# (strcmp): Add little-endian support. Optimise tail. +# * sysdeps/powerpc/powerpc32/strcmp.S: Similarly. +# * sysdeps/powerpc/powerpc64/strncmp.S: Likewise. +# * sysdeps/powerpc/powerpc32/strncmp.S: Likewise. +# * sysdeps/powerpc/powerpc64/power4/strncmp.S: Likewise. +# * sysdeps/powerpc/powerpc32/power4/strncmp.S: Likewise. +# * sysdeps/powerpc/powerpc64/power7/strncmp.S: Likewise. +# * sysdeps/powerpc/powerpc32/power7/strncmp.S: Likewise. +# +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/strncmp.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/strncmp.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/strncmp.S 2014-05-28 13:26:59.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/strncmp.S 2014-05-28 13:27:02.000000000 -0500 +@@ -26,7 +26,7 @@ + + EALIGN (BP_SYM(strncmp), 4, 0) + +-#define rTMP r0 ++#define rTMP2 r0 + #define rRTN r3 + #define rSTR1 r3 /* first string arg */ + #define rSTR2 r4 /* second string arg */ +@@ -42,6 +42,7 @@ + #define r7F7F r9 /* constant 0x7f7f7f7f */ + #define rNEG r10 /* ~(word in s1 | 0x7f7f7f7f) */ + #define rBITDIF r11 /* bits that differ in s1 & s2 words */ ++#define rTMP r12 + + dcbt 0,rSTR1 + or rTMP, rSTR2, rSTR1 +@@ -80,12 +81,45 @@ + we don't compare two strings as different because of gunk beyond + the end of the strings... */ + ++#ifdef __LITTLE_ENDIAN__ ++L(endstring): ++ slwi rTMP, rTMP, 1 ++ addi rTMP2, rTMP, -1 ++ andc rTMP2, rTMP2, rTMP ++ and rWORD2, rWORD2, rTMP2 /* Mask off gunk. */ ++ and rWORD1, rWORD1, rTMP2 ++ rlwinm rTMP2, rWORD2, 8, 0xffffffff /* Byte reverse word. */ ++ rlwinm rTMP, rWORD1, 8, 0xffffffff ++ rldimi rTMP2, rWORD2, 24, 32 ++ rldimi rTMP, rWORD1, 24, 32 ++ rlwimi rTMP2, rWORD2, 24, 16, 23 ++ rlwimi rTMP, rWORD1, 24, 16, 23 ++ xor. rBITDIF, rTMP, rTMP2 ++ sub rRTN, rTMP, rTMP2 ++ bgelr+ ++ ori rRTN, rTMP2, 1 ++ blr ++ ++L(different): ++ lwz rWORD1, -4(rSTR1) ++ rlwinm rTMP2, rWORD2, 8, 0xffffffff /* Byte reverse word. */ ++ rlwinm rTMP, rWORD1, 8, 0xffffffff ++ rldimi rTMP2, rWORD2, 24, 32 ++ rldimi rTMP, rWORD1, 24, 32 ++ rlwimi rTMP2, rWORD2, 24, 16, 23 ++ rlwimi rTMP, rWORD1, 24, 16, 23 ++ xor. rBITDIF, rTMP, rTMP2 ++ sub rRTN, rTMP, rTMP2 ++ bgelr+ ++ ori rRTN, rTMP2, 1 ++ blr ++ ++#else + L(endstring): + and rTMP, r7F7F, rWORD1 + beq cr1, L(equal) + add rTMP, rTMP, r7F7F + xor. rBITDIF, rWORD1, rWORD2 +- + andc rNEG, rNEG, rTMP + blt- L(highbit) + cntlzw rBITDIF, rBITDIF +@@ -93,28 +127,20 @@ + addi rNEG, rNEG, 7 + cmpw cr1, rNEG, rBITDIF + sub rRTN, rWORD1, rWORD2 +- blt- cr1, L(equal) +- srawi rRTN, rRTN, 31 +- ori rRTN, rRTN, 1 +- blr ++ bgelr+ cr1 + L(equal): + li rRTN, 0 + blr + + L(different): +- lwzu rWORD1, -4(rSTR1) ++ lwz rWORD1, -4(rSTR1) + xor. rBITDIF, rWORD1, rWORD2 + sub rRTN, rWORD1, rWORD2 +- blt- L(highbit) +- srawi rRTN, rRTN, 31 +- ori rRTN, rRTN, 1 +- blr ++ bgelr+ + L(highbit): +- srwi rWORD2, rWORD2, 24 +- srwi rWORD1, rWORD1, 24 +- sub rRTN, rWORD1, rWORD2 ++ ori rRTN, rWORD2, 1 + blr +- ++#endif + + /* Oh well. In this case, we just do a byte-by-byte comparison. */ + .align 4 +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strncmp.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strncmp.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strncmp.S 2014-05-28 13:26:59.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strncmp.S 2014-05-28 13:27:02.000000000 -0500 +@@ -28,7 +28,7 @@ + + EALIGN (BP_SYM(strncmp),5,0) + +-#define rTMP r0 ++#define rTMP2 r0 + #define rRTN r3 + #define rSTR1 r3 /* first string arg */ + #define rSTR2 r4 /* second string arg */ +@@ -44,6 +44,7 @@ + #define r7F7F r9 /* constant 0x7f7f7f7f */ + #define rNEG r10 /* ~(word in s1 | 0x7f7f7f7f) */ + #define rBITDIF r11 /* bits that differ in s1 & s2 words */ ++#define rTMP r12 + + dcbt 0,rSTR1 + nop +@@ -83,13 +84,45 @@ + /* OK. We've hit the end of the string. We need to be careful that + we don't compare two strings as different because of gunk beyond + the end of the strings... */ ++#ifdef __LITTLE_ENDIAN__ ++L(endstring): ++ slwi rTMP, rTMP, 1 ++ addi rTMP2, rTMP, -1 ++ andc rTMP2, rTMP2, rTMP ++ and rWORD2, rWORD2, rTMP2 /* Mask off gunk. */ ++ and rWORD1, rWORD1, rTMP2 ++ rlwinm rTMP2, rWORD2, 8, 0xffffffff /* Byte reverse word. */ ++ rlwinm rTMP, rWORD1, 8, 0xffffffff ++ rldimi rTMP2, rWORD2, 24, 32 ++ rldimi rTMP, rWORD1, 24, 32 ++ rlwimi rTMP2, rWORD2, 24, 16, 23 ++ rlwimi rTMP, rWORD1, 24, 16, 23 ++ xor. rBITDIF, rTMP, rTMP2 ++ sub rRTN, rTMP, rTMP2 ++ bgelr ++ ori rRTN, rTMP2, 1 ++ blr ++ ++L(different): ++ lwz rWORD1, -4(rSTR1) ++ rlwinm rTMP2, rWORD2, 8, 0xffffffff /* Byte reverse word. */ ++ rlwinm rTMP, rWORD1, 8, 0xffffffff ++ rldimi rTMP2, rWORD2, 24, 32 ++ rldimi rTMP, rWORD1, 24, 32 ++ rlwimi rTMP2, rWORD2, 24, 16, 23 ++ rlwimi rTMP, rWORD1, 24, 16, 23 ++ xor. rBITDIF, rTMP, rTMP2 ++ sub rRTN, rTMP, rTMP2 ++ bgelr ++ ori rRTN, rTMP2, 1 ++ blr + ++#else + L(endstring): + and rTMP,r7F7F,rWORD1 + beq cr1,L(equal) + add rTMP,rTMP,r7F7F + xor. rBITDIF,rWORD1,rWORD2 +- + andc rNEG,rNEG,rTMP + blt L(highbit) + cntlzw rBITDIF,rBITDIF +@@ -97,28 +130,20 @@ + addi rNEG,rNEG,7 + cmpw cr1,rNEG,rBITDIF + sub rRTN,rWORD1,rWORD2 +- blt cr1,L(equal) +- srawi rRTN,rRTN,31 +- ori rRTN,rRTN,1 +- blr ++ bgelr cr1 + L(equal): + li rRTN,0 + blr + + L(different): +- lwzu rWORD1,-4(rSTR1) ++ lwz rWORD1,-4(rSTR1) + xor. rBITDIF,rWORD1,rWORD2 + sub rRTN,rWORD1,rWORD2 +- blt L(highbit) +- srawi rRTN,rRTN,31 +- ori rRTN,rRTN,1 +- blr ++ bgelr + L(highbit): +- srwi rWORD2,rWORD2,24 +- srwi rWORD1,rWORD1,24 +- sub rRTN,rWORD1,rWORD2 ++ ori rRTN, rWORD2, 1 + blr +- ++#endif + + /* Oh well. In this case, we just do a byte-by-byte comparison. */ + .align 4 +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/strcmp.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/strcmp.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/strcmp.S 2014-05-28 13:26:59.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/strcmp.S 2014-05-28 13:27:02.000000000 -0500 +@@ -26,7 +26,7 @@ + + EALIGN (BP_SYM (strcmp), 4, 0) + +-#define rTMP r0 ++#define rTMP2 r0 + #define rRTN r3 + #define rSTR1 r3 /* first string arg */ + #define rSTR2 r4 /* second string arg */ +@@ -40,6 +40,7 @@ + #define r7F7F r8 /* constant 0x7f7f7f7f */ + #define rNEG r9 /* ~(word in s1 | 0x7f7f7f7f) */ + #define rBITDIF r10 /* bits that differ in s1 & s2 words */ ++#define rTMP r11 + + CHECK_BOUNDS_LOW (rSTR1, rTMP, rHIGH1) + CHECK_BOUNDS_LOW (rSTR2, rTMP, rHIGH2) +@@ -64,10 +65,45 @@ + and. rTMP, rTMP, rNEG + cmpw cr1, rWORD1, rWORD2 + beq+ L(g0) +-L(endstring): ++ + /* OK. We've hit the end of the string. We need to be careful that + we don't compare two strings as different because of gunk beyond + the end of the strings... */ ++#ifdef __LITTLE_ENDIAN__ ++L(endstring): ++ addi rTMP2, rTMP, -1 ++ andc rTMP2, rTMP2, rTMP ++ rlwimi rTMP2, rTMP2, 1, 0, 30 ++ and rWORD2, rWORD2, rTMP2 /* Mask off gunk. */ ++ and rWORD1, rWORD1, rTMP2 ++ rlwinm rTMP2, rWORD2, 8, 0xffffffff /* Byte reverse word. */ ++ rlwinm rTMP, rWORD1, 8, 0xffffffff ++ rlwimi rTMP2, rWORD2, 24, 0, 7 ++ rlwimi rTMP, rWORD1, 24, 0, 7 ++ rlwimi rTMP2, rWORD2, 24, 16, 23 ++ rlwimi rTMP, rWORD1, 24, 16, 23 ++ xor. rBITDIF, rTMP, rTMP2 ++ sub rRTN, rTMP, rTMP2 ++ bgelr+ ++ ori rRTN, rTMP2, 1 ++ blr ++ ++L(different): ++ lwz rWORD1, -4(rSTR1) ++ rlwinm rTMP2, rWORD2, 8, 0xffffffff /* Byte reverse word. */ ++ rlwinm rTMP, rWORD1, 8, 0xffffffff ++ rlwimi rTMP2, rWORD2, 24, 0, 7 ++ rlwimi rTMP, rWORD1, 24, 0, 7 ++ rlwimi rTMP2, rWORD2, 24, 16, 23 ++ rlwimi rTMP, rWORD1, 24, 16, 23 ++ xor. rBITDIF, rTMP, rTMP2 ++ sub rRTN, rTMP, rTMP2 ++ bgelr+ ++ ori rRTN, rTMP2, 1 ++ blr ++ ++#else ++L(endstring): + and rTMP, r7F7F, rWORD1 + beq cr1, L(equal) + add rTMP, rTMP, r7F7F +@@ -94,7 +130,7 @@ + ori rRTN, rWORD2, 1 + /* GKM FIXME: check high bounds. */ + blr +- ++#endif + + /* Oh well. In this case, we just do a byte-by-byte comparison. */ + .align 4 +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/strncmp.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/strncmp.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/strncmp.S 2014-05-28 13:26:59.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/strncmp.S 2014-05-28 13:27:02.000000000 -0500 +@@ -26,7 +26,7 @@ + + EALIGN (BP_SYM(strncmp), 4, 0) + +-#define rTMP r0 ++#define rTMP2 r0 + #define rRTN r3 + #define rSTR1 r3 /* first string arg */ + #define rSTR2 r4 /* second string arg */ +@@ -40,6 +40,7 @@ + #define r7F7F r9 /* constant 0x7f7f7f7f */ + #define rNEG r10 /* ~(word in s1 | 0x7f7f7f7f) */ + #define rBITDIF r11 /* bits that differ in s1 & s2 words */ ++#define rTMP r12 + + dcbt 0,rSTR1 + or rTMP, rSTR2, rSTR1 +@@ -78,12 +79,45 @@ + we don't compare two strings as different because of gunk beyond + the end of the strings... */ + ++#ifdef __LITTLE_ENDIAN__ ++L(endstring): ++ slwi rTMP, rTMP, 1 ++ addi rTMP2, rTMP, -1 ++ andc rTMP2, rTMP2, rTMP ++ and rWORD2, rWORD2, rTMP2 /* Mask off gunk. */ ++ and rWORD1, rWORD1, rTMP2 ++ rlwinm rTMP2, rWORD2, 8, 0xffffffff /* Byte reverse word. */ ++ rlwinm rTMP, rWORD1, 8, 0xffffffff ++ rlwimi rTMP2, rWORD2, 24, 0, 7 ++ rlwimi rTMP, rWORD1, 24, 0, 7 ++ rlwimi rTMP2, rWORD2, 24, 16, 23 ++ rlwimi rTMP, rWORD1, 24, 16, 23 ++ xor. rBITDIF, rTMP, rTMP2 ++ sub rRTN, rTMP, rTMP2 ++ bgelr+ ++ ori rRTN, rTMP2, 1 ++ blr ++ ++L(different): ++ lwz rWORD1, -4(rSTR1) ++ rlwinm rTMP2, rWORD2, 8, 0xffffffff /* Byte reverse word. */ ++ rlwinm rTMP, rWORD1, 8, 0xffffffff ++ rlwimi rTMP2, rWORD2, 24, 0, 7 ++ rlwimi rTMP, rWORD1, 24, 0, 7 ++ rlwimi rTMP2, rWORD2, 24, 16, 23 ++ rlwimi rTMP, rWORD1, 24, 16, 23 ++ xor. rBITDIF, rTMP, rTMP2 ++ sub rRTN, rTMP, rTMP2 ++ bgelr+ ++ ori rRTN, rTMP2, 1 ++ blr ++ ++#else + L(endstring): + and rTMP, r7F7F, rWORD1 + beq cr1, L(equal) + add rTMP, rTMP, r7F7F + xor. rBITDIF, rWORD1, rWORD2 +- + andc rNEG, rNEG, rTMP + blt- L(highbit) + cntlzw rBITDIF, rBITDIF +@@ -91,28 +125,20 @@ + addi rNEG, rNEG, 7 + cmpw cr1, rNEG, rBITDIF + sub rRTN, rWORD1, rWORD2 +- blt- cr1, L(equal) +- srawi rRTN, rRTN, 31 +- ori rRTN, rRTN, 1 +- blr ++ bgelr+ cr1 + L(equal): + li rRTN, 0 + blr + + L(different): +- lwzu rWORD1, -4(rSTR1) ++ lwz rWORD1, -4(rSTR1) + xor. rBITDIF, rWORD1, rWORD2 + sub rRTN, rWORD1, rWORD2 +- blt- L(highbit) +- srawi rRTN, rRTN, 31 +- ori rRTN, rRTN, 1 +- blr ++ bgelr+ + L(highbit): +- srwi rWORD2, rWORD2, 24 +- srwi rWORD1, rWORD1, 24 +- sub rRTN, rWORD1, rWORD2 ++ ori rRTN, rWORD2, 1 + blr +- ++#endif + + /* Oh well. In this case, we just do a byte-by-byte comparison. */ + .align 4 +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power4/strncmp.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power4/strncmp.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power4/strncmp.S 2014-05-28 13:26:59.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power4/strncmp.S 2014-05-28 13:27:02.000000000 -0500 +@@ -27,7 +27,7 @@ + EALIGN (BP_SYM(strncmp), 4, 0) + CALL_MCOUNT 3 + +-#define rTMP r0 ++#define rTMP2 r0 + #define rRTN r3 + #define rSTR1 r3 /* first string arg */ + #define rSTR2 r4 /* second string arg */ +@@ -43,6 +43,7 @@ + #define r7F7F r9 /* constant 0x7f7f7f7f7f7f7f7f */ + #define rNEG r10 /* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */ + #define rBITDIF r11 /* bits that differ in s1 & s2 words */ ++#define rTMP r12 + + dcbt 0,rSTR1 + or rTMP, rSTR2, rSTR1 +@@ -84,12 +85,59 @@ + we don't compare two strings as different because of gunk beyond + the end of the strings... */ + ++#ifdef __LITTLE_ENDIAN__ ++L(endstring): ++ addi rTMP2, rTMP, -1 ++ beq cr1, L(equal) ++ andc rTMP2, rTMP2, rTMP ++ rldimi rTMP2, rTMP2, 1, 0 ++ and rWORD2, rWORD2, rTMP2 /* Mask off gunk. */ ++ and rWORD1, rWORD1, rTMP2 ++ cmpd cr1, rWORD1, rWORD2 ++ beq cr1, L(equal) ++ xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */ ++ neg rNEG, rBITDIF ++ and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */ ++ cntlzd rNEG, rNEG /* bitcount of the bit. */ ++ andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */ ++ sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */ ++ sld rWORD2, rWORD2, rNEG ++ xor. rBITDIF, rWORD1, rWORD2 ++ sub rRTN, rWORD1, rWORD2 ++ blt- L(highbit) ++ sradi rRTN, rRTN, 63 /* must return an int. */ ++ ori rRTN, rRTN, 1 ++ blr ++L(equal): ++ li rRTN, 0 ++ blr ++ ++L(different): ++ ld rWORD1, -8(rSTR1) ++ xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */ ++ neg rNEG, rBITDIF ++ and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */ ++ cntlzd rNEG, rNEG /* bitcount of the bit. */ ++ andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */ ++ sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */ ++ sld rWORD2, rWORD2, rNEG ++ xor. rBITDIF, rWORD1, rWORD2 ++ sub rRTN, rWORD1, rWORD2 ++ blt- L(highbit) ++ sradi rRTN, rRTN, 63 ++ ori rRTN, rRTN, 1 ++ blr ++L(highbit): ++ sradi rRTN, rWORD2, 63 ++ ori rRTN, rRTN, 1 ++ blr ++ ++#else + L(endstring): + and rTMP, r7F7F, rWORD1 + beq cr1, L(equal) + add rTMP, rTMP, r7F7F + xor. rBITDIF, rWORD1, rWORD2 +- + andc rNEG, rNEG, rTMP + blt- L(highbit) + cntlzd rBITDIF, rBITDIF +@@ -98,7 +146,7 @@ + cmpd cr1, rNEG, rBITDIF + sub rRTN, rWORD1, rWORD2 + blt- cr1, L(equal) +- sradi rRTN, rRTN, 63 ++ sradi rRTN, rRTN, 63 /* must return an int. */ + ori rRTN, rRTN, 1 + blr + L(equal): +@@ -106,7 +154,7 @@ + blr + + L(different): +- ldu rWORD1, -8(rSTR1) ++ ld rWORD1, -8(rSTR1) + xor. rBITDIF, rWORD1, rWORD2 + sub rRTN, rWORD1, rWORD2 + blt- L(highbit) +@@ -114,11 +162,10 @@ + ori rRTN, rRTN, 1 + blr + L(highbit): +- srdi rWORD2, rWORD2, 56 +- srdi rWORD1, rWORD1, 56 +- sub rRTN, rWORD1, rWORD2 ++ sradi rRTN, rWORD2, 63 ++ ori rRTN, rRTN, 1 + blr +- ++#endif + + /* Oh well. In this case, we just do a byte-by-byte comparison. */ + .align 4 +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strncmp.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strncmp.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strncmp.S 2014-05-28 13:26:59.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strncmp.S 2014-05-28 13:27:02.000000000 -0500 +@@ -29,7 +29,7 @@ + EALIGN (BP_SYM(strncmp),5,0) + CALL_MCOUNT 3 + +-#define rTMP r0 ++#define rTMP2 r0 + #define rRTN r3 + #define rSTR1 r3 /* first string arg */ + #define rSTR2 r4 /* second string arg */ +@@ -45,6 +45,7 @@ + #define r7F7F r9 /* constant 0x7f7f7f7f7f7f7f7f */ + #define rNEG r10 /* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */ + #define rBITDIF r11 /* bits that differ in s1 & s2 words */ ++#define rTMP r12 + + dcbt 0,rSTR1 + nop +@@ -88,12 +89,57 @@ + we don't compare two strings as different because of gunk beyond + the end of the strings... */ + ++#ifdef __LITTLE_ENDIAN__ ++L(endstring): ++ addi rTMP2, rTMP, -1 ++ beq cr1, L(equal) ++ andc rTMP2, rTMP2, rTMP ++ rldimi rTMP2, rTMP2, 1, 0 ++ and rWORD2, rWORD2, rTMP2 /* Mask off gunk. */ ++ and rWORD1, rWORD1, rTMP2 ++ cmpd cr1, rWORD1, rWORD2 ++ beq cr1, L(equal) ++ cmpb rBITDIF, rWORD1, rWORD2 /* 0xff on equal bytes. */ ++ addi rNEG, rBITDIF, 1 ++ orc rNEG, rNEG, rBITDIF /* 0's below LS differing byte. */ ++ sldi rNEG, rNEG, 8 /* 1's above LS differing byte. */ ++ andc rWORD1, rWORD1, rNEG /* mask off MS bytes. */ ++ andc rWORD2, rWORD2, rNEG ++ xor. rBITDIF, rWORD1, rWORD2 ++ sub rRTN, rWORD1, rWORD2 ++ blt L(highbit) ++ sradi rRTN, rRTN, 63 /* must return an int. */ ++ ori rRTN, rRTN, 1 ++ blr ++L(equal): ++ li rRTN, 0 ++ blr ++ ++L(different): ++ ld rWORD1, -8(rSTR1) ++ cmpb rBITDIF, rWORD1, rWORD2 /* 0xff on equal bytes. */ ++ addi rNEG, rBITDIF, 1 ++ orc rNEG, rNEG, rBITDIF /* 0's below LS differing byte. */ ++ sldi rNEG, rNEG, 8 /* 1's above LS differing byte. */ ++ andc rWORD1, rWORD1, rNEG /* mask off MS bytes. */ ++ andc rWORD2, rWORD2, rNEG ++ xor. rBITDIF, rWORD1, rWORD2 ++ sub rRTN, rWORD1, rWORD2 ++ blt L(highbit) ++ sradi rRTN, rRTN, 63 ++ ori rRTN, rRTN, 1 ++ blr ++L(highbit): ++ sradi rRTN, rWORD2, 63 ++ ori rRTN, rRTN, 1 ++ blr ++ ++#else + L(endstring): + and rTMP,r7F7F,rWORD1 + beq cr1,L(equal) + add rTMP,rTMP,r7F7F + xor. rBITDIF,rWORD1,rWORD2 +- + andc rNEG,rNEG,rTMP + blt L(highbit) + cntlzd rBITDIF,rBITDIF +@@ -102,7 +148,7 @@ + cmpd cr1,rNEG,rBITDIF + sub rRTN,rWORD1,rWORD2 + blt cr1,L(equal) +- sradi rRTN,rRTN,63 ++ sradi rRTN,rRTN,63 /* must return an int. */ + ori rRTN,rRTN,1 + blr + L(equal): +@@ -110,7 +156,7 @@ + blr + + L(different): +- ldu rWORD1,-8(rSTR1) ++ ld rWORD1,-8(rSTR1) + xor. rBITDIF,rWORD1,rWORD2 + sub rRTN,rWORD1,rWORD2 + blt L(highbit) +@@ -118,11 +164,10 @@ + ori rRTN,rRTN,1 + blr + L(highbit): +- srdi rWORD2,rWORD2,56 +- srdi rWORD1,rWORD1,56 +- sub rRTN,rWORD1,rWORD2 ++ sradi rRTN,rWORD2,63 ++ ori rRTN,rRTN,1 + blr +- ++#endif + + /* Oh well. In this case, we just do a byte-by-byte comparison. */ + .align 4 +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/strcmp.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/strcmp.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/strcmp.S 2014-05-28 13:26:59.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/strcmp.S 2014-05-28 13:37:15.000000000 -0500 +@@ -27,7 +27,7 @@ + EALIGN (BP_SYM(strcmp), 4, 0) + CALL_MCOUNT 2 + +-#define rTMP r0 ++#define rTMP2 r0 + #define rRTN r3 + #define rSTR1 r3 /* first string arg */ + #define rSTR2 r4 /* second string arg */ +@@ -46,6 +46,7 @@ + #define r7F7F r8 /* constant 0x7f7f7f7f7f7f7f7f */ + #define rNEG r9 /* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */ + #define rBITDIF r10 /* bits that differ in s1 & s2 words */ ++#define rTMP r11 + + CHECK_BOUNDS_LOW (rSTR1, rTMP, rHIGH1) + CHECK_BOUNDS_LOW (rSTR2, rTMP, rHIGH2) +@@ -72,19 +73,66 @@ + ldu rWORD2, 8(rSTR2) + L(g1): add rTMP, rFEFE, rWORD1 + nor rNEG, r7F7F, rWORD1 +- + and. rTMP, rTMP, rNEG + cmpd cr1, rWORD1, rWORD2 + beq+ L(g0) +-L(endstring): ++ + /* OK. We've hit the end of the string. We need to be careful that + we don't compare two strings as different because of gunk beyond + the end of the strings... */ ++#ifdef __LITTLE_ENDIAN__ ++L(endstring): ++ addi rTMP2, rTMP, -1 ++ beq cr1, L(equal) ++ andc rTMP2, rTMP2, rTMP ++ rldimi rTMP2, rTMP2, 1, 0 ++ and rWORD2, rWORD2, rTMP2 /* Mask off gunk. */ ++ and rWORD1, rWORD1, rTMP2 ++ cmpd cr1, rWORD1, rWORD2 ++ beq cr1, L(equal) ++ xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */ ++ neg rNEG, rBITDIF ++ and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */ ++ cntlzd rNEG, rNEG /* bitcount of the bit. */ ++ andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */ ++ sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */ ++ sld rWORD2, rWORD2, rNEG ++ xor. rBITDIF, rWORD1, rWORD2 ++ sub rRTN, rWORD1, rWORD2 ++ blt- L(highbit) ++ sradi rRTN, rRTN, 63 /* must return an int. */ ++ ori rRTN, rRTN, 1 ++ blr ++L(equal): ++ li rRTN, 0 ++ blr ++ ++L(different): ++ ld rWORD1, -8(rSTR1) ++ xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */ ++ neg rNEG, rBITDIF ++ and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */ ++ cntlzd rNEG, rNEG /* bitcount of the bit. */ ++ andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */ ++ sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */ ++ sld rWORD2, rWORD2, rNEG ++ xor. rBITDIF, rWORD1, rWORD2 ++ sub rRTN, rWORD1, rWORD2 ++ blt- L(highbit) ++ sradi rRTN, rRTN, 63 ++ ori rRTN, rRTN, 1 ++ blr ++L(highbit): ++ sradi rRTN, rWORD2, 63 ++ ori rRTN, rRTN, 1 ++ blr ++ ++#else ++L(endstring): + and rTMP, r7F7F, rWORD1 + beq cr1, L(equal) + add rTMP, rTMP, r7F7F + xor. rBITDIF, rWORD1, rWORD2 +- + andc rNEG, rNEG, rTMP + blt- L(highbit) + cntlzd rBITDIF, rBITDIF +@@ -93,7 +141,7 @@ + cmpd cr1, rNEG, rBITDIF + sub rRTN, rWORD1, rWORD2 + blt- cr1, L(equal) +- sradi rRTN, rRTN, 63 ++ sradi rRTN, rRTN, 63 /* must return an int. */ + ori rRTN, rRTN, 1 + blr + L(equal): +@@ -110,12 +158,11 @@ + ori rRTN, rRTN, 1 + blr + L(highbit): +- srdi rWORD2, rWORD2, 56 +- srdi rWORD1, rWORD1, 56 +- sub rRTN, rWORD1, rWORD2 ++ sradi rRTN, rWORD2, 63 ++ ori rRTN, rRTN, 1 + /* GKM FIXME: check high bounds. */ + blr +- ++#endif + + /* Oh well. In this case, we just do a byte-by-byte comparison. */ + .align 4 +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/strncmp.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/strncmp.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/strncmp.S 2014-05-28 13:26:59.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/strncmp.S 2014-05-28 13:38:31.000000000 -0500 +@@ -27,7 +27,7 @@ + EALIGN (BP_SYM(strncmp), 4, 0) + CALL_MCOUNT 3 + +-#define rTMP r0 ++#define rTMP2 r0 + #define rRTN r3 + #define rSTR1 r3 /* first string arg */ + #define rSTR2 r4 /* second string arg */ +@@ -41,6 +41,7 @@ + #define r7F7F r9 /* constant 0x7f7f7f7f7f7f7f7f */ + #define rNEG r10 /* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */ + #define rBITDIF r11 /* bits that differ in s1 & s2 words */ ++#define rTMP r12 + + dcbt 0,rSTR1 + or rTMP, rSTR2, rSTR1 +@@ -81,13 +82,60 @@ + /* OK. We've hit the end of the string. We need to be careful that + we don't compare two strings as different because of gunk beyond + the end of the strings... */ +- ++ ++#ifdef __LITTLE_ENDIAN__ ++L(endstring): ++ addi rTMP2, rTMP, -1 ++ beq cr1, L(equal) ++ andc rTMP2, rTMP2, rTMP ++ rldimi rTMP2, rTMP2, 1, 0 ++ and rWORD2, rWORD2, rTMP2 /* Mask off gunk. */ ++ and rWORD1, rWORD1, rTMP2 ++ cmpd cr1, rWORD1, rWORD2 ++ beq cr1, L(equal) ++ xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */ ++ neg rNEG, rBITDIF ++ and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */ ++ cntlzd rNEG, rNEG /* bitcount of the bit. */ ++ andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */ ++ sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */ ++ sld rWORD2, rWORD2, rNEG ++ xor. rBITDIF, rWORD1, rWORD2 ++ sub rRTN, rWORD1, rWORD2 ++ blt- L(highbit) ++ sradi rRTN, rRTN, 63 /* must return an int. */ ++ ori rRTN, rRTN, 1 ++ blr ++L(equal): ++ li rRTN, 0 ++ blr ++ ++L(different): ++ ld rWORD1, -8(rSTR1) ++ xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */ ++ neg rNEG, rBITDIF ++ and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */ ++ cntlzd rNEG, rNEG /* bitcount of the bit. */ ++ andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */ ++ sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */ ++ sld rWORD2, rWORD2, rNEG ++ xor. rBITDIF, rWORD1, rWORD2 ++ sub rRTN, rWORD1, rWORD2 ++ blt- L(highbit) ++ sradi rRTN, rRTN, 63 ++ ori rRTN, rRTN, 1 ++ blr ++L(highbit): ++ sradi rRTN, rWORD2, 63 ++ ori rRTN, rRTN, 1 ++ blr ++ ++#else + L(endstring): + and rTMP, r7F7F, rWORD1 + beq cr1, L(equal) + add rTMP, rTMP, r7F7F + xor. rBITDIF, rWORD1, rWORD2 +- + andc rNEG, rNEG, rTMP + blt- L(highbit) + cntlzd rBITDIF, rBITDIF +@@ -96,7 +144,7 @@ + cmpd cr1, rNEG, rBITDIF + sub rRTN, rWORD1, rWORD2 + blt- cr1, L(equal) +- sradi rRTN, rRTN, 63 ++ sradi rRTN, rRTN, 63 /* must return an int. */ + ori rRTN, rRTN, 1 + blr + L(equal): +@@ -104,7 +152,7 @@ + blr + + L(different): +- ldu rWORD1, -8(rSTR1) ++ ld rWORD1, -8(rSTR1) + xor. rBITDIF, rWORD1, rWORD2 + sub rRTN, rWORD1, rWORD2 + blt- L(highbit) +@@ -112,11 +160,10 @@ + ori rRTN, rRTN, 1 + blr + L(highbit): +- srdi rWORD2, rWORD2, 56 +- srdi rWORD1, rWORD1, 56 +- sub rRTN, rWORD1, rWORD2 ++ sradi rRTN, rWORD2, 63 ++ ori rRTN, rRTN, 1 + blr +- ++#endif + + /* Oh well. In this case, we just do a byte-by-byte comparison. */ + .align 4 diff --git a/SOURCES/glibc-ppc64le-28.patch b/SOURCES/glibc-ppc64le-28.patch new file mode 100644 index 0000000..05f63e9 --- /dev/null +++ b/SOURCES/glibc-ppc64le-28.patch @@ -0,0 +1,167 @@ +# commit 43b84013714c46e6dcae4a5564c5527777ad5e08 +# Author: Alan Modra +# Date: Sat Aug 17 18:45:31 2013 +0930 +# +# PowerPC LE strcpy +# http://sourceware.org/ml/libc-alpha/2013-08/msg00100.html +# +# The strcpy changes for little-endian are quite straight-forward, just +# a matter of rotating the last word differently. +# +# I'll note that the powerpc64 version of stpcpy is just begging to be +# converted to use 64-bit loads and stores.. +# +# * sysdeps/powerpc/powerpc64/strcpy.S: Add little-endian support: +# * sysdeps/powerpc/powerpc32/strcpy.S: Likewise. +# * sysdeps/powerpc/powerpc64/stpcpy.S: Likewise. +# * sysdeps/powerpc/powerpc32/stpcpy.S: Likewise. +# +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/stpcpy.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/stpcpy.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/stpcpy.S 2014-05-28 13:40:01.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/stpcpy.S 2014-05-28 13:40:01.000000000 -0500 +@@ -74,7 +74,22 @@ + + mr rALT, rWORD + /* We've hit the end of the string. Do the rest byte-by-byte. */ +-L(g1): rlwinm. rTMP, rALT, 8, 24, 31 ++L(g1): ++#ifdef __LITTLE_ENDIAN__ ++ rlwinm. rTMP, rALT, 0, 24, 31 ++ stbu rALT, 4(rDEST) ++ beqlr- ++ rlwinm. rTMP, rALT, 24, 24, 31 ++ stbu rTMP, 1(rDEST) ++ beqlr- ++ rlwinm. rTMP, rALT, 16, 24, 31 ++ stbu rTMP, 1(rDEST) ++ beqlr- ++ rlwinm rTMP, rALT, 8, 24, 31 ++ stbu rTMP, 1(rDEST) ++ blr ++#else ++ rlwinm. rTMP, rALT, 8, 24, 31 + stbu rTMP, 4(rDEST) + beqlr- + rlwinm. rTMP, rALT, 16, 24, 31 +@@ -87,6 +102,7 @@ + CHECK_BOUNDS_HIGH (rDEST, rHIGH, twlgt) + STORE_RETURN_VALUE (rDEST) + blr ++#endif + + /* Oh well. In this case, we just do a byte-by-byte copy. */ + .align 4 +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/strcpy.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/strcpy.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/strcpy.S 2014-05-28 13:40:01.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/strcpy.S 2014-05-28 13:40:01.000000000 -0500 +@@ -78,7 +78,22 @@ + + mr rALT, rWORD + /* We've hit the end of the string. Do the rest byte-by-byte. */ +-L(g1): rlwinm. rTMP, rALT, 8, 24, 31 ++L(g1): ++#ifdef __LITTLE_ENDIAN__ ++ rlwinm. rTMP, rALT, 0, 24, 31 ++ stb rALT, 4(rDEST) ++ beqlr- ++ rlwinm. rTMP, rALT, 24, 24, 31 ++ stb rTMP, 5(rDEST) ++ beqlr- ++ rlwinm. rTMP, rALT, 16, 24, 31 ++ stb rTMP, 6(rDEST) ++ beqlr- ++ rlwinm rTMP, rALT, 8, 24, 31 ++ stb rTMP, 7(rDEST) ++ blr ++#else ++ rlwinm. rTMP, rALT, 8, 24, 31 + stb rTMP, 4(rDEST) + beqlr- + rlwinm. rTMP, rALT, 16, 24, 31 +@@ -90,6 +105,7 @@ + stb rALT, 7(rDEST) + /* GKM FIXME: check high bound. */ + blr ++#endif + + /* Oh well. In this case, we just do a byte-by-byte copy. */ + .align 4 +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/stpcpy.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/stpcpy.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/stpcpy.S 2014-05-28 13:40:01.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/stpcpy.S 2014-05-28 13:40:01.000000000 -0500 +@@ -75,7 +75,22 @@ + + mr rALT, rWORD + /* We've hit the end of the string. Do the rest byte-by-byte. */ +-L(g1): rlwinm. rTMP, rALT, 8, 24, 31 ++L(g1): ++#ifdef __LITTLE_ENDIAN__ ++ rlwinm. rTMP, rALT, 0, 24, 31 ++ stbu rALT, 4(rDEST) ++ beqlr- ++ rlwinm. rTMP, rALT, 24, 24, 31 ++ stbu rTMP, 1(rDEST) ++ beqlr- ++ rlwinm. rTMP, rALT, 16, 24, 31 ++ stbu rTMP, 1(rDEST) ++ beqlr- ++ rlwinm rTMP, rALT, 8, 24, 31 ++ stbu rTMP, 1(rDEST) ++ blr ++#else ++ rlwinm. rTMP, rALT, 8, 24, 31 + stbu rTMP, 4(rDEST) + beqlr- + rlwinm. rTMP, rALT, 16, 24, 31 +@@ -88,6 +103,7 @@ + CHECK_BOUNDS_HIGH (rDEST, rHIGH, twlgt) + STORE_RETURN_VALUE (rDEST) + blr ++#endif + + /* Oh well. In this case, we just do a byte-by-byte copy. */ + .align 4 +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/strcpy.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/strcpy.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/strcpy.S 2014-05-28 13:40:01.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/strcpy.S 2014-05-28 13:40:01.000000000 -0500 +@@ -90,6 +90,32 @@ + mr rALT, rWORD + /* We've hit the end of the string. Do the rest byte-by-byte. */ + L(g1): ++#ifdef __LITTLE_ENDIAN__ ++ extrdi. rTMP, rALT, 8, 56 ++ stb rALT, 8(rDEST) ++ beqlr- ++ extrdi. rTMP, rALT, 8, 48 ++ stb rTMP, 9(rDEST) ++ beqlr- ++ extrdi. rTMP, rALT, 8, 40 ++ stb rTMP, 10(rDEST) ++ beqlr- ++ extrdi. rTMP, rALT, 8, 32 ++ stb rTMP, 11(rDEST) ++ beqlr- ++ extrdi. rTMP, rALT, 8, 24 ++ stb rTMP, 12(rDEST) ++ beqlr- ++ extrdi. rTMP, rALT, 8, 16 ++ stb rTMP, 13(rDEST) ++ beqlr- ++ extrdi. rTMP, rALT, 8, 8 ++ stb rTMP, 14(rDEST) ++ beqlr- ++ extrdi rTMP, rALT, 8, 0 ++ stb rTMP, 15(rDEST) ++ blr ++#else + extrdi. rTMP, rALT, 8, 0 + stb rTMP, 8(rDEST) + beqlr- +@@ -114,6 +140,7 @@ + stb rALT, 15(rDEST) + /* GKM FIXME: check high bound. */ + blr ++#endif + + /* Oh well. In this case, we just do a byte-by-byte copy. */ + .align 4 diff --git a/SOURCES/glibc-ppc64le-29.patch b/SOURCES/glibc-ppc64le-29.patch new file mode 100644 index 0000000..291155e --- /dev/null +++ b/SOURCES/glibc-ppc64le-29.patch @@ -0,0 +1,642 @@ +# commit 664318c3eb07032e2bfcf47cb2aa3c89280c19e7 +# Author: Alan Modra +# Date: Sat Aug 17 18:46:05 2013 +0930 +# +# PowerPC LE strchr +# http://sourceware.org/ml/libc-alpha/2013-08/msg00101.html +# +# Adds little-endian support to optimised strchr assembly. I've also +# tweaked the big-endian code a little. In power7/strchr.S there's a +# check in the tail of the function that we didn't match 0 before +# finding a c match, done by comparing leading zero counts. It's just +# as valid, and quicker, to compare the raw output from cmpb. +# +# Another little tweak is to use rldimi/insrdi in place of rlwimi for +# the power7 strchr functions. Since rlwimi is cracked, it is a few +# cycles slower. rldimi can be used on the 32-bit power7 functions +# too. +# +# * sysdeps/powerpc/powerpc64/power7/strchr.S (strchr): Add little-endian +# support. Correct typos, formatting. Optimize tail. Use insrdi +# rather than rlwimi. +# * sysdeps/powerpc/powerpc32/power7/strchr.S: Likewise. +# * sysdeps/powerpc/powerpc64/power7/strchrnul.S (__strchrnul): Add +# little-endian support. Correct typos. +# * sysdeps/powerpc/powerpc32/power7/strchrnul.S: Likewise. Use insrdi +# rather than rlwimi. +# * sysdeps/powerpc/powerpc64/strchr.S (rTMP4, rTMP5): Define. Use +# in loop and entry code to keep "and." results. +# (strchr): Add little-endian support. Comment. Move cntlzd +# earlier in tail. +# * sysdeps/powerpc/powerpc32/strchr.S: Likewise. +# +Index: glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strchr.S +=================================================================== +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strchr.S.orig ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strchr.S +@@ -37,8 +37,8 @@ ENTRY (BP_SYM(strchr)) + beq cr7,L(null_match) + + /* Replicate byte to word. */ +- rlwimi r4,r4,8,16,23 +- rlwimi r4,r4,16,0,15 ++ insrdi r4,r4,8,48 ++ insrdi r4,r4,16,32 + + /* Now r4 has a word of c bytes and r0 has + a word of null bytes. */ +@@ -48,11 +48,17 @@ ENTRY (BP_SYM(strchr)) + + /* Move the words left and right to discard the bits that are + not part of the string and to bring them back as zeros. */ +- ++#ifdef __LITTLE_ENDIAN__ ++ srw r10,r10,r6 ++ srw r11,r11,r6 ++ slw r10,r10,r6 ++ slw r11,r11,r6 ++#else + slw r10,r10,r6 + slw r11,r11,r6 + srw r10,r10,r6 + srw r11,r11,r6 ++#endif + or r5,r10,r11 /* OR the results to speed things up. */ + cmpwi cr7,r5,0 /* If r5 == 0, no c or null bytes + have been found. */ +@@ -67,7 +73,7 @@ ENTRY (BP_SYM(strchr)) + + /* Handle WORD2 of pair. */ + lwzu r12,4(r8) +- cmpb r10,r12,r4 ++ cmpb r10,r12,r4 + cmpb r11,r12,r0 + or r5,r10,r11 + cmpwi cr7,r5,0 +@@ -102,22 +108,31 @@ L(loop): + bne cr6,L(done) + + /* The c/null byte must be in the second word. Adjust the address +- again and move the result of cmpb to r10 so we can calculate the +- pointer. */ ++ again and move the result of cmpb to r10/r11 so we can calculate ++ the pointer. */ + + mr r10,r6 + mr r11,r7 + addi r8,r8,4 + +- /* r5 has the output of the cmpb instruction, that is, it contains ++ /* r10/r11 have the output of the cmpb instructions, that is, + 0xff in the same position as the c/null byte in the original + word from the string. Use that to calculate the pointer. */ + L(done): +- cntlzw r4,r10 /* Count leading zeroes before c matches. */ +- cntlzw r0,r11 /* Count leading zeroes before null matches. */ +- cmplw cr7,r4,r0 ++#ifdef __LITTLE_ENDIAN__ ++ addi r3,r10,-1 ++ andc r3,r3,r10 ++ popcntw r0,r3 ++ addi r4,r11,-1 ++ andc r4,r4,r11 ++ cmplw cr7,r3,r4 ++ bgt cr7,L(no_match) ++#else ++ cntlzw r0,r10 /* Count leading zeros before c matches. */ ++ cmplw cr7,r11,r10 + bgt cr7,L(no_match) +- srwi r0,r4,3 /* Convert leading zeroes to bytes. */ ++#endif ++ srwi r0,r0,3 /* Convert leading zeros to bytes. */ + add r3,r8,r0 /* Return address of the matching c byte + or null in case c was not found. */ + blr +@@ -135,10 +150,14 @@ L(null_match): + cmpb r5,r12,r0 /* Compare each byte against null bytes. */ + + /* Move the words left and right to discard the bits that are +- not part of the string and to bring them back as zeros. */ +- ++ not part of the string and bring them back as zeros. */ ++#ifdef __LITTLE_ENDIAN__ ++ srw r5,r5,r6 ++ slw r5,r5,r6 ++#else + slw r5,r5,r6 + srw r5,r5,r6 ++#endif + cmpwi cr7,r5,0 /* If r10 == 0, no c or null bytes + have been found. */ + bne cr7,L(done_null) +@@ -193,7 +212,13 @@ L(loop_null): + 0xff in the same position as the null byte in the original + word from the string. Use that to calculate the pointer. */ + L(done_null): ++#ifdef __LITTLE_ENDIAN__ ++ addi r0,r5,-1 ++ andc r0,r0,r5 ++ popcntw r0,r0 ++#else + cntlzw r0,r5 /* Count leading zeros before the match. */ ++#endif + srwi r0,r0,3 /* Convert leading zeros to bytes. */ + add r3,r8,r0 /* Return address of the matching null byte. */ + blr +Index: glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strchrnul.S +=================================================================== +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strchrnul.S.orig ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strchrnul.S +@@ -29,8 +29,8 @@ ENTRY (BP_SYM(__strchrnul)) + clrrwi r8,r3,2 /* Align the address to word boundary. */ + + /* Replicate byte to word. */ +- rlwimi r4,r4,8,16,23 +- rlwimi r4,r4,16,0,15 ++ insrdi r4,r4,8,48 ++ insrdi r4,r4,16,32 + + rlwinm r6,r3,3,27,28 /* Calculate padding. */ + lwz r12,0(r8) /* Load word from memory. */ +@@ -45,10 +45,17 @@ ENTRY (BP_SYM(__strchrnul)) + + /* Move the words left and right to discard the bits that are + not part of the string and bring them back as zeros. */ ++#ifdef __LITTLE_ENDIAN__ ++ srw r10,r10,r6 ++ srw r9,r9,r6 ++ slw r10,r10,r6 ++ slw r9,r9,r6 ++#else + slw r10,r10,r6 + slw r9,r9,r6 + srw r10,r10,r6 + srw r9,r9,r6 ++#endif + or r5,r9,r10 /* OR the results to speed things up. */ + cmpwi cr7,r5,0 /* If r5 == 0, no c or null bytes + have been found. */ +@@ -56,7 +63,7 @@ ENTRY (BP_SYM(__strchrnul)) + + mtcrf 0x01,r8 + +- /* Are we now aligned to a quadword boundary? If so, skip to ++ /* Are we now aligned to a doubleword boundary? If so, skip to + the main loop. Otherwise, go through the alignment code. */ + + bt 29,L(loop) +@@ -78,7 +85,7 @@ L(loop): + single register for speed. This is an attempt + to speed up the null-checking process for bigger strings. */ + lwz r12,4(r8) +- lwzu r11,8(r8) ++ lwzu r11,8(r8) + cmpb r10,r12,r0 + cmpb r9,r12,r4 + cmpb r6,r11,r0 +@@ -97,9 +104,9 @@ L(loop): + addi r8,r8,-4 + bne cr6,L(done) + +- /* The c/null byte must be in the second word. Adjust the +- address again and move the result of cmpb to r10 so we can calculate +- the pointer. */ ++ /* The c/null byte must be in the second word. Adjust the address ++ again and move the result of cmpb to r5 so we can calculate the ++ pointer. */ + mr r5,r10 + addi r8,r8,4 + +@@ -107,7 +114,13 @@ L(loop): + 0xff in the same position as the c/null byte in the original + word from the string. Use that to calculate the pointer. */ + L(done): ++#ifdef __LITTLE_ENDIAN__ ++ addi r0,r5,-1 ++ andc r0,r0,r5 ++ popcntw r0,r0 ++#else + cntlzw r0,r5 /* Count leading zeros before the match. */ ++#endif + srwi r0,r0,3 /* Convert leading zeros to bytes. */ + add r3,r8,r0 /* Return address of matching c/null byte. */ + blr +Index: glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/strchr.S +=================================================================== +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/strchr.S.orig ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/strchr.S +@@ -44,6 +44,8 @@ ENTRY (BP_SYM (strchr)) + #define rIGN r10 /* number of bits we should ignore in the first word */ + #define rMASK r11 /* mask with the bits to ignore set to 0 */ + #define rTMP3 r12 ++#define rTMP4 rIGN ++#define rTMP5 rMASK + + CHECK_BOUNDS_LOW (rSTR, rTMP1, rTMP2) + STORE_RETURN_BOUNDS (rTMP1, rTMP2) +@@ -59,53 +61,74 @@ ENTRY (BP_SYM (strchr)) + addi r7F7F, r7F7F, 0x7f7f + /* Test the first (partial?) word. */ + lwz rWORD, 0(rSTR) ++#ifdef __LITTLE_ENDIAN__ ++ slw rMASK, rMASK, rIGN ++#else + srw rMASK, rMASK, rIGN ++#endif + orc rWORD, rWORD, rMASK + add rTMP1, rFEFE, rWORD + nor rTMP2, r7F7F, rWORD +- and. rTMP1, rTMP1, rTMP2 ++ and. rTMP4, rTMP1, rTMP2 + xor rTMP3, rCHR, rWORD + orc rTMP3, rTMP3, rMASK + b L(loopentry) + + /* The loop. */ + +-L(loop):lwzu rWORD, 4(rSTR) +- and. rTMP1, rTMP1, rTMP2 ++L(loop): ++ lwzu rWORD, 4(rSTR) ++ and. rTMP5, rTMP1, rTMP2 + /* Test for 0. */ +- add rTMP1, rFEFE, rWORD +- nor rTMP2, r7F7F, rWORD ++ add rTMP1, rFEFE, rWORD /* x - 0x01010101. */ ++ nor rTMP2, r7F7F, rWORD /* ~(x | 0x7f7f7f7f) == ~x & 0x80808080. */ + bne L(foundit) +- and. rTMP1, rTMP1, rTMP2 ++ and. rTMP4, rTMP1, rTMP2 /* (x - 0x01010101) & ~x & 0x80808080. */ + /* Start test for the bytes we're looking for. */ + xor rTMP3, rCHR, rWORD + L(loopentry): + add rTMP1, rFEFE, rTMP3 + nor rTMP2, r7F7F, rTMP3 + beq L(loop) ++ + /* There is a zero byte in the word, but may also be a matching byte (either + before or after the zero byte). In fact, we may be looking for a +- zero byte, in which case we return a match. We guess that this hasn't +- happened, though. */ +-L(missed): +- and. rTMP1, rTMP1, rTMP2 ++ zero byte, in which case we return a match. */ ++ and. rTMP5, rTMP1, rTMP2 + li rRTN, 0 + STORE_RETURN_VALUE (rSTR) + beqlr +-/* It did happen. Decide which one was first... +- I'm not sure if this is actually faster than a sequence of +- rotates, compares, and branches (we use it anyway because it's shorter). */ ++/* At this point: ++ rTMP5 bytes are 0x80 for each match of c, 0 otherwise. ++ rTMP4 bytes are 0x80 for each match of 0, 0 otherwise. ++ But there may be false matches in the next most significant byte from ++ a true match due to carries. This means we need to recalculate the ++ matches using a longer method for big-endian. */ ++#ifdef __LITTLE_ENDIAN__ ++ addi rTMP1, rTMP5, -1 ++ andc rTMP1, rTMP1, rTMP5 ++ cntlzw rCLZB, rTMP1 ++ addi rTMP2, rTMP4, -1 ++ andc rTMP2, rTMP2, rTMP4 ++ cmplw rTMP1, rTMP2 ++ bgtlr ++ subfic rCLZB, rCLZB, 32-7 ++#else ++/* I think we could reduce this by two instructions by keeping the "nor" ++ results from the loop for reuse here. See strlen.S tail. Similarly ++ one instruction could be pruned from L(foundit). */ + and rFEFE, r7F7F, rWORD +- or rMASK, r7F7F, rWORD ++ or rTMP5, r7F7F, rWORD + and rTMP1, r7F7F, rTMP3 +- or rIGN, r7F7F, rTMP3 ++ or rTMP4, r7F7F, rTMP3 + add rFEFE, rFEFE, r7F7F + add rTMP1, rTMP1, r7F7F +- nor rWORD, rMASK, rFEFE +- nor rTMP2, rIGN, rTMP1 ++ nor rWORD, rTMP5, rFEFE ++ nor rTMP2, rTMP4, rTMP1 ++ cntlzw rCLZB, rTMP2 + cmplw rWORD, rTMP2 + bgtlr +- cntlzw rCLZB, rTMP2 ++#endif + srwi rCLZB, rCLZB, 3 + add rRTN, rSTR, rCLZB + CHECK_BOUNDS_HIGH_RTN (rSTR, rTMP2, twlge) +@@ -113,13 +136,21 @@ L(missed): + blr + + L(foundit): ++#ifdef __LITTLE_ENDIAN__ ++ addi rTMP1, rTMP5, -1 ++ andc rTMP1, rTMP1, rTMP5 ++ cntlzw rCLZB, rTMP1 ++ subfic rCLZB, rCLZB, 32-7-32 ++ srawi rCLZB, rCLZB, 3 ++#else + and rTMP1, r7F7F, rTMP3 +- or rIGN, r7F7F, rTMP3 ++ or rTMP4, r7F7F, rTMP3 + add rTMP1, rTMP1, r7F7F +- nor rTMP2, rIGN, rTMP1 ++ nor rTMP2, rTMP4, rTMP1 + cntlzw rCLZB, rTMP2 + subi rSTR, rSTR, 4 + srwi rCLZB, rCLZB, 3 ++#endif + add rRTN, rSTR, rCLZB + CHECK_BOUNDS_HIGH_RTN (rSTR, rTMP2, twlge) + STORE_RETURN_VALUE (rSTR) +Index: glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strchr.S +=================================================================== +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strchr.S.orig ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strchr.S +@@ -37,8 +37,8 @@ ENTRY (BP_SYM(strchr)) + beq cr7,L(null_match) + + /* Replicate byte to doubleword. */ +- rlwimi r4,r4,8,16,23 +- rlwimi r4,r4,16,0,15 ++ insrdi r4,r4,8,48 ++ insrdi r4,r4,16,32 + insrdi r4,r4,32,0 + + /* Now r4 has a doubleword of c bytes and r0 has +@@ -49,11 +49,17 @@ ENTRY (BP_SYM(strchr)) + + /* Move the doublewords left and right to discard the bits that are + not part of the string and bring them back as zeros. */ +- ++#ifdef __LITTLE_ENDIAN__ ++ srd r10,r10,r6 ++ srd r11,r11,r6 ++ sld r10,r10,r6 ++ sld r11,r11,r6 ++#else + sld r10,r10,r6 + sld r11,r11,r6 + srd r10,r10,r6 + srd r11,r11,r6 ++#endif + or r5,r10,r11 /* OR the results to speed things up. */ + cmpdi cr7,r5,0 /* If r5 == 0, no c or null bytes + have been found. */ +@@ -110,15 +116,24 @@ L(loop): + mr r11,r7 + addi r8,r8,8 + +- /* r5 has the output of the cmpb instruction, that is, it contains ++ /* r10/r11 have the output of the cmpb instructions, that is, + 0xff in the same position as the c/null byte in the original + doubleword from the string. Use that to calculate the pointer. */ + L(done): +- cntlzd r4,r10 /* Count leading zeroes before c matches. */ +- cntlzd r0,r11 /* Count leading zeroes before null matches. */ +- cmpld cr7,r4,r0 ++#ifdef __LITTLE_ENDIAN__ ++ addi r3,r10,-1 ++ andc r3,r3,r10 ++ popcntd r0,r3 ++ addi r4,r11,-1 ++ andc r4,r4,r11 ++ cmpld cr7,r3,r4 + bgt cr7,L(no_match) +- srdi r0,r4,3 /* Convert leading zeroes to bytes. */ ++#else ++ cntlzd r0,r10 /* Count leading zeros before c matches. */ ++ cmpld cr7,r11,r10 ++ bgt cr7,L(no_match) ++#endif ++ srdi r0,r0,3 /* Convert leading zeros to bytes. */ + add r3,r8,r0 /* Return address of the matching c byte + or null in case c was not found. */ + blr +@@ -137,9 +152,13 @@ L(null_match): + + /* Move the doublewords left and right to discard the bits that are + not part of the string and bring them back as zeros. */ +- ++#ifdef __LITTLE_ENDIAN__ ++ srd r5,r5,r6 ++ sld r5,r5,r6 ++#else + sld r5,r5,r6 + srd r5,r5,r6 ++#endif + cmpdi cr7,r5,0 /* If r10 == 0, no c or null bytes + have been found. */ + bne cr7,L(done_null) +@@ -194,7 +213,13 @@ L(loop_null): + 0xff in the same position as the null byte in the original + doubleword from the string. Use that to calculate the pointer. */ + L(done_null): ++#ifdef __LITTLE_ENDIAN__ ++ addi r0,r5,-1 ++ andc r0,r0,r5 ++ popcntd r0,r0 ++#else + cntlzd r0,r5 /* Count leading zeros before the match. */ ++#endif + srdi r0,r0,3 /* Convert leading zeros to bytes. */ + add r3,r8,r0 /* Return address of the matching null byte. */ + blr +Index: glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strchrnul.S +=================================================================== +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strchrnul.S.orig ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strchrnul.S +@@ -29,8 +29,8 @@ ENTRY (BP_SYM(__strchrnul)) + clrrdi r8,r3,3 /* Align the address to doubleword boundary. */ + + /* Replicate byte to doubleword. */ +- rlwimi r4,r4,8,16,23 +- rlwimi r4,r4,16,0,15 ++ insrdi r4,r4,8,48 ++ insrdi r4,r4,16,32 + insrdi r4,r4,32,0 + + rlwinm r6,r3,3,26,28 /* Calculate padding. */ +@@ -46,10 +46,17 @@ ENTRY (BP_SYM(__strchrnul)) + + /* Move the doublewords left and right to discard the bits that are + not part of the string and to bring them back as zeros. */ ++#ifdef __LITTLE_ENDIAN__ ++ srd r10,r10,r6 ++ srd r9,r9,r6 ++ sld r10,r10,r6 ++ sld r9,r9,r6 ++#else + sld r10,r10,r6 + sld r9,r9,r6 + srd r10,r10,r6 + srd r9,r9,r6 ++#endif + or r5,r9,r10 /* OR the results to speed things up. */ + cmpdi cr7,r5,0 /* If r5 == 0, no c or null bytes + have been found. */ +@@ -99,7 +106,7 @@ L(loop): + bne cr6,L(done) + + /* The c/null byte must be in the second doubleword. Adjust the +- address again and move the result of cmpb to r10 so we can calculate ++ address again and move the result of cmpb to r5 so we can calculate + the pointer. */ + mr r5,r10 + addi r8,r8,8 +@@ -108,7 +115,13 @@ L(loop): + 0xff in the same position as the c/null byte in the original + doubleword from the string. Use that to calculate the pointer. */ + L(done): ++#ifdef __LITTLE_ENDIAN__ ++ addi r0,r5,-1 ++ andc r0,r0,r5 ++ popcntd r0,r0 ++#else + cntlzd r0,r5 /* Count leading zeros before the match. */ ++#endif + srdi r0,r0,3 /* Convert leading zeros to bytes. */ + add r3,r8,r0 /* Return address of matching c/null byte. */ + blr +Index: glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/strchr.S +=================================================================== +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/strchr.S.orig ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/strchr.S +@@ -50,14 +50,16 @@ ENTRY (BP_SYM (strchr)) + #define rIGN r10 /* number of bits we should ignore in the first word */ + #define rMASK r11 /* mask with the bits to ignore set to 0 */ + #define rTMP3 r12 ++#define rTMP4 rIGN ++#define rTMP5 rMASK + + CHECK_BOUNDS_LOW (rSTR, rTMP1, rTMP2) + STORE_RETURN_BOUNDS (rTMP1, rTMP2) + + dcbt 0,rRTN +- rlwimi rCHR, rCHR, 8, 16, 23 ++ insrdi rCHR, rCHR, 8, 48 + li rMASK, -1 +- rlwimi rCHR, rCHR, 16, 0, 15 ++ insrdi rCHR, rCHR, 16, 32 + rlwinm rIGN, rRTN, 3, 26, 28 + insrdi rCHR, rCHR, 32, 0 + lis rFEFE, -0x101 +@@ -70,53 +72,74 @@ ENTRY (BP_SYM (strchr)) + add rFEFE, rFEFE, rTMP1 + /* Test the first (partial?) word. */ + ld rWORD, 0(rSTR) ++#ifdef __LITTLE_ENDIAN__ ++ sld rMASK, rMASK, rIGN ++#else + srd rMASK, rMASK, rIGN ++#endif + orc rWORD, rWORD, rMASK + add rTMP1, rFEFE, rWORD + nor rTMP2, r7F7F, rWORD +- and. rTMP1, rTMP1, rTMP2 ++ and. rTMP4, rTMP1, rTMP2 + xor rTMP3, rCHR, rWORD + orc rTMP3, rTMP3, rMASK + b L(loopentry) + + /* The loop. */ + +-L(loop):ldu rWORD, 8(rSTR) +- and. rTMP1, rTMP1, rTMP2 ++L(loop): ++ ldu rWORD, 8(rSTR) ++ and. rTMP5, rTMP1, rTMP2 + /* Test for 0. */ +- add rTMP1, rFEFE, rWORD +- nor rTMP2, r7F7F, rWORD ++ add rTMP1, rFEFE, rWORD /* x - 0x01010101. */ ++ nor rTMP2, r7F7F, rWORD /* ~(x | 0x7f7f7f7f) == ~x & 0x80808080. */ + bne L(foundit) +- and. rTMP1, rTMP1, rTMP2 ++ and. rTMP4, rTMP1, rTMP2 /* (x - 0x01010101) & ~x & 0x80808080. */ + /* Start test for the bytes we're looking for. */ + xor rTMP3, rCHR, rWORD + L(loopentry): + add rTMP1, rFEFE, rTMP3 + nor rTMP2, r7F7F, rTMP3 + beq L(loop) ++ + /* There is a zero byte in the word, but may also be a matching byte (either + before or after the zero byte). In fact, we may be looking for a +- zero byte, in which case we return a match. We guess that this hasn't +- happened, though. */ +-L(missed): +- and. rTMP1, rTMP1, rTMP2 ++ zero byte, in which case we return a match. */ ++ and. rTMP5, rTMP1, rTMP2 + li rRTN, 0 + STORE_RETURN_VALUE (rSTR) + beqlr +-/* It did happen. Decide which one was first... +- I'm not sure if this is actually faster than a sequence of +- rotates, compares, and branches (we use it anyway because it's shorter). */ ++/* At this point: ++ rTMP5 bytes are 0x80 for each match of c, 0 otherwise. ++ rTMP4 bytes are 0x80 for each match of 0, 0 otherwise. ++ But there may be false matches in the next most significant byte from ++ a true match due to carries. This means we need to recalculate the ++ matches using a longer method for big-endian. */ ++#ifdef __LITTLE_ENDIAN__ ++ addi rTMP1, rTMP5, -1 ++ andc rTMP1, rTMP1, rTMP5 ++ cntlzd rCLZB, rTMP1 ++ addi rTMP2, rTMP4, -1 ++ andc rTMP2, rTMP2, rTMP4 ++ cmpld rTMP1, rTMP2 ++ bgtlr ++ subfic rCLZB, rCLZB, 64-7 ++#else ++/* I think we could reduce this by two instructions by keeping the "nor" ++ results from the loop for reuse here. See strlen.S tail. Similarly ++ one instruction could be pruned from L(foundit). */ + and rFEFE, r7F7F, rWORD +- or rMASK, r7F7F, rWORD ++ or rTMP5, r7F7F, rWORD + and rTMP1, r7F7F, rTMP3 +- or rIGN, r7F7F, rTMP3 ++ or rTMP4, r7F7F, rTMP3 + add rFEFE, rFEFE, r7F7F + add rTMP1, rTMP1, r7F7F +- nor rWORD, rMASK, rFEFE +- nor rTMP2, rIGN, rTMP1 ++ nor rWORD, rTMP5, rFEFE ++ nor rTMP2, rTMP4, rTMP1 ++ cntlzd rCLZB, rTMP2 + cmpld rWORD, rTMP2 + bgtlr +- cntlzd rCLZB, rTMP2 ++#endif + srdi rCLZB, rCLZB, 3 + add rRTN, rSTR, rCLZB + CHECK_BOUNDS_HIGH_RTN (rSTR, rTMP2, tdlge) +@@ -124,13 +147,21 @@ L(missed): + blr + + L(foundit): ++#ifdef __LITTLE_ENDIAN__ ++ addi rTMP1, rTMP5, -1 ++ andc rTMP1, rTMP1, rTMP5 ++ cntlzd rCLZB, rTMP1 ++ subfic rCLZB, rCLZB, 64-7-64 ++ sradi rCLZB, rCLZB, 3 ++#else + and rTMP1, r7F7F, rTMP3 +- or rIGN, r7F7F, rTMP3 ++ or rTMP4, r7F7F, rTMP3 + add rTMP1, rTMP1, r7F7F +- nor rTMP2, rIGN, rTMP1 ++ nor rTMP2, rTMP4, rTMP1 + cntlzd rCLZB, rTMP2 + subi rSTR, rSTR, 8 + srdi rCLZB, rCLZB, 3 ++#endif + add rRTN, rSTR, rCLZB + CHECK_BOUNDS_HIGH_RTN (rSTR, rTMP2, tdlge) + STORE_RETURN_VALUE (rSTR) diff --git a/SOURCES/glibc-ppc64le-30.patch b/SOURCES/glibc-ppc64le-30.patch new file mode 100644 index 0000000..3834dcc --- /dev/null +++ b/SOURCES/glibc-ppc64le-30.patch @@ -0,0 +1,7383 @@ +# commit fe6e95d7171eba5f3e07848f081676fae4e86322 +# Author: Alan Modra +# Date: Sat Aug 17 18:46:47 2013 +0930 +# +# PowerPC LE memcmp +# http://sourceware.org/ml/libc-alpha/2013-08/msg00102.html +# +# This is a rather large patch due to formatting and renaming. The +# formatting changes were to make it possible to compare power7 and +# power4 versions of memcmp. Using different register defines came +# about while I was wrestling with the code, trying to find spare +# registers at one stage. I found it much simpler if we refer to a reg +# by the same name throughout a function, so it's better if short-term +# multiple use regs like rTMP are referred to using their register +# number. I made the cr field usage changes when attempting to reload +# rWORDn regs in the exit path to byte swap before comparing when +# little-endian. That proved a bad idea due to the pipelining involved +# in the main loop; Offsets to reload the regs were different first +# time around the loop.. Anyway, I left the cr field usage changes in +# place for consistency. +# +# Aside from these more-or-less cosmetic changes, I fixed a number of +# places where an early exit path restores regs unnecessarily, removed +# some dead code, and optimised one or two exits. +# +# * sysdeps/powerpc/powerpc64/power7/memcmp.S: Add little-endian support. +# Formatting. Consistently use rXXX register defines or rN defines. +# Use early exit labels that avoid restoring unused non-volatile regs. +# Make cr field use more consistent with rWORDn compares. Rename +# regs used as shift registers for unaligned loop, using rN defines +# for short lifetime/multiple use regs. +# * sysdeps/powerpc/powerpc64/power4/memcmp.S: Likewise. +# * sysdeps/powerpc/powerpc32/power7/memcmp.S: Likewise. Exit with +# addi 1,1,64 to pop stack frame. Simplify return value code. +# * sysdeps/powerpc/powerpc32/power4/memcmp.S: Likewise. +# +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/memcmp.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/memcmp.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/memcmp.S 2014-05-28 19:22:37.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/memcmp.S 2014-05-28 23:55:52.000000000 -0500 +@@ -1,4 +1,4 @@ +-/* Optimized strcmp implementation for PowerPC64. ++/* Optimized strcmp implementation for PowerPC32. + Copyright (C) 2003, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + +@@ -20,13 +20,14 @@ + #include + #include + +-/* int [r3] memcmp (const char *s1 [r3], const char *s2 [r4], size_t size [r5]) */ +- ++/* int [r3] memcmp (const char *s1 [r3], ++ const char *s2 [r4], ++ size_t size [r5]) */ ++ + .machine power4 + EALIGN (BP_SYM(memcmp), 4, 0) + CALL_MCOUNT + +-#define rTMP r0 + #define rRTN r3 + #define rSTR1 r3 /* first string arg */ + #define rSTR2 r4 /* second string arg */ +@@ -37,33 +38,32 @@ + #define rWORD4 r9 /* next word in s2 */ + #define rWORD5 r10 /* next word in s1 */ + #define rWORD6 r11 /* next word in s2 */ +-#define rBITDIF r12 /* bits that differ in s1 & s2 words */ + #define rWORD7 r30 /* next word in s1 */ + #define rWORD8 r31 /* next word in s2 */ + +- xor rTMP, rSTR2, rSTR1 ++ xor r0, rSTR2, rSTR1 + cmplwi cr6, rN, 0 + cmplwi cr1, rN, 12 +- clrlwi. rTMP, rTMP, 30 +- clrlwi rBITDIF, rSTR1, 30 +- cmplwi cr5, rBITDIF, 0 ++ clrlwi. r0, r0, 30 ++ clrlwi r12, rSTR1, 30 ++ cmplwi cr5, r12, 0 + beq- cr6, L(zeroLength) +- dcbt 0,rSTR1 +- dcbt 0,rSTR2 ++ dcbt 0, rSTR1 ++ dcbt 0, rSTR2 + /* If less than 8 bytes or not aligned, use the unaligned + byte loop. */ + blt cr1, L(bytealigned) +- stwu 1,-64(1) ++ stwu 1, -64(r1) + cfi_adjust_cfa_offset(64) +- stw r31,48(1) +- cfi_offset(31,(48-64)) +- stw r30,44(1) +- cfi_offset(30,(44-64)) ++ stw rWORD8, 48(r1) ++ cfi_offset(rWORD8, (48-64)) ++ stw rWORD7, 44(r1) ++ cfi_offset(rWORD7, (44-64)) + bne L(unaligned) + /* At this point we know both strings have the same alignment and the +- compare length is at least 8 bytes. rBITDIF contains the low order ++ compare length is at least 8 bytes. r12 contains the low order + 2 bits of rSTR1 and cr5 contains the result of the logical compare +- of rBITDIF to 0. If rBITDIF == 0 then we are already word ++ of r12 to 0. If r12 == 0 then we are already word + aligned and can perform the word aligned loop. + + Otherwise we know the two strings have the same alignment (but not +@@ -72,74 +72,95 @@ + eliminate bits preceeding the first byte. Since we want to join the + normal (word aligned) compare loop, starting at the second word, + we need to adjust the length (rN) and special case the loop +- versioning for the first word. This insures that the loop count is ++ versioning for the first word. This ensures that the loop count is + correct and the first word (shifted) is in the expected register pair. */ +- .align 4 ++ .align 4 + L(samealignment): + clrrwi rSTR1, rSTR1, 2 + clrrwi rSTR2, rSTR2, 2 + beq cr5, L(Waligned) +- add rN, rN, rBITDIF +- slwi r11, rBITDIF, 3 +- srwi rTMP, rN, 4 /* Divide by 16 */ +- andi. rBITDIF, rN, 12 /* Get the word remainder */ ++ add rN, rN, r12 ++ slwi rWORD6, r12, 3 ++ srwi r0, rN, 4 /* Divide by 16 */ ++ andi. r12, rN, 12 /* Get the word remainder */ ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD1, 0(rSTR1) + lwz rWORD2, 0(rSTR2) +- cmplwi cr1, rBITDIF, 8 ++#endif ++ cmplwi cr1, r12, 8 + cmplwi cr7, rN, 16 + clrlwi rN, rN, 30 + beq L(dPs4) +- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group */ ++ mtctr r0 /* Power4 wants mtctr 1st in dispatch group */ + bgt cr1, L(dPs3) + beq cr1, L(dPs2) + + /* Remainder is 4 */ +- .align 3 ++ .align 3 + L(dsP1): +- slw rWORD5, rWORD1, r11 +- slw rWORD6, rWORD2, r11 ++ slw rWORD5, rWORD1, rWORD6 ++ slw rWORD6, rWORD2, rWORD6 + cmplw cr5, rWORD5, rWORD6 + blt cr7, L(dP1x) + /* Do something useful in this cycle since we have to branch anyway. */ ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD1, 4(rSTR1) + lwz rWORD2, 4(rSTR2) +- cmplw cr0, rWORD1, rWORD2 ++#endif ++ cmplw cr7, rWORD1, rWORD2 + b L(dP1e) + /* Remainder is 8 */ +- .align 4 ++ .align 4 + L(dPs2): +- slw rWORD5, rWORD1, r11 +- slw rWORD6, rWORD2, r11 ++ slw rWORD5, rWORD1, rWORD6 ++ slw rWORD6, rWORD2, rWORD6 + cmplw cr6, rWORD5, rWORD6 + blt cr7, L(dP2x) + /* Do something useful in this cycle since we have to branch anyway. */ ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD7, 0, rSTR1 ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD7, 4(rSTR1) + lwz rWORD8, 4(rSTR2) ++#endif + cmplw cr5, rWORD7, rWORD8 + b L(dP2e) + /* Remainder is 12 */ +- .align 4 ++ .align 4 + L(dPs3): +- slw rWORD3, rWORD1, r11 +- slw rWORD4, rWORD2, r11 ++ slw rWORD3, rWORD1, rWORD6 ++ slw rWORD4, rWORD2, rWORD6 + cmplw cr1, rWORD3, rWORD4 + b L(dP3e) + /* Count is a multiple of 16, remainder is 0 */ +- .align 4 ++ .align 4 + L(dPs4): +- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group */ +- slw rWORD1, rWORD1, r11 +- slw rWORD2, rWORD2, r11 +- cmplw cr0, rWORD1, rWORD2 ++ mtctr r0 /* Power4 wants mtctr 1st in dispatch group */ ++ slw rWORD1, rWORD1, rWORD6 ++ slw rWORD2, rWORD2, rWORD6 ++ cmplw cr7, rWORD1, rWORD2 + b L(dP4e) + + /* At this point we know both strings are word aligned and the + compare length is at least 8 bytes. */ +- .align 4 ++ .align 4 + L(Waligned): +- andi. rBITDIF, rN, 12 /* Get the word remainder */ +- srwi rTMP, rN, 4 /* Divide by 16 */ +- cmplwi cr1, rBITDIF, 8 ++ andi. r12, rN, 12 /* Get the word remainder */ ++ srwi r0, rN, 4 /* Divide by 16 */ ++ cmplwi cr1, r12, 8 + cmplwi cr7, rN, 16 + clrlwi rN, rN, 30 + beq L(dP4) +@@ -147,177 +168,352 @@ + beq cr1, L(dP2) + + /* Remainder is 4 */ +- .align 4 ++ .align 4 + L(dP1): +- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group */ ++ mtctr r0 /* Power4 wants mtctr 1st in dispatch group */ + /* Normally we'd use rWORD7/rWORD8 here, but since we might exit early + (8-15 byte compare), we want to use only volatile registers. This + means we can avoid restoring non-volatile registers since we did not + change any on the early exit path. The key here is the non-early + exit path only cares about the condition code (cr5), not about which + register pair was used. */ ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD5, 0, rSTR1 ++ lwbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD5, 0(rSTR1) + lwz rWORD6, 0(rSTR2) ++#endif + cmplw cr5, rWORD5, rWORD6 + blt cr7, L(dP1x) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD1, 4(rSTR1) + lwz rWORD2, 4(rSTR2) +- cmplw cr0, rWORD1, rWORD2 ++#endif ++ cmplw cr7, rWORD1, rWORD2 + L(dP1e): ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD3, 0, rSTR1 ++ lwbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD3, 8(rSTR1) + lwz rWORD4, 8(rSTR2) ++#endif + cmplw cr1, rWORD3, rWORD4 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD5, 0, rSTR1 ++ lwbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD5, 12(rSTR1) + lwz rWORD6, 12(rSTR2) ++#endif + cmplw cr6, rWORD5, rWORD6 +- bne cr5, L(dLcr5) +- bne cr0, L(dLcr0) +- ++ bne cr5, L(dLcr5x) ++ bne cr7, L(dLcr7x) ++ ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD7, 0, rSTR1 ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwzu rWORD7, 16(rSTR1) + lwzu rWORD8, 16(rSTR2) ++#endif + bne cr1, L(dLcr1) + cmplw cr5, rWORD7, rWORD8 + bdnz L(dLoop) + bne cr6, L(dLcr6) +- lwz r30,44(1) +- lwz r31,48(1) +- .align 3 ++ lwz rWORD7, 44(r1) ++ lwz rWORD8, 48(r1) ++ .align 3 + L(dP1x): + slwi. r12, rN, 3 +- bne cr5, L(dLcr5) ++ bne cr5, L(dLcr5x) + subfic rN, r12, 32 /* Shift count is 32 - (rN * 8). */ +- lwz 1,0(1) ++ addi 1, 1, 64 ++ cfi_adjust_cfa_offset(-64) + bne L(d00) + li rRTN, 0 + blr + + /* Remainder is 8 */ +- .align 4 ++ .align 4 ++ cfi_adjust_cfa_offset(64) + L(dP2): +- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group */ ++ mtctr r0 /* Power4 wants mtctr 1st in dispatch group */ ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD5, 0, rSTR1 ++ lwbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD5, 0(rSTR1) + lwz rWORD6, 0(rSTR2) ++#endif + cmplw cr6, rWORD5, rWORD6 + blt cr7, L(dP2x) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD7, 0, rSTR1 ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD7, 4(rSTR1) + lwz rWORD8, 4(rSTR2) ++#endif + cmplw cr5, rWORD7, rWORD8 + L(dP2e): ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD1, 8(rSTR1) + lwz rWORD2, 8(rSTR2) +- cmplw cr0, rWORD1, rWORD2 ++#endif ++ cmplw cr7, rWORD1, rWORD2 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD3, 0, rSTR1 ++ lwbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD3, 12(rSTR1) + lwz rWORD4, 12(rSTR2) ++#endif + cmplw cr1, rWORD3, rWORD4 ++#ifndef __LITTLE_ENDIAN__ + addi rSTR1, rSTR1, 4 + addi rSTR2, rSTR2, 4 ++#endif + bne cr6, L(dLcr6) + bne cr5, L(dLcr5) + b L(dLoop2) + /* Again we are on a early exit path (16-23 byte compare), we want to + only use volatile registers and avoid restoring non-volatile + registers. */ +- .align 4 ++ .align 4 + L(dP2x): ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD3, 0, rSTR1 ++ lwbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD3, 4(rSTR1) + lwz rWORD4, 4(rSTR2) +- cmplw cr5, rWORD3, rWORD4 ++#endif ++ cmplw cr1, rWORD3, rWORD4 + slwi. r12, rN, 3 +- bne cr6, L(dLcr6) ++ bne cr6, L(dLcr6x) ++#ifndef __LITTLE_ENDIAN__ + addi rSTR1, rSTR1, 4 + addi rSTR2, rSTR2, 4 +- bne cr5, L(dLcr5) ++#endif ++ bne cr1, L(dLcr1x) + subfic rN, r12, 32 /* Shift count is 32 - (rN * 8). */ +- lwz 1,0(1) ++ addi 1, 1, 64 ++ cfi_adjust_cfa_offset(-64) + bne L(d00) + li rRTN, 0 + blr + + /* Remainder is 12 */ +- .align 4 ++ .align 4 ++ cfi_adjust_cfa_offset(64) + L(dP3): +- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group */ ++ mtctr r0 /* Power4 wants mtctr 1st in dispatch group */ ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD3, 0, rSTR1 ++ lwbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD3, 0(rSTR1) + lwz rWORD4, 0(rSTR2) ++#endif + cmplw cr1, rWORD3, rWORD4 + L(dP3e): ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD5, 0, rSTR1 ++ lwbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD5, 4(rSTR1) + lwz rWORD6, 4(rSTR2) ++#endif + cmplw cr6, rWORD5, rWORD6 + blt cr7, L(dP3x) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD7, 0, rSTR1 ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD7, 8(rSTR1) + lwz rWORD8, 8(rSTR2) ++#endif + cmplw cr5, rWORD7, rWORD8 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD1, 12(rSTR1) + lwz rWORD2, 12(rSTR2) +- cmplw cr0, rWORD1, rWORD2 ++#endif ++ cmplw cr7, rWORD1, rWORD2 ++#ifndef __LITTLE_ENDIAN__ + addi rSTR1, rSTR1, 8 + addi rSTR2, rSTR2, 8 ++#endif + bne cr1, L(dLcr1) + bne cr6, L(dLcr6) + b L(dLoop1) + /* Again we are on a early exit path (24-31 byte compare), we want to + only use volatile registers and avoid restoring non-volatile + registers. */ +- .align 4 ++ .align 4 + L(dP3x): ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD1, 8(rSTR1) + lwz rWORD2, 8(rSTR2) +- cmplw cr5, rWORD1, rWORD2 ++#endif ++ cmplw cr7, rWORD1, rWORD2 + slwi. r12, rN, 3 +- bne cr1, L(dLcr1) ++ bne cr1, L(dLcr1x) ++#ifndef __LITTLE_ENDIAN__ + addi rSTR1, rSTR1, 8 + addi rSTR2, rSTR2, 8 +- bne cr6, L(dLcr6) ++#endif ++ bne cr6, L(dLcr6x) + subfic rN, r12, 32 /* Shift count is 32 - (rN * 8). */ +- bne cr5, L(dLcr5) +- lwz 1,0(1) ++ bne cr7, L(dLcr7x) ++ addi 1, 1, 64 ++ cfi_adjust_cfa_offset(-64) + bne L(d00) + li rRTN, 0 + blr + + /* Count is a multiple of 16, remainder is 0 */ +- .align 4 ++ .align 4 ++ cfi_adjust_cfa_offset(64) + L(dP4): +- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group */ ++ mtctr r0 /* Power4 wants mtctr 1st in dispatch group */ ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD1, 0(rSTR1) + lwz rWORD2, 0(rSTR2) +- cmplw cr0, rWORD1, rWORD2 ++#endif ++ cmplw cr7, rWORD1, rWORD2 + L(dP4e): ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD3, 0, rSTR1 ++ lwbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD3, 4(rSTR1) + lwz rWORD4, 4(rSTR2) ++#endif + cmplw cr1, rWORD3, rWORD4 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD5, 0, rSTR1 ++ lwbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD5, 8(rSTR1) + lwz rWORD6, 8(rSTR2) ++#endif + cmplw cr6, rWORD5, rWORD6 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD7, 0, rSTR1 ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwzu rWORD7, 12(rSTR1) + lwzu rWORD8, 12(rSTR2) ++#endif + cmplw cr5, rWORD7, rWORD8 +- bne cr0, L(dLcr0) ++ bne cr7, L(dLcr7) + bne cr1, L(dLcr1) + bdz- L(d24) /* Adjust CTR as we start with +4 */ + /* This is the primary loop */ +- .align 4 ++ .align 4 + L(dLoop): ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD1, 4(rSTR1) + lwz rWORD2, 4(rSTR2) ++#endif + cmplw cr1, rWORD3, rWORD4 + bne cr6, L(dLcr6) + L(dLoop1): ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD3, 0, rSTR1 ++ lwbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD3, 8(rSTR1) + lwz rWORD4, 8(rSTR2) ++#endif + cmplw cr6, rWORD5, rWORD6 + bne cr5, L(dLcr5) + L(dLoop2): ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD5, 0, rSTR1 ++ lwbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD5, 12(rSTR1) + lwz rWORD6, 12(rSTR2) ++#endif + cmplw cr5, rWORD7, rWORD8 +- bne cr0, L(dLcr0) ++ bne cr7, L(dLcr7) + L(dLoop3): ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD7, 0, rSTR1 ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwzu rWORD7, 16(rSTR1) + lwzu rWORD8, 16(rSTR2) ++#endif + bne- cr1, L(dLcr1) +- cmplw cr0, rWORD1, rWORD2 ++ cmplw cr7, rWORD1, rWORD2 + bdnz+ L(dLoop) + + L(dL4): +@@ -327,7 +523,7 @@ + bne cr5, L(dLcr5) + cmplw cr5, rWORD7, rWORD8 + L(d44): +- bne cr0, L(dLcr0) ++ bne cr7, L(dLcr7) + L(d34): + bne cr1, L(dLcr1) + L(d24): +@@ -336,69 +532,82 @@ + slwi. r12, rN, 3 + bne cr5, L(dLcr5) + L(d04): +- lwz r30,44(1) +- lwz r31,48(1) +- lwz 1,0(1) ++ lwz rWORD7, 44(r1) ++ lwz rWORD8, 48(r1) ++ addi 1, 1, 64 ++ cfi_adjust_cfa_offset(-64) + subfic rN, r12, 32 /* Shift count is 32 - (rN * 8). */ + beq L(zeroLength) + /* At this point we have a remainder of 1 to 3 bytes to compare. Since + we are aligned it is safe to load the whole word, and use +- shift right to eliminate bits beyond the compare length. */ ++ shift right to eliminate bits beyond the compare length. */ + L(d00): ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD1, 4(rSTR1) + lwz rWORD2, 4(rSTR2) ++#endif + srw rWORD1, rWORD1, rN + srw rWORD2, rWORD2, rN +- cmplw rWORD1,rWORD2 +- li rRTN,0 +- beqlr +- li rRTN,1 +- bgtlr +- li rRTN,-1 +- blr +- +- .align 4 +-L(dLcr0): +- lwz r30,44(1) +- lwz r31,48(1) ++ sub rRTN, rWORD1, rWORD2 ++ blr ++ ++ .align 4 ++ cfi_adjust_cfa_offset(64) ++L(dLcr7): ++ lwz rWORD7, 44(r1) ++ lwz rWORD8, 48(r1) ++L(dLcr7x): + li rRTN, 1 +- lwz 1,0(1) +- bgtlr cr0 ++ addi 1, 1, 64 ++ cfi_adjust_cfa_offset(-64) ++ bgtlr cr7 + li rRTN, -1 + blr +- .align 4 ++ .align 4 ++ cfi_adjust_cfa_offset(64) + L(dLcr1): +- lwz r30,44(1) +- lwz r31,48(1) ++ lwz rWORD7, 44(r1) ++ lwz rWORD8, 48(r1) ++L(dLcr1x): + li rRTN, 1 +- lwz 1,0(1) ++ addi 1, 1, 64 ++ cfi_adjust_cfa_offset(-64) + bgtlr cr1 + li rRTN, -1 + blr +- .align 4 ++ .align 4 ++ cfi_adjust_cfa_offset(64) + L(dLcr6): +- lwz r30,44(1) +- lwz r31,48(1) ++ lwz rWORD7, 44(r1) ++ lwz rWORD8, 48(r1) ++L(dLcr6x): + li rRTN, 1 +- lwz 1,0(1) ++ addi 1, 1, 64 ++ cfi_adjust_cfa_offset(-64) + bgtlr cr6 + li rRTN, -1 + blr +- .align 4 ++ .align 4 ++ cfi_adjust_cfa_offset(64) + L(dLcr5): +- lwz r30,44(1) +- lwz r31,48(1) ++ lwz rWORD7, 44(r1) ++ lwz rWORD8, 48(r1) + L(dLcr5x): + li rRTN, 1 +- lwz 1,0(1) ++ addi 1, 1, 64 ++ cfi_adjust_cfa_offset(-64) + bgtlr cr5 + li rRTN, -1 + blr + +- .align 4 ++ .align 4 + L(bytealigned): +- cfi_adjust_cfa_offset(-64) +- mtctr rN /* Power4 wants mtctr 1st in dispatch group */ ++ mtctr rN /* Power4 wants mtctr 1st in dispatch group */ + + /* We need to prime this loop. This loop is swing modulo scheduled + to avoid pipe delays. The dependent instruction latencies (load to +@@ -413,7 +622,7 @@ + lbz rWORD1, 0(rSTR1) + lbz rWORD2, 0(rSTR2) + bdz- L(b11) +- cmplw cr0, rWORD1, rWORD2 ++ cmplw cr7, rWORD1, rWORD2 + lbz rWORD3, 1(rSTR1) + lbz rWORD4, 1(rSTR2) + bdz- L(b12) +@@ -421,11 +630,11 @@ + lbzu rWORD5, 2(rSTR1) + lbzu rWORD6, 2(rSTR2) + bdz- L(b13) +- .align 4 ++ .align 4 + L(bLoop): + lbzu rWORD1, 1(rSTR1) + lbzu rWORD2, 1(rSTR2) +- bne- cr0, L(bLcr0) ++ bne- cr7, L(bLcr7) + + cmplw cr6, rWORD5, rWORD6 + bdz- L(b3i) +@@ -434,7 +643,7 @@ + lbzu rWORD4, 1(rSTR2) + bne- cr1, L(bLcr1) + +- cmplw cr0, rWORD1, rWORD2 ++ cmplw cr7, rWORD1, rWORD2 + bdz- L(b2i) + + lbzu rWORD5, 1(rSTR1) +@@ -451,23 +660,23 @@ + tested. In this case we must complete the pending operations + before returning. */ + L(b1i): +- bne- cr0, L(bLcr0) ++ bne- cr7, L(bLcr7) + bne- cr1, L(bLcr1) + b L(bx56) +- .align 4 ++ .align 4 + L(b2i): + bne- cr6, L(bLcr6) +- bne- cr0, L(bLcr0) ++ bne- cr7, L(bLcr7) + b L(bx34) +- .align 4 ++ .align 4 + L(b3i): + bne- cr1, L(bLcr1) + bne- cr6, L(bLcr6) + b L(bx12) +- .align 4 +-L(bLcr0): ++ .align 4 ++L(bLcr7): + li rRTN, 1 +- bgtlr cr0 ++ bgtlr cr7 + li rRTN, -1 + blr + L(bLcr1): +@@ -482,36 +691,31 @@ + blr + + L(b13): +- bne- cr0, L(bx12) ++ bne- cr7, L(bx12) + bne- cr1, L(bx34) + L(bx56): + sub rRTN, rWORD5, rWORD6 + blr + nop + L(b12): +- bne- cr0, L(bx12) ++ bne- cr7, L(bx12) + L(bx34): + sub rRTN, rWORD3, rWORD4 + blr +- + L(b11): + L(bx12): + sub rRTN, rWORD1, rWORD2 + blr +- +- .align 4 +-L(zeroLengthReturn): +- ++ .align 4 + L(zeroLength): + li rRTN, 0 + blr + +- cfi_adjust_cfa_offset(64) +- .align 4 ++ .align 4 + /* At this point we know the strings have different alignment and the +- compare length is at least 8 bytes. rBITDIF contains the low order ++ compare length is at least 8 bytes. r12 contains the low order + 2 bits of rSTR1 and cr5 contains the result of the logical compare +- of rBITDIF to 0. If rBITDIF == 0 then rStr1 is word aligned and can ++ of r12 to 0. If r12 == 0 then rStr1 is word aligned and can + perform the Wunaligned loop. + + Otherwise we know that rSTR1 is not aready word aligned yet. +@@ -520,79 +724,88 @@ + eliminate bits preceeding the first byte. Since we want to join the + normal (Wualigned) compare loop, starting at the second word, + we need to adjust the length (rN) and special case the loop +- versioning for the first W. This insures that the loop count is ++ versioning for the first W. This ensures that the loop count is + correct and the first W (shifted) is in the expected resister pair. */ + #define rSHL r29 /* Unaligned shift left count. */ + #define rSHR r28 /* Unaligned shift right count. */ +-#define rB r27 /* Left rotation temp for rWORD2. */ +-#define rD r26 /* Left rotation temp for rWORD4. */ +-#define rF r25 /* Left rotation temp for rWORD6. */ +-#define rH r24 /* Left rotation temp for rWORD8. */ +-#define rA r0 /* Right rotation temp for rWORD2. */ +-#define rC r12 /* Right rotation temp for rWORD4. */ +-#define rE r0 /* Right rotation temp for rWORD6. */ +-#define rG r12 /* Right rotation temp for rWORD8. */ ++#define rWORD8_SHIFT r27 /* Left rotation temp for rWORD2. */ ++#define rWORD2_SHIFT r26 /* Left rotation temp for rWORD4. */ ++#define rWORD4_SHIFT r25 /* Left rotation temp for rWORD6. */ ++#define rWORD6_SHIFT r24 /* Left rotation temp for rWORD8. */ ++ cfi_adjust_cfa_offset(64) + L(unaligned): +- stw r29,40(r1) +- cfi_offset(r29,(40-64)) ++ stw rSHL, 40(r1) ++ cfi_offset(rSHL, (40-64)) + clrlwi rSHL, rSTR2, 30 +- stw r28,36(r1) +- cfi_offset(r28,(36-64)) ++ stw rSHR, 36(r1) ++ cfi_offset(rSHR, (36-64)) + beq cr5, L(Wunaligned) +- stw r27,32(r1) +- cfi_offset(r27,(32-64)) ++ stw rWORD8_SHIFT, 32(r1) ++ cfi_offset(rWORD8_SHIFT, (32-64)) + /* Adjust the logical start of rSTR2 to compensate for the extra bits + in the 1st rSTR1 W. */ +- sub r27, rSTR2, rBITDIF ++ sub rWORD8_SHIFT, rSTR2, r12 + /* But do not attempt to address the W before that W that contains + the actual start of rSTR2. */ + clrrwi rSTR2, rSTR2, 2 +- stw r26,28(r1) +- cfi_offset(r26,(28-64)) +-/* Compute the left/right shift counts for the unalign rSTR2, ++ stw rWORD2_SHIFT, 28(r1) ++ cfi_offset(rWORD2_SHIFT, (28-64)) ++/* Compute the left/right shift counts for the unaligned rSTR2, + compensating for the logical (W aligned) start of rSTR1. */ +- clrlwi rSHL, r27, 30 ++ clrlwi rSHL, rWORD8_SHIFT, 30 + clrrwi rSTR1, rSTR1, 2 +- stw r25,24(r1) +- cfi_offset(r25,(24-64)) ++ stw rWORD4_SHIFT, 24(r1) ++ cfi_offset(rWORD4_SHIFT, (24-64)) + slwi rSHL, rSHL, 3 +- cmplw cr5, r27, rSTR2 +- add rN, rN, rBITDIF +- slwi r11, rBITDIF, 3 +- stw r24,20(r1) +- cfi_offset(r24,(20-64)) ++ cmplw cr5, rWORD8_SHIFT, rSTR2 ++ add rN, rN, r12 ++ slwi rWORD6, r12, 3 ++ stw rWORD6_SHIFT, 20(r1) ++ cfi_offset(rWORD6_SHIFT, (20-64)) + subfic rSHR, rSHL, 32 +- srwi rTMP, rN, 4 /* Divide by 16 */ +- andi. rBITDIF, rN, 12 /* Get the W remainder */ ++ srwi r0, rN, 4 /* Divide by 16 */ ++ andi. r12, rN, 12 /* Get the W remainder */ + /* We normally need to load 2 Ws to start the unaligned rSTR2, but in + this special case those bits may be discarded anyway. Also we + must avoid loading a W where none of the bits are part of rSTR2 as + this may cross a page boundary and cause a page fault. */ + li rWORD8, 0 + blt cr5, L(dus0) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD8, 0(rSTR2) +- la rSTR2, 4(rSTR2) ++ addi rSTR2, rSTR2, 4 ++#endif + slw rWORD8, rWORD8, rSHL + + L(dus0): ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD1, 0(rSTR1) + lwz rWORD2, 0(rSTR2) +- cmplwi cr1, rBITDIF, 8 ++#endif ++ cmplwi cr1, r12, 8 + cmplwi cr7, rN, 16 +- srw rG, rWORD2, rSHR ++ srw r12, rWORD2, rSHR + clrlwi rN, rN, 30 + beq L(duPs4) +- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group */ +- or rWORD8, rG, rWORD8 ++ mtctr r0 /* Power4 wants mtctr 1st in dispatch group */ ++ or rWORD8, r12, rWORD8 + bgt cr1, L(duPs3) + beq cr1, L(duPs2) + + /* Remainder is 4 */ +- .align 4 ++ .align 4 + L(dusP1): +- slw rB, rWORD2, rSHL +- slw rWORD7, rWORD1, r11 +- slw rWORD8, rWORD8, r11 ++ slw rWORD8_SHIFT, rWORD2, rSHL ++ slw rWORD7, rWORD1, rWORD6 ++ slw rWORD8, rWORD8, rWORD6 + bge cr7, L(duP1e) + /* At this point we exit early with the first word compare + complete and remainder of 0 to 3 bytes. See L(du14) for details on +@@ -602,95 +815,133 @@ + bne cr5, L(duLcr5) + cmplw cr7, rN, rSHR + beq L(duZeroReturn) +- li rA, 0 ++ li r0, 0 + ble cr7, L(dutrim) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD2, 4(rSTR2) +- srw rA, rWORD2, rSHR ++#endif ++ srw r0, rWORD2, rSHR + b L(dutrim) + /* Remainder is 8 */ +- .align 4 ++ .align 4 + L(duPs2): +- slw rH, rWORD2, rSHL +- slw rWORD5, rWORD1, r11 +- slw rWORD6, rWORD8, r11 ++ slw rWORD6_SHIFT, rWORD2, rSHL ++ slw rWORD5, rWORD1, rWORD6 ++ slw rWORD6, rWORD8, rWORD6 + b L(duP2e) + /* Remainder is 12 */ +- .align 4 ++ .align 4 + L(duPs3): +- slw rF, rWORD2, rSHL +- slw rWORD3, rWORD1, r11 +- slw rWORD4, rWORD8, r11 ++ slw rWORD4_SHIFT, rWORD2, rSHL ++ slw rWORD3, rWORD1, rWORD6 ++ slw rWORD4, rWORD8, rWORD6 + b L(duP3e) + /* Count is a multiple of 16, remainder is 0 */ +- .align 4 ++ .align 4 + L(duPs4): +- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group */ +- or rWORD8, rG, rWORD8 +- slw rD, rWORD2, rSHL +- slw rWORD1, rWORD1, r11 +- slw rWORD2, rWORD8, r11 ++ mtctr r0 /* Power4 wants mtctr 1st in dispatch group */ ++ or rWORD8, r12, rWORD8 ++ slw rWORD2_SHIFT, rWORD2, rSHL ++ slw rWORD1, rWORD1, rWORD6 ++ slw rWORD2, rWORD8, rWORD6 + b L(duP4e) + + /* At this point we know rSTR1 is word aligned and the + compare length is at least 8 bytes. */ +- .align 4 ++ .align 4 + L(Wunaligned): +- stw r27,32(r1) +- cfi_offset(r27,(32-64)) ++ stw rWORD8_SHIFT, 32(r1) ++ cfi_offset(rWORD8_SHIFT, (32-64)) + clrrwi rSTR2, rSTR2, 2 +- stw r26,28(r1) +- cfi_offset(r26,(28-64)) +- srwi rTMP, rN, 4 /* Divide by 16 */ +- stw r25,24(r1) +- cfi_offset(r25,(24-64)) +- andi. rBITDIF, rN, 12 /* Get the W remainder */ +- stw r24,20(r1) +- cfi_offset(r24,(20-64)) ++ stw rWORD2_SHIFT, 28(r1) ++ cfi_offset(rWORD2_SHIFT, (28-64)) ++ srwi r0, rN, 4 /* Divide by 16 */ ++ stw rWORD4_SHIFT, 24(r1) ++ cfi_offset(rWORD4_SHIFT, (24-64)) ++ andi. r12, rN, 12 /* Get the W remainder */ ++ stw rWORD6_SHIFT, 20(r1) ++ cfi_offset(rWORD6_SHIFT, (20-64)) + slwi rSHL, rSHL, 3 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD6, 0, rSTR2 ++ addi rSTR2, rSTR2, 4 ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD6, 0(rSTR2) + lwzu rWORD8, 4(rSTR2) +- cmplwi cr1, rBITDIF, 8 ++#endif ++ cmplwi cr1, r12, 8 + cmplwi cr7, rN, 16 + clrlwi rN, rN, 30 + subfic rSHR, rSHL, 32 +- slw rH, rWORD6, rSHL ++ slw rWORD6_SHIFT, rWORD6, rSHL + beq L(duP4) +- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group */ ++ mtctr r0 /* Power4 wants mtctr 1st in dispatch group */ + bgt cr1, L(duP3) + beq cr1, L(duP2) + + /* Remainder is 4 */ +- .align 4 ++ .align 4 + L(duP1): +- srw rG, rWORD8, rSHR ++ srw r12, rWORD8, rSHR ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD7, 0, rSTR1 ++ addi rSTR1, rSTR1, 4 ++#else + lwz rWORD7, 0(rSTR1) +- slw rB, rWORD8, rSHL +- or rWORD8, rG, rH ++#endif ++ slw rWORD8_SHIFT, rWORD8, rSHL ++ or rWORD8, r12, rWORD6_SHIFT + blt cr7, L(duP1x) + L(duP1e): ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD1, 4(rSTR1) + lwz rWORD2, 4(rSTR2) ++#endif + cmplw cr5, rWORD7, rWORD8 +- srw rA, rWORD2, rSHR +- slw rD, rWORD2, rSHL +- or rWORD2, rA, rB ++ srw r0, rWORD2, rSHR ++ slw rWORD2_SHIFT, rWORD2, rSHL ++ or rWORD2, r0, rWORD8_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD3, 0, rSTR1 ++ lwbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD3, 8(rSTR1) + lwz rWORD4, 8(rSTR2) +- cmplw cr0, rWORD1, rWORD2 +- srw rC, rWORD4, rSHR +- slw rF, rWORD4, rSHL ++#endif ++ cmplw cr7, rWORD1, rWORD2 ++ srw r12, rWORD4, rSHR ++ slw rWORD4_SHIFT, rWORD4, rSHL + bne cr5, L(duLcr5) +- or rWORD4, rC, rD ++ or rWORD4, r12, rWORD2_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD5, 0, rSTR1 ++ lwbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD5, 12(rSTR1) + lwz rWORD6, 12(rSTR2) ++#endif + cmplw cr1, rWORD3, rWORD4 +- srw rE, rWORD6, rSHR +- slw rH, rWORD6, rSHL +- bne cr0, L(duLcr0) +- or rWORD6, rE, rF ++ srw r0, rWORD6, rSHR ++ slw rWORD6_SHIFT, rWORD6, rSHL ++ bne cr7, L(duLcr7) ++ or rWORD6, r0, rWORD4_SHIFT + cmplw cr6, rWORD5, rWORD6 + b L(duLoop3) +- .align 4 ++ .align 4 + /* At this point we exit early with the first word compare + complete and remainder of 0 to 3 bytes. See L(du14) for details on + how we handle the remaining bytes. */ +@@ -700,186 +951,321 @@ + bne cr5, L(duLcr5) + cmplw cr7, rN, rSHR + beq L(duZeroReturn) +- li rA, 0 ++ li r0, 0 + ble cr7, L(dutrim) +- ld rWORD2, 8(rSTR2) +- srw rA, rWORD2, rSHR ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD2, 8(rSTR2) ++#endif ++ srw r0, rWORD2, rSHR + b L(dutrim) + /* Remainder is 8 */ +- .align 4 ++ .align 4 + L(duP2): +- srw rE, rWORD8, rSHR ++ srw r0, rWORD8, rSHR ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD5, 0, rSTR1 ++ addi rSTR1, rSTR1, 4 ++#else + lwz rWORD5, 0(rSTR1) +- or rWORD6, rE, rH +- slw rH, rWORD8, rSHL ++#endif ++ or rWORD6, r0, rWORD6_SHIFT ++ slw rWORD6_SHIFT, rWORD8, rSHL + L(duP2e): ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD7, 0, rSTR1 ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD7, 4(rSTR1) + lwz rWORD8, 4(rSTR2) ++#endif + cmplw cr6, rWORD5, rWORD6 +- srw rG, rWORD8, rSHR +- slw rB, rWORD8, rSHL +- or rWORD8, rG, rH ++ srw r12, rWORD8, rSHR ++ slw rWORD8_SHIFT, rWORD8, rSHL ++ or rWORD8, r12, rWORD6_SHIFT + blt cr7, L(duP2x) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD1, 8(rSTR1) + lwz rWORD2, 8(rSTR2) ++#endif + cmplw cr5, rWORD7, rWORD8 + bne cr6, L(duLcr6) +- srw rA, rWORD2, rSHR +- slw rD, rWORD2, rSHL +- or rWORD2, rA, rB ++ srw r0, rWORD2, rSHR ++ slw rWORD2_SHIFT, rWORD2, rSHL ++ or rWORD2, r0, rWORD8_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD3, 0, rSTR1 ++ lwbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD3, 12(rSTR1) + lwz rWORD4, 12(rSTR2) +- cmplw cr0, rWORD1, rWORD2 ++#endif ++ cmplw cr7, rWORD1, rWORD2 + bne cr5, L(duLcr5) +- srw rC, rWORD4, rSHR +- slw rF, rWORD4, rSHL +- or rWORD4, rC, rD ++ srw r12, rWORD4, rSHR ++ slw rWORD4_SHIFT, rWORD4, rSHL ++ or rWORD4, r12, rWORD2_SHIFT ++#ifndef __LITTLE_ENDIAN__ + addi rSTR1, rSTR1, 4 + addi rSTR2, rSTR2, 4 ++#endif + cmplw cr1, rWORD3, rWORD4 + b L(duLoop2) +- .align 4 ++ .align 4 + L(duP2x): + cmplw cr5, rWORD7, rWORD8 ++#ifndef __LITTLE_ENDIAN__ + addi rSTR1, rSTR1, 4 + addi rSTR2, rSTR2, 4 ++#endif + bne cr6, L(duLcr6) + slwi. rN, rN, 3 + bne cr5, L(duLcr5) + cmplw cr7, rN, rSHR + beq L(duZeroReturn) +- li rA, 0 ++ li r0, 0 + ble cr7, L(dutrim) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD2, 4(rSTR2) +- srw rA, rWORD2, rSHR ++#endif ++ srw r0, rWORD2, rSHR + b L(dutrim) + + /* Remainder is 12 */ +- .align 4 ++ .align 4 + L(duP3): +- srw rC, rWORD8, rSHR ++ srw r12, rWORD8, rSHR ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD3, 0, rSTR1 ++ addi rSTR1, rSTR1, 4 ++#else + lwz rWORD3, 0(rSTR1) +- slw rF, rWORD8, rSHL +- or rWORD4, rC, rH ++#endif ++ slw rWORD4_SHIFT, rWORD8, rSHL ++ or rWORD4, r12, rWORD6_SHIFT + L(duP3e): ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD5, 0, rSTR1 ++ lwbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD5, 4(rSTR1) + lwz rWORD6, 4(rSTR2) ++#endif + cmplw cr1, rWORD3, rWORD4 +- srw rE, rWORD6, rSHR +- slw rH, rWORD6, rSHL +- or rWORD6, rE, rF ++ srw r0, rWORD6, rSHR ++ slw rWORD6_SHIFT, rWORD6, rSHL ++ or rWORD6, r0, rWORD4_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD7, 0, rSTR1 ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD7, 8(rSTR1) + lwz rWORD8, 8(rSTR2) ++#endif + cmplw cr6, rWORD5, rWORD6 + bne cr1, L(duLcr1) +- srw rG, rWORD8, rSHR +- slw rB, rWORD8, rSHL +- or rWORD8, rG, rH ++ srw r12, rWORD8, rSHR ++ slw rWORD8_SHIFT, rWORD8, rSHL ++ or rWORD8, r12, rWORD6_SHIFT + blt cr7, L(duP3x) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD1, 12(rSTR1) + lwz rWORD2, 12(rSTR2) ++#endif + cmplw cr5, rWORD7, rWORD8 + bne cr6, L(duLcr6) +- srw rA, rWORD2, rSHR +- slw rD, rWORD2, rSHL +- or rWORD2, rA, rB ++ srw r0, rWORD2, rSHR ++ slw rWORD2_SHIFT, rWORD2, rSHL ++ or rWORD2, r0, rWORD8_SHIFT ++#ifndef __LITTLE_ENDIAN__ + addi rSTR1, rSTR1, 8 + addi rSTR2, rSTR2, 8 +- cmplw cr0, rWORD1, rWORD2 ++#endif ++ cmplw cr7, rWORD1, rWORD2 + b L(duLoop1) +- .align 4 ++ .align 4 + L(duP3x): ++#ifndef __LITTLE_ENDIAN__ + addi rSTR1, rSTR1, 8 + addi rSTR2, rSTR2, 8 ++#endif ++#if 0 ++/* Huh? We've already branched on cr1! */ + bne cr1, L(duLcr1) ++#endif + cmplw cr5, rWORD7, rWORD8 + bne cr6, L(duLcr6) + slwi. rN, rN, 3 + bne cr5, L(duLcr5) + cmplw cr7, rN, rSHR + beq L(duZeroReturn) +- li rA, 0 ++ li r0, 0 + ble cr7, L(dutrim) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD2, 4(rSTR2) +- srw rA, rWORD2, rSHR ++#endif ++ srw r0, rWORD2, rSHR + b L(dutrim) + + /* Count is a multiple of 16, remainder is 0 */ +- .align 4 ++ .align 4 + L(duP4): +- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group */ +- srw rA, rWORD8, rSHR ++ mtctr r0 /* Power4 wants mtctr 1st in dispatch group */ ++ srw r0, rWORD8, rSHR ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ addi rSTR1, rSTR1, 4 ++#else + lwz rWORD1, 0(rSTR1) +- slw rD, rWORD8, rSHL +- or rWORD2, rA, rH ++#endif ++ slw rWORD2_SHIFT, rWORD8, rSHL ++ or rWORD2, r0, rWORD6_SHIFT + L(duP4e): ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD3, 0, rSTR1 ++ lwbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD3, 4(rSTR1) + lwz rWORD4, 4(rSTR2) +- cmplw cr0, rWORD1, rWORD2 +- srw rC, rWORD4, rSHR +- slw rF, rWORD4, rSHL +- or rWORD4, rC, rD ++#endif ++ cmplw cr7, rWORD1, rWORD2 ++ srw r12, rWORD4, rSHR ++ slw rWORD4_SHIFT, rWORD4, rSHL ++ or rWORD4, r12, rWORD2_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD5, 0, rSTR1 ++ lwbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD5, 8(rSTR1) + lwz rWORD6, 8(rSTR2) ++#endif + cmplw cr1, rWORD3, rWORD4 +- bne cr0, L(duLcr0) +- srw rE, rWORD6, rSHR +- slw rH, rWORD6, rSHL +- or rWORD6, rE, rF ++ bne cr7, L(duLcr7) ++ srw r0, rWORD6, rSHR ++ slw rWORD6_SHIFT, rWORD6, rSHL ++ or rWORD6, r0, rWORD4_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD7, 0, rSTR1 ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwzu rWORD7, 12(rSTR1) + lwzu rWORD8, 12(rSTR2) ++#endif + cmplw cr6, rWORD5, rWORD6 + bne cr1, L(duLcr1) +- srw rG, rWORD8, rSHR +- slw rB, rWORD8, rSHL +- or rWORD8, rG, rH ++ srw r12, rWORD8, rSHR ++ slw rWORD8_SHIFT, rWORD8, rSHL ++ or rWORD8, r12, rWORD6_SHIFT + cmplw cr5, rWORD7, rWORD8 + bdz- L(du24) /* Adjust CTR as we start with +4 */ + /* This is the primary loop */ +- .align 4 ++ .align 4 + L(duLoop): ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD1, 4(rSTR1) + lwz rWORD2, 4(rSTR2) ++#endif + cmplw cr1, rWORD3, rWORD4 + bne cr6, L(duLcr6) +- srw rA, rWORD2, rSHR +- slw rD, rWORD2, rSHL +- or rWORD2, rA, rB ++ srw r0, rWORD2, rSHR ++ slw rWORD2_SHIFT, rWORD2, rSHL ++ or rWORD2, r0, rWORD8_SHIFT + L(duLoop1): ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD3, 0, rSTR1 ++ lwbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD3, 8(rSTR1) + lwz rWORD4, 8(rSTR2) ++#endif + cmplw cr6, rWORD5, rWORD6 + bne cr5, L(duLcr5) +- srw rC, rWORD4, rSHR +- slw rF, rWORD4, rSHL +- or rWORD4, rC, rD ++ srw r12, rWORD4, rSHR ++ slw rWORD4_SHIFT, rWORD4, rSHL ++ or rWORD4, r12, rWORD2_SHIFT + L(duLoop2): ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD5, 0, rSTR1 ++ lwbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD5, 12(rSTR1) + lwz rWORD6, 12(rSTR2) ++#endif + cmplw cr5, rWORD7, rWORD8 +- bne cr0, L(duLcr0) +- srw rE, rWORD6, rSHR +- slw rH, rWORD6, rSHL +- or rWORD6, rE, rF ++ bne cr7, L(duLcr7) ++ srw r0, rWORD6, rSHR ++ slw rWORD6_SHIFT, rWORD6, rSHL ++ or rWORD6, r0, rWORD4_SHIFT + L(duLoop3): ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD7, 0, rSTR1 ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else + lwzu rWORD7, 16(rSTR1) + lwzu rWORD8, 16(rSTR2) +- cmplw cr0, rWORD1, rWORD2 ++#endif ++ cmplw cr7, rWORD1, rWORD2 + bne- cr1, L(duLcr1) +- srw rG, rWORD8, rSHR +- slw rB, rWORD8, rSHL +- or rWORD8, rG, rH ++ srw r12, rWORD8, rSHR ++ slw rWORD8_SHIFT, rWORD8, rSHL ++ or rWORD8, r12, rWORD6_SHIFT + bdnz+ L(duLoop) + + L(duL4): ++#if 0 ++/* Huh? We've already branched on cr1! */ + bne cr1, L(duLcr1) ++#endif + cmplw cr1, rWORD3, rWORD4 + bne cr6, L(duLcr6) + cmplw cr6, rWORD5, rWORD6 + bne cr5, L(duLcr5) + cmplw cr5, rWORD7, rWORD8 + L(du44): +- bne cr0, L(duLcr0) ++ bne cr7, L(duLcr7) + L(du34): + bne cr1, L(duLcr1) + L(du24): +@@ -889,95 +1275,101 @@ + bne cr5, L(duLcr5) + /* At this point we have a remainder of 1 to 3 bytes to compare. We use + shift right to eliminate bits beyond the compare length. ++ This allows the use of word subtract to compute the final result. + + However it may not be safe to load rWORD2 which may be beyond the + string length. So we compare the bit length of the remainder to + the right shift count (rSHR). If the bit count is less than or equal + we do not need to load rWORD2 (all significant bits are already in +- rB). */ ++ rWORD8_SHIFT). */ + cmplw cr7, rN, rSHR + beq L(duZeroReturn) +- li rA, 0 ++ li r0, 0 + ble cr7, L(dutrim) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR2, rSTR2, 4 ++#else + lwz rWORD2, 4(rSTR2) +- srw rA, rWORD2, rSHR +- .align 4 ++#endif ++ srw r0, rWORD2, rSHR ++ .align 4 + L(dutrim): ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++#else + lwz rWORD1, 4(rSTR1) +- lwz r31,48(1) ++#endif ++ lwz rWORD8, 48(r1) + subfic rN, rN, 32 /* Shift count is 32 - (rN * 8). */ +- or rWORD2, rA, rB +- lwz r30,44(1) +- lwz r29,40(r1) ++ or rWORD2, r0, rWORD8_SHIFT ++ lwz rWORD7, 44(r1) ++ lwz rSHL, 40(r1) + srw rWORD1, rWORD1, rN + srw rWORD2, rWORD2, rN +- lwz r28,36(r1) +- lwz r27,32(r1) +- cmplw rWORD1,rWORD2 +- li rRTN,0 +- beq L(dureturn26) +- li rRTN,1 +- bgt L(dureturn26) +- li rRTN,-1 +- b L(dureturn26) +- .align 4 +-L(duLcr0): +- lwz r31,48(1) +- lwz r30,44(1) +- li rRTN, 1 +- bgt cr0, L(dureturn29) +- lwz r29,40(r1) +- lwz r28,36(r1) ++ lwz rSHR, 36(r1) ++ lwz rWORD8_SHIFT, 32(r1) ++ sub rRTN, rWORD1, rWORD2 ++ b L(dureturn26) ++ .align 4 ++L(duLcr7): ++ lwz rWORD8, 48(r1) ++ lwz rWORD7, 44(r1) ++ li rRTN, 1 ++ bgt cr7, L(dureturn29) ++ lwz rSHL, 40(r1) ++ lwz rSHR, 36(r1) + li rRTN, -1 + b L(dureturn27) +- .align 4 ++ .align 4 + L(duLcr1): +- lwz r31,48(1) +- lwz r30,44(1) ++ lwz rWORD8, 48(r1) ++ lwz rWORD7, 44(r1) + li rRTN, 1 + bgt cr1, L(dureturn29) +- lwz r29,40(r1) +- lwz r28,36(r1) ++ lwz rSHL, 40(r1) ++ lwz rSHR, 36(r1) + li rRTN, -1 + b L(dureturn27) +- .align 4 ++ .align 4 + L(duLcr6): +- lwz r31,48(1) +- lwz r30,44(1) ++ lwz rWORD8, 48(r1) ++ lwz rWORD7, 44(r1) + li rRTN, 1 + bgt cr6, L(dureturn29) +- lwz r29,40(r1) +- lwz r28,36(r1) ++ lwz rSHL, 40(r1) ++ lwz rSHR, 36(r1) + li rRTN, -1 + b L(dureturn27) +- .align 4 ++ .align 4 + L(duLcr5): +- lwz r31,48(1) +- lwz r30,44(1) ++ lwz rWORD8, 48(r1) ++ lwz rWORD7, 44(r1) + li rRTN, 1 + bgt cr5, L(dureturn29) +- lwz r29,40(r1) +- lwz r28,36(r1) ++ lwz rSHL, 40(r1) ++ lwz rSHR, 36(r1) + li rRTN, -1 + b L(dureturn27) + .align 3 + L(duZeroReturn): +- li rRTN,0 ++ li rRTN, 0 + .align 4 + L(dureturn): +- lwz r31,48(1) +- lwz r30,44(1) ++ lwz rWORD8, 48(r1) ++ lwz rWORD7, 44(r1) + L(dureturn29): +- lwz r29,40(r1) +- lwz r28,36(r1) ++ lwz rSHL, 40(r1) ++ lwz rSHR, 36(r1) + L(dureturn27): +- lwz r27,32(r1) ++ lwz rWORD8_SHIFT, 32(r1) + L(dureturn26): +- lwz r26,28(r1) ++ lwz rWORD2_SHIFT, 28(r1) + L(dureturn25): +- lwz r25,24(r1) +- lwz r24,20(r1) +- lwz 1,0(1) ++ lwz rWORD4_SHIFT, 24(r1) ++ lwz rWORD6_SHIFT, 20(r1) ++ addi 1, 1, 64 ++ cfi_adjust_cfa_offset(-64) + blr + END (BP_SYM (memcmp)) + +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memcmp.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memcmp.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memcmp.S 2014-05-28 19:22:37.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memcmp.S 2014-05-28 21:44:57.000000000 -0500 +@@ -25,10 +25,9 @@ + size_t size [r5]) */ + + .machine power7 +-EALIGN (BP_SYM(memcmp),4,0) ++EALIGN (BP_SYM(memcmp), 4, 0) + CALL_MCOUNT + +-#define rTMP r0 + #define rRTN r3 + #define rSTR1 r3 /* first string arg */ + #define rSTR2 r4 /* second string arg */ +@@ -39,35 +38,32 @@ + #define rWORD4 r9 /* next word in s2 */ + #define rWORD5 r10 /* next word in s1 */ + #define rWORD6 r11 /* next word in s2 */ +-#define rBITDIF r12 /* bits that differ in s1 & s2 words */ + #define rWORD7 r30 /* next word in s1 */ + #define rWORD8 r31 /* next word in s2 */ + +- xor rTMP,rSTR2,rSTR1 +- cmplwi cr6,rN,0 +- cmplwi cr1,rN,12 +- clrlwi. rTMP,rTMP,30 +- clrlwi rBITDIF,rSTR1,30 +- cmplwi cr5,rBITDIF,0 +- beq- cr6,L(zeroLength) +- dcbt 0,rSTR1 +- dcbt 0,rSTR2 +- +- /* If less than 8 bytes or not aligned, use the unaligned +- byte loop. */ +- +- blt cr1,L(bytealigned) +- stwu 1,-64(1) ++ xor r0, rSTR2, rSTR1 ++ cmplwi cr6, rN, 0 ++ cmplwi cr1, rN, 12 ++ clrlwi. r0, r0, 30 ++ clrlwi r12, rSTR1, 30 ++ cmplwi cr5, r12, 0 ++ beq- cr6, L(zeroLength) ++ dcbt 0, rSTR1 ++ dcbt 0, rSTR2 ++/* If less than 8 bytes or not aligned, use the unaligned ++ byte loop. */ ++ blt cr1, L(bytealigned) ++ stwu 1, -64(r1) + cfi_adjust_cfa_offset(64) +- stw r31,48(1) +- cfi_offset(31,(48-64)) +- stw r30,44(1) +- cfi_offset(30,(44-64)) ++ stw rWORD8, 48(r1) ++ cfi_offset(rWORD8, (48-64)) ++ stw rWORD7, 44(r1) ++ cfi_offset(rWORD7, (44-64)) + bne L(unaligned) + /* At this point we know both strings have the same alignment and the +- compare length is at least 8 bytes. rBITDIF contains the low order ++ compare length is at least 8 bytes. r12 contains the low order + 2 bits of rSTR1 and cr5 contains the result of the logical compare +- of rBITDIF to 0. If rBITDIF == 0 then we are already word ++ of r12 to 0. If r12 == 0 then we are already word + aligned and can perform the word aligned loop. + + Otherwise we know the two strings have the same alignment (but not +@@ -76,332 +72,541 @@ + eliminate bits preceeding the first byte. Since we want to join the + normal (word aligned) compare loop, starting at the second word, + we need to adjust the length (rN) and special case the loop +- versioning for the first word. This insures that the loop count is ++ versioning for the first word. This ensures that the loop count is + correct and the first word (shifted) is in the expected register pair. */ + .align 4 + L(samealignment): +- clrrwi rSTR1,rSTR1,2 +- clrrwi rSTR2,rSTR2,2 +- beq cr5,L(Waligned) +- add rN,rN,rBITDIF +- slwi r11,rBITDIF,3 +- srwi rTMP,rN,4 /* Divide by 16 */ +- andi. rBITDIF,rN,12 /* Get the word remainder */ +- lwz rWORD1,0(rSTR1) +- lwz rWORD2,0(rSTR2) +- cmplwi cr1,rBITDIF,8 +- cmplwi cr7,rN,16 +- clrlwi rN,rN,30 ++ clrrwi rSTR1, rSTR1, 2 ++ clrrwi rSTR2, rSTR2, 2 ++ beq cr5, L(Waligned) ++ add rN, rN, r12 ++ slwi rWORD6, r12, 3 ++ srwi r0, rN, 4 /* Divide by 16 */ ++ andi. r12, rN, 12 /* Get the word remainder */ ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD1, 0(rSTR1) ++ lwz rWORD2, 0(rSTR2) ++#endif ++ cmplwi cr1, r12, 8 ++ cmplwi cr7, rN, 16 ++ clrlwi rN, rN, 30 + beq L(dPs4) +- mtctr rTMP +- bgt cr1,L(dPs3) +- beq cr1,L(dPs2) ++ mtctr r0 ++ bgt cr1, L(dPs3) ++ beq cr1, L(dPs2) + + /* Remainder is 4 */ + .align 3 + L(dsP1): +- slw rWORD5,rWORD1,r11 +- slw rWORD6,rWORD2,r11 +- cmplw cr5,rWORD5,rWORD6 +- blt cr7,L(dP1x) ++ slw rWORD5, rWORD1, rWORD6 ++ slw rWORD6, rWORD2, rWORD6 ++ cmplw cr5, rWORD5, rWORD6 ++ blt cr7, L(dP1x) + /* Do something useful in this cycle since we have to branch anyway. */ +- lwz rWORD1,4(rSTR1) +- lwz rWORD2,4(rSTR2) +- cmplw cr0,rWORD1,rWORD2 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD1, 4(rSTR1) ++ lwz rWORD2, 4(rSTR2) ++#endif ++ cmplw cr7, rWORD1, rWORD2 + b L(dP1e) + /* Remainder is 8 */ + .align 4 + L(dPs2): +- slw rWORD5,rWORD1,r11 +- slw rWORD6,rWORD2,r11 +- cmplw cr6,rWORD5,rWORD6 +- blt cr7,L(dP2x) ++ slw rWORD5, rWORD1, rWORD6 ++ slw rWORD6, rWORD2, rWORD6 ++ cmplw cr6, rWORD5, rWORD6 ++ blt cr7, L(dP2x) + /* Do something useful in this cycle since we have to branch anyway. */ +- lwz rWORD7,4(rSTR1) +- lwz rWORD8,4(rSTR2) +- cmplw cr5,rWORD7,rWORD8 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD7, 0, rSTR1 ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD7, 4(rSTR1) ++ lwz rWORD8, 4(rSTR2) ++#endif ++ cmplw cr5, rWORD7, rWORD8 + b L(dP2e) + /* Remainder is 12 */ + .align 4 + L(dPs3): +- slw rWORD3,rWORD1,r11 +- slw rWORD4,rWORD2,r11 +- cmplw cr1,rWORD3,rWORD4 ++ slw rWORD3, rWORD1, rWORD6 ++ slw rWORD4, rWORD2, rWORD6 ++ cmplw cr1, rWORD3, rWORD4 + b L(dP3e) + /* Count is a multiple of 16, remainder is 0 */ + .align 4 + L(dPs4): +- mtctr rTMP +- slw rWORD1,rWORD1,r11 +- slw rWORD2,rWORD2,r11 +- cmplw cr0,rWORD1,rWORD2 ++ mtctr r0 ++ slw rWORD1, rWORD1, rWORD6 ++ slw rWORD2, rWORD2, rWORD6 ++ cmplw cr7, rWORD1, rWORD2 + b L(dP4e) + + /* At this point we know both strings are word aligned and the + compare length is at least 8 bytes. */ + .align 4 + L(Waligned): +- andi. rBITDIF,rN,12 /* Get the word remainder */ +- srwi rTMP,rN,4 /* Divide by 16 */ +- cmplwi cr1,rBITDIF,8 +- cmplwi cr7,rN,16 +- clrlwi rN,rN,30 ++ andi. r12, rN, 12 /* Get the word remainder */ ++ srwi r0, rN, 4 /* Divide by 16 */ ++ cmplwi cr1, r12, 8 ++ cmplwi cr7, rN, 16 ++ clrlwi rN, rN, 30 + beq L(dP4) +- bgt cr1,L(dP3) +- beq cr1,L(dP2) ++ bgt cr1, L(dP3) ++ beq cr1, L(dP2) + + /* Remainder is 4 */ + .align 4 + L(dP1): +- mtctr rTMP ++ mtctr r0 + /* Normally we'd use rWORD7/rWORD8 here, but since we might exit early + (8-15 byte compare), we want to use only volatile registers. This + means we can avoid restoring non-volatile registers since we did not + change any on the early exit path. The key here is the non-early + exit path only cares about the condition code (cr5), not about which + register pair was used. */ +- lwz rWORD5,0(rSTR1) +- lwz rWORD6,0(rSTR2) +- cmplw cr5,rWORD5,rWORD6 +- blt cr7,L(dP1x) +- lwz rWORD1,4(rSTR1) +- lwz rWORD2,4(rSTR2) +- cmplw cr0,rWORD1,rWORD2 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD5, 0, rSTR1 ++ lwbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD5, 0(rSTR1) ++ lwz rWORD6, 0(rSTR2) ++#endif ++ cmplw cr5, rWORD5, rWORD6 ++ blt cr7, L(dP1x) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD1, 4(rSTR1) ++ lwz rWORD2, 4(rSTR2) ++#endif ++ cmplw cr7, rWORD1, rWORD2 + L(dP1e): +- lwz rWORD3,8(rSTR1) +- lwz rWORD4,8(rSTR2) +- cmplw cr1,rWORD3,rWORD4 +- lwz rWORD5,12(rSTR1) +- lwz rWORD6,12(rSTR2) +- cmplw cr6,rWORD5,rWORD6 +- bne cr5,L(dLcr5) +- bne cr0,L(dLcr0) +- +- lwzu rWORD7,16(rSTR1) +- lwzu rWORD8,16(rSTR2) +- bne cr1,L(dLcr1) +- cmplw cr5,rWORD7,rWORD8 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD3, 0, rSTR1 ++ lwbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD3, 8(rSTR1) ++ lwz rWORD4, 8(rSTR2) ++#endif ++ cmplw cr1, rWORD3, rWORD4 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD5, 0, rSTR1 ++ lwbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD5, 12(rSTR1) ++ lwz rWORD6, 12(rSTR2) ++#endif ++ cmplw cr6, rWORD5, rWORD6 ++ bne cr5, L(dLcr5x) ++ bne cr7, L(dLcr7x) ++ ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD7, 0, rSTR1 ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwzu rWORD7, 16(rSTR1) ++ lwzu rWORD8, 16(rSTR2) ++#endif ++ bne cr1, L(dLcr1) ++ cmplw cr5, rWORD7, rWORD8 + bdnz L(dLoop) +- bne cr6,L(dLcr6) +- lwz r30,44(1) +- lwz r31,48(1) ++ bne cr6, L(dLcr6) ++ lwz rWORD7, 44(r1) ++ lwz rWORD8, 48(r1) + .align 3 + L(dP1x): +- slwi. r12,rN,3 +- bne cr5,L(dLcr5) +- subfic rN,r12,32 /* Shift count is 32 - (rN * 8). */ +- lwz 1,0(1) ++ slwi. r12, rN, 3 ++ bne cr5, L(dLcr5x) ++ subfic rN, r12, 32 /* Shift count is 32 - (rN * 8). */ ++ addi r1, r1, 64 ++ cfi_adjust_cfa_offset(-64) + bne L(d00) +- li rRTN,0 ++ li rRTN, 0 + blr + + /* Remainder is 8 */ + .align 4 ++ cfi_adjust_cfa_offset(64) + L(dP2): +- mtctr rTMP +- lwz rWORD5,0(rSTR1) +- lwz rWORD6,0(rSTR2) +- cmplw cr6,rWORD5,rWORD6 +- blt cr7,L(dP2x) +- lwz rWORD7,4(rSTR1) +- lwz rWORD8,4(rSTR2) +- cmplw cr5,rWORD7,rWORD8 ++ mtctr r0 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD5, 0, rSTR1 ++ lwbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD5, 0(rSTR1) ++ lwz rWORD6, 0(rSTR2) ++#endif ++ cmplw cr6, rWORD5, rWORD6 ++ blt cr7, L(dP2x) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD7, 0, rSTR1 ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD7, 4(rSTR1) ++ lwz rWORD8, 4(rSTR2) ++#endif ++ cmplw cr5, rWORD7, rWORD8 + L(dP2e): +- lwz rWORD1,8(rSTR1) +- lwz rWORD2,8(rSTR2) +- cmplw cr0,rWORD1,rWORD2 +- lwz rWORD3,12(rSTR1) +- lwz rWORD4,12(rSTR2) +- cmplw cr1,rWORD3,rWORD4 +- addi rSTR1,rSTR1,4 +- addi rSTR2,rSTR2,4 +- bne cr6,L(dLcr6) +- bne cr5,L(dLcr5) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD1, 8(rSTR1) ++ lwz rWORD2, 8(rSTR2) ++#endif ++ cmplw cr7, rWORD1, rWORD2 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD3, 0, rSTR1 ++ lwbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD3, 12(rSTR1) ++ lwz rWORD4, 12(rSTR2) ++#endif ++ cmplw cr1, rWORD3, rWORD4 ++#ifndef __LITTLE_ENDIAN__ ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#endif ++ bne cr6, L(dLcr6) ++ bne cr5, L(dLcr5) + b L(dLoop2) + /* Again we are on a early exit path (16-23 byte compare), we want to + only use volatile registers and avoid restoring non-volatile + registers. */ + .align 4 + L(dP2x): +- lwz rWORD3,4(rSTR1) +- lwz rWORD4,4(rSTR2) +- cmplw cr5,rWORD3,rWORD4 +- slwi. r12,rN,3 +- bne cr6,L(dLcr6) +- addi rSTR1,rSTR1,4 +- addi rSTR2,rSTR2,4 +- bne cr5,L(dLcr5) +- subfic rN,r12,32 /* Shift count is 32 - (rN * 8). */ +- lwz 1,0(1) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD3, 0, rSTR1 ++ lwbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD3, 4(rSTR1) ++ lwz rWORD4, 4(rSTR2) ++#endif ++ cmplw cr1, rWORD3, rWORD4 ++ slwi. r12, rN, 3 ++ bne cr6, L(dLcr6x) ++#ifndef __LITTLE_ENDIAN__ ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#endif ++ bne cr1, L(dLcr1x) ++ subfic rN, r12, 32 /* Shift count is 32 - (rN * 8). */ ++ addi r1, r1, 64 ++ cfi_adjust_cfa_offset(-64) + bne L(d00) +- li rRTN,0 ++ li rRTN, 0 + blr + + /* Remainder is 12 */ + .align 4 ++ cfi_adjust_cfa_offset(64) + L(dP3): +- mtctr rTMP +- lwz rWORD3,0(rSTR1) +- lwz rWORD4,0(rSTR2) +- cmplw cr1,rWORD3,rWORD4 ++ mtctr r0 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD3, 0, rSTR1 ++ lwbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD3, 0(rSTR1) ++ lwz rWORD4, 0(rSTR2) ++#endif ++ cmplw cr1, rWORD3, rWORD4 + L(dP3e): +- lwz rWORD5,4(rSTR1) +- lwz rWORD6,4(rSTR2) +- cmplw cr6,rWORD5,rWORD6 +- blt cr7,L(dP3x) +- lwz rWORD7,8(rSTR1) +- lwz rWORD8,8(rSTR2) +- cmplw cr5,rWORD7,rWORD8 +- lwz rWORD1,12(rSTR1) +- lwz rWORD2,12(rSTR2) +- cmplw cr0,rWORD1,rWORD2 +- addi rSTR1,rSTR1,8 +- addi rSTR2,rSTR2,8 +- bne cr1,L(dLcr1) +- bne cr6,L(dLcr6) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD5, 0, rSTR1 ++ lwbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD5, 4(rSTR1) ++ lwz rWORD6, 4(rSTR2) ++#endif ++ cmplw cr6, rWORD5, rWORD6 ++ blt cr7, L(dP3x) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD7, 0, rSTR1 ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD7, 8(rSTR1) ++ lwz rWORD8, 8(rSTR2) ++#endif ++ cmplw cr5, rWORD7, rWORD8 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD1, 12(rSTR1) ++ lwz rWORD2, 12(rSTR2) ++#endif ++ cmplw cr7, rWORD1, rWORD2 ++#ifndef __LITTLE_ENDIAN__ ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#endif ++ bne cr1, L(dLcr1) ++ bne cr6, L(dLcr6) + b L(dLoop1) + /* Again we are on a early exit path (24-31 byte compare), we want to + only use volatile registers and avoid restoring non-volatile + registers. */ + .align 4 + L(dP3x): +- lwz rWORD1,8(rSTR1) +- lwz rWORD2,8(rSTR2) +- cmplw cr5,rWORD1,rWORD2 +- slwi. r12,rN,3 +- bne cr1,L(dLcr1) +- addi rSTR1,rSTR1,8 +- addi rSTR2,rSTR2,8 +- bne cr6,L(dLcr6) +- subfic rN,r12,32 /* Shift count is 32 - (rN * 8). */ +- bne cr5,L(dLcr5) +- lwz 1,0(1) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD1, 8(rSTR1) ++ lwz rWORD2, 8(rSTR2) ++#endif ++ cmplw cr7, rWORD1, rWORD2 ++ slwi. r12, rN, 3 ++ bne cr1, L(dLcr1x) ++#ifndef __LITTLE_ENDIAN__ ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#endif ++ bne cr6, L(dLcr6x) ++ subfic rN, r12, 32 /* Shift count is 32 - (rN * 8). */ ++ bne cr7, L(dLcr7x) ++ addi r1, r1, 64 ++ cfi_adjust_cfa_offset(-64) + bne L(d00) +- li rRTN,0 ++ li rRTN, 0 + blr + + /* Count is a multiple of 16, remainder is 0 */ + .align 4 ++ cfi_adjust_cfa_offset(64) + L(dP4): +- mtctr rTMP +- lwz rWORD1,0(rSTR1) +- lwz rWORD2,0(rSTR2) +- cmplw cr0,rWORD1,rWORD2 ++ mtctr r0 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD1, 0(rSTR1) ++ lwz rWORD2, 0(rSTR2) ++#endif ++ cmplw cr7, rWORD1, rWORD2 + L(dP4e): +- lwz rWORD3,4(rSTR1) +- lwz rWORD4,4(rSTR2) +- cmplw cr1,rWORD3,rWORD4 +- lwz rWORD5,8(rSTR1) +- lwz rWORD6,8(rSTR2) +- cmplw cr6,rWORD5,rWORD6 +- lwzu rWORD7,12(rSTR1) +- lwzu rWORD8,12(rSTR2) +- cmplw cr5,rWORD7,rWORD8 +- bne cr0,L(dLcr0) +- bne cr1,L(dLcr1) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD3, 0, rSTR1 ++ lwbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD3, 4(rSTR1) ++ lwz rWORD4, 4(rSTR2) ++#endif ++ cmplw cr1, rWORD3, rWORD4 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD5, 0, rSTR1 ++ lwbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD5, 8(rSTR1) ++ lwz rWORD6, 8(rSTR2) ++#endif ++ cmplw cr6, rWORD5, rWORD6 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD7, 0, rSTR1 ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwzu rWORD7, 12(rSTR1) ++ lwzu rWORD8, 12(rSTR2) ++#endif ++ cmplw cr5, rWORD7, rWORD8 ++ bne cr7, L(dLcr7) ++ bne cr1, L(dLcr1) + bdz- L(d24) /* Adjust CTR as we start with +4 */ + /* This is the primary loop */ + .align 4 + L(dLoop): +- lwz rWORD1,4(rSTR1) +- lwz rWORD2,4(rSTR2) +- cmplw cr1,rWORD3,rWORD4 +- bne cr6,L(dLcr6) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD1, 4(rSTR1) ++ lwz rWORD2, 4(rSTR2) ++#endif ++ cmplw cr1, rWORD3, rWORD4 ++ bne cr6, L(dLcr6) + L(dLoop1): +- lwz rWORD3,8(rSTR1) +- lwz rWORD4,8(rSTR2) +- cmplw cr6,rWORD5,rWORD6 +- bne cr5,L(dLcr5) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD3, 0, rSTR1 ++ lwbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD3, 8(rSTR1) ++ lwz rWORD4, 8(rSTR2) ++#endif ++ cmplw cr6, rWORD5, rWORD6 ++ bne cr5, L(dLcr5) + L(dLoop2): +- lwz rWORD5,12(rSTR1) +- lwz rWORD6,12(rSTR2) +- cmplw cr5,rWORD7,rWORD8 +- bne cr0,L(dLcr0) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD5, 0, rSTR1 ++ lwbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD5, 12(rSTR1) ++ lwz rWORD6, 12(rSTR2) ++#endif ++ cmplw cr5, rWORD7, rWORD8 ++ bne cr7, L(dLcr7) + L(dLoop3): +- lwzu rWORD7,16(rSTR1) +- lwzu rWORD8,16(rSTR2) +- bne cr1,L(dLcr1) +- cmplw cr0,rWORD1,rWORD2 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD7, 0, rSTR1 ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwzu rWORD7, 16(rSTR1) ++ lwzu rWORD8, 16(rSTR2) ++#endif ++ bne cr1, L(dLcr1) ++ cmplw cr7, rWORD1, rWORD2 + bdnz L(dLoop) + + L(dL4): +- cmplw cr1,rWORD3,rWORD4 +- bne cr6,L(dLcr6) +- cmplw cr6,rWORD5,rWORD6 +- bne cr5,L(dLcr5) +- cmplw cr5,rWORD7,rWORD8 ++ cmplw cr1, rWORD3, rWORD4 ++ bne cr6, L(dLcr6) ++ cmplw cr6, rWORD5, rWORD6 ++ bne cr5, L(dLcr5) ++ cmplw cr5, rWORD7, rWORD8 + L(d44): +- bne cr0,L(dLcr0) ++ bne cr7, L(dLcr7) + L(d34): +- bne cr1,L(dLcr1) ++ bne cr1, L(dLcr1) + L(d24): +- bne cr6,L(dLcr6) ++ bne cr6, L(dLcr6) + L(d14): +- slwi. r12,rN,3 +- bne cr5,L(dLcr5) ++ slwi. r12, rN, 3 ++ bne cr5, L(dLcr5) + L(d04): +- lwz r30,44(1) +- lwz r31,48(1) +- lwz 1,0(1) +- subfic rN,r12,32 /* Shift count is 32 - (rN * 8). */ ++ lwz rWORD7, 44(r1) ++ lwz rWORD8, 48(r1) ++ addi r1, r1, 64 ++ cfi_adjust_cfa_offset(-64) ++ subfic rN, r12, 32 /* Shift count is 32 - (rN * 8). */ + beq L(zeroLength) + /* At this point we have a remainder of 1 to 3 bytes to compare. Since + we are aligned it is safe to load the whole word, and use +- shift right to eliminate bits beyond the compare length. */ ++ shift right to eliminate bits beyond the compare length. */ + L(d00): +- lwz rWORD1,4(rSTR1) +- lwz rWORD2,4(rSTR2) +- srw rWORD1,rWORD1,rN +- srw rWORD2,rWORD2,rN +- cmplw rWORD1,rWORD2 +- li rRTN,0 +- beqlr +- li rRTN,1 +- bgtlr +- li rRTN,-1 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD1, 4(rSTR1) ++ lwz rWORD2, 4(rSTR2) ++#endif ++ srw rWORD1, rWORD1, rN ++ srw rWORD2, rWORD2, rN ++ sub rRTN, rWORD1, rWORD2 + blr + + .align 4 +-L(dLcr0): +- lwz r30,44(1) +- lwz r31,48(1) +- li rRTN,1 +- lwz 1,0(1) +- bgtlr cr0 +- li rRTN,-1 ++ cfi_adjust_cfa_offset(64) ++L(dLcr7): ++ lwz rWORD7, 44(r1) ++ lwz rWORD8, 48(r1) ++L(dLcr7x): ++ li rRTN, 1 ++ addi r1, r1, 64 ++ cfi_adjust_cfa_offset(-64) ++ bgtlr cr7 ++ li rRTN, -1 + blr + .align 4 ++ cfi_adjust_cfa_offset(64) + L(dLcr1): +- lwz r30,44(1) +- lwz r31,48(1) +- li rRTN,1 +- lwz 1,0(1) ++ lwz rWORD7, 44(r1) ++ lwz rWORD8, 48(r1) ++L(dLcr1x): ++ li rRTN, 1 ++ addi r1, r1, 64 ++ cfi_adjust_cfa_offset(-64) + bgtlr cr1 +- li rRTN,-1 ++ li rRTN, -1 + blr + .align 4 ++ cfi_adjust_cfa_offset(64) + L(dLcr6): +- lwz r30,44(1) +- lwz r31,48(1) +- li rRTN,1 +- lwz 1,0(1) ++ lwz rWORD7, 44(r1) ++ lwz rWORD8, 48(r1) ++L(dLcr6x): ++ li rRTN, 1 ++ addi r1, r1, 64 ++ cfi_adjust_cfa_offset(-64) + bgtlr cr6 +- li rRTN,-1 ++ li rRTN, -1 + blr + .align 4 ++ cfi_adjust_cfa_offset(64) + L(dLcr5): +- lwz r30,44(1) +- lwz r31,48(1) ++ lwz rWORD7, 44(r1) ++ lwz rWORD8, 48(r1) + L(dLcr5x): +- li rRTN,1 +- lwz 1,0(1) ++ li rRTN, 1 ++ addi r1, r1, 64 ++ cfi_adjust_cfa_offset(-64) + bgtlr cr5 +- li rRTN,-1 ++ li rRTN, -1 + blr + + .align 4 + L(bytealigned): +- cfi_adjust_cfa_offset(-64) + mtctr rN + + /* We need to prime this loop. This loop is swing modulo scheduled +@@ -413,38 +618,39 @@ + + So we must precondition some registers and condition codes so that + we don't exit the loop early on the first iteration. */ +- lbz rWORD1,0(rSTR1) +- lbz rWORD2,0(rSTR2) ++ ++ lbz rWORD1, 0(rSTR1) ++ lbz rWORD2, 0(rSTR2) + bdz L(b11) +- cmplw cr0,rWORD1,rWORD2 +- lbz rWORD3,1(rSTR1) +- lbz rWORD4,1(rSTR2) ++ cmplw cr7, rWORD1, rWORD2 ++ lbz rWORD3, 1(rSTR1) ++ lbz rWORD4, 1(rSTR2) + bdz L(b12) +- cmplw cr1,rWORD3,rWORD4 +- lbzu rWORD5,2(rSTR1) +- lbzu rWORD6,2(rSTR2) ++ cmplw cr1, rWORD3, rWORD4 ++ lbzu rWORD5, 2(rSTR1) ++ lbzu rWORD6, 2(rSTR2) + bdz L(b13) + .align 4 + L(bLoop): +- lbzu rWORD1,1(rSTR1) +- lbzu rWORD2,1(rSTR2) +- bne cr0,L(bLcr0) ++ lbzu rWORD1, 1(rSTR1) ++ lbzu rWORD2, 1(rSTR2) ++ bne cr7, L(bLcr7) + +- cmplw cr6,rWORD5,rWORD6 ++ cmplw cr6, rWORD5, rWORD6 + bdz L(b3i) + +- lbzu rWORD3,1(rSTR1) +- lbzu rWORD4,1(rSTR2) +- bne cr1,L(bLcr1) ++ lbzu rWORD3, 1(rSTR1) ++ lbzu rWORD4, 1(rSTR2) ++ bne cr1, L(bLcr1) + +- cmplw cr0,rWORD1,rWORD2 ++ cmplw cr7, rWORD1, rWORD2 + bdz L(b2i) + +- lbzu rWORD5,1(rSTR1) +- lbzu rWORD6,1(rSTR2) +- bne cr6,L(bLcr6) ++ lbzu rWORD5, 1(rSTR1) ++ lbzu rWORD6, 1(rSTR2) ++ bne cr6, L(bLcr6) + +- cmplw cr1,rWORD3,rWORD4 ++ cmplw cr1, rWORD3, rWORD4 + bdnz L(bLoop) + + /* We speculatively loading bytes before we have tested the previous +@@ -454,67 +660,62 @@ + tested. In this case we must complete the pending operations + before returning. */ + L(b1i): +- bne cr0,L(bLcr0) +- bne cr1,L(bLcr1) ++ bne cr7, L(bLcr7) ++ bne cr1, L(bLcr1) + b L(bx56) + .align 4 + L(b2i): +- bne cr6,L(bLcr6) +- bne cr0,L(bLcr0) ++ bne cr6, L(bLcr6) ++ bne cr7, L(bLcr7) + b L(bx34) + .align 4 + L(b3i): +- bne cr1,L(bLcr1) +- bne cr6,L(bLcr6) ++ bne cr1, L(bLcr1) ++ bne cr6, L(bLcr6) + b L(bx12) + .align 4 +-L(bLcr0): +- li rRTN,1 +- bgtlr cr0 +- li rRTN,-1 ++L(bLcr7): ++ li rRTN, 1 ++ bgtlr cr7 ++ li rRTN, -1 + blr + L(bLcr1): +- li rRTN,1 ++ li rRTN, 1 + bgtlr cr1 +- li rRTN,-1 ++ li rRTN, -1 + blr + L(bLcr6): +- li rRTN,1 ++ li rRTN, 1 + bgtlr cr6 +- li rRTN,-1 ++ li rRTN, -1 + blr + + L(b13): +- bne cr0,L(bx12) +- bne cr1,L(bx34) ++ bne cr7, L(bx12) ++ bne cr1, L(bx34) + L(bx56): +- sub rRTN,rWORD5,rWORD6 ++ sub rRTN, rWORD5, rWORD6 + blr + nop + L(b12): +- bne cr0,L(bx12) ++ bne cr7, L(bx12) + L(bx34): +- sub rRTN,rWORD3,rWORD4 ++ sub rRTN, rWORD3, rWORD4 + blr +- + L(b11): + L(bx12): +- sub rRTN,rWORD1,rWORD2 ++ sub rRTN, rWORD1, rWORD2 + blr +- + .align 4 +-L(zeroLengthReturn): +- + L(zeroLength): +- li rRTN,0 ++ li rRTN, 0 + blr + +- cfi_adjust_cfa_offset(64) + .align 4 + /* At this point we know the strings have different alignment and the +- compare length is at least 8 bytes. rBITDIF contains the low order ++ compare length is at least 8 bytes. r12 contains the low order + 2 bits of rSTR1 and cr5 contains the result of the logical compare +- of rBITDIF to 0. If rBITDIF == 0 then rStr1 is word aligned and can ++ of r12 to 0. If r12 == 0 then rStr1 is word aligned and can + perform the Wunaligned loop. + + Otherwise we know that rSTR1 is not aready word aligned yet. +@@ -523,465 +724,654 @@ + eliminate bits preceeding the first byte. Since we want to join the + normal (Wualigned) compare loop, starting at the second word, + we need to adjust the length (rN) and special case the loop +- versioning for the first W. This insures that the loop count is ++ versioning for the first W. This ensures that the loop count is + correct and the first W (shifted) is in the expected resister pair. */ + #define rSHL r29 /* Unaligned shift left count. */ + #define rSHR r28 /* Unaligned shift right count. */ +-#define rB r27 /* Left rotation temp for rWORD2. */ +-#define rD r26 /* Left rotation temp for rWORD4. */ +-#define rF r25 /* Left rotation temp for rWORD6. */ +-#define rH r24 /* Left rotation temp for rWORD8. */ +-#define rA r0 /* Right rotation temp for rWORD2. */ +-#define rC r12 /* Right rotation temp for rWORD4. */ +-#define rE r0 /* Right rotation temp for rWORD6. */ +-#define rG r12 /* Right rotation temp for rWORD8. */ ++#define rWORD8_SHIFT r27 /* Left rotation temp for rWORD2. */ ++#define rWORD2_SHIFT r26 /* Left rotation temp for rWORD4. */ ++#define rWORD4_SHIFT r25 /* Left rotation temp for rWORD6. */ ++#define rWORD6_SHIFT r24 /* Left rotation temp for rWORD8. */ ++ cfi_adjust_cfa_offset(64) + L(unaligned): +- stw r29,40(r1) +- cfi_offset(r29,(40-64)) +- clrlwi rSHL,rSTR2,30 +- stw r28,36(r1) +- cfi_offset(r28,(36-64)) +- beq cr5,L(Wunaligned) +- stw r27,32(r1) +- cfi_offset(r27,(32-64)) ++ stw rSHL, 40(r1) ++ cfi_offset(rSHL, (40-64)) ++ clrlwi rSHL, rSTR2, 30 ++ stw rSHR, 36(r1) ++ cfi_offset(rSHR, (36-64)) ++ beq cr5, L(Wunaligned) ++ stw rWORD8_SHIFT, 32(r1) ++ cfi_offset(rWORD8_SHIFT, (32-64)) + /* Adjust the logical start of rSTR2 to compensate for the extra bits + in the 1st rSTR1 W. */ +- sub r27,rSTR2,rBITDIF ++ sub rWORD8_SHIFT, rSTR2, r12 + /* But do not attempt to address the W before that W that contains + the actual start of rSTR2. */ +- clrrwi rSTR2,rSTR2,2 +- stw r26,28(r1) +- cfi_offset(r26,(28-64)) +-/* Compute the left/right shift counts for the unalign rSTR2, ++ clrrwi rSTR2, rSTR2, 2 ++ stw rWORD2_SHIFT, 28(r1) ++ cfi_offset(rWORD2_SHIFT, (28-64)) ++/* Compute the left/right shift counts for the unaligned rSTR2, + compensating for the logical (W aligned) start of rSTR1. */ +- clrlwi rSHL,r27,30 +- clrrwi rSTR1,rSTR1,2 +- stw r25,24(r1) +- cfi_offset(r25,(24-64)) +- slwi rSHL,rSHL,3 +- cmplw cr5,r27,rSTR2 +- add rN,rN,rBITDIF +- slwi r11,rBITDIF,3 +- stw r24,20(r1) +- cfi_offset(r24,(20-64)) +- subfic rSHR,rSHL,32 +- srwi rTMP,rN,4 /* Divide by 16 */ +- andi. rBITDIF,rN,12 /* Get the W remainder */ ++ clrlwi rSHL, rWORD8_SHIFT, 30 ++ clrrwi rSTR1, rSTR1, 2 ++ stw rWORD4_SHIFT, 24(r1) ++ cfi_offset(rWORD4_SHIFT, (24-64)) ++ slwi rSHL, rSHL, 3 ++ cmplw cr5, rWORD8_SHIFT, rSTR2 ++ add rN, rN, r12 ++ slwi rWORD6, r12, 3 ++ stw rWORD6_SHIFT, 20(r1) ++ cfi_offset(rWORD6_SHIFT, (20-64)) ++ subfic rSHR, rSHL, 32 ++ srwi r0, rN, 4 /* Divide by 16 */ ++ andi. r12, rN, 12 /* Get the W remainder */ + /* We normally need to load 2 Ws to start the unaligned rSTR2, but in + this special case those bits may be discarded anyway. Also we + must avoid loading a W where none of the bits are part of rSTR2 as + this may cross a page boundary and cause a page fault. */ +- li rWORD8,0 +- blt cr5,L(dus0) +- lwz rWORD8,0(rSTR2) +- la rSTR2,4(rSTR2) +- slw rWORD8,rWORD8,rSHL ++ li rWORD8, 0 ++ blt cr5, L(dus0) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD8, 0(rSTR2) ++ addi rSTR2, rSTR2, 4 ++#endif ++ slw rWORD8, rWORD8, rSHL + + L(dus0): +- lwz rWORD1,0(rSTR1) +- lwz rWORD2,0(rSTR2) +- cmplwi cr1,rBITDIF,8 +- cmplwi cr7,rN,16 +- srw rG,rWORD2,rSHR +- clrlwi rN,rN,30 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD1, 0(rSTR1) ++ lwz rWORD2, 0(rSTR2) ++#endif ++ cmplwi cr1, r12, 8 ++ cmplwi cr7, rN, 16 ++ srw r12, rWORD2, rSHR ++ clrlwi rN, rN, 30 + beq L(duPs4) +- mtctr rTMP +- or rWORD8,rG,rWORD8 +- bgt cr1,L(duPs3) +- beq cr1,L(duPs2) ++ mtctr r0 ++ or rWORD8, r12, rWORD8 ++ bgt cr1, L(duPs3) ++ beq cr1, L(duPs2) + + /* Remainder is 4 */ + .align 4 + L(dusP1): +- slw rB,rWORD2,rSHL +- slw rWORD7,rWORD1,r11 +- slw rWORD8,rWORD8,r11 +- bge cr7,L(duP1e) ++ slw rWORD8_SHIFT, rWORD2, rSHL ++ slw rWORD7, rWORD1, rWORD6 ++ slw rWORD8, rWORD8, rWORD6 ++ bge cr7, L(duP1e) + /* At this point we exit early with the first word compare + complete and remainder of 0 to 3 bytes. See L(du14) for details on + how we handle the remaining bytes. */ +- cmplw cr5,rWORD7,rWORD8 +- slwi. rN,rN,3 +- bne cr5,L(duLcr5) +- cmplw cr7,rN,rSHR ++ cmplw cr5, rWORD7, rWORD8 ++ slwi. rN, rN, 3 ++ bne cr5, L(duLcr5) ++ cmplw cr7, rN, rSHR + beq L(duZeroReturn) +- li rA,0 +- ble cr7,L(dutrim) +- lwz rWORD2,4(rSTR2) +- srw rA,rWORD2,rSHR ++ li r0, 0 ++ ble cr7, L(dutrim) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD2, 4(rSTR2) ++#endif ++ srw r0, rWORD2, rSHR + b L(dutrim) + /* Remainder is 8 */ + .align 4 + L(duPs2): +- slw rH,rWORD2,rSHL +- slw rWORD5,rWORD1,r11 +- slw rWORD6,rWORD8,r11 ++ slw rWORD6_SHIFT, rWORD2, rSHL ++ slw rWORD5, rWORD1, rWORD6 ++ slw rWORD6, rWORD8, rWORD6 + b L(duP2e) + /* Remainder is 12 */ + .align 4 + L(duPs3): +- slw rF,rWORD2,rSHL +- slw rWORD3,rWORD1,r11 +- slw rWORD4,rWORD8,r11 ++ slw rWORD4_SHIFT, rWORD2, rSHL ++ slw rWORD3, rWORD1, rWORD6 ++ slw rWORD4, rWORD8, rWORD6 + b L(duP3e) + /* Count is a multiple of 16, remainder is 0 */ + .align 4 + L(duPs4): +- mtctr rTMP +- or rWORD8,rG,rWORD8 +- slw rD,rWORD2,rSHL +- slw rWORD1,rWORD1,r11 +- slw rWORD2,rWORD8,r11 ++ mtctr r0 ++ or rWORD8, r12, rWORD8 ++ slw rWORD2_SHIFT, rWORD2, rSHL ++ slw rWORD1, rWORD1, rWORD6 ++ slw rWORD2, rWORD8, rWORD6 + b L(duP4e) + + /* At this point we know rSTR1 is word aligned and the + compare length is at least 8 bytes. */ + .align 4 + L(Wunaligned): +- stw r27,32(r1) +- cfi_offset(r27,(32-64)) +- clrrwi rSTR2,rSTR2,2 +- stw r26,28(r1) +- cfi_offset(r26,(28-64)) +- srwi rTMP,rN,4 /* Divide by 16 */ +- stw r25,24(r1) +- cfi_offset(r25,(24-64)) +- andi. rBITDIF,rN,12 /* Get the W remainder */ +- stw r24,20(r1) +- cfi_offset(r24,(24-64)) +- slwi rSHL,rSHL,3 +- lwz rWORD6,0(rSTR2) +- lwzu rWORD8,4(rSTR2) +- cmplwi cr1,rBITDIF,8 +- cmplwi cr7,rN,16 +- clrlwi rN,rN,30 +- subfic rSHR,rSHL,32 +- slw rH,rWORD6,rSHL ++ stw rWORD8_SHIFT, 32(r1) ++ cfi_offset(rWORD8_SHIFT, (32-64)) ++ clrrwi rSTR2, rSTR2, 2 ++ stw rWORD2_SHIFT, 28(r1) ++ cfi_offset(rWORD2_SHIFT, (28-64)) ++ srwi r0, rN, 4 /* Divide by 16 */ ++ stw rWORD4_SHIFT, 24(r1) ++ cfi_offset(rWORD4_SHIFT, (24-64)) ++ andi. r12, rN, 12 /* Get the W remainder */ ++ stw rWORD6_SHIFT, 20(r1) ++ cfi_offset(rWORD6_SHIFT, (20-64)) ++ slwi rSHL, rSHL, 3 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD6, 0, rSTR2 ++ addi rSTR2, rSTR2, 4 ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD6, 0(rSTR2) ++ lwzu rWORD8, 4(rSTR2) ++#endif ++ cmplwi cr1, r12, 8 ++ cmplwi cr7, rN, 16 ++ clrlwi rN, rN, 30 ++ subfic rSHR, rSHL, 32 ++ slw rWORD6_SHIFT, rWORD6, rSHL + beq L(duP4) +- mtctr rTMP +- bgt cr1,L(duP3) +- beq cr1,L(duP2) ++ mtctr r0 ++ bgt cr1, L(duP3) ++ beq cr1, L(duP2) + + /* Remainder is 4 */ + .align 4 + L(duP1): +- srw rG,rWORD8,rSHR +- lwz rWORD7,0(rSTR1) +- slw rB,rWORD8,rSHL +- or rWORD8,rG,rH +- blt cr7,L(duP1x) ++ srw r12, rWORD8, rSHR ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD7, 0, rSTR1 ++ addi rSTR1, rSTR1, 4 ++#else ++ lwz rWORD7, 0(rSTR1) ++#endif ++ slw rWORD8_SHIFT, rWORD8, rSHL ++ or rWORD8, r12, rWORD6_SHIFT ++ blt cr7, L(duP1x) + L(duP1e): +- lwz rWORD1,4(rSTR1) +- lwz rWORD2,4(rSTR2) +- cmplw cr5,rWORD7,rWORD8 +- srw rA,rWORD2,rSHR +- slw rD,rWORD2,rSHL +- or rWORD2,rA,rB +- lwz rWORD3,8(rSTR1) +- lwz rWORD4,8(rSTR2) +- cmplw cr0,rWORD1,rWORD2 +- srw rC,rWORD4,rSHR +- slw rF,rWORD4,rSHL +- bne cr5,L(duLcr5) +- or rWORD4,rC,rD +- lwz rWORD5,12(rSTR1) +- lwz rWORD6,12(rSTR2) +- cmplw cr1,rWORD3,rWORD4 +- srw rE,rWORD6,rSHR +- slw rH,rWORD6,rSHL +- bne cr0,L(duLcr0) +- or rWORD6,rE,rF +- cmplw cr6,rWORD5,rWORD6 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD1, 4(rSTR1) ++ lwz rWORD2, 4(rSTR2) ++#endif ++ cmplw cr5, rWORD7, rWORD8 ++ srw r0, rWORD2, rSHR ++ slw rWORD2_SHIFT, rWORD2, rSHL ++ or rWORD2, r0, rWORD8_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD3, 0, rSTR1 ++ lwbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD3, 8(rSTR1) ++ lwz rWORD4, 8(rSTR2) ++#endif ++ cmplw cr7, rWORD1, rWORD2 ++ srw r12, rWORD4, rSHR ++ slw rWORD4_SHIFT, rWORD4, rSHL ++ bne cr5, L(duLcr5) ++ or rWORD4, r12, rWORD2_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD5, 0, rSTR1 ++ lwbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD5, 12(rSTR1) ++ lwz rWORD6, 12(rSTR2) ++#endif ++ cmplw cr1, rWORD3, rWORD4 ++ srw r0, rWORD6, rSHR ++ slw rWORD6_SHIFT, rWORD6, rSHL ++ bne cr7, L(duLcr7) ++ or rWORD6, r0, rWORD4_SHIFT ++ cmplw cr6, rWORD5, rWORD6 + b L(duLoop3) + .align 4 + /* At this point we exit early with the first word compare + complete and remainder of 0 to 3 bytes. See L(du14) for details on + how we handle the remaining bytes. */ + L(duP1x): +- cmplw cr5,rWORD7,rWORD8 +- slwi. rN,rN,3 +- bne cr5,L(duLcr5) +- cmplw cr7,rN,rSHR ++ cmplw cr5, rWORD7, rWORD8 ++ slwi. rN, rN, 3 ++ bne cr5, L(duLcr5) ++ cmplw cr7, rN, rSHR + beq L(duZeroReturn) +- li rA,0 +- ble cr7,L(dutrim) +- ld rWORD2,8(rSTR2) +- srw rA,rWORD2,rSHR ++ li r0, 0 ++ ble cr7, L(dutrim) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD2, 8(rSTR2) ++#endif ++ srw r0, rWORD2, rSHR + b L(dutrim) + /* Remainder is 8 */ + .align 4 + L(duP2): +- srw rE,rWORD8,rSHR +- lwz rWORD5,0(rSTR1) +- or rWORD6,rE,rH +- slw rH,rWORD8,rSHL ++ srw r0, rWORD8, rSHR ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD5, 0, rSTR1 ++ addi rSTR1, rSTR1, 4 ++#else ++ lwz rWORD5, 0(rSTR1) ++#endif ++ or rWORD6, r0, rWORD6_SHIFT ++ slw rWORD6_SHIFT, rWORD8, rSHL + L(duP2e): +- lwz rWORD7,4(rSTR1) +- lwz rWORD8,4(rSTR2) +- cmplw cr6,rWORD5,rWORD6 +- srw rG,rWORD8,rSHR +- slw rB,rWORD8,rSHL +- or rWORD8,rG,rH +- blt cr7,L(duP2x) +- lwz rWORD1,8(rSTR1) +- lwz rWORD2,8(rSTR2) +- cmplw cr5,rWORD7,rWORD8 +- bne cr6,L(duLcr6) +- srw rA,rWORD2,rSHR +- slw rD,rWORD2,rSHL +- or rWORD2,rA,rB +- lwz rWORD3,12(rSTR1) +- lwz rWORD4,12(rSTR2) +- cmplw cr0,rWORD1,rWORD2 +- bne cr5,L(duLcr5) +- srw rC,rWORD4,rSHR +- slw rF,rWORD4,rSHL +- or rWORD4,rC,rD +- addi rSTR1,rSTR1,4 +- addi rSTR2,rSTR2,4 +- cmplw cr1,rWORD3,rWORD4 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD7, 0, rSTR1 ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD7, 4(rSTR1) ++ lwz rWORD8, 4(rSTR2) ++#endif ++ cmplw cr6, rWORD5, rWORD6 ++ srw r12, rWORD8, rSHR ++ slw rWORD8_SHIFT, rWORD8, rSHL ++ or rWORD8, r12, rWORD6_SHIFT ++ blt cr7, L(duP2x) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD1, 8(rSTR1) ++ lwz rWORD2, 8(rSTR2) ++#endif ++ cmplw cr5, rWORD7, rWORD8 ++ bne cr6, L(duLcr6) ++ srw r0, rWORD2, rSHR ++ slw rWORD2_SHIFT, rWORD2, rSHL ++ or rWORD2, r0, rWORD8_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD3, 0, rSTR1 ++ lwbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD3, 12(rSTR1) ++ lwz rWORD4, 12(rSTR2) ++#endif ++ cmplw cr7, rWORD1, rWORD2 ++ bne cr5, L(duLcr5) ++ srw r12, rWORD4, rSHR ++ slw rWORD4_SHIFT, rWORD4, rSHL ++ or rWORD4, r12, rWORD2_SHIFT ++#ifndef __LITTLE_ENDIAN__ ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#endif ++ cmplw cr1, rWORD3, rWORD4 + b L(duLoop2) + .align 4 + L(duP2x): +- cmplw cr5,rWORD7,rWORD8 +- addi rSTR1,rSTR1,4 +- addi rSTR2,rSTR2,4 +- bne cr6,L(duLcr6) +- slwi. rN,rN,3 +- bne cr5,L(duLcr5) +- cmplw cr7,rN,rSHR ++ cmplw cr5, rWORD7, rWORD8 ++#ifndef __LITTLE_ENDIAN__ ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#endif ++ bne cr6, L(duLcr6) ++ slwi. rN, rN, 3 ++ bne cr5, L(duLcr5) ++ cmplw cr7, rN, rSHR + beq L(duZeroReturn) +- li rA,0 +- ble cr7,L(dutrim) +- lwz rWORD2,4(rSTR2) +- srw rA,rWORD2,rSHR ++ li r0, 0 ++ ble cr7, L(dutrim) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD2, 4(rSTR2) ++#endif ++ srw r0, rWORD2, rSHR + b L(dutrim) + + /* Remainder is 12 */ + .align 4 + L(duP3): +- srw rC,rWORD8,rSHR +- lwz rWORD3,0(rSTR1) +- slw rF,rWORD8,rSHL +- or rWORD4,rC,rH ++ srw r12, rWORD8, rSHR ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD3, 0, rSTR1 ++ addi rSTR1, rSTR1, 4 ++#else ++ lwz rWORD3, 0(rSTR1) ++#endif ++ slw rWORD4_SHIFT, rWORD8, rSHL ++ or rWORD4, r12, rWORD6_SHIFT + L(duP3e): +- lwz rWORD5,4(rSTR1) +- lwz rWORD6,4(rSTR2) +- cmplw cr1,rWORD3,rWORD4 +- srw rE,rWORD6,rSHR +- slw rH,rWORD6,rSHL +- or rWORD6,rE,rF +- lwz rWORD7,8(rSTR1) +- lwz rWORD8,8(rSTR2) +- cmplw cr6,rWORD5,rWORD6 +- bne cr1,L(duLcr1) +- srw rG,rWORD8,rSHR +- slw rB,rWORD8,rSHL +- or rWORD8,rG,rH +- blt cr7,L(duP3x) +- lwz rWORD1,12(rSTR1) +- lwz rWORD2,12(rSTR2) +- cmplw cr5,rWORD7,rWORD8 +- bne cr6,L(duLcr6) +- srw rA,rWORD2,rSHR +- slw rD,rWORD2,rSHL +- or rWORD2,rA,rB +- addi rSTR1,rSTR1,8 +- addi rSTR2,rSTR2,8 +- cmplw cr0,rWORD1,rWORD2 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD5, 0, rSTR1 ++ lwbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD5, 4(rSTR1) ++ lwz rWORD6, 4(rSTR2) ++#endif ++ cmplw cr1, rWORD3, rWORD4 ++ srw r0, rWORD6, rSHR ++ slw rWORD6_SHIFT, rWORD6, rSHL ++ or rWORD6, r0, rWORD4_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD7, 0, rSTR1 ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD7, 8(rSTR1) ++ lwz rWORD8, 8(rSTR2) ++#endif ++ cmplw cr6, rWORD5, rWORD6 ++ bne cr1, L(duLcr1) ++ srw r12, rWORD8, rSHR ++ slw rWORD8_SHIFT, rWORD8, rSHL ++ or rWORD8, r12, rWORD6_SHIFT ++ blt cr7, L(duP3x) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD1, 12(rSTR1) ++ lwz rWORD2, 12(rSTR2) ++#endif ++ cmplw cr5, rWORD7, rWORD8 ++ bne cr6, L(duLcr6) ++ srw r0, rWORD2, rSHR ++ slw rWORD2_SHIFT, rWORD2, rSHL ++ or rWORD2, r0, rWORD8_SHIFT ++#ifndef __LITTLE_ENDIAN__ ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#endif ++ cmplw cr7, rWORD1, rWORD2 + b L(duLoop1) + .align 4 + L(duP3x): +- addi rSTR1,rSTR1,8 +- addi rSTR2,rSTR2,8 +- bne cr1,L(duLcr1) +- cmplw cr5,rWORD7,rWORD8 +- bne cr6,L(duLcr6) +- slwi. rN,rN,3 +- bne cr5,L(duLcr5) +- cmplw cr7,rN,rSHR ++#ifndef __LITTLE_ENDIAN__ ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#endif ++#if 0 ++/* Huh? We've already branched on cr1! */ ++ bne cr1, L(duLcr1) ++#endif ++ cmplw cr5, rWORD7, rWORD8 ++ bne cr6, L(duLcr6) ++ slwi. rN, rN, 3 ++ bne cr5, L(duLcr5) ++ cmplw cr7, rN, rSHR + beq L(duZeroReturn) +- li rA,0 +- ble cr7,L(dutrim) +- lwz rWORD2,4(rSTR2) +- srw rA,rWORD2,rSHR ++ li r0, 0 ++ ble cr7, L(dutrim) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD2, 4(rSTR2) ++#endif ++ srw r0, rWORD2, rSHR + b L(dutrim) + + /* Count is a multiple of 16, remainder is 0 */ + .align 4 + L(duP4): +- mtctr rTMP +- srw rA,rWORD8,rSHR +- lwz rWORD1,0(rSTR1) +- slw rD,rWORD8,rSHL +- or rWORD2,rA,rH ++ mtctr r0 ++ srw r0, rWORD8, rSHR ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ addi rSTR1, rSTR1, 4 ++#else ++ lwz rWORD1, 0(rSTR1) ++#endif ++ slw rWORD2_SHIFT, rWORD8, rSHL ++ or rWORD2, r0, rWORD6_SHIFT + L(duP4e): +- lwz rWORD3,4(rSTR1) +- lwz rWORD4,4(rSTR2) +- cmplw cr0,rWORD1,rWORD2 +- srw rC,rWORD4,rSHR +- slw rF,rWORD4,rSHL +- or rWORD4,rC,rD +- lwz rWORD5,8(rSTR1) +- lwz rWORD6,8(rSTR2) +- cmplw cr1,rWORD3,rWORD4 +- bne cr0,L(duLcr0) +- srw rE,rWORD6,rSHR +- slw rH,rWORD6,rSHL +- or rWORD6,rE,rF +- lwzu rWORD7,12(rSTR1) +- lwzu rWORD8,12(rSTR2) +- cmplw cr6,rWORD5,rWORD6 +- bne cr1,L(duLcr1) +- srw rG,rWORD8,rSHR +- slw rB,rWORD8,rSHL +- or rWORD8,rG,rH +- cmplw cr5,rWORD7,rWORD8 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD3, 0, rSTR1 ++ lwbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD3, 4(rSTR1) ++ lwz rWORD4, 4(rSTR2) ++#endif ++ cmplw cr7, rWORD1, rWORD2 ++ srw r12, rWORD4, rSHR ++ slw rWORD4_SHIFT, rWORD4, rSHL ++ or rWORD4, r12, rWORD2_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD5, 0, rSTR1 ++ lwbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD5, 8(rSTR1) ++ lwz rWORD6, 8(rSTR2) ++#endif ++ cmplw cr1, rWORD3, rWORD4 ++ bne cr7, L(duLcr7) ++ srw r0, rWORD6, rSHR ++ slw rWORD6_SHIFT, rWORD6, rSHL ++ or rWORD6, r0, rWORD4_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD7, 0, rSTR1 ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwzu rWORD7, 12(rSTR1) ++ lwzu rWORD8, 12(rSTR2) ++#endif ++ cmplw cr6, rWORD5, rWORD6 ++ bne cr1, L(duLcr1) ++ srw r12, rWORD8, rSHR ++ slw rWORD8_SHIFT, rWORD8, rSHL ++ or rWORD8, r12, rWORD6_SHIFT ++ cmplw cr5, rWORD7, rWORD8 + bdz L(du24) /* Adjust CTR as we start with +4 */ + /* This is the primary loop */ + .align 4 + L(duLoop): +- lwz rWORD1,4(rSTR1) +- lwz rWORD2,4(rSTR2) +- cmplw cr1,rWORD3,rWORD4 +- bne cr6,L(duLcr6) +- srw rA,rWORD2,rSHR +- slw rD,rWORD2,rSHL +- or rWORD2,rA,rB ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD1, 4(rSTR1) ++ lwz rWORD2, 4(rSTR2) ++#endif ++ cmplw cr1, rWORD3, rWORD4 ++ bne cr6, L(duLcr6) ++ srw r0, rWORD2, rSHR ++ slw rWORD2_SHIFT, rWORD2, rSHL ++ or rWORD2, r0, rWORD8_SHIFT + L(duLoop1): +- lwz rWORD3,8(rSTR1) +- lwz rWORD4,8(rSTR2) +- cmplw cr6,rWORD5,rWORD6 +- bne cr5,L(duLcr5) +- srw rC,rWORD4,rSHR +- slw rF,rWORD4,rSHL +- or rWORD4,rC,rD ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD3, 0, rSTR1 ++ lwbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD3, 8(rSTR1) ++ lwz rWORD4, 8(rSTR2) ++#endif ++ cmplw cr6, rWORD5, rWORD6 ++ bne cr5, L(duLcr5) ++ srw r12, rWORD4, rSHR ++ slw rWORD4_SHIFT, rWORD4, rSHL ++ or rWORD4, r12, rWORD2_SHIFT + L(duLoop2): +- lwz rWORD5,12(rSTR1) +- lwz rWORD6,12(rSTR2) +- cmplw cr5,rWORD7,rWORD8 +- bne cr0,L(duLcr0) +- srw rE,rWORD6,rSHR +- slw rH,rWORD6,rSHL +- or rWORD6,rE,rF ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD5, 0, rSTR1 ++ lwbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD5, 12(rSTR1) ++ lwz rWORD6, 12(rSTR2) ++#endif ++ cmplw cr5, rWORD7, rWORD8 ++ bne cr7, L(duLcr7) ++ srw r0, rWORD6, rSHR ++ slw rWORD6_SHIFT, rWORD6, rSHL ++ or rWORD6, r0, rWORD4_SHIFT + L(duLoop3): +- lwzu rWORD7,16(rSTR1) +- lwzu rWORD8,16(rSTR2) +- cmplw cr0,rWORD1,rWORD2 +- bne cr1,L(duLcr1) +- srw rG,rWORD8,rSHR +- slw rB,rWORD8,rSHL +- or rWORD8,rG,rH ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD7, 0, rSTR1 ++ lwbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 4 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwzu rWORD7, 16(rSTR1) ++ lwzu rWORD8, 16(rSTR2) ++#endif ++ cmplw cr7, rWORD1, rWORD2 ++ bne cr1, L(duLcr1) ++ srw r12, rWORD8, rSHR ++ slw rWORD8_SHIFT, rWORD8, rSHL ++ or rWORD8, r12, rWORD6_SHIFT + bdnz L(duLoop) + + L(duL4): +- bne cr1,L(duLcr1) +- cmplw cr1,rWORD3,rWORD4 +- bne cr6,L(duLcr6) +- cmplw cr6,rWORD5,rWORD6 +- bne cr5,L(duLcr5) +- cmplw cr5,rWORD7,rWORD8 ++#if 0 ++/* Huh? We've already branched on cr1! */ ++ bne cr1, L(duLcr1) ++#endif ++ cmplw cr1, rWORD3, rWORD4 ++ bne cr6, L(duLcr6) ++ cmplw cr6, rWORD5, rWORD6 ++ bne cr5, L(duLcr5) ++ cmplw cr5, rWORD7, rWORD8 + L(du44): +- bne cr0,L(duLcr0) ++ bne cr7, L(duLcr7) + L(du34): +- bne cr1,L(duLcr1) ++ bne cr1, L(duLcr1) + L(du24): +- bne cr6,L(duLcr6) ++ bne cr6, L(duLcr6) + L(du14): +- slwi. rN,rN,3 +- bne cr5,L(duLcr5) ++ slwi. rN, rN, 3 ++ bne cr5, L(duLcr5) + /* At this point we have a remainder of 1 to 3 bytes to compare. We use + shift right to eliminate bits beyond the compare length. ++ This allows the use of word subtract to compute the final result. + + However it may not be safe to load rWORD2 which may be beyond the + string length. So we compare the bit length of the remainder to + the right shift count (rSHR). If the bit count is less than or equal + we do not need to load rWORD2 (all significant bits are already in +- rB). */ +- cmplw cr7,rN,rSHR ++ rWORD8_SHIFT). */ ++ cmplw cr7, rN, rSHR + beq L(duZeroReturn) +- li rA,0 +- ble cr7,L(dutrim) +- lwz rWORD2,4(rSTR2) +- srw rA,rWORD2,rSHR ++ li r0, 0 ++ ble cr7, L(dutrim) ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD2, 0, rSTR2 ++ addi rSTR2, rSTR2, 4 ++#else ++ lwz rWORD2, 4(rSTR2) ++#endif ++ srw r0, rWORD2, rSHR + .align 4 + L(dutrim): +- lwz rWORD1,4(rSTR1) +- lwz r31,48(1) +- subfic rN,rN,32 /* Shift count is 32 - (rN * 8). */ +- or rWORD2,rA,rB +- lwz r30,44(1) +- lwz r29,40(r1) +- srw rWORD1,rWORD1,rN +- srw rWORD2,rWORD2,rN +- lwz r28,36(r1) +- lwz r27,32(r1) +- cmplw rWORD1,rWORD2 +- li rRTN,0 +- beq L(dureturn26) +- li rRTN,1 +- bgt L(dureturn26) +- li rRTN,-1 ++#ifdef __LITTLE_ENDIAN__ ++ lwbrx rWORD1, 0, rSTR1 ++#else ++ lwz rWORD1, 4(rSTR1) ++#endif ++ lwz rWORD8, 48(r1) ++ subfic rN, rN, 32 /* Shift count is 32 - (rN * 8). */ ++ or rWORD2, r0, rWORD8_SHIFT ++ lwz rWORD7, 44(r1) ++ lwz rSHL, 40(r1) ++ srw rWORD1, rWORD1, rN ++ srw rWORD2, rWORD2, rN ++ lwz rSHR, 36(r1) ++ lwz rWORD8_SHIFT, 32(r1) ++ sub rRTN, rWORD1, rWORD2 + b L(dureturn26) + .align 4 +-L(duLcr0): +- lwz r31,48(1) +- lwz r30,44(1) +- li rRTN,1 +- bgt cr0,L(dureturn29) +- lwz r29,40(r1) +- lwz r28,36(r1) +- li rRTN,-1 ++L(duLcr7): ++ lwz rWORD8, 48(r1) ++ lwz rWORD7, 44(r1) ++ li rRTN, 1 ++ bgt cr7, L(dureturn29) ++ lwz rSHL, 40(r1) ++ lwz rSHR, 36(r1) ++ li rRTN, -1 + b L(dureturn27) + .align 4 + L(duLcr1): +- lwz r31,48(1) +- lwz r30,44(1) +- li rRTN,1 +- bgt cr1,L(dureturn29) +- lwz r29,40(r1) +- lwz r28,36(r1) +- li rRTN,-1 ++ lwz rWORD8, 48(r1) ++ lwz rWORD7, 44(r1) ++ li rRTN, 1 ++ bgt cr1, L(dureturn29) ++ lwz rSHL, 40(r1) ++ lwz rSHR, 36(r1) ++ li rRTN, -1 + b L(dureturn27) + .align 4 + L(duLcr6): +- lwz r31,48(1) +- lwz r30,44(1) +- li rRTN,1 +- bgt cr6,L(dureturn29) +- lwz r29,40(r1) +- lwz r28,36(r1) +- li rRTN,-1 ++ lwz rWORD8, 48(r1) ++ lwz rWORD7, 44(r1) ++ li rRTN, 1 ++ bgt cr6, L(dureturn29) ++ lwz rSHL, 40(r1) ++ lwz rSHR, 36(r1) ++ li rRTN, -1 + b L(dureturn27) + .align 4 + L(duLcr5): +- lwz r31,48(1) +- lwz r30,44(1) +- li rRTN,1 +- bgt cr5,L(dureturn29) +- lwz r29,40(r1) +- lwz r28,36(r1) +- li rRTN,-1 ++ lwz rWORD8, 48(r1) ++ lwz rWORD7, 44(r1) ++ li rRTN, 1 ++ bgt cr5, L(dureturn29) ++ lwz rSHL, 40(r1) ++ lwz rSHR, 36(r1) ++ li rRTN, -1 + b L(dureturn27) + .align 3 + L(duZeroReturn): +- li rRTN,0 ++ li rRTN, 0 + .align 4 + L(dureturn): +- lwz r31,48(1) +- lwz r30,44(1) ++ lwz rWORD8, 48(r1) ++ lwz rWORD7, 44(r1) + L(dureturn29): +- lwz r29,40(r1) +- lwz r28,36(r1) ++ lwz rSHL, 40(r1) ++ lwz rSHR, 36(r1) + L(dureturn27): +- lwz r27,32(r1) ++ lwz rWORD8_SHIFT, 32(r1) + L(dureturn26): +- lwz r26,28(r1) ++ lwz rWORD2_SHIFT, 28(r1) + L(dureturn25): +- lwz r25,24(r1) +- lwz r24,20(r1) +- lwz 1,0(1) ++ lwz rWORD4_SHIFT, 24(r1) ++ lwz rWORD6_SHIFT, 20(r1) ++ addi r1, r1, 64 ++ cfi_adjust_cfa_offset(-64) + blr + END (BP_SYM (memcmp)) ++ + libc_hidden_builtin_def (memcmp) + weak_alias (memcmp,bcmp) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power4/memcmp.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power4/memcmp.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power4/memcmp.S 2014-05-28 19:22:37.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power4/memcmp.S 2014-05-29 09:35:25.000000000 -0500 +@@ -1,5 +1,5 @@ +-/* Optimized strcmp implementation for PowerPC64. +- Copyright (C) 2003, 2006, 2011 Free Software Foundation, Inc. ++/* Optimized memcmp implementation for PowerPC64. ++ Copyright (C) 2003-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or +@@ -17,307 +17,492 @@ + . */ + + #include +-#include +-#include + +-/* int [r3] memcmp (const char *s1 [r3], const char *s2 [r4], size_t size [r5]) */ ++/* int [r3] memcmp (const char *s1 [r3], ++ const char *s2 [r4], ++ size_t size [r5]) */ + + .machine power4 +-EALIGN (BP_SYM(memcmp), 4, 0) ++EALIGN (memcmp, 4, 0) + CALL_MCOUNT 3 + +-#define rTMP r0 + #define rRTN r3 + #define rSTR1 r3 /* first string arg */ + #define rSTR2 r4 /* second string arg */ + #define rN r5 /* max string length */ +-/* Note: The Bounded pointer support in this code is broken. This code +- was inherited from PPC32 and that support was never completed. +- Current PPC gcc does not support -fbounds-check or -fbounded-pointers. */ + #define rWORD1 r6 /* current word in s1 */ + #define rWORD2 r7 /* current word in s2 */ + #define rWORD3 r8 /* next word in s1 */ + #define rWORD4 r9 /* next word in s2 */ + #define rWORD5 r10 /* next word in s1 */ + #define rWORD6 r11 /* next word in s2 */ +-#define rBITDIF r12 /* bits that differ in s1 & s2 words */ + #define rWORD7 r30 /* next word in s1 */ + #define rWORD8 r31 /* next word in s2 */ + +- xor rTMP, rSTR2, rSTR1 ++ xor r0, rSTR2, rSTR1 + cmpldi cr6, rN, 0 + cmpldi cr1, rN, 12 +- clrldi. rTMP, rTMP, 61 +- clrldi rBITDIF, rSTR1, 61 +- cmpldi cr5, rBITDIF, 0 ++ clrldi. r0, r0, 61 ++ clrldi r12, rSTR1, 61 ++ cmpldi cr5, r12, 0 + beq- cr6, L(zeroLength) +- dcbt 0,rSTR1 +- dcbt 0,rSTR2 +-/* If less than 8 bytes or not aligned, use the unalligned ++ dcbt 0, rSTR1 ++ dcbt 0, rSTR2 ++/* If less than 8 bytes or not aligned, use the unaligned + byte loop. */ + blt cr1, L(bytealigned) +- std rWORD8,-8(r1) +- cfi_offset(rWORD8,-8) +- std rWORD7,-16(r1) +- cfi_offset(rWORD7,-16) ++ std rWORD8, -8(r1) ++ cfi_offset(rWORD8, -8) ++ std rWORD7, -16(r1) ++ cfi_offset(rWORD7, -16) + bne L(unaligned) + /* At this point we know both strings have the same alignment and the +- compare length is at least 8 bytes. rBITDIF containes the low order ++ compare length is at least 8 bytes. r12 contains the low order + 3 bits of rSTR1 and cr5 contains the result of the logical compare +- of rBITDIF to 0. If rBITDIF == 0 then we are already double word +- aligned and can perform the DWaligned loop. +- ++ of r12 to 0. If r12 == 0 then we are already double word ++ aligned and can perform the DW aligned loop. ++ + Otherwise we know the two strings have the same alignment (but not +- yet DW). So we can force the string addresses to the next lower DW +- boundary and special case this first DW word using shift left to +- ellimiate bits preceeding the first byte. Since we want to join the +- normal (DWaligned) compare loop, starting at the second double word, ++ yet DW). So we force the string addresses to the next lower DW ++ boundary and special case this first DW using shift left to ++ eliminate bits preceding the first byte. Since we want to join the ++ normal (DW aligned) compare loop, starting at the second double word, + we need to adjust the length (rN) and special case the loop +- versioning for the first DW. This insures that the loop count is +- correct and the first DW (shifted) is in the expected resister pair. */ +- .align 4 ++ versioning for the first DW. This ensures that the loop count is ++ correct and the first DW (shifted) is in the expected register pair. */ ++ .align 4 + L(samealignment): + clrrdi rSTR1, rSTR1, 3 + clrrdi rSTR2, rSTR2, 3 + beq cr5, L(DWaligned) +- add rN, rN, rBITDIF +- sldi r11, rBITDIF, 3 +- srdi rTMP, rN, 5 /* Divide by 32 */ +- andi. rBITDIF, rN, 24 /* Get the DW remainder */ ++ add rN, rN, r12 ++ sldi rWORD6, r12, 3 ++ srdi r0, rN, 5 /* Divide by 32 */ ++ andi. r12, rN, 24 /* Get the DW remainder */ ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD1, 0(rSTR1) + ld rWORD2, 0(rSTR2) +- cmpldi cr1, rBITDIF, 16 ++#endif ++ cmpldi cr1, r12, 16 + cmpldi cr7, rN, 32 + clrldi rN, rN, 61 + beq L(dPs4) +- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group */ ++ mtctr r0 /* Power4 wants mtctr 1st in dispatch group */ + bgt cr1, L(dPs3) + beq cr1, L(dPs2) + + /* Remainder is 8 */ +- .align 3 ++ .align 3 + L(dsP1): +- sld rWORD5, rWORD1, r11 +- sld rWORD6, rWORD2, r11 ++ sld rWORD5, rWORD1, rWORD6 ++ sld rWORD6, rWORD2, rWORD6 + cmpld cr5, rWORD5, rWORD6 + blt cr7, L(dP1x) + /* Do something useful in this cycle since we have to branch anyway. */ ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD1, 8(rSTR1) + ld rWORD2, 8(rSTR2) +- cmpld cr0, rWORD1, rWORD2 ++#endif ++ cmpld cr7, rWORD1, rWORD2 + b L(dP1e) + /* Remainder is 16 */ +- .align 4 ++ .align 4 + L(dPs2): +- sld rWORD5, rWORD1, r11 +- sld rWORD6, rWORD2, r11 ++ sld rWORD5, rWORD1, rWORD6 ++ sld rWORD6, rWORD2, rWORD6 + cmpld cr6, rWORD5, rWORD6 + blt cr7, L(dP2x) + /* Do something useful in this cycle since we have to branch anyway. */ ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD7, 0, rSTR1 ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD7, 8(rSTR1) + ld rWORD8, 8(rSTR2) ++#endif + cmpld cr5, rWORD7, rWORD8 + b L(dP2e) + /* Remainder is 24 */ +- .align 4 ++ .align 4 + L(dPs3): +- sld rWORD3, rWORD1, r11 +- sld rWORD4, rWORD2, r11 ++ sld rWORD3, rWORD1, rWORD6 ++ sld rWORD4, rWORD2, rWORD6 + cmpld cr1, rWORD3, rWORD4 + b L(dP3e) + /* Count is a multiple of 32, remainder is 0 */ +- .align 4 ++ .align 4 + L(dPs4): +- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group */ +- sld rWORD1, rWORD1, r11 +- sld rWORD2, rWORD2, r11 +- cmpld cr0, rWORD1, rWORD2 ++ mtctr r0 /* Power4 wants mtctr 1st in dispatch group */ ++ sld rWORD1, rWORD1, rWORD6 ++ sld rWORD2, rWORD2, rWORD6 ++ cmpld cr7, rWORD1, rWORD2 + b L(dP4e) + + /* At this point we know both strings are double word aligned and the + compare length is at least 8 bytes. */ +- .align 4 ++ .align 4 + L(DWaligned): +- andi. rBITDIF, rN, 24 /* Get the DW remainder */ +- srdi rTMP, rN, 5 /* Divide by 32 */ +- cmpldi cr1, rBITDIF, 16 ++ andi. r12, rN, 24 /* Get the DW remainder */ ++ srdi r0, rN, 5 /* Divide by 32 */ ++ cmpldi cr1, r12, 16 + cmpldi cr7, rN, 32 + clrldi rN, rN, 61 + beq L(dP4) + bgt cr1, L(dP3) + beq cr1, L(dP2) +- ++ + /* Remainder is 8 */ +- .align 4 ++ .align 4 + L(dP1): +- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group */ ++ mtctr r0 /* Power4 wants mtctr 1st in dispatch group */ + /* Normally we'd use rWORD7/rWORD8 here, but since we might exit early +- (8-15 byte compare), we want to use only volitile registers. This +- means we can avoid restoring non-volitile registers since we did not ++ (8-15 byte compare), we want to use only volatile registers. This ++ means we can avoid restoring non-volatile registers since we did not + change any on the early exit path. The key here is the non-early +- exit path only cares about the condition code (cr5), not about which ++ exit path only cares about the condition code (cr5), not about which + register pair was used. */ ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD5, 0, rSTR1 ++ ldbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD5, 0(rSTR1) + ld rWORD6, 0(rSTR2) ++#endif + cmpld cr5, rWORD5, rWORD6 + blt cr7, L(dP1x) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD1, 8(rSTR1) + ld rWORD2, 8(rSTR2) +- cmpld cr0, rWORD1, rWORD2 ++#endif ++ cmpld cr7, rWORD1, rWORD2 + L(dP1e): ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD3, 0, rSTR1 ++ ldbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD3, 16(rSTR1) + ld rWORD4, 16(rSTR2) ++#endif + cmpld cr1, rWORD3, rWORD4 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD5, 0, rSTR1 ++ ldbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD5, 24(rSTR1) + ld rWORD6, 24(rSTR2) ++#endif + cmpld cr6, rWORD5, rWORD6 +- bne cr5, L(dLcr5) +- bne cr0, L(dLcr0) +- ++ bne cr5, L(dLcr5x) ++ bne cr7, L(dLcr7x) ++ ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD7, 0, rSTR1 ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ldu rWORD7, 32(rSTR1) + ldu rWORD8, 32(rSTR2) ++#endif + bne cr1, L(dLcr1) + cmpld cr5, rWORD7, rWORD8 + bdnz L(dLoop) + bne cr6, L(dLcr6) +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) +- .align 3 ++ ld rWORD8, -8(r1) ++ ld rWORD7, -16(r1) ++ .align 3 + L(dP1x): + sldi. r12, rN, 3 +- bne cr5, L(dLcr5) ++ bne cr5, L(dLcr5x) + subfic rN, r12, 64 /* Shift count is 64 - (rN * 8). */ + bne L(d00) + li rRTN, 0 + blr +- ++ + /* Remainder is 16 */ +- .align 4 ++ .align 4 + L(dP2): +- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group */ ++ mtctr r0 /* Power4 wants mtctr 1st in dispatch group */ ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD5, 0, rSTR1 ++ ldbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD5, 0(rSTR1) + ld rWORD6, 0(rSTR2) ++#endif + cmpld cr6, rWORD5, rWORD6 + blt cr7, L(dP2x) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD7, 0, rSTR1 ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD7, 8(rSTR1) + ld rWORD8, 8(rSTR2) ++#endif + cmpld cr5, rWORD7, rWORD8 + L(dP2e): ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD1, 16(rSTR1) + ld rWORD2, 16(rSTR2) +- cmpld cr0, rWORD1, rWORD2 ++#endif ++ cmpld cr7, rWORD1, rWORD2 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD3, 0, rSTR1 ++ ldbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD3, 24(rSTR1) + ld rWORD4, 24(rSTR2) ++#endif + cmpld cr1, rWORD3, rWORD4 ++#ifndef __LITTLE_ENDIAN__ + addi rSTR1, rSTR1, 8 + addi rSTR2, rSTR2, 8 ++#endif + bne cr6, L(dLcr6) + bne cr5, L(dLcr5) + b L(dLoop2) + /* Again we are on a early exit path (16-23 byte compare), we want to +- only use volitile registers and avoid restoring non-volitile ++ only use volatile registers and avoid restoring non-volatile + registers. */ +- .align 4 ++ .align 4 + L(dP2x): ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD3, 0, rSTR1 ++ ldbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD3, 8(rSTR1) + ld rWORD4, 8(rSTR2) +- cmpld cr5, rWORD3, rWORD4 ++#endif ++ cmpld cr1, rWORD3, rWORD4 + sldi. r12, rN, 3 +- bne cr6, L(dLcr6) ++ bne cr6, L(dLcr6x) ++#ifndef __LITTLE_ENDIAN__ + addi rSTR1, rSTR1, 8 + addi rSTR2, rSTR2, 8 +- bne cr5, L(dLcr5) ++#endif ++ bne cr1, L(dLcr1x) + subfic rN, r12, 64 /* Shift count is 64 - (rN * 8). */ + bne L(d00) + li rRTN, 0 + blr +- ++ + /* Remainder is 24 */ +- .align 4 ++ .align 4 + L(dP3): +- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group */ ++ mtctr r0 /* Power4 wants mtctr 1st in dispatch group */ ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD3, 0, rSTR1 ++ ldbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD3, 0(rSTR1) + ld rWORD4, 0(rSTR2) ++#endif + cmpld cr1, rWORD3, rWORD4 + L(dP3e): ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD5, 0, rSTR1 ++ ldbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD5, 8(rSTR1) + ld rWORD6, 8(rSTR2) ++#endif + cmpld cr6, rWORD5, rWORD6 + blt cr7, L(dP3x) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD7, 0, rSTR1 ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD7, 16(rSTR1) + ld rWORD8, 16(rSTR2) ++#endif + cmpld cr5, rWORD7, rWORD8 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD1, 24(rSTR1) + ld rWORD2, 24(rSTR2) +- cmpld cr0, rWORD1, rWORD2 ++#endif ++ cmpld cr7, rWORD1, rWORD2 ++#ifndef __LITTLE_ENDIAN__ + addi rSTR1, rSTR1, 16 + addi rSTR2, rSTR2, 16 ++#endif + bne cr1, L(dLcr1) + bne cr6, L(dLcr6) + b L(dLoop1) + /* Again we are on a early exit path (24-31 byte compare), we want to +- only use volitile registers and avoid restoring non-volitile ++ only use volatile registers and avoid restoring non-volatile + registers. */ +- .align 4 ++ .align 4 + L(dP3x): ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD1, 16(rSTR1) + ld rWORD2, 16(rSTR2) +- cmpld cr5, rWORD1, rWORD2 ++#endif ++ cmpld cr7, rWORD1, rWORD2 + sldi. r12, rN, 3 +- bne cr1, L(dLcr1) ++ bne cr1, L(dLcr1x) ++#ifndef __LITTLE_ENDIAN__ + addi rSTR1, rSTR1, 16 + addi rSTR2, rSTR2, 16 +- bne cr6, L(dLcr6) ++#endif ++ bne cr6, L(dLcr6x) + subfic rN, r12, 64 /* Shift count is 64 - (rN * 8). */ +- bne cr5, L(dLcr5) ++ bne cr7, L(dLcr7x) + bne L(d00) + li rRTN, 0 + blr +- ++ + /* Count is a multiple of 32, remainder is 0 */ +- .align 4 ++ .align 4 + L(dP4): +- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group */ ++ mtctr r0 /* Power4 wants mtctr 1st in dispatch group */ ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD1, 0(rSTR1) + ld rWORD2, 0(rSTR2) +- cmpld cr0, rWORD1, rWORD2 ++#endif ++ cmpld cr7, rWORD1, rWORD2 + L(dP4e): ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD3, 0, rSTR1 ++ ldbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD3, 8(rSTR1) + ld rWORD4, 8(rSTR2) ++#endif + cmpld cr1, rWORD3, rWORD4 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD5, 0, rSTR1 ++ ldbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD5, 16(rSTR1) + ld rWORD6, 16(rSTR2) ++#endif + cmpld cr6, rWORD5, rWORD6 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD7, 0, rSTR1 ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ldu rWORD7, 24(rSTR1) + ldu rWORD8, 24(rSTR2) ++#endif + cmpld cr5, rWORD7, rWORD8 +- bne cr0, L(dLcr0) ++ bne cr7, L(dLcr7) + bne cr1, L(dLcr1) + bdz- L(d24) /* Adjust CTR as we start with +4 */ + /* This is the primary loop */ +- .align 4 ++ .align 4 + L(dLoop): ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD1, 8(rSTR1) + ld rWORD2, 8(rSTR2) ++#endif + cmpld cr1, rWORD3, rWORD4 + bne cr6, L(dLcr6) + L(dLoop1): ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD3, 0, rSTR1 ++ ldbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD3, 16(rSTR1) + ld rWORD4, 16(rSTR2) ++#endif + cmpld cr6, rWORD5, rWORD6 + bne cr5, L(dLcr5) + L(dLoop2): ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD5, 0, rSTR1 ++ ldbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD5, 24(rSTR1) + ld rWORD6, 24(rSTR2) ++#endif + cmpld cr5, rWORD7, rWORD8 +- bne cr0, L(dLcr0) ++ bne cr7, L(dLcr7) + L(dLoop3): ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD7, 0, rSTR1 ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ldu rWORD7, 32(rSTR1) + ldu rWORD8, 32(rSTR2) ++#endif + bne- cr1, L(dLcr1) +- cmpld cr0, rWORD1, rWORD2 +- bdnz+ L(dLoop) +- ++ cmpld cr7, rWORD1, rWORD2 ++ bdnz+ L(dLoop) ++ + L(dL4): + cmpld cr1, rWORD3, rWORD4 + bne cr6, L(dLcr6) +@@ -325,84 +510,98 @@ + bne cr5, L(dLcr5) + cmpld cr5, rWORD7, rWORD8 + L(d44): +- bne cr0, L(dLcr0) ++ bne cr7, L(dLcr7) + L(d34): + bne cr1, L(dLcr1) + L(d24): + bne cr6, L(dLcr6) + L(d14): + sldi. r12, rN, 3 +- bne cr5, L(dLcr5) ++ bne cr5, L(dLcr5) + L(d04): +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) ++ ld rWORD8, -8(r1) ++ ld rWORD7, -16(r1) + subfic rN, r12, 64 /* Shift count is 64 - (rN * 8). */ + beq L(zeroLength) + /* At this point we have a remainder of 1 to 7 bytes to compare. Since + we are aligned it is safe to load the whole double word, and use +- shift right double to elliminate bits beyond the compare length. */ ++ shift right double to eliminate bits beyond the compare length. */ + L(d00): ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD1, 8(rSTR1) +- ld rWORD2, 8(rSTR2) ++ ld rWORD2, 8(rSTR2) ++#endif + srd rWORD1, rWORD1, rN + srd rWORD2, rWORD2, rN +- cmpld cr5, rWORD1, rWORD2 +- bne cr5, L(dLcr5x) ++ cmpld cr7, rWORD1, rWORD2 ++ bne cr7, L(dLcr7x) + li rRTN, 0 + blr +- .align 4 +-L(dLcr0): +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) ++ ++ .align 4 ++L(dLcr7): ++ ld rWORD8, -8(r1) ++ ld rWORD7, -16(r1) ++L(dLcr7x): + li rRTN, 1 +- bgtlr cr0 ++ bgtlr cr7 + li rRTN, -1 + blr +- .align 4 ++ .align 4 + L(dLcr1): +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) ++ ld rWORD8, -8(r1) ++ ld rWORD7, -16(r1) ++L(dLcr1x): + li rRTN, 1 + bgtlr cr1 + li rRTN, -1 + blr +- .align 4 ++ .align 4 + L(dLcr6): +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) ++ ld rWORD8, -8(r1) ++ ld rWORD7, -16(r1) ++L(dLcr6x): + li rRTN, 1 + bgtlr cr6 + li rRTN, -1 + blr +- .align 4 ++ .align 4 + L(dLcr5): +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) ++ ld rWORD8, -8(r1) ++ ld rWORD7, -16(r1) + L(dLcr5x): + li rRTN, 1 + bgtlr cr5 + li rRTN, -1 + blr +- +- .align 4 ++ ++ .align 4 + L(bytealigned): +- mtctr rN /* Power4 wants mtctr 1st in dispatch group */ ++ mtctr rN /* Power4 wants mtctr 1st in dispatch group */ ++#if 0 ++/* Huh? We've already branched on cr6! */ + beq- cr6, L(zeroLength) ++#endif + + /* We need to prime this loop. This loop is swing modulo scheduled +- to avoid pipe delays. The dependent instruction latencies (load to ++ to avoid pipe delays. The dependent instruction latencies (load to + compare to conditional branch) is 2 to 3 cycles. In this loop each + dispatch group ends in a branch and takes 1 cycle. Effectively +- the first iteration of the loop only serves to load operands and +- branches based on compares are delayed until the next loop. ++ the first iteration of the loop only serves to load operands and ++ branches based on compares are delayed until the next loop. + + So we must precondition some registers and condition codes so that + we don't exit the loop early on the first iteration. */ +- ++ + lbz rWORD1, 0(rSTR1) + lbz rWORD2, 0(rSTR2) + bdz- L(b11) +- cmpld cr0, rWORD1, rWORD2 ++ cmpld cr7, rWORD1, rWORD2 + lbz rWORD3, 1(rSTR1) + lbz rWORD4, 1(rSTR2) + bdz- L(b12) +@@ -410,20 +609,20 @@ + lbzu rWORD5, 2(rSTR1) + lbzu rWORD6, 2(rSTR2) + bdz- L(b13) +- .align 4 ++ .align 4 + L(bLoop): + lbzu rWORD1, 1(rSTR1) + lbzu rWORD2, 1(rSTR2) +- bne- cr0, L(bLcr0) ++ bne- cr7, L(bLcr7) + + cmpld cr6, rWORD5, rWORD6 + bdz- L(b3i) +- ++ + lbzu rWORD3, 1(rSTR1) + lbzu rWORD4, 1(rSTR2) + bne- cr1, L(bLcr1) + +- cmpld cr0, rWORD1, rWORD2 ++ cmpld cr7, rWORD1, rWORD2 + bdz- L(b2i) + + lbzu rWORD5, 1(rSTR1) +@@ -432,31 +631,31 @@ + + cmpld cr1, rWORD3, rWORD4 + bdnz+ L(bLoop) +- ++ + /* We speculatively loading bytes before we have tested the previous + bytes. But we must avoid overrunning the length (in the ctr) to +- prevent these speculative loads from causing a segfault. In this ++ prevent these speculative loads from causing a segfault. In this + case the loop will exit early (before the all pending bytes are + tested. In this case we must complete the pending operations + before returning. */ + L(b1i): +- bne- cr0, L(bLcr0) ++ bne- cr7, L(bLcr7) + bne- cr1, L(bLcr1) + b L(bx56) +- .align 4 ++ .align 4 + L(b2i): + bne- cr6, L(bLcr6) +- bne- cr0, L(bLcr0) ++ bne- cr7, L(bLcr7) + b L(bx34) +- .align 4 ++ .align 4 + L(b3i): + bne- cr1, L(bLcr1) + bne- cr6, L(bLcr6) + b L(bx12) +- .align 4 +-L(bLcr0): ++ .align 4 ++L(bLcr7): + li rRTN, 1 +- bgtlr cr0 ++ bgtlr cr7 + li rRTN, -1 + blr + L(bLcr1): +@@ -471,116 +670,121 @@ + blr + + L(b13): +- bne- cr0, L(bx12) ++ bne- cr7, L(bx12) + bne- cr1, L(bx34) + L(bx56): + sub rRTN, rWORD5, rWORD6 + blr + nop + L(b12): +- bne- cr0, L(bx12) +-L(bx34): ++ bne- cr7, L(bx12) ++L(bx34): + sub rRTN, rWORD3, rWORD4 + blr + L(b11): + L(bx12): + sub rRTN, rWORD1, rWORD2 + blr +- .align 4 +-L(zeroLengthReturn): +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) ++ .align 4 + L(zeroLength): + li rRTN, 0 + blr + +- .align 4 ++ .align 4 + /* At this point we know the strings have different alignment and the +- compare length is at least 8 bytes. rBITDIF containes the low order ++ compare length is at least 8 bytes. r12 contains the low order + 3 bits of rSTR1 and cr5 contains the result of the logical compare +- of rBITDIF to 0. If rBITDIF == 0 then rStr1 is double word ++ of r12 to 0. If r12 == 0 then rStr1 is double word + aligned and can perform the DWunaligned loop. +- +- Otherwise we know that rSTR1 is not aready DW aligned yet. ++ ++ Otherwise we know that rSTR1 is not already DW aligned yet. + So we can force the string addresses to the next lower DW +- boundary and special case this first DW word using shift left to +- ellimiate bits preceeding the first byte. Since we want to join the ++ boundary and special case this first DW using shift left to ++ eliminate bits preceding the first byte. Since we want to join the + normal (DWaligned) compare loop, starting at the second double word, + we need to adjust the length (rN) and special case the loop +- versioning for the first DW. This insures that the loop count is ++ versioning for the first DW. This ensures that the loop count is + correct and the first DW (shifted) is in the expected resister pair. */ +-#define rSHL r29 /* Unaligned shift left count. */ +-#define rSHR r28 /* Unaligned shift right count. */ +-#define rB r27 /* Left rotation temp for rWORD2. */ +-#define rD r26 /* Left rotation temp for rWORD4. */ +-#define rF r25 /* Left rotation temp for rWORD6. */ +-#define rH r24 /* Left rotation temp for rWORD8. */ +-#define rA r0 /* Right rotation temp for rWORD2. */ +-#define rC r12 /* Right rotation temp for rWORD4. */ +-#define rE r0 /* Right rotation temp for rWORD6. */ +-#define rG r12 /* Right rotation temp for rWORD8. */ ++#define rSHL r29 /* Unaligned shift left count. */ ++#define rSHR r28 /* Unaligned shift right count. */ ++#define rWORD8_SHIFT r27 /* Left rotation temp for rWORD2. */ ++#define rWORD2_SHIFT r26 /* Left rotation temp for rWORD4. */ ++#define rWORD4_SHIFT r25 /* Left rotation temp for rWORD6. */ ++#define rWORD6_SHIFT r24 /* Left rotation temp for rWORD8. */ + L(unaligned): +- std r29,-24(r1) +- cfi_offset(r29,-24) ++ std rSHL, -24(r1) ++ cfi_offset(rSHL, -24) + clrldi rSHL, rSTR2, 61 + beq- cr6, L(duzeroLength) +- std r28,-32(r1) +- cfi_offset(r28,-32) ++ std rSHR, -32(r1) ++ cfi_offset(rSHR, -32) + beq cr5, L(DWunaligned) +- std r27,-40(r1) +- cfi_offset(r27,-40) +-/* Adjust the logical start of rSTR2 ro compensate for the extra bits ++ std rWORD8_SHIFT, -40(r1) ++ cfi_offset(rWORD8_SHIFT, -40) ++/* Adjust the logical start of rSTR2 to compensate for the extra bits + in the 1st rSTR1 DW. */ +- sub r27, rSTR2, rBITDIF ++ sub rWORD8_SHIFT, rSTR2, r12 + /* But do not attempt to address the DW before that DW that contains + the actual start of rSTR2. */ + clrrdi rSTR2, rSTR2, 3 +- std r26,-48(r1) +- cfi_offset(r26,-48) +-/* Compute the leaft/right shift counts for the unalign rSTR2, +- compensating for the logical (DW aligned) start of rSTR1. */ +- clrldi rSHL, r27, 61 +- clrrdi rSTR1, rSTR1, 3 +- std r25,-56(r1) +- cfi_offset(r25,-56) ++ std rWORD2_SHIFT, -48(r1) ++ cfi_offset(rWORD2_SHIFT, -48) ++/* Compute the left/right shift counts for the unaligned rSTR2, ++ compensating for the logical (DW aligned) start of rSTR1. */ ++ clrldi rSHL, rWORD8_SHIFT, 61 ++ clrrdi rSTR1, rSTR1, 3 ++ std rWORD4_SHIFT, -56(r1) ++ cfi_offset(rWORD4_SHIFT, -56) + sldi rSHL, rSHL, 3 +- cmpld cr5, r27, rSTR2 +- add rN, rN, rBITDIF +- sldi r11, rBITDIF, 3 +- std r24,-64(r1) +- cfi_offset(r24,-64) ++ cmpld cr5, rWORD8_SHIFT, rSTR2 ++ add rN, rN, r12 ++ sldi rWORD6, r12, 3 ++ std rWORD6_SHIFT, -64(r1) ++ cfi_offset(rWORD6_SHIFT, -64) + subfic rSHR, rSHL, 64 +- srdi rTMP, rN, 5 /* Divide by 32 */ +- andi. rBITDIF, rN, 24 /* Get the DW remainder */ ++ srdi r0, rN, 5 /* Divide by 32 */ ++ andi. r12, rN, 24 /* Get the DW remainder */ + /* We normally need to load 2 DWs to start the unaligned rSTR2, but in + this special case those bits may be discarded anyway. Also we + must avoid loading a DW where none of the bits are part of rSTR2 as + this may cross a page boundary and cause a page fault. */ + li rWORD8, 0 + blt cr5, L(dus0) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD8, 0(rSTR2) +- la rSTR2, 8(rSTR2) ++ addi rSTR2, rSTR2, 8 ++#endif + sld rWORD8, rWORD8, rSHL + + L(dus0): ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD1, 0(rSTR1) + ld rWORD2, 0(rSTR2) +- cmpldi cr1, rBITDIF, 16 ++#endif ++ cmpldi cr1, r12, 16 + cmpldi cr7, rN, 32 +- srd rG, rWORD2, rSHR ++ srd r12, rWORD2, rSHR + clrldi rN, rN, 61 + beq L(duPs4) +- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group */ +- or rWORD8, rG, rWORD8 ++ mtctr r0 /* Power4 wants mtctr 1st in dispatch group */ ++ or rWORD8, r12, rWORD8 + bgt cr1, L(duPs3) + beq cr1, L(duPs2) + + /* Remainder is 8 */ +- .align 4 ++ .align 4 + L(dusP1): +- sld rB, rWORD2, rSHL +- sld rWORD7, rWORD1, r11 +- sld rWORD8, rWORD8, r11 ++ sld rWORD8_SHIFT, rWORD2, rSHL ++ sld rWORD7, rWORD1, rWORD6 ++ sld rWORD8, rWORD8, rWORD6 + bge cr7, L(duP1e) + /* At this point we exit early with the first double word compare + complete and remainder of 0 to 7 bytes. See L(du14) for details on +@@ -590,95 +794,133 @@ + bne cr5, L(duLcr5) + cmpld cr7, rN, rSHR + beq L(duZeroReturn) +- li rA, 0 ++ li r0, 0 + ble cr7, L(dutrim) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD2, 8(rSTR2) +- srd rA, rWORD2, rSHR ++#endif ++ srd r0, rWORD2, rSHR + b L(dutrim) + /* Remainder is 16 */ +- .align 4 ++ .align 4 + L(duPs2): +- sld rH, rWORD2, rSHL +- sld rWORD5, rWORD1, r11 +- sld rWORD6, rWORD8, r11 ++ sld rWORD6_SHIFT, rWORD2, rSHL ++ sld rWORD5, rWORD1, rWORD6 ++ sld rWORD6, rWORD8, rWORD6 + b L(duP2e) + /* Remainder is 24 */ +- .align 4 ++ .align 4 + L(duPs3): +- sld rF, rWORD2, rSHL +- sld rWORD3, rWORD1, r11 +- sld rWORD4, rWORD8, r11 ++ sld rWORD4_SHIFT, rWORD2, rSHL ++ sld rWORD3, rWORD1, rWORD6 ++ sld rWORD4, rWORD8, rWORD6 + b L(duP3e) + /* Count is a multiple of 32, remainder is 0 */ +- .align 4 ++ .align 4 + L(duPs4): +- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group */ +- or rWORD8, rG, rWORD8 +- sld rD, rWORD2, rSHL +- sld rWORD1, rWORD1, r11 +- sld rWORD2, rWORD8, r11 ++ mtctr r0 /* Power4 wants mtctr 1st in dispatch group */ ++ or rWORD8, r12, rWORD8 ++ sld rWORD2_SHIFT, rWORD2, rSHL ++ sld rWORD1, rWORD1, rWORD6 ++ sld rWORD2, rWORD8, rWORD6 + b L(duP4e) + + /* At this point we know rSTR1 is double word aligned and the + compare length is at least 8 bytes. */ +- .align 4 ++ .align 4 + L(DWunaligned): +- std r27,-40(r1) +- cfi_offset(r27,-40) ++ std rWORD8_SHIFT, -40(r1) ++ cfi_offset(rWORD8_SHIFT, -40) + clrrdi rSTR2, rSTR2, 3 +- std r26,-48(r1) +- cfi_offset(r26,-48) +- srdi rTMP, rN, 5 /* Divide by 32 */ +- std r25,-56(r1) +- cfi_offset(r25,-56) +- andi. rBITDIF, rN, 24 /* Get the DW remainder */ +- std r24,-64(r1) +- cfi_offset(r24,-64) ++ std rWORD2_SHIFT, -48(r1) ++ cfi_offset(rWORD2_SHIFT, -48) ++ srdi r0, rN, 5 /* Divide by 32 */ ++ std rWORD4_SHIFT, -56(r1) ++ cfi_offset(rWORD4_SHIFT, -56) ++ andi. r12, rN, 24 /* Get the DW remainder */ ++ std rWORD6_SHIFT, -64(r1) ++ cfi_offset(rWORD6_SHIFT, -64) + sldi rSHL, rSHL, 3 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD6, 0, rSTR2 ++ addi rSTR2, rSTR2, 8 ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD6, 0(rSTR2) + ldu rWORD8, 8(rSTR2) +- cmpldi cr1, rBITDIF, 16 ++#endif ++ cmpldi cr1, r12, 16 + cmpldi cr7, rN, 32 + clrldi rN, rN, 61 + subfic rSHR, rSHL, 64 +- sld rH, rWORD6, rSHL ++ sld rWORD6_SHIFT, rWORD6, rSHL + beq L(duP4) +- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group */ ++ mtctr r0 /* Power4 wants mtctr 1st in dispatch group */ + bgt cr1, L(duP3) + beq cr1, L(duP2) +- ++ + /* Remainder is 8 */ +- .align 4 ++ .align 4 + L(duP1): +- srd rG, rWORD8, rSHR ++ srd r12, rWORD8, rSHR ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD7, 0, rSTR1 ++ addi rSTR1, rSTR1, 8 ++#else + ld rWORD7, 0(rSTR1) +- sld rB, rWORD8, rSHL +- or rWORD8, rG, rH ++#endif ++ sld rWORD8_SHIFT, rWORD8, rSHL ++ or rWORD8, r12, rWORD6_SHIFT + blt cr7, L(duP1x) + L(duP1e): ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD1, 8(rSTR1) + ld rWORD2, 8(rSTR2) ++#endif + cmpld cr5, rWORD7, rWORD8 +- srd rA, rWORD2, rSHR +- sld rD, rWORD2, rSHL +- or rWORD2, rA, rB ++ srd r0, rWORD2, rSHR ++ sld rWORD2_SHIFT, rWORD2, rSHL ++ or rWORD2, r0, rWORD8_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD3, 0, rSTR1 ++ ldbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD3, 16(rSTR1) + ld rWORD4, 16(rSTR2) +- cmpld cr0, rWORD1, rWORD2 +- srd rC, rWORD4, rSHR +- sld rF, rWORD4, rSHL ++#endif ++ cmpld cr7, rWORD1, rWORD2 ++ srd r12, rWORD4, rSHR ++ sld rWORD4_SHIFT, rWORD4, rSHL + bne cr5, L(duLcr5) +- or rWORD4, rC, rD ++ or rWORD4, r12, rWORD2_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD5, 0, rSTR1 ++ ldbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD5, 24(rSTR1) + ld rWORD6, 24(rSTR2) ++#endif + cmpld cr1, rWORD3, rWORD4 +- srd rE, rWORD6, rSHR +- sld rH, rWORD6, rSHL +- bne cr0, L(duLcr0) +- or rWORD6, rE, rF ++ srd r0, rWORD6, rSHR ++ sld rWORD6_SHIFT, rWORD6, rSHL ++ bne cr7, L(duLcr7) ++ or rWORD6, r0, rWORD4_SHIFT + cmpld cr6, rWORD5, rWORD6 +- b L(duLoop3) +- .align 4 ++ b L(duLoop3) ++ .align 4 + /* At this point we exit early with the first double word compare + complete and remainder of 0 to 7 bytes. See L(du14) for details on + how we handle the remaining bytes. */ +@@ -688,186 +930,321 @@ + bne cr5, L(duLcr5) + cmpld cr7, rN, rSHR + beq L(duZeroReturn) +- li rA, 0 ++ li r0, 0 + ble cr7, L(dutrim) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD2, 8(rSTR2) +- srd rA, rWORD2, rSHR ++#endif ++ srd r0, rWORD2, rSHR + b L(dutrim) + /* Remainder is 16 */ +- .align 4 ++ .align 4 + L(duP2): +- srd rE, rWORD8, rSHR ++ srd r0, rWORD8, rSHR ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD5, 0, rSTR1 ++ addi rSTR1, rSTR1, 8 ++#else + ld rWORD5, 0(rSTR1) +- or rWORD6, rE, rH +- sld rH, rWORD8, rSHL ++#endif ++ or rWORD6, r0, rWORD6_SHIFT ++ sld rWORD6_SHIFT, rWORD8, rSHL + L(duP2e): ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD7, 0, rSTR1 ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD7, 8(rSTR1) + ld rWORD8, 8(rSTR2) ++#endif + cmpld cr6, rWORD5, rWORD6 +- srd rG, rWORD8, rSHR +- sld rB, rWORD8, rSHL +- or rWORD8, rG, rH ++ srd r12, rWORD8, rSHR ++ sld rWORD8_SHIFT, rWORD8, rSHL ++ or rWORD8, r12, rWORD6_SHIFT + blt cr7, L(duP2x) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD1, 16(rSTR1) + ld rWORD2, 16(rSTR2) ++#endif + cmpld cr5, rWORD7, rWORD8 + bne cr6, L(duLcr6) +- srd rA, rWORD2, rSHR +- sld rD, rWORD2, rSHL +- or rWORD2, rA, rB ++ srd r0, rWORD2, rSHR ++ sld rWORD2_SHIFT, rWORD2, rSHL ++ or rWORD2, r0, rWORD8_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD3, 0, rSTR1 ++ ldbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD3, 24(rSTR1) + ld rWORD4, 24(rSTR2) +- cmpld cr0, rWORD1, rWORD2 ++#endif ++ cmpld cr7, rWORD1, rWORD2 + bne cr5, L(duLcr5) +- srd rC, rWORD4, rSHR +- sld rF, rWORD4, rSHL +- or rWORD4, rC, rD ++ srd r12, rWORD4, rSHR ++ sld rWORD4_SHIFT, rWORD4, rSHL ++ or rWORD4, r12, rWORD2_SHIFT ++#ifndef __LITTLE_ENDIAN__ + addi rSTR1, rSTR1, 8 + addi rSTR2, rSTR2, 8 ++#endif + cmpld cr1, rWORD3, rWORD4 + b L(duLoop2) +- .align 4 ++ .align 4 + L(duP2x): + cmpld cr5, rWORD7, rWORD8 ++#ifndef __LITTLE_ENDIAN__ + addi rSTR1, rSTR1, 8 + addi rSTR2, rSTR2, 8 ++#endif + bne cr6, L(duLcr6) + sldi. rN, rN, 3 + bne cr5, L(duLcr5) + cmpld cr7, rN, rSHR + beq L(duZeroReturn) +- li rA, 0 ++ li r0, 0 + ble cr7, L(dutrim) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD2, 8(rSTR2) +- srd rA, rWORD2, rSHR ++#endif ++ srd r0, rWORD2, rSHR + b L(dutrim) +- ++ + /* Remainder is 24 */ +- .align 4 ++ .align 4 + L(duP3): +- srd rC, rWORD8, rSHR ++ srd r12, rWORD8, rSHR ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD3, 0, rSTR1 ++ addi rSTR1, rSTR1, 8 ++#else + ld rWORD3, 0(rSTR1) +- sld rF, rWORD8, rSHL +- or rWORD4, rC, rH ++#endif ++ sld rWORD4_SHIFT, rWORD8, rSHL ++ or rWORD4, r12, rWORD6_SHIFT + L(duP3e): ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD5, 0, rSTR1 ++ ldbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD5, 8(rSTR1) + ld rWORD6, 8(rSTR2) ++#endif + cmpld cr1, rWORD3, rWORD4 +- srd rE, rWORD6, rSHR +- sld rH, rWORD6, rSHL +- or rWORD6, rE, rF ++ srd r0, rWORD6, rSHR ++ sld rWORD6_SHIFT, rWORD6, rSHL ++ or rWORD6, r0, rWORD4_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD7, 0, rSTR1 ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD7, 16(rSTR1) + ld rWORD8, 16(rSTR2) ++#endif + cmpld cr6, rWORD5, rWORD6 + bne cr1, L(duLcr1) +- srd rG, rWORD8, rSHR +- sld rB, rWORD8, rSHL +- or rWORD8, rG, rH ++ srd r12, rWORD8, rSHR ++ sld rWORD8_SHIFT, rWORD8, rSHL ++ or rWORD8, r12, rWORD6_SHIFT + blt cr7, L(duP3x) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD1, 24(rSTR1) + ld rWORD2, 24(rSTR2) ++#endif + cmpld cr5, rWORD7, rWORD8 + bne cr6, L(duLcr6) +- srd rA, rWORD2, rSHR +- sld rD, rWORD2, rSHL +- or rWORD2, rA, rB ++ srd r0, rWORD2, rSHR ++ sld rWORD2_SHIFT, rWORD2, rSHL ++ or rWORD2, r0, rWORD8_SHIFT ++#ifndef __LITTLE_ENDIAN__ + addi rSTR1, rSTR1, 16 + addi rSTR2, rSTR2, 16 +- cmpld cr0, rWORD1, rWORD2 ++#endif ++ cmpld cr7, rWORD1, rWORD2 + b L(duLoop1) +- .align 4 ++ .align 4 + L(duP3x): ++#ifndef __LITTLE_ENDIAN__ + addi rSTR1, rSTR1, 16 + addi rSTR2, rSTR2, 16 ++#endif ++#if 0 ++/* Huh? We've already branched on cr1! */ + bne cr1, L(duLcr1) ++#endif + cmpld cr5, rWORD7, rWORD8 + bne cr6, L(duLcr6) + sldi. rN, rN, 3 + bne cr5, L(duLcr5) + cmpld cr7, rN, rSHR + beq L(duZeroReturn) +- li rA, 0 ++ li r0, 0 + ble cr7, L(dutrim) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD2, 8(rSTR2) +- srd rA, rWORD2, rSHR ++#endif ++ srd r0, rWORD2, rSHR + b L(dutrim) +- ++ + /* Count is a multiple of 32, remainder is 0 */ +- .align 4 ++ .align 4 + L(duP4): +- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group */ +- srd rA, rWORD8, rSHR ++ mtctr r0 /* Power4 wants mtctr 1st in dispatch group */ ++ srd r0, rWORD8, rSHR ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ addi rSTR1, rSTR1, 8 ++#else + ld rWORD1, 0(rSTR1) +- sld rD, rWORD8, rSHL +- or rWORD2, rA, rH ++#endif ++ sld rWORD2_SHIFT, rWORD8, rSHL ++ or rWORD2, r0, rWORD6_SHIFT + L(duP4e): ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD3, 0, rSTR1 ++ ldbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD3, 8(rSTR1) + ld rWORD4, 8(rSTR2) +- cmpld cr0, rWORD1, rWORD2 +- srd rC, rWORD4, rSHR +- sld rF, rWORD4, rSHL +- or rWORD4, rC, rD ++#endif ++ cmpld cr7, rWORD1, rWORD2 ++ srd r12, rWORD4, rSHR ++ sld rWORD4_SHIFT, rWORD4, rSHL ++ or rWORD4, r12, rWORD2_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD5, 0, rSTR1 ++ ldbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD5, 16(rSTR1) + ld rWORD6, 16(rSTR2) ++#endif + cmpld cr1, rWORD3, rWORD4 +- bne cr0, L(duLcr0) +- srd rE, rWORD6, rSHR +- sld rH, rWORD6, rSHL +- or rWORD6, rE, rF ++ bne cr7, L(duLcr7) ++ srd r0, rWORD6, rSHR ++ sld rWORD6_SHIFT, rWORD6, rSHL ++ or rWORD6, r0, rWORD4_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD7, 0, rSTR1 ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ldu rWORD7, 24(rSTR1) + ldu rWORD8, 24(rSTR2) ++#endif + cmpld cr6, rWORD5, rWORD6 + bne cr1, L(duLcr1) +- srd rG, rWORD8, rSHR +- sld rB, rWORD8, rSHL +- or rWORD8, rG, rH ++ srd r12, rWORD8, rSHR ++ sld rWORD8_SHIFT, rWORD8, rSHL ++ or rWORD8, r12, rWORD6_SHIFT + cmpld cr5, rWORD7, rWORD8 + bdz- L(du24) /* Adjust CTR as we start with +4 */ + /* This is the primary loop */ +- .align 4 ++ .align 4 + L(duLoop): ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD1, 8(rSTR1) + ld rWORD2, 8(rSTR2) ++#endif + cmpld cr1, rWORD3, rWORD4 + bne cr6, L(duLcr6) +- srd rA, rWORD2, rSHR +- sld rD, rWORD2, rSHL +- or rWORD2, rA, rB ++ srd r0, rWORD2, rSHR ++ sld rWORD2_SHIFT, rWORD2, rSHL ++ or rWORD2, r0, rWORD8_SHIFT + L(duLoop1): ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD3, 0, rSTR1 ++ ldbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD3, 16(rSTR1) + ld rWORD4, 16(rSTR2) ++#endif + cmpld cr6, rWORD5, rWORD6 + bne cr5, L(duLcr5) +- srd rC, rWORD4, rSHR +- sld rF, rWORD4, rSHL +- or rWORD4, rC, rD ++ srd r12, rWORD4, rSHR ++ sld rWORD4_SHIFT, rWORD4, rSHL ++ or rWORD4, r12, rWORD2_SHIFT + L(duLoop2): ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD5, 0, rSTR1 ++ ldbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD5, 24(rSTR1) + ld rWORD6, 24(rSTR2) ++#endif + cmpld cr5, rWORD7, rWORD8 +- bne cr0, L(duLcr0) +- srd rE, rWORD6, rSHR +- sld rH, rWORD6, rSHL +- or rWORD6, rE, rF ++ bne cr7, L(duLcr7) ++ srd r0, rWORD6, rSHR ++ sld rWORD6_SHIFT, rWORD6, rSHL ++ or rWORD6, r0, rWORD4_SHIFT + L(duLoop3): ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD7, 0, rSTR1 ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else + ldu rWORD7, 32(rSTR1) + ldu rWORD8, 32(rSTR2) +- cmpld cr0, rWORD1, rWORD2 ++#endif ++ cmpld cr7, rWORD1, rWORD2 + bne- cr1, L(duLcr1) +- srd rG, rWORD8, rSHR +- sld rB, rWORD8, rSHL +- or rWORD8, rG, rH +- bdnz+ L(duLoop) +- ++ srd r12, rWORD8, rSHR ++ sld rWORD8_SHIFT, rWORD8, rSHL ++ or rWORD8, r12, rWORD6_SHIFT ++ bdnz+ L(duLoop) ++ + L(duL4): ++#if 0 ++/* Huh? We've already branched on cr1! */ + bne cr1, L(duLcr1) ++#endif + cmpld cr1, rWORD3, rWORD4 + bne cr6, L(duLcr6) + cmpld cr6, rWORD5, rWORD6 + bne cr5, L(duLcr5) + cmpld cr5, rWORD7, rWORD8 + L(du44): +- bne cr0, L(duLcr0) ++ bne cr7, L(duLcr7) + L(du34): + bne cr1, L(duLcr1) + L(du24): +@@ -876,106 +1253,113 @@ + sldi. rN, rN, 3 + bne cr5, L(duLcr5) + /* At this point we have a remainder of 1 to 7 bytes to compare. We use +- shift right double to elliminate bits beyond the compare length. +- This allows the use of double word subtract to compute the final +- result. ++ shift right double to eliminate bits beyond the compare length. + +- However it may not be safe to load rWORD2 which may be beyond the ++ However it may not be safe to load rWORD2 which may be beyond the + string length. So we compare the bit length of the remainder to + the right shift count (rSHR). If the bit count is less than or equal + we do not need to load rWORD2 (all significant bits are already in +- rB). */ ++ rWORD8_SHIFT). */ + cmpld cr7, rN, rSHR + beq L(duZeroReturn) +- li rA, 0 ++ li r0, 0 + ble cr7, L(dutrim) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR2, rSTR2, 8 ++#else + ld rWORD2, 8(rSTR2) +- srd rA, rWORD2, rSHR +- .align 4 ++#endif ++ srd r0, rWORD2, rSHR ++ .align 4 + L(dutrim): ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++#else + ld rWORD1, 8(rSTR1) +- ld rWORD8,-8(r1) +- subfic rN, rN, 64 /* Shift count is 64 - (rN * 8). */ +- or rWORD2, rA, rB +- ld rWORD7,-16(r1) +- ld r29,-24(r1) ++#endif ++ ld rWORD8, -8(r1) ++ subfic rN, rN, 64 /* Shift count is 64 - (rN * 8). */ ++ or rWORD2, r0, rWORD8_SHIFT ++ ld rWORD7, -16(r1) ++ ld rSHL, -24(r1) + srd rWORD1, rWORD1, rN + srd rWORD2, rWORD2, rN +- ld r28,-32(r1) +- ld r27,-40(r1) ++ ld rSHR, -32(r1) ++ ld rWORD8_SHIFT, -40(r1) + li rRTN, 0 +- cmpld cr0, rWORD1, rWORD2 +- ld r26,-48(r1) +- ld r25,-56(r1) +- beq cr0, L(dureturn24) +- li rRTN, 1 +- ld r24,-64(r1) +- bgtlr cr0 +- li rRTN, -1 +- blr +- .align 4 +-L(duLcr0): +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) +- li rRTN, 1 +- bgt cr0, L(dureturn29) +- ld r29,-24(r1) +- ld r28,-32(r1) ++ cmpld cr7, rWORD1, rWORD2 ++ ld rWORD2_SHIFT, -48(r1) ++ ld rWORD4_SHIFT, -56(r1) ++ beq cr7, L(dureturn24) ++ li rRTN, 1 ++ ld rWORD6_SHIFT, -64(r1) ++ bgtlr cr7 ++ li rRTN, -1 ++ blr ++ .align 4 ++L(duLcr7): ++ ld rWORD8, -8(r1) ++ ld rWORD7, -16(r1) ++ li rRTN, 1 ++ bgt cr7, L(dureturn29) ++ ld rSHL, -24(r1) ++ ld rSHR, -32(r1) + li rRTN, -1 + b L(dureturn27) +- .align 4 ++ .align 4 + L(duLcr1): +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) ++ ld rWORD8, -8(r1) ++ ld rWORD7, -16(r1) + li rRTN, 1 +- bgt cr1, L(dureturn29) +- ld r29,-24(r1) +- ld r28,-32(r1) ++ bgt cr1, L(dureturn29) ++ ld rSHL, -24(r1) ++ ld rSHR, -32(r1) + li rRTN, -1 + b L(dureturn27) +- .align 4 ++ .align 4 + L(duLcr6): +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) ++ ld rWORD8, -8(r1) ++ ld rWORD7, -16(r1) + li rRTN, 1 +- bgt cr6, L(dureturn29) +- ld r29,-24(r1) +- ld r28,-32(r1) ++ bgt cr6, L(dureturn29) ++ ld rSHL, -24(r1) ++ ld rSHR, -32(r1) + li rRTN, -1 + b L(dureturn27) +- .align 4 ++ .align 4 + L(duLcr5): +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) ++ ld rWORD8, -8(r1) ++ ld rWORD7, -16(r1) + li rRTN, 1 +- bgt cr5, L(dureturn29) +- ld r29,-24(r1) +- ld r28,-32(r1) ++ bgt cr5, L(dureturn29) ++ ld rSHL, -24(r1) ++ ld rSHR, -32(r1) + li rRTN, -1 + b L(dureturn27) + .align 3 + L(duZeroReturn): +- li rRTN,0 ++ li rRTN, 0 + .align 4 + L(dureturn): +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) +-L(dureturn29): +- ld r29,-24(r1) +- ld r28,-32(r1) +-L(dureturn27): +- ld r27,-40(r1) +-L(dureturn26): +- ld r26,-48(r1) +-L(dureturn25): +- ld r25,-56(r1) ++ ld rWORD8, -8(r1) ++ ld rWORD7, -16(r1) ++L(dureturn29): ++ ld rSHL, -24(r1) ++ ld rSHR, -32(r1) ++L(dureturn27): ++ ld rWORD8_SHIFT, -40(r1) ++L(dureturn26): ++ ld rWORD2_SHIFT, -48(r1) ++L(dureturn25): ++ ld rWORD4_SHIFT, -56(r1) + L(dureturn24): +- ld r24,-64(r1) ++ ld rWORD6_SHIFT, -64(r1) + blr + L(duzeroLength): +- li rRTN,0 ++ li rRTN, 0 + blr + +-END (BP_SYM (memcmp)) ++END (memcmp) + libc_hidden_builtin_def (memcmp) + weak_alias (memcmp, bcmp) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memcmp.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memcmp.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memcmp.S 2014-05-28 19:22:37.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memcmp.S 2014-05-29 09:35:08.000000000 -0500 +@@ -1,5 +1,5 @@ + /* Optimized memcmp implementation for POWER7/PowerPC64. +- Copyright (C) 2010, 2011 Free Software Foundation, Inc. ++ Copyright (C) 2010-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or +@@ -17,379 +17,576 @@ + . */ + + #include +-#include +-#include + + /* int [r3] memcmp (const char *s1 [r3], + const char *s2 [r4], + size_t size [r5]) */ + + .machine power7 +-EALIGN (BP_SYM(memcmp),4,0) ++EALIGN (memcmp, 4, 0) + CALL_MCOUNT 3 + +-#define rTMP r0 + #define rRTN r3 + #define rSTR1 r3 /* first string arg */ + #define rSTR2 r4 /* second string arg */ + #define rN r5 /* max string length */ +-/* Note: The Bounded pointer support in this code is broken. This code +- was inherited from PPC32 and that support was never completed. +- Current PPC gcc does not support -fbounds-check or -fbounded-pointers. */ + #define rWORD1 r6 /* current word in s1 */ + #define rWORD2 r7 /* current word in s2 */ + #define rWORD3 r8 /* next word in s1 */ + #define rWORD4 r9 /* next word in s2 */ + #define rWORD5 r10 /* next word in s1 */ + #define rWORD6 r11 /* next word in s2 */ +-#define rBITDIF r12 /* bits that differ in s1 & s2 words */ + #define rWORD7 r30 /* next word in s1 */ + #define rWORD8 r31 /* next word in s2 */ + +- xor rTMP,rSTR2,rSTR1 +- cmpldi cr6,rN,0 +- cmpldi cr1,rN,12 +- clrldi. rTMP,rTMP,61 +- clrldi rBITDIF,rSTR1,61 +- cmpldi cr5,rBITDIF,0 +- beq- cr6,L(zeroLength) +- dcbt 0,rSTR1 +- dcbt 0,rSTR2 +-/* If less than 8 bytes or not aligned, use the unalligned ++ xor r0, rSTR2, rSTR1 ++ cmpldi cr6, rN, 0 ++ cmpldi cr1, rN, 12 ++ clrldi. r0, r0, 61 ++ clrldi r12, rSTR1, 61 ++ cmpldi cr5, r12, 0 ++ beq- cr6, L(zeroLength) ++ dcbt 0, rSTR1 ++ dcbt 0, rSTR2 ++/* If less than 8 bytes or not aligned, use the unaligned + byte loop. */ +- blt cr1,L(bytealigned) +- std rWORD8,-8(r1) +- cfi_offset(rWORD8,-8) +- std rWORD7,-16(r1) +- cfi_offset(rWORD7,-16) ++ blt cr1, L(bytealigned) ++ std rWORD8, -8(r1) ++ cfi_offset(rWORD8, -8) ++ std rWORD7, -16(r1) ++ cfi_offset(rWORD7, -16) + bne L(unaligned) + /* At this point we know both strings have the same alignment and the +- compare length is at least 8 bytes. rBITDIF containes the low order ++ compare length is at least 8 bytes. r12 contains the low order + 3 bits of rSTR1 and cr5 contains the result of the logical compare +- of rBITDIF to 0. If rBITDIF == 0 then we are already double word +- aligned and can perform the DWaligned loop. ++ of r12 to 0. If r12 == 0 then we are already double word ++ aligned and can perform the DW aligned loop. + + Otherwise we know the two strings have the same alignment (but not +- yet DW). So we can force the string addresses to the next lower DW +- boundary and special case this first DW word using shift left to +- ellimiate bits preceeding the first byte. Since we want to join the +- normal (DWaligned) compare loop, starting at the second double word, ++ yet DW). So we force the string addresses to the next lower DW ++ boundary and special case this first DW using shift left to ++ eliminate bits preceding the first byte. Since we want to join the ++ normal (DW aligned) compare loop, starting at the second double word, + we need to adjust the length (rN) and special case the loop +- versioning for the first DW. This insures that the loop count is +- correct and the first DW (shifted) is in the expected resister pair. */ ++ versioning for the first DW. This ensures that the loop count is ++ correct and the first DW (shifted) is in the expected register pair. */ + .align 4 + L(samealignment): +- clrrdi rSTR1,rSTR1,3 +- clrrdi rSTR2,rSTR2,3 +- beq cr5,L(DWaligned) +- add rN,rN,rBITDIF +- sldi r11,rBITDIF,3 +- srdi rTMP,rN,5 /* Divide by 32 */ +- andi. rBITDIF,rN,24 /* Get the DW remainder */ +- ld rWORD1,0(rSTR1) +- ld rWORD2,0(rSTR2) +- cmpldi cr1,rBITDIF,16 +- cmpldi cr7,rN,32 +- clrldi rN,rN,61 ++ clrrdi rSTR1, rSTR1, 3 ++ clrrdi rSTR2, rSTR2, 3 ++ beq cr5, L(DWaligned) ++ add rN, rN, r12 ++ sldi rWORD6, r12, 3 ++ srdi r0, rN, 5 /* Divide by 32 */ ++ andi. r12, rN, 24 /* Get the DW remainder */ ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD1, 0(rSTR1) ++ ld rWORD2, 0(rSTR2) ++#endif ++ cmpldi cr1, r12, 16 ++ cmpldi cr7, rN, 32 ++ clrldi rN, rN, 61 + beq L(dPs4) +- mtctr rTMP +- bgt cr1,L(dPs3) +- beq cr1,L(dPs2) ++ mtctr r0 ++ bgt cr1, L(dPs3) ++ beq cr1, L(dPs2) + + /* Remainder is 8 */ + .align 3 + L(dsP1): +- sld rWORD5,rWORD1,r11 +- sld rWORD6,rWORD2,r11 +- cmpld cr5,rWORD5,rWORD6 +- blt cr7,L(dP1x) ++ sld rWORD5, rWORD1, rWORD6 ++ sld rWORD6, rWORD2, rWORD6 ++ cmpld cr5, rWORD5, rWORD6 ++ blt cr7, L(dP1x) + /* Do something useful in this cycle since we have to branch anyway. */ +- ld rWORD1,8(rSTR1) +- ld rWORD2,8(rSTR2) +- cmpld cr0,rWORD1,rWORD2 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD1, 8(rSTR1) ++ ld rWORD2, 8(rSTR2) ++#endif ++ cmpld cr7, rWORD1, rWORD2 + b L(dP1e) + /* Remainder is 16 */ + .align 4 + L(dPs2): +- sld rWORD5,rWORD1,r11 +- sld rWORD6,rWORD2,r11 +- cmpld cr6,rWORD5,rWORD6 +- blt cr7,L(dP2x) ++ sld rWORD5, rWORD1, rWORD6 ++ sld rWORD6, rWORD2, rWORD6 ++ cmpld cr6, rWORD5, rWORD6 ++ blt cr7, L(dP2x) + /* Do something useful in this cycle since we have to branch anyway. */ +- ld rWORD7,8(rSTR1) +- ld rWORD8,8(rSTR2) +- cmpld cr5,rWORD7,rWORD8 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD7, 0, rSTR1 ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD7, 8(rSTR1) ++ ld rWORD8, 8(rSTR2) ++#endif ++ cmpld cr5, rWORD7, rWORD8 + b L(dP2e) + /* Remainder is 24 */ + .align 4 + L(dPs3): +- sld rWORD3,rWORD1,r11 +- sld rWORD4,rWORD2,r11 +- cmpld cr1,rWORD3,rWORD4 ++ sld rWORD3, rWORD1, rWORD6 ++ sld rWORD4, rWORD2, rWORD6 ++ cmpld cr1, rWORD3, rWORD4 + b L(dP3e) + /* Count is a multiple of 32, remainder is 0 */ + .align 4 + L(dPs4): +- mtctr rTMP +- sld rWORD1,rWORD1,r11 +- sld rWORD2,rWORD2,r11 +- cmpld cr0,rWORD1,rWORD2 ++ mtctr r0 ++ sld rWORD1, rWORD1, rWORD6 ++ sld rWORD2, rWORD2, rWORD6 ++ cmpld cr7, rWORD1, rWORD2 + b L(dP4e) + + /* At this point we know both strings are double word aligned and the + compare length is at least 8 bytes. */ + .align 4 + L(DWaligned): +- andi. rBITDIF,rN,24 /* Get the DW remainder */ +- srdi rTMP,rN,5 /* Divide by 32 */ +- cmpldi cr1,rBITDIF,16 +- cmpldi cr7,rN,32 +- clrldi rN,rN,61 ++ andi. r12, rN, 24 /* Get the DW remainder */ ++ srdi r0, rN, 5 /* Divide by 32 */ ++ cmpldi cr1, r12, 16 ++ cmpldi cr7, rN, 32 ++ clrldi rN, rN, 61 + beq L(dP4) +- bgt cr1,L(dP3) +- beq cr1,L(dP2) ++ bgt cr1, L(dP3) ++ beq cr1, L(dP2) + + /* Remainder is 8 */ + .align 4 + L(dP1): +- mtctr rTMP ++ mtctr r0 + /* Normally we'd use rWORD7/rWORD8 here, but since we might exit early +- (8-15 byte compare), we want to use only volitile registers. This +- means we can avoid restoring non-volitile registers since we did not ++ (8-15 byte compare), we want to use only volatile registers. This ++ means we can avoid restoring non-volatile registers since we did not + change any on the early exit path. The key here is the non-early + exit path only cares about the condition code (cr5), not about which + register pair was used. */ +- ld rWORD5,0(rSTR1) +- ld rWORD6,0(rSTR2) +- cmpld cr5,rWORD5,rWORD6 +- blt cr7,L(dP1x) +- ld rWORD1,8(rSTR1) +- ld rWORD2,8(rSTR2) +- cmpld cr0,rWORD1,rWORD2 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD5, 0, rSTR1 ++ ldbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD5, 0(rSTR1) ++ ld rWORD6, 0(rSTR2) ++#endif ++ cmpld cr5, rWORD5, rWORD6 ++ blt cr7, L(dP1x) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD1, 8(rSTR1) ++ ld rWORD2, 8(rSTR2) ++#endif ++ cmpld cr7, rWORD1, rWORD2 + L(dP1e): +- ld rWORD3,16(rSTR1) +- ld rWORD4,16(rSTR2) +- cmpld cr1,rWORD3,rWORD4 +- ld rWORD5,24(rSTR1) +- ld rWORD6,24(rSTR2) +- cmpld cr6,rWORD5,rWORD6 +- bne cr5,L(dLcr5) +- bne cr0,L(dLcr0) +- +- ldu rWORD7,32(rSTR1) +- ldu rWORD8,32(rSTR2) +- bne cr1,L(dLcr1) +- cmpld cr5,rWORD7,rWORD8 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD3, 0, rSTR1 ++ ldbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD3, 16(rSTR1) ++ ld rWORD4, 16(rSTR2) ++#endif ++ cmpld cr1, rWORD3, rWORD4 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD5, 0, rSTR1 ++ ldbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD5, 24(rSTR1) ++ ld rWORD6, 24(rSTR2) ++#endif ++ cmpld cr6, rWORD5, rWORD6 ++ bne cr5, L(dLcr5x) ++ bne cr7, L(dLcr7x) ++ ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD7, 0, rSTR1 ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ldu rWORD7, 32(rSTR1) ++ ldu rWORD8, 32(rSTR2) ++#endif ++ bne cr1, L(dLcr1) ++ cmpld cr5, rWORD7, rWORD8 + bdnz L(dLoop) +- bne cr6,L(dLcr6) +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) ++ bne cr6, L(dLcr6) ++ ld rWORD8, -8(r1) ++ ld rWORD7, -16(r1) + .align 3 + L(dP1x): +- sldi. r12,rN,3 +- bne cr5,L(dLcr5) +- subfic rN,r12,64 /* Shift count is 64 - (rN * 8). */ ++ sldi. r12, rN, 3 ++ bne cr5, L(dLcr5x) ++ subfic rN, r12, 64 /* Shift count is 64 - (rN * 8). */ + bne L(d00) +- li rRTN,0 ++ li rRTN, 0 + blr + + /* Remainder is 16 */ + .align 4 + L(dP2): +- mtctr rTMP +- ld rWORD5,0(rSTR1) +- ld rWORD6,0(rSTR2) +- cmpld cr6,rWORD5,rWORD6 +- blt cr7,L(dP2x) +- ld rWORD7,8(rSTR1) +- ld rWORD8,8(rSTR2) +- cmpld cr5,rWORD7,rWORD8 ++ mtctr r0 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD5, 0, rSTR1 ++ ldbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD5, 0(rSTR1) ++ ld rWORD6, 0(rSTR2) ++#endif ++ cmpld cr6, rWORD5, rWORD6 ++ blt cr7, L(dP2x) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD7, 0, rSTR1 ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD7, 8(rSTR1) ++ ld rWORD8, 8(rSTR2) ++#endif ++ cmpld cr5, rWORD7, rWORD8 + L(dP2e): +- ld rWORD1,16(rSTR1) +- ld rWORD2,16(rSTR2) +- cmpld cr0,rWORD1,rWORD2 +- ld rWORD3,24(rSTR1) +- ld rWORD4,24(rSTR2) +- cmpld cr1,rWORD3,rWORD4 +- addi rSTR1,rSTR1,8 +- addi rSTR2,rSTR2,8 +- bne cr6,L(dLcr6) +- bne cr5,L(dLcr5) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD1, 16(rSTR1) ++ ld rWORD2, 16(rSTR2) ++#endif ++ cmpld cr7, rWORD1, rWORD2 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD3, 0, rSTR1 ++ ldbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD3, 24(rSTR1) ++ ld rWORD4, 24(rSTR2) ++#endif ++ cmpld cr1, rWORD3, rWORD4 ++#ifndef __LITTLE_ENDIAN__ ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#endif ++ bne cr6, L(dLcr6) ++ bne cr5, L(dLcr5) + b L(dLoop2) + /* Again we are on a early exit path (16-23 byte compare), we want to +- only use volitile registers and avoid restoring non-volitile ++ only use volatile registers and avoid restoring non-volatile + registers. */ + .align 4 + L(dP2x): +- ld rWORD3,8(rSTR1) +- ld rWORD4,8(rSTR2) +- cmpld cr5,rWORD3,rWORD4 +- sldi. r12,rN,3 +- bne cr6,L(dLcr6) +- addi rSTR1,rSTR1,8 +- addi rSTR2,rSTR2,8 +- bne cr5,L(dLcr5) +- subfic rN,r12,64 /* Shift count is 64 - (rN * 8). */ ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD3, 0, rSTR1 ++ ldbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD3, 8(rSTR1) ++ ld rWORD4, 8(rSTR2) ++#endif ++ cmpld cr1, rWORD3, rWORD4 ++ sldi. r12, rN, 3 ++ bne cr6, L(dLcr6x) ++#ifndef __LITTLE_ENDIAN__ ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#endif ++ bne cr1, L(dLcr1x) ++ subfic rN, r12, 64 /* Shift count is 64 - (rN * 8). */ + bne L(d00) +- li rRTN,0 ++ li rRTN, 0 + blr + + /* Remainder is 24 */ + .align 4 + L(dP3): +- mtctr rTMP +- ld rWORD3,0(rSTR1) +- ld rWORD4,0(rSTR2) +- cmpld cr1,rWORD3,rWORD4 ++ mtctr r0 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD3, 0, rSTR1 ++ ldbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD3, 0(rSTR1) ++ ld rWORD4, 0(rSTR2) ++#endif ++ cmpld cr1, rWORD3, rWORD4 + L(dP3e): +- ld rWORD5,8(rSTR1) +- ld rWORD6,8(rSTR2) +- cmpld cr6,rWORD5,rWORD6 +- blt cr7,L(dP3x) +- ld rWORD7,16(rSTR1) +- ld rWORD8,16(rSTR2) +- cmpld cr5,rWORD7,rWORD8 +- ld rWORD1,24(rSTR1) +- ld rWORD2,24(rSTR2) +- cmpld cr0,rWORD1,rWORD2 +- addi rSTR1,rSTR1,16 +- addi rSTR2,rSTR2,16 +- bne cr1,L(dLcr1) +- bne cr6,L(dLcr6) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD5, 0, rSTR1 ++ ldbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD5, 8(rSTR1) ++ ld rWORD6, 8(rSTR2) ++#endif ++ cmpld cr6, rWORD5, rWORD6 ++ blt cr7, L(dP3x) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD7, 0, rSTR1 ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD7, 16(rSTR1) ++ ld rWORD8, 16(rSTR2) ++#endif ++ cmpld cr5, rWORD7, rWORD8 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD1, 24(rSTR1) ++ ld rWORD2, 24(rSTR2) ++#endif ++ cmpld cr7, rWORD1, rWORD2 ++#ifndef __LITTLE_ENDIAN__ ++ addi rSTR1, rSTR1, 16 ++ addi rSTR2, rSTR2, 16 ++#endif ++ bne cr1, L(dLcr1) ++ bne cr6, L(dLcr6) + b L(dLoop1) + /* Again we are on a early exit path (24-31 byte compare), we want to +- only use volitile registers and avoid restoring non-volitile ++ only use volatile registers and avoid restoring non-volatile + registers. */ + .align 4 + L(dP3x): +- ld rWORD1,16(rSTR1) +- ld rWORD2,16(rSTR2) +- cmpld cr5,rWORD1,rWORD2 +- sldi. r12,rN,3 +- bne cr1,L(dLcr1) +- addi rSTR1,rSTR1,16 +- addi rSTR2,rSTR2,16 +- bne cr6,L(dLcr6) +- subfic rN,r12,64 /* Shift count is 64 - (rN * 8). */ +- bne cr5,L(dLcr5) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD1, 16(rSTR1) ++ ld rWORD2, 16(rSTR2) ++#endif ++ cmpld cr7, rWORD1, rWORD2 ++ sldi. r12, rN, 3 ++ bne cr1, L(dLcr1x) ++#ifndef __LITTLE_ENDIAN__ ++ addi rSTR1, rSTR1, 16 ++ addi rSTR2, rSTR2, 16 ++#endif ++ bne cr6, L(dLcr6x) ++ subfic rN, r12, 64 /* Shift count is 64 - (rN * 8). */ ++ bne cr7, L(dLcr7x) + bne L(d00) +- li rRTN,0 ++ li rRTN, 0 + blr + + /* Count is a multiple of 32, remainder is 0 */ + .align 4 + L(dP4): +- mtctr rTMP +- ld rWORD1,0(rSTR1) +- ld rWORD2,0(rSTR2) +- cmpld cr0,rWORD1,rWORD2 ++ mtctr r0 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD1, 0(rSTR1) ++ ld rWORD2, 0(rSTR2) ++#endif ++ cmpld cr7, rWORD1, rWORD2 + L(dP4e): +- ld rWORD3,8(rSTR1) +- ld rWORD4,8(rSTR2) +- cmpld cr1,rWORD3,rWORD4 +- ld rWORD5,16(rSTR1) +- ld rWORD6,16(rSTR2) +- cmpld cr6,rWORD5,rWORD6 +- ldu rWORD7,24(rSTR1) +- ldu rWORD8,24(rSTR2) +- cmpld cr5,rWORD7,rWORD8 +- bne cr0,L(dLcr0) +- bne cr1,L(dLcr1) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD3, 0, rSTR1 ++ ldbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD3, 8(rSTR1) ++ ld rWORD4, 8(rSTR2) ++#endif ++ cmpld cr1, rWORD3, rWORD4 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD5, 0, rSTR1 ++ ldbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD5, 16(rSTR1) ++ ld rWORD6, 16(rSTR2) ++#endif ++ cmpld cr6, rWORD5, rWORD6 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD7, 0, rSTR1 ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ldu rWORD7, 24(rSTR1) ++ ldu rWORD8, 24(rSTR2) ++#endif ++ cmpld cr5, rWORD7, rWORD8 ++ bne cr7, L(dLcr7) ++ bne cr1, L(dLcr1) + bdz- L(d24) /* Adjust CTR as we start with +4 */ + /* This is the primary loop */ + .align 4 + L(dLoop): +- ld rWORD1,8(rSTR1) +- ld rWORD2,8(rSTR2) +- cmpld cr1,rWORD3,rWORD4 +- bne cr6,L(dLcr6) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD1, 8(rSTR1) ++ ld rWORD2, 8(rSTR2) ++#endif ++ cmpld cr1, rWORD3, rWORD4 ++ bne cr6, L(dLcr6) + L(dLoop1): +- ld rWORD3,16(rSTR1) +- ld rWORD4,16(rSTR2) +- cmpld cr6,rWORD5,rWORD6 +- bne cr5,L(dLcr5) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD3, 0, rSTR1 ++ ldbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD3, 16(rSTR1) ++ ld rWORD4, 16(rSTR2) ++#endif ++ cmpld cr6, rWORD5, rWORD6 ++ bne cr5, L(dLcr5) + L(dLoop2): +- ld rWORD5,24(rSTR1) +- ld rWORD6,24(rSTR2) +- cmpld cr5,rWORD7,rWORD8 +- bne cr0,L(dLcr0) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD5, 0, rSTR1 ++ ldbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD5, 24(rSTR1) ++ ld rWORD6, 24(rSTR2) ++#endif ++ cmpld cr5, rWORD7, rWORD8 ++ bne cr7, L(dLcr7) + L(dLoop3): +- ldu rWORD7,32(rSTR1) +- ldu rWORD8,32(rSTR2) +- bne cr1,L(dLcr1) +- cmpld cr0,rWORD1,rWORD2 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD7, 0, rSTR1 ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ldu rWORD7, 32(rSTR1) ++ ldu rWORD8, 32(rSTR2) ++#endif ++ bne cr1, L(dLcr1) ++ cmpld cr7, rWORD1, rWORD2 + bdnz L(dLoop) + + L(dL4): +- cmpld cr1,rWORD3,rWORD4 +- bne cr6,L(dLcr6) +- cmpld cr6,rWORD5,rWORD6 +- bne cr5,L(dLcr5) +- cmpld cr5,rWORD7,rWORD8 ++ cmpld cr1, rWORD3, rWORD4 ++ bne cr6, L(dLcr6) ++ cmpld cr6, rWORD5, rWORD6 ++ bne cr5, L(dLcr5) ++ cmpld cr5, rWORD7, rWORD8 + L(d44): +- bne cr0,L(dLcr0) ++ bne cr7, L(dLcr7) + L(d34): +- bne cr1,L(dLcr1) ++ bne cr1, L(dLcr1) + L(d24): +- bne cr6,L(dLcr6) ++ bne cr6, L(dLcr6) + L(d14): +- sldi. r12,rN,3 +- bne cr5,L(dLcr5) ++ sldi. r12, rN, 3 ++ bne cr5, L(dLcr5) + L(d04): +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) +- subfic rN,r12,64 /* Shift count is 64 - (rN * 8). */ ++ ld rWORD8, -8(r1) ++ ld rWORD7, -16(r1) ++ subfic rN, r12, 64 /* Shift count is 64 - (rN * 8). */ + beq L(zeroLength) + /* At this point we have a remainder of 1 to 7 bytes to compare. Since + we are aligned it is safe to load the whole double word, and use +- shift right double to elliminate bits beyond the compare length. */ ++ shift right double to eliminate bits beyond the compare length. */ + L(d00): +- ld rWORD1,8(rSTR1) +- ld rWORD2,8(rSTR2) +- srd rWORD1,rWORD1,rN +- srd rWORD2,rWORD2,rN +- cmpld cr5,rWORD1,rWORD2 +- bne cr5,L(dLcr5x) +- li rRTN,0 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD1, 8(rSTR1) ++ ld rWORD2, 8(rSTR2) ++#endif ++ srd rWORD1, rWORD1, rN ++ srd rWORD2, rWORD2, rN ++ cmpld cr7, rWORD1, rWORD2 ++ bne cr7, L(dLcr7x) ++ li rRTN, 0 + blr ++ + .align 4 +-L(dLcr0): +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) +- li rRTN,1 +- bgtlr cr0 +- li rRTN,-1 ++L(dLcr7): ++ ld rWORD8, -8(r1) ++ ld rWORD7, -16(r1) ++L(dLcr7x): ++ li rRTN, 1 ++ bgtlr cr7 ++ li rRTN, -1 + blr + .align 4 + L(dLcr1): +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) +- li rRTN,1 ++ ld rWORD8, -8(r1) ++ ld rWORD7, -16(r1) ++L(dLcr1x): ++ li rRTN, 1 + bgtlr cr1 +- li rRTN,-1 ++ li rRTN, -1 + blr + .align 4 + L(dLcr6): +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) +- li rRTN,1 ++ ld rWORD8, -8(r1) ++ ld rWORD7, -16(r1) ++L(dLcr6x): ++ li rRTN, 1 + bgtlr cr6 +- li rRTN,-1 ++ li rRTN, -1 + blr + .align 4 + L(dLcr5): +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) ++ ld rWORD8, -8(r1) ++ ld rWORD7, -16(r1) + L(dLcr5x): +- li rRTN,1 ++ li rRTN, 1 + bgtlr cr5 +- li rRTN,-1 ++ li rRTN, -1 + blr + + .align 4 + L(bytealigned): + mtctr rN +- beq cr6,L(zeroLength) ++#if 0 ++/* Huh? We've already branched on cr6! */ ++ beq cr6, L(zeroLength) ++#endif + + /* We need to prime this loop. This loop is swing modulo scheduled + to avoid pipe delays. The dependent instruction latencies (load to +@@ -401,38 +598,38 @@ + So we must precondition some registers and condition codes so that + we don't exit the loop early on the first iteration. */ + +- lbz rWORD1,0(rSTR1) +- lbz rWORD2,0(rSTR2) ++ lbz rWORD1, 0(rSTR1) ++ lbz rWORD2, 0(rSTR2) + bdz L(b11) +- cmpld cr0,rWORD1,rWORD2 +- lbz rWORD3,1(rSTR1) +- lbz rWORD4,1(rSTR2) ++ cmpld cr7, rWORD1, rWORD2 ++ lbz rWORD3, 1(rSTR1) ++ lbz rWORD4, 1(rSTR2) + bdz L(b12) +- cmpld cr1,rWORD3,rWORD4 +- lbzu rWORD5,2(rSTR1) +- lbzu rWORD6,2(rSTR2) ++ cmpld cr1, rWORD3, rWORD4 ++ lbzu rWORD5, 2(rSTR1) ++ lbzu rWORD6, 2(rSTR2) + bdz L(b13) + .align 4 + L(bLoop): +- lbzu rWORD1,1(rSTR1) +- lbzu rWORD2,1(rSTR2) +- bne cr0,L(bLcr0) ++ lbzu rWORD1, 1(rSTR1) ++ lbzu rWORD2, 1(rSTR2) ++ bne cr7, L(bLcr7) + +- cmpld cr6,rWORD5,rWORD6 ++ cmpld cr6, rWORD5, rWORD6 + bdz L(b3i) + +- lbzu rWORD3,1(rSTR1) +- lbzu rWORD4,1(rSTR2) +- bne cr1,L(bLcr1) ++ lbzu rWORD3, 1(rSTR1) ++ lbzu rWORD4, 1(rSTR2) ++ bne cr1, L(bLcr1) + +- cmpld cr0,rWORD1,rWORD2 ++ cmpld cr7, rWORD1, rWORD2 + bdz L(b2i) + +- lbzu rWORD5,1(rSTR1) +- lbzu rWORD6,1(rSTR2) +- bne cr6,L(bLcr6) ++ lbzu rWORD5, 1(rSTR1) ++ lbzu rWORD6, 1(rSTR2) ++ bne cr6, L(bLcr6) + +- cmpld cr1,rWORD3,rWORD4 ++ cmpld cr1, rWORD3, rWORD4 + bdnz L(bLoop) + + /* We speculatively loading bytes before we have tested the previous +@@ -442,542 +639,727 @@ + tested. In this case we must complete the pending operations + before returning. */ + L(b1i): +- bne cr0,L(bLcr0) +- bne cr1,L(bLcr1) ++ bne cr7, L(bLcr7) ++ bne cr1, L(bLcr1) + b L(bx56) + .align 4 + L(b2i): +- bne cr6,L(bLcr6) +- bne cr0,L(bLcr0) ++ bne cr6, L(bLcr6) ++ bne cr7, L(bLcr7) + b L(bx34) + .align 4 + L(b3i): +- bne cr1,L(bLcr1) +- bne cr6,L(bLcr6) ++ bne cr1, L(bLcr1) ++ bne cr6, L(bLcr6) + b L(bx12) + .align 4 +-L(bLcr0): +- li rRTN,1 +- bgtlr cr0 +- li rRTN,-1 ++L(bLcr7): ++ li rRTN, 1 ++ bgtlr cr7 ++ li rRTN, -1 + blr + L(bLcr1): +- li rRTN,1 ++ li rRTN, 1 + bgtlr cr1 +- li rRTN,-1 ++ li rRTN, -1 + blr + L(bLcr6): +- li rRTN,1 ++ li rRTN, 1 + bgtlr cr6 +- li rRTN,-1 ++ li rRTN, -1 + blr + + L(b13): +- bne cr0,L(bx12) +- bne cr1,L(bx34) ++ bne cr7, L(bx12) ++ bne cr1, L(bx34) + L(bx56): +- sub rRTN,rWORD5,rWORD6 ++ sub rRTN, rWORD5, rWORD6 + blr + nop + L(b12): +- bne cr0,L(bx12) ++ bne cr7, L(bx12) + L(bx34): +- sub rRTN,rWORD3,rWORD4 ++ sub rRTN, rWORD3, rWORD4 + blr + L(b11): + L(bx12): +- sub rRTN,rWORD1,rWORD2 ++ sub rRTN, rWORD1, rWORD2 + blr + .align 4 +-L(zeroLengthReturn): +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) + L(zeroLength): +- li rRTN,0 ++ li rRTN, 0 + blr + + .align 4 + /* At this point we know the strings have different alignment and the +- compare length is at least 8 bytes. rBITDIF containes the low order ++ compare length is at least 8 bytes. r12 contains the low order + 3 bits of rSTR1 and cr5 contains the result of the logical compare +- of rBITDIF to 0. If rBITDIF == 0 then rStr1 is double word ++ of r12 to 0. If r12 == 0 then rStr1 is double word + aligned and can perform the DWunaligned loop. + +- Otherwise we know that rSTR1 is not aready DW aligned yet. ++ Otherwise we know that rSTR1 is not already DW aligned yet. + So we can force the string addresses to the next lower DW +- boundary and special case this first DW word using shift left to +- ellimiate bits preceeding the first byte. Since we want to join the ++ boundary and special case this first DW using shift left to ++ eliminate bits preceding the first byte. Since we want to join the + normal (DWaligned) compare loop, starting at the second double word, + we need to adjust the length (rN) and special case the loop +- versioning for the first DW. This insures that the loop count is ++ versioning for the first DW. This ensures that the loop count is + correct and the first DW (shifted) is in the expected resister pair. */ +-#define rSHL r29 /* Unaligned shift left count. */ +-#define rSHR r28 /* Unaligned shift right count. */ +-#define rB r27 /* Left rotation temp for rWORD2. */ +-#define rD r26 /* Left rotation temp for rWORD4. */ +-#define rF r25 /* Left rotation temp for rWORD6. */ +-#define rH r24 /* Left rotation temp for rWORD8. */ +-#define rA r0 /* Right rotation temp for rWORD2. */ +-#define rC r12 /* Right rotation temp for rWORD4. */ +-#define rE r0 /* Right rotation temp for rWORD6. */ +-#define rG r12 /* Right rotation temp for rWORD8. */ ++#define rSHL r29 /* Unaligned shift left count. */ ++#define rSHR r28 /* Unaligned shift right count. */ ++#define rWORD8_SHIFT r27 /* Left rotation temp for rWORD2. */ ++#define rWORD2_SHIFT r26 /* Left rotation temp for rWORD4. */ ++#define rWORD4_SHIFT r25 /* Left rotation temp for rWORD6. */ ++#define rWORD6_SHIFT r24 /* Left rotation temp for rWORD8. */ + L(unaligned): +- std r29,-24(r1) +- cfi_offset(r29,-24) +- clrldi rSHL,rSTR2,61 +- beq cr6,L(duzeroLength) +- std r28,-32(r1) +- cfi_offset(r28,-32) +- beq cr5,L(DWunaligned) +- std r27,-40(r1) +- cfi_offset(r27,-40) +-/* Adjust the logical start of rSTR2 ro compensate for the extra bits ++ std rSHL, -24(r1) ++ cfi_offset(rSHL, -24) ++ clrldi rSHL, rSTR2, 61 ++ beq cr6, L(duzeroLength) ++ std rSHR, -32(r1) ++ cfi_offset(rSHR, -32) ++ beq cr5, L(DWunaligned) ++ std rWORD8_SHIFT, -40(r1) ++ cfi_offset(rWORD8_SHIFT, -40) ++/* Adjust the logical start of rSTR2 to compensate for the extra bits + in the 1st rSTR1 DW. */ +- sub r27,rSTR2,rBITDIF ++ sub rWORD8_SHIFT, rSTR2, r12 + /* But do not attempt to address the DW before that DW that contains + the actual start of rSTR2. */ +- clrrdi rSTR2,rSTR2,3 +- std r26,-48(r1) +- cfi_offset(r26,-48) +-/* Compute the leaft/right shift counts for the unalign rSTR2, ++ clrrdi rSTR2, rSTR2, 3 ++ std rWORD2_SHIFT, -48(r1) ++ cfi_offset(rWORD2_SHIFT, -48) ++/* Compute the left/right shift counts for the unaligned rSTR2, + compensating for the logical (DW aligned) start of rSTR1. */ +- clrldi rSHL,r27,61 +- clrrdi rSTR1,rSTR1,3 +- std r25,-56(r1) +- cfi_offset(r25,-56) +- sldi rSHL,rSHL,3 +- cmpld cr5,r27,rSTR2 +- add rN,rN,rBITDIF +- sldi r11,rBITDIF,3 +- std r24,-64(r1) +- cfi_offset(r24,-64) +- subfic rSHR,rSHL,64 +- srdi rTMP,rN,5 /* Divide by 32 */ +- andi. rBITDIF,rN,24 /* Get the DW remainder */ ++ clrldi rSHL, rWORD8_SHIFT, 61 ++ clrrdi rSTR1, rSTR1, 3 ++ std rWORD4_SHIFT, -56(r1) ++ cfi_offset(rWORD4_SHIFT, -56) ++ sldi rSHL, rSHL, 3 ++ cmpld cr5, rWORD8_SHIFT, rSTR2 ++ add rN, rN, r12 ++ sldi rWORD6, r12, 3 ++ std rWORD6_SHIFT, -64(r1) ++ cfi_offset(rWORD6_SHIFT, -64) ++ subfic rSHR, rSHL, 64 ++ srdi r0, rN, 5 /* Divide by 32 */ ++ andi. r12, rN, 24 /* Get the DW remainder */ + /* We normally need to load 2 DWs to start the unaligned rSTR2, but in + this special case those bits may be discarded anyway. Also we + must avoid loading a DW where none of the bits are part of rSTR2 as + this may cross a page boundary and cause a page fault. */ +- li rWORD8,0 +- blt cr5,L(dus0) +- ld rWORD8,0(rSTR2) +- la rSTR2,8(rSTR2) +- sld rWORD8,rWORD8,rSHL ++ li rWORD8, 0 ++ blt cr5, L(dus0) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD8, 0(rSTR2) ++ addi rSTR2, rSTR2, 8 ++#endif ++ sld rWORD8, rWORD8, rSHL + + L(dus0): +- ld rWORD1,0(rSTR1) +- ld rWORD2,0(rSTR2) +- cmpldi cr1,rBITDIF,16 +- cmpldi cr7,rN,32 +- srd rG,rWORD2,rSHR +- clrldi rN,rN,61 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD1, 0(rSTR1) ++ ld rWORD2, 0(rSTR2) ++#endif ++ cmpldi cr1, r12, 16 ++ cmpldi cr7, rN, 32 ++ srd r12, rWORD2, rSHR ++ clrldi rN, rN, 61 + beq L(duPs4) +- mtctr rTMP +- or rWORD8,rG,rWORD8 +- bgt cr1,L(duPs3) +- beq cr1,L(duPs2) ++ mtctr r0 ++ or rWORD8, r12, rWORD8 ++ bgt cr1, L(duPs3) ++ beq cr1, L(duPs2) + + /* Remainder is 8 */ + .align 4 + L(dusP1): +- sld rB,rWORD2,rSHL +- sld rWORD7,rWORD1,r11 +- sld rWORD8,rWORD8,r11 +- bge cr7,L(duP1e) ++ sld rWORD8_SHIFT, rWORD2, rSHL ++ sld rWORD7, rWORD1, rWORD6 ++ sld rWORD8, rWORD8, rWORD6 ++ bge cr7, L(duP1e) + /* At this point we exit early with the first double word compare + complete and remainder of 0 to 7 bytes. See L(du14) for details on + how we handle the remaining bytes. */ +- cmpld cr5,rWORD7,rWORD8 +- sldi. rN,rN,3 +- bne cr5,L(duLcr5) +- cmpld cr7,rN,rSHR ++ cmpld cr5, rWORD7, rWORD8 ++ sldi. rN, rN, 3 ++ bne cr5, L(duLcr5) ++ cmpld cr7, rN, rSHR + beq L(duZeroReturn) +- li rA,0 +- ble cr7,L(dutrim) +- ld rWORD2,8(rSTR2) +- srd rA,rWORD2,rSHR ++ li r0, 0 ++ ble cr7, L(dutrim) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD2, 8(rSTR2) ++#endif ++ srd r0, rWORD2, rSHR + b L(dutrim) + /* Remainder is 16 */ + .align 4 + L(duPs2): +- sld rH,rWORD2,rSHL +- sld rWORD5,rWORD1,r11 +- sld rWORD6,rWORD8,r11 ++ sld rWORD6_SHIFT, rWORD2, rSHL ++ sld rWORD5, rWORD1, rWORD6 ++ sld rWORD6, rWORD8, rWORD6 + b L(duP2e) + /* Remainder is 24 */ + .align 4 + L(duPs3): +- sld rF,rWORD2,rSHL +- sld rWORD3,rWORD1,r11 +- sld rWORD4,rWORD8,r11 ++ sld rWORD4_SHIFT, rWORD2, rSHL ++ sld rWORD3, rWORD1, rWORD6 ++ sld rWORD4, rWORD8, rWORD6 + b L(duP3e) + /* Count is a multiple of 32, remainder is 0 */ + .align 4 + L(duPs4): +- mtctr rTMP +- or rWORD8,rG,rWORD8 +- sld rD,rWORD2,rSHL +- sld rWORD1,rWORD1,r11 +- sld rWORD2,rWORD8,r11 ++ mtctr r0 ++ or rWORD8, r12, rWORD8 ++ sld rWORD2_SHIFT, rWORD2, rSHL ++ sld rWORD1, rWORD1, rWORD6 ++ sld rWORD2, rWORD8, rWORD6 + b L(duP4e) + + /* At this point we know rSTR1 is double word aligned and the + compare length is at least 8 bytes. */ + .align 4 + L(DWunaligned): +- std r27,-40(r1) +- cfi_offset(r27,-40) +- clrrdi rSTR2,rSTR2,3 +- std r26,-48(r1) +- cfi_offset(r26,-48) +- srdi rTMP,rN,5 /* Divide by 32 */ +- std r25,-56(r1) +- cfi_offset(r25,-56) +- andi. rBITDIF,rN,24 /* Get the DW remainder */ +- std r24,-64(r1) +- cfi_offset(r24,-64) +- sldi rSHL,rSHL,3 +- ld rWORD6,0(rSTR2) +- ldu rWORD8,8(rSTR2) +- cmpldi cr1,rBITDIF,16 +- cmpldi cr7,rN,32 +- clrldi rN,rN,61 +- subfic rSHR,rSHL,64 +- sld rH,rWORD6,rSHL ++ std rWORD8_SHIFT, -40(r1) ++ cfi_offset(rWORD8_SHIFT, -40) ++ clrrdi rSTR2, rSTR2, 3 ++ std rWORD2_SHIFT, -48(r1) ++ cfi_offset(rWORD2_SHIFT, -48) ++ srdi r0, rN, 5 /* Divide by 32 */ ++ std rWORD4_SHIFT, -56(r1) ++ cfi_offset(rWORD4_SHIFT, -56) ++ andi. r12, rN, 24 /* Get the DW remainder */ ++ std rWORD6_SHIFT, -64(r1) ++ cfi_offset(rWORD6_SHIFT, -64) ++ sldi rSHL, rSHL, 3 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD6, 0, rSTR2 ++ addi rSTR2, rSTR2, 8 ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD6, 0(rSTR2) ++ ldu rWORD8, 8(rSTR2) ++#endif ++ cmpldi cr1, r12, 16 ++ cmpldi cr7, rN, 32 ++ clrldi rN, rN, 61 ++ subfic rSHR, rSHL, 64 ++ sld rWORD6_SHIFT, rWORD6, rSHL + beq L(duP4) +- mtctr rTMP +- bgt cr1,L(duP3) +- beq cr1,L(duP2) ++ mtctr r0 ++ bgt cr1, L(duP3) ++ beq cr1, L(duP2) + + /* Remainder is 8 */ + .align 4 + L(duP1): +- srd rG,rWORD8,rSHR +- ld rWORD7,0(rSTR1) +- sld rB,rWORD8,rSHL +- or rWORD8,rG,rH +- blt cr7,L(duP1x) ++ srd r12, rWORD8, rSHR ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD7, 0, rSTR1 ++ addi rSTR1, rSTR1, 8 ++#else ++ ld rWORD7, 0(rSTR1) ++#endif ++ sld rWORD8_SHIFT, rWORD8, rSHL ++ or rWORD8, r12, rWORD6_SHIFT ++ blt cr7, L(duP1x) + L(duP1e): +- ld rWORD1,8(rSTR1) +- ld rWORD2,8(rSTR2) +- cmpld cr5,rWORD7,rWORD8 +- srd rA,rWORD2,rSHR +- sld rD,rWORD2,rSHL +- or rWORD2,rA,rB +- ld rWORD3,16(rSTR1) +- ld rWORD4,16(rSTR2) +- cmpld cr0,rWORD1,rWORD2 +- srd rC,rWORD4,rSHR +- sld rF,rWORD4,rSHL +- bne cr5,L(duLcr5) +- or rWORD4,rC,rD +- ld rWORD5,24(rSTR1) +- ld rWORD6,24(rSTR2) +- cmpld cr1,rWORD3,rWORD4 +- srd rE,rWORD6,rSHR +- sld rH,rWORD6,rSHL +- bne cr0,L(duLcr0) +- or rWORD6,rE,rF +- cmpld cr6,rWORD5,rWORD6 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD1, 8(rSTR1) ++ ld rWORD2, 8(rSTR2) ++#endif ++ cmpld cr5, rWORD7, rWORD8 ++ srd r0, rWORD2, rSHR ++ sld rWORD2_SHIFT, rWORD2, rSHL ++ or rWORD2, r0, rWORD8_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD3, 0, rSTR1 ++ ldbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD3, 16(rSTR1) ++ ld rWORD4, 16(rSTR2) ++#endif ++ cmpld cr7, rWORD1, rWORD2 ++ srd r12, rWORD4, rSHR ++ sld rWORD4_SHIFT, rWORD4, rSHL ++ bne cr5, L(duLcr5) ++ or rWORD4, r12, rWORD2_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD5, 0, rSTR1 ++ ldbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD5, 24(rSTR1) ++ ld rWORD6, 24(rSTR2) ++#endif ++ cmpld cr1, rWORD3, rWORD4 ++ srd r0, rWORD6, rSHR ++ sld rWORD6_SHIFT, rWORD6, rSHL ++ bne cr7, L(duLcr7) ++ or rWORD6, r0, rWORD4_SHIFT ++ cmpld cr6, rWORD5, rWORD6 + b L(duLoop3) + .align 4 + /* At this point we exit early with the first double word compare + complete and remainder of 0 to 7 bytes. See L(du14) for details on + how we handle the remaining bytes. */ + L(duP1x): +- cmpld cr5,rWORD7,rWORD8 +- sldi. rN,rN,3 +- bne cr5,L(duLcr5) +- cmpld cr7,rN,rSHR ++ cmpld cr5, rWORD7, rWORD8 ++ sldi. rN, rN, 3 ++ bne cr5, L(duLcr5) ++ cmpld cr7, rN, rSHR + beq L(duZeroReturn) +- li rA,0 +- ble cr7,L(dutrim) +- ld rWORD2,8(rSTR2) +- srd rA,rWORD2,rSHR ++ li r0, 0 ++ ble cr7, L(dutrim) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD2, 8(rSTR2) ++#endif ++ srd r0, rWORD2, rSHR + b L(dutrim) + /* Remainder is 16 */ + .align 4 + L(duP2): +- srd rE,rWORD8,rSHR +- ld rWORD5,0(rSTR1) +- or rWORD6,rE,rH +- sld rH,rWORD8,rSHL ++ srd r0, rWORD8, rSHR ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD5, 0, rSTR1 ++ addi rSTR1, rSTR1, 8 ++#else ++ ld rWORD5, 0(rSTR1) ++#endif ++ or rWORD6, r0, rWORD6_SHIFT ++ sld rWORD6_SHIFT, rWORD8, rSHL + L(duP2e): +- ld rWORD7,8(rSTR1) +- ld rWORD8,8(rSTR2) +- cmpld cr6,rWORD5,rWORD6 +- srd rG,rWORD8,rSHR +- sld rB,rWORD8,rSHL +- or rWORD8,rG,rH +- blt cr7,L(duP2x) +- ld rWORD1,16(rSTR1) +- ld rWORD2,16(rSTR2) +- cmpld cr5,rWORD7,rWORD8 +- bne cr6,L(duLcr6) +- srd rA,rWORD2,rSHR +- sld rD,rWORD2,rSHL +- or rWORD2,rA,rB +- ld rWORD3,24(rSTR1) +- ld rWORD4,24(rSTR2) +- cmpld cr0,rWORD1,rWORD2 +- bne cr5,L(duLcr5) +- srd rC,rWORD4,rSHR +- sld rF,rWORD4,rSHL +- or rWORD4,rC,rD +- addi rSTR1,rSTR1,8 +- addi rSTR2,rSTR2,8 +- cmpld cr1,rWORD3,rWORD4 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD7, 0, rSTR1 ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD7, 8(rSTR1) ++ ld rWORD8, 8(rSTR2) ++#endif ++ cmpld cr6, rWORD5, rWORD6 ++ srd r12, rWORD8, rSHR ++ sld rWORD8_SHIFT, rWORD8, rSHL ++ or rWORD8, r12, rWORD6_SHIFT ++ blt cr7, L(duP2x) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD1, 16(rSTR1) ++ ld rWORD2, 16(rSTR2) ++#endif ++ cmpld cr5, rWORD7, rWORD8 ++ bne cr6, L(duLcr6) ++ srd r0, rWORD2, rSHR ++ sld rWORD2_SHIFT, rWORD2, rSHL ++ or rWORD2, r0, rWORD8_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD3, 0, rSTR1 ++ ldbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD3, 24(rSTR1) ++ ld rWORD4, 24(rSTR2) ++#endif ++ cmpld cr7, rWORD1, rWORD2 ++ bne cr5, L(duLcr5) ++ srd r12, rWORD4, rSHR ++ sld rWORD4_SHIFT, rWORD4, rSHL ++ or rWORD4, r12, rWORD2_SHIFT ++#ifndef __LITTLE_ENDIAN__ ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#endif ++ cmpld cr1, rWORD3, rWORD4 + b L(duLoop2) + .align 4 + L(duP2x): +- cmpld cr5,rWORD7,rWORD8 +- addi rSTR1,rSTR1,8 +- addi rSTR2,rSTR2,8 +- bne cr6,L(duLcr6) +- sldi. rN,rN,3 +- bne cr5,L(duLcr5) +- cmpld cr7,rN,rSHR ++ cmpld cr5, rWORD7, rWORD8 ++#ifndef __LITTLE_ENDIAN__ ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#endif ++ bne cr6, L(duLcr6) ++ sldi. rN, rN, 3 ++ bne cr5, L(duLcr5) ++ cmpld cr7, rN, rSHR + beq L(duZeroReturn) +- li rA,0 +- ble cr7,L(dutrim) +- ld rWORD2,8(rSTR2) +- srd rA,rWORD2,rSHR ++ li r0, 0 ++ ble cr7, L(dutrim) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD2, 8(rSTR2) ++#endif ++ srd r0, rWORD2, rSHR + b L(dutrim) + + /* Remainder is 24 */ + .align 4 + L(duP3): +- srd rC,rWORD8,rSHR +- ld rWORD3,0(rSTR1) +- sld rF,rWORD8,rSHL +- or rWORD4,rC,rH ++ srd r12, rWORD8, rSHR ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD3, 0, rSTR1 ++ addi rSTR1, rSTR1, 8 ++#else ++ ld rWORD3, 0(rSTR1) ++#endif ++ sld rWORD4_SHIFT, rWORD8, rSHL ++ or rWORD4, r12, rWORD6_SHIFT + L(duP3e): +- ld rWORD5,8(rSTR1) +- ld rWORD6,8(rSTR2) +- cmpld cr1,rWORD3,rWORD4 +- srd rE,rWORD6,rSHR +- sld rH,rWORD6,rSHL +- or rWORD6,rE,rF +- ld rWORD7,16(rSTR1) +- ld rWORD8,16(rSTR2) +- cmpld cr6,rWORD5,rWORD6 +- bne cr1,L(duLcr1) +- srd rG,rWORD8,rSHR +- sld rB,rWORD8,rSHL +- or rWORD8,rG,rH +- blt cr7,L(duP3x) +- ld rWORD1,24(rSTR1) +- ld rWORD2,24(rSTR2) +- cmpld cr5,rWORD7,rWORD8 +- bne cr6,L(duLcr6) +- srd rA,rWORD2,rSHR +- sld rD,rWORD2,rSHL +- or rWORD2,rA,rB +- addi rSTR1,rSTR1,16 +- addi rSTR2,rSTR2,16 +- cmpld cr0,rWORD1,rWORD2 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD5, 0, rSTR1 ++ ldbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD5, 8(rSTR1) ++ ld rWORD6, 8(rSTR2) ++#endif ++ cmpld cr1, rWORD3, rWORD4 ++ srd r0, rWORD6, rSHR ++ sld rWORD6_SHIFT, rWORD6, rSHL ++ or rWORD6, r0, rWORD4_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD7, 0, rSTR1 ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD7, 16(rSTR1) ++ ld rWORD8, 16(rSTR2) ++#endif ++ cmpld cr6, rWORD5, rWORD6 ++ bne cr1, L(duLcr1) ++ srd r12, rWORD8, rSHR ++ sld rWORD8_SHIFT, rWORD8, rSHL ++ or rWORD8, r12, rWORD6_SHIFT ++ blt cr7, L(duP3x) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD1, 24(rSTR1) ++ ld rWORD2, 24(rSTR2) ++#endif ++ cmpld cr5, rWORD7, rWORD8 ++ bne cr6, L(duLcr6) ++ srd r0, rWORD2, rSHR ++ sld rWORD2_SHIFT, rWORD2, rSHL ++ or rWORD2, r0, rWORD8_SHIFT ++#ifndef __LITTLE_ENDIAN__ ++ addi rSTR1, rSTR1, 16 ++ addi rSTR2, rSTR2, 16 ++#endif ++ cmpld cr7, rWORD1, rWORD2 + b L(duLoop1) + .align 4 + L(duP3x): +- addi rSTR1,rSTR1,16 +- addi rSTR2,rSTR2,16 +- bne cr1,L(duLcr1) +- cmpld cr5,rWORD7,rWORD8 +- bne cr6,L(duLcr6) +- sldi. rN,rN,3 +- bne cr5,L(duLcr5) +- cmpld cr7,rN,rSHR ++#ifndef __LITTLE_ENDIAN__ ++ addi rSTR1, rSTR1, 16 ++ addi rSTR2, rSTR2, 16 ++#endif ++#if 0 ++/* Huh? We've already branched on cr1! */ ++ bne cr1, L(duLcr1) ++#endif ++ cmpld cr5, rWORD7, rWORD8 ++ bne cr6, L(duLcr6) ++ sldi. rN, rN, 3 ++ bne cr5, L(duLcr5) ++ cmpld cr7, rN, rSHR + beq L(duZeroReturn) +- li rA,0 +- ble cr7,L(dutrim) +- ld rWORD2,8(rSTR2) +- srd rA,rWORD2,rSHR ++ li r0, 0 ++ ble cr7, L(dutrim) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD2, 8(rSTR2) ++#endif ++ srd r0, rWORD2, rSHR + b L(dutrim) + + /* Count is a multiple of 32, remainder is 0 */ + .align 4 + L(duP4): +- mtctr rTMP +- srd rA,rWORD8,rSHR +- ld rWORD1,0(rSTR1) +- sld rD,rWORD8,rSHL +- or rWORD2,rA,rH ++ mtctr r0 ++ srd r0, rWORD8, rSHR ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ addi rSTR1, rSTR1, 8 ++#else ++ ld rWORD1, 0(rSTR1) ++#endif ++ sld rWORD2_SHIFT, rWORD8, rSHL ++ or rWORD2, r0, rWORD6_SHIFT + L(duP4e): +- ld rWORD3,8(rSTR1) +- ld rWORD4,8(rSTR2) +- cmpld cr0,rWORD1,rWORD2 +- srd rC,rWORD4,rSHR +- sld rF,rWORD4,rSHL +- or rWORD4,rC,rD +- ld rWORD5,16(rSTR1) +- ld rWORD6,16(rSTR2) +- cmpld cr1,rWORD3,rWORD4 +- bne cr0,L(duLcr0) +- srd rE,rWORD6,rSHR +- sld rH,rWORD6,rSHL +- or rWORD6,rE,rF +- ldu rWORD7,24(rSTR1) +- ldu rWORD8,24(rSTR2) +- cmpld cr6,rWORD5,rWORD6 +- bne cr1,L(duLcr1) +- srd rG,rWORD8,rSHR +- sld rB,rWORD8,rSHL +- or rWORD8,rG,rH +- cmpld cr5,rWORD7,rWORD8 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD3, 0, rSTR1 ++ ldbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD3, 8(rSTR1) ++ ld rWORD4, 8(rSTR2) ++#endif ++ cmpld cr7, rWORD1, rWORD2 ++ srd r12, rWORD4, rSHR ++ sld rWORD4_SHIFT, rWORD4, rSHL ++ or rWORD4, r12, rWORD2_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD5, 0, rSTR1 ++ ldbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD5, 16(rSTR1) ++ ld rWORD6, 16(rSTR2) ++#endif ++ cmpld cr1, rWORD3, rWORD4 ++ bne cr7, L(duLcr7) ++ srd r0, rWORD6, rSHR ++ sld rWORD6_SHIFT, rWORD6, rSHL ++ or rWORD6, r0, rWORD4_SHIFT ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD7, 0, rSTR1 ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ldu rWORD7, 24(rSTR1) ++ ldu rWORD8, 24(rSTR2) ++#endif ++ cmpld cr6, rWORD5, rWORD6 ++ bne cr1, L(duLcr1) ++ srd r12, rWORD8, rSHR ++ sld rWORD8_SHIFT, rWORD8, rSHL ++ or rWORD8, r12, rWORD6_SHIFT ++ cmpld cr5, rWORD7, rWORD8 + bdz L(du24) /* Adjust CTR as we start with +4 */ + /* This is the primary loop */ + .align 4 + L(duLoop): +- ld rWORD1,8(rSTR1) +- ld rWORD2,8(rSTR2) +- cmpld cr1,rWORD3,rWORD4 +- bne cr6,L(duLcr6) +- srd rA,rWORD2,rSHR +- sld rD,rWORD2,rSHL +- or rWORD2,rA,rB ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD1, 8(rSTR1) ++ ld rWORD2, 8(rSTR2) ++#endif ++ cmpld cr1, rWORD3, rWORD4 ++ bne cr6, L(duLcr6) ++ srd r0, rWORD2, rSHR ++ sld rWORD2_SHIFT, rWORD2, rSHL ++ or rWORD2, r0, rWORD8_SHIFT + L(duLoop1): +- ld rWORD3,16(rSTR1) +- ld rWORD4,16(rSTR2) +- cmpld cr6,rWORD5,rWORD6 +- bne cr5,L(duLcr5) +- srd rC,rWORD4,rSHR +- sld rF,rWORD4,rSHL +- or rWORD4,rC,rD ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD3, 0, rSTR1 ++ ldbrx rWORD4, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD3, 16(rSTR1) ++ ld rWORD4, 16(rSTR2) ++#endif ++ cmpld cr6, rWORD5, rWORD6 ++ bne cr5, L(duLcr5) ++ srd r12, rWORD4, rSHR ++ sld rWORD4_SHIFT, rWORD4, rSHL ++ or rWORD4, r12, rWORD2_SHIFT + L(duLoop2): +- ld rWORD5,24(rSTR1) +- ld rWORD6,24(rSTR2) +- cmpld cr5,rWORD7,rWORD8 +- bne cr0,L(duLcr0) +- srd rE,rWORD6,rSHR +- sld rH,rWORD6,rSHL +- or rWORD6,rE,rF ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD5, 0, rSTR1 ++ ldbrx rWORD6, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD5, 24(rSTR1) ++ ld rWORD6, 24(rSTR2) ++#endif ++ cmpld cr5, rWORD7, rWORD8 ++ bne cr7, L(duLcr7) ++ srd r0, rWORD6, rSHR ++ sld rWORD6_SHIFT, rWORD6, rSHL ++ or rWORD6, r0, rWORD4_SHIFT + L(duLoop3): +- ldu rWORD7,32(rSTR1) +- ldu rWORD8,32(rSTR2) +- cmpld cr0,rWORD1,rWORD2 +- bne- cr1,L(duLcr1) +- srd rG,rWORD8,rSHR +- sld rB,rWORD8,rSHL +- or rWORD8,rG,rH ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD7, 0, rSTR1 ++ ldbrx rWORD8, 0, rSTR2 ++ addi rSTR1, rSTR1, 8 ++ addi rSTR2, rSTR2, 8 ++#else ++ ldu rWORD7, 32(rSTR1) ++ ldu rWORD8, 32(rSTR2) ++#endif ++ cmpld cr7, rWORD1, rWORD2 ++ bne cr1, L(duLcr1) ++ srd r12, rWORD8, rSHR ++ sld rWORD8_SHIFT, rWORD8, rSHL ++ or rWORD8, r12, rWORD6_SHIFT + bdnz L(duLoop) + + L(duL4): +- bne cr1,L(duLcr1) +- cmpld cr1,rWORD3,rWORD4 +- bne cr6,L(duLcr6) +- cmpld cr6,rWORD5,rWORD6 +- bne cr5,L(duLcr5) +- cmpld cr5,rWORD7,rWORD8 ++#if 0 ++/* Huh? We've already branched on cr1! */ ++ bne cr1, L(duLcr1) ++#endif ++ cmpld cr1, rWORD3, rWORD4 ++ bne cr6, L(duLcr6) ++ cmpld cr6, rWORD5, rWORD6 ++ bne cr5, L(duLcr5) ++ cmpld cr5, rWORD7, rWORD8 + L(du44): +- bne cr0,L(duLcr0) ++ bne cr7, L(duLcr7) + L(du34): +- bne cr1,L(duLcr1) ++ bne cr1, L(duLcr1) + L(du24): +- bne cr6,L(duLcr6) ++ bne cr6, L(duLcr6) + L(du14): +- sldi. rN,rN,3 +- bne cr5,L(duLcr5) ++ sldi. rN, rN, 3 ++ bne cr5, L(duLcr5) + /* At this point we have a remainder of 1 to 7 bytes to compare. We use +- shift right double to elliminate bits beyond the compare length. +- This allows the use of double word subtract to compute the final +- result. ++ shift right double to eliminate bits beyond the compare length. + + However it may not be safe to load rWORD2 which may be beyond the + string length. So we compare the bit length of the remainder to + the right shift count (rSHR). If the bit count is less than or equal + we do not need to load rWORD2 (all significant bits are already in +- rB). */ +- cmpld cr7,rN,rSHR ++ rWORD8_SHIFT). */ ++ cmpld cr7, rN, rSHR + beq L(duZeroReturn) +- li rA,0 +- ble cr7,L(dutrim) +- ld rWORD2,8(rSTR2) +- srd rA,rWORD2,rSHR ++ li r0, 0 ++ ble cr7, L(dutrim) ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD2, 0, rSTR2 ++ addi rSTR2, rSTR2, 8 ++#else ++ ld rWORD2, 8(rSTR2) ++#endif ++ srd r0, rWORD2, rSHR + .align 4 + L(dutrim): +- ld rWORD1,8(rSTR1) +- ld rWORD8,-8(r1) +- subfic rN,rN,64 /* Shift count is 64 - (rN * 8). */ +- or rWORD2,rA,rB +- ld rWORD7,-16(r1) +- ld r29,-24(r1) +- srd rWORD1,rWORD1,rN +- srd rWORD2,rWORD2,rN +- ld r28,-32(r1) +- ld r27,-40(r1) +- li rRTN,0 +- cmpld cr0,rWORD1,rWORD2 +- ld r26,-48(r1) +- ld r25,-56(r1) +- beq cr0,L(dureturn24) +- li rRTN,1 +- ld r24,-64(r1) +- bgtlr cr0 +- li rRTN,-1 +- blr +- .align 4 +-L(duLcr0): +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) +- li rRTN,1 +- bgt cr0,L(dureturn29) +- ld r29,-24(r1) +- ld r28,-32(r1) +- li rRTN,-1 ++#ifdef __LITTLE_ENDIAN__ ++ ldbrx rWORD1, 0, rSTR1 ++#else ++ ld rWORD1, 8(rSTR1) ++#endif ++ ld rWORD8, -8(r1) ++ subfic rN, rN, 64 /* Shift count is 64 - (rN * 8). */ ++ or rWORD2, r0, rWORD8_SHIFT ++ ld rWORD7, -16(r1) ++ ld rSHL, -24(r1) ++ srd rWORD1, rWORD1, rN ++ srd rWORD2, rWORD2, rN ++ ld rSHR, -32(r1) ++ ld rWORD8_SHIFT, -40(r1) ++ li rRTN, 0 ++ cmpld cr7, rWORD1, rWORD2 ++ ld rWORD2_SHIFT, -48(r1) ++ ld rWORD4_SHIFT, -56(r1) ++ beq cr7, L(dureturn24) ++ li rRTN, 1 ++ ld rWORD6_SHIFT, -64(r1) ++ bgtlr cr7 ++ li rRTN, -1 ++ blr ++ .align 4 ++L(duLcr7): ++ ld rWORD8, -8(r1) ++ ld rWORD7, -16(r1) ++ li rRTN, 1 ++ bgt cr7, L(dureturn29) ++ ld rSHL, -24(r1) ++ ld rSHR, -32(r1) ++ li rRTN, -1 + b L(dureturn27) + .align 4 + L(duLcr1): +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) +- li rRTN,1 +- bgt cr1,L(dureturn29) +- ld r29,-24(r1) +- ld r28,-32(r1) +- li rRTN,-1 ++ ld rWORD8, -8(r1) ++ ld rWORD7, -16(r1) ++ li rRTN, 1 ++ bgt cr1, L(dureturn29) ++ ld rSHL, -24(r1) ++ ld rSHR, -32(r1) ++ li rRTN, -1 + b L(dureturn27) + .align 4 + L(duLcr6): +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) +- li rRTN,1 +- bgt cr6,L(dureturn29) +- ld r29,-24(r1) +- ld r28,-32(r1) +- li rRTN,-1 ++ ld rWORD8, -8(r1) ++ ld rWORD7, -16(r1) ++ li rRTN, 1 ++ bgt cr6, L(dureturn29) ++ ld rSHL, -24(r1) ++ ld rSHR, -32(r1) ++ li rRTN, -1 + b L(dureturn27) + .align 4 + L(duLcr5): +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) +- li rRTN,1 +- bgt cr5,L(dureturn29) +- ld r29,-24(r1) +- ld r28,-32(r1) +- li rRTN,-1 ++ ld rWORD8, -8(r1) ++ ld rWORD7, -16(r1) ++ li rRTN, 1 ++ bgt cr5, L(dureturn29) ++ ld rSHL, -24(r1) ++ ld rSHR, -32(r1) ++ li rRTN, -1 + b L(dureturn27) + .align 3 + L(duZeroReturn): +- li rRTN,0 ++ li rRTN, 0 + .align 4 + L(dureturn): +- ld rWORD8,-8(r1) +- ld rWORD7,-16(r1) ++ ld rWORD8, -8(r1) ++ ld rWORD7, -16(r1) + L(dureturn29): +- ld r29,-24(r1) +- ld r28,-32(r1) ++ ld rSHL, -24(r1) ++ ld rSHR, -32(r1) + L(dureturn27): +- ld r27,-40(r1) ++ ld rWORD8_SHIFT, -40(r1) + L(dureturn26): +- ld r26,-48(r1) ++ ld rWORD2_SHIFT, -48(r1) + L(dureturn25): +- ld r25,-56(r1) ++ ld rWORD4_SHIFT, -56(r1) + L(dureturn24): +- ld r24,-64(r1) ++ ld rWORD6_SHIFT, -64(r1) + blr + L(duzeroLength): +- li rRTN,0 ++ li rRTN, 0 + blr + +-END (BP_SYM (memcmp)) ++END (memcmp) + libc_hidden_builtin_def (memcmp) +-weak_alias (memcmp,bcmp) ++weak_alias (memcmp, bcmp) diff --git a/SOURCES/glibc-ppc64le-31.patch b/SOURCES/glibc-ppc64le-31.patch new file mode 100644 index 0000000..de90661 --- /dev/null +++ b/SOURCES/glibc-ppc64le-31.patch @@ -0,0 +1,2943 @@ +# commit 759cfef3ac4c07dba1ece0bbc1207e099348816d +# Author: Alan Modra +# Date: Sat Aug 17 18:47:22 2013 +0930 +# +# PowerPC LE memcpy +# http://sourceware.org/ml/libc-alpha/2013-08/msg00103.html +# +# LIttle-endian support for memcpy. I spent some time cleaning up the +# 64-bit power7 memcpy, in order to avoid the extra alignment traps +# power7 takes for little-endian. It probably would have been better +# to copy the linux kernel version of memcpy. +# +# * sysdeps/powerpc/powerpc32/power4/memcpy.S: Add little endian support. +# * sysdeps/powerpc/powerpc32/power6/memcpy.S: Likewise. +# * sysdeps/powerpc/powerpc32/power7/memcpy.S: Likewise. +# * sysdeps/powerpc/powerpc32/power7/mempcpy.S: Likewise. +# * sysdeps/powerpc/powerpc64/memcpy.S: Likewise. +# * sysdeps/powerpc/powerpc64/power4/memcpy.S: Likewise. +# * sysdeps/powerpc/powerpc64/power6/memcpy.S: Likewise. +# * sysdeps/powerpc/powerpc64/power7/memcpy.S: Likewise. +# * sysdeps/powerpc/powerpc64/power7/mempcpy.S: Likewise. Make better +# use of regs. Use power7 mtocrf. Tidy function tails. +# +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/memcpy.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/memcpy.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/memcpy.S 2014-05-29 13:04:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/memcpy.S 2014-05-29 13:04:56.000000000 -0500 +@@ -205,15 +205,28 @@ + blt cr6,5f + srwi 7,6,16 + bgt cr6,3f ++#ifdef __LITTLE_ENDIAN__ ++ sth 7,0(3) ++#else + sth 6,0(3) ++#endif + b 7f + .align 4 + 3: ++#ifdef __LITTLE_ENDIAN__ ++ rotlwi 6,6,24 ++ stb 6,0(3) ++ sth 7,1(3) ++#else + stb 7,0(3) + sth 6,1(3) ++#endif + b 7f + .align 4 + 5: ++#ifdef __LITTLE_ENDIAN__ ++ rotlwi 6,6,8 ++#endif + stb 6,0(3) + 7: + cmplwi cr1,10,16 +@@ -341,13 +354,23 @@ + bf 30,1f + + /* there are at least two words to copy, so copy them */ ++#ifdef __LITTLE_ENDIAN__ ++ srw 0,6,10 ++ slw 8,7,9 ++#else + slw 0,6,10 /* shift 1st src word to left align it in R0 */ + srw 8,7,9 /* shift 2nd src word to right align it in R8 */ ++#endif + or 0,0,8 /* or them to get word to store */ + lwz 6,8(5) /* load the 3rd src word */ + stw 0,0(4) /* store the 1st dst word */ ++#ifdef __LITTLE_ENDIAN__ ++ srw 0,7,10 ++ slw 8,6,9 ++#else + slw 0,7,10 /* now left align 2nd src word into R0 */ + srw 8,6,9 /* shift 3rd src word to right align it in R8 */ ++#endif + or 0,0,8 /* or them to get word to store */ + lwz 7,12(5) + stw 0,4(4) /* store the 2nd dst word */ +@@ -355,8 +378,13 @@ + addi 5,5,16 + bf 31,4f + /* there is a third word to copy, so copy it */ ++#ifdef __LITTLE_ENDIAN__ ++ srw 0,6,10 ++ slw 8,7,9 ++#else + slw 0,6,10 /* shift 3rd src word to left align it in R0 */ + srw 8,7,9 /* shift 4th src word to right align it in R8 */ ++#endif + or 0,0,8 /* or them to get word to store */ + stw 0,0(4) /* store 3rd dst word */ + mr 6,7 +@@ -366,8 +394,13 @@ + b 4f + .align 4 + 1: ++#ifdef __LITTLE_ENDIAN__ ++ srw 0,6,10 ++ slw 8,7,9 ++#else + slw 0,6,10 /* shift 1st src word to left align it in R0 */ + srw 8,7,9 /* shift 2nd src word to right align it in R8 */ ++#endif + addi 5,5,8 + or 0,0,8 /* or them to get word to store */ + bf 31,4f +@@ -380,23 +413,43 @@ + .align 4 + 4: + /* copy 16 bytes at a time */ ++#ifdef __LITTLE_ENDIAN__ ++ srw 0,6,10 ++ slw 8,7,9 ++#else + slw 0,6,10 + srw 8,7,9 ++#endif + or 0,0,8 + lwz 6,0(5) + stw 0,0(4) ++#ifdef __LITTLE_ENDIAN__ ++ srw 0,7,10 ++ slw 8,6,9 ++#else + slw 0,7,10 + srw 8,6,9 ++#endif + or 0,0,8 + lwz 7,4(5) + stw 0,4(4) ++#ifdef __LITTLE_ENDIAN__ ++ srw 0,6,10 ++ slw 8,7,9 ++#else + slw 0,6,10 + srw 8,7,9 ++#endif + or 0,0,8 + lwz 6,8(5) + stw 0,8(4) ++#ifdef __LITTLE_ENDIAN__ ++ srw 0,7,10 ++ slw 8,6,9 ++#else + slw 0,7,10 + srw 8,6,9 ++#endif + or 0,0,8 + lwz 7,12(5) + stw 0,12(4) +@@ -405,8 +458,13 @@ + bdnz+ 4b + 8: + /* calculate and store the final word */ ++#ifdef __LITTLE_ENDIAN__ ++ srw 0,6,10 ++ slw 8,7,9 ++#else + slw 0,6,10 + srw 8,7,9 ++#endif + or 0,0,8 + stw 0,0(4) + 3: +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/memcpy.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/memcpy.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/memcpy.S 2014-05-29 13:04:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/memcpy.S 2014-05-29 13:04:56.000000000 -0500 +@@ -221,15 +221,28 @@ + blt cr6,5f + srwi 7,6,16 + bgt cr6,3f ++#ifdef __LITTLE_ENDIAN__ ++ sth 7,0(3) ++#else + sth 6,0(3) ++#endif + b 7f + .align 4 + 3: ++#ifdef __LITTLE_ENDIAN__ ++ rotlwi 6,6,24 ++ stb 6,0(3) ++ sth 7,1(3) ++#else + stb 7,0(3) + sth 6,1(3) ++#endif + b 7f + .align 4 + 5: ++#ifdef __LITTLE_ENDIAN__ ++ rotlwi 6,6,8 ++#endif + stb 6,0(3) + 7: + cmplwi cr1,10,16 +@@ -579,7 +592,11 @@ + lwz 6,-1(4) + cmplwi cr6,31,4 + srwi 8,31,5 /* calculate the 32 byte loop count */ ++#ifdef __LITTLE_ENDIAN__ ++ srwi 6,6,8 ++#else + slwi 6,6,8 ++#endif + clrlwi 31,31,27 /* The remaining bytes, < 32. */ + blt cr5,L(wdu1_32tail) + mtctr 8 +@@ -587,8 +604,12 @@ + + lwz 8,3(4) + lwz 7,4(4) ++#ifdef __LITTLE_ENDIAN__ ++ rldimi 6,8,24,32 ++#else + /* Equivalent to: srwi 8,8,32-8; or 6,6,8 */ + rlwimi 6,8,8,(32-8),31 ++#endif + b L(wdu1_loop32x) + .align 4 + L(wdu1_loop32): +@@ -597,8 +618,12 @@ + lwz 7,4(4) + stw 10,-8(3) + stw 11,-4(3) ++#ifdef __LITTLE_ENDIAN__ ++ rldimi 6,8,24,32 ++#else + /* Equivalent to srwi 8,8,32-8; or 6,6,8 */ + rlwimi 6,8,8,(32-8),31 ++#endif + L(wdu1_loop32x): + lwz 10,8(4) + lwz 11,12(4) +@@ -615,7 +640,11 @@ + stw 6,16(3) + stw 7,20(3) + addi 3,3,32 ++#ifdef __LITTLE_ENDIAN__ ++ srwi 6,8,8 ++#else + slwi 6,8,8 ++#endif + bdnz+ L(wdu1_loop32) + stw 10,-8(3) + stw 11,-4(3) +@@ -626,8 +655,12 @@ + blt cr6,L(wdu_4tail) + /* calculate and store the final word */ + lwz 8,3(4) +-/* Equivalent to: srwi 8,8,32-9; or 6,6,8 */ ++#ifdef __LITTLE_ENDIAN__ ++ rldimi 6,8,24,32 ++#else ++/* Equivalent to: srwi 8,8,32-8; or 6,6,8 */ + rlwimi 6,8,8,(32-8),31 ++#endif + b L(wdu_32tailx) + + L(wdu2_32): +@@ -635,7 +668,11 @@ + lwz 6,-2(4) + cmplwi cr6,31,4 + srwi 8,31,5 /* calculate the 32 byte loop count */ ++#ifdef __LITTLE_ENDIAN__ ++ srwi 6,6,16 ++#else + slwi 6,6,16 ++#endif + clrlwi 31,31,27 /* The remaining bytes, < 32. */ + blt cr5,L(wdu2_32tail) + mtctr 8 +@@ -643,8 +680,11 @@ + + lwz 8,2(4) + lwz 7,4(4) +-/* Equivalent to: srwi 8,8,32-8; or 6,6,8 */ ++#ifdef __LITTLE_ENDIAN__ ++ rldimi 6,8,16,32 ++#else + rlwimi 6,8,16,(32-16),31 ++#endif + b L(wdu2_loop32x) + .align 4 + L(wdu2_loop32): +@@ -653,8 +693,11 @@ + lwz 7,4(4) + stw 10,-8(3) + stw 11,-4(3) +-/* Equivalent to srwi 8,8,32-8; or 6,6,8 */ ++#ifdef __LITTLE_ENDIAN__ ++ rldimi 6,8,16,32 ++#else + rlwimi 6,8,16,(32-16),31 ++#endif + L(wdu2_loop32x): + lwz 10,8(4) + lwz 11,12(4) +@@ -672,7 +715,11 @@ + stw 6,16(3) + stw 7,20(3) + addi 3,3,32 ++#ifdef __LITTLE_ENDIAN__ ++ srwi 6,8,16 ++#else + slwi 6,8,16 ++#endif + bdnz+ L(wdu2_loop32) + stw 10,-8(3) + stw 11,-4(3) +@@ -683,8 +730,11 @@ + blt cr6,L(wdu_4tail) + /* calculate and store the final word */ + lwz 8,2(4) +-/* Equivalent to: srwi 8,8,32-9; or 6,6,8 */ ++#ifdef __LITTLE_ENDIAN__ ++ rldimi 6,8,16,32 ++#else + rlwimi 6,8,16,(32-16),31 ++#endif + b L(wdu_32tailx) + + L(wdu3_32): +@@ -692,7 +742,11 @@ + lwz 6,-3(4) + cmplwi cr6,31,4 + srwi 8,31,5 /* calculate the 32 byte loop count */ ++#ifdef __LITTLE_ENDIAN__ ++ srwi 6,6,24 ++#else + slwi 6,6,24 ++#endif + clrlwi 31,31,27 /* The remaining bytes, < 32. */ + blt cr5,L(wdu3_32tail) + mtctr 8 +@@ -700,8 +754,11 @@ + + lwz 8,1(4) + lwz 7,4(4) +-/* Equivalent to: srwi 8,8,32-8; or 6,6,8 */ ++#ifdef __LITTLE_ENDIAN__ ++ rldimi 6,8,8,32 ++#else + rlwimi 6,8,24,(32-24),31 ++#endif + b L(wdu3_loop32x) + .align 4 + L(wdu3_loop32): +@@ -710,8 +767,11 @@ + lwz 7,4(4) + stw 10,-8(3) + stw 11,-4(3) +-/* Equivalent to srwi 8,8,32-8; or 6,6,8 */ ++#ifdef __LITTLE_ENDIAN__ ++ rldimi 6,8,8,32 ++#else + rlwimi 6,8,24,(32-24),31 ++#endif + L(wdu3_loop32x): + lwz 10,8(4) + lwz 11,12(4) +@@ -728,7 +788,11 @@ + stw 6,16(3) + stw 7,20(3) + addi 3,3,32 ++#ifdef __LITTLE_ENDIAN__ ++ srwi 6,8,24 ++#else + slwi 6,8,24 ++#endif + bdnz+ L(wdu3_loop32) + stw 10,-8(3) + stw 11,-4(3) +@@ -739,8 +803,11 @@ + blt cr6,L(wdu_4tail) + /* calculate and store the final word */ + lwz 8,1(4) +-/* Equivalent to: srwi 8,8,32-9; or 6,6,8 */ ++#ifdef __LITTLE_ENDIAN__ ++ rldimi 6,8,8,32 ++#else + rlwimi 6,8,24,(32-24),31 ++#endif + b L(wdu_32tailx) + .align 4 + L(wdu_32tailx): +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memcpy.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memcpy.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memcpy.S 2014-05-29 13:04:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memcpy.S 2014-05-29 13:04:56.000000000 -0500 +@@ -385,7 +385,7 @@ + + beq L(copy_GE_32_unaligned_cont) + +- /* SRC is not quadword aligned, get it aligned. */ ++ /* DST is not quadword aligned, get it aligned. */ + + mtcrf 0x01,0 + subf 31,0,5 +@@ -437,13 +437,21 @@ + mr 11,12 + mtcrf 0x01,9 + cmplwi cr6,9,1 ++#ifdef __LITTLE_ENDIAN__ ++ lvsr 5,0,12 ++#else + lvsl 5,0,12 ++#endif + lvx 3,0,12 + bf 31,L(setup_unaligned_loop) + + /* Copy another 16 bytes to align to 32-bytes due to the loop . */ + lvx 4,12,6 ++#ifdef __LITTLE_ENDIAN__ ++ vperm 6,4,3,5 ++#else + vperm 6,3,4,5 ++#endif + addi 11,12,16 + addi 10,3,16 + stvx 6,0,3 +@@ -463,11 +471,17 @@ + vector instructions though. */ + + lvx 4,11,6 /* vr4 = r11+16. */ +- vperm 6,3,4,5 /* Merge the correctly-aligned portions +- of vr3/vr4 into vr6. */ ++#ifdef __LITTLE_ENDIAN__ ++ vperm 6,4,3,5 ++#else ++ vperm 6,3,4,5 ++#endif + lvx 3,11,7 /* vr3 = r11+32. */ +- vperm 10,4,3,5 /* Merge the correctly-aligned portions +- of vr3/vr4 into vr10. */ ++#ifdef __LITTLE_ENDIAN__ ++ vperm 10,3,4,5 ++#else ++ vperm 10,4,3,5 ++#endif + addi 11,11,32 + stvx 6,0,10 + stvx 10,10,6 +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/mempcpy.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/mempcpy.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/mempcpy.S 2014-05-29 13:04:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/mempcpy.S 2014-05-29 13:04:56.000000000 -0500 +@@ -327,7 +327,7 @@ + + beq L(copy_GE_32_unaligned_cont) + +- /* SRC is not quadword aligned, get it aligned. */ ++ /* DST is not quadword aligned, get it aligned. */ + + mtcrf 0x01,0 + subf 31,0,5 +@@ -379,13 +379,21 @@ + mr 11,12 + mtcrf 0x01,9 + cmplwi cr6,9,1 +- lvsl 5,0,12 ++#ifdef __LITTLE_ENDIAN__ ++ lvsr 5,0,12 ++#else ++ lvsl 5,0,12 ++#endif + lvx 3,0,12 + bf 31,L(setup_unaligned_loop) + + /* Copy another 16 bytes to align to 32-bytes due to the loop . */ + lvx 4,12,6 +- vperm 6,3,4,5 ++#ifdef __LITTLE_ENDIAN__ ++ vperm 6,4,3,5 ++#else ++ vperm 6,3,4,5 ++#endif + addi 11,12,16 + addi 10,3,16 + stvx 6,0,3 +@@ -405,11 +413,17 @@ + vector instructions though. */ + + lvx 4,11,6 /* vr4 = r11+16. */ +- vperm 6,3,4,5 /* Merge the correctly-aligned portions +- of vr3/vr4 into vr6. */ ++#ifdef __LITTLE_ENDIAN__ ++ vperm 6,4,3,5 ++#else ++ vperm 6,3,4,5 ++#endif + lvx 3,11,7 /* vr3 = r11+32. */ +- vperm 10,4,3,5 /* Merge the correctly-aligned portions +- of vr3/vr4 into vr10. */ ++#ifdef __LITTLE_ENDIAN__ ++ vperm 10,3,4,5 ++#else ++ vperm 10,4,3,5 ++#endif + addi 11,11,32 + stvx 6,0,10 + stvx 10,10,6 +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/memcpy.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/memcpy.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/memcpy.S 2014-05-29 13:04:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/memcpy.S 2014-05-29 13:04:56.000000000 -0500 +@@ -214,15 +214,28 @@ + blt cr6,5f + srdi 7,6,16 + bgt cr6,3f ++#ifdef __LITTLE_ENDIAN__ ++ sth 7,0(3) ++#else + sth 6,0(3) ++#endif + b 7f + .align 4 + 3: ++#ifdef __LITTLE_ENDIAN__ ++ rotlwi 6,6,24 ++ stb 6,0(3) ++ sth 7,1(3) ++#else + stb 7,0(3) + sth 6,1(3) ++#endif + b 7f + .align 4 + 5: ++#ifdef __LITTLE_ENDIAN__ ++ rotlwi 6,6,8 ++#endif + stb 6,0(3) + 7: + cmpldi cr1,10,16 +@@ -330,7 +343,11 @@ + ld 7,8(5) + subfic 9,10,64 + beq 2f ++#ifdef __LITTLE_ENDIAN__ ++ srd 0,6,10 ++#else + sld 0,6,10 ++#endif + cmpldi 11,1 + mr 6,7 + addi 4,4,-8 +@@ -338,15 +355,25 @@ + b 1f + 2: addi 5,5,8 + .align 4 ++#ifdef __LITTLE_ENDIAN__ ++0: srd 0,6,10 ++ sld 8,7,9 ++#else + 0: sld 0,6,10 + srd 8,7,9 ++#endif + cmpldi 11,2 + ld 6,8(5) + or 0,0,8 + addi 11,11,-2 + std 0,0(4) ++#ifdef __LITTLE_ENDIAN__ ++ srd 0,7,10 ++1: sld 8,6,9 ++#else + sld 0,7,10 + 1: srd 8,6,9 ++#endif + or 0,0,8 + beq 8f + ld 7,16(5) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power4/memcpy.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power4/memcpy.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power4/memcpy.S 2014-05-29 13:04:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power4/memcpy.S 2014-05-29 13:05:51.000000000 -0500 +@@ -1,5 +1,5 @@ + /* Optimized memcpy implementation for PowerPC64. +- Copyright (C) 2003, 2006, 2011 Free Software Foundation, Inc. ++ Copyright (C) 2003-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or +@@ -17,26 +17,24 @@ + . */ + + #include +-#include +-#include + + /* __ptr_t [r3] memcpy (__ptr_t dst [r3], __ptr_t src [r4], size_t len [r5]); + Returns 'dst'. + +- Memcpy handles short copies (< 32-bytes) using a binary move blocks +- (no loops) of lwz/stw. The tail (remaining 1-3) bytes is handled +- with the appropriate combination of byte and halfword load/stores. +- There is minimal effort to optimize the alignment of short moves. ++ Memcpy handles short copies (< 32-bytes) using a binary move blocks ++ (no loops) of lwz/stw. The tail (remaining 1-3) bytes is handled ++ with the appropriate combination of byte and halfword load/stores. ++ There is minimal effort to optimize the alignment of short moves. + The 64-bit implementations of POWER3 and POWER4 do a reasonable job +- of handling unligned load/stores that do not cross 32-byte boundries. ++ of handling unaligned load/stores that do not cross 32-byte boundaries. + + Longer moves (>= 32-bytes) justify the effort to get at least the + destination doubleword (8-byte) aligned. Further optimization is +- posible when both source and destination are doubleword aligned. ++ possible when both source and destination are doubleword aligned. + Each case has a optimized unrolled loop. */ + + .machine power4 +-EALIGN (BP_SYM (memcpy), 5, 0) ++EALIGN (memcpy, 5, 0) + CALL_MCOUNT 3 + + cmpldi cr1,5,31 +@@ -44,20 +42,20 @@ + std 3,-16(1) + std 31,-8(1) + cfi_offset(31,-8) +- andi. 11,3,7 /* check alignement of dst. */ ++ andi. 11,3,7 /* check alignment of dst. */ + clrldi 0,0,61 /* Number of bytes until the 1st doubleword of dst. */ +- clrldi 10,4,61 /* check alignement of src. */ ++ clrldi 10,4,61 /* check alignment of src. */ + cmpldi cr6,5,8 + ble- cr1,.L2 /* If move < 32 bytes use short move code. */ +- cmpld cr6,10,11 ++ cmpld cr6,10,11 + mr 12,4 + srdi 9,5,3 /* Number of full double words remaining. */ + mtcrf 0x01,0 + mr 31,5 + beq .L0 +- ++ + subf 31,0,5 +- /* Move 0-7 bytes as needed to get the destination doubleword alligned. */ ++ /* Move 0-7 bytes as needed to get the destination doubleword aligned. */ + 1: bf 31,2f + lbz 6,0(12) + addi 12,12,1 +@@ -74,17 +72,17 @@ + stw 6,0(3) + addi 3,3,4 + 0: +- clrldi 10,12,61 /* check alignement of src again. */ ++ clrldi 10,12,61 /* check alignment of src again. */ + srdi 9,31,3 /* Number of full double words remaining. */ +- +- /* Copy doublewords from source to destination, assumpting the ++ ++ /* Copy doublewords from source to destination, assuming the + destination is aligned on a doubleword boundary. + + At this point we know there are at least 25 bytes left (32-7) to copy. +- The next step is to determine if the source is also doubleword aligned. ++ The next step is to determine if the source is also doubleword aligned. + If not branch to the unaligned move code at .L6. which uses + a load, shift, store strategy. +- ++ + Otherwise source and destination are doubleword aligned, and we can + the optimized doubleword copy loop. */ + .L0: +@@ -97,14 +95,14 @@ + Use a unrolled loop to copy 4 doubleword (32-bytes) per iteration. + If the copy is not an exact multiple of 32 bytes, 1-3 + doublewords are copied as needed to set up the main loop. After +- the main loop exits there may be a tail of 1-7 bytes. These byte are ++ the main loop exits there may be a tail of 1-7 bytes. These byte are + copied a word/halfword/byte at a time as needed to preserve alignment. */ + + srdi 8,31,5 + cmpldi cr1,9,4 + cmpldi cr6,11,0 + mr 11,12 +- ++ + bf 30,1f + ld 6,0(12) + ld 7,8(12) +@@ -115,7 +113,7 @@ + addi 10,3,16 + bf 31,4f + ld 0,16(12) +- std 0,16(3) ++ std 0,16(3) + blt cr1,3f + addi 11,12,24 + addi 10,3,24 +@@ -129,7 +127,7 @@ + addi 11,12,8 + std 6,0(3) + addi 10,3,8 +- ++ + .align 4 + 4: + ld 6,0(11) +@@ -144,7 +142,7 @@ + std 0,24(10) + addi 10,10,32 + bdnz 4b +-3: ++3: + + rldicr 0,31,0,60 + mtcrf 0x01,31 +@@ -152,9 +150,9 @@ + .L9: + add 3,3,0 + add 12,12,0 +- ++ + /* At this point we have a tail of 0-7 bytes and we know that the +- destiniation is double word aligned. */ ++ destination is double word aligned. */ + 4: bf 29,2f + lwz 6,0(12) + addi 12,12,4 +@@ -173,29 +171,29 @@ + ld 31,-8(1) + ld 3,-16(1) + blr +- +-/* Copy up to 31 bytes. This divided into two cases 0-8 bytes and 9-31 +- bytes. Each case is handled without loops, using binary (1,2,4,8) +- tests. +- ++ ++/* Copy up to 31 bytes. This divided into two cases 0-8 bytes and 9-31 ++ bytes. Each case is handled without loops, using binary (1,2,4,8) ++ tests. ++ + In the short (0-8 byte) case no attempt is made to force alignment +- of either source or destination. The hardware will handle the +- unaligned load/stores with small delays for crossing 32- 64-byte, and ++ of either source or destination. The hardware will handle the ++ unaligned load/stores with small delays for crossing 32- 64-byte, and + 4096-byte boundaries. Since these short moves are unlikely to be +- unaligned or cross these boundaries, the overhead to force ++ unaligned or cross these boundaries, the overhead to force + alignment is not justified. +- ++ + The longer (9-31 byte) move is more likely to cross 32- or 64-byte + boundaries. Since only loads are sensitive to the 32-/64-byte +- boundaries it is more important to align the source then the ++ boundaries it is more important to align the source then the + destination. If the source is not already word aligned, we first +- move 1-3 bytes as needed. Since we are only word aligned we don't +- use double word load/stores to insure that all loads are aligned. ++ move 1-3 bytes as needed. Since we are only word aligned we don't ++ use double word load/stores to insure that all loads are aligned. + While the destination and stores may still be unaligned, this + is only an issue for page (4096 byte boundary) crossing, which + should be rare for these short moves. The hardware handles this +- case automatically with a small delay. */ +- ++ case automatically with a small delay. */ ++ + .align 4 + .L2: + mtcrf 0x01,5 +@@ -216,15 +214,28 @@ + blt cr6,5f + srdi 7,6,16 + bgt cr6,3f ++#ifdef __LITTLE_ENDIAN__ ++ sth 7,0(3) ++#else + sth 6,0(3) ++#endif + b 7f + .align 4 + 3: ++#ifdef __LITTLE_ENDIAN__ ++ rotlwi 6,6,24 ++ stb 6,0(3) ++ sth 7,1(3) ++#else + stb 7,0(3) + sth 6,1(3) ++#endif + b 7f + .align 4 + 5: ++#ifdef __LITTLE_ENDIAN__ ++ rotlwi 6,6,8 ++#endif + stb 6,0(3) + 7: + cmpldi cr1,10,16 +@@ -258,11 +269,11 @@ + lwz 6,0(12) + addi 12,12,4 + stw 6,0(3) +- addi 3,3,4 ++ addi 3,3,4 + 2: /* Move 2-3 bytes. */ + bf 30,1f + lhz 6,0(12) +- sth 6,0(3) ++ sth 6,0(3) + bf 31,0f + lbz 7,2(12) + stb 7,2(3) +@@ -283,8 +294,8 @@ + mr 12,4 + bne cr6,4f + /* Would have liked to use use ld/std here but the 630 processors are +- slow for load/store doubles that are not at least word aligned. +- Unaligned Load/Store word execute with only a 1 cycle penaltity. */ ++ slow for load/store doubles that are not at least word aligned. ++ Unaligned Load/Store word execute with only a 1 cycle penalty. */ + lwz 6,0(4) + lwz 7,4(4) + stw 6,0(3) +@@ -299,14 +310,14 @@ + 6: + bf 30,5f + lhz 7,4(4) +- sth 7,4(3) ++ sth 7,4(3) + bf 31,0f + lbz 8,6(4) + stb 8,6(3) + ld 3,-16(1) + blr + .align 4 +-5: ++5: + bf 31,0f + lbz 6,4(4) + stb 6,4(3) +@@ -336,13 +347,23 @@ + bf 30,1f + + /* there are at least two DWs to copy */ ++#ifdef __LITTLE_ENDIAN__ ++ srd 0,6,10 ++ sld 8,7,9 ++#else + sld 0,6,10 + srd 8,7,9 ++#endif + or 0,0,8 + ld 6,16(5) + std 0,0(4) ++#ifdef __LITTLE_ENDIAN__ ++ srd 0,7,10 ++ sld 8,6,9 ++#else + sld 0,7,10 + srd 8,6,9 ++#endif + or 0,0,8 + ld 7,24(5) + std 0,8(4) +@@ -351,8 +372,13 @@ + blt cr6,8f /* if total DWs = 3, then bypass loop */ + bf 31,4f + /* there is a third DW to copy */ ++#ifdef __LITTLE_ENDIAN__ ++ srd 0,6,10 ++ sld 8,7,9 ++#else + sld 0,6,10 + srd 8,7,9 ++#endif + or 0,0,8 + std 0,0(4) + mr 6,7 +@@ -363,8 +389,13 @@ + b 4f + .align 4 + 1: ++#ifdef __LITTLE_ENDIAN__ ++ srd 0,6,10 ++ sld 8,7,9 ++#else + sld 0,6,10 + srd 8,7,9 ++#endif + addi 5,5,16 + or 0,0,8 + bf 31,4f +@@ -375,23 +406,44 @@ + addi 4,4,8 + .align 4 + /* copy 32 bytes at a time */ +-4: sld 0,6,10 ++4: ++#ifdef __LITTLE_ENDIAN__ ++ srd 0,6,10 ++ sld 8,7,9 ++#else ++ sld 0,6,10 + srd 8,7,9 ++#endif + or 0,0,8 + ld 6,0(5) + std 0,0(4) ++#ifdef __LITTLE_ENDIAN__ ++ srd 0,7,10 ++ sld 8,6,9 ++#else + sld 0,7,10 + srd 8,6,9 ++#endif + or 0,0,8 + ld 7,8(5) + std 0,8(4) ++#ifdef __LITTLE_ENDIAN__ ++ srd 0,6,10 ++ sld 8,7,9 ++#else + sld 0,6,10 + srd 8,7,9 ++#endif + or 0,0,8 + ld 6,16(5) + std 0,16(4) ++#ifdef __LITTLE_ENDIAN__ ++ srd 0,7,10 ++ sld 8,6,9 ++#else + sld 0,7,10 + srd 8,6,9 ++#endif + or 0,0,8 + ld 7,24(5) + std 0,24(4) +@@ -401,9 +453,14 @@ + .align 4 + 8: + /* calculate and store the final DW */ ++#ifdef __LITTLE_ENDIAN__ ++ srd 0,6,10 ++ sld 8,7,9 ++#else + sld 0,6,10 + srd 8,7,9 +- or 0,0,8 ++#endif ++ or 0,0,8 + std 0,0(4) + 3: + rldicr 0,31,0,60 +@@ -413,5 +470,5 @@ + ld 31,-8(1) + ld 3,-16(1) + blr +-END_GEN_TB (BP_SYM (memcpy),TB_TOCLESS) ++END_GEN_TB (memcpy,TB_TOCLESS) + libc_hidden_builtin_def (memcpy) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power6/memcpy.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power6/memcpy.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power6/memcpy.S 2014-05-29 13:04:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power6/memcpy.S 2014-05-29 13:05:27.000000000 -0500 +@@ -1,5 +1,5 @@ + /* Optimized memcpy implementation for PowerPC64. +- Copyright (C) 2003, 2006, 2007, 2011 Free Software Foundation, Inc. ++ Copyright (C) 2003-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or +@@ -17,52 +17,50 @@ + . */ + + #include +-#include +-#include + + /* __ptr_t [r3] memcpy (__ptr_t dst [r3], __ptr_t src [r4], size_t len [r5]); + Returns 'dst'. + +- Memcpy handles short copies (< 32-bytes) using a binary move blocks +- (no loops) of lwz/stw. The tail (remaining 1-3) bytes is handled +- with the appropriate combination of byte and halfword load/stores. +- There is minimal effort to optimize the alignment of short moves. ++ Memcpy handles short copies (< 32-bytes) using a binary move blocks ++ (no loops) of lwz/stw. The tail (remaining 1-3) bytes is handled ++ with the appropriate combination of byte and halfword load/stores. ++ There is minimal effort to optimize the alignment of short moves. + The 64-bit implementations of POWER3 and POWER4 do a reasonable job +- of handling unligned load/stores that do not cross 32-byte boundries. ++ of handling unaligned load/stores that do not cross 32-byte boundaries. + + Longer moves (>= 32-bytes) justify the effort to get at least the + destination doubleword (8-byte) aligned. Further optimization is +- posible when both source and destination are doubleword aligned. +- Each case has a optimized unrolled loop. +- +- For POWER6 unaligned loads will take a 20+ cycle hicup for any ++ possible when both source and destination are doubleword aligned. ++ Each case has a optimized unrolled loop. ++ ++ For POWER6 unaligned loads will take a 20+ cycle hiccup for any + L1 cache miss that crosses a 32- or 128-byte boundary. Store +- is more forgiving and does not take a hicup until page or +- segment boundaries. So we require doubleword alignment for ++ is more forgiving and does not take a hiccup until page or ++ segment boundaries. So we require doubleword alignment for + the source but may take a risk and only require word alignment + for the destination. */ + + .machine "power6" +-EALIGN (BP_SYM (memcpy), 7, 0) ++EALIGN (memcpy, 7, 0) + CALL_MCOUNT 3 + + cmpldi cr1,5,31 + neg 0,3 + std 3,-16(1) + std 31,-8(1) +- andi. 11,3,7 /* check alignement of dst. */ ++ andi. 11,3,7 /* check alignment of dst. */ + clrldi 0,0,61 /* Number of bytes until the 1st doubleword of dst. */ +- clrldi 10,4,61 /* check alignement of src. */ ++ clrldi 10,4,61 /* check alignment of src. */ + cmpldi cr6,5,8 + ble- cr1,.L2 /* If move < 32 bytes use short move code. */ + mtcrf 0x01,0 +- cmpld cr6,10,11 ++ cmpld cr6,10,11 + srdi 9,5,3 /* Number of full double words remaining. */ + beq .L0 +- ++ + subf 5,0,5 +- /* Move 0-7 bytes as needed to get the destination doubleword alligned. +- Duplicate some code to maximize fall-throught and minimize agen delays. */ ++ /* Move 0-7 bytes as needed to get the destination doubleword aligned. ++ Duplicate some code to maximize fall-through and minimize agen delays. */ + 1: bf 31,2f + lbz 6,0(4) + stb 6,0(3) +@@ -78,7 +76,7 @@ + lwz 6,1(4) + stw 6,1(3) + b 0f +- ++ + 2: bf 30,4f + lhz 6,0(4) + sth 6,0(3) +@@ -86,26 +84,26 @@ + lwz 6,2(4) + stw 6,2(3) + b 0f +- ++ + 4: bf 29,0f + lwz 6,0(4) + stw 6,0(3) +-0: ++0: + /* Add the number of bytes until the 1st doubleword of dst to src and dst. */ + add 4,4,0 + add 3,3,0 +- +- clrldi 10,4,61 /* check alignement of src again. */ ++ ++ clrldi 10,4,61 /* check alignment of src again. */ + srdi 9,5,3 /* Number of full double words remaining. */ +- +- /* Copy doublewords from source to destination, assumpting the ++ ++ /* Copy doublewords from source to destination, assuming the + destination is aligned on a doubleword boundary. + + At this point we know there are at least 25 bytes left (32-7) to copy. +- The next step is to determine if the source is also doubleword aligned. ++ The next step is to determine if the source is also doubleword aligned. + If not branch to the unaligned move code at .L6. which uses + a load, shift, store strategy. +- ++ + Otherwise source and destination are doubleword aligned, and we can + the optimized doubleword copy loop. */ + .align 4 +@@ -123,14 +121,14 @@ + the main loop exits there may be a tail of 1-7 bytes. These byte + are copied a word/halfword/byte at a time as needed to preserve + alignment. +- ++ + For POWER6 the L1 is store-through and the L2 is store-in. The + L2 is clocked at half CPU clock so we can store 16 bytes every + other cycle. POWER6 also has a load/store bypass so we can do +- load, load, store, store every 2 cycles. +- ++ load, load, store, store every 2 cycles. ++ + The following code is sensitive to cache line alignment. Do not +- make any change with out first making sure thay don't result in ++ make any change with out first making sure they don't result in + splitting ld/std pairs across a cache line. */ + + mtcrf 0x02,5 +@@ -273,7 +271,7 @@ + std 8,16+96(10) + std 0,24+96(10) + ble cr5,L(das_loop_e) +- ++ + mtctr 12 + .align 4 + L(das_loop2): +@@ -326,10 +324,10 @@ + .align 4 + L(das_tail): + beq cr1,0f +- ++ + L(das_tail2): + /* At this point we have a tail of 0-7 bytes and we know that the +- destiniation is double word aligned. */ ++ destination is double word aligned. */ + 4: bf 29,2f + lwz 6,0(4) + stw 6,0(3) +@@ -344,7 +342,7 @@ + lbz 6,4(4) + stb 6,4(3) + b 0f +- ++ + 2: bf 30,1f + lhz 6,0(4) + sth 6,0(3) +@@ -352,7 +350,7 @@ + lbz 6,2(4) + stb 6,2(3) + b 0f +- ++ + 1: bf 31,0f + lbz 6,0(4) + stb 6,0(3) +@@ -361,7 +359,7 @@ + ld 3,-16(1) + blr + +-/* Copy up to 31 bytes. This divided into two cases 0-8 bytes and 9-31 ++/* Copy up to 31 bytes. This divided into two cases 0-8 bytes and 9-31 + bytes. Each case is handled without loops, using binary (1,2,4,8) + tests. + +@@ -402,15 +400,28 @@ + blt cr6,5f + srdi 7,6,16 + bgt cr6,3f ++#ifdef __LITTLE_ENDIAN__ ++ sth 7,0(3) ++#else + sth 6,0(3) ++#endif + b 7f + .align 4 + 3: ++#ifdef __LITTLE_ENDIAN__ ++ rotlwi 6,6,24 ++ stb 6,0(3) ++ sth 7,1(3) ++#else + stb 7,0(3) + sth 6,1(3) ++#endif + b 7f + .align 4 + 5: ++#ifdef __LITTLE_ENDIAN__ ++ rotlwi 6,6,8 ++#endif + stb 6,0(3) + 7: + cmpldi cr1,10,16 +@@ -421,7 +432,7 @@ + /* At least 6 bytes left and the source is word aligned. This allows + some speculative loads up front. */ + /* We need to special case the fall-through because the biggest delays +- are due to address computation not being ready in time for the ++ are due to address computation not being ready in time for the + AGEN. */ + lwz 6,0(12) + lwz 7,4(12) +@@ -452,7 +463,7 @@ + ld 3,-16(1) + blr + .align 4 +-L(dus_tail16p8): /* less then 8 bytes left. */ ++L(dus_tail16p8): /* less than 8 bytes left. */ + beq cr1,L(dus_tailX) /* exactly 16 bytes, early exit. */ + cmpldi cr1,10,20 + bf 29,L(dus_tail16p2) +@@ -466,7 +477,7 @@ + ld 3,-16(1) + blr + .align 4 +-L(dus_tail16p4): /* less then 4 bytes left. */ ++L(dus_tail16p4): /* less than 4 bytes left. */ + addi 12,12,24 + addi 3,3,24 + bgt cr0,L(dus_tail2) +@@ -474,7 +485,7 @@ + ld 3,-16(1) + blr + .align 4 +-L(dus_tail16p2): /* 16 bytes moved, less then 4 bytes left. */ ++L(dus_tail16p2): /* 16 bytes moved, less than 4 bytes left. */ + addi 12,12,16 + addi 3,3,16 + b L(dus_tail2) +@@ -499,7 +510,7 @@ + ld 3,-16(1) + blr + .align 4 +-L(dus_tail8p4): /* less then 4 bytes left. */ ++L(dus_tail8p4): /* less than 4 bytes left. */ + addi 12,12,8 + addi 3,3,8 + bgt cr1,L(dus_tail2) +@@ -510,14 +521,14 @@ + .align 4 + L(dus_tail4): /* Move 4 bytes. */ + /* r6 already loaded speculatively. If we are here we know there is +- more then 4 bytes left. So there is no need to test. */ ++ more than 4 bytes left. So there is no need to test. */ + addi 12,12,4 + stw 6,0(3) + addi 3,3,4 + L(dus_tail2): /* Move 2-3 bytes. */ + bf 30,L(dus_tail1) + lhz 6,0(12) +- sth 6,0(3) ++ sth 6,0(3) + bf 31,L(dus_tailX) + lbz 7,2(12) + stb 7,2(3) +@@ -537,7 +548,7 @@ + .LE8: + mr 12,4 + bne cr6,L(dus_4) +-/* Exactly 8 bytes. We may cross a 32-/128-byte boundry and take a ~20 ++/* Exactly 8 bytes. We may cross a 32-/128-byte boundary and take a ~20 + cycle delay. This case should be rare and any attempt to avoid this + would take most of 20 cycles any way. */ + ld 6,0(4) +@@ -552,7 +563,7 @@ + stw 6,0(3) + bf 30,L(dus_5) + lhz 7,4(4) +- sth 7,4(3) ++ sth 7,4(3) + bf 31,L(dus_0) + lbz 8,6(4) + stb 8,6(3) +@@ -590,20 +601,31 @@ + bge cr0, L(du4_do) + blt cr5, L(du1_do) + beq cr5, L(du2_do) +- b L(du3_do) +- ++ b L(du3_do) ++ + .align 4 + L(du1_do): + bf 30,L(du1_1dw) + + /* there are at least two DWs to copy */ ++ /* FIXME: can combine last shift and "or" into "rldimi" */ ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 8 ++ sldi 8,7, 64-8 ++#else + sldi 0,6, 8 + srdi 8,7, 64-8 ++#endif + or 0,0,8 + ld 6,16(5) + std 0,0(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,7, 8 ++ sldi 8,6, 64-8 ++#else + sldi 0,7, 8 + srdi 8,6, 64-8 ++#endif + or 0,0,8 + ld 7,24(5) + std 0,8(4) +@@ -612,8 +634,13 @@ + blt cr6,L(du1_fini) /* if total DWs = 3, then bypass loop */ + bf 31,L(du1_loop) + /* there is a third DW to copy */ ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 8 ++ sldi 8,7, 64-8 ++#else + sldi 0,6, 8 + srdi 8,7, 64-8 ++#endif + or 0,0,8 + std 0,0(4) + mr 6,7 +@@ -624,8 +651,13 @@ + b L(du1_loop) + .align 4 + L(du1_1dw): ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 8 ++ sldi 8,7, 64-8 ++#else + sldi 0,6, 8 + srdi 8,7, 64-8 ++#endif + addi 5,5,16 + or 0,0,8 + bf 31,L(du1_loop) +@@ -637,23 +669,43 @@ + .align 4 + /* copy 32 bytes at a time */ + L(du1_loop): ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 8 ++ sldi 8,7, 64-8 ++#else + sldi 0,6, 8 + srdi 8,7, 64-8 ++#endif + or 0,0,8 + ld 6,0(5) + std 0,0(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,7, 8 ++ sldi 8,6, 64-8 ++#else + sldi 0,7, 8 + srdi 8,6, 64-8 ++#endif + or 0,0,8 + ld 7,8(5) + std 0,8(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 8 ++ sldi 8,7, 64-8 ++#else + sldi 0,6, 8 + srdi 8,7, 64-8 ++#endif + or 0,0,8 + ld 6,16(5) + std 0,16(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,7, 8 ++ sldi 8,6, 64-8 ++#else + sldi 0,7, 8 + srdi 8,6, 64-8 ++#endif + or 0,0,8 + ld 7,24(5) + std 0,24(4) +@@ -663,9 +715,14 @@ + .align 4 + L(du1_fini): + /* calculate and store the final DW */ ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 8 ++ sldi 8,7, 64-8 ++#else + sldi 0,6, 8 + srdi 8,7, 64-8 +- or 0,0,8 ++#endif ++ or 0,0,8 + std 0,0(4) + b L(du_done) + +@@ -674,13 +731,23 @@ + bf 30,L(du2_1dw) + + /* there are at least two DWs to copy */ ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 16 ++ sldi 8,7, 64-16 ++#else + sldi 0,6, 16 + srdi 8,7, 64-16 ++#endif + or 0,0,8 + ld 6,16(5) + std 0,0(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,7, 16 ++ sldi 8,6, 64-16 ++#else + sldi 0,7, 16 + srdi 8,6, 64-16 ++#endif + or 0,0,8 + ld 7,24(5) + std 0,8(4) +@@ -689,8 +756,13 @@ + blt cr6,L(du2_fini) /* if total DWs = 3, then bypass loop */ + bf 31,L(du2_loop) + /* there is a third DW to copy */ ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 16 ++ sldi 8,7, 64-16 ++#else + sldi 0,6, 16 + srdi 8,7, 64-16 ++#endif + or 0,0,8 + std 0,0(4) + mr 6,7 +@@ -701,8 +773,13 @@ + b L(du2_loop) + .align 4 + L(du2_1dw): ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 16 ++ sldi 8,7, 64-16 ++#else + sldi 0,6, 16 + srdi 8,7, 64-16 ++#endif + addi 5,5,16 + or 0,0,8 + bf 31,L(du2_loop) +@@ -714,23 +791,43 @@ + .align 4 + /* copy 32 bytes at a time */ + L(du2_loop): ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 16 ++ sldi 8,7, 64-16 ++#else + sldi 0,6, 16 + srdi 8,7, 64-16 ++#endif + or 0,0,8 + ld 6,0(5) + std 0,0(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,7, 16 ++ sldi 8,6, 64-16 ++#else + sldi 0,7, 16 + srdi 8,6, 64-16 ++#endif + or 0,0,8 + ld 7,8(5) + std 0,8(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 16 ++ sldi 8,7, 64-16 ++#else + sldi 0,6, 16 + srdi 8,7, 64-16 ++#endif + or 0,0,8 + ld 6,16(5) + std 0,16(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,7, 16 ++ sldi 8,6, 64-16 ++#else + sldi 0,7, 16 + srdi 8,6, 64-16 ++#endif + or 0,0,8 + ld 7,24(5) + std 0,24(4) +@@ -740,9 +837,14 @@ + .align 4 + L(du2_fini): + /* calculate and store the final DW */ ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 16 ++ sldi 8,7, 64-16 ++#else + sldi 0,6, 16 + srdi 8,7, 64-16 +- or 0,0,8 ++#endif ++ or 0,0,8 + std 0,0(4) + b L(du_done) + +@@ -751,13 +853,23 @@ + bf 30,L(du3_1dw) + + /* there are at least two DWs to copy */ ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 24 ++ sldi 8,7, 64-24 ++#else + sldi 0,6, 24 + srdi 8,7, 64-24 ++#endif + or 0,0,8 + ld 6,16(5) + std 0,0(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,7, 24 ++ sldi 8,6, 64-24 ++#else + sldi 0,7, 24 + srdi 8,6, 64-24 ++#endif + or 0,0,8 + ld 7,24(5) + std 0,8(4) +@@ -766,8 +878,13 @@ + blt cr6,L(du3_fini) /* if total DWs = 3, then bypass loop */ + bf 31,L(du3_loop) + /* there is a third DW to copy */ ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 24 ++ sldi 8,7, 64-24 ++#else + sldi 0,6, 24 + srdi 8,7, 64-24 ++#endif + or 0,0,8 + std 0,0(4) + mr 6,7 +@@ -778,8 +895,13 @@ + b L(du3_loop) + .align 4 + L(du3_1dw): ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 24 ++ sldi 8,7, 64-24 ++#else + sldi 0,6, 24 + srdi 8,7, 64-24 ++#endif + addi 5,5,16 + or 0,0,8 + bf 31,L(du3_loop) +@@ -791,23 +913,43 @@ + .align 4 + /* copy 32 bytes at a time */ + L(du3_loop): ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 24 ++ sldi 8,7, 64-24 ++#else + sldi 0,6, 24 + srdi 8,7, 64-24 ++#endif + or 0,0,8 + ld 6,0(5) + std 0,0(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,7, 24 ++ sldi 8,6, 64-24 ++#else + sldi 0,7, 24 + srdi 8,6, 64-24 ++#endif + or 0,0,8 + ld 7,8(5) + std 0,8(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 24 ++ sldi 8,7, 64-24 ++#else + sldi 0,6, 24 + srdi 8,7, 64-24 ++#endif + or 0,0,8 + ld 6,16(5) + std 0,16(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,7, 24 ++ sldi 8,6, 64-24 ++#else + sldi 0,7, 24 + srdi 8,6, 64-24 ++#endif + or 0,0,8 + ld 7,24(5) + std 0,24(4) +@@ -817,9 +959,14 @@ + .align 4 + L(du3_fini): + /* calculate and store the final DW */ ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 24 ++ sldi 8,7, 64-24 ++#else + sldi 0,6, 24 + srdi 8,7, 64-24 +- or 0,0,8 ++#endif ++ or 0,0,8 + std 0,0(4) + b L(du_done) + +@@ -834,13 +981,23 @@ + bf 30,L(du4_1dw) + + /* there are at least two DWs to copy */ ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 32 ++ sldi 8,7, 64-32 ++#else + sldi 0,6, 32 + srdi 8,7, 64-32 ++#endif + or 0,0,8 + ld 6,16(5) + std 0,0(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,7, 32 ++ sldi 8,6, 64-32 ++#else + sldi 0,7, 32 + srdi 8,6, 64-32 ++#endif + or 0,0,8 + ld 7,24(5) + std 0,8(4) +@@ -849,8 +1006,13 @@ + blt cr6,L(du4_fini) /* if total DWs = 3, then bypass loop */ + bf 31,L(du4_loop) + /* there is a third DW to copy */ ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 32 ++ sldi 8,7, 64-32 ++#else + sldi 0,6, 32 + srdi 8,7, 64-32 ++#endif + or 0,0,8 + std 0,0(4) + mr 6,7 +@@ -861,8 +1023,13 @@ + b L(du4_loop) + .align 4 + L(du4_1dw): ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 32 ++ sldi 8,7, 64-32 ++#else + sldi 0,6, 32 + srdi 8,7, 64-32 ++#endif + addi 5,5,16 + or 0,0,8 + bf 31,L(du4_loop) +@@ -874,23 +1041,43 @@ + .align 4 + /* copy 32 bytes at a time */ + L(du4_loop): ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 32 ++ sldi 8,7, 64-32 ++#else + sldi 0,6, 32 + srdi 8,7, 64-32 ++#endif + or 0,0,8 + ld 6,0(5) + std 0,0(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,7, 32 ++ sldi 8,6, 64-32 ++#else + sldi 0,7, 32 + srdi 8,6, 64-32 ++#endif + or 0,0,8 + ld 7,8(5) + std 0,8(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 32 ++ sldi 8,7, 64-32 ++#else + sldi 0,6, 32 + srdi 8,7, 64-32 ++#endif + or 0,0,8 + ld 6,16(5) + std 0,16(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,7, 32 ++ sldi 8,6, 64-32 ++#else + sldi 0,7, 32 + srdi 8,6, 64-32 ++#endif + or 0,0,8 + ld 7,24(5) + std 0,24(4) +@@ -900,9 +1087,14 @@ + .align 4 + L(du4_fini): + /* calculate and store the final DW */ ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 32 ++ sldi 8,7, 64-32 ++#else + sldi 0,6, 32 + srdi 8,7, 64-32 +- or 0,0,8 ++#endif ++ or 0,0,8 + std 0,0(4) + b L(du_done) + +@@ -911,13 +1103,23 @@ + bf 30,L(du5_1dw) + + /* there are at least two DWs to copy */ ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 40 ++ sldi 8,7, 64-40 ++#else + sldi 0,6, 40 + srdi 8,7, 64-40 ++#endif + or 0,0,8 + ld 6,16(5) + std 0,0(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,7, 40 ++ sldi 8,6, 64-40 ++#else + sldi 0,7, 40 + srdi 8,6, 64-40 ++#endif + or 0,0,8 + ld 7,24(5) + std 0,8(4) +@@ -926,8 +1128,13 @@ + blt cr6,L(du5_fini) /* if total DWs = 3, then bypass loop */ + bf 31,L(du5_loop) + /* there is a third DW to copy */ ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 40 ++ sldi 8,7, 64-40 ++#else + sldi 0,6, 40 + srdi 8,7, 64-40 ++#endif + or 0,0,8 + std 0,0(4) + mr 6,7 +@@ -938,8 +1145,13 @@ + b L(du5_loop) + .align 4 + L(du5_1dw): ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 40 ++ sldi 8,7, 64-40 ++#else + sldi 0,6, 40 + srdi 8,7, 64-40 ++#endif + addi 5,5,16 + or 0,0,8 + bf 31,L(du5_loop) +@@ -951,23 +1163,43 @@ + .align 4 + /* copy 32 bytes at a time */ + L(du5_loop): ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 40 ++ sldi 8,7, 64-40 ++#else + sldi 0,6, 40 + srdi 8,7, 64-40 ++#endif + or 0,0,8 + ld 6,0(5) + std 0,0(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,7, 40 ++ sldi 8,6, 64-40 ++#else + sldi 0,7, 40 + srdi 8,6, 64-40 ++#endif + or 0,0,8 + ld 7,8(5) + std 0,8(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 40 ++ sldi 8,7, 64-40 ++#else + sldi 0,6, 40 + srdi 8,7, 64-40 ++#endif + or 0,0,8 + ld 6,16(5) + std 0,16(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,7, 40 ++ sldi 8,6, 64-40 ++#else + sldi 0,7, 40 + srdi 8,6, 64-40 ++#endif + or 0,0,8 + ld 7,24(5) + std 0,24(4) +@@ -977,9 +1209,14 @@ + .align 4 + L(du5_fini): + /* calculate and store the final DW */ ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 40 ++ sldi 8,7, 64-40 ++#else + sldi 0,6, 40 + srdi 8,7, 64-40 +- or 0,0,8 ++#endif ++ or 0,0,8 + std 0,0(4) + b L(du_done) + +@@ -988,13 +1225,23 @@ + bf 30,L(du6_1dw) + + /* there are at least two DWs to copy */ ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 48 ++ sldi 8,7, 64-48 ++#else + sldi 0,6, 48 + srdi 8,7, 64-48 ++#endif + or 0,0,8 + ld 6,16(5) + std 0,0(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,7, 48 ++ sldi 8,6, 64-48 ++#else + sldi 0,7, 48 + srdi 8,6, 64-48 ++#endif + or 0,0,8 + ld 7,24(5) + std 0,8(4) +@@ -1003,8 +1250,13 @@ + blt cr6,L(du6_fini) /* if total DWs = 3, then bypass loop */ + bf 31,L(du6_loop) + /* there is a third DW to copy */ ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 48 ++ sldi 8,7, 64-48 ++#else + sldi 0,6, 48 + srdi 8,7, 64-48 ++#endif + or 0,0,8 + std 0,0(4) + mr 6,7 +@@ -1015,8 +1267,13 @@ + b L(du6_loop) + .align 4 + L(du6_1dw): ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 48 ++ sldi 8,7, 64-48 ++#else + sldi 0,6, 48 + srdi 8,7, 64-48 ++#endif + addi 5,5,16 + or 0,0,8 + bf 31,L(du6_loop) +@@ -1028,23 +1285,43 @@ + .align 4 + /* copy 32 bytes at a time */ + L(du6_loop): ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 48 ++ sldi 8,7, 64-48 ++#else + sldi 0,6, 48 + srdi 8,7, 64-48 ++#endif + or 0,0,8 + ld 6,0(5) + std 0,0(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,7, 48 ++ sldi 8,6, 64-48 ++#else + sldi 0,7, 48 + srdi 8,6, 64-48 ++#endif + or 0,0,8 + ld 7,8(5) + std 0,8(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 48 ++ sldi 8,7, 64-48 ++#else + sldi 0,6, 48 + srdi 8,7, 64-48 ++#endif + or 0,0,8 + ld 6,16(5) + std 0,16(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,7, 48 ++ sldi 8,6, 64-48 ++#else + sldi 0,7, 48 + srdi 8,6, 64-48 ++#endif + or 0,0,8 + ld 7,24(5) + std 0,24(4) +@@ -1054,9 +1331,14 @@ + .align 4 + L(du6_fini): + /* calculate and store the final DW */ ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 48 ++ sldi 8,7, 64-48 ++#else + sldi 0,6, 48 + srdi 8,7, 64-48 +- or 0,0,8 ++#endif ++ or 0,0,8 + std 0,0(4) + b L(du_done) + +@@ -1065,13 +1347,23 @@ + bf 30,L(du7_1dw) + + /* there are at least two DWs to copy */ ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 56 ++ sldi 8,7, 64-56 ++#else + sldi 0,6, 56 + srdi 8,7, 64-56 ++#endif + or 0,0,8 + ld 6,16(5) + std 0,0(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,7, 56 ++ sldi 8,6, 64-56 ++#else + sldi 0,7, 56 + srdi 8,6, 64-56 ++#endif + or 0,0,8 + ld 7,24(5) + std 0,8(4) +@@ -1080,8 +1372,13 @@ + blt cr6,L(du7_fini) /* if total DWs = 3, then bypass loop */ + bf 31,L(du7_loop) + /* there is a third DW to copy */ ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 56 ++ sldi 8,7, 64-56 ++#else + sldi 0,6, 56 + srdi 8,7, 64-56 ++#endif + or 0,0,8 + std 0,0(4) + mr 6,7 +@@ -1092,8 +1389,13 @@ + b L(du7_loop) + .align 4 + L(du7_1dw): ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 56 ++ sldi 8,7, 64-56 ++#else + sldi 0,6, 56 + srdi 8,7, 64-56 ++#endif + addi 5,5,16 + or 0,0,8 + bf 31,L(du7_loop) +@@ -1105,23 +1407,43 @@ + .align 4 + /* copy 32 bytes at a time */ + L(du7_loop): ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 56 ++ sldi 8,7, 64-56 ++#else + sldi 0,6, 56 + srdi 8,7, 64-56 ++#endif + or 0,0,8 + ld 6,0(5) + std 0,0(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,7, 56 ++ sldi 8,6, 64-56 ++#else + sldi 0,7, 56 + srdi 8,6, 64-56 ++#endif + or 0,0,8 + ld 7,8(5) + std 0,8(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 56 ++ sldi 8,7, 64-56 ++#else + sldi 0,6, 56 + srdi 8,7, 64-56 ++#endif + or 0,0,8 + ld 6,16(5) + std 0,16(4) ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,7, 56 ++ sldi 8,6, 64-56 ++#else + sldi 0,7, 56 + srdi 8,6, 64-56 ++#endif + or 0,0,8 + ld 7,24(5) + std 0,24(4) +@@ -1131,12 +1453,17 @@ + .align 4 + L(du7_fini): + /* calculate and store the final DW */ ++#ifdef __LITTLE_ENDIAN__ ++ srdi 0,6, 56 ++ sldi 8,7, 64-56 ++#else + sldi 0,6, 56 + srdi 8,7, 64-56 +- or 0,0,8 ++#endif ++ or 0,0,8 + std 0,0(4) + b L(du_done) +- ++ + .align 4 + L(du_done): + rldicr 0,31,0,60 +@@ -1144,9 +1471,9 @@ + beq cr1,0f /* If the tail is 0 bytes we are done! */ + + add 3,3,0 +- add 12,12,0 ++ add 12,12,0 + /* At this point we have a tail of 0-7 bytes and we know that the +- destiniation is double word aligned. */ ++ destination is double word aligned. */ + 4: bf 29,2f + lwz 6,0(12) + addi 12,12,4 +@@ -1165,5 +1492,5 @@ + ld 31,-8(1) + ld 3,-16(1) + blr +-END_GEN_TB (BP_SYM (memcpy),TB_TOCLESS) ++END_GEN_TB (memcpy,TB_TOCLESS) + libc_hidden_builtin_def (memcpy) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memcpy.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memcpy.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memcpy.S 2014-05-29 13:04:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memcpy.S 2014-05-29 13:05:40.000000000 -0500 +@@ -1,5 +1,5 @@ + /* Optimized memcpy implementation for PowerPC64/POWER7. +- Copyright (C) 2010, 2011 Free Software Foundation, Inc. ++ Copyright (C) 2010-2014 Free Software Foundation, Inc. + Contributed by Luis Machado . + This file is part of the GNU C Library. + +@@ -18,425 +18,366 @@ + . */ + + #include +-#include +-#include + + + /* __ptr_t [r3] memcpy (__ptr_t dst [r3], __ptr_t src [r4], size_t len [r5]); + Returns 'dst'. */ + ++#define dst 11 /* Use r11 so r3 kept unchanged. */ ++#define src 4 ++#define cnt 5 ++ + .machine power7 +-EALIGN (BP_SYM (memcpy), 5, 0) ++EALIGN (memcpy, 5, 0) + CALL_MCOUNT 3 + +- cmpldi cr1,5,31 ++ cmpldi cr1,cnt,31 + neg 0,3 +- std 3,-16(1) +- std 31,-8(1) +- cfi_offset(31,-8) + ble cr1, L(copy_LT_32) /* If move < 32 bytes use short move + code. */ + +- andi. 11,3,7 /* Check alignment of DST. */ +- ++#ifdef __LITTLE_ENDIAN__ ++/* In little-endian mode, power7 takes an alignment trap on any lxvd2x ++ or stxvd2x crossing a 32-byte boundary, so ensure the aligned_copy ++ loop is only used for quadword aligned copies. */ ++ andi. 10,3,15 ++ clrldi 11,4,60 ++#else ++ andi. 10,3,7 /* Check alignment of DST. */ ++ clrldi 11,4,61 /* Check alignment of SRC. */ ++#endif ++ cmpld cr6,10,11 /* SRC and DST alignments match? */ + +- clrldi 10,4,61 /* Check alignment of SRC. */ +- cmpld cr6,10,11 /* SRC and DST alignments match? */ +- mr 12,4 +- mr 31,5 ++ mr dst,3 + bne cr6,L(copy_GE_32_unaligned) ++ beq L(aligned_copy) + +- srdi 9,5,3 /* Number of full quadwords remaining. */ +- +- beq L(copy_GE_32_aligned_cont) +- +- clrldi 0,0,61 +- mtcrf 0x01,0 +- subf 31,0,5 +- +- /* Get the SRC aligned to 8 bytes. */ +- +-1: bf 31,2f +- lbz 6,0(12) +- addi 12,12,1 +- stb 6,0(3) +- addi 3,3,1 +-2: bf 30,4f +- lhz 6,0(12) +- addi 12,12,2 +- sth 6,0(3) +- addi 3,3,2 +-4: bf 29,0f +- lwz 6,0(12) +- addi 12,12,4 +- stw 6,0(3) +- addi 3,3,4 +-0: +- clrldi 10,12,61 /* Check alignment of SRC again. */ +- srdi 9,31,3 /* Number of full doublewords remaining. */ +- +-L(copy_GE_32_aligned_cont): +- +- clrldi 11,31,61 +- mtcrf 0x01,9 +- +- srdi 8,31,5 +- cmpldi cr1,9,4 +- cmpldi cr6,11,0 +- mr 11,12 ++ mtocrf 0x01,0 ++#ifdef __LITTLE_ENDIAN__ ++ clrldi 0,0,60 ++#else ++ clrldi 0,0,61 ++#endif + +- /* Copy 1~3 doublewords so the main loop starts +- at a multiple of 32 bytes. */ +- +- bf 30,1f +- ld 6,0(12) +- ld 7,8(12) +- addi 11,12,16 +- mtctr 8 +- std 6,0(3) +- std 7,8(3) +- addi 10,3,16 +- bf 31,4f +- ld 0,16(12) +- std 0,16(3) +- blt cr1,3f +- addi 11,12,24 +- addi 10,3,24 +- b 4f +- +- .align 4 +-1: /* Copy 1 doubleword and set the counter. */ +- mr 10,3 +- mtctr 8 +- bf 31,4f +- ld 6,0(12) +- addi 11,12,8 +- std 6,0(3) +- addi 10,3,8 ++/* Get the DST and SRC aligned to 8 bytes (16 for little-endian). */ ++1: ++ bf 31,2f ++ lbz 6,0(src) ++ addi src,src,1 ++ stb 6,0(dst) ++ addi dst,dst,1 ++2: ++ bf 30,4f ++ lhz 6,0(src) ++ addi src,src,2 ++ sth 6,0(dst) ++ addi dst,dst,2 ++4: ++ bf 29,8f ++ lwz 6,0(src) ++ addi src,src,4 ++ stw 6,0(dst) ++ addi dst,dst,4 ++8: ++#ifdef __LITTLE_ENDIAN__ ++ bf 28,16f ++ ld 6,0(src) ++ addi src,src,8 ++ std 6,0(dst) ++ addi dst,dst,8 ++16: ++#endif ++ subf cnt,0,cnt + ++/* Main aligned copy loop. Copies 128 bytes at a time. */ + L(aligned_copy): +- /* Main aligned copy loop. Copies up to 128-bytes at a time. */ +- .align 4 +-4: +- /* check for any 32-byte or 64-byte lumps that are outside of a +- nice 128-byte range. R8 contains the number of 32-byte +- lumps, so drop this into the CR, and use the SO/EQ bits to help +- handle the 32- or 64- byte lumps. Then handle the rest with an +- unrolled 128-bytes-at-a-time copy loop. */ +- mtocrf 1,8 +- li 6,16 # 16() index +- li 7,32 # 32() index +- li 8,48 # 48() index +- +-L(aligned_32byte): +- /* if the SO bit (indicating a 32-byte lump) is not set, move along. */ +- bns cr7,L(aligned_64byte) +- lxvd2x 6,0,11 +- lxvd2x 7,11,6 +- addi 11,11,32 +- stxvd2x 6,0,10 +- stxvd2x 7,10,6 +- addi 10,10,32 +- +-L(aligned_64byte): +- /* if the EQ bit (indicating a 64-byte lump) is not set, move along. */ +- bne cr7,L(aligned_128setup) +- lxvd2x 6,0,11 +- lxvd2x 7,11,6 +- lxvd2x 8,11,7 +- lxvd2x 9,11,8 +- addi 11,11,64 +- stxvd2x 6,0,10 +- stxvd2x 7,10,6 +- stxvd2x 8,10,7 +- stxvd2x 9,10,8 +- addi 10,10,64 +- +-L(aligned_128setup): +- /* Set up for the 128-byte at a time copy loop. */ +- srdi 8,31,7 +- cmpdi 8,0 # Any 4x lumps left? +- beq 3f # if not, move along. +- lxvd2x 6,0,11 +- lxvd2x 7,11,6 +- mtctr 8 # otherwise, load the ctr and begin. +- li 8,48 # 48() index ++ li 6,16 ++ li 7,32 ++ li 8,48 ++ mtocrf 0x02,cnt ++ srdi 12,cnt,7 ++ cmpdi 12,0 ++ beq L(aligned_tail) ++ lxvd2x 6,0,src ++ lxvd2x 7,src,6 ++ mtctr 12 + b L(aligned_128loop) + ++ .align 4 + L(aligned_128head): + /* for the 2nd + iteration of this loop. */ +- lxvd2x 6,0,11 +- lxvd2x 7,11,6 ++ lxvd2x 6,0,src ++ lxvd2x 7,src,6 + L(aligned_128loop): +- lxvd2x 8,11,7 +- lxvd2x 9,11,8 +- stxvd2x 6,0,10 +- addi 11,11,64 +- stxvd2x 7,10,6 +- stxvd2x 8,10,7 +- stxvd2x 9,10,8 +- lxvd2x 6,0,11 +- lxvd2x 7,11,6 +- addi 10,10,64 +- lxvd2x 8,11,7 +- lxvd2x 9,11,8 +- addi 11,11,64 +- stxvd2x 6,0,10 +- stxvd2x 7,10,6 +- stxvd2x 8,10,7 +- stxvd2x 9,10,8 +- addi 10,10,64 ++ lxvd2x 8,src,7 ++ lxvd2x 9,src,8 ++ stxvd2x 6,0,dst ++ addi src,src,64 ++ stxvd2x 7,dst,6 ++ stxvd2x 8,dst,7 ++ stxvd2x 9,dst,8 ++ lxvd2x 6,0,src ++ lxvd2x 7,src,6 ++ addi dst,dst,64 ++ lxvd2x 8,src,7 ++ lxvd2x 9,src,8 ++ addi src,src,64 ++ stxvd2x 6,0,dst ++ stxvd2x 7,dst,6 ++ stxvd2x 8,dst,7 ++ stxvd2x 9,dst,8 ++ addi dst,dst,64 + bdnz L(aligned_128head) + +-3: +- /* Check for tail bytes. */ +- rldicr 0,31,0,60 +- mtcrf 0x01,31 +- beq cr6,0f +- +-.L9: +- add 3,3,0 +- add 12,12,0 +- +- /* At this point we have a tail of 0-7 bytes and we know that the +- destination is doubleword-aligned. */ +-4: /* Copy 4 bytes. */ +- bf 29,2f +- +- lwz 6,0(12) +- addi 12,12,4 +- stw 6,0(3) +- addi 3,3,4 +-2: /* Copy 2 bytes. */ +- bf 30,1f +- +- lhz 6,0(12) +- addi 12,12,2 +- sth 6,0(3) +- addi 3,3,2 +-1: /* Copy 1 byte. */ +- bf 31,0f +- +- lbz 6,0(12) +- stb 6,0(3) +-0: /* Return original DST pointer. */ +- ld 31,-8(1) +- ld 3,-16(1) ++L(aligned_tail): ++ mtocrf 0x01,cnt ++ bf 25,32f ++ lxvd2x 6,0,src ++ lxvd2x 7,src,6 ++ lxvd2x 8,src,7 ++ lxvd2x 9,src,8 ++ addi src,src,64 ++ stxvd2x 6,0,dst ++ stxvd2x 7,dst,6 ++ stxvd2x 8,dst,7 ++ stxvd2x 9,dst,8 ++ addi dst,dst,64 ++32: ++ bf 26,16f ++ lxvd2x 6,0,src ++ lxvd2x 7,src,6 ++ addi src,src,32 ++ stxvd2x 6,0,dst ++ stxvd2x 7,dst,6 ++ addi dst,dst,32 ++16: ++ bf 27,8f ++ lxvd2x 6,0,src ++ addi src,src,16 ++ stxvd2x 6,0,dst ++ addi dst,dst,16 ++8: ++ bf 28,4f ++ ld 6,0(src) ++ addi src,src,8 ++ std 6,0(dst) ++ addi dst,dst,8 ++4: /* Copies 4~7 bytes. */ ++ bf 29,L(tail2) ++ lwz 6,0(src) ++ stw 6,0(dst) ++ bf 30,L(tail5) ++ lhz 7,4(src) ++ sth 7,4(dst) ++ bflr 31 ++ lbz 8,6(src) ++ stb 8,6(dst) ++ /* Return original DST pointer. */ + blr + +- /* Handle copies of 0~31 bytes. */ +- .align 4 ++ ++/* Handle copies of 0~31 bytes. */ ++ .align 4 + L(copy_LT_32): +- cmpldi cr6,5,8 +- mr 12,4 +- mtcrf 0x01,5 ++ mr dst,3 ++ cmpldi cr6,cnt,8 ++ mtocrf 0x01,cnt + ble cr6,L(copy_LE_8) + + /* At least 9 bytes to go. */ + neg 8,4 +- clrrdi 11,4,2 +- andi. 0,8,3 +- cmpldi cr1,5,16 +- mr 10,5 ++ andi. 0,8,3 ++ cmpldi cr1,cnt,16 + beq L(copy_LT_32_aligned) + +- /* Force 4-bytes alignment for SRC. */ +- mtocrf 0x01,0 +- subf 10,0,5 +-2: bf 30,1f +- +- lhz 6,0(12) +- addi 12,12,2 +- sth 6,0(3) +- addi 3,3,2 +-1: bf 31,L(end_4bytes_alignment) +- +- lbz 6,0(12) +- addi 12,12,1 +- stb 6,0(3) +- addi 3,3,1 ++ /* Force 4-byte alignment for SRC. */ ++ mtocrf 0x01,0 ++ subf cnt,0,cnt ++2: ++ bf 30,1f ++ lhz 6,0(src) ++ addi src,src,2 ++ sth 6,0(dst) ++ addi dst,dst,2 ++1: ++ bf 31,L(end_4bytes_alignment) ++ lbz 6,0(src) ++ addi src,src,1 ++ stb 6,0(dst) ++ addi dst,dst,1 + +- .align 4 ++ .align 4 + L(end_4bytes_alignment): +- cmpldi cr1,10,16 +- mtcrf 0x01,10 ++ cmpldi cr1,cnt,16 ++ mtocrf 0x01,cnt + + L(copy_LT_32_aligned): + /* At least 6 bytes to go, and SRC is word-aligned. */ + blt cr1,8f + + /* Copy 16 bytes. */ +- lwz 6,0(12) +- lwz 7,4(12) +- stw 6,0(3) +- lwz 8,8(12) +- stw 7,4(3) +- lwz 6,12(12) +- addi 12,12,16 +- stw 8,8(3) +- stw 6,12(3) +- addi 3,3,16 ++ lwz 6,0(src) ++ lwz 7,4(src) ++ stw 6,0(dst) ++ lwz 8,8(src) ++ stw 7,4(dst) ++ lwz 6,12(src) ++ addi src,src,16 ++ stw 8,8(dst) ++ stw 6,12(dst) ++ addi dst,dst,16 + 8: /* Copy 8 bytes. */ +- bf 28,4f ++ bf 28,L(tail4) ++ lwz 6,0(src) ++ lwz 7,4(src) ++ addi src,src,8 ++ stw 6,0(dst) ++ stw 7,4(dst) ++ addi dst,dst,8 ++ ++ .align 4 ++/* Copies 4~7 bytes. */ ++L(tail4): ++ bf 29,L(tail2) ++ lwz 6,0(src) ++ stw 6,0(dst) ++ bf 30,L(tail5) ++ lhz 7,4(src) ++ sth 7,4(dst) ++ bflr 31 ++ lbz 8,6(src) ++ stb 8,6(dst) ++ /* Return original DST pointer. */ ++ blr + +- lwz 6,0(12) +- lwz 7,4(12) +- addi 12,12,8 +- stw 6,0(3) +- stw 7,4(3) +- addi 3,3,8 +-4: /* Copy 4 bytes. */ +- bf 29,2f +- +- lwz 6,0(12) +- addi 12,12,4 +- stw 6,0(3) +- addi 3,3,4 +-2: /* Copy 2-3 bytes. */ ++ .align 4 ++/* Copies 2~3 bytes. */ ++L(tail2): + bf 30,1f +- +- lhz 6,0(12) +- sth 6,0(3) +- bf 31,0f +- lbz 7,2(12) +- stb 7,2(3) +- ld 3,-16(1) ++ lhz 6,0(src) ++ sth 6,0(dst) ++ bflr 31 ++ lbz 7,2(src) ++ stb 7,2(dst) + blr + +- .align 4 +-1: /* Copy 1 byte. */ +- bf 31,0f ++ .align 4 ++L(tail5): ++ bflr 31 ++ lbz 6,4(src) ++ stb 6,4(dst) ++ blr + +- lbz 6,0(12) +- stb 6,0(3) +-0: /* Return original DST pointer. */ +- ld 3,-16(1) ++ .align 4 ++1: ++ bflr 31 ++ lbz 6,0(src) ++ stb 6,0(dst) ++ /* Return original DST pointer. */ + blr + +- /* Handles copies of 0~8 bytes. */ +- .align 4 ++ ++/* Handles copies of 0~8 bytes. */ ++ .align 4 + L(copy_LE_8): +- bne cr6,4f ++ bne cr6,L(tail4) + + /* Though we could've used ld/std here, they are still + slow for unaligned cases. */ + +- lwz 6,0(4) +- lwz 7,4(4) +- stw 6,0(3) +- stw 7,4(3) +- ld 3,-16(1) /* Return original DST pointers. */ ++ lwz 6,0(src) ++ lwz 7,4(src) ++ stw 6,0(dst) ++ stw 7,4(dst) + blr + +- .align 4 +-4: /* Copies 4~7 bytes. */ +- bf 29,2b + +- lwz 6,0(4) +- stw 6,0(3) +- bf 30,5f +- lhz 7,4(4) +- sth 7,4(3) +- bf 31,0f +- lbz 8,6(4) +- stb 8,6(3) +- ld 3,-16(1) +- blr +- +- .align 4 +-5: /* Copy 1 byte. */ +- bf 31,0f +- +- lbz 6,4(4) +- stb 6,4(3) +- +-0: /* Return original DST pointer. */ +- ld 3,-16(1) +- blr +- +- /* Handle copies of 32+ bytes where DST is aligned (to quadword) but +- SRC is not. Use aligned quadword loads from SRC, shifted to realign +- the data, allowing for aligned DST stores. */ +- .align 4 ++/* Handle copies of 32+ bytes where DST is aligned (to quadword) but ++ SRC is not. Use aligned quadword loads from SRC, shifted to realign ++ the data, allowing for aligned DST stores. */ ++ .align 4 + L(copy_GE_32_unaligned): +- clrldi 0,0,60 /* Number of bytes until the 1st +- quadword. */ +- andi. 11,3,15 /* Check alignment of DST (against +- quadwords). */ +- srdi 9,5,4 /* Number of full quadwords remaining. */ ++ clrldi 0,0,60 /* Number of bytes until the 1st dst quadword. */ ++#ifndef __LITTLE_ENDIAN__ ++ andi. 10,3,15 /* Check alignment of DST (against quadwords). */ ++#endif ++ srdi 9,cnt,4 /* Number of full quadwords remaining. */ + + beq L(copy_GE_32_unaligned_cont) + +- /* SRC is not quadword aligned, get it aligned. */ ++ /* DST is not quadword aligned, get it aligned. */ + +- mtcrf 0x01,0 +- subf 31,0,5 ++ mtocrf 0x01,0 ++ subf cnt,0,cnt + + /* Vector instructions work best when proper alignment (16-bytes) + is present. Move 0~15 bytes as needed to get DST quadword-aligned. */ +-1: /* Copy 1 byte. */ ++1: + bf 31,2f +- +- lbz 6,0(12) +- addi 12,12,1 +- stb 6,0(3) +- addi 3,3,1 +-2: /* Copy 2 bytes. */ ++ lbz 6,0(src) ++ addi src,src,1 ++ stb 6,0(dst) ++ addi dst,dst,1 ++2: + bf 30,4f +- +- lhz 6,0(12) +- addi 12,12,2 +- sth 6,0(3) +- addi 3,3,2 +-4: /* Copy 4 bytes. */ ++ lhz 6,0(src) ++ addi src,src,2 ++ sth 6,0(dst) ++ addi dst,dst,2 ++4: + bf 29,8f +- +- lwz 6,0(12) +- addi 12,12,4 +- stw 6,0(3) +- addi 3,3,4 +-8: /* Copy 8 bytes. */ ++ lwz 6,0(src) ++ addi src,src,4 ++ stw 6,0(dst) ++ addi dst,dst,4 ++8: + bf 28,0f +- +- ld 6,0(12) +- addi 12,12,8 +- std 6,0(3) +- addi 3,3,8 ++ ld 6,0(src) ++ addi src,src,8 ++ std 6,0(dst) ++ addi dst,dst,8 + 0: +- clrldi 10,12,60 /* Check alignment of SRC. */ +- srdi 9,31,4 /* Number of full quadwords remaining. */ ++ srdi 9,cnt,4 /* Number of full quadwords remaining. */ + + /* The proper alignment is present, it is OK to copy the bytes now. */ + L(copy_GE_32_unaligned_cont): + + /* Setup two indexes to speed up the indexed vector operations. */ +- clrldi 11,31,60 +- li 6,16 /* Index for 16-bytes offsets. */ ++ clrldi 10,cnt,60 ++ li 6,16 /* Index for 16-bytes offsets. */ + li 7,32 /* Index for 32-bytes offsets. */ +- cmpldi cr1,11,0 +- srdi 8,31,5 /* Setup the loop counter. */ +- mr 10,3 +- mr 11,12 +- mtcrf 0x01,9 +- cmpldi cr6,9,1 +- lvsl 5,0,12 +- lvx 3,0,12 +- bf 31,L(setup_unaligned_loop) +- +- /* Copy another 16 bytes to align to 32-bytes due to the loop . */ +- lvx 4,12,6 +- vperm 6,3,4,5 +- addi 11,12,16 +- addi 10,3,16 +- stvx 6,0,3 ++ cmpldi cr1,10,0 ++ srdi 8,cnt,5 /* Setup the loop counter. */ ++ mtocrf 0x01,9 ++ cmpldi cr6,9,1 ++#ifdef __LITTLE_ENDIAN__ ++ lvsr 5,0,src ++#else ++ lvsl 5,0,src ++#endif ++ lvx 3,0,src ++ li 0,0 ++ bf 31,L(setup_unaligned_loop) ++ ++ /* Copy another 16 bytes to align to 32-bytes due to the loop. */ ++ lvx 4,src,6 ++#ifdef __LITTLE_ENDIAN__ ++ vperm 6,4,3,5 ++#else ++ vperm 6,3,4,5 ++#endif ++ addi src,src,16 ++ stvx 6,0,dst ++ addi dst,dst,16 + vor 3,4,4 ++ clrrdi 0,src,60 + + L(setup_unaligned_loop): +- mtctr 8 +- ble cr6,L(end_unaligned_loop) ++ mtctr 8 ++ ble cr6,L(end_unaligned_loop) + + /* Copy 32 bytes at a time using vector instructions. */ +- .align 4 ++ .align 4 + L(unaligned_loop): + + /* Note: vr6/vr10 may contain data that was already copied, +@@ -444,63 +385,56 @@ + some portions again. This is faster than having unaligned + vector instructions though. */ + +- lvx 4,11,6 /* vr4 = r11+16. */ +- vperm 6,3,4,5 /* Merge the correctly-aligned portions +- of vr3/vr4 into vr6. */ +- lvx 3,11,7 /* vr3 = r11+32. */ +- vperm 10,4,3,5 /* Merge the correctly-aligned portions +- of vr3/vr4 into vr10. */ +- addi 11,11,32 +- stvx 6,0,10 +- stvx 10,10,6 +- addi 10,10,32 +- ++ lvx 4,src,6 ++#ifdef __LITTLE_ENDIAN__ ++ vperm 6,4,3,5 ++#else ++ vperm 6,3,4,5 ++#endif ++ lvx 3,src,7 ++#ifdef __LITTLE_ENDIAN__ ++ vperm 10,3,4,5 ++#else ++ vperm 10,4,3,5 ++#endif ++ addi src,src,32 ++ stvx 6,0,dst ++ stvx 10,dst,6 ++ addi dst,dst,32 + bdnz L(unaligned_loop) + +- .align 4 ++ clrrdi 0,src,60 ++ ++ .align 4 + L(end_unaligned_loop): + + /* Check for tail bytes. */ +- rldicr 0,31,0,59 +- mtcrf 0x01,31 +- beq cr1,0f ++ mtocrf 0x01,cnt ++ beqlr cr1 + +- add 3,3,0 +- add 12,12,0 ++ add src,src,0 + + /* We have 1~15 tail bytes to copy, and DST is quadword aligned. */ +-8: /* Copy 8 bytes. */ ++ /* Copy 8 bytes. */ + bf 28,4f +- +- lwz 6,0(12) +- lwz 7,4(12) +- addi 12,12,8 +- stw 6,0(3) +- stw 7,4(3) +- addi 3,3,8 +-4: /* Copy 4 bytes. */ +- bf 29,2f +- +- lwz 6,0(12) +- addi 12,12,4 +- stw 6,0(3) +- addi 3,3,4 +-2: /* Copy 2~3 bytes. */ +- bf 30,1f +- +- lhz 6,0(12) +- addi 12,12,2 +- sth 6,0(3) +- addi 3,3,2 +-1: /* Copy 1 byte. */ +- bf 31,0f +- +- lbz 6,0(12) +- stb 6,0(3) +-0: /* Return original DST pointer. */ +- ld 31,-8(1) +- ld 3,-16(1) ++ lwz 6,0(src) ++ lwz 7,4(src) ++ addi src,src,8 ++ stw 6,0(dst) ++ stw 7,4(dst) ++ addi dst,dst,8 ++4: /* Copy 4~7 bytes. */ ++ bf 29,L(tail2) ++ lwz 6,0(src) ++ stw 6,0(dst) ++ bf 30,L(tail5) ++ lhz 7,4(src) ++ sth 7,4(dst) ++ bflr 31 ++ lbz 8,6(src) ++ stb 8,6(dst) ++ /* Return original DST pointer. */ + blr + +-END_GEN_TB (BP_SYM (memcpy),TB_TOCLESS) ++END_GEN_TB (memcpy,TB_TOCLESS) + libc_hidden_builtin_def (memcpy) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/mempcpy.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/mempcpy.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/mempcpy.S 2014-05-29 13:04:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/mempcpy.S 2014-05-29 13:04:56.000000000 -0500 +@@ -367,13 +367,21 @@ + mr 11,12 + mtcrf 0x01,9 + cmpldi cr6,9,1 +- lvsl 5,0,12 ++#ifdef __LITTLE_ENDIAN__ ++ lvsr 5,0,12 ++#else ++ lvsl 5,0,12 ++#endif + lvx 3,0,12 + bf 31,L(setup_unaligned_loop) + + /* Copy another 16 bytes to align to 32-bytes due to the loop . */ + lvx 4,12,6 +- vperm 6,3,4,5 ++#ifdef __LITTLE_ENDIAN__ ++ vperm 6,4,3,5 ++#else ++ vperm 6,3,4,5 ++#endif + addi 11,12,16 + addi 10,3,16 + stvx 6,0,3 +@@ -393,11 +401,17 @@ + vector instructions though. */ + + lvx 4,11,6 /* vr4 = r11+16. */ +- vperm 6,3,4,5 /* Merge the correctly-aligned portions +- of vr3/vr4 into vr6. */ ++#ifdef __LITTLE_ENDIAN__ ++ vperm 6,4,3,5 ++#else ++ vperm 6,3,4,5 ++#endif + lvx 3,11,7 /* vr3 = r11+32. */ +- vperm 10,4,3,5 /* Merge the correctly-aligned portions +- of vr3/vr4 into vr10. */ ++#ifdef __LITTLE_ENDIAN__ ++ vperm 10,3,4,5 ++#else ++ vperm 10,4,3,5 ++#endif + addi 11,11,32 + stvx 6,0,10 + stvx 10,10,6 diff --git a/SOURCES/glibc-ppc64le-32.patch b/SOURCES/glibc-ppc64le-32.patch new file mode 100644 index 0000000..058d53a --- /dev/null +++ b/SOURCES/glibc-ppc64le-32.patch @@ -0,0 +1,272 @@ +# commit 3be87c77d24c4456ccca4034363b6d1814cd0c84 +# Author: Alan Modra +# Date: Sat Aug 17 18:47:59 2013 +0930 +# +# PowerPC LE memset +# http://sourceware.org/ml/libc-alpha/2013-08/msg00104.html +# +# One of the things I noticed when looking at power7 timing is that rlwimi +# is cracked and the two resulting insns have a register dependency. +# That makes it a little slower than the equivalent rldimi. +# +# * sysdeps/powerpc/powerpc64/memset.S: Replace rlwimi with +# insrdi. Formatting. +# * sysdeps/powerpc/powerpc64/power4/memset.S: Likewise. +# * sysdeps/powerpc/powerpc64/power6/memset.S: Likewise. +# * sysdeps/powerpc/powerpc64/power7/memset.S: Likewise. +# * sysdeps/powerpc/powerpc32/power4/memset.S: Likewise. +# * sysdeps/powerpc/powerpc32/power6/memset.S: Likewise. +# * sysdeps/powerpc/powerpc32/power7/memset.S: Likewise. +# +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/memset.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/memset.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/memset.S 2014-05-29 13:07:41.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power4/memset.S 2014-05-29 13:07:46.000000000 -0500 +@@ -52,7 +52,7 @@ + + /* Align to word boundary. */ + cmplwi cr5, rLEN, 31 +- rlwimi rCHR, rCHR, 8, 16, 23 /* Replicate byte to halfword. */ ++ insrdi rCHR, rCHR, 8, 48 /* Replicate byte to halfword. */ + beq+ L(aligned) + mtcrf 0x01, rMEMP0 + subfic rALIGN, rALIGN, 4 +@@ -67,7 +67,7 @@ + /* Handle the case of size < 31. */ + L(aligned): + mtcrf 0x01, rLEN +- rlwimi rCHR, rCHR, 16, 0, 15 /* Replicate halfword to word. */ ++ insrdi rCHR, rCHR, 16, 32 /* Replicate halfword to word. */ + ble cr5, L(medium) + /* Align to 32-byte boundary. */ + andi. rALIGN, rMEMP, 0x1C +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/memset.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/memset.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/memset.S 2014-05-29 13:07:41.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power6/memset.S 2014-05-29 13:07:46.000000000 -0500 +@@ -50,7 +50,7 @@ + ble- cr1, L(small) + /* Align to word boundary. */ + cmplwi cr5, rLEN, 31 +- rlwimi rCHR, rCHR, 8, 16, 23 /* Replicate byte to halfword. */ ++ insrdi rCHR, rCHR, 8, 48 /* Replicate byte to halfword. */ + beq+ L(aligned) + mtcrf 0x01, rMEMP0 + subfic rALIGN, rALIGN, 4 +@@ -66,7 +66,7 @@ + /* Handle the case of size < 31. */ + L(aligned): + mtcrf 0x01, rLEN +- rlwimi rCHR, rCHR, 16, 0, 15 /* Replicate halfword to word. */ ++ insrdi rCHR, rCHR, 16, 32 /* Replicate halfword to word. */ + ble cr5, L(medium) + /* Align to 32-byte boundary. */ + andi. rALIGN, rMEMP, 0x1C +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memset.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memset.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memset.S 2014-05-29 13:07:41.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memset.S 2014-05-29 13:07:46.000000000 -0500 +@@ -37,8 +37,8 @@ + cfi_offset(31,-8) + + /* Replicate byte to word. */ +- rlwimi 4,4,8,16,23 +- rlwimi 4,4,16,0,15 ++ insrdi 4,4,8,48 ++ insrdi 4,4,16,32 + + ble cr6,L(small) /* If length <= 8, use short copy code. */ + +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/memset.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/memset.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/memset.S 2014-05-29 13:07:41.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/memset.S 2014-05-29 13:07:46.000000000 -0500 +@@ -73,14 +73,14 @@ + + /* Align to doubleword boundary. */ + cmpldi cr5, rLEN, 31 +- rlwimi rCHR, rCHR, 8, 16, 23 /* Replicate byte to halfword. */ ++ insrdi rCHR, rCHR, 8, 48 /* Replicate byte to halfword. */ + beq+ L(aligned2) + mtcrf 0x01, rMEMP0 + subfic rALIGN, rALIGN, 8 + cror 28,30,31 /* Detect odd word aligned. */ + add rMEMP, rMEMP, rALIGN + sub rLEN, rLEN, rALIGN +- rlwimi rCHR, rCHR, 16, 0, 15 /* Replicate halfword to word. */ ++ insrdi rCHR, rCHR, 16, 32 /* Replicate halfword to word. */ + bt 29, L(g4) + /* Process the even word of doubleword. */ + bf+ 31, L(g2) +@@ -102,14 +102,14 @@ + + /* Handle the case of size < 31. */ + L(aligned2): +- rlwimi rCHR, rCHR, 16, 0, 15 /* Replicate halfword to word. */ ++ insrdi rCHR, rCHR, 16, 32 /* Replicate halfword to word. */ + L(aligned): + mtcrf 0x01, rLEN + ble cr5, L(medium) + /* Align to 32-byte boundary. */ + andi. rALIGN, rMEMP, 0x18 + subfic rALIGN, rALIGN, 0x20 +- insrdi rCHR,rCHR,32,0 /* Replicate word to double word. */ ++ insrdi rCHR, rCHR, 32, 0 /* Replicate word to double word. */ + beq L(caligned) + mtcrf 0x01, rALIGN + add rMEMP, rMEMP, rALIGN +@@ -230,7 +230,7 @@ + /* Memset of 0-31 bytes. */ + .align 5 + L(medium): +- insrdi rCHR,rCHR,32,0 /* Replicate word to double word. */ ++ insrdi rCHR, rCHR, 32, 0 /* Replicate word to double word. */ + cmpldi cr1, rLEN, 16 + L(medium_tail2): + add rMEMP, rMEMP, rLEN +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power4/memset.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power4/memset.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power4/memset.S 2014-05-29 13:07:41.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power4/memset.S 2014-05-29 13:07:46.000000000 -0500 +@@ -68,14 +68,14 @@ + + /* Align to doubleword boundary. */ + cmpldi cr5, rLEN, 31 +- rlwimi rCHR, rCHR, 8, 16, 23 /* Replicate byte to halfword. */ ++ insrdi rCHR, rCHR, 8, 48 /* Replicate byte to halfword. */ + beq+ L(aligned2) + mtcrf 0x01, rMEMP0 + subfic rALIGN, rALIGN, 8 + cror 28,30,31 /* Detect odd word aligned. */ + add rMEMP, rMEMP, rALIGN + sub rLEN, rLEN, rALIGN +- rlwimi rCHR, rCHR, 16, 0, 15 /* Replicate halfword to word. */ ++ insrdi rCHR, rCHR, 16, 32 /* Replicate halfword to word. */ + bt 29, L(g4) + /* Process the even word of doubleword. */ + bf+ 31, L(g2) +@@ -97,14 +97,14 @@ + + /* Handle the case of size < 31. */ + L(aligned2): +- rlwimi rCHR, rCHR, 16, 0, 15 /* Replicate halfword to word. */ ++ insrdi rCHR, rCHR, 16, 32 /* Replicate halfword to word. */ + L(aligned): + mtcrf 0x01, rLEN + ble cr5, L(medium) + /* Align to 32-byte boundary. */ + andi. rALIGN, rMEMP, 0x18 + subfic rALIGN, rALIGN, 0x20 +- insrdi rCHR,rCHR,32,0 /* Replicate word to double word. */ ++ insrdi rCHR, rCHR, 32, 0 /* Replicate word to double word. */ + beq L(caligned) + mtcrf 0x01, rALIGN + add rMEMP, rMEMP, rALIGN +@@ -164,24 +164,24 @@ + L(getCacheAligned): + cmpldi cr1,rLEN,32 + andi. rTMP,rMEMP,127 +- blt cr1,L(handletail32) +- beq L(cacheAligned) ++ blt cr1,L(handletail32) ++ beq L(cacheAligned) + addi rMEMP,rMEMP,32 + addi rLEN,rLEN,-32 +- std rCHR,-32(rMEMP) +- std rCHR,-24(rMEMP) +- std rCHR,-16(rMEMP) +- std rCHR,-8(rMEMP) +- b L(getCacheAligned) ++ std rCHR,-32(rMEMP) ++ std rCHR,-24(rMEMP) ++ std rCHR,-16(rMEMP) ++ std rCHR,-8(rMEMP) ++ b L(getCacheAligned) + + /* Now we are aligned to the cache line and can use dcbz. */ + L(cacheAligned): + cmpld cr1,rLEN,rCLS +- blt cr1,L(handletail32) ++ blt cr1,L(handletail32) + dcbz 0,rMEMP + subf rLEN,rCLS,rLEN +- add rMEMP,rMEMP,rCLS +- b L(cacheAligned) ++ add rMEMP,rMEMP,rCLS ++ b L(cacheAligned) + + /* We are here because the cache line size was set and was not 32-bytes + and the remainder (rLEN) is less than the actual cache line size. +@@ -218,7 +218,7 @@ + /* Memset of 0-31 bytes. */ + .align 5 + L(medium): +- insrdi rCHR,rCHR,32,0 /* Replicate word to double word. */ ++ insrdi rCHR, rCHR, 32, 0 /* Replicate word to double word. */ + cmpldi cr1, rLEN, 16 + L(medium_tail2): + add rMEMP, rMEMP, rLEN +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power6/memset.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power6/memset.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power6/memset.S 2014-05-29 13:07:41.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power6/memset.S 2014-05-29 13:07:46.000000000 -0500 +@@ -65,14 +65,14 @@ + + /* Align to doubleword boundary. */ + cmpldi cr5, rLEN, 31 +- rlwimi rCHR, rCHR, 8, 16, 23 /* Replicate byte to halfword. */ ++ insrdi rCHR, rCHR, 8, 48 /* Replicate byte to halfword. */ + beq+ L(aligned2) + mtcrf 0x01, rMEMP0 + subfic rALIGN, rALIGN, 8 + cror 28,30,31 /* Detect odd word aligned. */ + add rMEMP, rMEMP, rALIGN + sub rLEN, rLEN, rALIGN +- rlwimi rCHR, rCHR, 16, 0, 15 /* Replicate halfword to word. */ ++ insrdi rCHR, rCHR, 16, 32 /* Replicate halfword to word. */ + bt 29, L(g4) + /* Process the even word of doubleword. */ + bf+ 31, L(g2) +@@ -94,14 +94,14 @@ + + /* Handle the case of size < 31. */ + L(aligned2): +- rlwimi rCHR, rCHR, 16, 0, 15 /* Replicate halfword to word. */ ++ insrdi rCHR, rCHR, 16, 32 /* Replicate halfword to word. */ + L(aligned): + mtcrf 0x01, rLEN + ble cr5, L(medium) + /* Align to 32-byte boundary. */ + andi. rALIGN, rMEMP, 0x18 + subfic rALIGN, rALIGN, 0x20 +- insrdi rCHR,rCHR,32,0 /* Replicate word to double word. */ ++ insrdi rCHR, rCHR, 32, 0 /* Replicate word to double word. */ + beq L(caligned) + mtcrf 0x01, rALIGN + add rMEMP, rMEMP, rALIGN +@@ -362,7 +362,7 @@ + /* Memset of 0-31 bytes. */ + .align 5 + L(medium): +- insrdi rCHR,rCHR,32,0 /* Replicate word to double word. */ ++ insrdi rCHR, rCHR, 32, 0 /* Replicate word to double word. */ + cmpldi cr1, rLEN, 16 + L(medium_tail2): + add rMEMP, rMEMP, rLEN +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memset.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memset.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memset.S 2014-05-29 13:07:41.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memset.S 2014-05-29 13:07:46.000000000 -0500 +@@ -34,8 +34,8 @@ + mr 10,3 + + /* Replicate byte to word. */ +- rlwimi 4,4,8,16,23 +- rlwimi 4,4,16,0,15 ++ insrdi 4,4,8,48 ++ insrdi 4,4,16,32 + ble cr6,L(small) /* If length <= 8, use short copy code. */ + + neg 0,3 +@@ -323,7 +323,7 @@ + clrldi 0,0,62 + beq L(medium_aligned) + +- /* Force 4-bytes alignment for SRC. */ ++ /* Force 4-bytes alignment for DST. */ + mtocrf 0x01,0 + subf 5,0,5 + 1: /* Copy 1 byte. */ diff --git a/SOURCES/glibc-ppc64le-33.patch b/SOURCES/glibc-ppc64le-33.patch new file mode 100644 index 0000000..9da11df --- /dev/null +++ b/SOURCES/glibc-ppc64le-33.patch @@ -0,0 +1,1255 @@ +# commit 466b03933234017473c12dd1d92bda5e7fe49df7 +# Author: Alan Modra +# Date: Sat Aug 17 18:48:36 2013 +0930 +# +# PowerPC LE memchr and memrchr +# http://sourceware.org/ml/libc-alpha/2013-08/msg00105.html +# +# Like strnlen, memchr and memrchr had a number of defects fixed by this +# patch as well as adding little-endian support. The first one I +# noticed was that the entry to the main loop needlessly checked for +# "are we done yet?" when we know the size is large enough that we can't +# be done. The second defect I noticed was that the main loop count was +# wrong, which in turn meant that the small loop needed to handle an +# extra word. Thirdly, there is nothing to say that the string can't +# wrap around zero, except of course that we'd normally hit a segfault +# on trying to read from address zero. Fixing that simplified a number +# of places: +# +# - /* Are we done already? */ +# - addi r9,r8,8 +# - cmpld r9,r7 +# - bge L(null) +# +# becomes +# +# + cmpld r8,r7 +# + beqlr +# +# However, the exit gets an extra test because I test for being on the +# last word then if so whether the byte offset is less than the end. +# Overall, the change is a win. +# +# Lastly, memrchr used the wrong cache hint. +# +# * sysdeps/powerpc/powerpc64/power7/memchr.S: Replace rlwimi with +# insrdi. Make better use of reg selection to speed exit slightly. +# Schedule entry path a little better. Remove useless "are we done" +# checks on entry to main loop. Handle wrapping around zero address. +# Correct main loop count. Handle single left-over word from main +# loop inline rather than by using loop_small. Remove extra word +# case in loop_small caused by wrong loop count. Add little-endian +# support. +# * sysdeps/powerpc/powerpc32/power7/memchr.S: Likewise. +# * sysdeps/powerpc/powerpc64/power7/memrchr.S: Likewise. Use proper +# cache hint. +# * sysdeps/powerpc/powerpc32/power7/memrchr.S: Likewise. +# * sysdeps/powerpc/powerpc64/power7/rawmemchr.S: Add little-endian +# support. Avoid rlwimi. +# * sysdeps/powerpc/powerpc32/power7/rawmemchr.S: Likewise. +# +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memchr.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memchr.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memchr.S 2014-05-29 13:09:17.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memchr.S 2014-05-29 13:13:37.000000000 -0500 +@@ -1,5 +1,5 @@ + /* Optimized memchr implementation for PowerPC32/POWER7 using cmpb insn. +- Copyright (C) 2010-2012 Free Software Foundation, Inc. ++ Copyright (C) 2010-2014 Free Software Foundation, Inc. + Contributed by Luis Machado . + This file is part of the GNU C Library. + +@@ -18,116 +18,118 @@ + . */ + + #include +-#include +-#include + + /* int [r3] memchr (char *s [r3], int byte [r4], int size [r5]) */ + .machine power7 +-ENTRY (BP_SYM (__memchr)) ++ENTRY (__memchr) + CALL_MCOUNT + dcbt 0,r3 + clrrwi r8,r3,2 +- rlwimi r4,r4,8,16,23 +- rlwimi r4,r4,16,0,15 ++ insrwi r4,r4,8,16 /* Replicate byte to word. */ + add r7,r3,r5 /* Calculate the last acceptable address. */ ++ insrwi r4,r4,16,0 + cmplwi r5,16 ++ li r9, -1 ++ rlwinm r6,r3,3,27,28 /* Calculate padding. */ ++ addi r7,r7,-1 ++#ifdef __LITTLE_ENDIAN__ ++ slw r9,r9,r6 ++#else ++ srw r9,r9,r6 ++#endif + ble L(small_range) + +- cmplw cr7,r3,r7 /* Compare the starting address (r3) with the +- ending address (r7). If (r3 >= r7), the size +- passed in is zero or negative. */ +- ble cr7,L(proceed) +- +- li r7,-1 /* Artificially set our ending address (r7) +- such that we will exit early. */ +-L(proceed): +- rlwinm r6,r3,3,27,28 /* Calculate padding. */ +- cmpli cr6,r6,0 /* cr6 == Do we have padding? */ + lwz r12,0(r8) /* Load word from memory. */ +- cmpb r10,r12,r4 /* Check for BYTE's in WORD1. */ +- beq cr6,L(proceed_no_padding) +- slw r10,r10,r6 +- srw r10,r10,r6 +-L(proceed_no_padding): +- cmplwi cr7,r10,0 /* If r10 == 0, no BYTEs have been found. */ ++ cmpb r3,r12,r4 /* Check for BYTEs in WORD1. */ ++ and r3,r3,r9 ++ clrlwi r5,r7,30 /* Byte count - 1 in last word. */ ++ clrrwi r7,r7,2 /* Address of last word. */ ++ cmplwi cr7,r3,0 /* If r3 == 0, no BYTEs have been found. */ + bne cr7,L(done) + +- /* Are we done already? */ +- addi r9,r8,4 +- cmplw cr6,r9,r7 +- bge cr6,L(null) +- + mtcrf 0x01,r8 + /* Are we now aligned to a doubleword boundary? If so, skip to + the main loop. Otherwise, go through the alignment code. */ +- + bt 29,L(loop_setup) + + /* Handle WORD2 of pair. */ + lwzu r12,4(r8) +- cmpb r10,r12,r4 +- cmplwi cr7,r10,0 ++ cmpb r3,r12,r4 ++ cmplwi cr7,r3,0 + bne cr7,L(done) + +- /* Are we done already? */ +- addi r9,r8,4 +- cmplw cr6,r9,r7 +- bge cr6,L(null) +- + L(loop_setup): +- sub r5,r7,r9 +- srwi r6,r5,3 /* Number of loop iterations. */ ++ /* The last word we want to read in the loop below is the one ++ containing the last byte of the string, ie. the word at ++ (s + size - 1) & ~3, or r7. The first word read is at ++ r8 + 4, we read 2 * cnt words, so the last word read will ++ be at r8 + 4 + 8 * cnt - 4. Solving for cnt gives ++ cnt = (r7 - r8) / 8 */ ++ sub r6,r7,r8 ++ srwi r6,r6,3 /* Number of loop iterations. */ + mtctr r6 /* Setup the counter. */ +- b L(loop) +- /* Main loop to look for BYTE backwards in the string. Since +- it's a small loop (< 8 instructions), align it to 32-bytes. */ +- .p2align 5 ++ ++ /* Main loop to look for BYTE in the string. Since ++ it's a small loop (8 instructions), align it to 32-bytes. */ ++ .align 5 + L(loop): + /* Load two words, compare and merge in a + single register for speed. This is an attempt + to speed up the byte-checking process for bigger strings. */ + lwz r12,4(r8) + lwzu r11,8(r8) +- cmpb r10,r12,r4 ++ cmpb r3,r12,r4 + cmpb r9,r11,r4 +- or r5,r9,r10 /* Merge everything in one word. */ +- cmplwi cr7,r5,0 ++ or r6,r9,r3 /* Merge everything in one word. */ ++ cmplwi cr7,r6,0 + bne cr7,L(found) + bdnz L(loop) + +- /* We're here because the counter reached 0, and that means we +- didn't have any matches for BYTE in the whole range. */ +- subi r11,r7,4 +- cmplw cr6,r8,r11 +- blt cr6,L(loop_small) +- b L(null) ++ /* We may have one more dword to read. */ ++ cmplw r8,r7 ++ beqlr + ++ lwzu r12,4(r8) ++ cmpb r3,r12,r4 ++ cmplwi cr6,r3,0 ++ bne cr6,L(done) ++ blr ++ ++ .align 4 ++L(found): + /* OK, one (or both) of the words contains BYTE. Check + the first word and decrement the address in case the first + word really contains BYTE. */ +- .align 4 +-L(found): +- cmplwi cr6,r10,0 ++ cmplwi cr6,r3,0 + addi r8,r8,-4 + bne cr6,L(done) + + /* BYTE must be in the second word. Adjust the address +- again and move the result of cmpb to r10 so we can calculate the ++ again and move the result of cmpb to r3 so we can calculate the + pointer. */ + +- mr r10,r9 ++ mr r3,r9 + addi r8,r8,4 + +- /* r10 has the output of the cmpb instruction, that is, it contains ++ /* r3 has the output of the cmpb instruction, that is, it contains + 0xff in the same position as BYTE in the original + word from the string. Use that to calculate the pointer. + We need to make sure BYTE is *before* the end of the range. */ + L(done): +- cntlzw r0,r10 /* Count leading zeroes before the match. */ +- srwi r0,r0,3 /* Convert leading zeroes to bytes. */ ++#ifdef __LITTLE_ENDIAN__ ++ addi r0,r3,-1 ++ andc r0,r0,r3 ++ popcntw r0,r0 /* Count trailing zeros. */ ++#else ++ cntlzw r0,r3 /* Count leading zeros before the match. */ ++#endif ++ cmplw r8,r7 /* Are we on the last word? */ ++ srwi r0,r0,3 /* Convert leading/trailing zeros to bytes. */ + add r3,r8,r0 +- cmplw r3,r7 +- bge L(null) ++ cmplw cr7,r0,r5 /* If on the last dword, check byte offset. */ ++ bnelr ++ blelr cr7 ++ li r3,0 + blr + + .align 4 +@@ -139,69 +141,44 @@ + .align 4 + L(small_range): + cmplwi r5,0 +- rlwinm r6,r3,3,27,28 /* Calculate padding. */ +- beq L(null) /* This branch is for the cmplwi r5,0 above */ ++ beq L(null) + lwz r12,0(r8) /* Load word from memory. */ +- cmplwi cr6,r6,0 /* cr6 == Do we have padding? */ +- cmpb r10,r12,r4 /* Check for BYTE in DWORD1. */ +- beq cr6,L(small_no_padding) +- slw r10,r10,r6 +- srw r10,r10,r6 +-L(small_no_padding): +- cmplwi cr7,r10,0 ++ cmpb r3,r12,r4 /* Check for BYTE in DWORD1. */ ++ and r3,r3,r9 ++ cmplwi cr7,r3,0 ++ clrlwi r5,r7,30 /* Byte count - 1 in last word. */ ++ clrrwi r7,r7,2 /* Address of last word. */ ++ cmplw r8,r7 /* Are we done already? */ + bne cr7,L(done) ++ beqlr + +- /* Are we done already? */ +- addi r9,r8,4 +- cmplw r9,r7 +- bge L(null) +- +-L(loop_small): /* loop_small has been unrolled. */ + lwzu r12,4(r8) +- cmpb r10,r12,r4 +- addi r9,r8,4 +- cmplwi cr6,r10,0 +- cmplw r9,r7 ++ cmpb r3,r12,r4 ++ cmplwi cr6,r3,0 ++ cmplw r8,r7 + bne cr6,L(done) +- bge L(null) ++ beqlr + + lwzu r12,4(r8) +- cmpb r10,r12,r4 +- addi r9,r8,4 +- cmplwi cr6,r10,0 +- cmplw r9,r7 ++ cmpb r3,r12,r4 ++ cmplwi cr6,r3,0 ++ cmplw r8,r7 + bne cr6,L(done) +- bge L(null) ++ beqlr + + lwzu r12,4(r8) +- cmpb r10,r12,r4 +- addi r9,r8,4 +- cmplwi cr6,r10,0 +- cmplw r9,r7 ++ cmpb r3,r12,r4 ++ cmplwi cr6,r3,0 ++ cmplw r8,r7 + bne cr6,L(done) +- bge L(null) ++ beqlr + + lwzu r12,4(r8) +- cmpb r10,r12,r4 +- addi r9,r8,4 +- cmplwi cr6,r10,0 +- cmplw r9,r7 ++ cmpb r3,r12,r4 ++ cmplwi cr6,r3,0 + bne cr6,L(done) +- bge L(null) +- +- /* For most cases we will never get here. Under some combinations of +- padding + length there is a leftover word that still needs to be +- checked. */ +- lwzu r12,4(r8) +- cmpb r10,r12,r4 +- addi r9,r8,4 +- cmplwi cr6,r10,0 +- bne cr6,L(done) +- +- /* save a branch and exit directly */ +- li r3,0 + blr + +-END (BP_SYM (__memchr)) +-weak_alias (BP_SYM (__memchr), BP_SYM(memchr)) ++END (__memchr) ++weak_alias (__memchr, memchr) + libc_hidden_builtin_def (memchr) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memrchr.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memrchr.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memrchr.S 2014-05-29 13:09:17.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memrchr.S 2014-05-29 13:13:47.000000000 -0500 +@@ -1,5 +1,5 @@ + /* Optimized memrchr implementation for PowerPC32/POWER7 using cmpb insn. +- Copyright (C) 2010 Free Software Foundation, Inc. ++ Copyright (C) 2010-2014 Free Software Foundation, Inc. + Contributed by Luis Machado . + This file is part of the GNU C Library. + +@@ -18,124 +18,136 @@ + . */ + + #include +-#include +-#include + + /* int [r3] memrchr (char *s [r3], int byte [r4], int size [r5]) */ + .machine power7 +-ENTRY (BP_SYM (__memrchr)) ++ENTRY (__memrchr) + CALL_MCOUNT +- dcbt 0,r3 +- mr r7,r3 +- add r3,r7,r5 /* Calculate the last acceptable address. */ +- cmplw cr7,r3,r7 /* Is the address equal or less than r3? */ ++ add r7,r3,r5 /* Calculate the last acceptable address. */ ++ neg r0,r7 ++ addi r7,r7,-1 ++ mr r10,r3 ++ clrrwi r6,r7,7 ++ li r9,3<<5 ++ dcbt r9,r6,16 /* Stream hint, decreasing addresses. */ + + /* Replicate BYTE to word. */ +- rlwimi r4,r4,8,16,23 +- rlwimi r4,r4,16,0,15 +- bge cr7,L(proceed) +- +- li r3,-1 /* Make r11 the biggest if r4 <= 0. */ +-L(proceed): ++ insrwi r4,r4,8,16 ++ insrwi r4,r4,16,0 + li r6,-4 +- addi r9,r3,-1 +- clrrwi r8,r9,2 +- addi r8,r8,4 +- neg r0,r3 ++ li r9,-1 + rlwinm r0,r0,3,27,28 /* Calculate padding. */ +- ++ clrrwi r8,r7,2 ++ srw r9,r9,r0 + cmplwi r5,16 ++ clrrwi r0,r10,2 + ble L(small_range) + +- lwbrx r12,r8,r6 /* Load reversed word from memory. */ +- cmpb r10,r12,r4 /* Check for BYTE in WORD1. */ +- slw r10,r10,r0 +- srw r10,r10,r0 +- cmplwi cr7,r10,0 /* If r10 == 0, no BYTE's have been found. */ ++#ifdef __LITTLE_ENDIAN__ ++ lwzx r12,0,r8 ++#else ++ lwbrx r12,0,r8 /* Load reversed word from memory. */ ++#endif ++ cmpb r3,r12,r4 /* Check for BYTE in WORD1. */ ++ and r3,r3,r9 ++ cmplwi cr7,r3,0 /* If r3 == 0, no BYTEs have been found. */ + bne cr7,L(done) + +- /* Are we done already? */ +- addi r9,r8,-4 +- cmplw cr6,r9,r7 +- ble cr6,L(null) +- + mtcrf 0x01,r8 + /* Are we now aligned to a doubleword boundary? If so, skip to + the main loop. Otherwise, go through the alignment code. */ +- mr r8,r9 +- bt 29,L(loop_setup) ++ bf 29,L(loop_setup) + + /* Handle WORD2 of pair. */ ++#ifdef __LITTLE_ENDIAN__ ++ lwzx r12,r8,r6 ++#else + lwbrx r12,r8,r6 +- cmpb r10,r12,r4 +- cmplwi cr7,r10,0 +- bne cr7,L(done) +- +- /* Are we done already? */ ++#endif + addi r8,r8,-4 +- cmplw cr6,r8,r7 +- ble cr6,L(null) ++ cmpb r3,r12,r4 ++ cmplwi cr7,r3,0 ++ bne cr7,L(done) + + L(loop_setup): +- li r0,-8 +- sub r5,r8,r7 +- srwi r9,r5,3 /* Number of loop iterations. */ ++ /* The last word we want to read in the loop below is the one ++ containing the first byte of the string, ie. the word at ++ s & ~3, or r0. The first word read is at r8 - 4, we ++ read 2 * cnt words, so the last word read will be at ++ r8 - 4 - 8 * cnt + 4. Solving for cnt gives ++ cnt = (r8 - r0) / 8 */ ++ sub r5,r8,r0 ++ addi r8,r8,-4 ++ srwi r9,r5,3 /* Number of loop iterations. */ + mtctr r9 /* Setup the counter. */ +- b L(loop) +- /* Main loop to look for BYTE backwards in the string. Since it's a +- small loop (< 8 instructions), align it to 32-bytes. */ +- .p2align 5 ++ ++ /* Main loop to look for BYTE backwards in the string. ++ FIXME: Investigate whether 32 byte align helps with this ++ 9 instruction loop. */ ++ .align 5 + L(loop): + /* Load two words, compare and merge in a + single register for speed. This is an attempt + to speed up the byte-checking process for bigger strings. */ + +- lwbrx r12,r8,r6 +- lwbrx r11,r8,r0 +- addi r8,r8,-4 +- cmpb r10,r12,r4 ++#ifdef __LITTLE_ENDIAN__ ++ lwzx r12,0,r8 ++ lwzx r11,r8,r6 ++#else ++ lwbrx r12,0,r8 ++ lwbrx r11,r8,r6 ++#endif ++ cmpb r3,r12,r4 + cmpb r9,r11,r4 +- or r5,r9,r10 /* Merge everything in one word. */ ++ or r5,r9,r3 /* Merge everything in one word. */ + cmplwi cr7,r5,0 + bne cr7,L(found) +- addi r8,r8,-4 ++ addi r8,r8,-8 + bdnz L(loop) +- /* We're here because the counter reached 0, and that means we +- didn't have any matches for BYTE in the whole range. Just return +- the original range. */ +- addi r9,r8,4 +- cmplw cr6,r9,r7 +- bgt cr6,L(loop_small) +- b L(null) + +- /* OK, one (or both) of the words contains BYTE. Check +- the first word and decrement the address in case the first +- word really contains BYTE. */ ++ /* We may have one more word to read. */ ++ cmplw r8,r0 ++ bnelr ++ ++#ifdef __LITTLE_ENDIAN__ ++ lwzx r12,0,r8 ++#else ++ lwbrx r12,0,r8 ++#endif ++ cmpb r3,r12,r4 ++ cmplwi cr7,r3,0 ++ bne cr7,L(done) ++ blr ++ + .align 4 + L(found): +- cmplwi cr6,r10,0 +- addi r8,r8,4 ++ /* OK, one (or both) of the words contains BYTE. Check ++ the first word. */ ++ cmplwi cr6,r3,0 + bne cr6,L(done) + + /* BYTE must be in the second word. Adjust the address +- again and move the result of cmpb to r10 so we can calculate the ++ again and move the result of cmpb to r3 so we can calculate the + pointer. */ + +- mr r10,r9 ++ mr r3,r9 + addi r8,r8,-4 + +- /* r10 has the output of the cmpb instruction, that is, it contains ++ /* r3 has the output of the cmpb instruction, that is, it contains + 0xff in the same position as BYTE in the original + word from the string. Use that to calculate the pointer. + We need to make sure BYTE is *before* the end of the + range. */ + L(done): +- cntlzw r0,r10 /* Count leading zeroes before the match. */ +- srwi r6,r0,3 /* Convert leading zeroes to bytes. */ +- addi r0,r6,1 ++ cntlzw r9,r3 /* Count leading zeros before the match. */ ++ cmplw r8,r0 /* Are we on the last word? */ ++ srwi r6,r9,3 /* Convert leading zeros to bytes. */ ++ addi r0,r6,-3 + sub r3,r8,r0 +- cmplw r3,r7 +- blt L(null) ++ cmplw cr7,r3,r10 ++ bnelr ++ bgelr cr7 ++ li r3,0 + blr + + .align 4 +@@ -149,29 +161,36 @@ + cmplwi r5,0 + beq L(null) + +- lwbrx r12,r8,r6 /* Load reversed word from memory. */ +- cmpb r10,r12,r4 /* Check for null bytes in WORD1. */ +- slw r10,r10,r0 +- srw r10,r10,r0 +- cmplwi cr7,r10,0 ++#ifdef __LITTLE_ENDIAN__ ++ lwzx r12,0,r8 ++#else ++ lwbrx r12,0,r8 /* Load reversed word from memory. */ ++#endif ++ cmpb r3,r12,r4 /* Check for BYTE in WORD1. */ ++ and r3,r3,r9 ++ cmplwi cr7,r3,0 + bne cr7,L(done) + ++ /* Are we done already? */ ++ cmplw r8,r0 + addi r8,r8,-4 +- cmplw r8,r7 +- ble L(null) +- b L(loop_small) ++ beqlr + +- .p2align 5 ++ .align 5 + L(loop_small): +- lwbrx r12,r8,r6 +- cmpb r10,r12,r4 +- cmplwi cr6,r10,0 +- bne cr6,L(done) ++#ifdef __LITTLE_ENDIAN__ ++ lwzx r12,0,r8 ++#else ++ lwbrx r12,0,r8 ++#endif ++ cmpb r3,r12,r4 ++ cmplw r8,r0 ++ cmplwi cr7,r3,0 ++ bne cr7,L(done) + addi r8,r8,-4 +- cmplw r8,r7 +- ble L(null) +- b L(loop_small) ++ bne L(loop_small) ++ blr + +-END (BP_SYM (__memrchr)) +-weak_alias (BP_SYM (__memrchr), BP_SYM(memrchr)) ++END (__memrchr) ++weak_alias (__memrchr, memrchr) + libc_hidden_builtin_def (memrchr) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/rawmemchr.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/rawmemchr.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/rawmemchr.S 2014-05-29 13:09:17.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/rawmemchr.S 2014-05-29 13:09:19.000000000 -0500 +@@ -29,16 +29,21 @@ + clrrwi r8,r3,2 /* Align the address to word boundary. */ + + /* Replicate byte to word. */ +- rlwimi r4,r4,8,16,23 +- rlwimi r4,r4,16,0,15 ++ rldimi r4,r4,8,48 ++ rldimi r4,r4,16,32 + + /* Now r4 has a word of c bytes. */ + + rlwinm r6,r3,3,27,28 /* Calculate padding. */ + lwz r12,0(r8) /* Load word from memory. */ + cmpb r5,r12,r4 /* Compare each byte against c byte. */ ++#ifdef __LITTLE_ENDIAN__ ++ srw r5,r5,r6 ++ slw r5,r5,r6 ++#else + slw r5,r5,r6 /* Move left to discard ignored bits. */ + srw r5,r5,r6 /* Bring the bits back as zeros. */ ++#endif + cmpwi cr7,r5,0 /* If r5 == 0, no c bytes have been found. */ + bne cr7,L(done) + +@@ -92,8 +97,14 @@ + word from the string. Use that fact to find out what is + the position of the byte inside the string. */ + L(done): ++#ifdef __LITTLE_ENDIAN__ ++ addi r0,r5,-1 ++ andc r0,r0,r5 ++ popcntw r0,r0 ++#else + cntlzw r0,r5 /* Count leading zeros before the match. */ +- srwi r0,r0,3 /* Convert leading zeroes to bytes. */ ++#endif ++ srwi r0,r0,3 /* Convert leading zeros to bytes. */ + add r3,r8,r0 /* Return address of the matching char. */ + blr + END (BP_SYM (__rawmemchr)) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memchr.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memchr.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memchr.S 2014-05-29 13:09:17.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memchr.S 2014-05-29 13:13:57.000000000 -0500 +@@ -1,5 +1,5 @@ + /* Optimized memchr implementation for PowerPC64/POWER7 using cmpb insn. +- Copyright (C) 2010-2012 Free Software Foundation, Inc. ++ Copyright (C) 2010-2014 Free Software Foundation, Inc. + Contributed by Luis Machado . + This file is part of the GNU C Library. + +@@ -18,118 +18,119 @@ + . */ + + #include +-#include +-#include + + /* int [r3] memchr (char *s [r3], int byte [r4], int size [r5]) */ + .machine power7 +-ENTRY (BP_SYM (__memchr)) +- CALL_MCOUNT 2 ++ENTRY (__memchr) ++ CALL_MCOUNT 3 + dcbt 0,r3 + clrrdi r8,r3,3 +- rlwimi r4,r4,8,16,23 +- rlwimi r4,r4,16,0,15 ++ insrdi r4,r4,8,48 + add r7,r3,r5 /* Calculate the last acceptable address. */ ++ insrdi r4,r4,16,32 + cmpldi r5,32 ++ li r9, -1 ++ rlwinm r6,r3,3,26,28 /* Calculate padding. */ + insrdi r4,r4,32,0 ++ addi r7,r7,-1 ++#ifdef __LITTLE_ENDIAN__ ++ sld r9,r9,r6 ++#else ++ srd r9,r9,r6 ++#endif + ble L(small_range) + +- cmpld cr7,r3,r7 /* Compare the starting address (r3) with the +- ending address (r7). If (r3 >= r7), +- the size passed in was zero or negative. */ +- ble cr7,L(proceed) +- +- li r7,-1 /* Artificially set our ending address (r7) +- such that we will exit early. */ +- +-L(proceed): +- rlwinm r6,r3,3,26,28 /* Calculate padding. */ +- cmpldi cr6,r6,0 /* cr6 == Do we have padding? */ + ld r12,0(r8) /* Load doubleword from memory. */ +- cmpb r10,r12,r4 /* Check for BYTEs in DWORD1. */ +- beq cr6,L(proceed_no_padding) +- sld r10,r10,r6 +- srd r10,r10,r6 +-L(proceed_no_padding): +- cmpldi cr7,r10,0 /* Does r10 indicate we got a hit? */ ++ cmpb r3,r12,r4 /* Check for BYTEs in DWORD1. */ ++ and r3,r3,r9 ++ clrldi r5,r7,61 /* Byte count - 1 in last dword. */ ++ clrrdi r7,r7,3 /* Address of last doubleword. */ ++ cmpldi cr7,r3,0 /* Does r3 indicate we got a hit? */ + bne cr7,L(done) + +- /* See if we are at the last acceptable address yet. */ +- addi r9,r8,8 +- cmpld cr6,r9,r7 +- bge cr6,L(null) +- + mtcrf 0x01,r8 + /* Are we now aligned to a quadword boundary? If so, skip to + the main loop. Otherwise, go through the alignment code. */ +- + bt 28,L(loop_setup) + + /* Handle DWORD2 of pair. */ + ldu r12,8(r8) +- cmpb r10,r12,r4 +- cmpldi cr7,r10,0 ++ cmpb r3,r12,r4 ++ cmpldi cr7,r3,0 + bne cr7,L(done) + +- /* Are we done already? */ +- addi r9,r8,8 +- cmpld cr6,r9,r7 +- bge cr6,L(null) +- + L(loop_setup): +- sub r5,r7,r9 +- srdi r6,r5,4 /* Number of loop iterations. */ ++ /* The last dword we want to read in the loop below is the one ++ containing the last byte of the string, ie. the dword at ++ (s + size - 1) & ~7, or r7. The first dword read is at ++ r8 + 8, we read 2 * cnt dwords, so the last dword read will ++ be at r8 + 8 + 16 * cnt - 8. Solving for cnt gives ++ cnt = (r7 - r8) / 16 */ ++ sub r6,r7,r8 ++ srdi r6,r6,4 /* Number of loop iterations. */ + mtctr r6 /* Setup the counter. */ +- b L(loop) +- /* Main loop to look for BYTE backwards in the string. Since +- it's a small loop (< 8 instructions), align it to 32-bytes. */ +- .p2align 5 ++ ++ /* Main loop to look for BYTE in the string. Since ++ it's a small loop (8 instructions), align it to 32-bytes. */ ++ .align 5 + L(loop): + /* Load two doublewords, compare and merge in a + single register for speed. This is an attempt + to speed up the byte-checking process for bigger strings. */ + ld r12,8(r8) + ldu r11,16(r8) +- cmpb r10,r12,r4 ++ cmpb r3,r12,r4 + cmpb r9,r11,r4 +- or r5,r9,r10 /* Merge everything in one doubleword. */ +- cmpldi cr7,r5,0 ++ or r6,r9,r3 /* Merge everything in one doubleword. */ ++ cmpldi cr7,r6,0 + bne cr7,L(found) + bdnz L(loop) + +- /* We're here because the counter reached 0, and that means we +- didn't have any matches for BYTE in the whole range. */ +- subi r11,r7,8 +- cmpld cr6,r8,r11 +- blt cr6,L(loop_small) +- b L(null) ++ /* We may have one more dword to read. */ ++ cmpld r8,r7 ++ beqlr + ++ ldu r12,8(r8) ++ cmpb r3,r12,r4 ++ cmpldi cr6,r3,0 ++ bne cr6,L(done) ++ blr ++ ++ .align 4 ++L(found): + /* OK, one (or both) of the doublewords contains BYTE. Check + the first doubleword and decrement the address in case the first + doubleword really contains BYTE. */ +- .align 4 +-L(found): +- cmpldi cr6,r10,0 ++ cmpldi cr6,r3,0 + addi r8,r8,-8 + bne cr6,L(done) + + /* BYTE must be in the second doubleword. Adjust the address +- again and move the result of cmpb to r10 so we can calculate the ++ again and move the result of cmpb to r3 so we can calculate the + pointer. */ + +- mr r10,r9 ++ mr r3,r9 + addi r8,r8,8 + +- /* r10 has the output of the cmpb instruction, that is, it contains ++ /* r3 has the output of the cmpb instruction, that is, it contains + 0xff in the same position as BYTE in the original + doubleword from the string. Use that to calculate the pointer. + We need to make sure BYTE is *before* the end of the range. */ + L(done): +- cntlzd r0,r10 /* Count leading zeroes before the match. */ +- srdi r0,r0,3 /* Convert leading zeroes to bytes. */ ++#ifdef __LITTLE_ENDIAN__ ++ addi r0,r3,-1 ++ andc r0,r0,r3 ++ popcntd r0,r0 /* Count trailing zeros. */ ++#else ++ cntlzd r0,r3 /* Count leading zeros before the match. */ ++#endif ++ cmpld r8,r7 /* Are we on the last dword? */ ++ srdi r0,r0,3 /* Convert leading/trailing zeros to bytes. */ + add r3,r8,r0 +- cmpld r3,r7 +- bge L(null) ++ cmpld cr7,r0,r5 /* If on the last dword, check byte offset. */ ++ bnelr ++ blelr cr7 ++ li r3,0 + blr + + .align 4 +@@ -141,67 +142,44 @@ + .align 4 + L(small_range): + cmpldi r5,0 +- rlwinm r6,r3,3,26,28 /* Calculate padding. */ +- beq L(null) /* This branch is for the cmpldi r5,0 above. */ ++ beq L(null) + ld r12,0(r8) /* Load word from memory. */ +- cmpldi cr6,r6,0 /* cr6 == Do we have padding? */ +- cmpb r10,r12,r4 /* Check for BYTE in DWORD1. */ +- /* If no padding, skip the shifts. */ +- beq cr6,L(small_no_padding) +- sld r10,r10,r6 +- srd r10,r10,r6 +-L(small_no_padding): +- cmpldi cr7,r10,0 ++ cmpb r3,r12,r4 /* Check for BYTE in DWORD1. */ ++ and r3,r3,r9 ++ cmpldi cr7,r3,0 ++ clrldi r5,r7,61 /* Byte count - 1 in last dword. */ ++ clrrdi r7,r7,3 /* Address of last doubleword. */ ++ cmpld r8,r7 /* Are we done already? */ + bne cr7,L(done) +- +- /* Are we done already? */ +- addi r9,r8,8 +- cmpld r9,r7 +- bge L(null) +- /* If we're not done, drop through into loop_small. */ +- +-L(loop_small): /* loop_small has been unrolled. */ +- ldu r12,8(r8) +- cmpb r10,r12,r4 +- addi r9,r8,8 +- cmpldi cr6,r10,0 +- cmpld r9,r7 +- bne cr6,L(done) /* Found something. */ +- bge L(null) /* Hit end of string (length). */ ++ beqlr + + ldu r12,8(r8) +- cmpb r10,r12,r4 +- addi r9,r8,8 +- cmpldi cr6,r10,0 +- cmpld r9,r7 ++ cmpb r3,r12,r4 ++ cmpldi cr6,r3,0 ++ cmpld r8,r7 + bne cr6,L(done) /* Found something. */ +- bge L(null) ++ beqlr /* Hit end of string (length). */ + + ldu r12,8(r8) +- subi r11,r7,8 +- cmpb r10,r12,r4 +- cmpldi cr6,r10,0 +- ori r2,r2,0 /* Force a dispatch group. */ ++ cmpb r3,r12,r4 ++ cmpldi cr6,r3,0 ++ cmpld r8,r7 + bne cr6,L(done) ++ beqlr + +- cmpld r8,r11 /* At end of range? */ +- bge L(null) +- +- /* For most cases we will never get here. Under some combinations of +- padding + length there is a leftover double that still needs to be +- checked. */ +- ldu r12,8(r8) +- cmpb r10,r12,r4 +- addi r9,r8,8 +- cmpldi cr6,r10,0 +- cmpld r9,r7 +- bne cr6,L(done) /* Found something. */ ++ ldu r12,8(r8) ++ cmpb r3,r12,r4 ++ cmpldi cr6,r3,0 ++ cmpld r8,r7 ++ bne cr6,L(done) ++ beqlr + +- /* Save a branch and exit directly. */ +- li r3,0 ++ ldu r12,8(r8) ++ cmpb r3,r12,r4 ++ cmpldi cr6,r3,0 ++ bne cr6,L(done) + blr + +- +-END (BP_SYM (__memchr)) +-weak_alias (BP_SYM (__memchr), BP_SYM(memchr)) ++END (__memchr) ++weak_alias (__memchr, memchr) + libc_hidden_builtin_def (memchr) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memrchr.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memrchr.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memrchr.S 2014-05-29 13:09:17.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memrchr.S 2014-05-29 13:14:06.000000000 -0500 +@@ -1,5 +1,5 @@ + /* Optimized memrchr implementation for PowerPC64/POWER7 using cmpb insn. +- Copyright (C) 2010 Free Software Foundation, Inc. ++ Copyright (C) 2010-2014 Free Software Foundation, Inc. + Contributed by Luis Machado . + This file is part of the GNU C Library. + +@@ -18,125 +18,137 @@ + . */ + + #include +-#include +-#include + + /* int [r3] memrchr (char *s [r3], int byte [r4], int size [r5]) */ + .machine power7 +-ENTRY (BP_SYM (__memrchr)) +- CALL_MCOUNT +- dcbt 0,r3 +- mr r7,r3 +- add r3,r7,r5 /* Calculate the last acceptable address. */ +- cmpld cr7,r3,r7 /* Is the address equal or less than r3? */ ++ENTRY (__memrchr) ++ CALL_MCOUNT 3 ++ add r7,r3,r5 /* Calculate the last acceptable address. */ ++ neg r0,r7 ++ addi r7,r7,-1 ++ mr r10,r3 ++ clrrdi r6,r7,7 ++ li r9,3<<5 ++ dcbt r9,r6,8 /* Stream hint, decreasing addresses. */ + + /* Replicate BYTE to doubleword. */ +- rlwimi r4,r4,8,16,23 +- rlwimi r4,r4,16,0,15 ++ insrdi r4,r4,8,48 ++ insrdi r4,r4,16,32 + insrdi r4,r4,32,0 +- bge cr7,L(proceed) +- +- li r3,-1 /* Make r11 the biggest if r4 <= 0. */ +-L(proceed): + li r6,-8 +- addi r9,r3,-1 +- clrrdi r8,r9,3 +- addi r8,r8,8 +- neg r0,r3 ++ li r9,-1 + rlwinm r0,r0,3,26,28 /* Calculate padding. */ +- ++ clrrdi r8,r7,3 ++ srd r9,r9,r0 + cmpldi r5,32 ++ clrrdi r0,r10,3 + ble L(small_range) + +- ldbrx r12,r8,r6 /* Load reversed doubleword from memory. */ +- cmpb r10,r12,r4 /* Check for BYTE in DWORD1. */ +- sld r10,r10,r0 +- srd r10,r10,r0 +- cmpldi cr7,r10,0 /* If r10 == 0, no BYTE's have been found. */ ++#ifdef __LITTLE_ENDIAN__ ++ ldx r12,0,r8 ++#else ++ ldbrx r12,0,r8 /* Load reversed doubleword from memory. */ ++#endif ++ cmpb r3,r12,r4 /* Check for BYTE in DWORD1. */ ++ and r3,r3,r9 ++ cmpldi cr7,r3,0 /* If r3 == 0, no BYTEs have been found. */ + bne cr7,L(done) + +- /* Are we done already? */ +- addi r9,r8,-8 +- cmpld cr6,r9,r7 +- ble cr6,L(null) +- + mtcrf 0x01,r8 +- /* Are we now aligned to a doubleword boundary? If so, skip to ++ /* Are we now aligned to a quadword boundary? If so, skip to + the main loop. Otherwise, go through the alignment code. */ +- mr r8,r9 +- bt 28,L(loop_setup) ++ bf 28,L(loop_setup) + + /* Handle DWORD2 of pair. */ ++#ifdef __LITTLE_ENDIAN__ ++ ldx r12,r8,r6 ++#else + ldbrx r12,r8,r6 +- cmpb r10,r12,r4 +- cmpldi cr7,r10,0 +- bne cr7,L(done) +- +- /* Are we done already. */ ++#endif + addi r8,r8,-8 +- cmpld cr6,r8,r7 +- ble cr6,L(null) ++ cmpb r3,r12,r4 ++ cmpldi cr7,r3,0 ++ bne cr7,L(done) + + L(loop_setup): +- li r0,-16 +- sub r5,r8,r7 +- srdi r9,r5,4 /* Number of loop iterations. */ ++ /* The last dword we want to read in the loop below is the one ++ containing the first byte of the string, ie. the dword at ++ s & ~7, or r0. The first dword read is at r8 - 8, we ++ read 2 * cnt dwords, so the last dword read will be at ++ r8 - 8 - 16 * cnt + 8. Solving for cnt gives ++ cnt = (r8 - r0) / 16 */ ++ sub r5,r8,r0 ++ addi r8,r8,-8 ++ srdi r9,r5,4 /* Number of loop iterations. */ + mtctr r9 /* Setup the counter. */ +- b L(loop) +- /* Main loop to look for BYTE backwards in the string. Since it's a +- small loop (< 8 instructions), align it to 32-bytes. */ +- .p2align 5 ++ ++ /* Main loop to look for BYTE backwards in the string. ++ FIXME: Investigate whether 32 byte align helps with this ++ 9 instruction loop. */ ++ .align 5 + L(loop): + /* Load two doublewords, compare and merge in a + single register for speed. This is an attempt + to speed up the byte-checking process for bigger strings. */ + +- ldbrx r12,r8,r6 +- ldbrx r11,r8,r0 +- addi r8,r8,-8 +- cmpb r10,r12,r4 ++#ifdef __LITTLE_ENDIAN__ ++ ldx r12,0,r8 ++ ldx r11,r8,r6 ++#else ++ ldbrx r12,0,r8 ++ ldbrx r11,r8,r6 ++#endif ++ cmpb r3,r12,r4 + cmpb r9,r11,r4 +- or r5,r9,r10 /* Merge everything in one doubleword. */ ++ or r5,r9,r3 /* Merge everything in one doubleword. */ + cmpldi cr7,r5,0 + bne cr7,L(found) +- addi r8,r8,-8 ++ addi r8,r8,-16 + bdnz L(loop) +- /* We're here because the counter reached 0, and that means we +- didn't have any matches for BYTE in the whole range. Just return +- the original range. */ +- addi r9,r8,8 +- cmpld cr6,r9,r7 +- bgt cr6,L(loop_small) +- b L(null) +- +- /* OK, one (or both) of the words contains BYTE. Check +- the first word and decrement the address in case the first +- word really contains BYTE. */ ++ ++ /* We may have one more word to read. */ ++ cmpld r8,r0 ++ bnelr ++ ++#ifdef __LITTLE_ENDIAN__ ++ ldx r12,0,r8 ++#else ++ ldbrx r12,0,r8 ++#endif ++ cmpb r3,r12,r4 ++ cmpldi cr7,r3,0 ++ bne cr7,L(done) ++ blr ++ + .align 4 + L(found): +- cmpldi cr6,r10,0 +- addi r8,r8,8 ++ /* OK, one (or both) of the dwords contains BYTE. Check ++ the first dword. */ ++ cmpldi cr6,r3,0 + bne cr6,L(done) + + /* BYTE must be in the second word. Adjust the address +- again and move the result of cmpb to r10 so we can calculate the ++ again and move the result of cmpb to r3 so we can calculate the + pointer. */ + +- mr r10,r9 ++ mr r3,r9 + addi r8,r8,-8 + +- /* r10 has the output of the cmpb instruction, that is, it contains +- 0xff in the same position as the BYTE in the original ++ /* r3 has the output of the cmpb instruction, that is, it contains ++ 0xff in the same position as BYTE in the original + word from the string. Use that to calculate the pointer. + We need to make sure BYTE is *before* the end of the + range. */ + L(done): +- cntlzd r0,r10 /* Count leading zeroes before the match. */ +- srdi r6,r0,3 /* Convert leading zeroes to bytes. */ +- addi r0,r6,1 ++ cntlzd r9,r3 /* Count leading zeros before the match. */ ++ cmpld r8,r0 /* Are we on the last word? */ ++ srdi r6,r9,3 /* Convert leading zeros to bytes. */ ++ addi r0,r6,-7 + sub r3,r8,r0 +- cmpld r3,r7 +- blt L(null) ++ cmpld cr7,r3,r10 ++ bnelr ++ bgelr cr7 ++ li r3,0 + blr + + .align 4 +@@ -150,30 +162,36 @@ + cmpldi r5,0 + beq L(null) + +- ldbrx r12,r8,r6 /* Load reversed doubleword from memory. */ +- cmpb r10,r12,r4 /* Check for BYTE in DWORD1. */ +- sld r10,r10,r0 +- srd r10,r10,r0 +- cmpldi cr7,r10,0 ++#ifdef __LITTLE_ENDIAN__ ++ ldx r12,0,r8 ++#else ++ ldbrx r12,0,r8 /* Load reversed doubleword from memory. */ ++#endif ++ cmpb r3,r12,r4 /* Check for BYTE in DWORD1. */ ++ and r3,r3,r9 ++ cmpldi cr7,r3,0 + bne cr7,L(done) + + /* Are we done already? */ ++ cmpld r8,r0 + addi r8,r8,-8 +- cmpld r8,r7 +- ble L(null) +- b L(loop_small) ++ beqlr + +- .p2align 5 ++ .align 5 + L(loop_small): +- ldbrx r12,r8,r6 +- cmpb r10,r12,r4 +- cmpldi cr6,r10,0 +- bne cr6,L(done) ++#ifdef __LITTLE_ENDIAN__ ++ ldx r12,0,r8 ++#else ++ ldbrx r12,0,r8 ++#endif ++ cmpb r3,r12,r4 ++ cmpld r8,r0 ++ cmpldi cr7,r3,0 ++ bne cr7,L(done) + addi r8,r8,-8 +- cmpld r8,r7 +- ble L(null) +- b L(loop_small) ++ bne L(loop_small) ++ blr + +-END (BP_SYM (__memrchr)) +-weak_alias (BP_SYM (__memrchr), BP_SYM(memrchr)) ++END (__memrchr) ++weak_alias (__memrchr, memrchr) + libc_hidden_builtin_def (memrchr) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/rawmemchr.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/rawmemchr.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/rawmemchr.S 2014-05-29 13:09:17.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/rawmemchr.S 2014-05-29 13:09:19.000000000 -0500 +@@ -29,8 +29,8 @@ + clrrdi r8,r3,3 /* Align the address to doubleword boundary. */ + + /* Replicate byte to doubleword. */ +- rlwimi r4,r4,8,16,23 +- rlwimi r4,r4,16,0,15 ++ insrdi r4,r4,8,48 ++ insrdi r4,r4,16,32 + insrdi r4,r4,32,0 + + /* Now r4 has a doubleword of c bytes. */ +@@ -38,8 +38,13 @@ + rlwinm r6,r3,3,26,28 /* Calculate padding. */ + ld r12,0(r8) /* Load doubleword from memory. */ + cmpb r5,r12,r4 /* Compare each byte against c byte. */ ++#ifdef __LITTLE_ENDIAN__ ++ srd r5,r5,r6 ++ sld r5,r5,r6 ++#else + sld r5,r5,r6 /* Move left to discard ignored bits. */ + srd r5,r5,r6 /* Bring the bits back as zeros. */ ++#endif + cmpdi cr7,r5,0 /* If r5 == 0, no c bytes have been found. */ + bne cr7,L(done) + +@@ -93,8 +98,14 @@ + doubleword from the string. Use that fact to find out what is + the position of the byte inside the string. */ + L(done): ++#ifdef __LITTLE_ENDIAN__ ++ addi r0,r5,-1 ++ andc r0,r0,r5 ++ popcntd r0,r0 /* Count trailing zeros. */ ++#else + cntlzd r0,r5 /* Count leading zeros before the match. */ +- srdi r0,r0,3 /* Convert leading zeroes to bytes. */ ++#endif ++ srdi r0,r0,3 /* Convert leading zeros to bytes. */ + add r3,r8,r0 /* Return address of the matching char. */ + blr + END (BP_SYM (__rawmemchr)) diff --git a/SOURCES/glibc-ppc64le-34.patch b/SOURCES/glibc-ppc64le-34.patch new file mode 100644 index 0000000..ef6362d --- /dev/null +++ b/SOURCES/glibc-ppc64le-34.patch @@ -0,0 +1,68 @@ +# commit 8f9ebb08af1368962d9f24c4cfacb55cf8eee560 +# Author: Alan Modra +# Date: Thu Oct 3 14:03:03 2013 +0930 +# +# PowerPC LE configury +# http://sourceware.org/ml/libc-alpha/2013-08/msg00096.html +# +# This adds the basic configury bits for powerpc64le and powerpcle. +# +# * configure.in: Map powerpc64le and powerpcle to base_machine/machine. +# * configure: Regenerate. +# * nptl/shlib-versions: Powerpc*le starts at 2.18. +# * shlib-versions: Likewise. +# +# commit 0ff8246327401ae8779e2697d5c7348611cdbf8a +# Author: Adhemerval Zanella +# Date: Tue Feb 4 09:49:08 2014 -0200 +# +# PowerPC: Change powerpc64le start ABI to 2.17. +# +diff -urN glibc-2.17-c758a686/configure glibc-2.17-c758a686/configure +--- glibc-2.17-c758a686/configure 2014-05-26 19:52:31.000000000 -0500 ++++ glibc-2.17-c758a686/configure 2014-05-26 19:54:13.000000000 -0500 +@@ -4195,8 +4195,8 @@ + # base_machine, we don't change it. + test -n "$base_machine" || case "$machine" in + i[34567]86) base_machine=i386 machine=i386/$machine ;; +-powerpc) base_machine=powerpc machine=powerpc/powerpc32 ;; +-powerpc64) base_machine=powerpc machine=powerpc/powerpc64 ;; ++powerpc64*) base_machine=powerpc machine=powerpc/powerpc64 ;; ++powerpc*) base_machine=powerpc machine=powerpc/powerpc32 ;; + s390) base_machine=s390 machine=s390/s390-32 ;; + s390x) base_machine=s390 machine=s390/s390-64 ;; + sh3*) base_machine=sh machine=sh/sh3 ;; +diff -urN glibc-2.17-c758a686/configure.in glibc-2.17-c758a686/configure.in +--- glibc-2.17-c758a686/configure.in 2014-05-26 19:52:30.000000000 -0500 ++++ glibc-2.17-c758a686/configure.in 2014-05-26 19:54:45.000000000 -0500 +@@ -549,8 +549,8 @@ + # base_machine, we don't change it. + test -n "$base_machine" || case "$machine" in + i[34567]86) base_machine=i386 machine=i386/$machine ;; +-powerpc) base_machine=powerpc machine=powerpc/powerpc32 ;; +-powerpc64) base_machine=powerpc machine=powerpc/powerpc64 ;; ++powerpc64*) base_machine=powerpc machine=powerpc/powerpc64 ;; ++powerpc*) base_machine=powerpc machine=powerpc/powerpc32 ;; + s390) base_machine=s390 machine=s390/s390-32 ;; + s390x) base_machine=s390 machine=s390/s390-64 ;; + sh3*) base_machine=sh machine=sh/sh3 ;; +diff -urN glibc-2.17-c758a686/nptl/shlib-versions glibc-2.17-c758a686/nptl/shlib-versions +--- glibc-2.17-c758a686/nptl/shlib-versions 2014-05-26 19:52:31.000000000 -0500 ++++ glibc-2.17-c758a686/nptl/shlib-versions 2014-05-26 19:53:31.000000000 -0500 +@@ -2,4 +2,5 @@ + sh.*-.*-linux.* libpthread=0 GLIBC_2.2 + s390x-.*-linux.* libpthread=0 GLIBC_2.2 + powerpc64-.*-linux.* libpthread=0 GLIBC_2.3 ++powerpc.*le-.*-linux.* libpthread=0 GLIBC_2.17 + .*-.*-linux.* libpthread=0 +diff -urN glibc-2.17-c758a686/shlib-versions glibc-2.17-c758a686/shlib-versions +--- glibc-2.17-c758a686/shlib-versions 2014-05-26 19:52:31.000000000 -0500 ++++ glibc-2.17-c758a686/shlib-versions 2014-05-26 19:53:31.000000000 -0500 +@@ -23,6 +23,7 @@ + + s390x-.*-linux.* DEFAULT GLIBC_2.2 + powerpc64-.*-linux.* DEFAULT GLIBC_2.3 ++powerpc.*le-.*-linux.* DEFAULT GLIBC_2.17 + .*-.*-gnu-gnu.* DEFAULT GLIBC_2.2.6 + + # Configuration ABI Identifier for ABI data files diff --git a/SOURCES/glibc-ppc64le-35.patch b/SOURCES/glibc-ppc64le-35.patch new file mode 100644 index 0000000..17434b9 --- /dev/null +++ b/SOURCES/glibc-ppc64le-35.patch @@ -0,0 +1,106 @@ +# commit 5162e7dd96efcd9b45c1dc1471a964d45278b1e1 +# Author: Ulrich Weigand +# Date: Wed Dec 4 06:41:52 2013 -0600 +# +# PowerPC64: Fix incorrect CFI in *context routines +# +# The context established by "makecontext" has a link register pointing +# back to an error path within the makecontext routine. This is currently +# covered by the CFI FDE for makecontext itself, which is simply wrong +# for the stack frame *inside* the context. When trying to unwind (e.g. +# doing a backtrace) in a routine inside a context created by makecontext, +# this can lead to uninitialized stack slots being accessed, causing the +# unwinder to crash in the worst case. +# +# Similarly, during parts of the "setcontext" routine, when the stack +# pointer has already been switched to point to the new context, the +# address range is still covered by the CFI FDE for setcontext. When +# trying to unwind in that situation (e.g. backtrace from an async +# signal handler for profiling), it is again possible that the unwinder +# crashes. +# +# Theses are all problems in existing code, but the changes in stack +# frame layout appear to make the "worst case" much more likely in +# the ELFv2 ABI context. This causes regressions e.g. in the libgo +# testsuite on ELFv2. +# +# This patch fixes this by ending the makecontext/setcontext FDEs +# before those problematic parts of the assembler, similar to what +# is already done on other platforms. This fixes the libgo +# regression on ELFv2. +# +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S 2014-05-29 13:16:16.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S 2014-05-29 13:16:17.000000000 -0500 +@@ -129,6 +129,10 @@ + the cpu link stack used to predict blr return addresses. */ + bcl 20,31,L(gotexitcodeaddr); + ++ /* End FDE now, because while executing on the context's stack ++ the unwind info would be wrong otherwise. */ ++ cfi_endproc ++ + /* This is the helper code which gets called if a function which + is registered with 'makecontext' returns. In this case we + have to install the context listed in the uc_link element of +@@ -157,6 +161,11 @@ + #endif + b L(do_exit) + ++ /* Re-establish FDE for the rest of the actual makecontext routine. */ ++ cfi_startproc ++ cfi_offset (lr, FRAME_LR_SAVE) ++ cfi_adjust_cfa_offset (128) ++ + /* The address of the exit code is in the link register. Store the lr + in the ucontext as LNK so the target function will return to our + exit code. */ +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S 2014-05-29 13:16:16.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S 2014-05-29 13:16:17.000000000 -0500 +@@ -129,6 +129,10 @@ + lfd fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31) + lfd fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31) + ++ /* End FDE now, because the unwind info would be wrong while ++ we're reloading registers to switch to the new context. */ ++ cfi_endproc ++ + ld r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31) + ld r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31) + mtlr r0 +@@ -177,6 +181,11 @@ + ld r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31) + bctr + ++ /* Re-establish FDE for the rest of the actual setcontext routine. */ ++ cfi_startproc ++ cfi_offset (lr, FRAME_LR_SAVE) ++ cfi_adjust_cfa_offset (128) ++ + L(nv_error_exit): + ld r0,128+FRAME_LR_SAVE(r1) + addi r1,r1,128 +@@ -403,6 +412,10 @@ + lfd fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31) + lfd fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31) + ++ /* End FDE now, because the unwind info would be wrong while ++ we're reloading registers to switch to the new context. */ ++ cfi_endproc ++ + ld r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31) + ld r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31) + mtlr r0 +@@ -451,6 +464,11 @@ + ld r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31) + bctr + ++ /* Re-establish FDE for the rest of the actual setcontext routine. */ ++ cfi_startproc ++ cfi_offset (lr, FRAME_LR_SAVE) ++ cfi_adjust_cfa_offset (128) ++ + L(error_exit): + ld r0,128+FRAME_LR_SAVE(r1) + addi r1,r1,128 diff --git a/SOURCES/glibc-ppc64le-36.patch b/SOURCES/glibc-ppc64le-36.patch new file mode 100644 index 0000000..fbe351c --- /dev/null +++ b/SOURCES/glibc-ppc64le-36.patch @@ -0,0 +1,105 @@ +# commit 7ec07d9a7b501f1b7d740fda02ba5f39d6d684e5 +# Author: Alan Modra +# Date: Wed Dec 4 06:44:06 2013 -0600 +# +# PowerPC64: Report overflow on @h and @ha relocations +# +# This patch updates glibc in accordance with the binutils patch checked in here: +# https://sourceware.org/ml/binutils/2013-10/msg00372.html +# +# This changes the various R_PPC64_..._HI and _HA relocations to report +# 32-bit overflows. The motivation is that existing uses of @h / @ha +# are to build up 32-bit offsets (for the "medium model" TOC access +# that GCC now defaults to), and we'd really like to see failures at +# link / load time rather than silent truncations. +# +# For those rare cases where a modifier is needed to build up a 64-bit +# constant, new relocations _HIGH / _HIGHA are supported. +# +# The patch also fixes a bug in overflow checking for the R_PPC64_ADDR30 +# and R_PPC64_ADDR32 relocations. +# +diff -urN glibc-2.17-c758a686/elf/elf.h glibc-2.17-c758a686/elf/elf.h +--- glibc-2.17-c758a686/elf/elf.h 2014-05-29 13:17:35.000000000 -0500 ++++ glibc-2.17-c758a686/elf/elf.h 2014-05-29 13:17:35.000000000 -0500 +@@ -2243,6 +2243,17 @@ + #define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */ + #define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */ + #define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */ ++#define R_PPC64_TLSGD 107 /* none (sym+add)@tlsgd */ ++#define R_PPC64_TLSLD 108 /* none (sym+add)@tlsld */ ++#define R_PPC64_TOCSAVE 109 /* none */ ++ ++/* Added when HA and HI relocs were changed to report overflows. */ ++#define R_PPC64_ADDR16_HIGH 110 ++#define R_PPC64_ADDR16_HIGHA 111 ++#define R_PPC64_TPREL16_HIGH 112 ++#define R_PPC64_TPREL16_HIGHA 113 ++#define R_PPC64_DTPREL16_HIGH 114 ++#define R_PPC64_DTPREL16_HIGHA 115 + + /* GNU extension to support local ifunc. */ + #define R_PPC64_JMP_IREL 247 +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h 2014-05-29 13:17:34.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h 2014-05-29 13:17:35.000000000 -0500 +@@ -663,11 +663,25 @@ + + case R_PPC64_TPREL16_HI: + value = elf_machine_tprel (map, sym_map, sym, reloc); ++ if (dont_expect (value + 0x80000000 >= 0x100000000LL)) ++ _dl_reloc_overflow (map, "R_PPC64_TPREL16_HI", reloc_addr, refsym); ++ *(Elf64_Half *) reloc_addr = PPC_HI (value); ++ break; ++ ++ case R_PPC64_TPREL16_HIGH: ++ value = elf_machine_tprel (map, sym_map, sym, reloc); + *(Elf64_Half *) reloc_addr = PPC_HI (value); + break; + + case R_PPC64_TPREL16_HA: + value = elf_machine_tprel (map, sym_map, sym, reloc); ++ if (dont_expect (value + 0x80008000 >= 0x100000000LL)) ++ _dl_reloc_overflow (map, "R_PPC64_TPREL16_HA", reloc_addr, refsym); ++ *(Elf64_Half *) reloc_addr = PPC_HA (value); ++ break; ++ ++ case R_PPC64_TPREL16_HIGHA: ++ value = elf_machine_tprel (map, sym_map, sym, reloc); + *(Elf64_Half *) reloc_addr = PPC_HA (value); + break; + +@@ -703,17 +717,23 @@ + break; + + case R_PPC64_ADDR16_HI: ++ if (dont_expect (value + 0x80000000 >= 0x100000000LL)) ++ _dl_reloc_overflow (map, "R_PPC64_ADDR16_HI", reloc_addr, refsym); ++ case R_PPC64_ADDR16_HIGH: + *(Elf64_Half *) reloc_addr = PPC_HI (value); + break; + + case R_PPC64_ADDR16_HA: ++ if (dont_expect (value + 0x80008000 >= 0x100000000LL)) ++ _dl_reloc_overflow (map, "R_PPC64_ADDR16_HA", reloc_addr, refsym); ++ case R_PPC64_ADDR16_HIGHA: + *(Elf64_Half *) reloc_addr = PPC_HA (value); + break; + + case R_PPC64_ADDR30: + { + Elf64_Addr delta = value - (Elf64_Xword) reloc_addr; +- if (dont_expect ((delta + 0x80000000) >= 0x10000000 ++ if (dont_expect ((delta + 0x80000000) >= 0x100000000LL + || (delta & 3) != 0)) + _dl_reloc_overflow (map, "R_PPC64_ADDR30", reloc_addr, refsym); + BIT_INSERT (*(Elf64_Word *) reloc_addr, delta, 0xfffffffc); +@@ -762,7 +782,7 @@ + return; + + case R_PPC64_ADDR32: +- if (dont_expect ((value + 0x80000000) >= 0x10000000)) ++ if (dont_expect ((value + 0x80000000) >= 0x100000000LL)) + _dl_reloc_overflow (map, "R_PPC64_ADDR32", reloc_addr, refsym); + *(Elf64_Word *) reloc_addr = value; + return; diff --git a/SOURCES/glibc-ppc64le-37.patch b/SOURCES/glibc-ppc64le-37.patch new file mode 100644 index 0000000..dad59a6 --- /dev/null +++ b/SOURCES/glibc-ppc64le-37.patch @@ -0,0 +1,31 @@ +# commit b525166bb93b060e1146f0263b76a9c1e7455b06 +# Author: Ulrich Weigand +# Date: Wed Dec 4 06:45:56 2013 -0600 +# +# PowerPC64: Add __private_ss field to TCB header +# +# The TCB header on Intel contains a field __private_ss that is used +# to efficiently implement the -fsplit-stack GCC feature. +# +# In order to prepare for a possible future implementation of that +# feature on powerpc64, we'd like to reserve a similar field in +# the TCB header as well. (It would be good if this went in with +# or before the ELFv2 patches to ensure that this field will be +# available always in the ELFv2 environment.) +# +# The field needs to be added at the front of tcbhead_t structure +# to avoid changing the ABI; see the recent discussion when adding +# the EBB fields. +# +diff -urN glibc-2.17-c758a686/nptl/sysdeps/powerpc/tls.h glibc-2.17-c758a686/nptl/sysdeps/powerpc/tls.h +--- glibc-2.17-c758a686/nptl/sysdeps/powerpc/tls.h 2014-05-29 13:19:25.000000000 -0500 ++++ glibc-2.17-c758a686/nptl/sysdeps/powerpc/tls.h 2014-05-29 13:19:25.000000000 -0500 +@@ -61,6 +61,8 @@ + are private. */ + typedef struct + { ++ /* GCC split stack support. */ ++ void *__private_ss; + /* Reservation for the Event-Based Branching ABI. */ + uintptr_t ebb_handler; + uintptr_t ebb_ctx_pointer; diff --git a/SOURCES/glibc-ppc64le-38.patch b/SOURCES/glibc-ppc64le-38.patch new file mode 100644 index 0000000..196f0ad --- /dev/null +++ b/SOURCES/glibc-ppc64le-38.patch @@ -0,0 +1,262 @@ +# commit d31beafa8e4ca69faa4cf362784796ef17299341 +# Author: Ulrich Weigand +# Date: Wed Dec 4 06:49:15 2013 -0600 +# +# PowerPC64 ELFv2 ABI 1/6: Code refactoring +# +# This is the first patch to support the new ELFv2 ABI in glibc. +# +# As preparation, this patch simply refactors some of the powerpc64 assembler +# code to move all code related to creating function descriptors (.opd section) +# or using function descriptors (function pointer call) into a central place +# in sysdep.h. +# +# Note that most locations creating .opd entries were already using macros +# in sysdep.h, this patch simply extends this to the remaining places. +# +# No relevant change in generated code expected. +# +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crti.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crti.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crti.S 2014-05-29 13:56:35.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crti.S 2014-05-29 13:56:37.000000000 -0500 +@@ -60,18 +60,8 @@ + .LC0: + .tc PREINIT_FUNCTION[TC], PREINIT_FUNCTION + #endif +- .type BODY_LABEL (_init), @function +- .globl _init +- .section ".opd", "aw" +- .align 3 +-_init: OPD_ENT (_init) +-#ifdef HAVE_ASM_GLOBAL_DOT_NAME +- .globl BODY_LABEL (_init) +- .size _init, 24 +-#else +- .type _init, @function +-#endif + .section ".init", "ax", @progbits ++ ENTRY_2(_init) + .align ALIGNARG (2) + BODY_LABEL (_init): + mflr 0 +@@ -87,18 +77,8 @@ + nop + 1: + +- .type BODY_LABEL (_fini), @function +- .globl _fini +- .section ".opd", "aw" +- .align 3 +-_fini: OPD_ENT (_fini) +-#ifdef HAVE_ASM_GLOBAL_DOT_NAME +- .globl BODY_LABEL (_fini) +- .size _fini, 24 +-#else +- .type _fini, @function +-#endif + .section ".fini", "ax", @progbits ++ ENTRY_2(_fini) + .align ALIGNARG (2) + BODY_LABEL (_fini): + mflr 0 +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h 2014-05-29 13:56:35.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h 2014-05-29 13:56:37.000000000 -0500 +@@ -122,14 +122,7 @@ + #define RTLD_START \ + asm (".pushsection \".text\"\n" \ + " .align 2\n" \ +-" .type " BODY_PREFIX "_start,@function\n" \ +-" .pushsection \".opd\",\"aw\"\n" \ +-" .align 3\n" \ +-" .globl _start\n" \ + " " ENTRY_2(_start) "\n" \ +-"_start:\n" \ +-" " OPD_ENT(_start) "\n" \ +-" .popsection\n" \ + BODY_PREFIX "_start:\n" \ + /* We start with the following on the stack, from top: \ + argc (4 bytes); \ +@@ -154,11 +147,6 @@ + ".LT__start_name_end:\n" \ + " .align 2\n" \ + " " END_2(_start) "\n" \ +-" .globl _dl_start_user\n" \ +-" .pushsection \".opd\",\"aw\"\n" \ +-"_dl_start_user:\n" \ +-" " OPD_ENT(_dl_start_user) "\n" \ +-" .popsection\n" \ + " .pushsection \".toc\",\"aw\"\n" \ + DL_STARTING_UP_DEF \ + ".LC__rtld_local:\n" \ +@@ -170,7 +158,6 @@ + ".LC__dl_fini:\n" \ + " .tc _dl_fini[TC],_dl_fini\n" \ + " .popsection\n" \ +-" .type " BODY_PREFIX "_dl_start_user,@function\n" \ + " " ENTRY_2(_dl_start_user) "\n" \ + /* Now, we do our main work of calling initialisation procedures. \ + The ELF ABI doesn't say anything about parameters for these, \ +@@ -228,10 +215,7 @@ + /* Now, call the start function descriptor at r30... */ \ + " .globl ._dl_main_dispatch\n" \ + "._dl_main_dispatch:\n" \ +-" ld 0,0(30)\n" \ +-" ld 2,8(30)\n" \ +-" mtctr 0\n" \ +-" ld 11,16(30)\n" \ ++" " PPC64_LOAD_FUNCPTR(30) "\n" \ + " bctr\n" \ + ".LT__dl_start_user:\n" \ + " .long 0\n" \ +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-trampoline.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-trampoline.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-trampoline.S 2014-05-29 13:56:35.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-trampoline.S 2014-05-29 13:56:37.000000000 -0500 +@@ -71,12 +71,8 @@ + ld r5,INT_PARMS+16(r1) + ld r4,INT_PARMS+8(r1) + mtcrf 0xFF,r0 +-/* Load the target address, toc and static chain reg from the function +- descriptor returned by fixup. */ +- ld r0,0(r3) +- ld r2,8(r3) +- mtctr r0 +- ld r11,16(r3) ++/* Prepare for calling the function returned by fixup. */ ++ PPC64_LOAD_FUNCPTR r3 + ld r3,INT_PARMS+0(r1) + /* Unwind the stack frame, and jump. */ + addi r1,r1,FRAME_SIZE +@@ -322,13 +318,9 @@ + ld r5,INT_PARMS+16(r1) + ld r4,INT_PARMS+8(r1) + mtcrf 0xFF,r0 +-/* Load the target address, toc and static chain reg from the function +- descriptor returned by fixup. */ +- ld r0,0(r3) +- ld r2,8(r3) +- ld r11,16(r3) ++/* Prepare for calling the function returned by fixup. */ ++ PPC64_LOAD_FUNCPTR r3 + ld r3,INT_PARMS+0(r1) +- mtctr r0 + /* Load the floating point registers. */ + lfd fp1,FPR_PARMS+0(r1) + lfd fp2,FPR_PARMS+8(r1) +@@ -386,14 +378,10 @@ + ld r5,INT_PARMS+16(r1) + ld r4,INT_PARMS+8(r1) + mtcrf 0xFF,r0 +-/* Load the target address, toc and static chain reg from the function +- descriptor returned by fixup. */ +- ld r0,0(r3) ++/* Prepare for calling the function returned by fixup. */ + std r2,40(r1) +- ld r2,8(r3) +- ld r11,16(r3) ++ PPC64_LOAD_FUNCPTR r3 + ld r3,INT_PARMS+0(r1) +- mtctr r0 + /* Load the floating point registers. */ + lfd fp1,FPR_PARMS+0(r1) + lfd fp2,FPR_PARMS+8(r1) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/sysdep.h glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/sysdep.h +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/sysdep.h 2014-05-29 13:56:35.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/sysdep.h 2014-05-29 13:56:37.000000000 -0500 +@@ -74,6 +74,14 @@ + #endif + .endm + ++/* Macro to prepare for calling via a function pointer. */ ++ .macro PPC64_LOAD_FUNCPTR PTR ++ ld r12,0(\PTR) ++ ld r2,8(\PTR) ++ mtctr r12 ++ ld r11,16(\PTR) ++ .endm ++ + #ifdef USE_PPC64_OVERLAPPING_OPD + # define OPD_ENT(name) .quad BODY_LABEL (name), .TOC.@tocbase + #else +@@ -81,7 +89,6 @@ + #endif + + #define ENTRY_1(name) \ +- .section ".text"; \ + .type BODY_LABEL(name),@function; \ + .globl name; \ + .section ".opd","aw"; \ +@@ -110,6 +117,7 @@ + #endif + + #define ENTRY(name) \ ++ .section ".text"; \ + ENTRY_2(name) \ + .align ALIGNARG(2); \ + BODY_LABEL(name): \ +@@ -127,6 +135,7 @@ + /* EALIGN is like ENTRY, but does alignment to 'words'*4 bytes + past a 2^alignt boundary. */ + #define EALIGN(name, alignt, words) \ ++ .section ".text"; \ + ENTRY_2(name) \ + .align ALIGNARG(alignt); \ + EALIGN_W_##words; \ +@@ -286,24 +295,42 @@ + + #else /* !__ASSEMBLER__ */ + ++#define PPC64_LOAD_FUNCPTR(ptr) \ ++ "ld 12,0(" #ptr ");\n" \ ++ "ld 2,8(" #ptr ");\n" \ ++ "mtctr 12;\n" \ ++ "ld 11,16(" #ptr ");" ++ + #ifdef USE_PPC64_OVERLAPPING_OPD + # define OPD_ENT(name) ".quad " BODY_PREFIX #name ", .TOC.@tocbase;" + #else + # define OPD_ENT(name) ".quad " BODY_PREFIX #name ", .TOC.@tocbase, 0;" + #endif + ++#define ENTRY_1(name) \ ++ ".type " BODY_PREFIX #name ",@function;\n" \ ++ ".globl " #name ";\n" \ ++ ".pushsection \".opd\",\"aw\";\n" \ ++ ".align 3;\n" \ ++#name ":\n" \ ++ OPD_ENT (name) "\n" \ ++ ".popsection;" ++ + #ifdef HAVE_ASM_GLOBAL_DOT_NAME + # define DOT_PREFIX "." + # define BODY_PREFIX "." + # define ENTRY_2(name) \ + ".globl " BODY_PREFIX #name ";\n" \ ++ ENTRY_1(name) "\n" \ + ".size " #name ", 24;" + # define END_2(name) \ + ".size " BODY_PREFIX #name ",.-" BODY_PREFIX #name ";" + #else + # define DOT_PREFIX "" + # define BODY_PREFIX ".LY" +-# define ENTRY_2(name) ".type " #name ",@function;" ++# define ENTRY_2(name) \ ++ ".type " #name ",@function;\n" \ ++ ENTRY_1(name) + # define END_2(name) \ + ".size " #name ",.-" BODY_PREFIX #name ";\n" \ + ".size " BODY_PREFIX #name ",.-" BODY_PREFIX #name ";" +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S 2014-05-29 13:56:35.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S 2014-05-29 13:56:37.000000000 -0500 +@@ -104,9 +104,7 @@ + + std r2,40(r1) + /* Call procedure. */ +- ld r0,0(r30) +- ld r2,8(r30) +- mtctr r0 ++ PPC64_LOAD_FUNCPTR r30 + mr r3,r31 + bctrl + ld r2,40(r1) diff --git a/SOURCES/glibc-ppc64le-39.patch b/SOURCES/glibc-ppc64le-39.patch new file mode 100644 index 0000000..f837d99 --- /dev/null +++ b/SOURCES/glibc-ppc64le-39.patch @@ -0,0 +1,508 @@ +# commit 696caf1d002ff059ddd20fd5eaccd76229c14850 +# Author: Ulrich Weigand +# Date: Wed Dec 4 06:51:11 2013 -0600 +# +# PowerPC64 ELFv2 ABI 2/6: Remove function descriptors +# +# This patch adds support for the ELFv2 ABI feature to remove function +# descriptors. See this GCC patch for in-depth discussion: +# http://gcc.gnu.org/ml/gcc-patches/2013-11/msg01141.html +# +# This mostly involves two types of changes: updating assembler source +# files to the new logic, and updating the dynamic loader. +# +# After the refactoring in the previous patch, most of the assembler source +# changes can be handled simply by providing ELFv2 versions of the +# macros in sysdep.h. One somewhat non-obvious change is in __GI__setjmp: +# this used to "fall through" to the immediately following __setjmp ENTRY +# point. This is no longer safe in the ELFv2 since ENTRY defines both +# a global and a local entry point, and you cannot simply fall through +# to a global entry point as it requires r12 to be set up. +# +# Also, makecontext needs to be updated to set up registers according to +# the new ABI for calling into the context's start routine. +# +# The dynamic linker changes mostly consist of removing special code +# to handle function descriptors. We also need to support the new PLT +# and glink format used by the the ELFv2 linker, see: +# https://sourceware.org/ml/binutils/2013-10/msg00376.html +# +# In addition, the dynamic linker now verifies that the dynamic libraries +# it loads match its own ABI. +# +# The hack in VDSO_IFUNC_RET to "synthesize" a function descriptor +# for vDSO routines is also no longer necessary for ELFv2. +# +diff -urN glibc-2.17-c758a686/elf/elf.h glibc-2.17-c758a686/elf/elf.h +--- glibc-2.17-c758a686/elf/elf.h 2014-05-29 13:58:25.000000000 -0500 ++++ glibc-2.17-c758a686/elf/elf.h 2014-05-29 13:58:25.000000000 -0500 +@@ -2263,6 +2263,12 @@ + #define R_PPC64_REL16_HI 251 /* half16 (sym+add-.)@h */ + #define R_PPC64_REL16_HA 252 /* half16 (sym+add-.)@ha */ + ++/* e_flags bits specifying ABI. ++ 1 for original function descriptor using ABI, ++ 2 for revised ABI without function descriptors, ++ 0 for unspecified or not using any features affected by the differences. */ ++#define EF_PPC64_ABI 3 ++ + /* PowerPC64 specific values for the Dyn d_tag field. */ + #define DT_PPC64_GLINK (DT_LOPROC + 0) + #define DT_PPC64_OPD (DT_LOPROC + 1) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crti.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crti.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crti.S 2014-05-29 13:58:25.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crti.S 2014-05-29 13:58:25.000000000 -0500 +@@ -64,6 +64,7 @@ + ENTRY_2(_init) + .align ALIGNARG (2) + BODY_LABEL (_init): ++ LOCALENTRY(_init) + mflr 0 + std 0, 16(r1) + stdu r1, -112(r1) +@@ -81,6 +82,7 @@ + ENTRY_2(_fini) + .align ALIGNARG (2) + BODY_LABEL (_fini): ++ LOCALENTRY(_fini) + mflr 0 + std 0, 16(r1) + stdu r1, -112(r1) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-irel.h glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-irel.h +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-irel.h 2014-05-29 13:58:25.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-irel.h 2014-05-29 13:58:25.000000000 -0500 +@@ -50,7 +50,11 @@ + { + Elf64_Addr *const reloc_addr = (void *) reloc->r_offset; + Elf64_Addr value = elf_ifunc_invoke(reloc->r_addend); ++#if _CALL_ELF != 2 + *(Elf64_FuncDesc *) reloc_addr = *(Elf64_FuncDesc *) value; ++#else ++ *reloc_addr = value; ++#endif + } + else + __libc_fatal ("unexpected reloc type in static binary"); +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h 2014-05-29 13:58:25.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h 2014-05-29 14:05:46.000000000 -0500 +@@ -31,6 +31,7 @@ + in l_info array. */ + #define DT_PPC64(x) (DT_PPC64_##x - DT_LOPROC + DT_NUM) + ++#if _CALL_ELF != 2 + /* A PowerPC64 function descriptor. The .plt (procedure linkage + table) and .opd (official procedure descriptor) sections are + arrays of these. */ +@@ -40,6 +41,7 @@ + Elf64_Addr fd_toc; + Elf64_Addr fd_aux; + } Elf64_FuncDesc; ++#endif + + #define ELF_MULT_MACHINES_SUPPORTED + +@@ -47,6 +49,18 @@ + static inline int + elf_machine_matches_host (const Elf64_Ehdr *ehdr) + { ++ /* Verify that the binary matches our ABI version. */ ++ if ((ehdr->e_flags & EF_PPC64_ABI) != 0) ++ { ++#if _CALL_ELF != 2 ++ if ((ehdr->e_flags & EF_PPC64_ABI) != 1) ++ return 0; ++#else ++ if ((ehdr->e_flags & EF_PPC64_ABI) != 2) ++ return 0; ++#endif ++ } ++ + return ehdr->e_machine == EM_PPC64; + } + +@@ -124,6 +138,7 @@ + " .align 2\n" \ + " " ENTRY_2(_start) "\n" \ + BODY_PREFIX "_start:\n" \ ++" " LOCALENTRY(_start) "\n" \ + /* We start with the following on the stack, from top: \ + argc (4 bytes); \ + arguments for program (terminated by NULL); \ +@@ -165,6 +180,7 @@ + Changing these is strongly discouraged (not least because argc is \ + passed by value!). */ \ + BODY_PREFIX "_dl_start_user:\n" \ ++" " LOCALENTRY(_dl_start_user) "\n" \ + /* the address of _start in r30. */ \ + " mr 30,3\n" \ + /* &_dl_argc in 29, &_dl_argv in 27, and _dl_loaded in 28. */ \ +@@ -256,8 +272,22 @@ + relocations behave "normally", ie. always use the real address + like PLT relocations. So always set ELF_RTYPE_CLASS_PLT. */ + ++#if _CALL_ELF != 2 + #define elf_machine_type_class(type) \ + (ELF_RTYPE_CLASS_PLT | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY)) ++#else ++/* And now that you have read that large comment, you can disregard it ++ all for ELFv2. ELFv2 does need the special SHN_UNDEF treatment. */ ++#define IS_PPC64_TLS_RELOC(R) \ ++ (((R) >= R_PPC64_TLS && (R) <= R_PPC64_DTPREL16_HIGHESTA) \ ++ || ((R) >= R_PPC64_TPREL16_HIGH && (R) <= R_PPC64_DTPREL16_HIGHA)) ++ ++#define elf_machine_type_class(type) \ ++ ((((type) == R_PPC64_JMP_SLOT \ ++ || (type) == R_PPC64_ADDR24 \ ++ || IS_PPC64_TLS_RELOC (type)) * ELF_RTYPE_CLASS_PLT) \ ++ | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY)) ++#endif + + /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */ + #define ELF_MACHINE_JMP_SLOT R_PPC64_JMP_SLOT +@@ -266,8 +296,19 @@ + #define ELF_MACHINE_NO_REL 1 + + /* Stuff for the PLT. */ ++#if _CALL_ELF != 2 + #define PLT_INITIAL_ENTRY_WORDS 3 ++#define PLT_ENTRY_WORDS 3 + #define GLINK_INITIAL_ENTRY_WORDS 8 ++/* The first 32k entries of glink can set an index and branch using two ++ instructions; past that point, glink uses three instructions. */ ++#define GLINK_ENTRY_WORDS(I) (((I) < 0x8000)? 2 : 3) ++#else ++#define PLT_INITIAL_ENTRY_WORDS 2 ++#define PLT_ENTRY_WORDS 1 ++#define GLINK_INITIAL_ENTRY_WORDS 8 ++#define GLINK_ENTRY_WORDS(I) 1 ++#endif + + #define PPC_DCBST(where) asm volatile ("dcbst 0,%0" : : "r"(where) : "memory") + #define PPC_DCBT(where) asm volatile ("dcbt 0,%0" : : "r"(where) : "memory") +@@ -312,17 +353,12 @@ + + if (lazy) + { +- /* The function descriptor of the appropriate trampline +- routine is used to set the 1st and 2nd doubleword of the +- plt_reserve. */ +- Elf64_FuncDesc *resolve_fd; + Elf64_Word glink_offset; +- /* the plt_reserve area is the 1st 3 doublewords of the PLT */ +- Elf64_FuncDesc *plt_reserve = (Elf64_FuncDesc *) plt; + Elf64_Word offset; ++ Elf64_Addr dlrr; + +- resolve_fd = (Elf64_FuncDesc *) (profile ? _dl_profile_resolve +- : _dl_runtime_resolve); ++ dlrr = (Elf64_Addr) (profile ? _dl_profile_resolve ++ : _dl_runtime_resolve); + if (profile && GLRO(dl_profile) != NULL + && _dl_name_match_p (GLRO(dl_profile), map)) + /* This is the object we are looking for. Say that we really +@@ -330,20 +366,33 @@ + GL(dl_profile_map) = map; + + ++#if _CALL_ELF != 2 + /* We need to stuff the address/TOC of _dl_runtime_resolve + into doublewords 0 and 1 of plt_reserve. Then we need to + stuff the map address into doubleword 2 of plt_reserve. + This allows the GLINK0 code to transfer control to the + correct trampoline which will transfer control to fixup + in dl-machine.c. */ +- plt_reserve->fd_func = resolve_fd->fd_func; +- plt_reserve->fd_toc = resolve_fd->fd_toc; +- plt_reserve->fd_aux = (Elf64_Addr) map; ++ { ++ /* The plt_reserve area is the 1st 3 doublewords of the PLT. */ ++ Elf64_FuncDesc *plt_reserve = (Elf64_FuncDesc *) plt; ++ Elf64_FuncDesc *resolve_fd = (Elf64_FuncDesc *) dlrr; ++ plt_reserve->fd_func = resolve_fd->fd_func; ++ plt_reserve->fd_toc = resolve_fd->fd_toc; ++ plt_reserve->fd_aux = (Elf64_Addr) map; + #ifdef RTLD_BOOTSTRAP +- /* When we're bootstrapping, the opd entry will not have +- been relocated yet. */ +- plt_reserve->fd_func += l_addr; +- plt_reserve->fd_toc += l_addr; ++ /* When we're bootstrapping, the opd entry will not have ++ been relocated yet. */ ++ plt_reserve->fd_func += l_addr; ++ plt_reserve->fd_toc += l_addr; ++#endif ++ } ++#else ++ /* When we don't have function descriptors, the first doubleword ++ of the PLT holds the address of _dl_runtime_resolve, and the ++ second doubleword holds the map address. */ ++ plt[0] = dlrr; ++ plt[1] = (Elf64_Addr) map; + #endif + + /* Set up the lazy PLT entries. */ +@@ -354,14 +403,8 @@ + { + + plt[offset] = (Elf64_Xword) &glink[glink_offset]; +- offset += 3; +- /* The first 32k entries of glink can set an index and +- branch using two instructions; Past that point, +- glink uses three instructions. */ +- if (i < 0x8000) +- glink_offset += 2; +- else +- glink_offset += 3; ++ offset += PLT_ENTRY_WORDS; ++ glink_offset += GLINK_ENTRY_WORDS (i); + } + + /* Now, we've modified data. We need to write the changes from +@@ -389,6 +432,7 @@ + const Elf64_Rela *reloc, + Elf64_Addr *reloc_addr, Elf64_Addr finaladdr) + { ++#if _CALL_ELF != 2 + Elf64_FuncDesc *plt = (Elf64_FuncDesc *) reloc_addr; + Elf64_FuncDesc *rel = (Elf64_FuncDesc *) finaladdr; + Elf64_Addr offset = 0; +@@ -426,6 +470,9 @@ + plt->fd_func = rel->fd_func + offset; + PPC_DCBST (&plt->fd_func); + PPC_ISYNC; ++#else ++ *reloc_addr = finaladdr; ++#endif + + return finaladdr; + } +@@ -433,6 +480,7 @@ + static inline void __attribute__ ((always_inline)) + elf_machine_plt_conflict (Elf64_Addr *reloc_addr, Elf64_Addr finaladdr) + { ++#if _CALL_ELF != 2 + Elf64_FuncDesc *plt = (Elf64_FuncDesc *) reloc_addr; + Elf64_FuncDesc *rel = (Elf64_FuncDesc *) finaladdr; + +@@ -443,6 +491,9 @@ + PPC_DCBST (&plt->fd_aux); + PPC_DCBST (&plt->fd_toc); + PPC_SYNC; ++#else ++ *reloc_addr = finaladdr; ++#endif + } + + /* Return the final value of a plt relocation. */ +@@ -512,6 +563,7 @@ + resolve_ifunc (Elf64_Addr value, + const struct link_map *map, const struct link_map *sym_map) + { ++#if _CALL_ELF != 2 + #ifndef RESOLVE_CONFLICT_FIND_MAP + /* The function we are calling may not yet have its opd entry relocated. */ + Elf64_FuncDesc opd; +@@ -529,6 +581,7 @@ + value = (Elf64_Addr) &opd; + } + #endif ++#endif + return ((Elf64_Addr (*) (unsigned long int)) value) (GLRO(dl_hwcap)); + } + +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S 2014-05-29 13:58:25.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S 2014-05-29 14:00:27.000000000 -0500 +@@ -55,21 +55,22 @@ + that saves r2 since the call won't go via a plt call stub. See + bugz #269. __GI__setjmp is used in csu/libc-start.c when + HAVE_CLEANUP_JMP_BUF is defined. */ +-ENTRY (BP_SYM (__GI__setjmp)) ++ENTRY (__GI__setjmp) + std r2,40(r1) /* Save the callers TOC in the save area. */ +- cfi_endproc +-END_2 (BP_SYM (__GI__setjmp)) +-/* Fall thru. */ ++ CALL_MCOUNT 1 ++ li r4,0 /* Set second argument to 0. */ ++ b JUMPTARGET (GLUE(__sigsetjmp,_ent)) ++END (__GI__setjmp) + #endif + +-ENTRY (BP_SYM (_setjmp)) ++ENTRY (_setjmp) + CALL_MCOUNT 1 + li r4,0 /* Set second argument to 0. */ + b JUMPTARGET (GLUE(__sigsetjmp,_ent)) +-END (BP_SYM (_setjmp)) ++END (_setjmp) + libc_hidden_def (_setjmp) + +-ENTRY (BP_SYM (__sigsetjmp)) ++ENTRY (__sigsetjmp) + CALL_MCOUNT 2 + JUMPTARGET(GLUE(__sigsetjmp,_ent)): + CHECK_BOUNDS_BOTH_WIDE_LIT (r3, r8, r9, JB_SIZE) +@@ -215,18 +216,18 @@ + li r3,0 + blr + #elif defined SHARED +- b JUMPTARGET (BP_SYM (__sigjmp_save)) ++ b JUMPTARGET (__sigjmp_save) + #else + mflr r0 + std r0,16(r1) + stdu r1,-112(r1) + cfi_adjust_cfa_offset(112) + cfi_offset(lr,16) +- bl JUMPTARGET (BP_SYM (__sigjmp_save)) ++ bl JUMPTARGET (__sigjmp_save) + nop + ld r0,112+16(r1) + addi r1,r1,112 + mtlr r0 + blr + #endif +-END (BP_SYM (__sigsetjmp)) ++END (__sigsetjmp) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/sysdep.h glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/sysdep.h +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/sysdep.h 2014-05-29 13:58:25.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/sysdep.h 2014-05-29 13:58:25.000000000 -0500 +@@ -74,6 +74,8 @@ + #endif + .endm + ++#if _CALL_ELF != 2 ++ + /* Macro to prepare for calling via a function pointer. */ + .macro PPC64_LOAD_FUNCPTR PTR + ld r12,0(\PTR) +@@ -115,13 +117,37 @@ + .size name,.-BODY_LABEL(name); \ + .size BODY_LABEL(name),.-BODY_LABEL(name); + #endif ++#define LOCALENTRY(name) ++ ++#else /* _CALL_ELF */ ++ ++/* Macro to prepare for calling via a function pointer. */ ++ .macro PPC64_LOAD_FUNCPTR PTR ++ mr r12,\PTR ++ mtctr r12 ++ .endm ++ ++#define DOT_LABEL(X) X ++#define BODY_LABEL(X) X ++#define ENTRY_2(name) \ ++ .globl name; \ ++ .type name,@function; ++#define END_2(name) \ ++ .size name,.-name; ++#define LOCALENTRY(name) \ ++1: addis r2,r12,.TOC.-1b@ha; \ ++ addi r2,r2,.TOC.-1b@l; \ ++ .localentry name,.-name; ++ ++#endif /* _CALL_ELF */ + + #define ENTRY(name) \ + .section ".text"; \ + ENTRY_2(name) \ + .align ALIGNARG(2); \ + BODY_LABEL(name): \ +- cfi_startproc; ++ cfi_startproc; \ ++ LOCALENTRY(name) + + #define EALIGN_W_0 /* No words to insert. */ + #define EALIGN_W_1 nop +@@ -140,7 +166,8 @@ + .align ALIGNARG(alignt); \ + EALIGN_W_##words; \ + BODY_LABEL(name): \ +- cfi_startproc; ++ cfi_startproc; \ ++ LOCALENTRY(name) + + /* Local labels stripped out by the linker. */ + #undef L +@@ -295,6 +322,8 @@ + + #else /* !__ASSEMBLER__ */ + ++#if _CALL_ELF != 2 ++ + #define PPC64_LOAD_FUNCPTR(ptr) \ + "ld 12,0(" #ptr ");\n" \ + "ld 2,8(" #ptr ");\n" \ +@@ -335,5 +364,26 @@ + ".size " #name ",.-" BODY_PREFIX #name ";\n" \ + ".size " BODY_PREFIX #name ",.-" BODY_PREFIX #name ";" + #endif ++#define LOCALENTRY(name) ++ ++#else /* _CALL_ELF */ ++ ++#define PPC64_LOAD_FUNCPTR(ptr) \ ++ "mr 12," #ptr ";\n" \ ++ "mtctr 12;" ++ ++#define DOT_PREFIX "" ++#define BODY_PREFIX "" ++#define ENTRY_2(name) \ ++ ".type " #name ",@function;\n" \ ++ ".globl " #name ";" ++#define END_2(name) \ ++ ".size " #name ",.-" #name ";" ++#define LOCALENTRY(name) \ ++ "1: addis 2,12,.TOC.-1b@ha;\n" \ ++ "addi 2,2,.TOC.-1b@l;\n" \ ++ ".localentry " #name ",.-" #name ";" ++ ++#endif /* _CALL_ELF */ + + #endif /* __ASSEMBLER__ */ +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h 2014-05-29 13:58:24.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h 2014-05-29 13:58:25.000000000 -0500 +@@ -23,6 +23,8 @@ + + /* Now define our stuff. */ + ++#if _CALL_ELF != 2 ++ + static __always_inline bool + _dl_ppc64_is_opd_sym (const struct link_map *l, const ElfW(Sym) *sym) + { +@@ -73,4 +75,6 @@ + #define DL_ADDR_SYM_MATCH(L, SYM, MATCHSYM, ADDR) \ + _dl_ppc64_addr_sym_match (L, SYM, MATCHSYM, ADDR) + ++#endif ++ + #endif /* ldsodefs.h */ +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S 2014-05-29 13:58:24.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S 2014-05-29 13:58:25.000000000 -0500 +@@ -111,6 +111,7 @@ + + L(noparms): + ++#if _CALL_ELF != 2 + /* Load the function address and TOC from the function descriptor + and store them in the ucontext as NIP and r2. Store the 3rd + field of the function descriptor into the ucontext as r11 in case +@@ -121,6 +122,12 @@ + std r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r3) + std r10,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r3) + std r9,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r3) ++#else ++ /* In the ELFv2 ABI, the function pointer is already the address. ++ Store it as NIP and r12 as required by the ABI. */ ++ std r4,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r3) ++ std r4,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r3) ++#endif + + /* If the target function returns we need to do some cleanup. We use a + code trick to get the address of our cleanup function into the link diff --git a/SOURCES/glibc-ppc64le-40.patch b/SOURCES/glibc-ppc64le-40.patch new file mode 100644 index 0000000..663d2f3 --- /dev/null +++ b/SOURCES/glibc-ppc64le-40.patch @@ -0,0 +1,159 @@ +# commit 122b66defdb9e4ded3ccc5c2b290f0520c6fa3cd +# Author: Ulrich Weigand +# Date: Wed Dec 4 06:52:40 2013 -0600 +# +# PowerPC64 ELFv2 ABI 3/6: PLT local entry point optimization +# +# This is a follow-on to the previous patch to support the ELFv2 ABI in the +# dynamic loader, split off into its own patch since it is just an optional +# optimization. +# +# In the ELFv2 ABI, most functions define both a global and a local entry +# point; the local entry requires r2 to be already set up by the caller +# to point to the callee's TOC; while the global entry does not require +# the caller to know about the callee's TOC, but it needs to set up r12 +# to the callee's entry point address. +# +# Now, when setting up a PLT slot, the dynamic linker will usually need +# to enter the target function's global entry point. However, if the +# linker can prove that the target function is in the same DSO as the +# PLT slot itself, and the whole DSO only uses a single TOC (which the +# linker will let ld.so know via a DT_PPC64_OPT entry), then it is +# possible to actually enter the local entry point address into the +# PLT slot, for a slight improvement in performance. +# +# Note that this uncovered a problem on the first call via _dl_runtime_resolve, +# because that routine neglected to restore the caller's TOC before calling +# the target function for the first time, since it assumed that function +# would always reload its own TOC anyway ... +# +diff -urN glibc-2.17-c758a686/elf/elf.h glibc-2.17-c758a686/elf/elf.h +--- glibc-2.17-c758a686/elf/elf.h 2014-05-29 14:08:44.000000000 -0500 ++++ glibc-2.17-c758a686/elf/elf.h 2014-05-29 14:08:44.000000000 -0500 +@@ -2273,8 +2273,19 @@ + #define DT_PPC64_GLINK (DT_LOPROC + 0) + #define DT_PPC64_OPD (DT_LOPROC + 1) + #define DT_PPC64_OPDSZ (DT_LOPROC + 2) ++#define DT_PPC64_OPT (DT_LOPROC + 3) + #define DT_PPC64_NUM 3 + ++/* PowerPC64 specific values for the DT_PPC64_OPT Dyn entry. */ ++#define PPC64_OPT_TLS 1 ++#define PPC64_OPT_MULTI_TOC 2 ++ ++/* PowerPC64 specific values for the Elf64_Sym st_other field. */ ++#define STO_PPC64_LOCAL_BIT 5 ++#define STO_PPC64_LOCAL_MASK (7 << STO_PPC64_LOCAL_BIT) ++#define PPC64_LOCAL_ENTRY_OFFSET(other) \ ++ (((1 << (((other) & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT)) >> 2) << 2) ++ + + /* ARM specific declarations */ + +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h 2014-05-29 14:08:40.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h 2014-05-29 14:08:44.000000000 -0500 +@@ -425,6 +425,42 @@ + return lazy; + } + ++#if _CALL_ELF == 2 ++/* If the PLT entry whose reloc is 'reloc' resolves to a function in ++ the same object, return the target function's local entry point ++ offset if usable. */ ++static inline Elf64_Addr __attribute__ ((always_inline)) ++ppc64_local_entry_offset (struct link_map *map, lookup_t sym_map, ++ const Elf64_Rela *reloc) ++{ ++ const Elf64_Sym *symtab; ++ const Elf64_Sym *sym; ++ ++ /* If the target function is in a different object, we cannot ++ use the local entry point. */ ++ if (sym_map != map) ++ return 0; ++ ++ /* If the linker inserted multiple TOCs, we cannot use the ++ local entry point. */ ++ if (map->l_info[DT_PPC64(OPT)] ++ && (map->l_info[DT_PPC64(OPT)]->d_un.d_val & PPC64_OPT_MULTI_TOC)) ++ return 0; ++ ++ /* Otherwise, we can use the local entry point. Retrieve its offset ++ from the symbol's ELF st_other field. */ ++ symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]); ++ sym = &symtab[ELFW(R_SYM) (reloc->r_info)]; ++ ++ /* If the target function is an ifunc then the local entry offset is ++ for the resolver, not the final destination. */ ++ if (__builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)) ++ return 0; ++ ++ return PPC64_LOCAL_ENTRY_OFFSET (sym->st_other); ++} ++#endif ++ + /* Change the PLT entry whose reloc is 'reloc' to call the actual + routine. */ + static inline Elf64_Addr __attribute__ ((always_inline)) +@@ -471,6 +507,7 @@ + PPC_DCBST (&plt->fd_func); + PPC_ISYNC; + #else ++ finaladdr += ppc64_local_entry_offset (map, sym_map, reloc); + *reloc_addr = finaladdr; + #endif + +@@ -478,7 +515,9 @@ + } + + static inline void __attribute__ ((always_inline)) +-elf_machine_plt_conflict (Elf64_Addr *reloc_addr, Elf64_Addr finaladdr) ++elf_machine_plt_conflict (struct link_map *map, lookup_t sym_map, ++ const Elf64_Rela *reloc, ++ Elf64_Addr *reloc_addr, Elf64_Addr finaladdr) + { + #if _CALL_ELF != 2 + Elf64_FuncDesc *plt = (Elf64_FuncDesc *) reloc_addr; +@@ -492,6 +531,7 @@ + PPC_DCBST (&plt->fd_toc); + PPC_SYNC; + #else ++ finaladdr += ppc64_local_entry_offset (map, sym_map, reloc); + *reloc_addr = finaladdr; + #endif + } +@@ -641,7 +681,7 @@ + /* Fall thru */ + case R_PPC64_JMP_SLOT: + #ifdef RESOLVE_CONFLICT_FIND_MAP +- elf_machine_plt_conflict (reloc_addr, value); ++ elf_machine_plt_conflict (map, sym_map, reloc, reloc_addr, value); + #else + elf_machine_fixup_plt (map, sym_map, reloc, reloc_addr, value); + #endif +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-trampoline.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-trampoline.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-trampoline.S 2014-05-29 14:08:40.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-trampoline.S 2014-05-29 14:08:44.000000000 -0500 +@@ -74,6 +74,10 @@ + /* Prepare for calling the function returned by fixup. */ + PPC64_LOAD_FUNCPTR r3 + ld r3,INT_PARMS+0(r1) ++#if _CALL_ELF == 2 ++/* Restore the caller's TOC in case we jump to a local entry point. */ ++ ld r2,FRAME_SIZE+40(r1) ++#endif + /* Unwind the stack frame, and jump. */ + addi r1,r1,FRAME_SIZE + bctr +@@ -321,6 +325,10 @@ + /* Prepare for calling the function returned by fixup. */ + PPC64_LOAD_FUNCPTR r3 + ld r3,INT_PARMS+0(r1) ++#if _CALL_ELF == 2 ++/* Restore the caller's TOC in case we jump to a local entry point. */ ++ ld r2,FRAME_SIZE+40(r1) ++#endif + /* Load the floating point registers. */ + lfd fp1,FPR_PARMS+0(r1) + lfd fp2,FPR_PARMS+8(r1) diff --git a/SOURCES/glibc-ppc64le-41.patch b/SOURCES/glibc-ppc64le-41.patch new file mode 100644 index 0000000..506d761 --- /dev/null +++ b/SOURCES/glibc-ppc64le-41.patch @@ -0,0 +1,764 @@ +# commit 8b8a692cfd7d80f1ee7c8b9ab356a259367dd187 +# Author: Ulrich Weigand +# Date: Wed Dec 4 06:55:03 2013 -0600 +# +# PowerPC64 ELFv2 ABI 4/6: Stack frame layout changes +# +# This updates glibc for the changes in the ELFv2 relating to the +# stack frame layout. These are described in more detail here: +# http://gcc.gnu.org/ml/gcc-patches/2013-11/msg01149.html +# http://gcc.gnu.org/ml/gcc-patches/2013-11/msg01146.html +# +# Specifically, the "compiler and linker doublewords" were removed, +# which has the effect that the save slot for the TOC register is +# now at offset 24 rather than 40 to the stack pointer. +# +# In addition, a function may now no longer necessarily assume that +# its caller has set up a 64-byte register save area its use. +# +# To address the first change, the patch goes through all assembler +# files and replaces immediate offsets in instructions accessing the +# ABI-defined stack slots by symbolic offsets. Those already were +# defined in ucontext_i.sym and used in some of the context routines, +# but that doesn't really seem like the right place for those defines. +# +# The patch instead defines those symbolic offsets in sysdeps.h, +# in two variants for the old and new ABI, and uses them systematically +# in all assembler files, not just the context routines. +# +# The second change only affected a few assembler files that used +# the save area to temporarily store some registers. In those +# cases where this happens within a leaf function, this patch +# changes the code to store those registers to the "red zone" +# below the stack pointer. Otherwise, the functions already allocate +# a stack frame, and the patch changes them to add extra space in +# these frames as temporary space for the ELFv2 ABI. +# +diff -urN glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h +--- glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h 2014-05-29 14:10:00.000000000 -0500 ++++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h 2014-05-29 14:10:00.000000000 -0500 +@@ -31,6 +31,14 @@ + # define DASHDASHPFX(str) __##str + # endif + ++#if _CALL_ELF == 2 ++#define CANCEL_FRAMESIZE (FRAME_MIN_SIZE+16+48) ++#define CANCEL_PARM_SAVE (FRAME_MIN_SIZE+16) ++#else ++#define CANCEL_FRAMESIZE (FRAME_MIN_SIZE+16) ++#define CANCEL_PARM_SAVE (CANCEL_FRAMESIZE+FRAME_PARM_SAVE) ++#endif ++ + # undef PSEUDO + # define PSEUDO(name, syscall_name, args) \ + .section ".text"; \ +@@ -44,52 +52,52 @@ + PSEUDO_RET; \ + .size DASHDASHPFX(syscall_name##_nocancel),.-DASHDASHPFX(syscall_name##_nocancel); \ + .Lpseudo_cancel: \ +- stdu 1,-128(1); \ +- cfi_adjust_cfa_offset (128); \ ++ stdu 1,-CANCEL_FRAMESIZE(1); \ ++ cfi_adjust_cfa_offset (CANCEL_FRAMESIZE); \ + mflr 9; \ +- std 9,128+16(1); \ +- cfi_offset (lr, 16); \ ++ std 9,CANCEL_FRAMESIZE+FRAME_LR_SAVE(1); \ ++ cfi_offset (lr, FRAME_LR_SAVE); \ + DOCARGS_##args; /* save syscall args around CENABLE. */ \ + CENABLE; \ +- std 3,112(1); /* store CENABLE return value (MASK). */ \ ++ std 3,FRAME_MIN_SIZE(1); /* store CENABLE return value (MASK). */ \ + UNDOCARGS_##args; /* restore syscall args. */ \ + DO_CALL (SYS_ify (syscall_name)); \ + mfcr 0; /* save CR/R3 around CDISABLE. */ \ +- std 3,120(1); \ +- std 0,128+8(1); \ +- cfi_offset (cr, 8); \ +- ld 3,112(1); /* pass MASK to CDISABLE. */ \ ++ std 3,FRAME_MIN_SIZE+8(1); \ ++ std 0,CANCEL_FRAMESIZE+FRAME_CR_SAVE(1); \ ++ cfi_offset (cr, FRAME_CR_SAVE); \ ++ ld 3,FRAME_MIN_SIZE(1); /* pass MASK to CDISABLE. */ \ + CDISABLE; \ +- ld 9,128+16(1); \ +- ld 0,128+8(1); /* restore CR/R3. */ \ +- ld 3,120(1); \ ++ ld 9,CANCEL_FRAMESIZE+FRAME_LR_SAVE(1); \ ++ ld 0,CANCEL_FRAMESIZE+FRAME_CR_SAVE(1); /* restore CR/R3. */ \ ++ ld 3,FRAME_MIN_SIZE+8(1); \ + mtlr 9; \ + mtcr 0; \ +- addi 1,1,128; \ +- cfi_adjust_cfa_offset (-128); \ ++ addi 1,1,CANCEL_FRAMESIZE; \ ++ cfi_adjust_cfa_offset (-CANCEL_FRAMESIZE); \ + cfi_restore (lr); \ + cfi_restore (cr) + + # define DOCARGS_0 + # define UNDOCARGS_0 + +-# define DOCARGS_1 std 3,128+48(1); DOCARGS_0 +-# define UNDOCARGS_1 ld 3,128+48(1); UNDOCARGS_0 ++# define DOCARGS_1 std 3,CANCEL_PARM_SAVE(1); DOCARGS_0 ++# define UNDOCARGS_1 ld 3,CANCEL_PARM_SAVE(1); UNDOCARGS_0 + +-# define DOCARGS_2 std 4,128+56(1); DOCARGS_1 +-# define UNDOCARGS_2 ld 4,128+56(1); UNDOCARGS_1 ++# define DOCARGS_2 std 4,CANCEL_PARM_SAVE+8(1); DOCARGS_1 ++# define UNDOCARGS_2 ld 4,CANCEL_PARM_SAVE+8(1); UNDOCARGS_1 + +-# define DOCARGS_3 std 5,128+64(1); DOCARGS_2 +-# define UNDOCARGS_3 ld 5,128+64(1); UNDOCARGS_2 ++# define DOCARGS_3 std 5,CANCEL_PARM_SAVE+16(1); DOCARGS_2 ++# define UNDOCARGS_3 ld 5,CANCEL_PARM_SAVE+16(1); UNDOCARGS_2 + +-# define DOCARGS_4 std 6,128+72(1); DOCARGS_3 +-# define UNDOCARGS_4 ld 6,128+72(1); UNDOCARGS_3 ++# define DOCARGS_4 std 6,CANCEL_PARM_SAVE+24(1); DOCARGS_3 ++# define UNDOCARGS_4 ld 6,CANCEL_PARM_SAVE+24(1); UNDOCARGS_3 + +-# define DOCARGS_5 std 7,128+80(1); DOCARGS_4 +-# define UNDOCARGS_5 ld 7,128+80(1); UNDOCARGS_4 ++# define DOCARGS_5 std 7,CANCEL_PARM_SAVE+32(1); DOCARGS_4 ++# define UNDOCARGS_5 ld 7,CANCEL_PARM_SAVE+32(1); UNDOCARGS_4 + +-# define DOCARGS_6 std 8,128+88(1); DOCARGS_5 +-# define UNDOCARGS_6 ld 8,128+88(1); UNDOCARGS_5 ++# define DOCARGS_6 std 8,CANCEL_PARM_SAVE+40(1); DOCARGS_5 ++# define UNDOCARGS_6 ld 8,CANCEL_PARM_SAVE+40(1); UNDOCARGS_5 + + # ifdef IS_IN_libpthread + # ifdef SHARED +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/__longjmp-common.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/__longjmp-common.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/__longjmp-common.S 2014-05-29 14:09:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/__longjmp-common.S 2014-05-29 14:10:00.000000000 -0500 +@@ -133,7 +133,7 @@ + ld r14,((JB_GPRS+0)*8)(r3) + lfd fp14,((JB_FPRS+0)*8)(r3) + #if defined SHARED && !defined IS_IN_rtld +- std r2,40(r1) /* Restore the callers TOC save area. */ ++ std r2,FRAME_TOC_SAVE(r1) /* Restore the callers TOC save area. */ + #endif + ld r15,((JB_GPRS+1)*8)(r3) + lfd fp15,((JB_FPRS+1)*8)(r3) +@@ -151,7 +151,7 @@ + PTR_DEMANGLE2 (r0, r25) + #endif + mtlr r0 +-/* std r2,40(r1) Restore the TOC save area. */ ++/* std r2,FRAME_TOC_SAVE(r1) Restore the TOC save area. */ + ld r21,((JB_GPRS+7)*8)(r3) + lfd fp21,((JB_FPRS+7)*8)(r3) + ld r22,((JB_GPRS+8)*8)(r3) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crti.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crti.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crti.S 2014-05-29 14:09:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crti.S 2014-05-29 14:10:00.000000000 -0500 +@@ -66,8 +66,8 @@ + BODY_LABEL (_init): + LOCALENTRY(_init) + mflr 0 +- std 0, 16(r1) +- stdu r1, -112(r1) ++ std 0, FRAME_LR_SAVE(r1) ++ stdu r1, -FRAME_MIN_SIZE_PARM(r1) + #if PREINIT_FUNCTION_WEAK + addis r9, r2, .LC0@toc@ha + ld r0, .LC0@toc@l(r9) +@@ -84,5 +84,5 @@ + BODY_LABEL (_fini): + LOCALENTRY(_fini) + mflr 0 +- std 0, 16(r1) +- stdu r1, -112(r1) ++ std 0, FRAME_LR_SAVE(r1) ++ stdu r1, -FRAME_MIN_SIZE_PARM(r1) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crtn.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crtn.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crtn.S 2014-05-29 14:09:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crtn.S 2014-05-29 14:10:00.000000000 -0500 +@@ -39,13 +39,13 @@ + #include + + .section .init,"ax",@progbits +- addi r1, r1, 112 +- ld r0, 16(r1) ++ addi r1, r1, FRAME_MIN_SIZE_PARM ++ ld r0, FRAME_LR_SAVE(r1) + mtlr r0 + blr + + .section .fini,"ax",@progbits +- addi r1, r1, 112 +- ld r0, 16(r1) ++ addi r1, r1, FRAME_MIN_SIZE_PARM ++ ld r0, FRAME_LR_SAVE(r1) + mtlr r0 + blr +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-trampoline.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-trampoline.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-trampoline.S 2014-05-29 14:09:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-trampoline.S 2014-05-29 14:10:00.000000000 -0500 +@@ -26,13 +26,13 @@ + parm1 (r3) and the index (r0) need to be converted to an offset + (index * 24) in parm2 (r4). */ + +-#define FRAME_SIZE 176 ++#define FRAME_SIZE (FRAME_MIN_SIZE+64) + /* We need to save the registers used to pass parameters, ie. r3 thru + r10; Use local var space rather than the parameter save area, + because gcc as of 2010/05 doesn't allocate a proper stack frame for + a function that makes no calls except for __tls_get_addr and we + might be here resolving the __tls_get_addr call. */ +-#define INT_PARMS 112 ++#define INT_PARMS FRAME_MIN_SIZE + EALIGN(_dl_runtime_resolve, 4, 0) + stdu r1,-FRAME_SIZE(r1) + cfi_adjust_cfa_offset (FRAME_SIZE) +@@ -48,25 +48,25 @@ + mflr r0 + std r8,INT_PARMS+40(r1) + /* Store the LR in the LR Save area. */ +- std r0,FRAME_SIZE+16(r1) +- cfi_offset (lr, 16) ++ std r0,FRAME_SIZE+FRAME_LR_SAVE(r1) ++ cfi_offset (lr, FRAME_LR_SAVE) + mfcr r0 + std r9,INT_PARMS+48(r1) + std r10,INT_PARMS+56(r1) + /* I'm almost certain we don't have to save cr... be safe. */ +- std r0,FRAME_SIZE+8(r1) ++ std r0,FRAME_SIZE+FRAME_CR_SAVE(r1) + bl JUMPTARGET(_dl_fixup) + #ifndef SHARED + nop + #endif + /* Put the registers back. */ +- ld r0,FRAME_SIZE+16(r1) ++ ld r0,FRAME_SIZE+FRAME_LR_SAVE(r1) + ld r10,INT_PARMS+56(r1) + ld r9,INT_PARMS+48(r1) + ld r8,INT_PARMS+40(r1) + ld r7,INT_PARMS+32(r1) + mtlr r0 +- ld r0,FRAME_SIZE+8(r1) ++ ld r0,FRAME_SIZE+FRAME_CR_SAVE(r1) + ld r6,INT_PARMS+24(r1) + ld r5,INT_PARMS+16(r1) + ld r4,INT_PARMS+8(r1) +@@ -76,7 +76,7 @@ + ld r3,INT_PARMS+0(r1) + #if _CALL_ELF == 2 + /* Restore the caller's TOC in case we jump to a local entry point. */ +- ld r2,FRAME_SIZE+40(r1) ++ ld r2,FRAME_SIZE+FRAME_TOC_SAVE(r1) + #endif + /* Unwind the stack frame, and jump. */ + addi r1,r1,FRAME_SIZE +@@ -86,6 +86,7 @@ + #undef INT_PARMS + + /* Stack layout: ++ (Note: some of these are not required for the ELFv2 ABI.) + +592 previous backchain + +584 spill_r31 + +576 spill_r30 +@@ -147,10 +148,11 @@ + +64 parm3 + +56 parm2 + +48 parm1 +- * Parameter save area, Allocated by the call, at least 8 double words +- +40 TOC save area +- +32 Reserved for linker +- +24 Reserved for compiler ++ * Parameter save area ++ * (v1 ABI: Allocated by the call, at least 8 double words) ++ +40 v1 ABI: TOC save area ++ +32 v1 ABI: Reserved for linker ++ +24 v1 ABI: Reserved for compiler / v2 ABI: TOC save area + +16 LR save area + +8 CR save area + r1+0 stack back chain +@@ -206,15 +208,15 @@ + /* Store the LR in the LR Save area of the previous frame. */ + /* XXX Do we have to do this? */ + la r8,FRAME_SIZE(r1) +- std r5,FRAME_SIZE+16(r1) +- cfi_offset (lr, 16) ++ std r5,FRAME_SIZE+FRAME_LR_SAVE(r1) ++ cfi_offset (lr, FRAME_LR_SAVE) + std r5,CALLING_LR(r1) + mfcr r0 + std r9,INT_PARMS+48(r1) + std r10,INT_PARMS+56(r1) + std r8,CALLING_SP(r1) + /* I'm almost certain we don't have to save cr... be safe. */ +- std r0,FRAME_SIZE+8(r1) ++ std r0,FRAME_SIZE+FRAME_CR_SAVE(r1) + ld r12,.LC__dl_hwcap@toc(r2) + #ifdef SHARED + /* Load _rtld_local_ro._dl_hwcap. */ +@@ -311,13 +313,13 @@ + lvx v12,r11,r10 + lvx v13,r11,r9 + L(restoreFXR): +- ld r0,FRAME_SIZE+16(r1) ++ ld r0,FRAME_SIZE+FRAME_LR_SAVE(r1) + ld r10,INT_PARMS+56(r1) + ld r9,INT_PARMS+48(r1) + ld r8,INT_PARMS+40(r1) + ld r7,INT_PARMS+32(r1) + mtlr r0 +- ld r0,FRAME_SIZE+8(r1) ++ ld r0,FRAME_SIZE+FRAME_CR_SAVE(r1) + ld r6,INT_PARMS+24(r1) + ld r5,INT_PARMS+16(r1) + ld r4,INT_PARMS+8(r1) +@@ -327,7 +329,7 @@ + ld r3,INT_PARMS+0(r1) + #if _CALL_ELF == 2 + /* Restore the caller's TOC in case we jump to a local entry point. */ +- ld r2,FRAME_SIZE+40(r1) ++ ld r2,FRAME_SIZE+FRAME_TOC_SAVE(r1) + #endif + /* Load the floating point registers. */ + lfd fp1,FPR_PARMS+0(r1) +@@ -375,19 +377,19 @@ + lvx v12,r11,r10 + lvx v13,r11,r9 + L(restoreFXR2): +- ld r0,FRAME_SIZE+16(r1) ++ ld r0,FRAME_SIZE+FRAME_LR_SAVE(r1) + ld r10,INT_PARMS+56(r1) + ld r9,INT_PARMS+48(r1) + ld r8,INT_PARMS+40(r1) + ld r7,INT_PARMS+32(r1) + mtlr r0 +- ld r0,FRAME_SIZE+8(r1) ++ ld r0,FRAME_SIZE+FRAME_CR_SAVE(r1) + ld r6,INT_PARMS+24(r1) + ld r5,INT_PARMS+16(r1) + ld r4,INT_PARMS+8(r1) + mtcrf 0xFF,r0 + /* Prepare for calling the function returned by fixup. */ +- std r2,40(r1) ++ std r2,FRAME_TOC_SAVE(r1) + PPC64_LOAD_FUNCPTR r3 + ld r3,INT_PARMS+0(r1) + /* Load the floating point registers. */ +@@ -406,7 +408,7 @@ + lfd fp13,FPR_PARMS+96(r1) + /* Call the target function. */ + bctrl +- ld r2,40(r1) ++ ld r2,FRAME_TOC_SAVE(r1) + lwz r12,VR_VRSAVE(r1) + /* But return here and store the return values. */ + std r3,INT_RTN(r1) +@@ -441,7 +443,7 @@ + beq L(pltexitreturn) + lvx v2,0,r10 + L(pltexitreturn): +- ld r0,FRAME_SIZE+16(r1) ++ ld r0,FRAME_SIZE+FRAME_LR_SAVE(r1) + ld r31,584(r1) + ld r30,576(r1) + mtlr r0 +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/ppc-mcount.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/ppc-mcount.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/ppc-mcount.S 2014-05-29 14:09:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/ppc-mcount.S 2014-05-29 14:10:00.000000000 -0500 +@@ -24,16 +24,16 @@ + ENTRY(_mcount) + mflr r4 + ld r11, 0(r1) +- stdu r1,-112(r1) +- cfi_adjust_cfa_offset (112) +- std r4, 128(r1) +- cfi_offset (lr, 16) +- ld r3, 16(r11) ++ stdu r1,-FRAME_MIN_SIZE(r1) ++ cfi_adjust_cfa_offset (FRAME_MIN_SIZE) ++ std r4, FRAME_MIN_SIZE+FRAME_LR_SAVE(r1) ++ cfi_offset (lr, FRAME_LR_SAVE) ++ ld r3, FRAME_LR_SAVE(r11) + bl JUMPTARGET(__mcount_internal) + nop +- ld r0, 128(r1) ++ ld r0, FRAME_MIN_SIZE+FRAME_LR_SAVE(r1) + mtlr r0 +- addi r1,r1,112 ++ addi r1,r1,FRAME_MIN_SIZE + blr + END(_mcount) + +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S 2014-05-29 14:09:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S 2014-05-29 14:10:00.000000000 -0500 +@@ -56,7 +56,7 @@ + bugz #269. __GI__setjmp is used in csu/libc-start.c when + HAVE_CLEANUP_JMP_BUF is defined. */ + ENTRY (__GI__setjmp) +- std r2,40(r1) /* Save the callers TOC in the save area. */ ++ std r2,FRAME_TOC_SAVE(r1) /* Save the callers TOC in the save area. */ + CALL_MCOUNT 1 + li r4,0 /* Set second argument to 0. */ + b JUMPTARGET (GLUE(__sigsetjmp,_ent)) +@@ -83,7 +83,7 @@ + #endif + mflr r0 + #if defined SHARED && !defined IS_IN_rtld +- ld r5,40(r1) /* Retrieve the callers TOC. */ ++ ld r5,FRAME_TOC_SAVE(r1) /* Retrieve the callers TOC. */ + std r5,(JB_GPR2*8)(3) + #else + std r2,(JB_GPR2*8)(3) +@@ -219,14 +219,14 @@ + b JUMPTARGET (__sigjmp_save) + #else + mflr r0 +- std r0,16(r1) +- stdu r1,-112(r1) +- cfi_adjust_cfa_offset(112) +- cfi_offset(lr,16) ++ std r0,FRAME_LR_SAVE(r1) ++ stdu r1,-FRAME_MIN_SIZE(r1) ++ cfi_adjust_cfa_offset(FRAME_MIN_SIZE) ++ cfi_offset(lr,FRAME_LR_SAVE) + bl JUMPTARGET (__sigjmp_save) + nop +- ld r0,112+16(r1) +- addi r1,r1,112 ++ ld r0,FRAME_MIN_SIZE+FRAME_LR_SAVE(r1) ++ addi r1,r1,FRAME_MIN_SIZE + mtlr r0 + blr + #endif +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/sysdep.h glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/sysdep.h +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/sysdep.h 2014-05-29 14:09:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/sysdep.h 2014-05-29 14:10:00.000000000 -0500 +@@ -20,25 +20,67 @@ + + #ifdef __ASSEMBLER__ + ++/* Stack frame offsets. */ ++#if _CALL_ELF != 2 ++#define FRAME_MIN_SIZE 112 ++#define FRAME_MIN_SIZE_PARM 112 ++#define FRAME_BACKCHAIN 0 ++#define FRAME_CR_SAVE 8 ++#define FRAME_LR_SAVE 16 ++#define FRAME_TOC_SAVE 40 ++#define FRAME_PARM_SAVE 48 ++#define FRAME_PARM1_SAVE 48 ++#define FRAME_PARM2_SAVE 56 ++#define FRAME_PARM3_SAVE 64 ++#define FRAME_PARM4_SAVE 72 ++#define FRAME_PARM5_SAVE 80 ++#define FRAME_PARM6_SAVE 88 ++#define FRAME_PARM7_SAVE 96 ++#define FRAME_PARM8_SAVE 104 ++#define FRAME_PARM9_SAVE 112 ++#else ++#define FRAME_MIN_SIZE 32 ++#define FRAME_MIN_SIZE_PARM 96 ++#define FRAME_BACKCHAIN 0 ++#define FRAME_CR_SAVE 8 ++#define FRAME_LR_SAVE 16 ++#define FRAME_TOC_SAVE 24 ++#define FRAME_PARM_SAVE 32 ++#define FRAME_PARM1_SAVE 32 ++#define FRAME_PARM2_SAVE 40 ++#define FRAME_PARM3_SAVE 48 ++#define FRAME_PARM4_SAVE 56 ++#define FRAME_PARM5_SAVE 64 ++#define FRAME_PARM6_SAVE 72 ++#define FRAME_PARM7_SAVE 80 ++#define FRAME_PARM8_SAVE 88 ++#define FRAME_PARM9_SAVE 96 ++#endif ++ + /* Support macros for CALL_MCOUNT. */ ++#if _CALL_ELF == 2 ++#define call_mcount_parm_offset (-64) ++#else ++#define call_mcount_parm_offset FRAME_PARM_SAVE ++#endif + .macro SAVE_ARG NARG + .if \NARG + SAVE_ARG \NARG-1 +- std 2+\NARG,40+8*(\NARG)(1) ++ std 2+\NARG,call_mcount_parm_offset-8+8*(\NARG)(1) + .endif + .endm + + .macro REST_ARG NARG + .if \NARG + REST_ARG \NARG-1 +- ld 2+\NARG,112+40+8*(\NARG)(1) ++ ld 2+\NARG,FRAME_MIN_SIZE_PARM+call_mcount_parm_offset-8+8*(\NARG)(1) + .endif + .endm + + .macro CFI_SAVE_ARG NARG + .if \NARG + CFI_SAVE_ARG \NARG-1 +- cfi_offset(2+\NARG,40+8*(\NARG)) ++ cfi_offset(2+\NARG,call_mcount_parm_offset-8+8*(\NARG)) + .endif + .endm + +@@ -55,20 +97,20 @@ + #ifdef PROF + mflr r0 + SAVE_ARG \NARG +- std r0,16(r1) +- stdu r1,-112(r1) +- cfi_adjust_cfa_offset(112) +- cfi_offset(lr,16) ++ std r0,FRAME_LR_SAVE(r1) ++ stdu r1,-FRAME_MIN_SIZE_PARM(r1) ++ cfi_adjust_cfa_offset(FRAME_MIN_SIZE_PARM) ++ cfi_offset(lr,FRAME_LR_SAVE) + CFI_SAVE_ARG \NARG + bl JUMPTARGET (_mcount) + #ifndef SHARED + nop + #endif +- ld r0,128(r1) ++ ld r0,FRAME_MIN_SIZE_PARM+FRAME_LR_SAVE(r1) + REST_ARG \NARG + mtlr r0 +- addi r1,r1,112 +- cfi_adjust_cfa_offset(-112) ++ addi r1,r1,FRAME_MIN_SIZE_PARM ++ cfi_adjust_cfa_offset(-FRAME_MIN_SIZE_PARM) + cfi_restore(lr) + CFI_REST_ARG \NARG + #endif +@@ -267,15 +309,15 @@ + .else; \ + .Local_syscall_error: \ + mflr 0; \ +- std 0,16(1); \ +- stdu 1,-112(1); \ +- cfi_adjust_cfa_offset(112); \ +- cfi_offset(lr,16); \ ++ std 0,FRAME_LR_SAVE(1); \ ++ stdu 1,-FRAME_MIN_SIZE(1); \ ++ cfi_adjust_cfa_offset(FRAME_MIN_SIZE); \ ++ cfi_offset(lr,FRAME_LR_SAVE); \ + bl JUMPTARGET(__syscall_error); \ + nop; \ +- ld 0,112+16(1); \ +- addi 1,1,112; \ +- cfi_adjust_cfa_offset(-112); \ ++ ld 0,FRAME_MIN_SIZE+FRAME_LR_SAVE(1); \ ++ addi 1,1,FRAME_MIN_SIZE; \ ++ cfi_adjust_cfa_offset(-FRAME_MIN_SIZE); \ + mtlr 0; \ + cfi_restore(lr); \ + blr; \ +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/____longjmp_chk.S glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/____longjmp_chk.S +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/____longjmp_chk.S 2014-05-29 14:09:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/____longjmp_chk.S 2014-05-29 14:10:00.000000000 -0500 +@@ -33,24 +33,24 @@ + cmpld reg, r1; \ + bge+ .Lok; \ + mflr r0; \ +- std r0,16(r1); \ ++ std r0,FRAME_LR_SAVE(r1); \ + mr r31,r3; \ + mr r30,r4; \ +- stdu r1,-144(r1); \ ++ stdu r1,-FRAME_MIN_SIZE-32(r1); \ + cfi_remember_state; \ +- cfi_adjust_cfa_offset (144); \ +- cfi_offset (lr, 16); \ ++ cfi_adjust_cfa_offset (FRAME_MIN_SIZE+32); \ ++ cfi_offset (lr, FRAME_LR_SAVE); \ + li r3,0; \ +- addi r4,r1,112; \ ++ addi r4,r1,FRAME_MIN_SIZE; \ + li r0,__NR_sigaltstack; \ + sc; \ + /* Without working sigaltstack we cannot perform the test. */ \ + bso .Lok2; \ +- lwz r0,112+8(r1); \ ++ lwz r0,FRAME_MIN_SIZE+8(r1); \ + andi. r4,r0,1; \ + beq .Lfail; \ +- ld r0,112+16(r1); \ +- ld r4,112(r1); \ ++ ld r0,FRAME_MIN_SIZE+16(r1); \ ++ ld r4,FRAME_MIN_SIZE(r1); \ + add r4,r4,r0; \ + sub r3,r3,reg; \ + cmpld r3,r0; \ +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/brk.S glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/brk.S +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/brk.S 2014-05-29 14:09:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/brk.S 2014-05-29 14:10:00.000000000 -0500 +@@ -31,9 +31,9 @@ + CALL_MCOUNT 1 + DISCARD_BOUNDS (r3) /* the bounds are meaningless, so toss 'em. */ + +- std r3,48(r1) ++ std r3,-8(r1) + DO_CALL(SYS_ify(brk)) +- ld r6,48(r1) ++ ld r6,-8(r1) + ld r5,.LC__curbrk@toc(r2) + std r3,0(r5) + cmpld r6,r3 +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S 2014-05-29 14:09:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S 2014-05-29 14:10:00.000000000 -0500 +@@ -45,22 +45,22 @@ + cror cr0*4+eq,cr1*4+eq,cr0*4+eq + beq- cr0,L(badargs) + +- /* Save some regs in parm save area. */ ++ /* Save some regs in the "red zone". */ + #ifdef RESET_PID +- std r29,48(r1) ++ std r29,-24(r1) + #endif +- std r30,56(r1) +- std r31,64(r1) ++ std r30,-16(r1) ++ std r31,-8(r1) + #ifdef RESET_PID +- cfi_offset(r29,48) ++ cfi_offset(r29,-24) + #endif +- cfi_offset(r30,56) +- cfi_offset(r31,64) ++ cfi_offset(r30,-16) ++ cfi_offset(r31,-8) + + /* Set up stack frame for child. */ + clrrdi r4,r4,4 + li r0,0 +- stdu r0,-112(r4) /* min stack frame is 112 bytes per ABI */ ++ stdu r0,-FRAME_MIN_SIZE_PARM(r4) + + /* Save fn, args, stack across syscall. */ + mr r30,r3 /* Function in r30. */ +@@ -102,12 +102,12 @@ + L(oldpid): + #endif + +- std r2,40(r1) ++ std r2,FRAME_TOC_SAVE(r1) + /* Call procedure. */ + PPC64_LOAD_FUNCPTR r30 + mr r3,r31 + bctrl +- ld r2,40(r1) ++ ld r2,FRAME_TOC_SAVE(r1) + /* Call _exit with result from procedure. */ + #ifdef SHARED + b JUMPTARGET(__GI__exit) +@@ -126,15 +126,15 @@ + L(parent): + /* Parent. Restore registers & return. */ + #ifdef RESET_PID +- cfi_offset(r29,48) ++ cfi_offset(r29,-24) + #endif +- cfi_offset(r30,56) +- cfi_offset(r31,64) ++ cfi_offset(r30,-16) ++ cfi_offset(r31,-8) + #ifdef RESET_PID +- ld r29,48(r1) ++ ld r29,-24(r1) + #endif +- ld r30,56(r1) +- ld r31,64(r1) ++ ld r30,-16(r1) ++ ld r31,-8(r1) + #ifdef RESET_PID + cfi_restore(r29) + #endif +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S 2014-05-29 14:09:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S 2014-05-29 14:10:00.000000000 -0500 +@@ -46,8 +46,13 @@ + # endif + #endif + +-#define FRAMESIZE 128 +-#define stackblock FRAMESIZE+48 /* offset to parm save area. */ ++#if _CALL_ELF == 2 ++#define FRAMESIZE (FRAME_MIN_SIZE+16+64) ++#define stackblock (FRAME_MIN_SIZE+16) ++#else ++#define FRAMESIZE (FRAME_MIN_SIZE+16) ++#define stackblock (FRAMESIZE+FRAME_PARM_SAVE) /* offset to parm save area. */ ++#endif + + .text + ENTRY(__socket) +@@ -98,22 +103,22 @@ + .Lsocket_cancel: + cfi_adjust_cfa_offset(FRAMESIZE) + mflr r9 +- std r9,FRAMESIZE+16(r1) +- cfi_offset (lr, 16) ++ std r9,FRAMESIZE+FRAME_LR_SAVE(r1) ++ cfi_offset (lr, FRAME_LR_SAVE) + CENABLE +- std r3,120(r1) ++ std r3,FRAME_MIN_SIZE+8(r1) + li r3,P(SOCKOP_,socket) + addi r4,r1,stackblock + DO_CALL(SYS_ify(socketcall)) + mfcr r0 +- std r3,112(r1) +- std r0,FRAMESIZE+8(r1) +- cfi_offset (cr, 8) +- ld r3,120(r1) ++ std r3,FRAME_MIN_SIZE(r1) ++ std r0,FRAMESIZE+FRAME_CR_SAVE(r1) ++ cfi_offset (cr, FRAME_CR_SAVE) ++ ld r3,FRAME_MIN_SIZE+8(r1) + CDISABLE +- ld r4,FRAMESIZE+16(r1) +- ld r0,FRAMESIZE+8(r1) +- ld r3,112(r1) ++ ld r4,FRAMESIZE+FRAME_LR_SAVE(r1) ++ ld r0,FRAMESIZE+FRAME_CR_SAVE(r1) ++ ld r3,FRAME_MIN_SIZE(r1) + mtlr r4 + mtcr r0 + addi r1,r1,FRAMESIZE +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/ucontext_i.sym glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/ucontext_i.sym +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/ucontext_i.sym 2014-05-29 14:09:56.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/ucontext_i.sym 2014-05-29 14:10:00.000000000 -0500 +@@ -8,27 +8,6 @@ + SIG_SETMASK + + +--- Offsets of the fields in the powerpc64 ABI stack frame. +--- XXX Do these correspond to some struct? +- +-FRAME_BACKCHAIN 0 +-FRAME_CR_SAVE 8 +-FRAME_LR_SAVE 16 +-FRAME_COMPILER_DW 24 +-FRAME_LINKER_DW 32 +-FRAME_TOC_SAVE 40 +-FRAME_PARM_SAVE 48 +-FRAME_PARM1_SAVE 48 +-FRAME_PARM2_SAVE 56 +-FRAME_PARM3_SAVE 64 +-FRAME_PARM4_SAVE 72 +-FRAME_PARM5_SAVE 80 +-FRAME_PARM6_SAVE 88 +-FRAME_PARM7_SAVE 96 +-FRAME_PARM8_SAVE 104 +-FRAME_PARM9_SAVE 112 +- +- + -- Offsets of the fields in the ucontext_t structure. + #define ucontext(member) offsetof (ucontext_t, member) + #define mcontext(member) ucontext (uc_mcontext.member) diff --git a/SOURCES/glibc-ppc64le-42.patch b/SOURCES/glibc-ppc64le-42.patch new file mode 100644 index 0000000..f5fa53e --- /dev/null +++ b/SOURCES/glibc-ppc64le-42.patch @@ -0,0 +1,404 @@ +# commit 61cd8fe4017c251617dd300818917e61a12ab48e +# Author: Ulrich Weigand +# Date: Wed Dec 4 06:59:37 2013 -0600 +# +# PowerPC64 ELFv2 ABI 5/6: LD_AUDIT interface changes +# +# The ELFv2 ABI changes the calling convention by passing and returning +# structures in registers in more cases than the old ABI: +# http://gcc.gnu.org/ml/gcc-patches/2013-11/msg01145.html +# http://gcc.gnu.org/ml/gcc-patches/2013-11/msg01147.html +# +# For the most part, this does not affect glibc, since glibc assembler +# files do not use structure parameters / return values. However, one +# place is affected: the LD_AUDIT interface provides a structure to +# the audit routine that contains all registers holding function +# argument and return values for the intercepted PLT call. +# +# Since the new ABI now sometimes uses registers to return values +# that were never used for this purpose in the old ABI, this structure +# has to be extended. To force audit routines to be modified for the +# new ABI if necessary, the patch defines v2 variants of the la_ppc64 +# types and routines. +# +# In addition, the patch contains two unrelated changes to the +# PLT trampoline routines: it fixes a bug where FPR return values +# were stored in the wrong place, and it removes the unnecessary +# save/restore of CR. +# +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/bits/link.h glibc-2.17-c758a686/sysdeps/powerpc/bits/link.h +--- glibc-2.17-c758a686/sysdeps/powerpc/bits/link.h 2014-05-29 14:11:12.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/bits/link.h 2014-05-29 14:11:20.000000000 -0500 +@@ -63,7 +63,7 @@ + + __END_DECLS + +-#else ++#elif _CALL_ELF != 2 + + /* Registers for entry into PLT on PPC64. */ + typedef struct La_ppc64_regs +@@ -107,4 +107,48 @@ + + __END_DECLS + ++#else ++ ++/* Registers for entry into PLT on PPC64 in the ELFv2 ABI. */ ++typedef struct La_ppc64v2_regs ++{ ++ uint64_t lr_reg[8]; ++ double lr_fp[13]; ++ uint32_t __padding; ++ uint32_t lr_vrsave; ++ uint32_t lr_vreg[12][4] __attribute__ ((aligned (16))); ++ uint64_t lr_r1; ++ uint64_t lr_lr; ++} La_ppc64v2_regs; ++ ++/* Return values for calls from PLT on PPC64 in the ELFv2 ABI. */ ++typedef struct La_ppc64v2_retval ++{ ++ uint64_t lrv_r3; ++ uint64_t lrv_r4; ++ double lrv_fp[10]; ++ uint32_t lrv_vreg[8][4] __attribute__ ((aligned (16))); ++} La_ppc64v2_retval; ++ ++ ++__BEGIN_DECLS ++ ++extern Elf64_Addr la_ppc64v2_gnu_pltenter (Elf64_Sym *__sym, ++ unsigned int __ndx, ++ uintptr_t *__refcook, ++ uintptr_t *__defcook, ++ La_ppc64v2_regs *__regs, ++ unsigned int *__flags, ++ const char *__symname, ++ long int *__framesizep); ++extern unsigned int la_ppc64v2_gnu_pltexit (Elf64_Sym *__sym, ++ unsigned int __ndx, ++ uintptr_t *__refcook, ++ uintptr_t *__defcook, ++ const La_ppc64v2_regs *__inregs, ++ La_ppc64v2_retval *__outregs, ++ const char *__symname); ++ ++__END_DECLS ++ + #endif +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/ldsodefs.h glibc-2.17-c758a686/sysdeps/powerpc/ldsodefs.h +--- glibc-2.17-c758a686/sysdeps/powerpc/ldsodefs.h 2014-05-29 14:11:12.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/ldsodefs.h 2014-05-29 14:11:20.000000000 -0500 +@@ -25,6 +25,8 @@ + struct La_ppc32_retval; + struct La_ppc64_regs; + struct La_ppc64_retval; ++struct La_ppc64v2_regs; ++struct La_ppc64v2_retval; + + #define ARCH_PLTENTER_MEMBERS \ + Elf32_Addr (*ppc32_gnu_pltenter) (Elf32_Sym *, unsigned int, uintptr_t *, \ +@@ -34,7 +36,12 @@ + Elf64_Addr (*ppc64_gnu_pltenter) (Elf64_Sym *, unsigned int, uintptr_t *, \ + uintptr_t *, struct La_ppc64_regs *, \ + unsigned int *, const char *name, \ +- long int *framesizep) ++ long int *framesizep); \ ++ Elf64_Addr (*ppc64v2_gnu_pltenter) (Elf64_Sym *, unsigned int, \ ++ uintptr_t *, uintptr_t *, \ ++ struct La_ppc64v2_regs *, \ ++ unsigned int *, const char *name, \ ++ long int *framesizep) + + #define ARCH_PLTEXIT_MEMBERS \ + unsigned int (*ppc32_gnu_pltexit) (Elf32_Sym *, unsigned int, \ +@@ -47,7 +54,14 @@ + uintptr_t *, \ + uintptr_t *, \ + const struct La_ppc64_regs *, \ +- struct La_ppc64_retval *, const char *) ++ struct La_ppc64_retval *, \ ++ const char *); \ ++ unsigned int (*ppc64v2_gnu_pltexit) (Elf64_Sym *, unsigned int, \ ++ uintptr_t *, \ ++ uintptr_t *, \ ++ const struct La_ppc64v2_regs *,\ ++ struct La_ppc64v2_retval *, \ ++ const char *) + + #include_next + +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h 2014-05-29 14:11:12.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h 2014-05-29 14:11:20.000000000 -0500 +@@ -546,8 +546,13 @@ + + + /* Names of the architecture-specific auditing callback functions. */ ++#if _CALL_ELF != 2 + #define ARCH_LA_PLTENTER ppc64_gnu_pltenter + #define ARCH_LA_PLTEXIT ppc64_gnu_pltexit ++#else ++#define ARCH_LA_PLTENTER ppc64v2_gnu_pltenter ++#define ARCH_LA_PLTEXIT ppc64v2_gnu_pltexit ++#endif + + #endif /* dl_machine_h */ + +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-trampoline.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-trampoline.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-trampoline.S 2014-05-29 14:11:12.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-trampoline.S 2014-05-29 14:11:20.000000000 -0500 +@@ -50,11 +50,8 @@ + /* Store the LR in the LR Save area. */ + std r0,FRAME_SIZE+FRAME_LR_SAVE(r1) + cfi_offset (lr, FRAME_LR_SAVE) +- mfcr r0 + std r9,INT_PARMS+48(r1) + std r10,INT_PARMS+56(r1) +-/* I'm almost certain we don't have to save cr... be safe. */ +- std r0,FRAME_SIZE+FRAME_CR_SAVE(r1) + bl JUMPTARGET(_dl_fixup) + #ifndef SHARED + nop +@@ -66,11 +63,9 @@ + ld r8,INT_PARMS+40(r1) + ld r7,INT_PARMS+32(r1) + mtlr r0 +- ld r0,FRAME_SIZE+FRAME_CR_SAVE(r1) + ld r6,INT_PARMS+24(r1) + ld r5,INT_PARMS+16(r1) + ld r4,INT_PARMS+8(r1) +- mtcrf 0xFF,r0 + /* Prepare for calling the function returned by fixup. */ + PPC64_LOAD_FUNCPTR r3 + ld r3,INT_PARMS+0(r1) +@@ -85,18 +80,30 @@ + #undef FRAME_SIZE + #undef INT_PARMS + +- /* Stack layout: +- (Note: some of these are not required for the ELFv2 ABI.) +- +592 previous backchain +- +584 spill_r31 +- +576 spill_r30 +- +560 v1 +- +552 fp4 +- +544 fp3 +- +536 fp2 +- +528 fp1 +- +520 r4 +- +512 r3 ++ /* Stack layout: ELFv2 ABI. ++ +752 previous backchain ++ +744 spill_r31 ++ +736 spill_r30 ++ +720 v8 ++ +704 v7 ++ +688 v6 ++ +672 v5 ++ +656 v4 ++ +640 v3 ++ +624 v2 ++ +608 v1 ++ +600 fp10 ++ ELFv1 ABI +592 fp9 ++ +592 previous backchain +584 fp8 ++ +584 spill_r31 +576 fp7 ++ +576 spill_r30 +568 fp6 ++ +560 v1 +560 fp5 ++ +552 fp4 +552 fp4 ++ +544 fp3 +544 fp3 ++ +536 fp2 +536 fp2 ++ +528 fp1 +528 fp1 ++ +520 r4 +520 r4 ++ +512 r3 +512 r3 + return values + +504 free + +496 stackframe +@@ -157,10 +164,15 @@ + +8 CR save area + r1+0 stack back chain + */ +-#define FRAME_SIZE 592 ++#if _CALL_ELF == 2 ++# define FRAME_SIZE 752 ++# define VR_RTN 608 ++#else ++# define FRAME_SIZE 592 ++# define VR_RTN 560 ++#endif + #define INT_RTN 512 + #define FPR_RTN 528 +-#define VR_RTN 560 + #define STACK_FRAME 496 + #define CALLING_LR 488 + #define CALLING_SP 480 +@@ -205,18 +217,14 @@ + mflr r5 + std r7,INT_PARMS+32(r1) + std r8,INT_PARMS+40(r1) +-/* Store the LR in the LR Save area of the previous frame. */ +-/* XXX Do we have to do this? */ ++/* Store the LR in the LR Save area. */ + la r8,FRAME_SIZE(r1) + std r5,FRAME_SIZE+FRAME_LR_SAVE(r1) + cfi_offset (lr, FRAME_LR_SAVE) + std r5,CALLING_LR(r1) +- mfcr r0 + std r9,INT_PARMS+48(r1) + std r10,INT_PARMS+56(r1) + std r8,CALLING_SP(r1) +-/* I'm almost certain we don't have to save cr... be safe. */ +- std r0,FRAME_SIZE+FRAME_CR_SAVE(r1) + ld r12,.LC__dl_hwcap@toc(r2) + #ifdef SHARED + /* Load _rtld_local_ro._dl_hwcap. */ +@@ -319,11 +327,9 @@ + ld r8,INT_PARMS+40(r1) + ld r7,INT_PARMS+32(r1) + mtlr r0 +- ld r0,FRAME_SIZE+FRAME_CR_SAVE(r1) + ld r6,INT_PARMS+24(r1) + ld r5,INT_PARMS+16(r1) + ld r4,INT_PARMS+8(r1) +- mtcrf 0xFF,r0 + /* Prepare for calling the function returned by fixup. */ + PPC64_LOAD_FUNCPTR r3 + ld r3,INT_PARMS+0(r1) +@@ -346,10 +352,11 @@ + lfd fp12,FPR_PARMS+88(r1) + lfd fp13,FPR_PARMS+96(r1) + /* Unwind the stack frame, and jump. */ +- ld r31,584(r1) +- ld r30,576(r1) ++ ld r31,FRAME_SIZE-8(r1) ++ ld r30,FRAME_SIZE-16(r1) + addi r1,r1,FRAME_SIZE + bctr ++ + L(do_pltexit): + la r10,(VR_PARMS+0)(r1) + la r9,(VR_PARMS+16)(r1) +@@ -383,11 +390,9 @@ + ld r8,INT_PARMS+40(r1) + ld r7,INT_PARMS+32(r1) + mtlr r0 +- ld r0,FRAME_SIZE+FRAME_CR_SAVE(r1) + ld r6,INT_PARMS+24(r1) + ld r5,INT_PARMS+16(r1) + ld r4,INT_PARMS+8(r1) +- mtcrf 0xFF,r0 + /* Prepare for calling the function returned by fixup. */ + std r2,FRAME_TOC_SAVE(r1) + PPC64_LOAD_FUNCPTR r3 +@@ -413,16 +418,37 @@ + /* But return here and store the return values. */ + std r3,INT_RTN(r1) + std r4,INT_RTN+8(r1) +- stfd fp1,FPR_PARMS+0(r1) +- stfd fp2,FPR_PARMS+8(r1) ++ stfd fp1,FPR_RTN+0(r1) ++ stfd fp2,FPR_RTN+8(r1) + cmpdi cr0,r12,0 + la r10,VR_RTN(r1) +- stfd fp3,FPR_PARMS+16(r1) +- stfd fp4,FPR_PARMS+24(r1) ++ stfd fp3,FPR_RTN+16(r1) ++ stfd fp4,FPR_RTN+24(r1) ++#if _CALL_ELF == 2 ++ la r12,VR_RTN+16(r1) ++ stfd fp5,FPR_RTN+32(r1) ++ stfd fp6,FPR_RTN+40(r1) ++ li r5,32 ++ li r6,64 ++ stfd fp7,FPR_RTN+48(r1) ++ stfd fp8,FPR_RTN+56(r1) ++ stfd fp9,FPR_RTN+64(r1) ++ stfd fp10,FPR_RTN+72(r1) ++#endif + mr r3,r31 + mr r4,r30 + beq L(callpltexit) + stvx v2,0,r10 ++#if _CALL_ELF == 2 ++ stvx v3,0,r12 ++ stvx v4,r5,r10 ++ stvx v5,r5,r12 ++ addi r5,r5,64 ++ stvx v6,r6,r10 ++ stvx v7,r6,r12 ++ stvx v8,r5,r10 ++ stvx v9,r5,r12 ++#endif + L(callpltexit): + addi r5,r1,INT_PARMS + addi r6,r1,INT_RTN +@@ -434,18 +460,39 @@ + lwz r12,VR_VRSAVE(r1) + ld r3,INT_RTN(r1) + ld r4,INT_RTN+8(r1) +- lfd fp1,FPR_PARMS+0(r1) +- lfd fp2,FPR_PARMS+8(r1) ++ lfd fp1,FPR_RTN+0(r1) ++ lfd fp2,FPR_RTN+8(r1) + cmpdi cr0,r12,0 +- la r10,VR_RTN(r1) +- lfd fp3,FPR_PARMS+16(r1) +- lfd fp4,FPR_PARMS+24(r1) ++ la r11,VR_RTN(r1) ++ lfd fp3,FPR_RTN+16(r1) ++ lfd fp4,FPR_RTN+24(r1) ++#if _CALL_ELF == 2 ++ la r12,VR_RTN+16(r1) ++ lfd fp5,FPR_RTN+32(r1) ++ lfd fp6,FPR_RTN+40(r1) ++ li r30,32 ++ li r31,64 ++ lfd fp7,FPR_RTN+48(r1) ++ lfd fp8,FPR_RTN+56(r1) ++ lfd fp9,FPR_RTN+64(r1) ++ lfd fp10,FPR_RTN+72(r1) ++#endif + beq L(pltexitreturn) +- lvx v2,0,r10 ++ lvx v2,0,r11 ++#if _CALL_ELF == 2 ++ lvx v3,0,r12 ++ lvx v4,r30,r11 ++ lvx v5,r30,r12 ++ addi r30,r30,64 ++ lvx v6,r31,r11 ++ lvx v7,r31,r12 ++ lvx v8,r30,r11 ++ lvx v9,r30,r12 ++#endif + L(pltexitreturn): + ld r0,FRAME_SIZE+FRAME_LR_SAVE(r1) +- ld r31,584(r1) +- ld r30,576(r1) ++ ld r31,FRAME_SIZE-8(r1) ++ ld r30,FRAME_SIZE-16(r1) + mtlr r0 + ld r1,0(r1) + blr +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/tst-audit.h glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/tst-audit.h +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/tst-audit.h 2014-05-29 14:11:12.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/tst-audit.h 2014-05-29 14:11:20.000000000 -0500 +@@ -18,8 +18,16 @@ + License along with the GNU C Library. If not, see + . */ + ++#if _CALL_ELF != 2 + #define pltenter la_ppc64_gnu_pltenter + #define pltexit la_ppc64_gnu_pltexit + #define La_regs La_ppc64_regs + #define La_retval La_ppc64_retval + #define int_retval lrv_r3 ++#else ++#define pltenter la_ppc64v2_gnu_pltenter ++#define pltexit la_ppc64v2_gnu_pltexit ++#define La_regs La_ppc64v2_regs ++#define La_retval La_ppc64v2_retval ++#define int_retval lrv_r3 ++#endif diff --git a/SOURCES/glibc-ppc64le-43.patch b/SOURCES/glibc-ppc64le-43.patch new file mode 100644 index 0000000..8c43abb --- /dev/null +++ b/SOURCES/glibc-ppc64le-43.patch @@ -0,0 +1,248 @@ +# commit 5b118558f9fb0620508d51c34c2cb5ba4f1f01c2 +# Author: Ulrich Weigand +# Date: Wed Dec 4 07:08:48 2013 -0600 +# +# PowerPC64 ELFv2 ABI 6/6: Bump ld.so soname version number +# +# To avoid having a ELFv2 binary accidentally picking up an old ABI ld.so, +# this patch bumps the soname to ld64.so.2. +# +# In theory (or for testing purposes) this will also allow co-installing +# ld.so versions for both ABIs on the same system. Note that the kernel +# will already be able to load executables of both ABIs. However, there +# is currently no plan to use that theoretical possibility in a any +# supported distribution environment ... +# +# Note that in order to check which ABI to use, we need to invoke the +# compiler to check the _CALL_ELF macro; this is done in a new configure +# check in sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac, +# replacing the hard-coded value of default-abi in the Makefile. +# +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/Makefile glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/Makefile +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/Makefile 2014-05-29 14:12:25.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/Makefile 2014-05-29 14:12:30.000000000 -0500 +@@ -1,9 +1,12 @@ +-abi-variants := 32 64 ++abi-variants := 32 64-v1 64-v2 + abi-32-options := -U__powerpc64__ + abi-32-condition := __WORDSIZE == 32 +-abi-64-options := -D__powerpc64__ +-abi-64-condition := __WORDSIZE == 64 +-abi-64-ld-soname := ld64.so.1 ++abi-64-v1-options := -D__powerpc64__ -U_CALL_ELF -D_CALL_ELF=1 ++abi-64-v1-condition := __WORDSIZE == 64 && _CALL_ELF != 2 ++abi-64-v1-ld-soname := ld64.so.1 ++abi-64-v2-options := -D__powerpc64__ -U_CALL_ELF -D_CALL_ELF=2 ++abi-64-v2-condition := __WORDSIZE == 64 && _CALL_ELF == 2 ++abi-64-v2-ld-soname := ld64.so.2 + + ifeq ($(subdir),rt) + librt-routines += rt-sysdep +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/ldconfig.h glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/ldconfig.h +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/ldconfig.h 2014-05-29 14:12:25.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/ldconfig.h 2014-05-29 14:12:30.000000000 -0500 +@@ -20,7 +20,8 @@ + + #define SYSDEP_KNOWN_INTERPRETER_NAMES \ + { "/lib/ld.so.1", FLAG_ELF_LIBC6 }, \ +- { "/lib64/ld64.so.1", FLAG_ELF_LIBC6 }, ++ { "/lib64/ld64.so.1", FLAG_ELF_LIBC6 }, \ ++ { "/lib64/ld64.so.2", FLAG_ELF_LIBC6 }, + #define SYSDEP_KNOWN_LIBRARY_NAMES \ + { "libc.so.6", FLAG_ELF_LIBC6 }, \ + { "libm.so.6", FLAG_ELF_LIBC6 }, +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/Makefile glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/Makefile +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/Makefile 2014-05-29 14:12:25.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/Makefile 1969-12-31 18:00:00.000000000 -0600 +@@ -1,2 +0,0 @@ +-# See Makeconfig regarding the use of default-abi. +-default-abi := 64 +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure 1969-12-31 18:00:00.000000000 -0600 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure 2014-05-29 14:12:30.000000000 -0500 +@@ -0,0 +1,166 @@ ++# This file is generated from configure.ac by Autoconf. DO NOT EDIT! ++ # Local configure fragment for sysdeps/unix/sysv/linux/powerpc/powerpc64/. ++ ++# Define default-abi according to compiler flags. ++ ++ ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 ++$as_echo_n "checking for grep that handles long lines and -e... " >&6; } ++if ${ac_cv_path_GREP+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test -z "$GREP"; then ++ ac_path_GREP_found=false ++ # Loop through the user's path and test for each of PROGNAME-LIST ++ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_prog in grep ggrep; do ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" ++ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue ++# Check for GNU ac_path_GREP and select it if it is found. ++ # Check for GNU $ac_path_GREP ++case `"$ac_path_GREP" --version 2>&1` in ++*GNU*) ++ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; ++*) ++ ac_count=0 ++ $as_echo_n 0123456789 >"conftest.in" ++ while : ++ do ++ cat "conftest.in" "conftest.in" >"conftest.tmp" ++ mv "conftest.tmp" "conftest.in" ++ cp "conftest.in" "conftest.nl" ++ $as_echo 'GREP' >> "conftest.nl" ++ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break ++ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break ++ as_fn_arith $ac_count + 1 && ac_count=$as_val ++ if test $ac_count -gt ${ac_path_GREP_max-0}; then ++ # Best one so far, save it but keep looking for a better one ++ ac_cv_path_GREP="$ac_path_GREP" ++ ac_path_GREP_max=$ac_count ++ fi ++ # 10*(2^10) chars as input seems more than enough ++ test $ac_count -gt 10 && break ++ done ++ rm -f conftest.in conftest.tmp conftest.nl conftest.out;; ++esac ++ ++ $ac_path_GREP_found && break 3 ++ done ++ done ++ done ++IFS=$as_save_IFS ++ if test -z "$ac_cv_path_GREP"; then ++ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 ++ fi ++else ++ ac_cv_path_GREP=$GREP ++fi ++ ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 ++$as_echo "$ac_cv_path_GREP" >&6; } ++ GREP="$ac_cv_path_GREP" ++ ++ ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 ++$as_echo_n "checking for egrep... " >&6; } ++if ${ac_cv_path_EGREP+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 ++ then ac_cv_path_EGREP="$GREP -E" ++ else ++ if test -z "$EGREP"; then ++ ac_path_EGREP_found=false ++ # Loop through the user's path and test for each of PROGNAME-LIST ++ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_prog in egrep; do ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" ++ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue ++# Check for GNU ac_path_EGREP and select it if it is found. ++ # Check for GNU $ac_path_EGREP ++case `"$ac_path_EGREP" --version 2>&1` in ++*GNU*) ++ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; ++*) ++ ac_count=0 ++ $as_echo_n 0123456789 >"conftest.in" ++ while : ++ do ++ cat "conftest.in" "conftest.in" >"conftest.tmp" ++ mv "conftest.tmp" "conftest.in" ++ cp "conftest.in" "conftest.nl" ++ $as_echo 'EGREP' >> "conftest.nl" ++ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break ++ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break ++ as_fn_arith $ac_count + 1 && ac_count=$as_val ++ if test $ac_count -gt ${ac_path_EGREP_max-0}; then ++ # Best one so far, save it but keep looking for a better one ++ ac_cv_path_EGREP="$ac_path_EGREP" ++ ac_path_EGREP_max=$ac_count ++ fi ++ # 10*(2^10) chars as input seems more than enough ++ test $ac_count -gt 10 && break ++ done ++ rm -f conftest.in conftest.tmp conftest.nl conftest.out;; ++esac ++ ++ $ac_path_EGREP_found && break 3 ++ done ++ done ++ done ++IFS=$as_save_IFS ++ if test -z "$ac_cv_path_EGREP"; then ++ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 ++ fi ++else ++ ac_cv_path_EGREP=$EGREP ++fi ++ ++ fi ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 ++$as_echo "$ac_cv_path_EGREP" >&6; } ++ EGREP="$ac_cv_path_EGREP" ++ ++ ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler is using the PowerPC64 ELFv2 ABI" >&5 ++$as_echo_n "checking whether the compiler is using the PowerPC64 ELFv2 ABI... " >&6; } ++if ${libc_cv_ppc64_elfv2_abi+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#if _CALL_ELF == 2 ++ yes ++ #endif ++ ++_ACEOF ++if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | ++ $EGREP "yes" >/dev/null 2>&1; then : ++ libc_cv_ppc64_elfv2_abi=yes ++else ++ libc_cv_ppc64_elfv2_abi=no ++fi ++rm -f conftest* ++ ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ppc64_elfv2_abi" >&5 ++$as_echo "$libc_cv_ppc64_elfv2_abi" >&6; } ++if test $libc_cv_ppc64_elfv2_abi = yes; then ++ config_vars="$config_vars ++default-abi = 64-v2" ++else ++ config_vars="$config_vars ++default-abi = 64-v1" ++fi +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac 1969-12-31 18:00:00.000000000 -0600 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac 2014-05-29 14:12:30.000000000 -0500 +@@ -0,0 +1,15 @@ ++GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory. ++# Local configure fragment for sysdeps/unix/sysv/linux/powerpc/powerpc64/. ++ ++# Define default-abi according to compiler flags. ++AC_CACHE_CHECK([whether the compiler is using the PowerPC64 ELFv2 ABI], ++ [libc_cv_ppc64_elfv2_abi], ++ [AC_EGREP_CPP(yes,[#if _CALL_ELF == 2 ++ yes ++ #endif ++ ], libc_cv_ppc64_elfv2_abi=yes, libc_cv_ppc64_elfv2_abi=no)]) ++if test $libc_cv_ppc64_elfv2_abi = yes; then ++ LIBC_CONFIG_VAR([default-abi], [64-v2]) ++else ++ LIBC_CONFIG_VAR([default-abi], [64-v1]) ++fi diff --git a/SOURCES/glibc-ppc64le-44.patch b/SOURCES/glibc-ppc64le-44.patch new file mode 100644 index 0000000..e074cb9 --- /dev/null +++ b/SOURCES/glibc-ppc64le-44.patch @@ -0,0 +1,26 @@ +# commit c859b32e9d76afe8a3f20bb9528961a573c06937 +# Author: Alan Modra +# Date: Tue Apr 1 14:07:42 2014 +1030 +# +# Fix s_copysign stack temp for PowerPC64 ELFv2 +# +# [BZ #16786] +# * sysdeps/powerpc/powerpc64/fpu/s_copysign.S: Don't trash stack. +# +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_copysign.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_copysign.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_copysign.S 2014-05-29 14:13:47.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/fpu/s_copysign.S 2014-05-29 14:13:50.000000000 -0500 +@@ -27,11 +27,11 @@ + /* double [f1] copysign (double [f1] x, double [f2] y); + copysign(x,y) returns a value with the magnitude of x and + with the sign bit of y. */ +- stfd fp2,56(r1) ++ stfd fp2,-8(r1) + nop + nop + nop +- ld r3,56(r1) ++ ld r3,-8(r1) + cmpdi r3,0 + blt L(0) + fabs fp1,fp1 diff --git a/SOURCES/glibc-ppc64le-45.patch b/SOURCES/glibc-ppc64le-45.patch new file mode 100644 index 0000000..9030fc2 --- /dev/null +++ b/SOURCES/glibc-ppc64le-45.patch @@ -0,0 +1,33 @@ +# +# For PPC64LE only! +# +# This is fixed upstream by the removal of Versions.def +# and auto-generation of the SHLIB_COMPAT required entries. +# See: https://sourceware.org/ml/libc-alpha/2014-02/msg00818.html +# Backporting that infrastructure to RHEL 7.x is too much work +# at this junction for little reward. Instead we simply fix up +# the Versions.def to include GLIBC_2.3 which is used by +# nptl/old_pthread_atfork.c, otherwise ppc64le will get +# pthread_atfork in libpthread.so.0 when it should not. +# +# The ABI testing for libpthread.so now passes for ppc64le. +# +diff -urN glibc-2.17-c758a686/Versions.def glibc-2.17-c758a686/Versions.def +--- glibc-2.17-c758a686/Versions.def 2014-06-02 21:13:12.000000000 +0000 ++++ glibc-2.17-c758a686/Versions.def 2014-06-02 21:14:38.000000000 +0000 +@@ -92,6 +92,7 @@ + GLIBC_2.2 + GLIBC_2.2.3 + GLIBC_2.2.6 ++ GLIBC_2.3 + GLIBC_2.3.2 + GLIBC_2.3.3 + GLIBC_2.3.4 +@@ -99,6 +100,7 @@ + GLIBC_2.6 + GLIBC_2.11 + GLIBC_2.12 ++ GLIBC_2.17 + GLIBC_PRIVATE + } + libresolv { diff --git a/SOURCES/glibc-ppc64le-46.patch b/SOURCES/glibc-ppc64le-46.patch new file mode 100644 index 0000000..6f3d1d9 --- /dev/null +++ b/SOURCES/glibc-ppc64le-46.patch @@ -0,0 +1,22 @@ +# +# On POWER this patch also fixes test-ildoubl and test-ldouble failures where tan +# rounded toward zero had acceptable 1 ULP error. Upstream is using 3 ULP, but +# we prefer to keep the bound tighter unless we have a reason not to. +# +# This is the ppc64le version which is required becuase it applies *after* another +# ppc64le patch that touches the same ULPs file. See glibc-power-libm-test-ulps.patch +# for the ppc64/ppc version. +# +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/fpu/libm-test-ulps glibc-2.17-c758a686/sysdeps/powerpc/fpu/libm-test-ulps +--- glibc-2.17-c758a686/sysdeps/powerpc/fpu/libm-test-ulps 2014-07-25 22:07:06.280020855 -0400 ++++ glibc-2.17-c758a686/sysdeps/powerpc/fpu/libm-test-ulps 2014-07-25 22:26:54.650021033 -0400 +@@ -2644,6 +2644,9 @@ + Test "tan_towardzero (2)": + ildouble: 1 + ldouble: 1 ++Test "tan_towardzero (2) == -2.1850398632615189916433061023136825434320": ++ildouble: 1 ++ldouble: 1 + Test "tan_towardzero (3) == -0.1425465430742778052956354105339134932261": + float: 1 + ifloat: 1 diff --git a/SOURCES/glibc-rh1000923.patch b/SOURCES/glibc-rh1000923.patch new file mode 100644 index 0000000..afc6f63 --- /dev/null +++ b/SOURCES/glibc-rh1000923.patch @@ -0,0 +1,32 @@ +commit 595aba70a4c676f7efaf6a012f54cd22aa189c5b +Author: Siddhesh Poyarekar +Date: Mon Aug 26 15:42:29 2013 +0530 + + Initialize res_hconf in nscd + + Fixes BZ #15890. + +diff -pruN glibc-2.17-c758a686/nscd/aicache.c glibc-2.17-c758a686/nscd/aicache.c +--- glibc-2.17-c758a686/nscd/aicache.c 2013-08-11 04:22:55.000000000 +0530 ++++ glibc-2.17-c758a686/nscd/aicache.c 2013-08-26 11:10:25.843470413 +0530 +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #include "dbg_log.h" + #include "nscd.h" +@@ -100,8 +101,11 @@ addhstaiX (struct database_dyn *db, int + no_more = __nss_database_lookup ("hosts", NULL, + "dns [!UNAVAIL=return] files", &nip); + ++ /* Initialize configurations. */ ++ if (__builtin_expect (!_res_hconf.initialized, 0)) ++ _res_hconf_init (); + if (__res_maybe_init (&_res, 0) == -1) +- no_more = 1; ++ no_more = 1; + + /* If we are looking for both IPv4 and IPv6 address we don't want + the lookup functions to automatically promote IPv4 addresses to diff --git a/SOURCES/glibc-rh1008298.patch b/SOURCES/glibc-rh1008298.patch new file mode 100644 index 0000000..9d7b35c --- /dev/null +++ b/SOURCES/glibc-rh1008298.patch @@ -0,0 +1,46 @@ +diff --git glibc-2.17-c758a686/malloc/malloc.c glibc-2.17-c758a686/malloc/malloc.c +index 3148c5f..f7718a9 100644 +--- glibc-2.17-c758a686/malloc/malloc.c ++++ glibc-2.17-c758a686/malloc/malloc.c +@@ -3015,6 +3015,13 @@ __libc_memalign(size_t alignment, size_t bytes) + /* Otherwise, ensure that it is at least a minimum chunk size */ + if (alignment < MINSIZE) alignment = MINSIZE; + ++ /* Check for overflow. */ ++ if (bytes > SIZE_MAX - alignment - MINSIZE) ++ { ++ __set_errno (ENOMEM); ++ return 0; ++ } ++ + arena_get(ar_ptr, bytes + alignment + MINSIZE); + if(!ar_ptr) + return 0; +@@ -3046,6 +3046,13 @@ __libc_valloc(size_t bytes) + + size_t pagesz = GLRO(dl_pagesize); + ++ /* Check for overflow. */ ++ if (bytes > SIZE_MAX - pagesz - MINSIZE) ++ { ++ __set_errno (ENOMEM); ++ return 0; ++ } ++ + __malloc_ptr_t (*hook) __MALLOC_PMT ((size_t, size_t, + const __malloc_ptr_t)) = + force_reg (__memalign_hook); +@@ -3082,6 +3082,13 @@ __libc_pvalloc(size_t bytes) + size_t page_mask = GLRO(dl_pagesize) - 1; + size_t rounded_bytes = (bytes + page_mask) & ~(page_mask); + ++ /* Check for overflow. */ ++ if (bytes > SIZE_MAX - 2*pagesz - MINSIZE) ++ { ++ __set_errno (ENOMEM); ++ return 0; ++ } ++ + __malloc_ptr_t (*hook) __MALLOC_PMT ((size_t, size_t, + const __malloc_ptr_t)) = + force_reg (__memalign_hook); diff --git a/SOURCES/glibc-rh1020637.patch b/SOURCES/glibc-rh1020637.patch new file mode 100644 index 0000000..9d4561a --- /dev/null +++ b/SOURCES/glibc-rh1020637.patch @@ -0,0 +1,128 @@ +commit acd98a8ed1460497e788c701eb92616f1df9b446 +Author: Andreas Krebbel +Date: Fri Nov 29 09:57:04 2013 +0100 + + [BZ #16214] S/390: Fix TLS GOT pointer setup. + +diff --git glibc-2.17-c758a686/sysdeps/s390/Versions glibc-2.17-c758a686/sysdeps/s390/Versions +index e18617c..baf9842 100644 +--- glibc-2.17-c758a686/sysdeps/s390/Versions ++++ glibc-2.17-c758a686/sysdeps/s390/Versions +@@ -3,4 +3,8 @@ ld { + # runtime interface to TLS + __tls_get_offset; + } ++ GLIBC_PRIVATE { ++ # Exported by ld used by libc. ++ __tls_get_addr_internal; ++ } + } +diff --git glibc-2.17-c758a686/sysdeps/s390/dl-tls.h glibc-2.17-c758a686/sysdeps/s390/dl-tls.h +index 68a5af4..52192a2 100644 +--- glibc-2.17-c758a686/sysdeps/s390/dl-tls.h ++++ glibc-2.17-c758a686/sysdeps/s390/dl-tls.h +@@ -26,11 +26,26 @@ typedef struct + + + #ifdef SHARED +-/* This is the prototype for the GNU version. */ +-extern void *__tls_get_addr (tls_index *ti) attribute_hidden; ++ + extern unsigned long __tls_get_offset (unsigned long got_offset); + + # ifdef IS_IN_rtld ++ ++# include ++ ++extern void *__tls_get_addr (tls_index *ti) attribute_hidden; ++/* Make a temporary alias of __tls_get_addr to remove the hidden ++ attribute. Then export __tls_get_addr as __tls_get_addr_internal ++ for use from libc. We do not want to export __tls_get_addr, but we ++ do need to use it from libc when looking up the address of a TLS ++ variable. We don't use __tls_get_offset because it requires r12 to ++ be setup and that might not always be true. Either way it's more ++ optimal to use __tls_get_addr directly (that's what ++ __tls_get_offset does anyways). */ ++strong_alias (__tls_get_addr, __tls_get_addr_internal_tmp); ++versioned_symbol (ld, __tls_get_addr_internal_tmp, ++ __tls_get_addr_internal, GLIBC_PRIVATE); ++ + /* The special thing about the s390 TLS ABI is that we do not have the + standard __tls_get_addr function but the __tls_get_offset function + which differs in two important aspects: +@@ -63,15 +78,21 @@ __tls_get_offset:\n\ + 1: .long __tls_get_addr - 0b\n\ + "); + # endif +-# endif ++# else /* IS_IN_rtld */ ++extern void *__tls_get_addr_internal (tls_index *ti); ++# endif /* !IS_IN_rtld */ + + # define GET_ADDR_OFFSET \ + (ti->ti_offset - (unsigned long) __builtin_thread_pointer ()) + +-# define __TLS_GET_ADDR(__ti) \ +- ({ extern char _GLOBAL_OFFSET_TABLE_[] attribute_hidden; \ +- (void *) __tls_get_offset ((char *) (__ti) - _GLOBAL_OFFSET_TABLE_) \ +- + (unsigned long) __builtin_thread_pointer (); }) ++/* Use the privately exported __tls_get_addr_internal instead of ++ __tls_get_offset in order to avoid the __tls_get_offset special ++ linkage requiring the GOT pointer to be set up in r12. The ++ compiler will take care of setting up r12 only if itself issued the ++ __tls_get_offset call. */ ++# define __TLS_GET_ADDR(__ti) \ ++ ({ (void *) __tls_get_addr_internal ((char *) (__ti)) \ ++ + (unsigned long) __builtin_thread_pointer (); }) + + #endif + +diff --git glibc-2.17-c758a686/sysdeps/s390/s390-32/tls-macros.h glibc-2.17-c758a686/sysdeps/s390/s390-32/tls-macros.h +index 8a0ad58..a592d81 100644 +--- glibc-2.17-c758a686/sysdeps/s390/s390-32/tls-macros.h ++++ glibc-2.17-c758a686/sysdeps/s390/s390-32/tls-macros.h +@@ -8,12 +8,15 @@ + + #ifdef PIC + # define TLS_IE(x) \ +- ({ unsigned long __offset; \ ++ ({ unsigned long __offset, __got; \ + asm ("bras %0,1f\n" \ +- "0:\t.long " #x "@gotntpoff\n" \ +- "1:\tl %0,0(%0)\n\t" \ +- "l %0,0(%0,%%r12):tls_load:" #x \ +- : "=&a" (__offset) : : "cc" ); \ ++ "0:\t.long _GLOBAL_OFFSET_TABLE_-0b\n\t" \ ++ ".long " #x "@gotntpoff\n" \ ++ "1:\tl %1,0(%0)\n\t" \ ++ "la %1,0(%1,%0)\n\t" \ ++ "l %0,4(%0)\n\t" \ ++ "l %0,0(%0,%1):tls_load:" #x "\n" \ ++ : "=&a" (__offset), "=&a" (__got) : : "cc" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) + #else + # define TLS_IE(x) \ +diff --git glibc-2.17-c758a686/sysdeps/s390/s390-64/tls-macros.h glibc-2.17-c758a686/sysdeps/s390/s390-64/tls-macros.h +index be8aa6c..3c59436 100644 +--- glibc-2.17-c758a686/sysdeps/s390/s390-64/tls-macros.h ++++ glibc-2.17-c758a686/sysdeps/s390/s390-64/tls-macros.h +@@ -8,12 +8,13 @@ + + #ifdef PIC + # define TLS_IE(x) \ +- ({ unsigned long __offset; \ +- asm ("bras %0,1f\n" \ +- "0:\t.quad " #x "@gotntpoff\n" \ +- "1:\tlg %0,0(%0)\n\t" \ +- "lg %0,0(%0,%%r12):tls_load:" #x \ +- : "=&a" (__offset) : : "cc" ); \ ++ ({ unsigned long __offset, __got; \ ++ asm ("bras %0,0f\n\t" \ ++ ".quad " #x "@gotntpoff\n" \ ++ "0:\tlarl %1,_GLOBAL_OFFSET_TABLE_\n\t" \ ++ "lg %0,0(%0)\n\t" \ ++ "lg %0,0(%0,%1):tls_load:" #x "\n" \ ++ : "=&a" (__offset), "=&a" (__got) : : "cc" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) + #else + # define TLS_IE(x) \ diff --git a/SOURCES/glibc-rh1025612.patch b/SOURCES/glibc-rh1025612.patch new file mode 100644 index 0000000..93ab27d --- /dev/null +++ b/SOURCES/glibc-rh1025612.patch @@ -0,0 +1,50 @@ +commit 7cbcdb3699584db8913ca90f705d6337633ee10f +Author: Siddhesh Poyarekar +Date: Fri Oct 25 10:22:12 2013 +0530 + + Fix stack overflow due to large AF_INET6 requests + + Resolves #16072 (CVE-2013-4458). + + This patch fixes another stack overflow in getaddrinfo when it is + called with AF_INET6. The AF_UNSPEC case was fixed as CVE-2013-1914, + but the AF_INET6 case went undetected back then. + +diff --git glibc-2.17-c758a686/sysdeps/posix/getaddrinfo.c glibc-2.17-c758a686/sysdeps/posix/getaddrinfo.c +index e6ce4cf..8ff74b4 100644 +--- glibc-2.17-c758a686/sysdeps/posix/getaddrinfo.c ++++ glibc-2.17-c758a686/sysdeps/posix/getaddrinfo.c +@@ -197,7 +197,22 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp, + &rc, &herrno, NULL, &localcanon)); \ + if (rc != ERANGE || herrno != NETDB_INTERNAL) \ + break; \ +- tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \ ++ if (!malloc_tmpbuf && __libc_use_alloca (alloca_used + 2 * tmpbuflen)) \ ++ tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen, 2 * tmpbuflen, \ ++ alloca_used); \ ++ else \ ++ { \ ++ char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL, \ ++ 2 * tmpbuflen); \ ++ if (newp == NULL) \ ++ { \ ++ result = -EAI_MEMORY; \ ++ goto free_and_return; \ ++ } \ ++ tmpbuf = newp; \ ++ malloc_tmpbuf = true; \ ++ tmpbuflen = 2 * tmpbuflen; \ ++ } \ + } \ + if (status == NSS_STATUS_SUCCESS && rc == 0) \ + h = &th; \ +@@ -209,7 +224,8 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp, + { \ + __set_h_errno (herrno); \ + _res.options |= old_res_options & RES_USE_INET6; \ +- return -EAI_SYSTEM; \ ++ result = -EAI_SYSTEM; \ ++ goto free_and_return; \ + } \ + if (herrno == TRY_AGAIN) \ + no_data = EAI_AGAIN; \ diff --git a/SOURCES/glibc-rh1025934.patch b/SOURCES/glibc-rh1025934.patch new file mode 100644 index 0000000..37758d9 --- /dev/null +++ b/SOURCES/glibc-rh1025934.patch @@ -0,0 +1,143 @@ +Mostly equivalent upstream commit: + +commit 0699f766b10c86912b75f35bef697106b70c1cf6 +Author: Carlos O'Donell +Date: Thu Apr 10 18:31:53 2014 -0400 + + nscd: Make SELinux checks dynamic. + +diff --git glibc-2.17-c758a686/nscd/selinux.c glibc-2.17-c758a686/nscd/selinux.c +index 0866c44..ba55b04 100644 +--- glibc-2.17-c758a686/nscd/selinux.c ++++ glibc-2.17-c758a686/nscd/selinux.c +@@ -44,35 +44,31 @@ + /* Global variable to tell if the kernel has SELinux support. */ + int selinux_enabled; + +-/* Define mappings of access vector permissions to request types. */ +-static const access_vector_t perms[LASTREQ] = ++/* Define mappings of request type to AVC permission name. */ ++static const char *perms[LASTREQ] = + { +- [GETPWBYNAME] = NSCD__GETPWD, +- [GETPWBYUID] = NSCD__GETPWD, +- [GETGRBYNAME] = NSCD__GETGRP, +- [GETGRBYGID] = NSCD__GETGRP, +- [GETHOSTBYNAME] = NSCD__GETHOST, +- [GETHOSTBYNAMEv6] = NSCD__GETHOST, +- [GETHOSTBYADDR] = NSCD__GETHOST, +- [GETHOSTBYADDRv6] = NSCD__GETHOST, +- [GETSTAT] = NSCD__GETSTAT, +- [SHUTDOWN] = NSCD__ADMIN, +- [INVALIDATE] = NSCD__ADMIN, +- [GETFDPW] = NSCD__SHMEMPWD, +- [GETFDGR] = NSCD__SHMEMGRP, +- [GETFDHST] = NSCD__SHMEMHOST, +- [GETAI] = NSCD__GETHOST, +- [INITGROUPS] = NSCD__GETGRP, +-#ifdef NSCD__GETSERV +- [GETSERVBYNAME] = NSCD__GETSERV, +- [GETSERVBYPORT] = NSCD__GETSERV, +- [GETFDSERV] = NSCD__SHMEMSERV, +-#endif +-#ifdef NSCD__GETNETGRP +- [GETNETGRENT] = NSCD__GETNETGRP, +- [INNETGR] = NSCD__GETNETGRP, +- [GETFDNETGR] = NSCD__SHMEMNETGRP, +-#endif ++ [GETPWBYNAME] = "getpwd", ++ [GETPWBYUID] = "getpwd", ++ [GETGRBYNAME] = "getgrp", ++ [GETGRBYGID] = "getgrp", ++ [GETHOSTBYNAME] = "gethost", ++ [GETHOSTBYNAMEv6] = "gethost", ++ [GETHOSTBYADDR] = "gethost", ++ [GETHOSTBYADDRv6] = "gethost", ++ [SHUTDOWN] = "admin", ++ [GETSTAT] = "getstat", ++ [INVALIDATE] = "admin", ++ [GETFDPW] = "shmempwd", ++ [GETFDGR] = "shmemgrp", ++ [GETFDHST] = "shmemhost", ++ [GETAI] = "gethost", ++ [INITGROUPS] = "getgrp", ++ [GETSERVBYNAME] = "getserv", ++ [GETSERVBYPORT] = "getserv", ++ [GETFDSERV] = "shmemserv", ++ [GETNETGRENT] = "getnetgrp", ++ [INNETGR] = "getnetgrp", ++ [GETFDNETGR] = "shmemnetgrp", + }; + + /* Store an entry ref to speed AVC decisions. */ +@@ -344,7 +340,18 @@ nscd_avc_init (void) + + + /* Check the permission from the caller (via getpeercon) to nscd. +- Returns 0 if access is allowed, 1 if denied, and -1 on error. */ ++ Returns 0 if access is allowed, 1 if denied, and -1 on error. ++ ++ Implementation note: ++ The SELinux policy, enablement, and permission bits are all dynamic ++ and the caching done by glibc is not entirely correct. This nscd ++ support should be rewritten to use selinux_check_permission. ++ A rewrite is risky though and requires some refactoring fist. ++ Instead we use symbolic mappings instead of compile time ++ constants (which selinux upstream says are going away), and use ++ security_deny_unknown to determine what to do if selinux-policy ++ doesn't have a definition for the the permission or object class ++ we are looking up. */ + int + nscd_request_avc_has_perm (int fd, request_type req) + { +@@ -354,6 +361,33 @@ nscd_request_avc_has_perm (int fd, request_type req) + security_id_t ssid = NULL; + security_id_t tsid = NULL; + int rc = -1; ++ security_class_t sc_nscd = 0; ++ access_vector_t perm = 0; ++ int avc_deny_unknown = 0; ++ ++ /* Check if SELinux denys or allows unknown object classes ++ and permissions. It is 0 if they are allowed, 1 if they ++ are not allowed and -1 on error. */ ++ if ((avc_deny_unknown = security_deny_unknown ()) == -1) ++ dbg_log (_("Error querying policy for undefined object classes " ++ "or permissions.")); ++ ++ /* Get the security class for nscd. If this fails we will likely be ++ unable to do anything unless avc_deny_unknown is 0. */ ++ if ((sc_nscd = string_to_security_class ("nscd")) == 0 ++ && avc_deny_unknown == 1) ++ dbg_log (_("Error getting security class for nscd.")); ++ ++ /* Convert permission to AVC bits. */ ++ perm = string_to_av_perm (sc_nscd, perms[req]); ++ if (perm == 0 && avc_deny_unknown == 1) ++ dbg_log (_("Error translating permission name " ++ "\"%s\" to access vector bit."), perms[req]); ++ ++ /* If the nscd security class was not found or perms were not ++ found and AVC does not deny unknown values then allow it. */ ++ if ((sc_nscd == 0 || perm == 0) && avc_deny_unknown == 0) ++ return 0; + + if (getpeercon (fd, &scon) < 0) + { +@@ -372,15 +406,7 @@ nscd_request_avc_has_perm (int fd, request_type req) + goto out; + } + +-#ifndef NSCD__GETSERV +- if (perms[req] == 0) +- { +- dbg_log (_("compile-time support for database policy missing")); +- goto out; +- } +-#endif +- +- rc = avc_has_perm (ssid, tsid, SECCLASS_NSCD, perms[req], &aeref, NULL) < 0; ++ rc = avc_has_perm (ssid, tsid, sc_nscd, perm, &aeref, NULL) < 0; + + out: + if (scon) diff --git a/SOURCES/glibc-rh1027101.patch b/SOURCES/glibc-rh1027101.patch new file mode 100644 index 0000000..2b419c9 --- /dev/null +++ b/SOURCES/glibc-rh1027101.patch @@ -0,0 +1,58 @@ +commit 362b47fe09ca9a928d444c7e2f7992f7f61bfc3e +Author: Maxim Kuvyrkov +Date: Tue Dec 24 09:44:50 2013 +1300 + + Fix race in free() of fastbin chunk: BZ #15073 + + Perform sanity check only if we have_lock. Due to lockless nature of fastbins + we need to be careful derefencing pointers to fastbin entries (chunksize(old) + in this case) in multithreaded environments. + + The fix is to add have_lock to the if-condition checks. The rest of the patch + only makes code more readable. + + * malloc/malloc.c (_int_free): Perform sanity check only if we + have_lock. + +Index: b/malloc/malloc.c +=================================================================== +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -3909,25 +3909,29 @@ _int_free(mstate av, mchunkptr p, int ha + unsigned int idx = fastbin_index(size); + fb = &fastbin (av, idx); + +- mchunkptr fd; +- mchunkptr old = *fb; ++ /* Atomically link P to its fastbin: P->FD = *FB; *FB = P; */ ++ mchunkptr old = *fb, old2; + unsigned int old_idx = ~0u; + do + { +- /* Another simple check: make sure the top of the bin is not the +- record we are going to add (i.e., double free). */ ++ /* Check that the top of the bin is not the record we are going to add ++ (i.e., double free). */ + if (__builtin_expect (old == p, 0)) + { + errstr = "double free or corruption (fasttop)"; + goto errout; + } +- if (old != NULL) ++ /* Check that size of fastbin chunk at the top is the same as ++ size of the chunk that we are adding. We can dereference OLD ++ only if we have the lock, otherwise it might have already been ++ deallocated. See use of OLD_IDX below for the actual check. */ ++ if (have_lock && old != NULL) + old_idx = fastbin_index(chunksize(old)); +- p->fd = fd = old; ++ p->fd = old2 = old; + } +- while ((old = catomic_compare_and_exchange_val_rel (fb, p, fd)) != fd); ++ while ((old = catomic_compare_and_exchange_val_rel (fb, p, old2)) != old2); + +- if (fd != NULL && __builtin_expect (old_idx != idx, 0)) ++ if (have_lock && old != NULL && __builtin_expect (old_idx != idx, 0)) + { + errstr = "invalid fastbin entry (free)"; + goto errout; diff --git a/SOURCES/glibc-rh1027348-1.patch b/SOURCES/glibc-rh1027348-1.patch new file mode 100644 index 0000000..363a3af --- /dev/null +++ b/SOURCES/glibc-rh1027348-1.patch @@ -0,0 +1,280 @@ +Backporting the C11 atomic support will allow future algorithms +to be more easily backported to RHEL7. This is initially backported +to support the new semaphore algorithm which is now in RHEL7 +(rhbz#1027348). + +commit 1ea339b69725cb2f30b5a84cb7ca96111c9a637b +Author: Torvald Riegel +Date: Sat Oct 18 01:02:59 2014 +0200 + + Add arch-specific configuration for C11 atomics support. + + This sets __HAVE_64B_ATOMICS if provided. It also sets + USE_ATOMIC_COMPILER_BUILTINS to true if the existing atomic ops use the + __atomic* builtins (aarch64, mips partially) or if this has been + tested (x86_64); otherwise, this is set to false so that C11 atomics will + be based on the existing atomic operations. + +Index: glibc-2.17-c758a686/ports/sysdeps/aarch64/bits/atomic.h +=================================================================== +--- glibc-2.17-c758a686.orig/ports/sysdeps/aarch64/bits/atomic.h ++++ glibc-2.17-c758a686/ports/sysdeps/aarch64/bits/atomic.h +@@ -36,6 +36,8 @@ typedef uintptr_t uatomicptr_t; + typedef intmax_t atomic_max_t; + typedef uintmax_t uatomic_max_t; + ++#define __HAVE_64B_ATOMICS 1 ++#define USE_ATOMIC_COMPILER_BUILTINS 1 + + /* Compare and exchange. + For all "bool" routines, we return FALSE if exchange succesful. */ +Index: glibc-2.17-c758a686/ports/sysdeps/alpha/bits/atomic.h +=================================================================== +--- glibc-2.17-c758a686.orig/ports/sysdeps/alpha/bits/atomic.h ++++ glibc-2.17-c758a686/ports/sysdeps/alpha/bits/atomic.h +@@ -42,6 +42,9 @@ typedef uintptr_t uatomicptr_t; + typedef intmax_t atomic_max_t; + typedef uintmax_t uatomic_max_t; + ++#define __HAVE_64B_ATOMICS 1 ++#define USE_ATOMIC_COMPILER_BUILTINS 0 ++ + + #ifdef UP + # define __MB /* nothing */ +Index: glibc-2.17-c758a686/ports/sysdeps/arm/bits/atomic.h +=================================================================== +--- glibc-2.17-c758a686.orig/ports/sysdeps/arm/bits/atomic.h ++++ glibc-2.17-c758a686/ports/sysdeps/arm/bits/atomic.h +@@ -33,6 +33,9 @@ typedef uintptr_t uatomicptr_t; + typedef intmax_t atomic_max_t; + typedef uintmax_t uatomic_max_t; + ++#define __HAVE_64B_ATOMICS 0 ++#define USE_ATOMIC_COMPILER_BUILTINS 0 ++ + void __arm_link_error (void); + + /* Use the atomic builtins provided by GCC in case the backend provides +Index: glibc-2.17-c758a686/sysdeps/i386/i486/bits/atomic.h +=================================================================== +--- glibc-2.17-c758a686.orig/sysdeps/i386/i486/bits/atomic.h ++++ glibc-2.17-c758a686/sysdeps/i386/i486/bits/atomic.h +@@ -54,6 +54,9 @@ typedef uintmax_t uatomic_max_t; + # endif + #endif + ++#define __HAVE_64B_ATOMICS 0 ++#define USE_ATOMIC_COMPILER_BUILTINS 0 ++ + + #define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \ + __sync_val_compare_and_swap (mem, oldval, newval) +Index: glibc-2.17-c758a686/ports/sysdeps/ia64/bits/atomic.h +=================================================================== +--- glibc-2.17-c758a686.orig/ports/sysdeps/ia64/bits/atomic.h ++++ glibc-2.17-c758a686/ports/sysdeps/ia64/bits/atomic.h +@@ -43,6 +43,9 @@ typedef uintptr_t uatomicptr_t; + typedef intmax_t atomic_max_t; + typedef uintmax_t uatomic_max_t; + ++#define __HAVE_64B_ATOMICS 1 ++#define USE_ATOMIC_COMPILER_BUILTINS 0 ++ + + #define __arch_compare_and_exchange_bool_8_acq(mem, newval, oldval) \ + (abort (), 0) +Index: glibc-2.17-c758a686/ports/sysdeps/m68k/coldfire/bits/atomic.h +=================================================================== +--- glibc-2.17-c758a686.orig/ports/sysdeps/m68k/coldfire/bits/atomic.h ++++ glibc-2.17-c758a686/ports/sysdeps/m68k/coldfire/bits/atomic.h +@@ -49,6 +49,10 @@ typedef uintptr_t uatomicptr_t; + typedef intmax_t atomic_max_t; + typedef uintmax_t uatomic_max_t; + ++/* If we have just non-atomic operations, we can as well make them wide. */ ++#define __HAVE_64B_ATOMICS 1 ++#define USE_ATOMIC_COMPILER_BUILTINS 0 ++ + /* The only basic operation needed is compare and exchange. */ + #define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \ + ({ __typeof (mem) __gmemp = (mem); \ +Index: glibc-2.17-c758a686/ports/sysdeps/m68k/m680x0/m68020/bits/atomic.h +=================================================================== +--- glibc-2.17-c758a686.orig/ports/sysdeps/m68k/m680x0/m68020/bits/atomic.h ++++ glibc-2.17-c758a686/ports/sysdeps/m68k/m680x0/m68020/bits/atomic.h +@@ -44,6 +44,9 @@ typedef uintptr_t uatomicptr_t; + typedef intmax_t atomic_max_t; + typedef uintmax_t uatomic_max_t; + ++#define __HAVE_64B_ATOMICS 1 ++#define USE_ATOMIC_COMPILER_BUILTINS 0 ++ + #define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ + ({ __typeof (*(mem)) __ret; \ + __asm __volatile ("cas%.b %0,%2,%1" \ +Index: glibc-2.17-c758a686/ports/sysdeps/mips/bits/atomic.h +=================================================================== +--- glibc-2.17-c758a686.orig/ports/sysdeps/mips/bits/atomic.h ++++ glibc-2.17-c758a686/ports/sysdeps/mips/bits/atomic.h +@@ -43,6 +43,12 @@ typedef uintmax_t uatomic_max_t; + #define MIPS_PUSH_MIPS2 + #endif + ++#if _MIPS_SIM == _ABIO32 ++#define __HAVE_64B_ATOMICS 0 ++#else ++#define __HAVE_64B_ATOMICS 1 ++#endif ++ + /* See the comments in about the use of the sync instruction. */ + #ifndef MIPS_SYNC + # define MIPS_SYNC sync +@@ -82,6 +88,8 @@ typedef uintmax_t uatomic_max_t; + /* The __atomic_* builtins are available in GCC 4.7 and later, but MIPS + support for their efficient implementation was added only in GCC 4.8. */ + ++#define USE_ATOMIC_COMPILER_BUILTINS 1 ++ + /* Compare and exchange. + For all "bool" routines, we return FALSE if exchange succesful. */ + +@@ -204,6 +212,8 @@ typedef uintmax_t uatomic_max_t; + /* This implementation using inline assembly will be removed once glibc + requires GCC 4.8 or later to build. */ + ++#define USE_ATOMIC_COMPILER_BUILTINS 0 ++ + /* Compare and exchange. For all of the "xxx" routines, we expect a + "__prev" and a "__cmp" variable to be provided by the enclosing scope, + in which values are returned. */ +Index: glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/bits/atomic.h +=================================================================== +--- glibc-2.17-c758a686.orig/sysdeps/powerpc/powerpc32/bits/atomic.h ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/bits/atomic.h +@@ -33,6 +33,9 @@ + # define MUTEX_HINT_REL + #endif + ++#define __HAVE_64B_ATOMICS 0 ++#define USE_ATOMIC_COMPILER_BUILTINS 0 ++ + /* + * The 32-bit exchange_bool is different on powerpc64 because the subf + * does signed 64-bit arthmatic while the lwarx is 32-bit unsigned +Index: glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/bits/atomic.h +=================================================================== +--- glibc-2.17-c758a686.orig/sysdeps/powerpc/powerpc64/bits/atomic.h ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/bits/atomic.h +@@ -33,6 +33,9 @@ + # define MUTEX_HINT_REL + #endif + ++#define __HAVE_64B_ATOMICS 1 ++#define USE_ATOMIC_COMPILER_BUILTINS 0 ++ + /* The 32-bit exchange_bool is different on powerpc64 because the subf + does signed 64-bit arthmatic while the lwarx is 32-bit unsigned + (a load word and zero (high 32) form) load. +Index: glibc-2.17-c758a686/sysdeps/s390/bits/atomic.h +=================================================================== +--- glibc-2.17-c758a686.orig/sysdeps/s390/bits/atomic.h ++++ glibc-2.17-c758a686/sysdeps/s390/bits/atomic.h +@@ -43,6 +43,8 @@ typedef uintptr_t uatomicptr_t; + typedef intmax_t atomic_max_t; + typedef uintmax_t uatomic_max_t; + ++#define USE_ATOMIC_COMPILER_BUILTINS 0 ++ + + #define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ + (abort (), (__typeof (*mem)) 0) +@@ -59,6 +61,7 @@ typedef uintmax_t uatomic_max_t; + __archold; }) + + #ifdef __s390x__ ++# define __HAVE_64B_ATOMICS 1 + # define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ + ({ __typeof (mem) __archmem = (mem); \ + __typeof (*mem) __archold = (oldval); \ +@@ -67,6 +70,7 @@ typedef uintmax_t uatomic_max_t; + : "d" ((long) (newval)), "m" (*__archmem) : "cc", "memory" ); \ + __archold; }) + #else ++# define __HAVE_64B_ATOMICS 0 + /* For 31 bit we do not really need 64-bit compare-and-exchange. We can + implement them by use of the csd instruction. The straightforward + implementation causes warnings so we skip the definition for now. */ +Index: glibc-2.17-c758a686/sysdeps/sparc/sparc32/bits/atomic.h +=================================================================== +--- glibc-2.17-c758a686.orig/sysdeps/sparc/sparc32/bits/atomic.h ++++ glibc-2.17-c758a686/sysdeps/sparc/sparc32/bits/atomic.h +@@ -47,6 +47,9 @@ typedef uintptr_t uatomicptr_t; + typedef intmax_t atomic_max_t; + typedef uintmax_t uatomic_max_t; + ++#define __HAVE_64B_ATOMICS 0 ++#define USE_ATOMIC_COMPILER_BUILTINS 0 ++ + + /* We have no compare and swap, just test and set. + The following implementation contends on 64 global locks +Index: glibc-2.17-c758a686/sysdeps/sparc/sparc32/sparcv9/bits/atomic.h +=================================================================== +--- glibc-2.17-c758a686.orig/sysdeps/sparc/sparc32/sparcv9/bits/atomic.h ++++ glibc-2.17-c758a686/sysdeps/sparc/sparc32/sparcv9/bits/atomic.h +@@ -44,6 +44,9 @@ typedef uintptr_t uatomicptr_t; + typedef intmax_t atomic_max_t; + typedef uintmax_t uatomic_max_t; + ++#define __HAVE_64B_ATOMICS 0 ++#define USE_ATOMIC_COMPILER_BUILTINS 0 ++ + + #define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ + (abort (), (__typeof (*mem)) 0) +Index: glibc-2.17-c758a686/sysdeps/sparc/sparc64/bits/atomic.h +=================================================================== +--- glibc-2.17-c758a686.orig/sysdeps/sparc/sparc64/bits/atomic.h ++++ glibc-2.17-c758a686/sysdeps/sparc/sparc64/bits/atomic.h +@@ -44,6 +44,9 @@ typedef uintptr_t uatomicptr_t; + typedef intmax_t atomic_max_t; + typedef uintmax_t uatomic_max_t; + ++#define __HAVE_64B_ATOMICS 1 ++#define USE_ATOMIC_COMPILER_BUILTINS 0 ++ + + #define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ + (abort (), (__typeof (*mem)) 0) +Index: glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/hppa/bits/atomic.h +=================================================================== +--- glibc-2.17-c758a686.orig/ports/sysdeps/unix/sysv/linux/hppa/bits/atomic.h ++++ glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/hppa/bits/atomic.h +@@ -44,6 +44,9 @@ typedef uintptr_t uatomicptr_t; + typedef intmax_t atomic_max_t; + typedef uintmax_t uatomic_max_t; + ++#define __HAVE_64B_ATOMICS 0 ++#define USE_ATOMIC_COMPILER_BUILTINS 0 ++ + /* prev = *addr; + if (prev == old) + *addr = new; +Index: glibc-2.17-c758a686/sysdeps/x86_64/bits/atomic.h +=================================================================== +--- glibc-2.17-c758a686.orig/sysdeps/x86_64/bits/atomic.h ++++ glibc-2.17-c758a686/sysdeps/x86_64/bits/atomic.h +@@ -55,6 +55,12 @@ typedef uintmax_t uatomic_max_t; + # endif + #endif + ++#define __HAVE_64B_ATOMICS 1 ++#if __GNUC_PREREQ (4, 7) ++#define USE_ATOMIC_COMPILER_BUILTINS 1 ++#else ++#define USE_ATOMIC_COMPILER_BUILTINS 0 ++#endif + + #define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \ + __sync_val_compare_and_swap (mem, oldval, newval) diff --git a/SOURCES/glibc-rh1027348-2.patch b/SOURCES/glibc-rh1027348-2.patch new file mode 100644 index 0000000..ca54870 --- /dev/null +++ b/SOURCES/glibc-rh1027348-2.patch @@ -0,0 +1,229 @@ +commit ff8714269c9312d9164456279a56b6f6c47e2771 +Author: Torvald Riegel +Date: Sun Sep 14 20:04:54 2014 +0200 + + Add atomic operations similar to those provided by C11. + +Index: glibc-2.17-c758a686/include/atomic.h +=================================================================== +--- glibc-2.17-c758a686.orig/include/atomic.h ++++ glibc-2.17-c758a686/include/atomic.h +@@ -542,6 +542,218 @@ + ({ __typeof (x) __x; __asm ("" : "=r" (__x) : "0" (x)); __x; }) + #endif + ++/* This is equal to 1 iff the architecture supports 64b atomic operations. */ ++#ifndef __HAVE_64B_ATOMICS ++#error Unable to determine if 64-bit atomics are present. ++#endif ++ ++/* The following functions are a subset of the atomic operations provided by ++ C11. Usually, a function named atomic_OP_MO(args) is equivalent to C11's ++ atomic_OP_explicit(args, memory_order_MO); exceptions noted below. */ ++ ++/* Each arch can request to use compiler built-ins for C11 atomics. If it ++ does, all atomics will be based on these. */ ++#if USE_ATOMIC_COMPILER_BUILTINS ++ ++/* We require 32b atomic operations; some archs also support 64b atomic ++ operations. */ ++void __atomic_link_error (void); ++# if __HAVE_64B_ATOMICS == 1 ++# define __atomic_check_size(mem) \ ++ if ((sizeof (*mem) != 4) && (sizeof (*mem) != 8)) \ ++ __atomic_link_error (); ++# else ++# define __atomic_check_size(mem) \ ++ if (sizeof (*mem) != 4) \ ++ __atomic_link_error (); ++# endif ++ ++# define atomic_thread_fence_acquire() \ ++ __atomic_thread_fence (__ATOMIC_ACQUIRE) ++# define atomic_thread_fence_release() \ ++ __atomic_thread_fence (__ATOMIC_RELEASE) ++# define atomic_thread_fence_seq_cst() \ ++ __atomic_thread_fence (__ATOMIC_SEQ_CST) ++ ++# define atomic_load_relaxed(mem) \ ++ ({ __atomic_check_size((mem)); __atomic_load_n ((mem), __ATOMIC_RELAXED); }) ++# define atomic_load_acquire(mem) \ ++ ({ __atomic_check_size((mem)); __atomic_load_n ((mem), __ATOMIC_ACQUIRE); }) ++ ++# define atomic_store_relaxed(mem, val) \ ++ do { \ ++ __atomic_check_size((mem)); \ ++ __atomic_store_n ((mem), (val), __ATOMIC_RELAXED); \ ++ } while (0) ++# define atomic_store_release(mem, val) \ ++ do { \ ++ __atomic_check_size((mem)); \ ++ __atomic_store_n ((mem), (val), __ATOMIC_RELEASE); \ ++ } while (0) ++ ++/* On failure, this CAS has memory_order_relaxed semantics. */ ++# define atomic_compare_exchange_weak_relaxed(mem, expected, desired) \ ++ ({ __atomic_check_size((mem)); \ ++ __atomic_compare_exchange_n ((mem), (expected), (desired), 1, \ ++ __ATOMIC_RELAXED, __ATOMIC_RELAXED); }) ++# define atomic_compare_exchange_weak_acquire(mem, expected, desired) \ ++ ({ __atomic_check_size((mem)); \ ++ __atomic_compare_exchange_n ((mem), (expected), (desired), 1, \ ++ __ATOMIC_ACQUIRE, __ATOMIC_RELAXED); }) ++# define atomic_compare_exchange_weak_release(mem, expected, desired) \ ++ ({ __atomic_check_size((mem)); \ ++ __atomic_compare_exchange_n ((mem), (expected), (desired), 1, \ ++ __ATOMIC_RELEASE, __ATOMIC_RELAXED); }) ++ ++# define atomic_exchange_acquire(mem, desired) \ ++ ({ __atomic_check_size((mem)); \ ++ __atomic_exchange_n ((mem), (desired), __ATOMIC_ACQUIRE); }) ++# define atomic_exchange_release(mem, desired) \ ++ ({ __atomic_check_size((mem)); \ ++ __atomic_exchange_n ((mem), (desired), __ATOMIC_RELEASE); }) ++ ++# define atomic_fetch_add_relaxed(mem, operand) \ ++ ({ __atomic_check_size((mem)); \ ++ __atomic_fetch_add ((mem), (operand), __ATOMIC_RELAXED); }) ++# define atomic_fetch_add_acquire(mem, operand) \ ++ ({ __atomic_check_size((mem)); \ ++ __atomic_fetch_add ((mem), (operand), __ATOMIC_ACQUIRE); }) ++# define atomic_fetch_add_release(mem, operand) \ ++ ({ __atomic_check_size((mem)); \ ++ __atomic_fetch_add ((mem), (operand), __ATOMIC_RELEASE); }) ++# define atomic_fetch_add_acq_rel(mem, operand) \ ++ ({ __atomic_check_size((mem)); \ ++ __atomic_fetch_add ((mem), (operand), __ATOMIC_ACQ_REL); }) ++ ++# define atomic_fetch_and_acquire(mem, operand) \ ++ ({ __atomic_check_size((mem)); \ ++ __atomic_fetch_and ((mem), (operand), __ATOMIC_ACQUIRE); }) ++ ++# define atomic_fetch_or_relaxed(mem, operand) \ ++ ({ __atomic_check_size((mem)); \ ++ __atomic_fetch_or ((mem), (operand), __ATOMIC_RELAXED); }) ++# define atomic_fetch_or_acquire(mem, operand) \ ++ ({ __atomic_check_size((mem)); \ ++ __atomic_fetch_or ((mem), (operand), __ATOMIC_ACQUIRE); }) ++ ++#else /* !USE_ATOMIC_COMPILER_BUILTINS */ ++ ++/* By default, we assume that read, write, and full barriers are equivalent ++ to acquire, release, and seq_cst barriers. Archs for which this does not ++ hold have to provide custom definitions of the fences. */ ++# ifndef atomic_thread_fence_acquire ++# define atomic_thread_fence_acquire() atomic_read_barrier () ++# endif ++# ifndef atomic_thread_fence_release ++# define atomic_thread_fence_release() atomic_write_barrier () ++# endif ++# ifndef atomic_thread_fence_seq_cst ++# define atomic_thread_fence_seq_cst() atomic_full_barrier () ++# endif ++ ++# ifndef atomic_load_relaxed ++# define atomic_load_relaxed(mem) \ ++ ({ __typeof (*(mem)) __atg100_val; \ ++ __asm ("" : "=r" (__atg100_val) : "0" (*(mem))); \ ++ __atg100_val; }) ++# endif ++# ifndef atomic_load_acquire ++# define atomic_load_acquire(mem) \ ++ ({ __typeof (*(mem)) __atg101_val = atomic_load_relaxed (mem); \ ++ atomic_thread_fence_acquire (); \ ++ __atg101_val; }) ++# endif ++ ++# ifndef atomic_store_relaxed ++/* XXX Use inline asm here? */ ++# define atomic_store_relaxed(mem, val) do { *(mem) = (val); } while (0) ++# endif ++# ifndef atomic_store_release ++# define atomic_store_release(mem, val) \ ++ do { \ ++ atomic_thread_fence_release (); \ ++ atomic_store_relaxed ((mem), (val)); \ ++ } while (0) ++# endif ++ ++/* On failure, this CAS has memory_order_relaxed semantics. */ ++/* XXX This potentially has one branch more than necessary, but archs ++ currently do not define a CAS that returns both the previous value and ++ the success flag. */ ++# ifndef atomic_compare_exchange_weak_acquire ++# define atomic_compare_exchange_weak_acquire(mem, expected, desired) \ ++ ({ typeof (*(expected)) __atg102_expected = *(expected); \ ++ *(expected) = \ ++ atomic_compare_and_exchange_val_acq ((mem), (desired), *(expected)); \ ++ *(expected) == __atg102_expected; }) ++# endif ++# ifndef atomic_compare_exchange_weak_relaxed ++/* XXX Fall back to CAS with acquire MO because archs do not define a weaker ++ CAS. */ ++# define atomic_compare_exchange_weak_relaxed(mem, expected, desired) \ ++ atomic_compare_exchange_weak_acquire ((mem), (expected), (desired)) ++# endif ++# ifndef atomic_compare_exchange_weak_release ++# define atomic_compare_exchange_weak_release(mem, expected, desired) \ ++ ({ typeof (*(expected)) __atg103_expected = *(expected); \ ++ *(expected) = \ ++ atomic_compare_and_exchange_val_rel ((mem), (desired), *(expected)); \ ++ *(expected) == __atg103_expected; }) ++# endif ++ ++# ifndef atomic_exchange_acquire ++# define atomic_exchange_acquire(mem, val) \ ++ atomic_exchange_acq ((mem), (val)) ++# endif ++# ifndef atomic_exchange_release ++# define atomic_exchange_release(mem, val) \ ++ atomic_exchange_rel ((mem), (val)) ++# endif ++ ++# ifndef atomic_fetch_add_acquire ++# define atomic_fetch_add_acquire(mem, operand) \ ++ atomic_exchange_and_add_acq ((mem), (operand)) ++# endif ++# ifndef atomic_fetch_add_relaxed ++/* XXX Fall back to acquire MO because the MO semantics of ++ atomic_exchange_and_add are not documented; the generic version falls back ++ to atomic_exchange_and_add_acq if atomic_exchange_and_add is not defined, ++ and vice versa. */ ++# define atomic_fetch_add_relaxed(mem, operand) \ ++ atomic_fetch_add_acquire ((mem), (operand)) ++# endif ++# ifndef atomic_fetch_add_release ++# define atomic_fetch_add_release(mem, operand) \ ++ atomic_exchange_and_add_rel ((mem), (operand)) ++# endif ++# ifndef atomic_fetch_add_acq_rel ++# define atomic_fetch_add_acq_rel(mem, operand) \ ++ ({ atomic_thread_fence_release (); \ ++ atomic_exchange_and_add_acq ((mem), (operand)); }) ++# endif ++ ++/* XXX The default for atomic_and_val has acquire semantics, but this is not ++ documented. */ ++# ifndef atomic_fetch_and_acquire ++# define atomic_fetch_and_acquire(mem, operand) \ ++ atomic_and_val ((mem), (operand)) ++# endif ++ ++/* XXX The default for atomic_or_val has acquire semantics, but this is not ++ documented. */ ++# ifndef atomic_fetch_or_acquire ++# define atomic_fetch_or_acquire(mem, operand) \ ++ atomic_or_val ((mem), (operand)) ++# endif ++/* XXX Fall back to acquire MO because archs do not define a weaker ++ atomic_or_val. */ ++# ifndef atomic_fetch_or_relaxed ++# define atomic_fetch_or_relaxed(mem, operand) \ ++ atomic_fetch_or_acquire ((mem), (operand)) ++# endif ++ ++#endif /* !USE_ATOMIC_COMPILER_BUILTINS */ ++ + + #ifndef atomic_delay + # define atomic_delay() do { /* nothing */ } while (0) diff --git a/SOURCES/glibc-rh1027348-3.patch b/SOURCES/glibc-rh1027348-3.patch new file mode 100644 index 0000000..b2040fe --- /dev/null +++ b/SOURCES/glibc-rh1027348-3.patch @@ -0,0 +1,144 @@ +commit 88ed594f5d431d855256edbe7e886c8cf4b575dc +Author: Roland McGrath +Date: Tue May 19 15:04:41 2015 -0700 + + BZ#18434: Fix sem_post EOVERFLOW check for [!__HAVE_64B_ATOMICS]. + +Index: glibc-2.17-c758a686/nptl/Makefile +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/Makefile ++++ glibc-2.17-c758a686/nptl/Makefile +@@ -224,6 +224,7 @@ tests = tst-typesizes \ + tst-key1 tst-key2 tst-key3 tst-key4 \ + tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \ + tst-sem8 tst-sem9 tst-sem10 tst-sem11 tst-sem12 tst-sem13 tst-sem14 \ ++ tst-sem15 \ + tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 \ + tst-align tst-align2 tst-align3 \ + tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \ +Index: glibc-2.17-c758a686/nptl/tst-sem15.c +=================================================================== +--- /dev/null ++++ glibc-2.17-c758a686/nptl/tst-sem15.c +@@ -0,0 +1,99 @@ ++/* Test for SEM_VALUE_MAX overflow detection: BZ #18434. ++ Copyright (C) 2015 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++static int ++do_test (void) ++{ ++ sem_t s; ++ ++ if (sem_init (&s, 0, SEM_VALUE_MAX)) ++ { ++ printf ("sem_init: %m\n"); ++ return 1; ++ } ++ ++ int result = 0; ++ ++ int value = 0xdeadbeef; ++ if (sem_getvalue (&s, &value)) ++ { ++ printf ("sem_getvalue: %m\n"); ++ result = 1; ++ } ++ else ++ { ++ printf ("sem_getvalue after init: %d\n", value); ++ if (value != SEM_VALUE_MAX) ++ { ++ printf ("\tshould be %d\n", SEM_VALUE_MAX); ++ result = 1; ++ } ++ } ++ ++ errno = 0; ++ if (sem_post(&s) == 0) ++ { ++ puts ("sem_post at SEM_VALUE_MAX succeeded!"); ++ result = 1; ++ } ++ else ++ { ++ printf ("sem_post at SEM_VALUE_MAX: %m (%d)\n", errno); ++ if (errno != EOVERFLOW) ++ { ++ printf ("\tshould be %s (EOVERFLOW = %d)\n", ++ strerror (EOVERFLOW), EOVERFLOW); ++ result = 1; ++ } ++ } ++ ++ value = 0xbad1d00d; ++ if (sem_getvalue (&s, &value)) ++ { ++ printf ("sem_getvalue: %m\n"); ++ result = 1; ++ } ++ else ++ { ++ printf ("sem_getvalue after post: %d\n", value); ++ if (value != SEM_VALUE_MAX) ++ { ++ printf ("\tshould be %d\n", SEM_VALUE_MAX); ++ result = 1; ++ } ++ } ++ ++ if (sem_destroy (&s)) ++ { ++ printf ("sem_destroy: %m\n"); ++ result = 1; ++ } ++ ++ return result; ++} ++ ++#define TEST_FUNCTION do_test () ++#include "../test-skeleton.c" +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/sem_post.c +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/sem_post.c ++++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/sem_post.c +@@ -83,14 +83,14 @@ __new_sem_post (sem_t *sem) + unsigned int v = atomic_load_relaxed (&isem->value); + do + { +- if ((v << SEM_VALUE_SHIFT) == SEM_VALUE_MAX) ++ if ((v >> SEM_VALUE_SHIFT) == SEM_VALUE_MAX) + { + __set_errno (EOVERFLOW); + return -1; + } + } +- while (!atomic_compare_exchange_weak_release (&isem->value, +- &v, v + (1 << SEM_VALUE_SHIFT))); ++ while (!atomic_compare_exchange_weak_release ++ (&isem->value, &v, v + (1 << SEM_VALUE_SHIFT))); + + /* If there is any potentially blocked waiter, wake one of them. */ + if ((v & SEM_NWAITERS_MASK) != 0) diff --git a/SOURCES/glibc-rh1027348-4.patch b/SOURCES/glibc-rh1027348-4.patch new file mode 100644 index 0000000..27f6115 --- /dev/null +++ b/SOURCES/glibc-rh1027348-4.patch @@ -0,0 +1,105 @@ +commit c2f5813ae0a68f6c6d69e66dac2da6e46b9df034 +Author: Joseph Myers +Date: Wed Mar 18 17:05:38 2015 +0000 + + Make sem_timedwait use FUTEX_CLOCK_REALTIME (bug 18138). + + sem_timedwait converts absolute timeouts to relative to pass them to + the futex syscall. (Before the recent reimplementation, on x86_64 it + used FUTEX_CLOCK_REALTIME, but not on other architectures.) + + Correctly implementing POSIX requirements, however, requires use of + FUTEX_CLOCK_REALTIME; passing a relative timeout to the kernel does + not conform to POSIX. The POSIX specification for sem_timedwait says + "The timeout shall be based on the CLOCK_REALTIME clock.". The POSIX + specification for clock_settime says "If the value of the + CLOCK_REALTIME clock is set via clock_settime(), the new value of the + clock shall be used to determine the time of expiration for absolute + time services based upon the CLOCK_REALTIME clock. This applies to the + time at which armed absolute timers expire. If the absolute time + requested at the invocation of such a time service is before the new + value of the clock, the time service shall expire immediately as if + the clock had reached the requested time normally.". If a relative + timeout is passed to the kernel, it is interpreted according to the + CLOCK_MONOTONIC clock, and so fails to meet that POSIX requirement in + the event of clock changes. + + This patch makes sem_timedwait use lll_futex_timed_wait_bitset with + FUTEX_CLOCK_REALTIME when possible, as done in some other places in + NPTL. FUTEX_CLOCK_REALTIME is always available for supported Linux + kernel versions; unavailability of lll_futex_timed_wait_bitset is only + an issue for hppa (an issue noted in + , and fixed by the + unreviewed + that + removes the hppa lowlevellock.h completely). + + In the FUTEX_CLOCK_REALTIME case, the glibc code still needs to check + for negative tv_sec and handle that as timeout, because the Linux + kernel returns EINVAL not ETIMEDOUT for that case, so resulting in + failures of nptl/tst-abstime and nptl/tst-sem13 in the absence of that + check. If we're trying to distinguish between Linux-specific and + generic-futex NPTL code, I suppose having this in an nptl/ file isn't + ideal, but there doesn't seem to be any better place at present. + + It's not possible to add a testcase for this issue to the testsuite + because of the requirement to change the system clock as part of a + test (this is a case where testing would require some form of + container, with root in that container, and one whose CLOCK_REALTIME + is isolated from that of the host; I'm not sure what forms of + containers, short of a full virtual machine, provide that clock + isolation). + + Tested for x86_64. Also tested for powerpc with the testcase included + in the bug. + + [BZ #18138] + * nptl/sem_waitcommon.c: Include . + (futex_abstimed_wait) + [__ASSUME_FUTEX_CLOCK_REALTIME && lll_futex_timed_wait_bitset]: + Use lll_futex_timed_wait_bitset with FUTEX_CLOCK_REALTIME instead + of lll_futex_timed_wait. + +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/sem_waitcommon.c +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/sem_waitcommon.c ++++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/sem_waitcommon.c +@@ -17,6 +17,7 @@ + License along with the GNU C Library; if not, see + . */ + ++#include + #include + #include + #include +@@ -45,6 +46,13 @@ futex_abstimed_wait (unsigned int* futex + } + else + { ++#if (defined __ASSUME_FUTEX_CLOCK_REALTIME \ ++ && defined lll_futex_timed_wait_bitset) ++ /* The Linux kernel returns EINVAL for this, but in userspace ++ such a value is valid. */ ++ if (abstime->tv_sec < 0) ++ return ETIMEDOUT; ++#else + struct timeval tv; + struct timespec rt; + int sec, nsec; +@@ -68,9 +76,16 @@ futex_abstimed_wait (unsigned int* futex + /* Do wait. */ + rt.tv_sec = sec; + rt.tv_nsec = nsec; ++#endif + if (cancel) + oldtype = __pthread_enable_asynccancel (); ++#if (defined __ASSUME_FUTEX_CLOCK_REALTIME \ ++ && defined lll_futex_timed_wait_bitset) ++ err = lll_futex_timed_wait_bitset (futex, expected, abstime, ++ FUTEX_CLOCK_REALTIME, private); ++#else + err = lll_futex_timed_wait (futex, expected, &rt, private); ++#endif + if (cancel) + __pthread_disable_asynccancel (oldtype); + } diff --git a/SOURCES/glibc-rh1027348.patch b/SOURCES/glibc-rh1027348.patch new file mode 100644 index 0000000..4aca8a2 --- /dev/null +++ b/SOURCES/glibc-rh1027348.patch @@ -0,0 +1,3917 @@ +Torvald Riegel's semaphore reimplemenation to fix upstream swbz#12674. + +commit 042e1521c794a945edc43b5bfa7e69ad70420524 +Author: Carlos O'Donell +Date: Wed Jan 21 00:46:16 2015 -0500 + + Fix semaphore destruction (bug 12674). + + This commit fixes semaphore destruction by either using 64b atomic + operations (where available), or by using two separate fields when only + 32b atomic operations are available. In the latter case, we keep a + conservative estimate of whether there are any waiting threads in one + bit of the field that counts the number of available tokens, thus + allowing sem_post to atomically both add a token and determine whether + it needs to call futex_wake. + + See: + https://sourceware.org/ml/libc-alpha/2014-12/msg00155.html + +Notes: +* For x86_64 and i686, rather than movign to the generic lll_futex_wake + we fix the existing versions to return the syscall result and to be + usable as an R-value. +* We also backport fixes for swbz#18434, and swbz#18138. +* We ignore swbz#17870 because it applies only to x32. + +Index: glibc-2.17-c758a686/nptl/DESIGN-sem.txt +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/DESIGN-sem.txt ++++ /dev/null +@@ -1,46 +0,0 @@ +-Semaphores pseudocode +-============================== +- +- int sem_wait(sem_t * sem); +- int sem_trywait(sem_t * sem); +- int sem_post(sem_t * sem); +- int sem_getvalue(sem_t * sem, int * sval); +- +-struct sem_t { +- +- unsigned int count; +- - current semaphore count, also used as a futex +-} +- +-sem_wait(sem_t *sem) +-{ +- for (;;) { +- +- if (atomic_decrement_if_positive(sem->count)) +- break; +- +- futex_wait(&sem->count, 0) +- } +-} +- +-sem_post(sem_t *sem) +-{ +- n = atomic_increment(sem->count); +- // Pass the new value of sem->count +- futex_wake(&sem->count, n + 1); +-} +- +-sem_trywait(sem_t *sem) +-{ +- if (atomic_decrement_if_positive(sem->count)) { +- return 0; +- } else { +- return EAGAIN; +- } +-} +- +-sem_getvalue(sem_t *sem, int *sval) +-{ +- *sval = sem->count; +- read_barrier(); +-} +Index: glibc-2.17-c758a686/nptl/Makefile +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/Makefile ++++ glibc-2.17-c758a686/nptl/Makefile +@@ -95,7 +95,7 @@ libpthread-routines = nptl-init vars eve + sem_init sem_destroy \ + sem_open sem_close sem_unlink \ + sem_getvalue \ +- sem_wait sem_trywait sem_timedwait sem_post \ ++ sem_wait sem_timedwait sem_post \ + cleanup cleanup_defer cleanup_compat \ + cleanup_defer_compat unwind \ + pt-longjmp pt-cleanup\ +Index: glibc-2.17-c758a686/nptl/sem_getvalue.c +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sem_getvalue.c ++++ glibc-2.17-c758a686/nptl/sem_getvalue.c +@@ -19,23 +19,37 @@ + #include + #include + #include "semaphoreP.h" ++#include + + + int +-__new_sem_getvalue (sem, sval) +- sem_t *sem; +- int *sval; ++__new_sem_getvalue (sem_t *sem, int *sval) + { + struct new_sem *isem = (struct new_sem *) sem; + + /* XXX Check for valid SEM parameter. */ ++ /* FIXME This uses relaxed MO, even though POSIX specifies that this function ++ should be linearizable. However, its debatable whether linearizability ++ is the right requirement. We need to follow up with POSIX and, if ++ necessary, use a stronger MO here and elsewhere (e.g., potentially ++ release MO in all places where we consume a token). */ + +- *sval = isem->value; ++#if __HAVE_64B_ATOMICS ++ *sval = atomic_load_relaxed (&isem->data) & SEM_VALUE_MASK; ++#else ++ *sval = atomic_load_relaxed (&isem->value) >> SEM_VALUE_SHIFT; ++#endif + + return 0; + } + versioned_symbol (libpthread, __new_sem_getvalue, sem_getvalue, GLIBC_2_1); + #if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) +-strong_alias (__new_sem_getvalue, __old_sem_getvalue) ++int ++__old_sem_getvalue (sem_t *sem, int *sval) ++{ ++ struct old_sem *isem = (struct old_sem *) sem; ++ *sval = isem->value; ++ return 0; ++} + compat_symbol (libpthread, __old_sem_getvalue, sem_getvalue, GLIBC_2_0); + #endif +Index: glibc-2.17-c758a686/nptl/sem_init.c +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sem_init.c ++++ glibc-2.17-c758a686/nptl/sem_init.c +@@ -18,17 +18,28 @@ + + #include + #include +-#include + #include + #include "semaphoreP.h" + #include + ++/* Returns FUTEX_PRIVATE if pshared is zero and private futexes are supported; ++ returns FUTEX_SHARED otherwise. ++ TODO Remove when cleaning up the futex API throughout glibc. */ ++static __always_inline int ++futex_private_if_supported (int pshared) ++{ ++ if (pshared != 0) ++ return LLL_SHARED; ++#ifdef __ASSUME_PRIVATE_FUTEX ++ return LLL_PRIVATE; ++#else ++ return THREAD_GETMEM (THREAD_SELF, header.private_futex) ++ ^ FUTEX_PRIVATE_FLAG; ++#endif ++} + + int +-__new_sem_init (sem, pshared, value) +- sem_t *sem; +- int pshared; +- unsigned int value; ++__new_sem_init (sem_t *sem, int pshared, unsigned int value) + { + /* Parameter sanity check. */ + if (__builtin_expect (value > SEM_VALUE_MAX, 0)) +@@ -40,16 +51,15 @@ __new_sem_init (sem, pshared, value) + /* Map to the internal type. */ + struct new_sem *isem = (struct new_sem *) sem; + +- /* Use the values the user provided. */ +- isem->value = value; +-#ifdef __ASSUME_PRIVATE_FUTEX +- isem->private = pshared ? 0 : FUTEX_PRIVATE_FLAG; ++ /* Use the values the caller provided. */ ++#if __HAVE_64B_ATOMICS ++ isem->data = value; + #else +- isem->private = pshared ? 0 : THREAD_GETMEM (THREAD_SELF, +- header.private_futex); ++ isem->value = value << SEM_VALUE_SHIFT; ++ isem->nwaiters = 0; + #endif + +- isem->nwaiters = 0; ++ isem->private = futex_private_if_supported (pshared); + + return 0; + } +Index: glibc-2.17-c758a686/nptl/sem_open.c +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sem_open.c ++++ glibc-2.17-c758a686/nptl/sem_open.c +@@ -307,9 +307,14 @@ sem_open (const char *name, int oflag, . + struct new_sem newsem; + } sem; + +- sem.newsem.value = value; +- sem.newsem.private = 0; ++#if __HAVE_64B_ATOMICS ++ sem.newsem.data = value; ++#else ++ sem.newsem.value = value << SEM_VALUE_SHIFT; + sem.newsem.nwaiters = 0; ++#endif ++ /* This always is a shared semaphore. */ ++ sem.newsem.private = LLL_SHARED; + + /* Initialize the remaining bytes as well. */ + memset ((char *) &sem.initsem + sizeof (struct new_sem), '\0', +Index: glibc-2.17-c758a686/nptl/tst-sem11.c +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/tst-sem11.c ++++ glibc-2.17-c758a686/nptl/tst-sem11.c +@@ -34,8 +34,11 @@ main (void) + puts ("sem_init failed"); + return 1; + } +- ++#if __HAVE_64B_ATOMICS ++ if ((u.ns.data >> SEM_NWAITERS_SHIFT) != 0) ++#else + if (u.ns.nwaiters != 0) ++#endif + { + puts ("nwaiters not initialized"); + return 1; +@@ -68,7 +71,11 @@ main (void) + goto again; + } + ++#if __HAVE_64B_ATOMICS ++ if ((u.ns.data >> SEM_NWAITERS_SHIFT) != 0) ++#else + if (u.ns.nwaiters != 0) ++#endif + { + puts ("nwaiters not reset"); + return 1; +Index: glibc-2.17-c758a686/nptl/tst-sem13.c +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/tst-sem13.c ++++ glibc-2.17-c758a686/nptl/tst-sem13.c +@@ -33,9 +33,14 @@ do_test (void) + perror ("sem_timedwait did not fail with EINVAL"); + return 1; + } +- if (u.ns.nwaiters != 0) ++#if __HAVE_64B_ATOMICS ++ unsigned int nwaiters = (u.ns.data >> SEM_NWAITERS_SHIFT); ++#else ++ unsigned int nwaiters = u.ns.nwaiters; ++#endif ++ if (nwaiters != 0) + { +- printf ("sem_timedwait modified nwaiters: %ld\n", u.ns.nwaiters); ++ printf ("sem_timedwait modified nwaiters: %d\n", nwaiters); + return 1; + } + +@@ -52,9 +57,14 @@ do_test (void) + perror ("2nd sem_timedwait did not fail with ETIMEDOUT"); + return 1; + } +- if (u.ns.nwaiters != 0) ++#if __HAVE_64B_ATOMICS ++ nwaiters = (u.ns.data >> SEM_NWAITERS_SHIFT); ++#else ++ nwaiters = u.ns.nwaiters; ++#endif ++ if (nwaiters != 0) + { +- printf ("2nd sem_timedwait modified nwaiters: %ld\n", u.ns.nwaiters); ++ printf ("2nd sem_timedwait modified nwaiters: %d\n", nwaiters); + return 1; + } + +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S ++++ /dev/null +@@ -1,151 +0,0 @@ +-/* Copyright (C) 2002,2003,2005,2007,2008,2011-2012 +- Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2002. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +-#include +- +- +- .text +- +- .globl __new_sem_post +- .type __new_sem_post,@function +- .align 16 +-__new_sem_post: +- cfi_startproc +- pushl %ebx +- cfi_adjust_cfa_offset(4) +- cfi_offset(%ebx, -8) +- +- movl 8(%esp), %ebx +- +-#if VALUE == 0 +- movl (%ebx), %eax +-#else +- movl VALUE(%ebx), %eax +-#endif +-0: cmpl $SEM_VALUE_MAX, %eax +- je 3f +- leal 1(%eax), %edx +- LOCK +-#if VALUE == 0 +- cmpxchgl %edx, (%ebx) +-#else +- cmpxchgl %edx, VALUE(%ebx) +-#endif +- jnz 0b +- +- cmpl $0, NWAITERS(%ebx) +- je 2f +- +- movl $FUTEX_WAKE, %ecx +- orl PRIVATE(%ebx), %ecx +- movl $1, %edx +- movl $SYS_futex, %eax +- ENTER_KERNEL +- +- testl %eax, %eax +- js 1f +- +-2: xorl %eax, %eax +- popl %ebx +- cfi_adjust_cfa_offset(-4) +- cfi_restore(%ebx) +- ret +- +- cfi_adjust_cfa_offset(4) +- cfi_offset(%ebx, -8) +-1: +-#ifdef PIC +- SETUP_PIC_REG(bx) +-#else +- movl $4f, %ebx +-4: +-#endif +- addl $_GLOBAL_OFFSET_TABLE_, %ebx +-#ifdef NO_TLS_DIRECT_SEG_REFS +- movl errno@gotntpoff(%ebx), %edx +- addl %gs:0, %edx +- movl $EINVAL, (%edx) +-#else +- movl errno@gotntpoff(%ebx), %edx +- movl $EINVAL, %gs:(%edx) +-#endif +- +- orl $-1, %eax +- popl %ebx +- ret +- +-3: +-#ifdef PIC +- SETUP_PIC_REG(bx) +-#else +- movl $5f, %ebx +-5: +-#endif +- addl $_GLOBAL_OFFSET_TABLE_, %ebx +-#ifdef NO_TLS_DIRECT_SEG_REFS +- movl errno@gotntpoff(%ebx), %edx +- addl %gs:0, %edx +- movl $EOVERFLOW, (%edx) +-#else +- movl errno@gotntpoff(%ebx), %edx +- movl $EOVERFLOW, %gs:(%edx) +-#endif +- +- orl $-1, %eax +- popl %ebx +- cfi_adjust_cfa_offset(-4) +- cfi_restore(%ebx) +- ret +- cfi_endproc +- .size __new_sem_post,.-__new_sem_post +- versioned_symbol(libpthread, __new_sem_post, sem_post, GLIBC_2_1) +-#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) +- .global __old_sem_post +- .type __old_sem_post,@function +-__old_sem_post: +- cfi_startproc +- pushl %ebx +- cfi_adjust_cfa_offset(4) +- cfi_offset(%ebx, -8) +- +- movl 8(%esp), %ebx +- LOCK +- addl $1, (%ebx) +- +- movl $SYS_futex, %eax +- movl $FUTEX_WAKE, %ecx +- movl $1, %edx +- ENTER_KERNEL +- +- testl %eax, %eax +- js 1b +- +- xorl %eax, %eax +- popl %ebx +- cfi_adjust_cfa_offset(-4) +- cfi_restore(%ebx) +- ret +- cfi_endproc +- .size __old_sem_post,.-__old_sem_post +- compat_symbol(libpthread, __old_sem_post, sem_post, GLIBC_2_0) +-#endif +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S ++++ /dev/null +@@ -1,327 +0,0 @@ +-/* Copyright (C) 2002-2012 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2002. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +-#include +- +- +-#if VALUE != 0 +-# error "code needs to be rewritten for VALUE != 0" +-#endif +- +- +- .text +- +- .globl sem_timedwait +- .type sem_timedwait,@function +- .align 16 +-sem_timedwait: +-.LSTARTCODE: +- movl 4(%esp), %ecx +- +- movl (%ecx), %eax +-2: testl %eax, %eax +- je 1f +- +- leal -1(%eax), %edx +- LOCK +- cmpxchgl %edx, (%ecx) +- jne 2b +- +- xorl %eax, %eax +- ret +- +- /* Check whether the timeout value is valid. */ +-1: pushl %esi +-.Lpush_esi: +- pushl %edi +-.Lpush_edi: +- pushl %ebx +-.Lpush_ebx: +- subl $12, %esp +-.Lsub_esp: +- +- movl 32(%esp), %edi +- +- /* Check for invalid nanosecond field. */ +- cmpl $1000000000, 4(%edi) +- movl $EINVAL, %esi +- jae .Lerrno_exit +- +- LOCK +- incl NWAITERS(%ecx) +- +-7: xorl %ecx, %ecx +- movl %esp, %ebx +- movl %ecx, %edx +- movl $__NR_gettimeofday, %eax +- ENTER_KERNEL +- +- /* Compute relative timeout. */ +- movl 4(%esp), %eax +- movl $1000, %edx +- mul %edx /* Milli seconds to nano seconds. */ +- movl (%edi), %ecx +- movl 4(%edi), %edx +- subl (%esp), %ecx +- subl %eax, %edx +- jns 5f +- addl $1000000000, %edx +- subl $1, %ecx +-5: testl %ecx, %ecx +- movl $ETIMEDOUT, %esi +- js 6f /* Time is already up. */ +- +- movl %ecx, (%esp) /* Store relative timeout. */ +- movl %edx, 4(%esp) +- +-.LcleanupSTART: +- call __pthread_enable_asynccancel +- movl %eax, 8(%esp) +- +- movl 28(%esp), %ebx /* Load semaphore address. */ +-#if FUTEX_WAIT == 0 +- movl PRIVATE(%ebx), %ecx +-#else +- movl $FUTEX_WAIT, %ecx +- orl PRIVATE(%ebx), %ecx +-#endif +- movl %esp, %esi +- xorl %edx, %edx +- movl $SYS_futex, %eax +- ENTER_KERNEL +- movl %eax, %esi +- +- movl 8(%esp), %eax +- call __pthread_disable_asynccancel +-.LcleanupEND: +- +- testl %esi, %esi +- je 9f +- cmpl $-EWOULDBLOCK, %esi +- jne 3f +- +-9: movl (%ebx), %eax +-8: testl %eax, %eax +- je 7b +- +- leal -1(%eax), %ecx +- LOCK +- cmpxchgl %ecx, (%ebx) +- jne 8b +- +- xorl %eax, %eax +- +- LOCK +- decl NWAITERS(%ebx) +- +-10: addl $12, %esp +-.Ladd_esp: +- popl %ebx +-.Lpop_ebx: +- popl %edi +-.Lpop_edi: +- popl %esi +-.Lpop_esi: +- ret +- +-.Lafter_ret: +-3: negl %esi +-6: +- movl 28(%esp), %ebx /* Load semaphore address. */ +- LOCK +- decl NWAITERS(%ebx) +-.Lerrno_exit: +-#ifdef PIC +- SETUP_PIC_REG(bx) +-#else +- movl $4f, %ebx +-4: +-#endif +- addl $_GLOBAL_OFFSET_TABLE_, %ebx +-#ifdef NO_TLS_DIRECT_SEG_REFS +- movl errno@gotntpoff(%ebx), %edx +- addl %gs:0, %edx +- movl %esi, (%edx) +-#else +- movl errno@gotntpoff(%ebx), %edx +- movl %esi, %gs:(%edx) +-#endif +- +- orl $-1, %eax +- jmp 10b +- .size sem_timedwait,.-sem_timedwait +- +- +- .type sem_wait_cleanup,@function +-sem_wait_cleanup: +- LOCK +- decl NWAITERS(%ebx) +- movl %eax, (%esp) +-.LcallUR: +- call _Unwind_Resume@PLT +- hlt +-.LENDCODE: +- .size sem_wait_cleanup,.-sem_wait_cleanup +- +- +- .section .gcc_except_table,"a",@progbits +-.LexceptSTART: +- .byte 0xff # @LPStart format (omit) +- .byte 0xff # @TType format (omit) +- .byte 0x01 # call-site format +- # DW_EH_PE_uleb128 +- .uleb128 .Lcstend-.Lcstbegin +-.Lcstbegin: +- .uleb128 .LcleanupSTART-.LSTARTCODE +- .uleb128 .LcleanupEND-.LcleanupSTART +- .uleb128 sem_wait_cleanup-.LSTARTCODE +- .uleb128 0 +- .uleb128 .LcallUR-.LSTARTCODE +- .uleb128 .LENDCODE-.LcallUR +- .uleb128 0 +- .uleb128 0 +-.Lcstend: +- +- +- .section .eh_frame,"a",@progbits +-.LSTARTFRAME: +- .long .LENDCIE-.LSTARTCIE # Length of the CIE. +-.LSTARTCIE: +- .long 0 # CIE ID. +- .byte 1 # Version number. +-#ifdef SHARED +- .string "zPLR" # NUL-terminated augmentation +- # string. +-#else +- .string "zPL" # NUL-terminated augmentation +- # string. +-#endif +- .uleb128 1 # Code alignment factor. +- .sleb128 -4 # Data alignment factor. +- .byte 8 # Return address register +- # column. +-#ifdef SHARED +- .uleb128 7 # Augmentation value length. +- .byte 0x9b # Personality: DW_EH_PE_pcrel +- # + DW_EH_PE_sdata4 +- # + DW_EH_PE_indirect +- .long DW.ref.__gcc_personality_v0-. +- .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel +- # + DW_EH_PE_sdata4. +- .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel +- # + DW_EH_PE_sdata4. +-#else +- .uleb128 6 # Augmentation value length. +- .byte 0x0 # Personality: absolute +- .long __gcc_personality_v0 +- .byte 0x0 # LSDA Encoding: absolute +-#endif +- .byte 0x0c # DW_CFA_def_cfa +- .uleb128 4 +- .uleb128 4 +- .byte 0x88 # DW_CFA_offset, column 0x10 +- .uleb128 1 +- .align 4 +-.LENDCIE: +- +- .long .LENDFDE-.LSTARTFDE # Length of the FDE. +-.LSTARTFDE: +- .long .LSTARTFDE-.LSTARTFRAME # CIE pointer. +-#ifdef SHARED +- .long .LSTARTCODE-. # PC-relative start address +- # of the code. +-#else +- .long .LSTARTCODE # Start address of the code. +-#endif +- .long .LENDCODE-.LSTARTCODE # Length of the code. +- .uleb128 4 # Augmentation size +-#ifdef SHARED +- .long .LexceptSTART-. +-#else +- .long .LexceptSTART +-#endif +- +- .byte 4 # DW_CFA_advance_loc4 +- .long .Lpush_esi-.LSTARTCODE +- .byte 14 # DW_CFA_def_cfa_offset +- .uleb128 8 +- .byte 0x86 # DW_CFA_offset %esi +- .uleb128 2 +- .byte 4 # DW_CFA_advance_loc4 +- .long .Lpush_edi-.Lpush_esi +- .byte 14 # DW_CFA_def_cfa_offset +- .uleb128 12 +- .byte 0x87 # DW_CFA_offset %edi +- .uleb128 3 +- .byte 4 # DW_CFA_advance_loc4 +- .long .Lpush_ebx-.Lpush_edi +- .byte 14 # DW_CFA_def_cfa_offset +- .uleb128 16 +- .byte 0x83 # DW_CFA_offset %ebx +- .uleb128 4 +- .byte 4 # DW_CFA_advance_loc4 +- .long .Lsub_esp-.Lpush_ebx +- .byte 14 # DW_CFA_def_cfa_offset +- .uleb128 28 +- .byte 4 # DW_CFA_advance_loc4 +- .long .Ladd_esp-.Lsub_esp +- .byte 14 # DW_CFA_def_cfa_offset +- .uleb128 16 +- .byte 4 # DW_CFA_advance_loc4 +- .long .Lpop_ebx-.Ladd_esp +- .byte 14 # DW_CFA_def_cfa_offset +- .uleb128 12 +- .byte 0xc3 # DW_CFA_restore %ebx +- .byte 4 # DW_CFA_advance_loc4 +- .long .Lpop_edi-.Lpop_ebx +- .byte 14 # DW_CFA_def_cfa_offset +- .uleb128 8 +- .byte 0xc7 # DW_CFA_restore %edi +- .byte 4 # DW_CFA_advance_loc4 +- .long .Lpop_esi-.Lpop_edi +- .byte 14 # DW_CFA_def_cfa_offset +- .uleb128 4 +- .byte 0xc6 # DW_CFA_restore %esi +- .byte 4 # DW_CFA_advance_loc4 +- .long .Lafter_ret-.Lpop_esi +- .byte 14 # DW_CFA_def_cfa_offset +- .uleb128 28 +- .byte 0x86 # DW_CFA_offset %esi +- .uleb128 2 +- .byte 0x87 # DW_CFA_offset %edi +- .uleb128 3 +- .byte 0x83 # DW_CFA_offset %ebx +- .uleb128 4 +- .align 4 +-.LENDFDE: +- +- +-#ifdef SHARED +- .hidden DW.ref.__gcc_personality_v0 +- .weak DW.ref.__gcc_personality_v0 +- .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits +- .align 4 +- .type DW.ref.__gcc_personality_v0, @object +- .size DW.ref.__gcc_personality_v0, 4 +-DW.ref.__gcc_personality_v0: +- .long __gcc_personality_v0 +-#endif +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S ++++ /dev/null +@@ -1,67 +0,0 @@ +-/* Copyright (C) 2002-2003, 2005, 2007, 2011-2012 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2002. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +- +- .text +- +- .globl __new_sem_trywait +- .type __new_sem_trywait,@function +- .align 16 +-__new_sem_trywait: +- movl 4(%esp), %ecx +- +- movl (%ecx), %eax +-2: testl %eax, %eax +- jz 1f +- +- leal -1(%eax), %edx +- LOCK +- cmpxchgl %edx, (%ecx) +- jne 2b +- xorl %eax, %eax +- ret +- +-1: +-#ifdef PIC +- SETUP_PIC_REG(cx) +-#else +- movl $3f, %ecx +-3: +-#endif +- addl $_GLOBAL_OFFSET_TABLE_, %ecx +-#ifdef NO_TLS_DIRECT_SEG_REFS +- movl errno@gotntpoff(%ecx), %edx +- addl %gs:0, %edx +- movl $EAGAIN, (%edx) +-#else +- movl errno@gotntpoff(%ecx), %edx +- movl $EAGAIN, %gs:(%edx) +-#endif +- orl $-1, %eax +- ret +- .size __new_sem_trywait,.-__new_sem_trywait +- versioned_symbol(libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1) +-#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) +- .global __old_sem_trywait +-__old_sem_trywait = __new_sem_trywait +- compat_symbol(libpthread, __old_sem_trywait, sem_trywait, GLIBC_2_0) +-#endif +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S ++++ /dev/null +@@ -1,343 +0,0 @@ +-/* Copyright (C) 2002-2003, 2005, 2007, 2011-2012 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2002. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +-#include +- +- +-#if VALUE != 0 +-# error "code needs to be rewritten for VALUE != 0" +-#endif +- +- .text +- +- .globl __new_sem_wait +- .type __new_sem_wait,@function +- .align 16 +-__new_sem_wait: +-.LSTARTCODE: +- pushl %ebx +-.Lpush_ebx: +- pushl %esi +-.Lpush_esi: +- subl $4, %esp +-.Lsub_esp: +- +- movl 16(%esp), %ebx +- +- movl (%ebx), %eax +-2: testl %eax, %eax +- je 1f +- +- leal -1(%eax), %edx +- LOCK +- cmpxchgl %edx, (%ebx) +- jne 2b +-7: xorl %eax, %eax +- +-9: movl 4(%esp), %esi +- movl 8(%esp), %ebx +- addl $12, %esp +-.Ladd_esp: +- ret +- +-.Lafter_ret: +-1: LOCK +- incl NWAITERS(%ebx) +- +-.LcleanupSTART: +-6: call __pthread_enable_asynccancel +- movl %eax, (%esp) +- +-#if FUTEX_WAIT == 0 +- movl PRIVATE(%ebx), %ecx +-#else +- movl $FUTEX_WAIT, %ecx +- orl PRIVATE(%ebx), %ecx +-#endif +- xorl %esi, %esi +- xorl %edx, %edx +- movl $SYS_futex, %eax +- ENTER_KERNEL +- movl %eax, %esi +- +- movl (%esp), %eax +- call __pthread_disable_asynccancel +-.LcleanupEND: +- +- testl %esi, %esi +- je 3f +- cmpl $-EWOULDBLOCK, %esi +- jne 4f +- +-3: +- movl (%ebx), %eax +-5: testl %eax, %eax +- je 6b +- +- leal -1(%eax), %edx +- LOCK +- cmpxchgl %edx, (%ebx) +- jne 5b +- +- LOCK +- decl NWAITERS(%ebx) +- jmp 7b +- +-4: LOCK +- decl NWAITERS(%ebx) +- +- negl %esi +-#ifdef PIC +- SETUP_PIC_REG(bx) +-#else +- movl $8f, %ebx +-8: +-#endif +- addl $_GLOBAL_OFFSET_TABLE_, %ebx +-#ifdef NO_TLS_DIRECT_SEG_REFS +- movl errno@gotntpoff(%ebx), %edx +- addl %gs:0, %edx +- movl %esi, (%edx) +-#else +- movl errno@gotntpoff(%ebx), %edx +- movl %esi, %gs:(%edx) +-#endif +- orl $-1, %eax +- +- jmp 9b +- .size __new_sem_wait,.-__new_sem_wait +- versioned_symbol(libpthread, __new_sem_wait, sem_wait, GLIBC_2_1) +- +- +- .type sem_wait_cleanup,@function +-sem_wait_cleanup: +- LOCK +- decl NWAITERS(%ebx) +- movl %eax, (%esp) +-.LcallUR: +- call _Unwind_Resume@PLT +- hlt +-.LENDCODE: +- .size sem_wait_cleanup,.-sem_wait_cleanup +- +- +- .section .gcc_except_table,"a",@progbits +-.LexceptSTART: +- .byte 0xff # @LPStart format (omit) +- .byte 0xff # @TType format (omit) +- .byte 0x01 # call-site format +- # DW_EH_PE_uleb128 +- .uleb128 .Lcstend-.Lcstbegin +-.Lcstbegin: +- .uleb128 .LcleanupSTART-.LSTARTCODE +- .uleb128 .LcleanupEND-.LcleanupSTART +- .uleb128 sem_wait_cleanup-.LSTARTCODE +- .uleb128 0 +- .uleb128 .LcallUR-.LSTARTCODE +- .uleb128 .LENDCODE-.LcallUR +- .uleb128 0 +- .uleb128 0 +-.Lcstend: +- +- +- .section .eh_frame,"a",@progbits +-.LSTARTFRAME: +- .long .LENDCIE-.LSTARTCIE # Length of the CIE. +-.LSTARTCIE: +- .long 0 # CIE ID. +- .byte 1 # Version number. +-#ifdef SHARED +- .string "zPLR" # NUL-terminated augmentation +- # string. +-#else +- .string "zPL" # NUL-terminated augmentation +- # string. +-#endif +- .uleb128 1 # Code alignment factor. +- .sleb128 -4 # Data alignment factor. +- .byte 8 # Return address register +- # column. +-#ifdef SHARED +- .uleb128 7 # Augmentation value length. +- .byte 0x9b # Personality: DW_EH_PE_pcrel +- # + DW_EH_PE_sdata4 +- # + DW_EH_PE_indirect +- .long DW.ref.__gcc_personality_v0-. +- .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel +- # + DW_EH_PE_sdata4. +- .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel +- # + DW_EH_PE_sdata4. +-#else +- .uleb128 6 # Augmentation value length. +- .byte 0x0 # Personality: absolute +- .long __gcc_personality_v0 +- .byte 0x0 # LSDA Encoding: absolute +-#endif +- .byte 0x0c # DW_CFA_def_cfa +- .uleb128 4 +- .uleb128 4 +- .byte 0x88 # DW_CFA_offset, column 0x10 +- .uleb128 1 +- .align 4 +-.LENDCIE: +- +- .long .LENDFDE-.LSTARTFDE # Length of the FDE. +-.LSTARTFDE: +- .long .LSTARTFDE-.LSTARTFRAME # CIE pointer. +-#ifdef SHARED +- .long .LSTARTCODE-. # PC-relative start address +- # of the code. +-#else +- .long .LSTARTCODE # Start address of the code. +-#endif +- .long .LENDCODE-.LSTARTCODE # Length of the code. +- .uleb128 4 # Augmentation size +-#ifdef SHARED +- .long .LexceptSTART-. +-#else +- .long .LexceptSTART +-#endif +- +- .byte 4 # DW_CFA_advance_loc4 +- .long .Lpush_ebx-.LSTARTCODE +- .byte 14 # DW_CFA_def_cfa_offset +- .uleb128 8 +- .byte 0x83 # DW_CFA_offset %ebx +- .uleb128 2 +- .byte 4 # DW_CFA_advance_loc4 +- .long .Lpush_esi-.Lpush_ebx +- .byte 14 # DW_CFA_def_cfa_offset +- .uleb128 12 +- .byte 0x86 # DW_CFA_offset %esi +- .uleb128 3 +- .byte 4 # DW_CFA_advance_loc4 +- .long .Lsub_esp-.Lpush_esi +- .byte 14 # DW_CFA_def_cfa_offset +- .uleb128 16 +- .byte 4 # DW_CFA_advance_loc4 +- .long .Ladd_esp-.Lsub_esp +- .byte 14 # DW_CFA_def_cfa_offset +- .uleb128 4 +- .byte 0xc3 # DW_CFA_restore %ebx +- .byte 0xc6 # DW_CFA_restore %esi +- .byte 4 # DW_CFA_advance_loc4 +- .long .Lafter_ret-.Ladd_esp +- .byte 14 # DW_CFA_def_cfa_offset +- .uleb128 16 +- .byte 0x83 # DW_CFA_offset %ebx +- .uleb128 2 +- .byte 0x86 # DW_CFA_offset %esi +- .uleb128 3 +- .align 4 +-.LENDFDE: +- +- +-#ifdef SHARED +- .hidden DW.ref.__gcc_personality_v0 +- .weak DW.ref.__gcc_personality_v0 +- .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits +- .align 4 +- .type DW.ref.__gcc_personality_v0, @object +- .size DW.ref.__gcc_personality_v0, 4 +-DW.ref.__gcc_personality_v0: +- .long __gcc_personality_v0 +-#endif +- +- +-#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) +- .section ".text.compat", "ax" +- .global __old_sem_wait +- .type __old_sem_wait,@function +- .align 16 +- cfi_startproc +-__old_sem_wait: +- pushl %ebx +- cfi_adjust_cfa_offset(4) +- pushl %esi +- cfi_adjust_cfa_offset(4) +- subl $4, %esp +- cfi_adjust_cfa_offset(4) +- +- movl 16(%esp), %ebx +- cfi_offset(ebx, -8) +- +- cfi_offset(esi, -12) +-3: movl (%ebx), %eax +-2: testl %eax, %eax +- je 1f +- +- leal -1(%eax), %edx +- LOCK +- cmpxchgl %edx, (%ebx) +- jne 2b +- xorl %eax, %eax +- +-5: movl 4(%esp), %esi +- movl 8(%esp), %ebx +- addl $12, %esp +- cfi_restore(ebx) +- cfi_restore(esi) +- cfi_adjust_cfa_offset(-12) +- ret +- +- cfi_adjust_cfa_offset(12) +- cfi_offset(ebx, -8) +- cfi_offset(esi, -12) +-1: call __pthread_enable_asynccancel +- movl %eax, (%esp) +- +- xorl %esi, %esi +- movl $SYS_futex, %eax +- movl %esi, %ecx +- movl %esi, %edx +- ENTER_KERNEL +- movl %eax, %esi +- +- movl (%esp), %eax +- call __pthread_disable_asynccancel +- +- testl %esi, %esi +- je 3b +- cmpl $-EWOULDBLOCK, %esi +- je 3b +- negl %esi +-#ifdef PIC +- SETUP_PIC_REG(bx) +-#else +- movl $4f, %ebx +-4: +-#endif +- addl $_GLOBAL_OFFSET_TABLE_, %ebx +-#ifdef NO_TLS_DIRECT_SEG_REFS +- movl errno@gotntpoff(%ebx), %edx +- addl %gs:0, %edx +- movl %esi, (%edx) +-#else +- movl errno@gotntpoff(%ebx), %edx +- movl %esi, %gs:(%edx) +-#endif +- orl $-1, %eax +- jmp 5b +- cfi_endproc +- .size __old_sem_wait,.-__old_sem_wait +- compat_symbol(libpthread, __old_sem_wait, sem_wait, GLIBC_2_0) +-#endif +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_post.S +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_post.S ++++ /dev/null +@@ -1,19 +0,0 @@ +-/* Copyright (C) 2003 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2003. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include "../i486/sem_post.S" +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S ++++ /dev/null +@@ -1,19 +0,0 @@ +-/* Copyright (C) 2003 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2003. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include "../i486/sem_timedwait.S" +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S ++++ /dev/null +@@ -1,19 +0,0 @@ +-/* Copyright (C) 2003 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2003. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include "../i486/sem_trywait.S" +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_wait.S +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_wait.S ++++ /dev/null +@@ -1,19 +0,0 @@ +-/* Copyright (C) 2003 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2003. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include "../i486/sem_wait.S" +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_post.S +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_post.S ++++ /dev/null +@@ -1,19 +0,0 @@ +-/* Copyright (C) 2003 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2003. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include "../i486/sem_post.S" +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S ++++ /dev/null +@@ -1,19 +0,0 @@ +-/* Copyright (C) 2003 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2003. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include "../i486/sem_timedwait.S" +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S ++++ /dev/null +@@ -1,19 +0,0 @@ +-/* Copyright (C) 2003 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2003. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include "../i486/sem_trywait.S" +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_wait.S +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_wait.S ++++ /dev/null +@@ -1,19 +0,0 @@ +-/* Copyright (C) 2003 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2003. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include "../i486/sem_wait.S" +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/internaltypes.h +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/internaltypes.h ++++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/internaltypes.h +@@ -20,6 +20,8 @@ + #define _INTERNALTYPES_H 1 + + #include ++#include ++#include + + + struct pthread_attr +@@ -141,9 +143,29 @@ struct pthread_key_struct + /* Semaphore variable structure. */ + struct new_sem + { ++#if __HAVE_64B_ATOMICS ++ /* The data field holds both value (in the least-significant 32 bytes) and ++ nwaiters. */ ++# if __BYTE_ORDER == __LITTLE_ENDIAN ++# define SEM_VALUE_OFFSET 0 ++# elif __BYTE_ORDER == __BIG_ENDIAN ++# define SEM_VALUE_OFFSET 1 ++# else ++# error Unsupported byte order. ++# endif ++# define SEM_NWAITERS_SHIFT 32 ++# define SEM_VALUE_MASK (~(unsigned int)0) ++ unsigned long int data; ++ int private; ++ int pad; ++#else ++# define SEM_VALUE_SHIFT 1 ++# define SEM_NWAITERS_MASK ((unsigned int)1) + unsigned int value; + int private; +- unsigned long int nwaiters; ++ int pad; ++ unsigned int nwaiters; ++#endif + }; + + struct old_sem +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/sem_post.c +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/powerpc/sem_post.c ++++ /dev/null +@@ -1,71 +0,0 @@ +-/* sem_post -- post to a POSIX semaphore. Powerpc version. +- Copyright (C) 2003-2012 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Paul Mackerras , 2003. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-int +-__new_sem_post (sem_t *sem) +-{ +- struct new_sem *isem = (struct new_sem *) sem; +- +- __asm __volatile (__lll_rel_instr ::: "memory"); +- atomic_increment (&isem->value); +- __asm __volatile (__lll_acq_instr ::: "memory"); +- if (isem->nwaiters > 0) +- { +- int err = lll_futex_wake (&isem->value, 1, +- isem->private ^ FUTEX_PRIVATE_FLAG); +- if (__builtin_expect (err, 0) < 0) +- { +- __set_errno (-err); +- return -1; +- } +- } +- return 0; +-} +-versioned_symbol (libpthread, __new_sem_post, sem_post, GLIBC_2_1); +- +-#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) +- +-int +-attribute_compat_text_section +-__old_sem_post (sem_t *sem) +-{ +- int *futex = (int *) sem; +- +- __asm __volatile (__lll_rel_instr ::: "memory"); +- (void) atomic_increment_val (futex); +- /* We always have to assume it is a shared semaphore. */ +- int err = lll_futex_wake (futex, 1, LLL_SHARED); +- if (__builtin_expect (err, 0) < 0) +- { +- __set_errno (-err); +- return -1; +- } +- return 0; +-} +- +-compat_symbol (libpthread, __old_sem_post, sem_post, GLIBC_2_0); +-#endif +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/sem_post.c +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/sem_post.c ++++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/sem_post.c +@@ -25,34 +25,78 @@ + + #include + ++/* Wrapper for lll_futex_wake, with error checking. ++ TODO Remove when cleaning up the futex API throughout glibc. */ ++static __always_inline void ++futex_wake (unsigned int* futex, int processes_to_wake, int private) ++{ ++ int res = lll_futex_wake (futex, processes_to_wake, private); ++ /* No error. Ignore the number of woken processes. */ ++ if (res >= 0) ++ return; ++ switch (res) ++ { ++ case -EFAULT: /* Could have happened due to memory reuse. */ ++ case -EINVAL: /* Could be either due to incorrect alignment (a bug in ++ glibc or in the application) or due to memory being ++ reused for a PI futex. We cannot distinguish between the ++ two causes, and one of them is correct use, so we do not ++ act in this case. */ ++ return; ++ case -ENOSYS: /* Must have been caused by a glibc bug. */ ++ /* No other errors are documented at this time. */ ++ default: ++ abort (); ++ } ++} ++ ++ ++/* See sem_wait for an explanation of the algorithm. */ + int + __new_sem_post (sem_t *sem) + { + struct new_sem *isem = (struct new_sem *) sem; ++ int private = isem->private; + +- __typeof (isem->value) cur; ++#if __HAVE_64B_ATOMICS ++ /* Add a token to the semaphore. We use release MO to make sure that a ++ thread acquiring this token synchronizes with us and other threads that ++ added tokens before (the release sequence includes atomic RMW operations ++ by other threads). */ ++ /* TODO Use atomic_fetch_add to make it scale better than a CAS loop? */ ++ unsigned long int d = atomic_load_relaxed (&isem->data); + do + { +- cur = isem->value; +- if (isem->value == SEM_VALUE_MAX) ++ if ((d & SEM_VALUE_MASK) == SEM_VALUE_MAX) + { + __set_errno (EOVERFLOW); + return -1; + } + } +- while (atomic_compare_and_exchange_bool_rel (&isem->value, cur + 1, cur)); ++ while (!atomic_compare_exchange_weak_release (&isem->data, &d, d + 1)); + +- atomic_full_barrier (); +- if (isem->nwaiters > 0) ++ /* If there is any potentially blocked waiter, wake one of them. */ ++ if ((d >> SEM_NWAITERS_SHIFT) > 0) ++ futex_wake (((unsigned int *) &isem->data) + SEM_VALUE_OFFSET, 1, private); ++#else ++ /* Add a token to the semaphore. Similar to 64b version. */ ++ unsigned int v = atomic_load_relaxed (&isem->value); ++ do + { +- int err = lll_futex_wake (&isem->value, 1, +- isem->private ^ FUTEX_PRIVATE_FLAG); +- if (__builtin_expect (err, 0) < 0) ++ if ((v << SEM_VALUE_SHIFT) == SEM_VALUE_MAX) + { +- __set_errno (-err); ++ __set_errno (EOVERFLOW); + return -1; + } + } ++ while (!atomic_compare_exchange_weak_release (&isem->value, ++ &v, v + (1 << SEM_VALUE_SHIFT))); ++ ++ /* If there is any potentially blocked waiter, wake one of them. */ ++ if ((v & SEM_NWAITERS_MASK) != 0) ++ futex_wake (&isem->value, 1, private); ++#endif ++ + return 0; + } + versioned_symbol (libpthread, __new_sem_post, sem_post, GLIBC_2_1); +@@ -65,6 +109,9 @@ __old_sem_post (sem_t *sem) + { + int *futex = (int *) sem; + ++ /* We must need to synchronize with consumers of this token, so the atomic ++ increment must have release MO semantics. */ ++ atomic_write_barrier (); + (void) atomic_increment_val (futex); + /* We always have to assume it is a shared semaphore. */ + int err = lll_futex_wake (futex, 1, LLL_SHARED); +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c ++++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c +@@ -1,5 +1,5 @@ +-/* sem_timedwait -- wait on a semaphore. Generic futex-using version. +- Copyright (C) 2003, 2007, 2012 Free Software Foundation, Inc. ++/* sem_timedwait -- wait on a semaphore with timeout. ++ Copyright (C) 2003-2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + +@@ -17,42 +17,13 @@ + License along with the GNU C Library; if not, see + . */ + +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +- +- +-extern void __sem_wait_cleanup (void *arg) attribute_hidden; +- +-/* This is in a seperate function in order to make sure gcc +- puts the call site into an exception region, and thus the +- cleanups get properly run. */ +-static int +-__attribute__ ((noinline)) +-do_futex_timed_wait (struct new_sem *isem, struct timespec *rt) +-{ +- int err, oldtype = __pthread_enable_asynccancel (); +- +- err = lll_futex_timed_wait (&isem->value, 0, rt, +- isem->private ^ FUTEX_PRIVATE_FLAG); +- +- __pthread_disable_asynccancel (oldtype); +- return err; +-} ++#include "sem_waitcommon.c" + ++/* This is in a separate file because because sem_timedwait is only provided ++ if __USE_XOPEN2K is defined. */ + int + sem_timedwait (sem_t *sem, const struct timespec *abstime) + { +- struct new_sem *isem = (struct new_sem *) sem; +- int err; +- +- if (atomic_decrement_if_positive (&isem->value) > 0) +- return 0; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + { +@@ -60,57 +31,8 @@ sem_timedwait (sem_t *sem, const struct + return -1; + } + +- atomic_increment (&isem->nwaiters); +- +- pthread_cleanup_push (__sem_wait_cleanup, isem); +- +- while (1) +- { +- struct timeval tv; +- struct timespec rt; +- int sec, nsec; +- +- /* Get the current time. */ +- __gettimeofday (&tv, NULL); +- +- /* Compute relative timeout. */ +- sec = abstime->tv_sec - tv.tv_sec; +- nsec = abstime->tv_nsec - tv.tv_usec * 1000; +- if (nsec < 0) +- { +- nsec += 1000000000; +- --sec; +- } +- +- /* Already timed out? */ +- if (sec < 0) +- { +- __set_errno (ETIMEDOUT); +- err = -1; +- break; +- } +- +- /* Do wait. */ +- rt.tv_sec = sec; +- rt.tv_nsec = nsec; +- err = do_futex_timed_wait(isem, &rt); +- if (err != 0 && err != -EWOULDBLOCK) +- { +- __set_errno (-err); +- err = -1; +- break; +- } +- +- if (atomic_decrement_if_positive (&isem->value) > 0) +- { +- err = 0; +- break; +- } +- } +- +- pthread_cleanup_pop (0); +- +- atomic_decrement (&isem->nwaiters); +- +- return err; ++ if (__new_sem_wait_fast ((struct new_sem *) sem, 0) == 0) ++ return 0; ++ else ++ return __new_sem_wait_slow((struct new_sem *) sem, abstime); + } +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/sem_trywait.c +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/sem_trywait.c ++++ /dev/null +@@ -1,49 +0,0 @@ +-/* sem_trywait -- wait on a semaphore. Generic futex-using version. +- Copyright (C) 2003 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Paul Mackerras , 2003. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +-#include +- +-#include +- +- +-int +-__new_sem_trywait (sem_t *sem) +-{ +- int *futex = (int *) sem; +- int val; +- +- if (*futex > 0) +- { +- val = atomic_decrement_if_positive (futex); +- if (val > 0) +- return 0; +- } +- +- __set_errno (EAGAIN); +- return -1; +-} +-versioned_symbol (libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1); +-#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) +-strong_alias (__new_sem_trywait, __old_sem_trywait) +-compat_symbol (libpthread, __old_sem_trywait, sem_trywait, GLIBC_2_0); +-#endif +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/sem_wait.c +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/sem_wait.c ++++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/sem_wait.c +@@ -17,79 +17,18 @@ + License along with the GNU C Library; if not, see + . */ + +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +- +- +-void +-attribute_hidden +-__sem_wait_cleanup (void *arg) +-{ +- struct new_sem *isem = (struct new_sem *) arg; +- +- atomic_decrement (&isem->nwaiters); +-} +- +-/* This is in a seperate function in order to make sure gcc +- puts the call site into an exception region, and thus the +- cleanups get properly run. */ +-static int +-__attribute__ ((noinline)) +-do_futex_wait (struct new_sem *isem) +-{ +- int err, oldtype = __pthread_enable_asynccancel (); +- +- err = lll_futex_wait (&isem->value, 0, isem->private ^ FUTEX_PRIVATE_FLAG); +- +- __pthread_disable_asynccancel (oldtype); +- return err; +-} ++#include "sem_waitcommon.c" + + int + __new_sem_wait (sem_t *sem) + { +- struct new_sem *isem = (struct new_sem *) sem; +- int err; +- +- if (atomic_decrement_if_positive (&isem->value) > 0) ++ if (__new_sem_wait_fast ((struct new_sem *) sem, 0) == 0) + return 0; +- +- atomic_increment (&isem->nwaiters); +- +- pthread_cleanup_push (__sem_wait_cleanup, isem); +- +- while (1) +- { +- err = do_futex_wait(isem); +- if (err != 0 && err != -EWOULDBLOCK) +- { +- __set_errno (-err); +- err = -1; +- break; +- } +- +- if (atomic_decrement_if_positive (&isem->value) > 0) +- { +- err = 0; +- break; +- } +- } +- +- pthread_cleanup_pop (0); +- +- atomic_decrement (&isem->nwaiters); +- +- return err; ++ else ++ return __new_sem_wait_slow((struct new_sem *) sem, NULL); + } + versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1); + +- + #if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) + int + attribute_compat_text_section +@@ -120,3 +59,34 @@ __old_sem_wait (sem_t *sem) + + compat_symbol (libpthread, __old_sem_wait, sem_wait, GLIBC_2_0); + #endif ++ ++int ++__new_sem_trywait (sem_t *sem) ++{ ++ /* We must not fail spuriously, so require a definitive result even if this ++ may lead to a long execution time. */ ++ if (__new_sem_wait_fast ((struct new_sem *) sem, 1) == 0) ++ return 0; ++ __set_errno (EAGAIN); ++ return -1; ++} ++versioned_symbol (libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1); ++#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) ++int ++__old_sem_trywait (sem_t *sem) ++{ ++ int *futex = (int *) sem; ++ int val; ++ ++ if (*futex > 0) ++ { ++ val = atomic_decrement_if_positive (futex); ++ if (val > 0) ++ return 0; ++ } ++ ++ __set_errno (EAGAIN); ++ return -1; ++} ++compat_symbol (libpthread, __old_sem_trywait, sem_trywait, GLIBC_2_0); ++#endif +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/sem_waitcommon.c +=================================================================== +--- /dev/null ++++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/sem_waitcommon.c +@@ -0,0 +1,467 @@ ++/* sem_waitcommon -- wait on a semaphore, shared code. ++ Copyright (C) 2003-2015 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Paul Mackerras , 2003. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++/* Wrapper for lll_futex_wait with absolute timeout and error checking. ++ TODO Remove when cleaning up the futex API throughout glibc. */ ++static __always_inline int ++futex_abstimed_wait (unsigned int* futex, unsigned int expected, ++ const struct timespec* abstime, int private, bool cancel) ++{ ++ int err, oldtype; ++ if (abstime == NULL) ++ { ++ if (cancel) ++ oldtype = __pthread_enable_asynccancel (); ++ err = lll_futex_wait (futex, expected, private); ++ if (cancel) ++ __pthread_disable_asynccancel (oldtype); ++ } ++ else ++ { ++ struct timeval tv; ++ struct timespec rt; ++ int sec, nsec; ++ ++ /* Get the current time. */ ++ __gettimeofday (&tv, NULL); ++ ++ /* Compute relative timeout. */ ++ sec = abstime->tv_sec - tv.tv_sec; ++ nsec = abstime->tv_nsec - tv.tv_usec * 1000; ++ if (nsec < 0) ++ { ++ nsec += 1000000000; ++ --sec; ++ } ++ ++ /* Already timed out? */ ++ if (sec < 0) ++ return ETIMEDOUT; ++ ++ /* Do wait. */ ++ rt.tv_sec = sec; ++ rt.tv_nsec = nsec; ++ if (cancel) ++ oldtype = __pthread_enable_asynccancel (); ++ err = lll_futex_timed_wait (futex, expected, &rt, private); ++ if (cancel) ++ __pthread_disable_asynccancel (oldtype); ++ } ++ switch (err) ++ { ++ case 0: ++ case -EAGAIN: ++ case -EINTR: ++ case -ETIMEDOUT: ++ return -err; ++ ++ case -EFAULT: /* Must have been caused by a glibc or application bug. */ ++ case -EINVAL: /* Either due to wrong alignment or due to the timeout not ++ being normalized. Must have been caused by a glibc or ++ application bug. */ ++ case -ENOSYS: /* Must have been caused by a glibc bug. */ ++ /* No other errors are documented at this time. */ ++ default: ++ abort (); ++ } ++} ++ ++/* Wrapper for lll_futex_wake, with error checking. ++ TODO Remove when cleaning up the futex API throughout glibc. */ ++static __always_inline void ++futex_wake (unsigned int* futex, int processes_to_wake, int private) ++{ ++ int res = lll_futex_wake (futex, processes_to_wake, private); ++ /* No error. Ignore the number of woken processes. */ ++ if (res >= 0) ++ return; ++ switch (res) ++ { ++ case -EFAULT: /* Could have happened due to memory reuse. */ ++ case -EINVAL: /* Could be either due to incorrect alignment (a bug in ++ glibc or in the application) or due to memory being ++ reused for a PI futex. We cannot distinguish between the ++ two causes, and one of them is correct use, so we do not ++ act in this case. */ ++ return; ++ case -ENOSYS: /* Must have been caused by a glibc bug. */ ++ /* No other errors are documented at this time. */ ++ default: ++ abort (); ++ } ++} ++ ++ ++/* The semaphore provides two main operations: sem_post adds a token to the ++ semaphore; sem_wait grabs a token from the semaphore, potentially waiting ++ until there is a token available. A sem_wait needs to synchronize with ++ the sem_post that provided the token, so that whatever lead to the sem_post ++ happens before the code after sem_wait. ++ ++ Conceptually, available tokens can simply be counted; let's call that the ++ value of the semaphore. However, we also want to know whether there might ++ be a sem_wait that is blocked on the value because it was zero (using a ++ futex with the value being the futex variable); if there is no blocked ++ sem_wait, sem_post does not need to execute a futex_wake call. Therefore, ++ we also need to count the number of potentially blocked sem_wait calls ++ (which we call nwaiters). ++ ++ What makes this tricky is that POSIX requires that a semaphore can be ++ destroyed as soon as the last remaining sem_wait has returned, and no ++ other sem_wait or sem_post calls are executing concurrently. However, the ++ sem_post call whose token was consumed by the last sem_wait is considered ++ to have finished once it provided the token to the sem_wait. ++ Thus, sem_post must not access the semaphore struct anymore after it has ++ made a token available; IOW, it needs to be able to atomically provide ++ a token and check whether any blocked sem_wait calls might exist. ++ ++ This is straightforward to do if the architecture provides 64b atomics ++ because we can just put both the value and nwaiters into one variable that ++ we access atomically: This is the data field, the value is in the ++ least-significant 32 bits, and nwaiters in the other bits. When sem_post ++ makes a value available, it can atomically check nwaiters. ++ ++ If we have only 32b atomics available, we cannot put both nwaiters and ++ value into one 32b value because then we might have too few bits for both ++ of those counters. Therefore, we need to use two distinct fields. ++ ++ To allow sem_post to atomically make a token available and check for ++ blocked sem_wait calls, we use one bit in value to indicate whether ++ nwaiters is nonzero. That allows sem_post to use basically the same ++ algorithm as with 64b atomics, but requires sem_wait to update the bit; it ++ can't do this atomically with another access to nwaiters, but it can compute ++ a conservative value for the bit because it's benign if the bit is set ++ even if nwaiters is zero (all we get is an unnecessary futex wake call by ++ sem_post). ++ Specifically, sem_wait will unset the bit speculatively if it believes that ++ there is no other concurrently executing sem_wait. If it misspeculated, ++ it will have to clean up by waking any other sem_wait call (i.e., what ++ sem_post would do otherwise). This does not conflict with the destruction ++ requirement because the semaphore must not be destructed while any sem_wait ++ is still executing. */ ++ ++/* Set this to true if you assume that, in contrast to current Linux futex ++ documentation, lll_futex_wake can return -EINTR only if interrupted by a ++ signal, not spuriously due to some other reason. ++ TODO Discuss EINTR conditions with the Linux kernel community. For ++ now, we set this to true to not change behavior of semaphores compared ++ to previous glibc builds. */ ++static const int sem_assume_only_signals_cause_futex_EINTR = 1; ++ ++#if !__HAVE_64B_ATOMICS ++static void ++__sem_wait_32_finish (struct new_sem *sem); ++#endif ++ ++static void ++__sem_wait_cleanup (void *arg) ++{ ++ struct new_sem *sem = (struct new_sem *) arg; ++ ++#if __HAVE_64B_ATOMICS ++ /* Stop being registered as a waiter. See below for MO. */ ++ atomic_fetch_add_relaxed (&sem->data, -(1UL << SEM_NWAITERS_SHIFT)); ++#else ++ __sem_wait_32_finish (sem); ++#endif ++} ++ ++/* Wait until at least one token is available, possibly with a timeout. ++ This is in a separate function in order to make sure gcc ++ puts the call site into an exception region, and thus the ++ cleanups get properly run. TODO still necessary? Other futex_wait ++ users don't seem to need it. */ ++static int ++__attribute__ ((noinline)) ++do_futex_wait (struct new_sem *sem, const struct timespec *abstime) ++{ ++ int err; ++ ++#if __HAVE_64B_ATOMICS ++ err = futex_abstimed_wait ((unsigned int *) &sem->data + SEM_VALUE_OFFSET, 0, ++ abstime, sem->private, true); ++#else ++ err = futex_abstimed_wait (&sem->value, SEM_NWAITERS_MASK, abstime, ++ sem->private, true); ++#endif ++ ++ return err; ++} ++ ++/* Fast path: Try to grab a token without blocking. */ ++static int ++__new_sem_wait_fast (struct new_sem *sem, int definitive_result) ++{ ++ /* We need acquire MO if we actually grab a token, so that this ++ synchronizes with all token providers (i.e., the RMW operation we read ++ from or all those before it in modification order; also see sem_post). ++ We do not need to guarantee any ordering if we observed that there is ++ no token (POSIX leaves it unspecified whether functions that fail ++ synchronize memory); thus, relaxed MO is sufficient for the initial load ++ and the failure path of the CAS. If the weak CAS fails and we need a ++ definitive result, retry. */ ++#if __HAVE_64B_ATOMICS ++ unsigned long d = atomic_load_relaxed (&sem->data); ++ do ++ { ++ if ((d & SEM_VALUE_MASK) == 0) ++ break; ++ if (atomic_compare_exchange_weak_acquire (&sem->data, &d, d - 1)) ++ return 0; ++ } ++ while (definitive_result); ++ return -1; ++#else ++ unsigned int v = atomic_load_relaxed (&sem->value); ++ do ++ { ++ if ((v >> SEM_VALUE_SHIFT) == 0) ++ break; ++ if (atomic_compare_exchange_weak_acquire (&sem->value, ++ &v, v - (1 << SEM_VALUE_SHIFT))) ++ return 0; ++ } ++ while (definitive_result); ++ return -1; ++#endif ++} ++ ++/* Slow path that blocks. */ ++static int ++__attribute__ ((noinline)) ++__new_sem_wait_slow (struct new_sem *sem, const struct timespec *abstime) ++{ ++ int err = 0; ++ ++#if __HAVE_64B_ATOMICS ++ /* Add a waiter. Relaxed MO is sufficient because we can rely on the ++ ordering provided by the RMW operations we use. */ ++ unsigned long d = atomic_fetch_add_relaxed (&sem->data, ++ 1UL << SEM_NWAITERS_SHIFT); ++ ++ pthread_cleanup_push (__sem_wait_cleanup, sem); ++ ++ /* Wait for a token to be available. Retry until we can grab one. */ ++ for (;;) ++ { ++ /* If there is no token available, sleep until there is. */ ++ if ((d & SEM_VALUE_MASK) == 0) ++ { ++ err = do_futex_wait (sem, abstime); ++ /* A futex return value of 0 or EAGAIN is due to a real or spurious ++ wake-up, or due to a change in the number of tokens. We retry in ++ these cases. ++ If we timed out, forward this to the caller. ++ EINTR could be either due to being interrupted by a signal, or ++ due to a spurious wake-up. Thus, we cannot distinguish between ++ both, and are not allowed to return EINTR to the caller but have ++ to retry; this is because we may not have been interrupted by a ++ signal. However, if we assume that only signals cause a futex ++ return of EINTR, we forward EINTR to the caller. ++ ++ Retrying on EINTR is technically always allowed because to ++ reliably interrupt sem_wait with a signal, the signal handler ++ must call sem_post (which is AS-Safe). In executions where the ++ signal handler does not do that, the implementation can correctly ++ claim that sem_wait hadn't actually started to execute yet, and ++ thus the signal never actually interrupted sem_wait. We make no ++ timing guarantees, so the program can never observe that sem_wait ++ actually did start to execute. Thus, in a correct program, we ++ can expect a signal that wanted to interrupt the sem_wait to have ++ provided a token, and can just try to grab this token if ++ futex_wait returns EINTR. */ ++ if (err == ETIMEDOUT || ++ (err == EINTR && sem_assume_only_signals_cause_futex_EINTR)) ++ { ++ __set_errno (err); ++ err = -1; ++ /* Stop being registered as a waiter. */ ++ atomic_fetch_add_relaxed (&sem->data, ++ -(1UL << SEM_NWAITERS_SHIFT)); ++ break; ++ } ++ /* Relaxed MO is sufficient; see below. */ ++ d = atomic_load_relaxed (&sem->data); ++ } ++ else ++ { ++ /* Try to grab both a token and stop being a waiter. We need ++ acquire MO so this synchronizes with all token providers (i.e., ++ the RMW operation we read from or all those before it in ++ modification order; also see sem_post). On the failure path, ++ relaxed MO is sufficient because we only eventually need the ++ up-to-date value; the futex_wait or the CAS perform the real ++ work. */ ++ if (atomic_compare_exchange_weak_acquire (&sem->data, ++ &d, d - 1 - (1UL << SEM_NWAITERS_SHIFT))) ++ { ++ err = 0; ++ break; ++ } ++ } ++ } ++ ++ pthread_cleanup_pop (0); ++#else ++ /* The main difference to the 64b-atomics implementation is that we need to ++ access value and nwaiters in separate steps, and that the nwaiters bit ++ in the value can temporarily not be set even if nwaiters is nonzero. ++ We work around incorrectly unsetting the nwaiters bit by letting sem_wait ++ set the bit again and waking the number of waiters that could grab a ++ token. There are two additional properties we need to ensure: ++ (1) We make sure that whenever unsetting the bit, we see the increment of ++ nwaiters by the other thread that set the bit. IOW, we will notice if ++ we make a mistake. ++ (2) When setting the nwaiters bit, we make sure that we see the unsetting ++ of the bit by another waiter that happened before us. This avoids having ++ to blindly set the bit whenever we need to block on it. We set/unset ++ the bit while having incremented nwaiters (i.e., are a registered ++ waiter), and the problematic case only happens when one waiter indeed ++ followed another (i.e., nwaiters was never larger than 1); thus, this ++ works similarly as with a critical section using nwaiters (see the MOs ++ and related comments below). ++ ++ An alternative approach would be to unset the bit after decrementing ++ nwaiters; however, that would result in needing Dekker-like ++ synchronization and thus full memory barriers. We also would not be able ++ to prevent misspeculation, so this alternative scheme does not seem ++ beneficial. */ ++ unsigned int v; ++ ++ /* Add a waiter. We need acquire MO so this synchronizes with the release ++ MO we use when decrementing nwaiters below; it ensures that if another ++ waiter unset the bit before us, we see that and set it again. Also see ++ property (2) above. */ ++ atomic_fetch_add_acquire (&sem->nwaiters, 1); ++ ++ pthread_cleanup_push (__sem_wait_cleanup, sem); ++ ++ /* Wait for a token to be available. Retry until we can grab one. */ ++ /* We do not need any ordering wrt. to this load's reads-from, so relaxed ++ MO is sufficient. The acquire MO above ensures that in the problematic ++ case, we do see the unsetting of the bit by another waiter. */ ++ v = atomic_load_relaxed (&sem->value); ++ do ++ { ++ do ++ { ++ /* We are about to block, so make sure that the nwaiters bit is ++ set. We need release MO on the CAS to ensure that when another ++ waiter unsets the nwaiters bit, it will also observe that we ++ incremented nwaiters in the meantime (also see the unsetting of ++ the bit below). Relaxed MO on CAS failure is sufficient (see ++ above). */ ++ do ++ { ++ if ((v & SEM_NWAITERS_MASK) != 0) ++ break; ++ } ++ while (!atomic_compare_exchange_weak_release (&sem->value, ++ &v, v | SEM_NWAITERS_MASK)); ++ /* If there is no token, wait. */ ++ if ((v >> SEM_VALUE_SHIFT) == 0) ++ { ++ /* See __HAVE_64B_ATOMICS variant. */ ++ err = do_futex_wait(sem, abstime); ++ if (err == ETIMEDOUT || ++ (err == EINTR && sem_assume_only_signals_cause_futex_EINTR)) ++ { ++ __set_errno (err); ++ err = -1; ++ goto error; ++ } ++ err = 0; ++ /* We blocked, so there might be a token now. Relaxed MO is ++ sufficient (see above). */ ++ v = atomic_load_relaxed (&sem->value); ++ } ++ } ++ /* If there is no token, we must not try to grab one. */ ++ while ((v >> SEM_VALUE_SHIFT) == 0); ++ } ++ /* Try to grab a token. We need acquire MO so this synchronizes with ++ all token providers (i.e., the RMW operation we read from or all those ++ before it in modification order; also see sem_post). */ ++ while (!atomic_compare_exchange_weak_acquire (&sem->value, ++ &v, v - (1 << SEM_VALUE_SHIFT))); ++ ++error: ++ pthread_cleanup_pop (0); ++ ++ __sem_wait_32_finish (sem); ++#endif ++ ++ return err; ++} ++ ++/* Stop being a registered waiter (non-64b-atomics code only). */ ++#if !__HAVE_64B_ATOMICS ++static void ++__sem_wait_32_finish (struct new_sem *sem) ++{ ++ /* The nwaiters bit is still set, try to unset it now if this seems ++ necessary. We do this before decrementing nwaiters so that the unsetting ++ is visible to other waiters entering after us. Relaxed MO is sufficient ++ because we are just speculating here; a stronger MO would not prevent ++ misspeculation. */ ++ unsigned int wguess = atomic_load_relaxed (&sem->nwaiters); ++ if (wguess == 1) ++ /* We might be the last waiter, so unset. This needs acquire MO so that ++ it syncronizes with the release MO when setting the bit above; if we ++ overwrite someone else that set the bit, we'll read in the following ++ decrement of nwaiters at least from that release sequence, so we'll ++ see if the other waiter is still active or if another writer entered ++ in the meantime (i.e., using the check below). */ ++ atomic_fetch_and_acquire (&sem->value, ~SEM_NWAITERS_MASK); ++ ++ /* Now stop being a waiter, and see whether our guess was correct. ++ This needs release MO so that it synchronizes with the acquire MO when ++ a waiter increments nwaiters; this makes sure that newer writers see that ++ we reset the waiters_present bit. */ ++ unsigned int wfinal = atomic_fetch_add_release (&sem->nwaiters, -1); ++ if (wfinal > 1 && wguess == 1) ++ { ++ /* We guessed wrong, and so need to clean up after the mistake and ++ unblock any waiters that could have not been woken. There is no ++ additional ordering that we need to set up, so relaxed MO is ++ sufficient. */ ++ unsigned int v = atomic_fetch_or_relaxed (&sem->value, ++ SEM_NWAITERS_MASK); ++ /* If there are available tokens, then wake as many waiters. If there ++ aren't any, then there is no need to wake anyone because there is ++ none to grab for another waiter. If tokens become available ++ subsequently, then the respective sem_post calls will do the wake-up ++ due to us having set the nwaiters bit again. */ ++ v >>= SEM_VALUE_SHIFT; ++ if (v > 0) ++ futex_wake (&sem->value, v, sem->private); ++ } ++} ++#endif +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/structsem.sym +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/structsem.sym ++++ /dev/null +@@ -1,12 +0,0 @@ +-#include +-#include +-#include +-#include +-#include "internaltypes.h" +- +--- +- +-VALUE offsetof (struct new_sem, value) +-PRIVATE offsetof (struct new_sem, private) +-NWAITERS offsetof (struct new_sem, nwaiters) +-SEM_VALUE_MAX SEM_VALUE_MAX +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S ++++ /dev/null +@@ -1,75 +0,0 @@ +-/* Copyright (C) 2002,2003,2005,2007,2008,2011 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2002. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +-#include +- +- +- .text +- +- .globl sem_post +- .type sem_post,@function +- .align 16 +-sem_post: +-#if VALUE == 0 +- movl (%rdi), %eax +-#else +- movl VALUE(%rdi), %eax +-#endif +-0: cmpl $SEM_VALUE_MAX, %eax +- je 3f +- leal 1(%rax), %esi +- LOCK +-#if VALUE == 0 +- cmpxchgl %esi, (%rdi) +-#else +- cmpxchgl %esi, VALUE(%rdi) +-#endif +- jnz 0b +- +- LP_OP(cmp) $0, NWAITERS(%rdi) +- je 2f +- +- movl $SYS_futex, %eax +- movl $FUTEX_WAKE, %esi +- orl PRIVATE(%rdi), %esi +- movl $1, %edx +- syscall +- +- testq %rax, %rax +- js 1f +- +-2: xorl %eax, %eax +- retq +- +-1: +- movl $EINVAL, %eax +- jmp 4f +- +-3: +- movl $EOVERFLOW, %eax +- +-4: +- movq errno@gottpoff(%rip), %rdx +- movl %eax, %fs:(%rdx) +- orl $-1, %eax +- retq +- .size sem_post,.-sem_post +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S ++++ /dev/null +@@ -1,380 +0,0 @@ +-/* Copyright (C) 2002,2003,2005,2007,2009,2010,2011 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2002. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +-#include +-#include +- +- .text +- +- .globl sem_timedwait +- .type sem_timedwait,@function +- .align 16 +-sem_timedwait: +-.LSTARTCODE: +- cfi_startproc +-#ifdef SHARED +- cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect, +- DW.ref.__gcc_personality_v0) +- cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART) +-#else +- cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0) +- cfi_lsda(DW_EH_PE_udata4, .LexceptSTART) +-#endif +-#if VALUE == 0 +- movl (%rdi), %eax +-#else +- movl VALUE(%rdi), %eax +-#endif +-2: testl %eax, %eax +- je 1f +- +- leaq -1(%rax), %rdx +- LOCK +-#if VALUE == 0 +- cmpxchgl %edx, (%rdi) +-#else +- cmpxchgl %edx, VALUE(%rdi) +-#endif +- jne 2b +- +- xorl %eax, %eax +- retq +- +- /* Check whether the timeout value is valid. */ +-1: cmpq $1000000000, 8(%rsi) +- jae 6f +- +-#ifndef __ASSUME_FUTEX_CLOCK_REALTIME +-# ifdef PIC +- cmpl $0, __have_futex_clock_realtime(%rip) +-# else +- cmpl $0, __have_futex_clock_realtime +-# endif +- je .Lreltmo +-#endif +- +- cmpq $0, (%rsi) +- js 16f +- +- /* This push is only needed to store the sem_t pointer for the +- exception handler. */ +- pushq %rdi +- cfi_adjust_cfa_offset(8) +- +- movq %rsi, %r10 +- +- LOCK +- LP_OP(add) $1, NWAITERS(%rdi) +- +-.LcleanupSTART: +-13: call __pthread_enable_asynccancel +- movl %eax, %r8d +- +-#if VALUE != 0 +- leaq VALUE(%rdi), %rdi +-#endif +- movl $0xffffffff, %r9d +- movl $FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, %esi +- orl PRIVATE(%rdi), %esi +- movl $SYS_futex, %eax +- xorl %edx, %edx +- syscall +- movq %rax, %r9 +-#if VALUE != 0 +- leaq -VALUE(%rdi), %rdi +-#endif +- +- xchgq %r8, %rdi +- call __pthread_disable_asynccancel +-.LcleanupEND: +- movq %r8, %rdi +- +- testq %r9, %r9 +- je 11f +- cmpq $-EWOULDBLOCK, %r9 +- jne 3f +- +-11: +-#if VALUE == 0 +- movl (%rdi), %eax +-#else +- movl VALUE(%rdi), %eax +-#endif +-14: testl %eax, %eax +- je 13b +- +- leaq -1(%rax), %rcx +- LOCK +-#if VALUE == 0 +- cmpxchgl %ecx, (%rdi) +-#else +- cmpxchgl %ecx, VALUE(%rdi) +-#endif +- jne 14b +- +- xorl %eax, %eax +- +-15: LOCK +- LP_OP(sub) $1, NWAITERS(%rdi) +- +- leaq 8(%rsp), %rsp +- cfi_adjust_cfa_offset(-8) +- retq +- +- cfi_adjust_cfa_offset(8) +-3: negq %r9 +- movq errno@gottpoff(%rip), %rdx +- movl %r9d, %fs:(%rdx) +- +- orl $-1, %eax +- jmp 15b +- +- cfi_adjust_cfa_offset(-8) +-6: +- movq errno@gottpoff(%rip), %rdx +- movl $EINVAL, %fs:(%rdx) +- +- orl $-1, %eax +- +- retq +- +-16: +- movq errno@gottpoff(%rip), %rdx +- movl $ETIMEDOUT, %fs:(%rdx) +- +- orl $-1, %eax +- +- retq +- +-#ifndef __ASSUME_FUTEX_CLOCK_REALTIME +-.Lreltmo: +- pushq %r12 +- cfi_adjust_cfa_offset(8) +- cfi_rel_offset(%r12, 0) +- pushq %r13 +- cfi_adjust_cfa_offset(8) +- cfi_rel_offset(%r13, 0) +- pushq %r14 +- cfi_adjust_cfa_offset(8) +- cfi_rel_offset(%r14, 0) +- +-#ifdef __ASSUME_FUTEX_CLOCK_REALTIME +-# define STACKFRAME 8 +-#else +-# define STACKFRAME 24 +-#endif +- subq $STACKFRAME, %rsp +- cfi_adjust_cfa_offset(STACKFRAME) +- +- movq %rdi, %r12 +- movq %rsi, %r13 +- +- LOCK +- LP_OP(add) $1, NWAITERS(%r12) +- +-7: xorl %esi, %esi +- movq %rsp,%rdi +- /* This call works because we directly jump to a system call entry +- which preserves all the registers. */ +- call JUMPTARGET(__gettimeofday) +- +- /* Compute relative timeout. */ +- movq 8(%rsp), %rax +- movl $1000, %edi +- mul %rdi /* Milli seconds to nano seconds. */ +- movq (%r13), %rdi +- movq 8(%r13), %rsi +- subq (%rsp), %rdi +- subq %rax, %rsi +- jns 5f +- addq $1000000000, %rsi +- decq %rdi +-5: testq %rdi, %rdi +- movl $ETIMEDOUT, %r14d +- js 36f /* Time is already up. */ +- +- movq %rdi, (%rsp) /* Store relative timeout. */ +- movq %rsi, 8(%rsp) +- +-.LcleanupSTART2: +- call __pthread_enable_asynccancel +- movl %eax, 16(%rsp) +- +- movq %rsp, %r10 +-# if VALUE == 0 +- movq %r12, %rdi +-# else +- leaq VALUE(%r12), %rdi +-# endif +-# if FUTEX_WAIT == 0 +- movl PRIVATE(%rdi), %esi +-# else +- movl $FUTEX_WAIT, %esi +- orl PRIVATE(%rdi), %esi +-# endif +- movl $SYS_futex, %eax +- xorl %edx, %edx +- syscall +- movq %rax, %r14 +- +- movl 16(%rsp), %edi +- call __pthread_disable_asynccancel +-.LcleanupEND2: +- +- testq %r14, %r14 +- je 9f +- cmpq $-EWOULDBLOCK, %r14 +- jne 33f +- +-9: +-# if VALUE == 0 +- movl (%r12), %eax +-# else +- movl VALUE(%r12), %eax +-# endif +-8: testl %eax, %eax +- je 7b +- +- leaq -1(%rax), %rcx +- LOCK +-# if VALUE == 0 +- cmpxchgl %ecx, (%r12) +-# else +- cmpxchgl %ecx, VALUE(%r12) +-# endif +- jne 8b +- +- xorl %eax, %eax +- +-45: LOCK +- LP_OP(sub) $1, NWAITERS(%r12) +- +- addq $STACKFRAME, %rsp +- cfi_adjust_cfa_offset(-STACKFRAME) +- popq %r14 +- cfi_adjust_cfa_offset(-8) +- cfi_restore(%r14) +- popq %r13 +- cfi_adjust_cfa_offset(-8) +- cfi_restore(%r13) +- popq %r12 +- cfi_adjust_cfa_offset(-8) +- cfi_restore(%r12) +- retq +- +- cfi_adjust_cfa_offset(STACKFRAME + 3 * 8) +- cfi_rel_offset(%r12, STACKFRAME + 2 * 8) +- cfi_rel_offset(%r13, STACKFRAME + 1 * 8) +- cfi_rel_offset(%r14, STACKFRAME) +-33: negq %r14 +-36: +- movq errno@gottpoff(%rip), %rdx +- movl %r14d, %fs:(%rdx) +- +- orl $-1, %eax +- jmp 45b +-#endif +- cfi_endproc +- .size sem_timedwait,.-sem_timedwait +- +- +- .type sem_timedwait_cleanup,@function +-sem_timedwait_cleanup: +- cfi_startproc +- cfi_adjust_cfa_offset(8) +- +- movq (%rsp), %rdi +- LOCK +- LP_OP(sub) $1, NWAITERS(%rdi) +- movq %rax, %rdi +-.LcallUR: +- call _Unwind_Resume@PLT +- hlt +-.LENDCODE: +- cfi_endproc +- .size sem_timedwait_cleanup,.-sem_timedwait_cleanup +- +- +-#ifndef __ASSUME_FUTEX_CLOCK_REALTIME +- .type sem_timedwait_cleanup2,@function +-sem_timedwait_cleanup2: +- cfi_startproc +- cfi_adjust_cfa_offset(STACKFRAME + 3 * 8) +- cfi_rel_offset(%r12, STACKFRAME + 2 * 8) +- cfi_rel_offset(%r13, STACKFRAME + 1 * 8) +- cfi_rel_offset(%r14, STACKFRAME) +- +- LOCK +- LP_OP(sub) $1, NWAITERS(%r12) +- movq %rax, %rdi +- movq STACKFRAME(%rsp), %r14 +- movq STACKFRAME+8(%rsp), %r13 +- movq STACKFRAME+16(%rsp), %r12 +-.LcallUR2: +- call _Unwind_Resume@PLT +- hlt +-.LENDCODE2: +- cfi_endproc +- .size sem_timedwait_cleanup2,.-sem_timedwait_cleanup2 +-#endif +- +- +- .section .gcc_except_table,"a",@progbits +-.LexceptSTART: +- .byte DW_EH_PE_omit # @LPStart format +- .byte DW_EH_PE_omit # @TType format +- .byte DW_EH_PE_uleb128 # call-site format +- .uleb128 .Lcstend-.Lcstbegin +-.Lcstbegin: +- .uleb128 .LcleanupSTART-.LSTARTCODE +- .uleb128 .LcleanupEND-.LcleanupSTART +- .uleb128 sem_timedwait_cleanup-.LSTARTCODE +- .uleb128 0 +-#ifndef __ASSUME_FUTEX_CLOCK_REALTIME +- .uleb128 .LcleanupSTART2-.LSTARTCODE +- .uleb128 .LcleanupEND2-.LcleanupSTART2 +- .uleb128 sem_timedwait_cleanup2-.LSTARTCODE +- .uleb128 0 +-#endif +- .uleb128 .LcallUR-.LSTARTCODE +- .uleb128 .LENDCODE-.LcallUR +- .uleb128 0 +- .uleb128 0 +-#ifndef __ASSUME_FUTEX_CLOCK_REALTIME +- .uleb128 .LcallUR2-.LSTARTCODE +- .uleb128 .LENDCODE2-.LcallUR2 +- .uleb128 0 +- .uleb128 0 +-#endif +-.Lcstend: +- +- +-#ifdef SHARED +- .hidden DW.ref.__gcc_personality_v0 +- .weak DW.ref.__gcc_personality_v0 +- .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits +- .align LP_SIZE +- .type DW.ref.__gcc_personality_v0, @object +- .size DW.ref.__gcc_personality_v0, LP_SIZE +-DW.ref.__gcc_personality_v0: +- ASM_ADDR __gcc_personality_v0 +-#endif +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S ++++ /dev/null +@@ -1,47 +0,0 @@ +-/* Copyright (C) 2002, 2003, 2005, 2007, 2011 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2002. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +- +- .text +- +- .globl sem_trywait +- .type sem_trywait,@function +- .align 16 +-sem_trywait: +- movl (%rdi), %eax +-2: testl %eax, %eax +- jz 1f +- +- leal -1(%rax), %edx +- LOCK +- cmpxchgl %edx, (%rdi) +- jne 2b +- +- xorl %eax, %eax +- retq +- +-1: +- movq errno@gottpoff(%rip), %rdx +- movl $EAGAIN, %fs:(%rdx) +- orl $-1, %eax +- retq +- .size sem_trywait,.-sem_trywait +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S ++++ /dev/null +@@ -1,176 +0,0 @@ +-/* Copyright (C) 2002, 2003, 2005, 2007, 2009, 2011 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2002. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +-#include +- +- +- .text +- +- .globl sem_wait +- .type sem_wait,@function +- .align 16 +-sem_wait: +-.LSTARTCODE: +- cfi_startproc +-#ifdef SHARED +- cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect, +- DW.ref.__gcc_personality_v0) +- cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART) +-#else +- cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0) +- cfi_lsda(DW_EH_PE_udata4, .LexceptSTART) +-#endif +- +-#if VALUE == 0 +- movl (%rdi), %eax +-#else +- movl VALUE(%rdi), %eax +-#endif +-2: testl %eax, %eax +- je 1f +- +- leal -1(%rax), %edx +- LOCK +-#if VALUE == 0 +- cmpxchgl %edx, (%rdi) +-#else +- cmpxchgl %edx, VALUE(%rdi) +-#endif +- jne 2b +- +- xorl %eax, %eax +- retq +- +- /* This push is only needed to store the sem_t pointer for the +- exception handler. */ +-1: pushq %rdi +- cfi_adjust_cfa_offset(8) +- +- LOCK +- LP_OP(add) $1, NWAITERS(%rdi) +- +-.LcleanupSTART: +-6: call __pthread_enable_asynccancel +- movl %eax, %r8d +- +- xorq %r10, %r10 +- movl $SYS_futex, %eax +-#if FUTEX_WAIT == 0 +- movl PRIVATE(%rdi), %esi +-#else +- movl $FUTEX_WAIT, %esi +- orl PRIVATE(%rdi), %esi +-#endif +- xorl %edx, %edx +- syscall +- movq %rax, %rcx +- +- xchgq %r8, %rdi +- call __pthread_disable_asynccancel +-.LcleanupEND: +- movq %r8, %rdi +- +- testq %rcx, %rcx +- je 3f +- cmpq $-EWOULDBLOCK, %rcx +- jne 4f +- +-3: +-#if VALUE == 0 +- movl (%rdi), %eax +-#else +- movl VALUE(%rdi), %eax +-#endif +-5: testl %eax, %eax +- je 6b +- +- leal -1(%rax), %edx +- LOCK +-#if VALUE == 0 +- cmpxchgl %edx, (%rdi) +-#else +- cmpxchgl %edx, VALUE(%rdi) +-#endif +- jne 5b +- +- xorl %eax, %eax +- +-9: LOCK +- LP_OP(sub) $1, NWAITERS(%rdi) +- +- leaq 8(%rsp), %rsp +- cfi_adjust_cfa_offset(-8) +- +- retq +- +- cfi_adjust_cfa_offset(8) +-4: negq %rcx +- movq errno@gottpoff(%rip), %rdx +- movl %ecx, %fs:(%rdx) +- orl $-1, %eax +- +- jmp 9b +- .size sem_wait,.-sem_wait +- +- +- .type sem_wait_cleanup,@function +-sem_wait_cleanup: +- movq (%rsp), %rdi +- LOCK +- LP_OP(sub) $1, NWAITERS(%rdi) +- movq %rax, %rdi +-.LcallUR: +- call _Unwind_Resume@PLT +- hlt +-.LENDCODE: +- cfi_endproc +- .size sem_wait_cleanup,.-sem_wait_cleanup +- +- +- .section .gcc_except_table,"a",@progbits +-.LexceptSTART: +- .byte DW_EH_PE_omit # @LPStart format +- .byte DW_EH_PE_omit # @TType format +- .byte DW_EH_PE_uleb128 # call-site format +- .uleb128 .Lcstend-.Lcstbegin +-.Lcstbegin: +- .uleb128 .LcleanupSTART-.LSTARTCODE +- .uleb128 .LcleanupEND-.LcleanupSTART +- .uleb128 sem_wait_cleanup-.LSTARTCODE +- .uleb128 0 +- .uleb128 .LcallUR-.LSTARTCODE +- .uleb128 .LENDCODE-.LcallUR +- .uleb128 0 +- .uleb128 0 +-.Lcstend: +- +- +-#ifdef SHARED +- .hidden DW.ref.__gcc_personality_v0 +- .weak DW.ref.__gcc_personality_v0 +- .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits +- .align LP_SIZE +- .type DW.ref.__gcc_personality_v0, @object +- .size DW.ref.__gcc_personality_v0, LP_SIZE +-DW.ref.__gcc_personality_v0: +- ASM_ADDR __gcc_personality_v0 +-#endif +Index: glibc-2.17-c758a686/ports/sysdeps/unix/sysv/linux/alpha/nptl/sem_post.c +=================================================================== +--- glibc-2.17-c758a686.orig/ports/sysdeps/unix/sysv/linux/alpha/nptl/sem_post.c ++++ /dev/null +@@ -1,5 +0,0 @@ +-/* ??? This is an ass-backwards way to do this. We should simply define +- the acquire/release semantics of atomic_exchange_and_add. And even if +- we don't do this, we should be using atomic_full_barrier or otherwise. */ +-#define __lll_rel_instr "mb" +-#include +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/sh/sem_post.S +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/sh/sem_post.S ++++ /dev/null +@@ -1,111 +0,0 @@ +-/* Copyright (C) 2003-2012 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +-#include +-#include "lowlevel-atomic.h" +- +- +- .text +- +- .globl __new_sem_post +- .type __new_sem_post,@function +- .align 5 +- cfi_startproc +-__new_sem_post: +- mov.l @(VALUE,r4), r2 +-0: +- mov.l .Lmax, r1 +- cmp/eq r1, r2 +- bt/s 3f +- mov r2, r3 +- mov r3, r5 +- add #1, r5 +- CMPXCHG (r3, @(VALUE,r4), r5, r2) +- bf 0b +- mov.l @(NWAITERS,r4), r2 +- tst r2, r2 +- bt 2f +- mov #FUTEX_WAKE, r5 +- mov.l @(PRIVATE,r4), r1 +- or r1, r5 +- mov #1, r6 +- mov #0, r7 +- mov #SYS_futex, r3 +- extu.b r3, r3 +- trapa #0x14 +- SYSCALL_INST_PAD +- +- cmp/pz r0 +- bf 1f +-2: +- rts +- mov #0, r0 +- +-1: +- bra 4f +- mov #EINVAL, r2 +- +-3: +- mov #EOVERFLOW, r2 +-4: +- mov.l r12, @-r15 +- cfi_adjust_cfa_offset (4) +- cfi_rel_offset (r12, 0) +- mov.l r8, @-r15 +- cfi_adjust_cfa_offset (4) +- cfi_rel_offset (r8, 0) +- sts.l pr, @-r15 +- cfi_adjust_cfa_offset (4) +- cfi_rel_offset (pr, 0) +- mova .Lgot3, r0 +- mov.l .Lgot3, r12 +- add r0, r12 +- +- mov.l .Lerrno3, r0 +- stc gbr, r1 +- mov.l @(r0, r12), r0 +- bra .Lexit +- add r1, r0 +- .align 2 +-.Lerrno3: +- .long errno@GOTTPOFF +-.Lexit: +- mov.l r2, @r0 +- lds.l @r15+, pr +- cfi_adjust_cfa_offset (-4) +- cfi_restore (pr) +- mov.l @r15+, r8 +- cfi_adjust_cfa_offset (-4) +- cfi_restore (r8) +- mov.l @r15+, r12 +- cfi_adjust_cfa_offset (-4) +- cfi_restore (r12) +- rts +- mov #-1, r0 +- cfi_endproc +- +- .align 2 +-.Lmax: +- .long SEM_VALUE_MAX +-.Lgot3: +- .long _GLOBAL_OFFSET_TABLE_ +- .size __new_sem_post,.-__new_sem_post +- versioned_symbol(libpthread, __new_sem_post, sem_post, GLIBC_2_1) +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/sh/sem_timedwait.S +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/sh/sem_timedwait.S ++++ /dev/null +@@ -1,281 +0,0 @@ +-/* Copyright (C) 2003-2012 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include "lowlevel-atomic.h" +- +- +-#if VALUE != 0 +-# error "code needs to be rewritten for VALUE != 0" +-#endif +- +- .text +- +- .globl sem_timedwait +- .type sem_timedwait,@function +- .align 5 +- cfi_startproc +-sem_timedwait: +-.LSTARTCODE: +-#ifdef SHARED +- cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect, +- DW.ref.__gcc_personality_v0) +- cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART) +-#else +- cfi_personality(DW_EH_PE_absptr, __gcc_personality_v0) +- cfi_lsda(DW_EH_PE_absptr, .LexceptSTART) +-#endif +- mov.l @r4, r0 +-2: +- tst r0, r0 +- bt 1f +- mov r0, r3 +- mov r0, r6 +- add #-1, r3 +- CMPXCHG (r6, @r4, r3, r2) +- bf/s 2b +- mov r2, r0 +- rts +- mov #0, r0 +- +-1: +- /* Check whether the timeout value is valid. */ +- mov.l r8, @-r15 +- cfi_adjust_cfa_offset (4) +- cfi_rel_offset (r8, 0) +- mov.l r9, @-r15 +- cfi_adjust_cfa_offset (4) +- cfi_rel_offset (r9, 0) +- mov.l r10, @-r15 +- cfi_adjust_cfa_offset (4) +- cfi_rel_offset (r10, 0) +- mov.l r12, @-r15 +- cfi_adjust_cfa_offset (4) +- cfi_rel_offset (r12, 0) +- sts.l pr, @-r15 +- cfi_adjust_cfa_offset (4) +- cfi_rel_offset (pr, 0) +- add #-8, r15 +- cfi_adjust_cfa_offset (8) +- +- mov r4, r8 +- mov r5, r9 +- +- /* Check for invalid nanosecond field. */ +- mov.l @(4,r9), r0 +- mov.l .L1g, r1 +- cmp/hs r1, r0 +- bt/s .Lerrno_exit +- mov #EINVAL, r10 +- INC (@(NWAITERS,r8),r2) +- +-7: +- /* Compute relative timeout. */ +- mov r15, r4 +- mov #0, r5 +- mov #__NR_gettimeofday, r3 +- trapa #0x12 +- SYSCALL_INST_PAD +- +- mov.l @(4,r15), r0 +- mov.w .L1k, r1 +- dmulu.l r0, r1 /* Milli seconds to nano seconds. */ +- mov.l @r9, r2 +- mov.l @(4,r9), r3 +- mov.l @r15, r0 +- sts macl, r1 +- sub r0, r2 +- clrt +- subc r1, r3 +- bf 5f +- mov.l .L1g, r1 +- add r1, r3 +- add #-1, r2 +-5: +- cmp/pz r2 +- bf/s 6f /* Time is already up. */ +- mov #ETIMEDOUT, r0 +- +- /* Store relative timeout. */ +- mov.l r2, @r15 +- mov.l r3, @(4,r15) +- +-.LcleanupSTART: +- mov.l .Lenable0, r1 +- bsrf r1 +- nop +-.Lenable0b: +- mov r0, r10 +- +- mov r8, r4 +-#if FUTEX_WAIT == 0 +- mov.l @(PRIVATE,r8), r5 +-#else +- mov.l @(PRIVATE,r8), r5 +- mov #FUTEX_WAIT, r0 +- or r0, r5 +-#endif +- mov #0, r6 +- mov r15, r7 +- mov #SYS_futex, r3 +- extu.b r3, r3 +- trapa #0x14 +- SYSCALL_INST_PAD +- +- mov.l .Ldisable0, r1 +- mov r10, r4 +- bsrf r1 +- mov r0, r10 +-.Ldisable0b: +- mov r10, r0 +-.LcleanupEND: +- +- tst r0, r0 +- bt 9f +- cmp/eq #-EWOULDBLOCK, r0 +- bf 3f +-9: +- mov.l @r8, r0 +-8: +- tst r0, r0 +- bt 7b +- +- mov r0, r3 +- mov r0, r4 +- add #-1, r3 +- CMPXCHG (r4, @r8, r3, r2) +- bf/s 8b +- mov r2, r0 +- +- DEC (@(NWAITERS,r8), r2) +- mov #0, r0 +- +-10: +- cfi_remember_state +- add #8, r15 +- cfi_adjust_cfa_offset (-8) +- lds.l @r15+, pr +- cfi_adjust_cfa_offset (-4) +- cfi_restore (pr) +- mov.l @r15+, r12 +- cfi_adjust_cfa_offset (-4) +- cfi_restore (r12) +- mov.l @r15+, r10 +- cfi_adjust_cfa_offset (-4) +- cfi_restore (r10) +- mov.l @r15+, r9 +- cfi_adjust_cfa_offset (-4) +- cfi_restore (r9) +- mov.l @r15+, r8 +- cfi_adjust_cfa_offset (-4) +- cfi_restore (r8) +- rts +- nop +- cfi_restore_state +- +-3: +- neg r0, r0 +-6: +- mov r0, r10 +- DEC (@(NWAITERS,r8), r2) +-.Lerrno_exit: +- mova .Lgot2, r0 +- mov.l .Lgot2, r12 +- add r0, r12 +- +- mov.l .Lerrno2, r0 +- stc gbr, r1 +- mov.l @(r0, r12), r0 +- bra .Lexit +- add r1, r0 +- .align 2 +-.Lerrno2: +- .long errno@GOTTPOFF +-.Lexit: +- mov.l r10, @r0 +- bra 10b +- mov #-1, r0 +- +-.L1k: +- .word 1000 +- .align 2 +-.L1g: +- .long 1000000000 +-.Lgot2: +- .long _GLOBAL_OFFSET_TABLE_ +-.Lenable0: +- .long __pthread_enable_asynccancel-.Lenable0b +-.Ldisable0: +- .long __pthread_disable_asynccancel-.Ldisable0b +- .size sem_timedwait,.-sem_timedwait +- +- .type sem_wait_cleanup,@function +-sem_wait_cleanup: +- DEC (@(NWAITERS,r8), r2) +-.LcallUR: +- mov.l .Lresume, r1 +-#ifdef PIC +- add r12, r1 +-#endif +- jsr @r1 +- nop +- sleep +- +- .align 2 +-.Lresume: +-#ifdef PIC +- .long _Unwind_Resume@GOTOFF +-#else +- .long _Unwind_Resume +-#endif +-.LENDCODE: +- cfi_endproc +- .size sem_wait_cleanup,.-sem_wait_cleanup +- +- +- .section .gcc_except_table,"a",@progbits +-.LexceptSTART: +- .byte DW_EH_PE_omit ! @LPStart format (omit) +- .byte DW_EH_PE_omit ! @TType format (omit) +- .byte DW_EH_PE_uleb128 ! call-site format +- .uleb128 .Lcstend-.Lcstbegin +-.Lcstbegin: +- .uleb128 .LcleanupSTART-.LSTARTCODE +- .uleb128 .LcleanupEND-.LcleanupSTART +- .uleb128 sem_wait_cleanup-.LSTARTCODE +- .uleb128 0 +- .uleb128 .LcallUR-.LSTARTCODE +- .uleb128 .LENDCODE-.LcallUR +- .uleb128 0 +- .uleb128 0 +-.Lcstend: +- +-#ifdef SHARED +- .hidden DW.ref.__gcc_personality_v0 +- .weak DW.ref.__gcc_personality_v0 +- .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits +- .align 4 +- .type DW.ref.__gcc_personality_v0, @object +- .size DW.ref.__gcc_personality_v0, 4 +-DW.ref.__gcc_personality_v0: +- .long __gcc_personality_v0 +-#endif +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/sh/sem_trywait.S +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/sh/sem_trywait.S ++++ /dev/null +@@ -1,102 +0,0 @@ +-/* Copyright (C) 2003-2012 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +-#include "lowlevel-atomic.h" +- +- +- .text +- +- .globl __new_sem_trywait +- .type __new_sem_trywait,@function +- .align 5 +- cfi_startproc +-__new_sem_trywait: +- mov.l r12, @-r15 +- cfi_adjust_cfa_offset (4) +- cfi_rel_offset (r12, 0) +- mov.l r8, @-r15 +- cfi_adjust_cfa_offset (4) +- cfi_rel_offset (r8, 0) +- sts.l pr, @-r15 +- cfi_adjust_cfa_offset (4) +- cfi_rel_offset (pr, 0) +- mov r4, r8 +- mov.l @r8, r0 +-2: +- tst r0, r0 +- bt 1f +- +- mov r0, r3 +- mov r0, r4 +- add #-1, r3 +- CMPXCHG (r4, @r8, r3, r2) +- bf/s 2b +- mov r2, r0 +- +- cfi_remember_state +- lds.l @r15+, pr +- cfi_adjust_cfa_offset (-4) +- cfi_restore (pr) +- mov.l @r15+, r8 +- cfi_adjust_cfa_offset (-4) +- cfi_restore (r8) +- mov.l @r15+, r12 +- cfi_adjust_cfa_offset (-4) +- cfi_restore (r12) +- rts +- mov #0, r0 +- cfi_restore_state +- +-1: +- mov #EAGAIN, r8 +- mova .Lgot1, r0 +- mov.l .Lgot1, r12 +- add r0, r12 +- +- mov.l .Lerrno1, r0 +- stc gbr, r1 +- mov.l @(r0, r12), r0 +- bra .Lexit +- add r1, r0 +- .align 2 +-.Lerrno1: +- .long errno@GOTTPOFF +-.Lexit: +- mov.l r8, @r0 +- lds.l @r15+, pr +- cfi_adjust_cfa_offset (-4) +- cfi_restore (pr) +- mov.l @r15+, r8 +- cfi_adjust_cfa_offset (-4) +- cfi_restore (r8) +- mov.l @r15+, r12 +- cfi_adjust_cfa_offset (-4) +- cfi_restore (r12) +- rts +- mov #-1, r0 +- +- cfi_endproc +- +- .align 2 +-.Lgot1: +- .long _GLOBAL_OFFSET_TABLE_ +- .size __new_sem_trywait,.-__new_sem_trywait +- versioned_symbol(libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1) +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S ++++ /dev/null +@@ -1,229 +0,0 @@ +-/* Copyright (C) 2003-2012 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include "lowlevel-atomic.h" +- +- +-#if VALUE != 0 +-# error "code needs to be rewritten for VALUE != 0" +-#endif +- +- .text +- +- .globl __new_sem_wait +- .type __new_sem_wait,@function +- .align 5 +- cfi_startproc +-__new_sem_wait: +-.LSTARTCODE: +-#ifdef SHARED +- cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect, +- DW.ref.__gcc_personality_v0) +- cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART) +-#else +- cfi_personality(DW_EH_PE_absptr, __gcc_personality_v0) +- cfi_lsda(DW_EH_PE_absptr, .LexceptSTART) +-#endif +- mov.l r8, @-r15 +- cfi_adjust_cfa_offset (4) +- cfi_rel_offset (r8, 0) +- mov.l r10, @-r15 +- cfi_adjust_cfa_offset (4) +- cfi_rel_offset (r10, 0) +- mov.l r12, @-r15 +- cfi_adjust_cfa_offset (4) +- cfi_rel_offset (r12, 0) +- sts.l pr, @-r15 +- cfi_adjust_cfa_offset (4) +- cfi_rel_offset (pr, 0) +- +- mov r4, r8 +- mov.l @r8, r0 +-2: +- tst r0, r0 +- bt 1f +- mov r0, r3 +- mov r0, r4 +- add #-1, r3 +- CMPXCHG (r4, @r8, r3, r2) +- bf/s 2b +- mov r2, r0 +-7: +- mov #0, r0 +-9: +- cfi_remember_state +- lds.l @r15+, pr +- cfi_adjust_cfa_offset (-4) +- cfi_restore (pr) +- mov.l @r15+, r12 +- cfi_adjust_cfa_offset (-4) +- cfi_restore (r12) +- mov.l @r15+, r10 +- cfi_adjust_cfa_offset (-4) +- cfi_restore (r10) +- rts +- mov.l @r15+, r8 +- /* Omit CFI for restore in delay slot. */ +- cfi_restore_state +- +-.Lafter_ret: +-1: +- INC (@(NWAITERS,r8),r2) +- +-.LcleanupSTART: +-6: +- mov.l .Lenable0, r1 +- bsrf r1 +- nop +-.Lenable0b: +- mov r0, r10 +- +- mov r8, r4 +-#if FUTEX_WAIT == 0 +- mov.l @(PRIVATE,r8), r5 +-#else +- mov.l @(PRIVATE,r8), r5 +- mov #FUTEX_WAIT, r0 +- or r0, r5 +-#endif +- mov #0, r6 +- mov #0, r7 +- mov #SYS_futex, r3 +- extu.b r3, r3 +- trapa #0x14 +- SYSCALL_INST_PAD +- +- mov.l .Ldisable0, r1 +- mov r10, r4 +- bsrf r1 +- mov r0, r10 +-.Ldisable0b: +- mov r10, r0 +-.LcleanupEND: +- +- tst r0, r0 +- bt 3f +- cmp/eq #-EWOULDBLOCK, r0 +- bf 4f +- +-3: +- mov.l @r8, r0 +-5: +- tst r0, r0 +- bt 6b +- +- mov r0, r3 +- mov r0, r4 +- add #-1, r3 +- CMPXCHG (r4, @r8, r3, r2) +- bf/s 5b +- mov r2, r0 +- +- DEC (@(NWAITERS,r8), r2) +- bra 7b +- nop +- +-4: +- neg r0, r0 +- mov r0, r4 +- DEC (@(NWAITERS,r8), r2) +- mov r4, r8 +- mova .Lgot0, r0 +- mov.l .Lgot0, r12 +- add r0, r12 +- +- mov.l .Lerrno0, r0 +- stc gbr, r1 +- mov.l @(r0, r12), r0 +- bra .Lexit +- add r1, r0 +- .align 2 +-.Lerrno0: +- .long errno@GOTTPOFF +-.Lexit: +- mov.l r8, @r0 +- bra 9b +- mov #-1, r0 +- +- .align 2 +-.Lgot0: +- .long _GLOBAL_OFFSET_TABLE_ +-.Lenable0: +- .long __pthread_enable_asynccancel-.Lenable0b +-.Ldisable0: +- .long __pthread_disable_asynccancel-.Ldisable0b +- .size __new_sem_wait,.-__new_sem_wait +- versioned_symbol(libpthread, __new_sem_wait, sem_wait, GLIBC_2_1) +- +- +- .type sem_wait_cleanup,@function +-sem_wait_cleanup: +- DEC (@(NWAITERS,r8), r2) +-.LcallUR: +- mov.l .Lresume, r1 +-#ifdef PIC +- add r12, r1 +-#endif +- jsr @r1 +- nop +- sleep +- +- .align 2 +-.Lresume: +-#ifdef PIC +- .long _Unwind_Resume@GOTOFF +-#else +- .long _Unwind_Resume +-#endif +-.LENDCODE: +- cfi_endproc +- .size sem_wait_cleanup,.-sem_wait_cleanup +- +- +- .section .gcc_except_table,"a",@progbits +-.LexceptSTART: +- .byte DW_EH_PE_omit ! @LPStart format (omit) +- .byte DW_EH_PE_omit ! @TType format (omit) +- .byte DW_EH_PE_uleb128 ! call-site format +- .uleb128 .Lcstend-.Lcstbegin +-.Lcstbegin: +- .uleb128 .LcleanupSTART-.LSTARTCODE +- .uleb128 .LcleanupEND-.LcleanupSTART +- .uleb128 sem_wait_cleanup-.LSTARTCODE +- .uleb128 0 +- .uleb128 .LcallUR-.LSTARTCODE +- .uleb128 .LENDCODE-.LcallUR +- .uleb128 0 +- .uleb128 0 +-.Lcstend: +- +-#ifdef SHARED +- .hidden DW.ref.__gcc_personality_v0 +- .weak DW.ref.__gcc_personality_v0 +- .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits +- .align 4 +- .type DW.ref.__gcc_personality_v0, @object +- .size DW.ref.__gcc_personality_v0, 4 +-DW.ref.__gcc_personality_v0: +- .long __gcc_personality_v0 +-#endif +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/Makefile +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/Makefile ++++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/Makefile +@@ -24,8 +24,7 @@ libpthread-sysdep_routines += pt-fork pt + + gen-as-const-headers += lowlevelcond.sym lowlevelrwlock.sym \ + lowlevelbarrier.sym unwindbuf.sym \ +- lowlevelrobustlock.sym pthread-pi-defines.sym \ +- structsem.sym ++ lowlevelrobustlock.sym pthread-pi-defines.sym + endif + + ifeq ($(subdir),posix) +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h ++++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h +@@ -225,17 +225,18 @@ LLL_STUB_UNWIND_INFO_END + + + #define lll_futex_wake(futex, nr, private) \ +- do { \ +- int __ignore; \ ++ ({ \ ++ int __status; \ + register __typeof (nr) _nr __asm ("edx") = (nr); \ + LIBC_PROBE (lll_futex_wake, 3, futex, nr, private); \ + __asm __volatile ("syscall" \ +- : "=a" (__ignore) \ ++ : "=a" (__status) \ + : "0" (SYS_futex), "D" (futex), \ + "S" (__lll_private_flag (FUTEX_WAKE, private)), \ + "d" (_nr) \ + : "memory", "cc", "r10", "r11", "cx"); \ +- } while (0) ++ __status; \ ++ }) + + + /* NB: in the lll_trylock macro we simply return the value in %eax +Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h +=================================================================== +--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h ++++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h +@@ -224,20 +224,21 @@ LLL_STUB_UNWIND_INFO_END + + + #define lll_futex_wake(futex, nr, private) \ +- do { \ +- int __ignore; \ ++ ({ \ ++ int __status; \ + register __typeof (nr) _nr asm ("edx") = (nr); \ + LIBC_PROBE (lll_futex_wake, 3, futex, nr, private); \ + __asm __volatile (LLL_EBX_LOAD \ + LLL_ENTER_KERNEL \ + LLL_EBX_LOAD \ +- : "=a" (__ignore) \ ++ : "=a" (__status) \ + : "0" (SYS_futex), LLL_EBX_REG (futex), \ + "c" (__lll_private_flag (FUTEX_WAKE, private)), \ + "d" (_nr), \ + "i" (0) /* phony, to align next arg's number */, \ + "i" (offsetof (tcbhead_t, sysinfo))); \ +- } while (0) ++ __status; \ ++ }) + + + /* NB: in the lll_trylock macro we simply return the value in %eax diff --git a/SOURCES/glibc-rh1028652.patch b/SOURCES/glibc-rh1028652.patch new file mode 100644 index 0000000..0717f71 --- /dev/null +++ b/SOURCES/glibc-rh1028652.patch @@ -0,0 +1,96 @@ +# +# Upstream power patch to increase MINSIGSTKSZ and SIGSTKSZ to +# account for the kernel signal frame size increase. +# +# commit f7c399cff5bd04ee9dc117fb6b0f39597dc047c6 +# Author: Alan Modra +# Date: Sat Aug 17 18:37:18 2013 +0930 +# +# PowerPC SIGSTKSZ +# http://sourceware.org/ml/libc-alpha/2013-08/msg00093.html +# +# This copies the sparc version of sigstack.h, which gives powerpc +# #define MINSIGSTKSZ 4096 +# #define SIGSTKSZ 16384 +# +# Before the VSX changes, struct rt_sigframe size was 1920 plus 128 for +# __SIGNAL_FRAMESIZE giving ppc64 exactly the default MINSIGSTKSZ of +# 2048. +# +# After VSX, ucontext increased by 256 bytes. Oops, we're over +# MINSIGSTKSZ, so powerpc has been using the wrong value for quite a +# while. Add another ucontext for TM and rt_sigframe is now at 3872, +# giving actual MINSIGSTKSZ of 4000. +# +# The glibc testcase that I was looking at was tst-cancel21, which +# allocates 2*SIGSTKSZ (not because the test is trying to be +# conservative, but because the test actually has nested signal stack +# frames). We blew the allocation by 48 bytes when using current +# mainline gcc to compile glibc (le ppc64). +# +# The required stack depth in _dl_lookup_symbol_x from the top of the +# next signal frame was 10944 bytes. I guess you'd want to add 288 to +# that, implying an actual SIGSTKSZ of 11232. +# +# * sysdeps/unix/sysv/linux/powerpc/bits/sigstack.h: New file. +# +diff --git glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/bits/sigstack.h glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/bits/sigstack.h +new file mode 100644 +index 0000000..33be9e8 +--- /dev/null ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/bits/sigstack.h +@@ -0,0 +1,54 @@ ++/* sigstack, sigaltstack definitions. ++ Copyright (C) 1998-2013 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _SIGNAL_H ++# error "Never include this file directly. Use instead" ++#endif ++ ++ ++/* Structure describing a signal stack (obsolete). */ ++struct sigstack ++ { ++ void *ss_sp; /* Signal stack pointer. */ ++ int ss_onstack; /* Nonzero if executing on this stack. */ ++ }; ++ ++ ++/* Possible values for `ss_flags.'. */ ++enum ++{ ++ SS_ONSTACK = 1, ++#define SS_ONSTACK SS_ONSTACK ++ SS_DISABLE ++#define SS_DISABLE SS_DISABLE ++}; ++ ++/* Minimum stack size for a signal handler. */ ++#define MINSIGSTKSZ 4096 ++ ++/* System default stack size. */ ++#define SIGSTKSZ 16384 ++ ++ ++/* Alternate, preferred interface. */ ++typedef struct sigaltstack ++ { ++ void *ss_sp; ++ int ss_flags; ++ size_t ss_size; ++ } stack_t; diff --git a/SOURCES/glibc-rh1032435.patch b/SOURCES/glibc-rh1032435.patch new file mode 100644 index 0000000..694bec2 --- /dev/null +++ b/SOURCES/glibc-rh1032435.patch @@ -0,0 +1,390 @@ +commit 977f4b31b7ca4a4e498c397f3fd70510694bbd86 +Author: Siddhesh Poyarekar +Date: Wed Oct 30 16:13:37 2013 +0530 + + Fix reads for sizes larger than INT_MAX in AF_INET lookup + + Currently for AF_INET lookups from the hosts file, buffer sizes larger + than INT_MAX silently overflow and may result in access beyond bounds + of a buffer. This happens when the number of results in an AF_INET + lookup in /etc/hosts are very large. + + There are two aspects to the problem. One problem is that the size + computed from the buffer size is stored into an int, which results in + overflow for large sizes. Additionally, even if this size was + expanded, the function used to read content into the buffer (fgets) + accepts only int sizes. As a result, the fix is to have a function + wrap around fgets that calls it multiple times with int sizes if + necessary. + +(The previous commit fixes upstream bug 16071.) + +commit ac60763eac3d43b7234dd21286ad3ec3f17957fc +Author: Andreas Schwab +Date: Mon Jun 23 10:24:45 2014 +0200 + + Don't ignore too long lines in nss_files (BZ #17079) + +commit e07aabba73ea62e7dfa0512507c92efb851fbdbe +Author: Florian Weimer +Date: Tue Sep 22 13:20:18 2015 +0200 + + Add test case for bug 18287 + +commit 90fa42a1d7b78de0d75f7e3af362275b2abe807f +Author: Florian Weimer +Date: Tue Sep 22 13:40:17 2015 +0200 + + Test in commit e07aabba73ea62e7dfa0512507c92efb851fbdbe is for bug 17079 + +diff -u b/nss/nss_files/files-XXX.c b/nss/nss_files/files-XXX.c +--- b/nss/nss_files/files-XXX.c ++++ b/nss/nss_files/files-XXX.c +@@ -179,8 +179,53 @@ + return NSS_STATUS_SUCCESS; + } + +-/* Parsing the database file into `struct STRUCTURE' data structures. */ + ++typedef enum ++{ ++ gcr_ok = 0, ++ gcr_error = -1, ++ gcr_overflow = -2 ++} get_contents_ret; ++ ++/* Hack around the fact that fgets only accepts int sizes. */ ++static get_contents_ret ++get_contents (char *linebuf, size_t len, FILE *stream) ++{ ++ size_t remaining_len = len; ++ char *curbuf = linebuf; ++ ++ do ++ { ++ int curlen = ((remaining_len > (size_t) INT_MAX) ? INT_MAX ++ : remaining_len); ++ ++ /* Terminate the line so that we can test for overflow. */ ++ ((unsigned char *) curbuf)[curlen - 1] = 0xff; ++ ++ char *p = fgets_unlocked (curbuf, curlen, stream); ++ ++ /* EOF or read error. */ ++ if (p == NULL) ++ return gcr_error; ++ ++ /* Done reading in the line. */ ++ if (((unsigned char *) curbuf)[curlen - 1] == 0xff) ++ return gcr_ok; ++ ++ /* Drop the terminating '\0'. */ ++ remaining_len -= curlen - 1; ++ curbuf += curlen - 1; ++ } ++ /* fgets copies one less than the input length. Our last iteration is of ++ REMAINING_LEN and once that is done, REMAINING_LEN is decremented by ++ REMAINING_LEN - 1, leaving the result as 1. */ ++ while (remaining_len > 1); ++ ++ /* This means that the current buffer was not large enough. */ ++ return gcr_overflow; ++} ++ ++/* Parsing the database file into `struct STRUCTURE' data structures. */ + static enum nss_status + internal_getent (struct STRUCTURE *result, + char *buffer, size_t buflen, int *errnop H_ERRNO_PROTO +@@ -188,7 +233,7 @@ + { + char *p; + struct parser_data *data = (void *) buffer; +- int linebuflen = buffer + buflen - data->linebuffer; ++ size_t linebuflen = buffer + buflen - data->linebuffer; + int parse_result; + + if (buflen < sizeof *data + 2) +@@ -200,17 +245,16 @@ + + do + { +- /* Terminate the line so that we can test for overflow. */ +- ((unsigned char *) data->linebuffer)[linebuflen - 1] = '\xff'; ++ get_contents_ret r = get_contents (data->linebuffer, linebuflen, stream); + +- p = fgets_unlocked (data->linebuffer, linebuflen, stream); +- if (p == NULL) ++ if (r == gcr_error) + { + /* End of file or read error. */ + H_ERRNO_SET (HOST_NOT_FOUND); + return NSS_STATUS_NOTFOUND; + } +- else if (((unsigned char *) data->linebuffer)[linebuflen - 1] != 0xff) ++ ++ if (r == gcr_overflow) + { + /* The line is too long. Give the user the opportunity to + enlarge the buffer. */ +@@ -219,7 +263,8 @@ + return NSS_STATUS_TRYAGAIN; + } + +- /* Skip leading blanks. */ ++ /* Everything OK. Now skip leading blanks. */ ++ p = data->linebuffer; + while (isspace (*p)) + ++p; + } + +diff a/nss/bug17079.c b/nss/bug17079.c +--- /dev/null ++++ b/nss/bug17079.c +@@ -0,0 +1,236 @@ ++/* Test for bug 17079: heap overflow in NSS with small buffers. ++ Copyright (C) 2015 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Check if two passwd structs contain the same data. */ ++static bool ++equal (const struct passwd *a, const struct passwd *b) ++{ ++ return strcmp (a->pw_name, b->pw_name) == 0 ++ && strcmp (a->pw_passwd, b->pw_passwd) == 0 ++ && a->pw_uid == b->pw_uid ++ && a->pw_gid == b->pw_gid ++ && strcmp (a->pw_gecos, b->pw_gecos) == 0 ++ && strcmp (a->pw_dir, b->pw_dir) == 0 ++ && strcmp (a->pw_shell, b->pw_shell) == 0; ++} ++ ++enum { MAX_TEST_ITEMS = 10 }; ++static struct passwd test_items[MAX_TEST_ITEMS]; ++static int test_count; ++ ++/* Initialize test_items and test_count above, with data from the ++ passwd database. */ ++static bool ++init_test_items (void) ++{ ++ setpwent (); ++ do ++ { ++ struct passwd *pwd = getpwent (); ++ if (pwd == NULL) ++ break; ++ struct passwd *target = test_items + test_count; ++ target->pw_name = strdup (pwd->pw_name); ++ target->pw_passwd = strdup (pwd->pw_passwd); ++ target->pw_uid = pwd->pw_uid; ++ target->pw_gid = pwd->pw_gid; ++ target->pw_gecos = strdup (pwd->pw_gecos); ++ target->pw_dir = strdup (pwd->pw_dir); ++ target->pw_shell = strdup (pwd->pw_shell); ++ } ++ while (++test_count < MAX_TEST_ITEMS); ++ endpwent (); ++ ++ /* Filter out those test items which cannot be looked up by name or ++ UID. */ ++ bool found = false; ++ for (int i = 0; i < test_count; ++i) ++ { ++ struct passwd *pwd1 = getpwnam (test_items[i].pw_name); ++ struct passwd *pwd2 = getpwuid (test_items[i].pw_uid); ++ if (pwd1 == NULL || !equal (pwd1, test_items + i) ++ || pwd2 == NULL || !equal (pwd2, test_items + i)) ++ test_items[i].pw_name = NULL; ++ else ++ found = true; ++ } ++ ++ if (!found) ++ puts ("error: no accounts found which can be looked up by name and UID."); ++ return found; ++} ++ ++/* Set to true if an error is encountered. */ ++static bool errors; ++ ++/* Return true if the padding has not been tampered with. */ ++static bool ++check_padding (char *buffer, size_t size, char pad) ++{ ++ char *end = buffer + size; ++ while (buffer < end) ++ { ++ if (*buffer != pad) ++ return false; ++ ++buffer; ++ } ++ return true; ++} ++ ++/* Test one buffer size and padding combination. */ ++static void ++test_one (const struct passwd *item, size_t buffer_size, ++ char pad, size_t padding_size) ++{ ++ char *buffer = malloc (buffer_size + padding_size); ++ if (buffer == NULL) ++ { ++ puts ("error: malloc failure"); ++ errors = true; ++ return; ++ } ++ ++ struct passwd pwd; ++ struct passwd *result; ++ int ret; ++ ++ /* Test getpwname_r. */ ++ memset (buffer, pad, buffer_size + padding_size); ++ pwd = (struct passwd) {}; ++ ret = getpwnam_r (item->pw_name, &pwd, buffer, buffer_size, &result); ++ if (!check_padding (buffer + buffer_size, padding_size, pad)) ++ { ++ printf ("error: padding change: " ++ "name \"%s\", buffer size %zu, padding size %zu, pad 0x%02x\n", ++ item->pw_name, buffer_size, padding_size, (unsigned char) pad); ++ errors = true; ++ } ++ if (ret == 0) ++ { ++ if (result == NULL) ++ { ++ printf ("error: no data: name \"%s\", buffer size %zu\n", ++ item->pw_name, buffer_size); ++ errors = true; ++ } ++ else if (!equal (item, result)) ++ { ++ printf ("error: lookup mismatch: name \"%s\", buffer size %zu\n", ++ item->pw_name, buffer_size); ++ errors = true; ++ } ++ } ++ else if (ret != ERANGE) ++ { ++ errno = ret; ++ printf ("error: lookup failure for name \"%s\": %m (%d)\n", ++ item->pw_name, ret); ++ errors = true; ++ } ++ ++ /* Test getpwuid_r. */ ++ memset (buffer, pad, buffer_size + padding_size); ++ pwd = (struct passwd) {}; ++ ret = getpwuid_r (item->pw_uid, &pwd, buffer, buffer_size, &result); ++ if (!check_padding (buffer + buffer_size, padding_size, pad)) ++ { ++ printf ("error: padding change: " ++ "UID %ld, buffer size %zu, padding size %zu, pad 0x%02x\n", ++ (long) item->pw_uid, buffer_size, padding_size, ++ (unsigned char) pad); ++ errors = true; ++ } ++ if (ret == 0) ++ { ++ if (result == NULL) ++ { ++ printf ("error: no data: UID %ld, buffer size %zu\n", ++ (long) item->pw_uid, buffer_size); ++ errors = true; ++ } ++ else if (!equal (item, result)) ++ { ++ printf ("error: lookup mismatch: UID %ld, buffer size %zu\n", ++ (long) item->pw_uid, buffer_size); ++ errors = true; ++ } ++ } ++ else if (ret != ERANGE) ++ { ++ errno = ret; ++ printf ("error: lookup failure for UID \"%ld\": %m (%d)\n", ++ (long) item->pw_uid, ret); ++ errors = true; ++ } ++ ++ free (buffer); ++} ++ ++/* Test one buffer size with different paddings. */ ++static void ++test_buffer_size (size_t buffer_size) ++{ ++ for (int i = 0; i < test_count; ++i) ++ for (size_t padding_size = 0; padding_size < 3; ++padding_size) ++ { ++ test_one (test_items + i, buffer_size, '\0', padding_size); ++ if (padding_size > 0) ++ { ++ test_one (test_items + i, buffer_size, ':', padding_size); ++ test_one (test_items + i, buffer_size, '\n', padding_size); ++ test_one (test_items + i, buffer_size, '\xff', padding_size); ++ test_one (test_items + i, buffer_size, '@', padding_size); ++ } ++ } ++} ++ ++int ++do_test (void) ++{ ++ if (!init_test_items ()) ++ return 1; ++ printf ("info: %d test items\n", test_count); ++ ++ for (size_t buffer_size = 0; buffer_size <= 65; ++buffer_size) ++ test_buffer_size (buffer_size); ++ for (size_t buffer_size = 64 + 4; buffer_size < 256; buffer_size += 4) ++ test_buffer_size (buffer_size); ++ test_buffer_size (255); ++ test_buffer_size (257); ++ for (size_t buffer_size = 256; buffer_size < 512; buffer_size += 8) ++ test_buffer_size (buffer_size); ++ test_buffer_size (511); ++ test_buffer_size (513); ++ test_buffer_size (1024); ++ test_buffer_size (2048); ++ ++ if (errors) ++ return 1; ++ else ++ return 0; ++} ++ ++#define TEST_FUNCTION do_test () ++#include "../test-skeleton.c" +diff a/nss/Makefile b/nss/Makefile +--- a/nss/Makefile ++++ b/nss/Makefile +@@ -39,6 +39,6 @@ + extra-objs += $(makedb-modules:=.o) + +-tests = test-netdb tst-nss-test1 ++tests = test-netdb tst-nss-test1 bug17079 + xtests = bug-erange + + include ../Makeconfig diff --git a/SOURCES/glibc-rh1039304-1.patch b/SOURCES/glibc-rh1039304-1.patch new file mode 100644 index 0000000..f2bbe6e --- /dev/null +++ b/SOURCES/glibc-rh1039304-1.patch @@ -0,0 +1,185 @@ +commit 5c1a69238fcb87ff7f916a5ce7960b2864afb3a1 +Author: Florian Weimer +Date: Sat Nov 11 11:23:40 2017 +0100 + + resolv: Add tst-res_hnok + +diff --git a/resolv/Makefile b/resolv/Makefile +index 988871086a70b291..b1fd2e2db8736f9b 100644 +--- a/resolv/Makefile ++++ b/resolv/Makefile +@@ -50,6 +50,7 @@ tests += \ + tst-ns_name \ + tst-ns_name_compress \ + tst-res_hconf_reorder \ ++ tst-res_hnok \ + tst-res_use_inet6 \ + tst-resolv-basic \ + tst-resolv-edns \ +@@ -182,6 +183,7 @@ $(objpfx)tst-resolv-canonname: \ + $(objpfx)tst-ns_name: $(objpfx)libresolv.so + $(objpfx)tst-ns_name.out: tst-ns_name.data + $(objpfx)tst-ns_name_compress: $(objpfx)libresolv.so ++$(objpfx)tst-res_hnok: $(objpfx)libresolv.so + + + # This test case uses the deprecated RES_USE_INET6 resolver option. +diff --git a/resolv/tst-res_hnok.c b/resolv/tst-res_hnok.c +new file mode 100644 +index 0000000000000000..9c923038218e965c +--- /dev/null ++++ b/resolv/tst-res_hnok.c +@@ -0,0 +1,153 @@ ++/* Tests for res_hnok and related functions. ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* Bits which indicate which functions are supposed to report ++ success. */ ++enum ++ { ++ hnok = 1, ++ dnok = 2, ++ mailok = 4, ++ ownok = 8, ++ allnomailok = hnok | dnok | ownok, ++ allok = hnok | dnok | mailok | ownok ++ }; ++ ++/* A string of 60 characters. */ ++#define STRING60 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" ++ ++/* A string of 63 characters (maximum label length). */ ++#define STRING63 STRING60 "zzz" ++ ++/* Combines a test name with the expected results. */ ++struct test_case ++{ ++ const char *dn; ++ unsigned int result; /* Combination of the *ok flags. */ ++}; ++ ++static const struct test_case tests[] = ++ { ++ { "", allok }, ++ { ".", allok }, ++ { "www", allnomailok }, ++ { "example", allnomailok }, ++ { "example.com", allok }, ++ { "www.example.com", allok }, ++ { "www.example.com.", allok }, ++ { "*.example.com", dnok | mailok | ownok }, ++ { "-v", dnok }, ++ { "-v.example.com", mailok | dnok }, ++ { "**.example.com", dnok | mailok }, ++ { STRING63, allnomailok }, ++ { STRING63 ".example.com", allok }, ++ { STRING63 "." STRING63 "." STRING63 "." STRING60 "z", allok }, ++ { "hostmaster@mail.example.com", dnok | mailok }, ++ { "with whitespace", 0 }, ++ { "with\twhitespace", 0 }, ++ { "with\nwhitespace", 0 }, ++ { "with.whitespace ", 0 }, ++ { "with.whitespace\t", 0 }, ++ { "with.whitespace\n", 0 }, ++ { "with\\ whitespace", 0 }, ++ { "with\\\twhitespace", 0 }, ++ { "with\\\nwhitespace", 0 }, ++ { "with.whitespace\\ ", 0 }, ++ { "with.whitespace\\\t", 0 }, ++ { "with.whitespace\\\n", 0 }, ++ }; ++ ++/* Run test case *TEST with FUNC (named FUNCNAME) and report an error ++ if the result does not match the result flag at BIT. */ ++static void ++one_test (const struct test_case *test, const char *funcname, ++ int (*func) (const char *), unsigned int bit) ++{ ++ int expected = (test->result & bit) != 0; ++ int actual = func (test->dn); ++ if (actual != expected) ++ { ++ support_record_failure (); ++ printf ("error: %s (\"%s\"): expected=%d, actual=%d\n", ++ funcname, test->dn, expected, actual); ++ } ++} ++ ++/* Run 255 tests using all the bytes from 1 to 255, surround the byte ++ with the strings PREFIX and SUFFIX, and check that FUNC (named ++ FUNCNAME) accepts only those bytes listed in ACCEPTED. */ ++static void ++one_char (const char *prefix, const char *accepted, const char *suffix, ++ const char *funcname, int (*func) (const char *)) ++{ ++ for (int ch = 1; ch <= 255; ++ch) ++ { ++ char dn[1024]; ++ snprintf (dn, sizeof (dn), "%s%c%s", prefix, ch, suffix); ++ int expected = strchr (accepted, ch) != NULL; ++ int actual = func (dn); ++ if (actual != expected) ++ { ++ support_record_failure (); ++ printf ("error: %s (\"%s\"): expected=%d, actual=%d\n", ++ funcname, dn, expected, actual); ++ } ++ } ++} ++ ++static int ++do_test (void) ++{ ++ for (const struct test_case *test = tests; test < array_end (tests); ++test) ++ { ++ if (test_verbose) ++ printf ("info: testing domain name [[[%s]]] (0x%x)\n", ++ test->dn, test->result); ++ one_test (test, "res_hnok", res_hnok, hnok); ++ one_test (test, "res_dnok", res_dnok, dnok); ++ one_test (test, "res_mailok", res_mailok, mailok); ++ one_test (test, "res_ownok", res_ownok, ownok); ++ } ++ ++ one_char ++ ("", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.", ++ "", "res_hnok", res_hnok); ++ one_char ++ ("middle", ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.-_", ++ "suffix", "res_hnok", res_hnok); ++ one_char ++ ("middle", ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.-_" ++ "!\"#$%&'()*+,/:;<=>?@[\\]^`{|}~", ++ "suffix.example", "res_mailok", res_mailok); ++ one_char ++ ("mailbox.middle", ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.-_", ++ "suffix.example", "res_mailok", res_mailok); ++ ++ return 0; ++} ++ ++#include diff --git a/SOURCES/glibc-rh1039304-2.patch b/SOURCES/glibc-rh1039304-2.patch new file mode 100644 index 0000000..7bea4a3 --- /dev/null +++ b/SOURCES/glibc-rh1039304-2.patch @@ -0,0 +1,235 @@ +commit e2a9fca8101443076235a8dbcfceaa2d96bf4801 +Author: Florian Weimer +Date: Sat Nov 11 11:33:32 2017 +0100 + + resolv: Add tst-ns_name_pton + +diff --git a/resolv/Makefile b/resolv/Makefile +index b1fd2e2db8736f9b..0130a09db2d69451 100644 +--- a/resolv/Makefile ++++ b/resolv/Makefile +@@ -49,6 +49,7 @@ tests += \ + tst-bug18665-tcp \ + tst-ns_name \ + tst-ns_name_compress \ ++ tst-ns_name_pton \ + tst-res_hconf_reorder \ + tst-res_hnok \ + tst-res_use_inet6 \ +@@ -183,6 +184,7 @@ $(objpfx)tst-resolv-canonname: \ + $(objpfx)tst-ns_name: $(objpfx)libresolv.so + $(objpfx)tst-ns_name.out: tst-ns_name.data + $(objpfx)tst-ns_name_compress: $(objpfx)libresolv.so ++$(objpfx)tst-ns_name_pton: $(objpfx)libresolv.so + $(objpfx)tst-res_hnok: $(objpfx)libresolv.so + + +diff --git a/resolv/tst-ns_name_pton.c b/resolv/tst-ns_name_pton.c +new file mode 100644 +index 0000000000000000..879d97c9d3816210 +--- /dev/null ++++ b/resolv/tst-ns_name_pton.c +@@ -0,0 +1,203 @@ ++/* Tests for ns_name_pton. ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Bits which indicate which functions are supposed to report ++ success. */ ++enum ++ { ++ hnok = 1, ++ dnok = 2, ++ mailok = 4, ++ ownok = 8, ++ allnomailok = hnok | dnok | ownok, ++ allok = hnok | dnok | mailok | ownok ++ }; ++ ++/* A string of 60 characters. */ ++#define STRING60 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" ++ ++/* A string of 63 characters (maximum label length). */ ++#define STRING63 STRING60 "zzz" ++ ++/* A string of 60 bytes (non-ASCII). */ ++#define STRING60OCT \ ++ "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ ++ "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ ++ "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ ++ "\377\377\377\377\377\377\377\377\377" ++ ++/* A string of 63 bytes (non-ASCII). */ ++#define STRING63OCT STRING60OCT "\377\377\377" ++ ++/* A string of 60 bytes (non-ASCII, quoted decimal). */ ++#define STRING60DEC \ ++ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ ++ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ ++ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ ++ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ ++ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ ++ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" ++ ++/* A string of 63 bytes (non-ASCII, quoted decimal). */ ++#define STRING63DEC STRING60DEC "\\255\\255\\255" ++ ++/* Combines a test name with the expected results. */ ++struct test_case ++{ ++ const char *dn; ++ const char *back; /* Expected test result converted using ns_name_ntop. */ ++ bool fully_qualified; /* True if the domain name has a trailing dot. */ ++}; ++ ++static const struct test_case tests[] = ++ { ++ { "", ".", false }, ++ { ".", ".", true }, ++ { "..", NULL, }, ++ { "www", "www", false }, ++ { "www.", "www", true }, ++ { "www\\.", "www\\.", false }, ++ { ".www", NULL, }, ++ { ".www\\.", NULL, }, ++ { "example.com", "example.com", false }, ++ { "example.com.", "example.com", true }, ++ { ".example.com", NULL, }, ++ { ".example.com.", NULL, }, ++ { "example\\.com", "example\\.com", false }, ++ { "example\\.com.", "example\\.com", true }, ++ { "example..", NULL, }, ++ { "example..com", NULL, }, ++ { "example..com", NULL, }, ++ { "\\0", NULL, }, ++ { "\\00", NULL, }, ++ { "\\000", "\\000", false }, ++ { "\\1", NULL, }, ++ { "\\01", NULL, }, ++ { "\\001", "\\001", false }, ++ { "\\1x", NULL, }, ++ { "\\01x", NULL, }, ++ { "\\001x", "\\001x", false }, ++ { "\\256", NULL, }, ++ { "\\0641", "\\@1", false }, ++ { "\\0011", "\\0011", false }, ++ { STRING63, STRING63, false }, ++ { STRING63 ".", STRING63, true }, ++ { STRING63 "z", NULL, }, ++ { STRING63 "\\.", NULL, }, ++ { STRING60 "zz\\.", STRING60 "zz\\.", false }, ++ { STRING60 "zz\\..", STRING60 "zz\\.", true }, ++ { STRING63 "." STRING63 "." STRING63 "." STRING60 "z", ++ STRING63 "." STRING63 "." STRING63 "." STRING60 "z", false }, ++ { STRING63 "." STRING63 "." STRING63 "." STRING60 "z.", ++ STRING63 "." STRING63 "." STRING63 "." STRING60 "z", true }, ++ { STRING63 "." STRING63 "." STRING63 "." STRING60 "zz", NULL, }, ++ { STRING63 "." STRING63 "." STRING63 "." STRING60 "zzz", NULL, }, ++ { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT "\377", ++ STRING63DEC "." STRING63DEC "." STRING63DEC "." STRING60DEC "\\255", ++ false }, ++ { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT "\377.", ++ STRING63DEC "." STRING63DEC "." STRING63DEC "." STRING60DEC "\\255", ++ true }, ++ { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT ++ "\377\377", NULL, }, ++ { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT ++ "\377\377\377", NULL, }, ++ }; ++ ++static int ++do_test (void) ++{ ++ unsigned char *wire = xmalloc (NS_MAXCDNAME); ++ char *text = xmalloc (NS_MAXDNAME); ++ for (const struct test_case *test = tests; test < array_end (tests); ++test) ++ { ++ if (test_verbose) ++ printf ("info: testing domain name [[[%s]]]\n", test->dn); ++ int ret = ns_name_pton (test->dn, wire, NS_MAXCDNAME); ++ if (ret == -1) ++ { ++ if (test->back != NULL) ++ { ++ support_record_failure (); ++ printf ("error: unexpected decoding failure for [[%s]]\n", ++ test->dn); ++ } ++ /* Otherwise, we have an expected decoding failure. */ ++ continue; ++ } ++ ++ if (ret < -1 || ret > 1) ++ { ++ support_record_failure (); ++ printf ("error: invalid return value %d for [[%s]]\n", ++ ret, test->dn); ++ continue; ++ } ++ ++ int ret2 = ns_name_ntop (wire, text, NS_MAXDNAME); ++ ++ if (ret2 < 0) ++ { ++ support_record_failure (); ++ printf ("error: failure to convert back [[%s]]\n", test->dn); ++ } ++ ++ if (test->back == NULL) ++ { ++ support_record_failure (); ++ printf ("error: unexpected success converting [[%s]]\n", test->dn); ++ if (ret2 >= 1) ++ printf ("error: result converts back to [[%s]]\n", test->dn); ++ continue; ++ } ++ ++ if (strcmp (text, test->back) != 0) ++ { ++ support_record_failure (); ++ printf ("error: back-conversion of [[%s]] did not match\n", ++ test->dn); ++ printf ("error: expected: [[%s]]\n", test->back); ++ printf ("error: actual: [[%s]]\n", text); ++ } ++ ++ if (ret != test->fully_qualified) ++ { ++ support_record_failure (); ++ printf ("error: invalid fully-qualified status for [[%s]]\n", ++ test->dn); ++ printf ("error: expected: %d\n", (int) test->fully_qualified); ++ printf ("error: actual: %d\n", ret); ++ } ++ } ++ ++ free (text); ++ free (wire); ++ return 0; ++} ++ ++#include diff --git a/SOURCES/glibc-rh1039304-3.patch b/SOURCES/glibc-rh1039304-3.patch new file mode 100644 index 0000000..d39d4d2 --- /dev/null +++ b/SOURCES/glibc-rh1039304-3.patch @@ -0,0 +1,40 @@ +commit 9e0ad3049dbae88d615bfb038e53bf365a39a634 +Author: Florian Weimer +Date: Sat Nov 11 11:41:45 2017 +0100 + + resolv: ns_name_pton should report trailing \ as error [BZ #22413] + +diff --git a/resolv/ns_name.c b/resolv/ns_name.c +index 08a75e2fe0b4edd6..73213fee2dca530b 100644 +--- a/resolv/ns_name.c ++++ b/resolv/ns_name.c +@@ -222,6 +222,11 @@ ns_name_pton(const char *src, u_char *dst, size_t dstsiz) + } + *bp++ = (u_char)c; + } ++ if (escaped) { ++ /* Trailing backslash. */ ++ __set_errno (EMSGSIZE); ++ return -1; ++ } + c = (bp - label - 1); + if ((c & NS_CMPRSFLGS) != 0) { /*%< Label too big. */ + __set_errno (EMSGSIZE); +diff --git a/resolv/tst-ns_name_pton.c b/resolv/tst-ns_name_pton.c +index 879d97c9d3816210..73bdb05e08e405dc 100644 +--- a/resolv/tst-ns_name_pton.c ++++ b/resolv/tst-ns_name_pton.c +@@ -127,6 +127,13 @@ static const struct test_case tests[] = + "\377\377", NULL, }, + { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT + "\377\377\377", NULL, }, ++ { "\\", NULL, }, ++ { "\\\\", "\\\\", false }, ++ { "\\\\.", "\\\\", true }, ++ { "\\\\\\", NULL, }, ++ { "a\\", NULL, }, ++ { "a.\\", NULL, }, ++ { "a.b\\", NULL, }, + }; + + static int diff --git a/SOURCES/glibc-rh1039304-4.patch b/SOURCES/glibc-rh1039304-4.patch new file mode 100644 index 0000000..e67eab1 --- /dev/null +++ b/SOURCES/glibc-rh1039304-4.patch @@ -0,0 +1,322 @@ +commit c0a25aa92b612786f4e45292c4aee1d7d47123f8 +Author: Florian Weimer +Date: Sat Nov 11 11:51:08 2017 +0100 + + resolv: More precise checks in res_hnok, res_dnok [BZ #22409] [BZ #22412] + + res_hnok rejected some host names used on the Internet, such as + www-.example.com. res_hnok and res_dnok failed to perform basic syntax + checking on DNS domain names. + + Also fix res_mailok, res_ownok. + +diff --git a/resolv/res_comp.c b/resolv/res_comp.c +index ffb2ed59147d3680..79760e891f607daa 100644 +--- a/resolv/res_comp.c ++++ b/resolv/res_comp.c +@@ -1,3 +1,21 @@ ++/* Domain name processing functions. ++ Copyright (C) 1995-2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ + /* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. +@@ -121,110 +139,118 @@ dn_skipname(const u_char *ptr, const u_char *eom) { + } + libresolv_hidden_def (dn_skipname) + +-/* +- * Verify that a domain name uses an acceptable character set. +- */ ++/* Return true if the string consists of printable ASCII characters ++ only. */ ++static bool ++printable_string (const char *dn) ++{ ++ while (true) ++ { ++ char ch = *dn; ++ if (ch == '\0') ++ return true; ++ if (ch <= ' ' || ch > '~') ++ return false; ++ ++dn; ++ } ++} + +-/* +- * Note the conspicuous absence of ctype macros in these definitions. On +- * non-ASCII hosts, we can't depend on string literals or ctype macros to +- * tell us anything about network-format data. The rest of the BIND system +- * is not careful about this, but for some reason, we're doing it right here. +- */ +-#define PERIOD 0x2e +-#define hyphenchar(c) ((c) == 0x2d) +-#define underscorechar(c) ((c) == 0x5f) +-#define bslashchar(c) ((c) == 0x5c) +-#define periodchar(c) ((c) == PERIOD) +-#define asterchar(c) ((c) == 0x2a) +-#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \ +- || ((c) >= 0x61 && (c) <= 0x7a)) +-#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39) +- +-#define borderchar(c) (alphachar(c) || digitchar(c)) +-#define middlechar(c) (borderchar(c) || hyphenchar(c) || underscorechar(c)) +-#define domainchar(c) ((c) > 0x20 && (c) < 0x7f) ++/* Return true if DN points to a name consisting only of [0-9a-zA-Z_-] ++ characters. DN must be in DNS wire format, without ++ compression. */ ++static bool ++binary_hnok (const unsigned char *dn) ++{ ++ while (true) ++ { ++ size_t label_length = *dn; ++ if (label_length == 0) ++ break; ++ ++dn; ++ const unsigned char *label_end = dn + label_length; ++ do ++ { ++ unsigned char ch = *dn; ++ if (!(('0' <= ch && ch <= '9') ++ || ('A' <= ch && ch <= 'Z') ++ || ('a' <= ch && ch <= 'z') ++ || ch == '-' || ch == '_')) ++ return false; ++ ++dn; ++ } ++ while (dn < label_end); ++ } ++ return true; ++} ++ ++/* Return true if the binary domain name has a first labels which ++ starts with '-'. */ ++static inline bool ++binary_leading_dash (const unsigned char *dn) ++{ ++ return dn[0] > 0 && dn[1] == '-'; ++} + ++/* Return 1 if res_hnok is a valid host name. Labels must only ++ contain [0-9a-zA-Z_-] characters, and the name must not start with ++ a '-'. The latter is to avoid confusion with program options. */ + int +-res_hnok(const char *dn) { +- int pch = PERIOD, ch = *dn++; +- +- while (ch != '\0') { +- int nch = *dn++; +- +- if (periodchar(ch)) { +- (void)NULL; +- } else if (periodchar(pch)) { +- if (!borderchar(ch)) +- return (0); +- } else if (periodchar(nch) || nch == '\0') { +- if (!borderchar(ch)) +- return (0); +- } else { +- if (!middlechar(ch)) +- return (0); +- } +- pch = ch, ch = nch; +- } +- return (1); ++res_hnok (const char *dn) ++{ ++ unsigned char buf[NS_MAXCDNAME]; ++ if (!printable_string (dn) ++ || ns_name_pton (dn, buf, sizeof (buf)) < 0 ++ || binary_leading_dash (buf)) ++ return 0; ++ return binary_hnok (buf); + } + libresolv_hidden_def (res_hnok) + +-/* +- * hostname-like (A, MX, WKS) owners can have "*" as their first label +- * but must otherwise be as a host name. +- */ ++/* Hostname-like (A, MX, WKS) owners can have "*" as their first label ++ but must otherwise be as a host name. */ + int +-res_ownok(const char *dn) { +- if (asterchar(dn[0])) { +- if (periodchar(dn[1])) +- return (res_hnok(dn+2)); +- if (dn[1] == '\0') +- return (1); +- } +- return (res_hnok(dn)); ++res_ownok (const char *dn) ++{ ++ unsigned char buf[NS_MAXCDNAME]; ++ if (!printable_string (dn) ++ || ns_name_pton (dn, buf, sizeof (buf)) < 0 ++ || binary_leading_dash (buf)) ++ return 0; ++ if (buf[0] == 1 && buf [1] == '*') ++ /* Skip over the leading "*." part. */ ++ return binary_hnok (buf + 2); ++ else ++ return binary_hnok (buf); + } + +-/* +- * SOA RNAMEs and RP RNAMEs can have any printable character in their first +- * label, but the rest of the name has to look like a host name. +- */ ++/* SOA RNAMEs and RP RNAMEs can have any byte in their first label, ++ but the rest of the name has to look like a host name. */ + int +-res_mailok(const char *dn) { +- int ch, escaped = 0; +- +- /* "." is a valid missing representation */ +- if (*dn == '\0') +- return (1); +- +- /* otherwise