diff options
author | Andreas Schwab <schwab@redhat.com> | 2009-10-30 16:11:14 +0100 |
---|---|---|
committer | Andreas Schwab <schwab@redhat.com> | 2009-10-30 16:11:14 +0100 |
commit | 017dd87448e913383a8be5773569f218e8c661c5 (patch) | |
tree | d9124fdbb290416e60553c87aa9f9f1750d7acb8 /sysdeps | |
parent | f8e81cec78280ef92014305c1e10a808b1260683 (diff) | |
parent | 3a83202db6e5591f2b72974c1ad98602c6620770 (diff) | |
download | glibc-017dd87448e913383a8be5773569f218e8c661c5.tar glibc-017dd87448e913383a8be5773569f218e8c661c5.tar.gz glibc-017dd87448e913383a8be5773569f218e8c661c5.tar.bz2 glibc-017dd87448e913383a8be5773569f218e8c661c5.zip |
Merge remote branch 'origin/master' into fedora/master
Diffstat (limited to 'sysdeps')
55 files changed, 1180 insertions, 63 deletions
diff --git a/sysdeps/generic/elf/ifunc-sel.h b/sysdeps/generic/elf/ifunc-sel.h new file mode 100644 index 0000000000..6a27b69c5b --- /dev/null +++ b/sysdeps/generic/elf/ifunc-sel.h @@ -0,0 +1,26 @@ +/* Used by the elf ifunc tests. */ +#ifndef ELF_IFUNC_SEL_H +#define ELF_IFUNC_SEL_H 1 + +extern int global; + +static inline void * +ifunc_sel (int (*f1) (void), int (*f2) (void), int (*f3) (void)) +{ + switch (global) + { + case 1: + return f1; + case -1: + return f2; + default: + return f3; + } +} + +static inline void * +ifunc_one (int (*f1) (void)) +{ + return f1; +} +#endif diff --git a/sysdeps/generic/netinet/ip.h b/sysdeps/generic/netinet/ip.h index fc91440527..38bd7556da 100644 --- a/sysdeps/generic/netinet/ip.h +++ b/sysdeps/generic/netinet/ip.h @@ -1,4 +1,5 @@ -/* Copyright (C) 1991,92,93,95,96,97,98,99,2000 Free Software Foundation, Inc. +/* Copyright (C) 1991,92,93,95,96,97,98,99,2000,2009 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 @@ -153,6 +154,41 @@ struct ip_timestamp #define IP_MAXPACKET 65535 /* maximum packet size */ /* + * Definitions for Explicit Congestion Notification (ECN) + * + * Taken from RFC-3168, Section 5. + */ + +#define IPTOS_ECN_MASK 0x03 +#define IPTOS_ECN(x) ((x) & IPTOS_ECN_MASK) +#define IPTOS_ECN_NOT_ECT 0x00 +#define IPTOS_ECN_ECT1 0x01 +#define IPTOS_ECN_ECT0 0x02 +#define IPTOS_ECN_CE 0x03 + +/* + * Definitions for IP differentiated services code points (DSCP) + * + * Taken from RFC-2597, Section 6 and RFC-2598, Section 2.3. + */ + +#define IPTOS_DSCP_MASK 0xfc +#define IPTOS_DSCP(x) ((x) & IPTOS_DSCP_MASK) +#define IPTOS_DSCP_AF11 0x28 +#define IPTOS_DSCP_AF12 0x30 +#define IPTOS_DSCP_AF13 0x38 +#define IPTOS_DSCP_AF21 0x48 +#define IPTOS_DSCP_AF22 0x50 +#define IPTOS_DSCP_AF23 0x58 +#define IPTOS_DSCP_AF31 0x68 +#define IPTOS_DSCP_AF32 0x70 +#define IPTOS_DSCP_AF33 0x78 +#define IPTOS_DSCP_AF41 0x88 +#define IPTOS_DSCP_AF42 0x90 +#define IPTOS_DSCP_AF43 0x98 +#define IPTOS_DSCP_EF 0xb8 + +/* * Definitions for IP type of service (ip_tos) */ #define IPTOS_TOS_MASK 0x1E diff --git a/sysdeps/gnu/getutmp.c b/sysdeps/gnu/getutmp.c index 7b6d7713ea..9647c252e2 100644 --- a/sysdeps/gnu/getutmp.c +++ b/sysdeps/gnu/getutmp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1999 Free Software Foundation, Inc. +/* Copyright (C) 1999, 2009 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 @@ -19,10 +19,12 @@ #include <assert.h> #include <string.h> #include <utmp.h> +#ifndef _UTMPX_H /* This is an ugly hack but we must not see the getutmpx declaration. */ -#define getutmpx XXXgetutmpx -#include <utmpx.h> -#undef getutmpx +# define getutmpx XXXgetutmpx +# include <utmpx.h> +# undef getutmpx +#endif void getutmp (const struct utmpx *utmpx, struct utmp *utmp) diff --git a/sysdeps/gnu/netinet/udp.h b/sysdeps/gnu/netinet/udp.h index 45b69f7499..ae1beb9e1a 100644 --- a/sysdeps/gnu/netinet/udp.h +++ b/sysdeps/gnu/netinet/udp.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 92, 93, 95, 96, 97, 2004 Free Software Foundation, Inc. +/* Copyright (C) 1991-1993,1995-1997,2004,2009 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 @@ -74,6 +74,16 @@ struct udphdr }; #endif +/* UDP socket options */ +#define UDP_CORK 1 /* Never send partially complete segments. */ +#define UDP_ENCAP 100 /* Set the socket to accept + encapsulated packets. */ + +/* UDP encapsulation types */ +#define UDP_ENCAP_ESPINUDP_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */ +#define UDP_ENCAP_ESPINUDP 2 /* draft-ietf-ipsec-udp-encaps-06 */ +#define UDP_ENCAP_L2TPINUDP 3 /* rfc2661 */ + #define SOL_UDP 17 /* sockopt level for UDP */ #endif /* netinet/udp.h */ diff --git a/sysdeps/i386/fpu/s_expm1.S b/sysdeps/i386/fpu/s_expm1.S index e761183639..c690a458f8 100644 --- a/sysdeps/i386/fpu/s_expm1.S +++ b/sysdeps/i386/fpu/s_expm1.S @@ -22,6 +22,7 @@ /* Using: e^x - 1 = 2^(x * log2(e)) - 1 */ +#include <sysdep.h> #include <machine/asm.h> #ifdef __ELF__ @@ -48,6 +49,11 @@ l2e: .tfloat 1.442695040888963407359924681002 .text ENTRY(__expm1) + movzwl 4+6(%esp), %eax + xorb $0x80, %ah // invert sign bit (now 1 is "positive") + cmpl $0xc086, %eax // is num >= 704? + jae HIDDEN_JUMPTARGET (__exp) + fldl 4(%esp) // x fxam // Is NaN or +-Inf? fstsw %ax diff --git a/sysdeps/i386/fpu/s_expm1f.S b/sysdeps/i386/fpu/s_expm1f.S index 88adb75b86..8645107274 100644 --- a/sysdeps/i386/fpu/s_expm1f.S +++ b/sysdeps/i386/fpu/s_expm1f.S @@ -22,6 +22,7 @@ /* Using: e^x - 1 = 2^(x * log2(e)) - 1 */ +#include <sysdep.h> #include <machine/asm.h> #ifdef __ELF__ @@ -48,6 +49,11 @@ l2e: .tfloat 1.442695040888963407359924681002 .text ENTRY(__expm1f) + movzwl 4+2(%esp), %eax + xorb $0x80, %ah // invert sign bit (now 1 is "positive") + cmpl $0xc2b1, %eax // is num >= 88.5? + jae HIDDEN_JUMPTARGET (__expf) + flds 4(%esp) // x fxam // Is NaN or +-Inf? fstsw %ax diff --git a/sysdeps/i386/fpu/s_expm1l.S b/sysdeps/i386/fpu/s_expm1l.S index b69b22bc62..60b5b82e20 100644 --- a/sysdeps/i386/fpu/s_expm1l.S +++ b/sysdeps/i386/fpu/s_expm1l.S @@ -22,6 +22,7 @@ /* Using: e^x - 1 = 2^(x * log2(e)) - 1 */ +#include <sysdep.h> #include <machine/asm.h> #ifdef __ELF__ @@ -51,7 +52,7 @@ ENTRY(__expm1l) movzwl 4+8(%esp), %eax // load sign bit and 15-bit exponent xorb $0x80, %ah // invert sign bit (now 1 is "positive") cmpl $0xc006, %eax // is num positive and exp >= 6 (number is >= 128.0)? - jae __ieee754_expl // (if num is denormal, it is at least >= 64.0) + jae HIDDEN_JUMPTARGET (__expl) // (if num is denormal, it is at least >= 64.0) fldt 4(%esp) // x fxam // Is NaN or +-Inf? diff --git a/sysdeps/ieee754/dbl-64/w_exp.c b/sysdeps/ieee754/dbl-64/w_exp.c index 445c5788d2..1216492090 100644 --- a/sysdeps/ieee754/dbl-64/w_exp.c +++ b/sysdeps/ieee754/dbl-64/w_exp.c @@ -51,6 +51,7 @@ u_threshold= -7.45133219101941108420e+02; /* 0xc0874910, 0xD52D3051 */ return z; #endif } +hidden_def (__exp) weak_alias (__exp, exp) #ifdef NO_LONG_DOUBLE strong_alias (__exp, __expl) diff --git a/sysdeps/ieee754/flt-32/w_expf.c b/sysdeps/ieee754/flt-32/w_expf.c index 4ba21c7c42..83b268f570 100644 --- a/sysdeps/ieee754/flt-32/w_expf.c +++ b/sysdeps/ieee754/flt-32/w_expf.c @@ -56,4 +56,5 @@ u_threshold= -1.0397208405e+02; /* 0xc2cff1b5 */ return z; #endif } +hidden_def (__expf) weak_alias (__expf, expf) diff --git a/sysdeps/ieee754/ldbl-128/w_expl.c b/sysdeps/ieee754/ldbl-128/w_expl.c index 816ce3caa6..d6205d3ef8 100644 --- a/sysdeps/ieee754/ldbl-128/w_expl.c +++ b/sysdeps/ieee754/ldbl-128/w_expl.c @@ -55,4 +55,5 @@ u_threshold= -1.1433462743336297878837243843452621503410E4; return z; #endif } +hidden_def (__expl) weak_alias (__expl, expl) diff --git a/sysdeps/ieee754/ldbl-96/w_expl.c b/sysdeps/ieee754/ldbl-96/w_expl.c index b8152cea65..53bb143734 100644 --- a/sysdeps/ieee754/ldbl-96/w_expl.c +++ b/sysdeps/ieee754/ldbl-96/w_expl.c @@ -57,4 +57,5 @@ u_threshold= -1.140019167866942050398521670162263001513e4; return z; #endif } +hidden_def (__expl) weak_alias (__expl, expl) diff --git a/sysdeps/posix/tempname.c b/sysdeps/posix/tempname.c index be979d8c8a..57ce5a942c 100644 --- a/sysdeps/posix/tempname.c +++ b/sysdeps/posix/tempname.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2001, 2006, 2007 Free Software Foundation, Inc. +/* Copyright (C) 1991-2001, 2006, 2007, 2009 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 @@ -210,9 +210,9 @@ static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; /* Generate a temporary file name based on TMPL. TMPL must match the - rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed - does not exist at the time of the call to __gen_tempname. TMPL is - overwritten with the result. + rules for mk[s]temp (i.e. end in "XXXXXX", possibly with a suffix). + The name constructed does not exist at the time of the call to + __gen_tempname. TMPL is overwritten with the result. KIND may be one of: __GT_NOCREATE: simply verify that the name does not exist @@ -223,7 +223,7 @@ static const char letters[] = We use a clever algorithm to get hard-to-predict names. */ int -__gen_tempname (char *tmpl, int flags, int kind) +__gen_tempname (char *tmpl, int suffixlen, int flags, int kind) { int len; char *XXXXXX; @@ -251,14 +251,14 @@ __gen_tempname (char *tmpl, int flags, int kind) #endif len = strlen (tmpl); - if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX")) + if (len < 6 + suffixlen || memcmp (&tmpl[len - 6 - suffixlen], "XXXXXX", 6)) { __set_errno (EINVAL); return -1; } /* This is where the Xs start. */ - XXXXXX = &tmpl[len - 6]; + XXXXXX = &tmpl[len - 6 - suffixlen]; /* Get some more or less random data. */ #ifdef RANDOM_BITS diff --git a/sysdeps/powerpc/elf/ifunc-sel.h b/sysdeps/powerpc/elf/ifunc-sel.h new file mode 100644 index 0000000000..526d8ed88b --- /dev/null +++ b/sysdeps/powerpc/elf/ifunc-sel.h @@ -0,0 +1,46 @@ +/* Used by the elf ifunc tests. */ +#ifndef ELF_IFUNC_SEL_H +#define ELF_IFUNC_SEL_H 1 + +extern int global; + +static inline void * +ifunc_sel (int (*f1) (void), int (*f2) (void), int (*f3) (void)) +{ + register void *ret __asm__ ("r3"); + __asm__ ("mflr 12\n\t" + "bcl 20,31,1f\n" + "1:\tmflr 11\n\t" + "mtlr 12\n\t" + "addis 12,11,global-1b@ha\n\t" + "lwz 12,global-1b@l(12)\n\t" + "addis %0,11,%2-1b@ha\n\t" + "addi %0,%0,%2-1b@l\n\t" + "cmpwi 12,1\n\t" + "beqlr\n\t" + "addis %0,11,%3-1b@ha\n\t" + "addi %0,%0,%3-1b@l\n\t" + "cmpwi 12,-1\n\t" + "beqlr\n\t" + "addis %0,11,%4-1b@ha\n\t" + "addi %0,%0,%4-1b@l" + : "=r" (ret) + : "X" (&global), "X" (f1), "X" (f2), "X" (f3)); + return ret; +} + +static inline void * +ifunc_one (int (*f1) (void)) +{ + register void *ret __asm__ ("r3"); + __asm__ ("mflr 12\n\t" + "bcl 20,31,1f\n" + "1:\tmflr %0\n\t" + "mtlr 12\n\t" + "addis %0,%0,%1-1b@ha\n\t" + "addi %0,%0,%1-1b@l" + : "=r" (ret) + : "X" (f1)); + return ret; +} +#endif diff --git a/sysdeps/powerpc/powerpc32/dl-irel.h b/sysdeps/powerpc/powerpc32/dl-irel.h new file mode 100644 index 0000000000..3f204cd7ae --- /dev/null +++ b/sysdeps/powerpc/powerpc32/dl-irel.h @@ -0,0 +1,45 @@ +/* Machine-dependent ELF indirect relocation inline functions. + PowerPC version. + Copyright (C) 2009 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _DL_IREL_H +#define _DL_IREL_H + +#include <stdio.h> +#include <unistd.h> + +#define ELF_MACHINE_IRELA 1 + +static inline void +__attribute ((always_inline)) +elf_irela (const Elf32_Rela *reloc) +{ + unsigned int r_type = ELF32_R_TYPE (reloc->r_info); + + if (__builtin_expect (r_type == R_PPC_IRELATIVE, 1)) + { + Elf32_Addr *const reloc_addr = (void *) reloc->r_offset; + Elf32_Addr value = ((Elf32_Addr (*) (void)) reloc->r_addend) (); + *reloc_addr = value; + } + else + __libc_fatal ("unexpected reloc type in static binary"); +} + +#endif /* dl-irel.h */ diff --git a/sysdeps/powerpc/powerpc32/dl-machine.c b/sysdeps/powerpc/powerpc32/dl-machine.c index 71540bd185..ee4c3e0c1c 100644 --- a/sysdeps/powerpc/powerpc32/dl-machine.c +++ b/sysdeps/powerpc/powerpc32/dl-machine.c @@ -337,7 +337,7 @@ __elf_machine_runtime_setup (struct link_map *map, int lazy, int profile) } Elf32_Addr -__elf_machine_fixup_plt (struct link_map *map, const Elf32_Rela *reloc, +__elf_machine_fixup_plt (struct link_map *map, Elf32_Addr *reloc_addr, Elf32_Addr finaladdr) { Elf32_Sword delta = finaladdr - (Elf32_Word) reloc_addr; @@ -430,6 +430,10 @@ __process_machine_rela (struct link_map *map, *reloc_addr = finaladdr; return; + case R_PPC_IRELATIVE: + *reloc_addr = ((Elf32_Addr (*) (void)) finaladdr) (); + return; + case R_PPC_UADDR32: ((char *) reloc_addr)[0] = finaladdr >> 24; ((char *) reloc_addr)[1] = finaladdr >> 16; diff --git a/sysdeps/powerpc/powerpc32/dl-machine.h b/sysdeps/powerpc/powerpc32/dl-machine.h index a50ffdd1c2..6f8d0f506e 100644 --- a/sysdeps/powerpc/powerpc32/dl-machine.h +++ b/sysdeps/powerpc/powerpc32/dl-machine.h @@ -226,7 +226,6 @@ elf_machine_runtime_setup (struct link_map *map, /* Change the PLT entry whose reloc is 'reloc' to call the actual routine. */ extern Elf32_Addr __elf_machine_fixup_plt (struct link_map *map, - const Elf32_Rela *reloc, Elf32_Addr *reloc_addr, Elf32_Addr finaladdr); @@ -237,7 +236,7 @@ elf_machine_fixup_plt (struct link_map *map, lookup_t t, { if (map->l_info[DT_PPC(GOT)] == 0) /* Handle old style PLT. */ - return __elf_machine_fixup_plt (map, reloc, reloc_addr, finaladdr); + return __elf_machine_fixup_plt (map, reloc_addr, finaladdr); *reloc_addr = finaladdr; return finaladdr; @@ -317,6 +316,11 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, value = reloc->r_addend; #endif + if (sym != NULL + && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0) + && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)) + value = ((Elf32_Addr (*) (void)) value) (); + /* A small amount of code is duplicated here for speed. In libc, more than 90% of the relocs are R_PPC_RELATIVE; in the X11 shared libraries, 60% are R_PPC_RELATIVE, 24% are R_PPC_GLOB_DAT or diff --git a/sysdeps/powerpc/powerpc64/dl-irel.h b/sysdeps/powerpc/powerpc64/dl-irel.h new file mode 100644 index 0000000000..6cded5091d --- /dev/null +++ b/sysdeps/powerpc/powerpc64/dl-irel.h @@ -0,0 +1,58 @@ +/* Machine-dependent ELF indirect relocation inline functions. + PowerPC64 version. + Copyright (C) 2009 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _DL_IREL_H +#define _DL_IREL_H + +#include <stdio.h> +#include <unistd.h> + +#define ELF_MACHINE_IRELA 1 + +typedef struct +{ + Elf64_Addr fd_func; + Elf64_Addr fd_toc; + Elf64_Addr fd_aux; +} Elf64_FuncDesc; + +static inline void +__attribute ((always_inline)) +elf_irela (const Elf64_Rela *reloc) +{ + unsigned int r_type = ELF64_R_TYPE (reloc->r_info); + + if (__builtin_expect (r_type == R_PPC64_IRELATIVE, 1)) + { + Elf64_Addr *const reloc_addr = (void *) reloc->r_offset; + Elf64_Addr value = ((Elf64_Addr (*) (void)) reloc->r_addend) (); + *reloc_addr = value; + } + else if (__builtin_expect (r_type == R_PPC64_JMP_IREL, 1)) + { + Elf64_Addr *const reloc_addr = (void *) reloc->r_offset; + Elf64_Addr value = ((Elf64_Addr (*) (void)) reloc->r_addend) (); + *(Elf64_FuncDesc *) reloc_addr = *(Elf64_FuncDesc *) value; + } + else + __libc_fatal ("unexpected reloc type in static binary"); +} + +#endif /* dl-irel.h */ diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h index b674dbef43..8a720ae9c2 100644 --- a/sysdeps/powerpc/powerpc64/dl-machine.h +++ b/sysdeps/powerpc/powerpc64/dl-machine.h @@ -526,6 +526,29 @@ elf_machine_tprel (struct link_map *map, } #endif +/* Call function at address VALUE (an OPD entry) to resolve ifunc relocs. */ +auto inline Elf64_Addr __attribute__ ((always_inline)) +resolve_ifunc (Elf64_Addr value, + const struct link_map *map, const struct link_map *sym_map) +{ + /* The function we are calling may not yet have its opd entry relocated. */ + Elf64_FuncDesc opd; + if (map != sym_map +#if !defined RTLD_BOOTSTRAP && defined SHARED + /* Bootstrap map doesn't have l_relocated set for it. */ + && sym_map != &GL(dl_rtld_map) +#endif + && !sym_map->l_relocated) + { + Elf64_FuncDesc *func = (Elf64_FuncDesc *) value; + opd.fd_func = func->fd_func + sym_map->l_addr; + opd.fd_toc = func->fd_toc + sym_map->l_addr; + opd.fd_aux = func->fd_aux; + value = (Elf64_Addr) &opd; + } + return ((Elf64_Addr (*) (void)) value) (); +} + /* Perform the relocation specified by RELOC and SYM (which is fully resolved). MAP is the object containing the reloc. */ auto inline void __attribute__ ((always_inline)) @@ -550,11 +573,17 @@ elf_machine_rela (struct link_map *map, if (__builtin_expect (r_type == R_PPC64_NONE, 0)) return; - /* We need SYM_MAP even in the absence of TLS, for elf_machine_fixup_plt. */ + /* We need SYM_MAP even in the absence of TLS, for elf_machine_fixup_plt + and STT_GNU_IFUNC. */ struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type); Elf64_Addr value = ((sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value) + reloc->r_addend); + if (sym != NULL + && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0) + && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)) + value = resolve_ifunc (value, map, sym_map); + /* For relocs that don't edit code, return. For relocs that might edit instructions, break from the switch. */ switch (r_type) @@ -564,6 +593,14 @@ elf_machine_rela (struct link_map *map, *reloc_addr = value; return; + case R_PPC64_IRELATIVE: + value = resolve_ifunc (value, map, sym_map); + *reloc_addr = value; + return; + + case R_PPC64_JMP_IREL: + value = resolve_ifunc (value, map, sym_map); + /* Fall thru */ case R_PPC64_JMP_SLOT: #ifdef RESOLVE_CONFLICT_FIND_MAP elf_machine_plt_conflict (reloc_addr, value); diff --git a/sysdeps/pthread/aio_misc.c b/sysdeps/pthread/aio_misc.c index fd3fcbb755..c82acbbc2d 100644 --- a/sysdeps/pthread/aio_misc.c +++ b/sysdeps/pthread/aio_misc.c @@ -1,5 +1,5 @@ /* Handle general operations. - Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2006, 2007 + Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2006, 2007, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -372,9 +372,13 @@ __aio_enqueue_request (aiocb_union *aiocbp, int operation) /* Simply enqueue it after the running one according to the priority. */ + last = NULL; while (runp->next_prio != NULL && runp->next_prio->aiocbp->aiocb.__abs_prio >= prio) - runp = runp->next_prio; + { + last = runp; + runp = runp->next_prio; + } newp->next_prio = runp->next_prio; runp->next_prio = newp; @@ -403,6 +407,7 @@ __aio_enqueue_request (aiocb_union *aiocbp, int operation) } newp->next_prio = NULL; + last = NULL; } if (running == yes) @@ -423,7 +428,8 @@ __aio_enqueue_request (aiocb_union *aiocbp, int operation) running = newp->running = allocated; /* Now try to start a thread. */ - if (aio_create_helper_thread (&thid, handle_fildes_io, newp) == 0) + result = aio_create_helper_thread (&thid, handle_fildes_io, newp); + if (result == 0) /* We managed to enqueue the request. All errors which can happen now can be recognized by calls to `aio_return' and `aio_error'. */ @@ -434,10 +440,14 @@ __aio_enqueue_request (aiocb_union *aiocbp, int operation) running = newp->running = yes; if (nthreads == 0) - /* We cannot create a thread in the moment and there is - also no thread running. This is a problem. `errno' is - set to EAGAIN if this is only a temporary problem. */ - result = -1; + { + /* We cannot create a thread in the moment and there is + also no thread running. This is a problem. `errno' is + set to EAGAIN if this is only a temporary problem. */ + __aio_remove_request (last, newp, 0); + } + else + result = 0; } } } @@ -459,6 +469,8 @@ __aio_enqueue_request (aiocb_union *aiocbp, int operation) { /* Something went wrong. */ __aio_free_request (newp); + aiocbp->aiocb.__error_code = result; + __set_errno (result); newp = NULL; } diff --git a/sysdeps/unix/sysv/linux/faccessat.c b/sysdeps/unix/sysv/linux/faccessat.c index 10b903d076..c154deb40f 100644 --- a/sysdeps/unix/sysv/linux/faccessat.c +++ b/sysdeps/unix/sysv/linux/faccessat.c @@ -1,5 +1,5 @@ /* Test for access to file, relative to open directory. Linux version. - Copyright (C) 2006 Free Software Foundation, Inc. + Copyright (C) 2006, 2009 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 @@ -72,6 +72,12 @@ faccessat (fd, file, mode, flag) if (fd != AT_FDCWD && file[0] != '/') { size_t filelen = strlen (file); + if (__builtin_expect (filelen == 0, 0)) + { + __set_errno (ENOENT); + return -1; + } + static const char procfd[] = "/proc/self/fd/%d/%s"; /* Buffer for the path name we are going to use. It consists of - the string /proc/self/fd/ diff --git a/sysdeps/unix/sysv/linux/fchmodat.c b/sysdeps/unix/sysv/linux/fchmodat.c index 8b420153f1..051691230d 100644 --- a/sysdeps/unix/sysv/linux/fchmodat.c +++ b/sysdeps/unix/sysv/linux/fchmodat.c @@ -1,5 +1,5 @@ /* Change the protections of file relative to open directory. Linux version. - Copyright (C) 2006 Free Software Foundation, Inc. + Copyright (C) 2006, 2009 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 @@ -71,6 +71,12 @@ fchmodat (fd, file, mode, flag) if (fd != AT_FDCWD && file[0] != '/') { size_t filelen = strlen (file); + if (__builtin_expect (filelen == 0, 0)) + { + __set_errno (ENOENT); + return -1; + } + static const char procfd[] = "/proc/self/fd/%d/%s"; /* Buffer for the path name we are going to use. It consists of - the string /proc/self/fd/ diff --git a/sysdeps/unix/sysv/linux/fchownat.c b/sysdeps/unix/sysv/linux/fchownat.c index 0f731775b3..db43755694 100644 --- a/sysdeps/unix/sysv/linux/fchownat.c +++ b/sysdeps/unix/sysv/linux/fchownat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006, 2009 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 @@ -66,6 +66,12 @@ fchownat (fd, file, owner, group, flag) if (fd != AT_FDCWD && file[0] != '/') { size_t filelen = strlen (file); + if (__builtin_expect (filelen == 0, 0)) + { + __set_errno (ENOENT); + return -1; + } + static const char procfd[] = "/proc/self/fd/%d/%s"; /* Buffer for the path name we are going to use. It consists of - the string /proc/self/fd/ diff --git a/sysdeps/unix/sysv/linux/fcntl.c b/sysdeps/unix/sysv/linux/fcntl.c index 1f5aca14a4..b19654c625 100644 --- a/sysdeps/unix/sysv/linux/fcntl.c +++ b/sysdeps/unix/sysv/linux/fcntl.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2000, 2002, 2003, 2004, 2009 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 @@ -23,6 +23,40 @@ #include <stdarg.h> #include <sys/syscall.h> +#include <kernel-features.h> + + +#ifdef __ASSUME_F_GETOWN_EX +# define miss_F_GETOWN_EX 0 +#else +static int miss_F_GETOWN_EX; +#endif + + +static int +do_fcntl (int fd, int cmd, void *arg) +{ + if (cmd != F_GETOWN || miss_F_GETOWN_EX) + return INLINE_SYSCALL (fcntl, 3, fd, cmd, arg); + + INTERNAL_SYSCALL_DECL (err); + struct f_owner_ex fex; + int res = INTERNAL_SYSCALL (fcntl, err, 3, fd, F_GETOWN_EX, &fex); + if (!INTERNAL_SYSCALL_ERROR_P (res, err)) + return fex.type == F_OWNER_GID ? -fex.pid : fex.pid; + +#ifndef __ASSUME_F_GETOWN_EX + if (INTERNAL_SYSCALL_ERRNO (res, err) == EINVAL) + { + res = INLINE_SYSCALL (fcntl, 3, fd, F_GETOWN, arg); + miss_F_GETOWN_EX = 1; + return res; + } +#endif + + __set_errno (INTERNAL_SYSCALL_ERRNO (res, err)); + return -1; +} #ifndef NO_CANCELLATION @@ -36,7 +70,7 @@ __fcntl_nocancel (int fd, int cmd, ...) arg = va_arg (ap, void *); va_end (ap); - return INLINE_SYSCALL (fcntl, 3, fd, cmd, arg); + return do_fcntl (fd, cmd, arg); } #endif @@ -52,11 +86,11 @@ __libc_fcntl (int fd, int cmd, ...) va_end (ap); if (SINGLE_THREAD_P || cmd != F_SETLKW) - return INLINE_SYSCALL (fcntl, 3, fd, cmd, arg); + return do_fcntl (fd, cmd, arg); int oldtype = LIBC_CANCEL_ASYNC (); - int result = INLINE_SYSCALL (fcntl, 3, fd, cmd, arg); + int result = do_fcntl (fd, cmd, arg); LIBC_CANCEL_RESET (oldtype); diff --git a/sysdeps/unix/sysv/linux/futimesat.c b/sysdeps/unix/sysv/linux/futimesat.c index 5f3a3f52f3..8292533afb 100644 --- a/sysdeps/unix/sysv/linux/futimesat.c +++ b/sysdeps/unix/sysv/linux/futimesat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006, 2009 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 @@ -61,6 +61,12 @@ futimesat (fd, file, tvp) if (fd != AT_FDCWD && file[0] != '/') { size_t filelen = strlen (file); + if (__builtin_expect (filelen == 0, 0)) + { + __set_errno (ENOENT); + return -1; + } + static const char procfd[] = "/proc/self/fd/%d/%s"; /* Buffer for the path name we are going to use. It consists of - the string /proc/self/fd/ diff --git a/sysdeps/unix/sysv/linux/fxstatat.c b/sysdeps/unix/sysv/linux/fxstatat.c index 1b9add40d7..dd5c9bc684 100644 --- a/sysdeps/unix/sysv/linux/fxstatat.c +++ b/sysdeps/unix/sysv/linux/fxstatat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006, 2007, 2009 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 @@ -85,6 +85,12 @@ __fxstatat (int vers, int fd, const char *file, struct stat *st, int flag) if (fd != AT_FDCWD && file[0] != '/') { size_t filelen = strlen (file); + if (__builtin_expect (filelen == 0, 0)) + { + __set_errno (ENOENT); + return -1; + } + static const char procfd[] = "/proc/self/fd/%d/%s"; /* Buffer for the path name we are going to use. It consists of - the string /proc/self/fd/ diff --git a/sysdeps/unix/sysv/linux/fxstatat64.c b/sysdeps/unix/sysv/linux/fxstatat64.c index cb932b8e59..442e4ca989 100644 --- a/sysdeps/unix/sysv/linux/fxstatat64.c +++ b/sysdeps/unix/sysv/linux/fxstatat64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005,2006 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006, 2009 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 @@ -90,6 +90,12 @@ __fxstatat64 (int vers, int fd, const char *file, struct stat64 *st, int flag) if (fd != AT_FDCWD && file[0] != '/') { size_t filelen = strlen (file); + if (__builtin_expect (filelen == 0, 0)) + { + __set_errno (ENOENT); + return -1; + } + static const char procfd[] = "/proc/self/fd/%d/%s"; /* Buffer for the path name we are going to use. It consists of - the string /proc/self/fd/ diff --git a/sysdeps/unix/sysv/linux/getpt.c b/sysdeps/unix/sysv/linux/getpt.c index bb1ea47643..6b26fdfcdc 100644 --- a/sysdeps/unix/sysv/linux/getpt.c +++ b/sysdeps/unix/sysv/linux/getpt.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. +/* Copyright (C) 1998, 1999, 2001, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998. @@ -64,9 +64,10 @@ __posix_openpt (oflag) } /* If /dev/pts is not mounted then the UNIX98 pseudo terminals - are not usable. */ + are not usable. */ __close (fd); have_no_dev_ptmx = 1; + __set_errno (ENOENT); } else { @@ -76,6 +77,8 @@ __posix_openpt (oflag) return -1; } } + else + __set_errno (ENOENT); return -1; } diff --git a/sysdeps/unix/sysv/linux/i386/bits/fcntl.h b/sysdeps/unix/sysv/linux/i386/bits/fcntl.h index 35ef665998..d1718a17c9 100644 --- a/sysdeps/unix/sysv/linux/i386/bits/fcntl.h +++ b/sysdeps/unix/sysv/linux/i386/bits/fcntl.h @@ -1,5 +1,5 @@ /* O_*, F_*, FD_* bit values for Linux. - Copyright (C) 1995, 1996, 1997, 1998, 2000, 2004, 2006, 2007 + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2004, 2006, 2007, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -166,6 +166,23 @@ struct flock64 }; #endif +#ifdef __USE_GNU +/* Owner types. */ +enum __pid_type + { + F_OWNER_TID = 0, /* Kernel thread. */ + F_OWNER_PID, /* Process. */ + F_OWNER_GID /* Process group. */ + }; + +/* Structure to use with F_GETOWN_EX and F_SETOWN_EX. */ +struct f_owner_ex + { + enum __pid_type type; /* Owner type of ID. */ + __pid_t pid; /* ID of owner. */ + }; +#endif + /* Define some more compatibility macros to be backward compatible with BSD systems which did not managed to hide these kernel macros. */ #ifdef __USE_BSD diff --git a/sysdeps/unix/sysv/linux/i386/fchownat.c b/sysdeps/unix/sysv/linux/i386/fchownat.c index 34acf10c27..1b02fde459 100644 --- a/sysdeps/unix/sysv/linux/i386/fchownat.c +++ b/sysdeps/unix/sysv/linux/i386/fchownat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006, 2009 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 @@ -63,6 +63,12 @@ fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag) if (fd != AT_FDCWD && file[0] != '/') { size_t filelen = strlen (file); + if (__builtin_expect (filelen == 0, 0)) + { + __set_errno (ENOENT); + return -1; + } + static const char procfd[] = "/proc/self/fd/%d/%s"; /* Buffer for the path name we are going to use. It consists of - the string /proc/self/fd/ diff --git a/sysdeps/unix/sysv/linux/i386/fcntl.c b/sysdeps/unix/sysv/linux/i386/fcntl.c index b27373d24b..5544d6e0d9 100644 --- a/sysdeps/unix/sysv/linux/i386/fcntl.c +++ b/sysdeps/unix/sysv/linux/i386/fcntl.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000,2002,2003,2004,2006 Free Software Foundation, Inc. +/* Copyright (C) 2000,2002,2003,2004,2006,2009 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 @@ -30,6 +30,13 @@ int __have_no_fcntl64; #endif +#ifdef __ASSUME_F_GETOWN_EX +# define miss_F_GETOWN_EX 0 +#else +static int miss_F_GETOWN_EX; +#endif + + #if defined NO_CANCELLATION && __ASSUME_FCNTL64 == 0 # define __fcntl_nocancel __libc_fcntl #endif @@ -119,6 +126,26 @@ __fcntl_nocancel (int fd, int cmd, ...) assert (F_SETLK - F_SETLKW == F_SETLK64 - F_SETLKW64); return INLINE_SYSCALL (fcntl, 3, fd, cmd + F_SETLK - F_SETLK64, &fl); } + case F_GETOWN: + if (! miss_F_GETOWN_EX) + { + INTERNAL_SYSCALL_DECL (err); + struct f_owner_ex fex; + int res = INTERNAL_SYSCALL (fcntl, err, 3, fd, F_GETOWN_EX, &fex); + if (!INTERNAL_SYSCALL_ERROR_P (res, err)) + return fex.type == F_OWNER_GID ? -fex.pid : fex.pid; + +#ifndef __ASSUME_F_GETOWN_EX + if (INTERNAL_SYSCALL_ERRNO (res, err) == EINVAL) + miss_F_GETOWN_EX = 1; + else +#endif + { + __set_errno (INTERNAL_SYSCALL_ERRNO (res, err)); + return -1; + } + } + /* FALLTHROUGH */ default: return INLINE_SYSCALL (fcntl, 3, fd, cmd, arg); } diff --git a/sysdeps/unix/sysv/linux/i386/fxstatat.c b/sysdeps/unix/sysv/linux/i386/fxstatat.c index 94f6e81186..37757937b3 100644 --- a/sysdeps/unix/sysv/linux/i386/fxstatat.c +++ b/sysdeps/unix/sysv/linux/i386/fxstatat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006, 2009 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 @@ -86,6 +86,12 @@ __fxstatat (int vers, int fd, const char *file, struct stat *st, int flag) if (fd != AT_FDCWD && file[0] != '/') { size_t filelen = strlen (file); + if (__builtin_expect (filelen == 0, 0)) + { + __set_errno (ENOENT); + return -1; + } + static const char procfd[] = "/proc/self/fd/%d/%s"; /* Buffer for the path name we are going to use. It consists of - the string /proc/self/fd/ diff --git a/sysdeps/unix/sysv/linux/ia64/bits/fcntl.h b/sysdeps/unix/sysv/linux/ia64/bits/fcntl.h index 6abc5ced65..9e11f648f8 100644 --- a/sysdeps/unix/sysv/linux/ia64/bits/fcntl.h +++ b/sysdeps/unix/sysv/linux/ia64/bits/fcntl.h @@ -1,5 +1,5 @@ /* O_*, F_*, FD_* bit values for Linux/IA64. - Copyright (C) 1999, 2000, 2004, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 1999,2000,2004,2006,2007,2009 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 @@ -159,6 +159,23 @@ struct flock64 }; #endif +#ifdef __USE_GNU +/* Owner types. */ +enum __pid_type + { + F_OWNER_TID = 0, /* Kernel thread. */ + F_OWNER_PID, /* Process. */ + F_OWNER_GID /* Process group. */ + }; + +/* Structure to use with F_GETOWN_EX and F_SETOWN_EX. */ +struct f_owner_ex + { + enum __pid_type type; /* Owner type of ID. */ + __pid_t pid; /* ID of owner. */ + }; +#endif + /* Define some more compatibility macros to be backward compatible with BSD systems which did not managed to hide these kernel macros. */ diff --git a/sysdeps/unix/sysv/linux/ia64/bits/siginfo.h b/sysdeps/unix/sysv/linux/ia64/bits/siginfo.h index 66310c65b3..240ebbc9e1 100644 --- a/sysdeps/unix/sysv/linux/ia64/bits/siginfo.h +++ b/sysdeps/unix/sysv/linux/ia64/bits/siginfo.h @@ -1,5 +1,5 @@ /* siginfo_t, sigevent and constants. Linux/ia64 version. - Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2000-2004, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by David Mosberger-Tang <davidm@hpl.hp.com>. @@ -310,6 +310,10 @@ typedef struct sigevent { int _pad[__SIGEV_PAD_SIZE]; + /* When SIGEV_SIGNAL and SIGEV_THREAD_ID set, LWP ID of the + thread to receive the signal. */ + __pid_t _tid; + struct { void (*_function) (sigval_t); /* Function to start. */ diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h index ff065effb5..f48e644e09 100644 --- a/sysdeps/unix/sysv/linux/kernel-features.h +++ b/sysdeps/unix/sysv/linux/kernel-features.h @@ -542,3 +542,8 @@ # define __ASSUME_PREADV 1 # define __ASSUME_PWRITEV 1 #endif + +/* Support for F_GETOWN_EX was introduced in 2.6.32. */ +#if __LINUX_KERNEL_VERSION >= 0x020620 +# define __ASSUME_F_GETOWN_EX 1 +#endif diff --git a/sysdeps/unix/sysv/linux/linkat.c b/sysdeps/unix/sysv/linux/linkat.c index cfd0e18223..b2b7b0386b 100644 --- a/sysdeps/unix/sysv/linux/linkat.c +++ b/sysdeps/unix/sysv/linux/linkat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006, 2009 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 @@ -66,6 +66,12 @@ linkat (fromfd, from, tofd, to, flags) if (fromfd != AT_FDCWD && from[0] != '/') { size_t filelen = strlen (from); + if (__builtin_expect (filelen == 0, 0)) + { + __set_errno (ENOENT); + return -1; + } + /* Buffer for the path name we are going to use. It consists of - the string /proc/self/fd/ - the file descriptor number diff --git a/sysdeps/unix/sysv/linux/mkdirat.c b/sysdeps/unix/sysv/linux/mkdirat.c index 3c190085ce..aa89d08730 100644 --- a/sysdeps/unix/sysv/linux/mkdirat.c +++ b/sysdeps/unix/sysv/linux/mkdirat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006, 2009 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 @@ -57,6 +57,12 @@ mkdirat (fd, file, mode) if (fd != AT_FDCWD && file[0] != '/') { size_t filelen = strlen (file); + if (__builtin_expect (filelen == 0, 0)) + { + __set_errno (ENOENT); + return -1; + } + static const char procfd[] = "/proc/self/fd/%d/%s"; /* Buffer for the path name we are going to use. It consists of - the string /proc/self/fd/ diff --git a/sysdeps/unix/sysv/linux/openat.c b/sysdeps/unix/sysv/linux/openat.c index 45b566f2d0..7916c71105 100644 --- a/sysdeps/unix/sysv/linux/openat.c +++ b/sysdeps/unix/sysv/linux/openat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006, 2007, 2009 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 @@ -110,6 +110,12 @@ OPENAT_NOT_CANCEL (fd, file, oflag, mode) if (fd != AT_FDCWD && file[0] != '/') { size_t filelen = strlen (file); + if (__builtin_expect (filelen == 0, 0)) + { + __set_errno (ENOENT); + return -1; + } + static const char procfd[] = "/proc/self/fd/%d/%s"; /* Buffer for the path name we are going to use. It consists of - the string /proc/self/fd/ diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/fcntl.h b/sysdeps/unix/sysv/linux/powerpc/bits/fcntl.h index 90b669ab60..dc2e0e6201 100644 --- a/sysdeps/unix/sysv/linux/powerpc/bits/fcntl.h +++ b/sysdeps/unix/sysv/linux/powerpc/bits/fcntl.h @@ -1,5 +1,5 @@ /* O_*, F_*, FD_* bit values for Linux/PowerPC. - Copyright (C) 1995, 1996, 1997, 1998, 2000, 2003, 2004, 2006, 2007 + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2003, 2004, 2006, 2007, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -166,6 +166,23 @@ struct flock64 }; #endif +#ifdef __USE_GNU +/* Owner types. */ +enum __pid_type + { + F_OWNER_TID = 0, /* Kernel thread. */ + F_OWNER_PID, /* Process. */ + F_OWNER_GID /* Process group. */ + }; + +/* Structure to use with F_GETOWN_EX and F_SETOWN_EX. */ +struct f_owner_ex + { + enum __pid_type type; /* Owner type of ID. */ + __pid_t pid; /* ID of owner. */ + }; +#endif + /* Define some more compatibility macros to be backward compatible with BSD systems which did not managed to hide these kernel macros. */ #ifdef __USE_BSD diff --git a/sysdeps/unix/sysv/linux/powerpc/fchownat.c b/sysdeps/unix/sysv/linux/powerpc/fchownat.c index 67c570648a..46f6d97c6b 100644 --- a/sysdeps/unix/sysv/linux/powerpc/fchownat.c +++ b/sysdeps/unix/sysv/linux/powerpc/fchownat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006, 2009 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 @@ -66,6 +66,12 @@ fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag) if (fd != AT_FDCWD && file[0] != '/') { size_t filelen = strlen (file); + if (__builtin_expect (filelen == 0, 0)) + { + __set_errno (ENOENT); + return -1; + } + static const char procfd[] = "/proc/self/fd/%d/%s"; /* Buffer for the path name we are going to use. It consists of - the string /proc/self/fd/ diff --git a/sysdeps/unix/sysv/linux/readlinkat.c b/sysdeps/unix/sysv/linux/readlinkat.c index 1361596503..55abff143d 100644 --- a/sysdeps/unix/sysv/linux/readlinkat.c +++ b/sysdeps/unix/sysv/linux/readlinkat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006, 2009 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 @@ -59,6 +59,12 @@ readlinkat (fd, path, buf, len) if (fd != AT_FDCWD && path[0] != '/') { size_t pathlen = strlen (path); + if (__builtin_expect (pathlen == 0, 0)) + { + __set_errno (ENOENT); + return -1; + } + static const char procfd[] = "/proc/self/fd/%d/%s"; /* Buffer for the path name we are going to use. It consists of - the string /proc/self/fd/ diff --git a/sysdeps/unix/sysv/linux/renameat.c b/sysdeps/unix/sysv/linux/renameat.c index 86bb75a7b0..160bdc4903 100644 --- a/sysdeps/unix/sysv/linux/renameat.c +++ b/sysdeps/unix/sysv/linux/renameat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006, 2009 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 @@ -135,6 +135,12 @@ renameat (oldfd, old, newfd, new) if (oldfd != AT_FDCWD && old[0] != '/') { size_t filelen = strlen (old); + if (__builtin_expect (filelen == 0, 0)) + { + __set_errno (ENOENT); + return -1; + } + /* Buffer for the path name we are going to use. It consists of - the string /proc/self/fd/ - the file descriptor number @@ -154,6 +160,12 @@ renameat (oldfd, old, newfd, new) if (newfd != AT_FDCWD && new[0] != '/') { size_t filelen = strlen (new); + if (__builtin_expect (filelen == 0, 0)) + { + __set_errno (ENOENT); + return -1; + } + /* Buffer for the path name we are going to use. It consists of - the string /proc/self/fd/ - the file descriptor number diff --git a/sysdeps/unix/sysv/linux/s390/bits/fcntl.h b/sysdeps/unix/sysv/linux/s390/bits/fcntl.h index ff5941df65..b50c00c882 100644 --- a/sysdeps/unix/sysv/linux/s390/bits/fcntl.h +++ b/sysdeps/unix/sysv/linux/s390/bits/fcntl.h @@ -1,5 +1,5 @@ /* O_*, F_*, FD_* bit values for Linux. - Copyright (C) 2000,2001,2002,2004,2006,2007 Free Software Foundation, Inc. + Copyright (C) 2000,2001,2002,2004,2006,2007,2009 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 @@ -181,6 +181,23 @@ struct flock64 }; #endif +#ifdef __USE_GNU +/* Owner types. */ +enum __pid_type + { + F_OWNER_TID = 0, /* Kernel thread. */ + F_OWNER_PID, /* Process. */ + F_OWNER_GID /* Process group. */ + }; + +/* Structure to use with F_GETOWN_EX and F_SETOWN_EX. */ +struct f_owner_ex + { + enum __pid_type type; /* Owner type of ID. */ + __pid_t pid; /* ID of owner. */ + }; +#endif + /* Define some more compatibility macros to be backward compatible with BSD systems which did not managed to hide these kernel macros. */ #ifdef __USE_BSD diff --git a/sysdeps/unix/sysv/linux/s390/bits/siginfo.h b/sysdeps/unix/sysv/linux/s390/bits/siginfo.h index 0b79853137..55b3f88c0a 100644 --- a/sysdeps/unix/sysv/linux/s390/bits/siginfo.h +++ b/sysdeps/unix/sysv/linux/s390/bits/siginfo.h @@ -1,5 +1,5 @@ /* siginfo_t, sigevent and constants. S/390 version. - Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 2001, 2002, 2003, 2009 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 @@ -26,7 +26,7 @@ #if (!defined __have_sigval_t \ && (defined _SIGNAL_H || defined __need_siginfo_t \ - || defined __need_sigevent_t)) + || defined __need_sigevent_t)) # define __have_sigval_t 1 /* Type for data associated with a signal. */ @@ -96,7 +96,7 @@ typedef struct siginfo struct { void *si_addr; /* Faulting insn/memory ref. */ - int si_trapno; + int si_trapno; } _sigfault; /* SIGPOLL. */ @@ -282,6 +282,10 @@ typedef struct sigevent { int _pad[__SIGEV_PAD_SIZE]; + /* When SIGEV_SIGNAL and SIGEV_THREAD_ID set, LWP ID of the + thread to receive the signal. */ + __pid_t _tid; + struct { void (*_function) (sigval_t); /* Function to start. */ diff --git a/sysdeps/unix/sysv/linux/sh/bits/fcntl.h b/sysdeps/unix/sysv/linux/sh/bits/fcntl.h index 35ef665998..d1718a17c9 100644 --- a/sysdeps/unix/sysv/linux/sh/bits/fcntl.h +++ b/sysdeps/unix/sysv/linux/sh/bits/fcntl.h @@ -1,5 +1,5 @@ /* O_*, F_*, FD_* bit values for Linux. - Copyright (C) 1995, 1996, 1997, 1998, 2000, 2004, 2006, 2007 + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2004, 2006, 2007, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -166,6 +166,23 @@ struct flock64 }; #endif +#ifdef __USE_GNU +/* Owner types. */ +enum __pid_type + { + F_OWNER_TID = 0, /* Kernel thread. */ + F_OWNER_PID, /* Process. */ + F_OWNER_GID /* Process group. */ + }; + +/* Structure to use with F_GETOWN_EX and F_SETOWN_EX. */ +struct f_owner_ex + { + enum __pid_type type; /* Owner type of ID. */ + __pid_t pid; /* ID of owner. */ + }; +#endif + /* Define some more compatibility macros to be backward compatible with BSD systems which did not managed to hide these kernel macros. */ #ifdef __USE_BSD diff --git a/sysdeps/unix/sysv/linux/sparc/bits/fcntl.h b/sysdeps/unix/sysv/linux/sparc/bits/fcntl.h index d59744a55e..648bea8e58 100644 --- a/sysdeps/unix/sysv/linux/sparc/bits/fcntl.h +++ b/sysdeps/unix/sysv/linux/sparc/bits/fcntl.h @@ -1,5 +1,5 @@ /* O_*, F_*, FD_* bit values for Linux/SPARC. - Copyright (C) 1995, 1996, 1997, 1998, 2000, 2003, 2004, 2006, 2007 + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2003, 2004, 2006, 2007, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -185,6 +185,23 @@ struct flock64 }; #endif +#ifdef __USE_GNU +/* Owner types. */ +enum __pid_type + { + F_OWNER_TID = 0, /* Kernel thread. */ + F_OWNER_PID, /* Process. */ + F_OWNER_GID /* Process group. */ + }; + +/* Structure to use with F_GETOWN_EX and F_SETOWN_EX. */ +struct f_owner_ex + { + enum __pid_type type; /* Owner type of ID. */ + __pid_t pid; /* ID of owner. */ + }; +#endif + /* Define some more compatibility macros to be backward compatible with BSD systems which did not managed to hide these kernel macros. */ #ifdef __USE_BSD diff --git a/sysdeps/unix/sysv/linux/symlinkat.c b/sysdeps/unix/sysv/linux/symlinkat.c index 4cfc924bfc..d2704777bd 100644 --- a/sysdeps/unix/sysv/linux/symlinkat.c +++ b/sysdeps/unix/sysv/linux/symlinkat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006, 2009 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 @@ -57,6 +57,12 @@ symlinkat (from, tofd, to) if (tofd != AT_FDCWD && to[0] != '/') { size_t tolen = strlen (to); + if (__builtin_expect (tolen == 0, 0)) + { + __set_errno (ENOENT); + return -1; + } + static const char procfd[] = "/proc/self/fd/%d/%s"; /* Buffer for the path name we are going to use. It consists of - the string /proc/self/fd/ diff --git a/sysdeps/unix/sysv/linux/ttyname.c b/sysdeps/unix/sysv/linux/ttyname.c index 1b79787515..69af6adc65 100644 --- a/sysdeps/unix/sysv/linux/ttyname.c +++ b/sysdeps/unix/sysv/linux/ttyname.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991,92,93,1996-2002,2006 Free Software Foundation, Inc. +/* Copyright (C) 1991,92,93,1996-2002,2006,2009 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 @@ -59,6 +59,11 @@ getttyname (const char *dev, dev_t mydev, ino64_t myino, int save, int *dostat) return NULL; } + /* Prepare for the loop. If we already have a buffer copy the directory + name we look at into it. */ + if (devlen < namelen) + *((char *) __mempcpy (getttyname_name, dev, devlen - 1)) = '/'; + while ((d = __readdir64 (dirstream)) != NULL) if ((d->d_fileno == myino || *dostat) && strcmp (d->d_name, "stdin") diff --git a/sysdeps/unix/sysv/linux/unlinkat.c b/sysdeps/unix/sysv/linux/unlinkat.c index 0a07a8a875..bb5f89810b 100644 --- a/sysdeps/unix/sysv/linux/unlinkat.c +++ b/sysdeps/unix/sysv/linux/unlinkat.c @@ -1,5 +1,5 @@ /* unlinkat -- Remove a link by relative name. - Copyright (C) 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 2005, 2006, 2009 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 @@ -64,6 +64,12 @@ unlinkat (fd, file, flag) if (fd != AT_FDCWD && file[0] != '/') { size_t filelen = strlen (file); + if (__builtin_expect (filelen == 0, 0)) + { + __set_errno (ENOENT); + return -1; + } + static const char procfd[] = "/proc/self/fd/%d/%s"; /* Buffer for the path name we are going to use. It consists of - the string /proc/self/fd/ diff --git a/sysdeps/unix/sysv/linux/wordsize-64/fxstatat.c b/sysdeps/unix/sysv/linux/wordsize-64/fxstatat.c index 8b1c932ba9..cc41fdedc0 100644 --- a/sysdeps/unix/sysv/linux/wordsize-64/fxstatat.c +++ b/sysdeps/unix/sysv/linux/wordsize-64/fxstatat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006, 2009 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 @@ -72,6 +72,12 @@ __fxstatat (int vers, int fd, const char *file, struct stat *st, int flag) if (fd != AT_FDCWD && file[0] != '/') { size_t filelen = strlen (file); + if (__builtin_expect (filelen == 0, 0)) + { + __set_errno (ENOENT); + return -1; + } + static const char procfd[] = "/proc/self/fd/%d/%s"; /* Buffer for the path name we are going to use. It consists of - the string /proc/self/fd/ diff --git a/sysdeps/unix/sysv/linux/x86_64/bits/fcntl.h b/sysdeps/unix/sysv/linux/x86_64/bits/fcntl.h index bc0f4d687b..e9806ee004 100644 --- a/sysdeps/unix/sysv/linux/x86_64/bits/fcntl.h +++ b/sysdeps/unix/sysv/linux/x86_64/bits/fcntl.h @@ -1,5 +1,5 @@ /* O_*, F_*, FD_* bit values for Linux/x86-64. - Copyright (C) 2001, 2002, 2004, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 2001,2002,2004,2006,2007,2009 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 @@ -180,6 +180,23 @@ struct flock64 }; #endif +#ifdef __USE_GNU +/* Owner types. */ +enum __pid_type + { + F_OWNER_TID = 0, /* Kernel thread. */ + F_OWNER_PID, /* Process. */ + F_OWNER_GID /* Process group. */ + }; + +/* Structure to use with F_GETOWN_EX and F_SETOWN_EX. */ +struct f_owner_ex + { + enum __pid_type type; /* Owner type of ID. */ + __pid_t pid; /* ID of owner. */ + }; +#endif + /* Define some more compatibility macros to be backward compatible with BSD systems which did not managed to hide these kernel macros. */ #ifdef __USE_BSD diff --git a/sysdeps/unix/sysv/linux/xmknodat.c b/sysdeps/unix/sysv/linux/xmknodat.c index ef27b686cc..177b3db986 100644 --- a/sysdeps/unix/sysv/linux/xmknodat.c +++ b/sysdeps/unix/sysv/linux/xmknodat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006, 2009 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 @@ -72,6 +72,12 @@ __xmknodat (int vers, int fd, const char *file, mode_t mode, dev_t *dev) if (fd != AT_FDCWD && file[0] != '/') { size_t filelen = strlen (file); + if (__builtin_expect (filelen == 0, 0)) + { + __set_errno (ENOENT); + return -1; + } + static const char procfd[] = "/proc/self/fd/%d/%s"; /* Buffer for the path name we are going to use. It consists of - the string /proc/self/fd/ diff --git a/sysdeps/x86_64/multiarch/Makefile b/sysdeps/x86_64/multiarch/Makefile index 0ded3b3261..364e7bbbd2 100644 --- a/sysdeps/x86_64/multiarch/Makefile +++ b/sysdeps/x86_64/multiarch/Makefile @@ -4,7 +4,8 @@ gen-as-const-headers += ifunc-defines.sym endif ifeq ($(subdir),string) -sysdep_routines += stpncpy-c strncpy-c strcmp-ssse3 strncmp-ssse3 +sysdep_routines += stpncpy-c strncpy-c strcmp-ssse3 strncmp-ssse3 \ + strend-sse4 ifeq (yes,$(config-cflags-sse4)) sysdep_routines += strcspn-c strpbrk-c strspn-c strstr-c strcasestr-c CFLAGS-strcspn-c.c += -msse4 diff --git a/sysdeps/x86_64/multiarch/strchr.S b/sysdeps/x86_64/multiarch/strchr.S new file mode 100644 index 0000000000..b35566d1a5 --- /dev/null +++ b/sysdeps/x86_64/multiarch/strchr.S @@ -0,0 +1,177 @@ +/* strchr with SSE4.2 + Copyright (C) 2009 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <ifunc-defines.h> + + +/* Define multiple versions only for the definition in libc. */ +#ifndef NOT_IN_libc + .text +ENTRY(strchr) + .type strchr, @gnu_indirect_function + cmpl $0, __cpu_features+KIND_OFFSET(%rip) + jne 1f + call __init_cpu_features +1: leaq __strchr_sse2(%rip), %rax + testl $(1<<20), __cpu_features+CPUID_OFFSET+COMMON_CPUID_INDEX_1*CPUID_SIZE+CPUID_ECX_OFFSET(%rip) + jz 2f + leaq __strchr_sse42(%rip), %rax +2: ret +END(strchr) + + +/* + This implementation uses SSE4 instructions to compare up to 16 bytes + at a time looking for the first occurrence of the character c in the + string s: + + char *strchr (const char *s, int c); + + We use 0xa: + _SIDD_SBYTE_OPS + | _SIDD_CMP_EQUAL_EACH + | _SIDD_LEAST_SIGNIFICANT + on pcmpistri to compare xmm/mem128 + + 0 1 2 3 4 5 6 7 8 9 A B C D E F + X X X X X X X X X X X X X X X X + + against xmm + + 0 1 2 3 4 5 6 7 8 9 A B C D E F + C C C C C C C C C C C C C C C C + + to find out if the first 16byte data element has a byte C and the + offset of the first byte. There are 3 cases: + + 1. The first 16byte data element has the byte C at the offset X. + 2. The first 16byte data element has EOS and doesn't have the byte C. + 3. The first 16byte data element is valid and doesn't have the byte C. + + Here is the table of ECX, CFlag, ZFlag and SFlag for 3 cases: + + case ECX CFlag ZFlag SFlag + 1 X 1 0/1 0 + 2 16 0 1 0 + 3 16 0 0 0 + + We exit from the loop for cases 1 and 2 with jbe which branches + when either CFlag or ZFlag is 1. If CFlag == 1, ECX has the offset + X for case 1. */ + + .section .text.sse4.2,"ax",@progbits + .align 16 + .type __strchr_sse42, @function +__strchr_sse42: + cfi_startproc + CALL_MCOUNT + testb %sil, %sil + je __strend_sse4 + pxor %xmm2, %xmm2 + movd %esi, %xmm1 + movl %edi, %ecx + andl $15, %ecx + movq %rdi, %r8 + je L(aligned_start) + +/* Handle unaligned string. */ + andq $-16, %r8 + pshufb %xmm2, %xmm1 + movdqa (%r8), %xmm0 + pcmpeqb %xmm0, %xmm2 + pcmpeqb %xmm1, %xmm0 + /* Find where NULL is. */ + pmovmskb %xmm2, %edx + /* Check if there is a match. */ + pmovmskb %xmm0, %esi + /* Remove the leading bytes. */ + sarl %cl, %edx + sarl %cl, %esi + testl %esi, %esi + je L(unaligned_no_match) + /* Check which byte is a match. */ + bsfl %esi, %eax + /* Is there a NULL? */ + testl %edx, %edx + je L(unaligned_match) + bsfl %edx, %esi + cmpl %esi, %eax + /* Return NULL if NULL comes first. */ + ja L(return_null) +L(unaligned_match): + addq %rdi, %rax + ret + + .p2align 4 +L(unaligned_no_match): + testl %edx, %edx + jne L(return_null) + +/* Loop start on aligned string. */ +L(loop): + addq $16, %r8 +L(aligned_start): + pcmpistri $0x2, (%r8), %xmm1 + jbe L(wrap) + addq $16, %r8 + pcmpistri $0x2, (%r8), %xmm1 + jbe L(wrap) + addq $16, %r8 + pcmpistri $0x2, (%r8), %xmm1 + jbe L(wrap) + addq $16, %r8 + pcmpistri $0x2, (%r8), %xmm1 + jbe L(wrap) + jmp L(loop) +L(wrap): + jc L(loop_exit) + +/* Return NULL. */ +L(return_null): + xorl %eax, %eax + ret + +/* Loop exit. */ + .p2align 4 +L(loop_exit): + leaq (%r8,%rcx), %rax + ret + cfi_endproc + .size __strchr_sse42, .-__strchr_sse42 + + +# undef ENTRY +# define ENTRY(name) \ + .type __strchr_sse2, @function; \ + .align 16; \ + __strchr_sse2: cfi_startproc; \ + CALL_MCOUNT +# undef END +# define END(name) \ + cfi_endproc; .size __strchr_sse2, .-__strchr_sse2 +# undef libc_hidden_builtin_def +/* It doesn't make sense to send libc-internal strchr calls through a PLT. + The speedup we get from using SSE4.2 instruction is likely eaten away + by the indirect call in the PLT. */ +# define libc_hidden_builtin_def(name) \ + .globl __GI_strchr; __GI_strchr = __strchr_sse2 +#endif + +#include "../strchr.S" diff --git a/sysdeps/x86_64/multiarch/strend-sse4.S b/sysdeps/x86_64/multiarch/strend-sse4.S new file mode 100644 index 0000000000..c3220b3386 --- /dev/null +++ b/sysdeps/x86_64/multiarch/strend-sse4.S @@ -0,0 +1,49 @@ +/* Return the pointer to the end of string, using SSE4.2 + Copyright (C) 2009 Free Software Foundation, Inc. + Contributed by Intel Corporation. + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include "asm-syntax.h" + + .section .text.sse4.2,"ax",@progbits +ENTRY (__strend_sse4) + pxor %xmm2, %xmm2 + movq %rdi, %rcx + andq $~15, %rdi + movdqa %xmm2, %xmm1 + pcmpeqb (%rdi), %xmm2 + orl $0xffffffff, %esi + subq %rdi, %rcx + shll %cl, %esi + pmovmskb %xmm2, %edx + andl %esi, %edx + jnz 1f + +2: pcmpistri $0x08, 16(%rdi), %xmm1 + leaq 16(%rdi), %rdi + jnz 2b + + leaq (%rdi,%rcx), %rax + ret + +1: bsfl %edx, %eax + addq %rdi, %rax + ret + +END (__strend_sse4) diff --git a/sysdeps/x86_64/multiarch/strrchr.S b/sysdeps/x86_64/multiarch/strrchr.S new file mode 100644 index 0000000000..f6665f34b7 --- /dev/null +++ b/sysdeps/x86_64/multiarch/strrchr.S @@ -0,0 +1,278 @@ +/* strrchr with SSE4.2 + Copyright (C) 2009 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <ifunc-defines.h> + + +/* Define multiple versions only for the definition in libc and for + the DSO. In static binaries we need strrchr before the initialization + happened. */ +#if defined SHARED && !defined NOT_IN_libc + .text +ENTRY(strrchr) + .type strrchr, @gnu_indirect_function + cmpl $0, __cpu_features+KIND_OFFSET(%rip) + jne 1f + call __init_cpu_features +1: leaq __strrchr_sse2(%rip), %rax + testl $(1<<20), __cpu_features+CPUID_OFFSET+COMMON_CPUID_INDEX_1*CPUID_SIZE+CPUID_ECX_OFFSET(%rip) + jz 2f + leaq __strrchr_sse42(%rip), %rax +2: ret +END(strrchr) + +/* + This implementation uses SSE4 instructions to compare up to 16 bytes + at a time looking for the last occurrence of the character c in the + string s: + + char *strrchr (const char *s, int c); + + We use 0x4a: + _SIDD_SBYTE_OPS + | _SIDD_CMP_EQUAL_EACH + | _SIDD_MOST_SIGNIFICANT + on pcmpistri to compare xmm/mem128 + + 0 1 2 3 4 5 6 7 8 9 A B C D E F + X X X X X X X X X X X X X X X X + + against xmm + + 0 1 2 3 4 5 6 7 8 9 A B C D E F + C C C C C C C C C C C C C C C C + + to find out if the first 16byte data element has a byte C and the + last offset. There are 4 cases: + + 1. The first 16byte data element has EOS and has the byte C at the + last offset X. + 2. The first 16byte data element is valid and has the byte C at the + last offset X. + 3. The first 16byte data element has EOS and doesn't have the byte C. + 4. The first 16byte data element is valid and doesn't have the byte C. + + Here is the table of ECX, CFlag, ZFlag and SFlag for 3 cases: + + case ECX CFlag ZFlag SFlag + 1 X 1 1 0 + 2 X 1 0 0 + 3 16 0 1 0 + 4 16 0 0 0 + + We exit from the loop for cases 1 and 3 with jz which branches + when ZFlag is 1. If CFlag == 1, ECX has the offset X for case 1. */ + + + .section .text.sse4.2,"ax",@progbits + .align 16 + .type __strrchr_sse42, @function +__strrchr_sse42: + cfi_startproc + CALL_MCOUNT + testb %sil, %sil + je __strend_sse4 + xor %eax,%eax /* RAX has the last occurrence of s. */ + movd %esi, %xmm1 + punpcklbw %xmm1, %xmm1 + movl %edi, %esi + punpcklbw %xmm1, %xmm1 + andl $15, %esi + pshufd $0, %xmm1, %xmm1 + movq %rdi, %r8 + je L(loop) + +/* Handle unaligned string using psrldq. */ + leaq L(psrldq_table)(%rip), %rdx + andq $-16, %r8 + movslq (%rdx,%rsi,4),%r9 + movdqa (%r8), %xmm0 + addq %rdx, %r9 + jmp *%r9 + +/* Handle unaligned string with offset 1 using psrldq. */ + .p2align 4 +L(psrldq_1): + psrldq $1, %xmm0 + + .p2align 4 +L(unaligned_pcmpistri): + pcmpistri $0x4a, %xmm1, %xmm0 + jnc L(unaligned_no_byte) + leaq (%rdi,%rcx), %rax +L(unaligned_no_byte): + /* Find the length of the unaligned string. */ + pcmpistri $0x3a, %xmm0, %xmm0 + movl $16, %edx + subl %esi, %edx + cmpl %ecx, %edx + /* Return RAX if the unaligned fragment to next 16B already + contain the NULL terminator. */ + jg L(exit) + addq $16, %r8 + +/* Loop start on aligned string. */ + .p2align 4 +L(loop): + pcmpistri $0x4a, (%r8), %xmm1 + jbe L(match_or_eos) + addq $16, %r8 + jmp L(loop) + .p2align 4 +L(match_or_eos): + je L(had_eos) +L(match_no_eos): + leaq (%r8,%rcx), %rax + addq $16, %r8 + jmp L(loop) + .p2align 4 +L(had_eos): + jnc L(exit) + leaq (%r8,%rcx), %rax + .p2align 4 +L(exit): + ret + +/* Handle unaligned string with offset 15 using psrldq. */ + .p2align 4 +L(psrldq_15): + psrldq $15, %xmm0 + jmp L(unaligned_pcmpistri) + +/* Handle unaligned string with offset 14 using psrldq. */ + .p2align 4 +L(psrldq_14): + psrldq $14, %xmm0 + jmp L(unaligned_pcmpistri) + +/* Handle unaligned string with offset 13 using psrldq. */ + .p2align 4 +L(psrldq_13): + psrldq $13, %xmm0 + jmp L(unaligned_pcmpistri) + +/* Handle unaligned string with offset 12 using psrldq. */ + .p2align 4 +L(psrldq_12): + psrldq $12, %xmm0 + jmp L(unaligned_pcmpistri) + +/* Handle unaligned string with offset 11 using psrldq. */ + .p2align 4 +L(psrldq_11): + psrldq $11, %xmm0 + jmp L(unaligned_pcmpistri) + +/* Handle unaligned string with offset 10 using psrldq. */ + .p2align 4 +L(psrldq_10): + psrldq $10, %xmm0 + jmp L(unaligned_pcmpistri) + +/* Handle unaligned string with offset 9 using psrldq. */ + .p2align 4 +L(psrldq_9): + psrldq $9, %xmm0 + jmp L(unaligned_pcmpistri) + +/* Handle unaligned string with offset 8 using psrldq. */ + .p2align 4 +L(psrldq_8): + psrldq $8, %xmm0 + jmp L(unaligned_pcmpistri) + +/* Handle unaligned string with offset 7 using psrldq. */ + .p2align 4 +L(psrldq_7): + psrldq $7, %xmm0 + jmp L(unaligned_pcmpistri) + +/* Handle unaligned string with offset 6 using psrldq. */ + .p2align 4 +L(psrldq_6): + psrldq $6, %xmm0 + jmp L(unaligned_pcmpistri) + +/* Handle unaligned string with offset 5 using psrldq. */ + .p2align 4 +L(psrldq_5): + psrldq $5, %xmm0 + jmp L(unaligned_pcmpistri) + +/* Handle unaligned string with offset 4 using psrldq. */ + .p2align 4 +L(psrldq_4): + psrldq $4, %xmm0 + jmp L(unaligned_pcmpistri) + +/* Handle unaligned string with offset 3 using psrldq. */ + .p2align 4 +L(psrldq_3): + psrldq $3, %xmm0 + jmp L(unaligned_pcmpistri) + +/* Handle unaligned string with offset 2 using psrldq. */ + .p2align 4 +L(psrldq_2): + psrldq $2, %xmm0 + jmp L(unaligned_pcmpistri) + + cfi_endproc + .size __strrchr_sse42, .-__strrchr_sse42 + + .section .rodata.sse4.2,"a",@progbits + .p2align 4 +L(psrldq_table): + .int L(loop) - L(psrldq_table) + .int L(psrldq_1) - L(psrldq_table) + .int L(psrldq_2) - L(psrldq_table) + .int L(psrldq_3) - L(psrldq_table) + .int L(psrldq_4) - L(psrldq_table) + .int L(psrldq_5) - L(psrldq_table) + .int L(psrldq_6) - L(psrldq_table) + .int L(psrldq_7) - L(psrldq_table) + .int L(psrldq_8) - L(psrldq_table) + .int L(psrldq_9) - L(psrldq_table) + .int L(psrldq_10) - L(psrldq_table) + .int L(psrldq_11) - L(psrldq_table) + .int L(psrldq_12) - L(psrldq_table) + .int L(psrldq_13) - L(psrldq_table) + .int L(psrldq_14) - L(psrldq_table) + .int L(psrldq_15) - L(psrldq_table) + + +# undef ENTRY +# define ENTRY(name) \ + .type __strrchr_sse2, @function; \ + .align 16; \ + __strrchr_sse2: cfi_startproc; \ + CALL_MCOUNT +# undef END +# define END(name) \ + cfi_endproc; .size __strrchr_sse2, .-__strrchr_sse2 +# undef libc_hidden_builtin_def +/* It doesn't make sense to send libc-internal strrchr calls through a PLT. + The speedup we get from using SSE4.2 instruction is likely eaten away + by the indirect call in the PLT. */ +# define libc_hidden_builtin_def(name) \ + .globl __GI_strrchr; __GI_strrchr = __strrchr_sse2 +#endif + +#include "../strrchr.S" |