diff options
author | Jakub Jelinek <jakub@redhat.com> | 2009-03-20 20:00:20 +0000 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2009-03-20 20:00:20 +0000 |
commit | ef860a878bf532436a469fc1f89fe3366862a949 (patch) | |
tree | c4a2666ac77cdaa00f41bd8f66a828b39e2642ff | |
parent | d4c583b4466962a9d9d4ca54ab6108dc7b42cdcc (diff) |
Updated to fedora-glibc-20090320T1944cvs/fedora-glibc-2_9_90-11
67 files changed, 1951 insertions, 620 deletions
@@ -1,3 +1,139 @@ +2009-03-16 Ulrich Drepper <drepper@redhat.com> + + * include/dirent.h: Yet more changes to match sort function type + change. + * sysdeps/unix/sysv/linux/i386/alphasort64.c: Likewise. + * sysdeps/unix/sysv/linux/i386/olddirent.h: Likewise. + * sysdeps/unix/sysv/linux/i386/versionsort64.c: Likewise. + +2009-03-16 Thomas Schwinge <tschwinge@gnu.org> + + * dirent/scandir64.c (scandir64): Adjust declaration to type change. + +2009-03-16 Ulrich Drepper <drepper@redhat.com> + + * nscd/connections.c (restart): Try to preserve the process name + by reading the /proc/self/exe symlink and using the return name. + Patch by Jeff Bastian <jbastian@redhat.com>. + +2009-03-15 Ulrich Drepper <drepper@redhat.com> + + [BZ #9733] + * elf/dl-load.c (_dl_map_object_from_fd): Only call audit hooks + if we are not loading a new audit library. + * elf/dl-reloc (_dl_relocate_object): Third parameter is now a bitmask. + Only use profiling trampoline for auditing if we are not relocating + an audit library. + * elf/dl-open.c (dl_open_worker): Adjust _dl_relocate_object call. + * elf/rtld.c: Likewise. + * sysdeps/generic/ldsodefs.h: Adjust _dl_relocate_object prototype. + + * elf/rtld.c (dl_main): Extend help message for --audit option. + + [BZ #9759] + * dirent/dirent.h: Adjust prototypes of scandir, scandir64, alphasort, + alphasort64, versionsort, and versionsort64 to POSIX 2008. + * dirent/alphasort.c: Adjust implementation to type change. + * dirent/alphasort64.c: Likewise. + * dirent/scandir.c: Likewise. + * dirent/versionsort.c: Likewise. + * dirent/versionsort64.c: Likewise. + * sysdeps/wordsize-64/alphasort.c: Add hack to hide alphasort64 + declaration. + * sysdeps/wordsize-64/versionsort.c: Add hack to hide versionsort64 + declaration. + + [BZ #9880] + * inet/inet6_rth.c (inet6_rth_reverse): Compute number of segments + correctly. Set segleft member in output as required. + Patch partly by Yang Hongyang <yanghy@cn.fujitsu.com>. + * inet/tst-inet6_rth.c (do_test): Add tests for inet6_rth_reverse. + + [BZ #9881] + * inet/inet6_rth.c (inet6_rth_add): Add some error checking. + Patch mostly by Yang Hongyang <yanghy@cn.fujitsu.com>. + * inet/Makefile (tests): Add tst-inet6_rth. + * inet/tst-inet6_rth.c: New file. + + [BZ #5807] + * string/strlen.c (strlen): Fix omission in the expression to test + for NUL bytes. + +2009-03-14 Ulrich Drepper <drepper@redhat.com> + + * crypt/sha256test.c (main): Perform 100,000 'a' test in a second way. + + * elf/dl-runtime.c (reloc_offset): Define. + (reloc_index): Define. + (_dl_fixup): Rename reloc_offset parameter to reloc_arg. + (_dl_fixup_profile): Likewise. Use reloc_index instead of + computing index from reloc_offset. + (_dl_call_pltexit): Likewise. + * sysdeps/x86_64/dl-trampoline.S (_dl_runtime_resolve): Just pass + the relocation index to _dl_fixup. + (_dl_runtime_profile): Likewise for _dl_fixup_profile and + _dl_call_pltexit. + * sysdeps/x86_64/dl-runtime.c: New file. + + [BZ #9893] + * sysdeps/x86_64/dl-trampoline.S (_dl_runtime_profile): Fix + alignment of La_x86_64_regs. Store xmm parameters. + Patch mostly by Jiri Olsa <olsajiri@gmail.com>. + + [BZ #9913] + * string/strverscmp.c (__strverscmp): Fix case of different digits + in fractional part of string. + Patch by Jingyu Liu <jyliu@fortinet.com>. + * string/Makefile (tests): Add tst-svc2. + * string/tst-svc2.c: New file. + + * string/strverscmp.c (__strverscmp): Optimize size of tables. + + * locale/iso-639.def: Add Min Nan. + +2009-03-11 Carlos Eduardo Seo <cseo@linux.vnet.ibm.com> + + [BZ #9948] + * elf/dl-sysdep.c (_dl_show_auxv): Add support for AT_BASE_PLATFORM. + +2009-03-14 Ulrich Drepper <drepper@redhat.com> + + * elf/dl-sysdep.c (auxvars): Compress data structure. + + * sysdeps/i386/dl-machine.h (elf_machine_rel): Implement + STT_GNU_IFUNC handling. + (elf_machine_rela): Likewise. + +2009-03-13 Ulrich Drepper <drepper@redhat.com> + + * config.h.in (USE_MULTIARCH): Define. + * configure.in: Handle --enable-multi-arch. + * elf/dl-runtime.c (_dl_fixup): Handle STT_GNU_IFUNC. + (_dl_fixup_profile): Likewise. + * elf/do-lookup.c (dl_lookup_x): Likewise. + * sysdeps/x86_64/dl-machine.h: Handle STT_GNU_IFUNC. + * elf/elf.h (STT_GNU_IFUNC): Define. + * include/libc-symbols.h (libc_ifunc): Define. + * sysdeps/x86_64/cacheinfo.c: If USE_MULTIARCH is defined, use the + framework in init-arch.h to get CPUID values. + * sysdeps/x86_64/multiarch/Makefile: New file. + * sysdeps/x86_64/multiarch/init-arch.c: New file. + * sysdeps/x86_64/multiarch/init-arch.h: New file. + * sysdeps/x86_64/multiarch/sched_cpucount.c: New file. + + * config.make.in (experimental-malloc): Define. + * configure.in: Handle --enable-experimental-malloc. + * malloc/Makefile: Handle experimental-malloc flag. + * malloc/malloc.c: Implement PER_THREAD and ATOMIC_FASTBINS features. + * malloc/arena.c: Likewise. + * malloc/hooks.c: Likewise. + * malloc/malloc.h: Define M_ARENA_TEST and M_ARENA_MAX. + +2009-03-11 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/x86_64/dl-machine.h (elf_machine_rela): Add branch + prediction. A few size optimizations. + 2009-03-10 Ulrich Drepper <drepper@redhat.com> * time/tzset.c: Optimize a bit for size. @@ -1,4 +1,4 @@ -GNU C Library NEWS -- history of user-visible changes. 2009-3-8 +GNU C Library NEWS -- history of user-visible changes. 2009-3-14 Copyright (C) 1992-2008, 2009 Free Software Foundation, Inc. See the end for copying conditions. @@ -7,7 +7,7 @@ using `glibc' in the "product" field. Version 2.10 -* New Linux interface: accept4 +* New Linux interfaces: accept4, fallocate, fallocate64. * Correct declarations of string function when used in C++ code. This could lead to compile error for invalid C++ code. @@ -21,6 +21,11 @@ Version 2.10 * New ISO C++1x interfaces: quick_exit, at_quick_exit Implemented by Ulrich Drepper. +* Support for selecting between multiple function definitions at runtime + using STT_GNU_IFUNC symbols. Implemented by Ulrich Drepper. + +* New locale: nan_TW@latin + Version 2.9 diff --git a/config.h.in b/config.h.in index b5abb10187..8dbc224a7d 100644 --- a/config.h.in +++ b/config.h.in @@ -189,6 +189,9 @@ /* Define if __stack_chk_guard canary should be randomized at program startup. */ #undef ENABLE_STACKGUARD_RANDOMIZE +/* Define if multi-arch DSOs should be generated. */ +#undef USE_MULTIARCH + /* */ diff --git a/config.make.in b/config.make.in index aa73466713..6da6362f24 100644 --- a/config.make.in +++ b/config.make.in @@ -70,6 +70,7 @@ versioning = @VERSIONING@ oldest-abi = @oldest_abi@ no-whole-archive = @no_whole_archive@ exceptions = @exceptions@ +multi-arch = @multi_arch@ mach-interface-list = @mach_interface_list@ @@ -78,6 +79,8 @@ have-ksh = @libc_cv_have_ksh@ sizeof-long-double = @sizeof_long_double@ +experimental-malloc = @experimental_malloc@ + # Configuration options. build-static = @static@ build-shared = @shared@ @@ -660,6 +660,8 @@ oldest_abi bindnow force_install all_warnings +multi_arch +experimental_malloc build build_cpu build_vendor @@ -1380,6 +1382,10 @@ Optional Features: --enable-kernel=VERSION compile for compatibility with kernel not older than VERSION --enable-all-warnings enable all useful warnings gcc can issue + --enable-multi-arch enable single DSO with optimizations for multiple + architectures + --enable-experimental-malloc + enable experimental malloc features Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -2173,6 +2179,29 @@ fi +# Check whether --enable-multi-arch was given. +if test "${enable_multi_arch+set}" = set; then + enableval=$enable_multi_arch; multi_arch=$enableval +else + multi_arch=no +fi + +if test x"$multi_arch" = xyes; then + cat >>confdefs.h <<\_ACEOF +#define USE_MULTIARCH 1 +_ACEOF + + multi_arch_d=/multiarch +fi + + +# Check whether --enable-experimental-malloc was given. +if test "${enable_experimental_malloc+set}" = set; then + enableval=$enable_experimental_malloc; experimental_malloc=$enableval +fi + + + # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5 @@ -2627,7 +2656,7 @@ for b in $base ''; do test "$v" = / && continue for o in /$ostry ''; do test "$o" = / && continue - for m in $mach ''; do + for m in $multi_arch_d $mach ''; do for d in $add_ons_pfx ''; do for a in $add_ons_sfx ''; do if test -n "$m0$m0sub$b$v$o$m$msub"; then @@ -5684,6 +5713,37 @@ _ACEOF fi +# For the multi-arch option we need support in the assembler. +if test "$multi_arch" = yes; then + if test "x$libc_cv_asm_type_prefix" != xno; then +{ echo "$as_me:$LINENO: checking for assembler gnu_indirect_function symbol type support" >&5 +echo $ECHO_N "checking for assembler gnu_indirect_function symbol type support... $ECHO_C" >&6; } +if test "${libc_cv_asm_gnu_indirect_function+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat > conftest.s <<EOF +.type foo,%gnu_indirect_function +EOF +if ${CC-cc} -c $ASFLAGS conftest.s 1>&5 2>&5; +then + libc_cv_asm_gnu_indirect_function=yes +else + libc_cv_asm_gnu_indirect_function=no +fi +rm -f conftest* +fi +{ echo "$as_me:$LINENO: result: $libc_cv_asm_gnu_indirect_function" >&5 +echo "${ECHO_T}$libc_cv_asm_gnu_indirect_function" >&6; } + else + libc_cv_asm_gnu_indirect_function=no + fi + if test x"$libc_cv_asm_gnu_indirect_function" != xyes; then + { { echo "$as_me:$LINENO: error: --enable-multi-arch support requires assembler and linker support" >&5 +echo "$as_me: error: --enable-multi-arch support requires assembler and linker support" >&2;} + { (exit 1); exit 1; }; } + fi +fi + { echo "$as_me:$LINENO: checking for .symver assembler directive" >&5 echo $ECHO_N "checking for .symver assembler directive... $ECHO_C" >&6; } if test "${libc_cv_asm_symver_directive+set}" = set; then @@ -9184,6 +9244,8 @@ oldest_abi!$oldest_abi$ac_delim bindnow!$bindnow$ac_delim force_install!$force_install$ac_delim all_warnings!$all_warnings$ac_delim +multi_arch!$multi_arch$ac_delim +experimental_malloc!$experimental_malloc$ac_delim build!$build$ac_delim build_cpu!$build_cpu$ac_delim build_vendor!$build_vendor$ac_delim @@ -9235,8 +9297,6 @@ libc_cv_have_bash2!$libc_cv_have_bash2$ac_delim KSH!$KSH$ac_delim libc_cv_have_ksh!$libc_cv_have_ksh$ac_delim AWK!$AWK$ac_delim -PERL!$PERL$ac_delim -INSTALL_INFO!$INSTALL_INFO$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then @@ -9278,6 +9338,8 @@ _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF +PERL!$PERL$ac_delim +INSTALL_INFO!$INSTALL_INFO$ac_delim BISON!$BISON$ac_delim VERSIONING!$VERSIONING$ac_delim libc_cv_cc_with_libunwind!$libc_cv_cc_with_libunwind$ac_delim @@ -9334,7 +9396,7 @@ LIBOBJS!$LIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 54; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 56; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 diff --git a/configure.in b/configure.in index d7b22f3a3b..4015722d5a 100644 --- a/configure.in +++ b/configure.in @@ -254,6 +254,24 @@ AC_ARG_ENABLE([all-warnings], []) AC_SUBST(all_warnings) +AC_ARG_ENABLE([multi-arch], + AC_HELP_STRING([--enable-multi-arch], + [enable single DSO with optimizations for multiple architectures]), + [multi_arch=$enableval], + [multi_arch=no]) +if test x"$multi_arch" = xyes; then + AC_DEFINE(USE_MULTIARCH) + multi_arch_d=/multiarch +fi +AC_SUBST(multi_arch) + +AC_ARG_ENABLE([experimental-malloc], + AC_HELP_STRING([--enable-experimental-malloc], + [enable experimental malloc features]), + [experimental_malloc=$enableval], + []) +AC_SUBST(experimental_malloc) + AC_CANONICAL_HOST # The way shlib-versions is used to generate soversions.mk uses a @@ -608,7 +626,7 @@ for b in $base ''; do test "$v" = / && continue for o in /$ostry ''; do test "$o" = / && continue - for m in $mach ''; do + for m in $multi_arch_d $mach ''; do for d in $add_ons_pfx ''; do for a in $add_ons_sfx ''; do if test -n "$m0$m0sub$b$v$o$m$msub"; then @@ -1157,6 +1175,29 @@ if test "x$libc_cv_asm_type_prefix" != xno; then AC_DEFINE_UNQUOTED(ASM_TYPE_DIRECTIVE_PREFIX, ${libc_cv_asm_type_prefix}) fi +# For the multi-arch option we need support in the assembler. +if test "$multi_arch" = yes; then + if test "x$libc_cv_asm_type_prefix" != xno; then +AC_CACHE_CHECK([for assembler gnu_indirect_function symbol type support], + libc_cv_asm_gnu_indirect_function, [dnl +cat > conftest.s <<EOF +.type foo,%gnu_indirect_function +EOF +if ${CC-cc} -c $ASFLAGS conftest.s 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; +then + libc_cv_asm_gnu_indirect_function=yes +else + libc_cv_asm_gnu_indirect_function=no +fi +rm -f conftest*]) + else + libc_cv_asm_gnu_indirect_function=no + fi + if test x"$libc_cv_asm_gnu_indirect_function" != xyes; then + AC_MSG_ERROR([--enable-multi-arch support requires assembler and linker support]) + fi +fi + AC_CACHE_CHECK(for .symver assembler directive, libc_cv_asm_symver_directive, [cat > conftest.s <<EOF ${libc_cv_dot_text} diff --git a/crypt/sha256test.c b/crypt/sha256test.c index b13a3c511e..39e80307c7 100644 --- a/crypt/sha256test.c +++ b/crypt/sha256test.c @@ -84,7 +84,17 @@ main (void) "\xf1\x80\x9a\x48\xa4\x97\x20\x0e\x04\x6d\x39\xcc\xc7\x11\x2c\xd0"; if (memcmp (expected, sum, 32) != 0) { - printf ("test %d failed\n", cnt); + printf ("test %d failed\n", cnt++); + result = 1; + } + + __sha256_init_ctx (&ctx); + for (int i = 0; i < 100000; ++i) + __sha256_process_bytes (buf, 10, &ctx); + __sha256_finish_ctx (&ctx, sum); + if (memcmp (expected, sum, 32) != 0) + { + printf ("test %d failed\n", cnt++); result = 1; } diff --git a/dirent/alphasort.c b/dirent/alphasort.c index b378626f6c..360b17c5a0 100644 --- a/dirent/alphasort.c +++ b/dirent/alphasort.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1992, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1992, 1997, 1998, 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 @@ -20,8 +20,7 @@ #include <string.h> int -alphasort (const void *a, const void *b) +alphasort (const struct dirent **a, const struct dirent **b) { - return strcoll ((*(const struct dirent **) a)->d_name, - (*(const struct dirent **) b)->d_name); + return strcoll ((*a)->d_name, (*b)->d_name); } diff --git a/dirent/alphasort64.c b/dirent/alphasort64.c index fe84aec2f1..f91cba5088 100644 --- a/dirent/alphasort64.c +++ b/dirent/alphasort64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1992, 1997, 1998, 2000 Free Software Foundation, Inc. +/* Copyright (C) 1992, 1997, 1998, 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 @@ -20,8 +20,7 @@ #include <string.h> int -alphasort64 (const void *a, const void *b) +alphasort64 (const struct dirent64 **a, const struct dirent64 **b) { - return strcoll ((*(const struct dirent64 **) a)->d_name, - (*(const struct dirent64 **) b)->d_name); + return strcoll ((*a)->d_name, (*b)->d_name); } diff --git a/dirent/dirent.h b/dirent/dirent.h index cb6d0bc2d5..369ccdc9ee 100644 --- a/dirent/dirent.h +++ b/dirent/dirent.h @@ -252,7 +252,8 @@ extern int dirfd (DIR *__dirp) __THROW __nonnull ((1)); extern int scandir (__const char *__restrict __dir, struct dirent ***__restrict __namelist, int (*__selector) (__const struct dirent *), - int (*__cmp) (__const void *, __const void *)) + int (*__cmp) (__const struct dirent **, + __const struct dirent **)) __nonnull ((1, 2)); # else # ifdef __REDIRECT @@ -260,7 +261,8 @@ extern int __REDIRECT (scandir, (__const char *__restrict __dir, struct dirent ***__restrict __namelist, int (*__selector) (__const struct dirent *), - int (*__cmp) (__const void *, __const void *)), + int (*__cmp) (__const struct dirent **, + __const struct dirent **)), scandir64) __nonnull ((1, 2)); # else # define scandir scandir64 @@ -273,18 +275,21 @@ extern int __REDIRECT (scandir, extern int scandir64 (__const char *__restrict __dir, struct dirent64 ***__restrict __namelist, int (*__selector) (__const struct dirent64 *), - int (*__cmp) (__const void *, __const void *)) + int (*__cmp) (__const struct dirent64 **, + __const struct dirent64 **)) __nonnull ((1, 2)); # endif /* Function to compare two `struct dirent's alphabetically. */ # ifndef __USE_FILE_OFFSET64 -extern int alphasort (__const void *__e1, __const void *__e2) +extern int alphasort (__const struct dirent **__e1, + __const struct dirent **__e2) __THROW __attribute_pure__ __nonnull ((1, 2)); # else # ifdef __REDIRECT extern int __REDIRECT_NTH (alphasort, - (__const void *__e1, __const void *__e2), + (__const struct dirent **__e1, + __const struct dirent **__e2), alphasort64) __attribute_pure__ __nonnull ((1, 2)); # else # define alphasort alphasort64 @@ -292,51 +297,54 @@ extern int __REDIRECT_NTH (alphasort, # endif # if defined __USE_GNU && defined __USE_LARGEFILE64 -extern int alphasort64 (__const void *__e1, __const void *__e2) +extern int alphasort64 (__const struct dirent64 **__e1, + __const struct dirent64 **__e2) __THROW __attribute_pure__ __nonnull ((1, 2)); # endif +#endif /* Use BSD or misc or XPG7. */ -# if defined __USE_BSD || defined __USE_MISC +#if defined __USE_BSD || defined __USE_MISC /* Read directory entries from FD into BUF, reading at most NBYTES. Reading starts at offset *BASEP, and *BASEP is updated with the new position after reading. Returns the number of bytes read; zero when at end of directory; or -1 for errors. */ -# ifndef __USE_FILE_OFFSET64 +# ifndef __USE_FILE_OFFSET64 extern __ssize_t getdirentries (int __fd, char *__restrict __buf, size_t __nbytes, __off_t *__restrict __basep) __THROW __nonnull ((2, 4)); -# else -# ifdef __REDIRECT +# else +# ifdef __REDIRECT extern __ssize_t __REDIRECT_NTH (getdirentries, (int __fd, char *__restrict __buf, size_t __nbytes, __off64_t *__restrict __basep), getdirentries64) __nonnull ((2, 4)); -# else -# define getdirentries getdirentries64 -# endif +# else +# define getdirentries getdirentries64 # endif +# endif -# ifdef __USE_LARGEFILE64 +# ifdef __USE_LARGEFILE64 extern __ssize_t getdirentries64 (int __fd, char *__restrict __buf, size_t __nbytes, __off64_t *__restrict __basep) __THROW __nonnull ((2, 4)); -# endif -# endif /* Use BSD or misc. */ -#endif /* Use BSD or misc or XPG7. */ +# endif +#endif /* Use BSD or misc. */ #ifdef __USE_GNU /* Function to compare two `struct dirent's by name & version. */ # ifndef __USE_FILE_OFFSET64 -extern int versionsort (__const void *__e1, __const void *__e2) +extern int versionsort (__const struct dirent **__e1, + __const struct dirent **__e2) __THROW __attribute_pure__ __nonnull ((1, 2)); # else # ifdef __REDIRECT extern int __REDIRECT_NTH (versionsort, - (__const void *__e1, __const void *__e2), + (__const struct dirent **__e1, + __const struct dirent **__e2), versionsort64) __attribute_pure__ __nonnull ((1, 2)); # else @@ -345,7 +353,8 @@ extern int __REDIRECT_NTH (versionsort, # endif # ifdef __USE_LARGEFILE64 -extern int versionsort64 (__const void *__e1, __const void *__e2) +extern int versionsort64 (__const struct dirent64 **__e1, + __const struct dirent64 **__e2) __THROW __attribute_pure__ __nonnull ((1, 2)); # endif #endif /* Use GNU. */ diff --git a/dirent/scandir.c b/dirent/scandir.c index 89bd9e94fe..2e03578a3c 100644 --- a/dirent/scandir.c +++ b/dirent/scandir.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1992-1998, 2000, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1992-1998,2000,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 @@ -57,7 +57,7 @@ SCANDIR (dir, namelist, select, cmp) const char *dir; DIRENT_TYPE ***namelist; int (*select) (const DIRENT_TYPE *); - int (*cmp) (const void *, const void *); + int (*cmp) (const DIRENT_TYPE **, const DIRENT_TYPE **); { DIR *dp = __opendir (dir); DIRENT_TYPE **v = NULL; @@ -134,7 +134,8 @@ SCANDIR (dir, namelist, select, cmp) { /* Sort the list if we have a comparison function to sort with. */ if (cmp != NULL) - qsort (v, c.cnt, sizeof (*v), cmp); + qsort (v, c.cnt, sizeof (*v), + (int (*) (const void *, const void *)) cmp); *namelist = v; } diff --git a/dirent/scandir64.c b/dirent/scandir64.c index 68608de9a0..b7bd654658 100644 --- a/dirent/scandir64.c +++ b/dirent/scandir64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 Free Software Foundation, Inc. +/* Copyright (C) 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 @@ -25,6 +25,7 @@ int scandir64 (__const char *__restrict __dir, struct dirent64 ***__restrict __namelist, int (*__selector) (__const struct dirent64 *), - int (*__cmp) (__const void *, __const void *)); + int (*__cmp) (__const struct dirent64 **, + __const struct dirent64 **)); #include <dirent/scandir.c> diff --git a/dirent/versionsort.c b/dirent/versionsort.c index d986981bce..f7bd717848 100644 --- a/dirent/versionsort.c +++ b/dirent/versionsort.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1992, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1992, 1997, 1998, 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 @@ -20,8 +20,7 @@ #include <string.h> int -versionsort (const void *a, const void *b) +versionsort (const struct dirent **a, const struct dirent **b) { - return __strverscmp ((*(const struct dirent **) a)->d_name, - (*(const struct dirent **) b)->d_name); + return __strverscmp ((*a)->d_name, (*b)->d_name); } diff --git a/dirent/versionsort64.c b/dirent/versionsort64.c index e471827023..5b2833111b 100644 --- a/dirent/versionsort64.c +++ b/dirent/versionsort64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1992, 1997, 1998, 2000 Free Software Foundation, Inc. +/* Copyright (C) 1992, 1997, 1998, 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 @@ -20,8 +20,7 @@ #include <string.h> int -versionsort64 (const void *a, const void *b) +versionsort64 (const struct dirent64 **a, const struct dirent64 **b) { - return __strverscmp ((*(const struct dirent64 **) a)->d_name, - (*(const struct dirent64 **) b)->d_name); + return __strverscmp ((*a)->d_name, (*b)->d_name); } diff --git a/elf/dl-load.c b/elf/dl-load.c index c77c259156..0deb51e445 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -941,7 +941,8 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp, { #ifdef SHARED /* Auditing checkpoint: we are going to add new objects. */ - if (__builtin_expect (GLRO(dl_naudit) > 0, 0)) + if ((mode & __RTLD_AUDIT) == 0 + && __builtin_expect (GLRO(dl_naudit) > 0, 0)) { struct link_map *head = GL(dl_ns)[nsid]._ns_loaded; /* Do not call the functions for any auditing object. */ diff --git a/elf/dl-open.c b/elf/dl-open.c index f825aa0437..75dc7bc406 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -1,5 +1,5 @@ /* Load a shared object at runtime, relocate it, and run its initializer. - Copyright (C) 1996-2004, 2005, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 1996-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 @@ -207,7 +207,6 @@ dl_open_worker (void *a) const char *file = args->file; int mode = args->mode; struct link_map *new; - int lazy; unsigned int i; bool any_tls = false; struct link_map *call_map = NULL; @@ -366,7 +365,9 @@ dl_open_worker (void *a) _dl_debug_state (); /* Only do lazy relocation if `LD_BIND_NOW' is not set. */ - lazy = (mode & RTLD_BINDING_MASK) == RTLD_LAZY && GLRO(dl_lazy); + int reloc_mode = mode & __RTLD_AUDIT; + if (GLRO(dl_lazy)) + reloc_mode |= mode & RTLD_LAZY; /* Relocate the objects loaded. We do this in reverse order so that copy relocs of earlier objects overwrite the data written by later objects. */ @@ -388,7 +389,7 @@ dl_open_worker (void *a) start the profiling. */ struct link_map *old_profile_map = GL(dl_profile_map); - _dl_relocate_object (l, l->l_scope, 1, 1); + _dl_relocate_object (l, l->l_scope, reloc_mode | RTLD_LAZY, 1); if (old_profile_map == NULL && GL(dl_profile_map) != NULL) { @@ -401,7 +402,7 @@ dl_open_worker (void *a) } else #endif - _dl_relocate_object (l, l->l_scope, lazy, 0); + _dl_relocate_object (l, l->l_scope, reloc_mode, 0); } if (l == new) diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c index a303cb4ce6..28f08de3e7 100644 --- a/elf/dl-reloc.c +++ b/elf/dl-reloc.c @@ -1,5 +1,5 @@ /* Relocate a shared object and resolve its references to other loaded objects. - Copyright (C) 1995-2004, 2005, 2006, 2008 Free Software Foundation, Inc. + Copyright (C) 1995-2006, 2008, 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 @@ -151,7 +151,7 @@ _dl_nothread_init_static_tls (struct link_map *map) void _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], - int lazy, int consider_profiling) + int reloc_mode, int consider_profiling) { struct textrels { @@ -162,10 +162,12 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], } *textrels = NULL; /* Initialize it to make the compiler happy. */ const char *errstring = NULL; + int lazy = reloc_mode & RTLD_LAZY; #ifdef SHARED /* If we are auditing, install the same handlers we need for profiling. */ - consider_profiling |= GLRO(dl_audit) != NULL; + if ((reloc_mode & __RTLD_AUDIT) == 0) + consider_profiling |= GLRO(dl_audit) != NULL; #elif defined PROF /* Never use dynamic linker profiling for gprof profiling code. */ # define consider_profiling 0 diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c index 968e293409..93c8f29d39 100644 --- a/elf/dl-runtime.c +++ b/elf/dl-runtime.c @@ -1,5 +1,5 @@ /* On-demand PLT fixup for shared objects. - Copyright (C) 1995-2006, 2007 Free Software Foundation, Inc. + Copyright (C) 1995-2006, 2007, 2008, 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 @@ -46,6 +46,12 @@ # define ARCH_FIXUP_ATTRIBUTE #endif +#ifndef reloc_offset +# define reloc_offset reloc_arg +# define reloc_index reloc_arg / sizeof (PLTREL) +#endif + + /* This function is called through a special trampoline from the PLT the first time each PLT entry is called. We must perform the relocation @@ -63,7 +69,7 @@ _dl_fixup ( # endif /* GKM FIXME: Fix trampoline to pass bounds so we can do without the `__unbounded' qualifier. */ - struct link_map *__unbounded l, ElfW(Word) reloc_offset) + struct link_map *__unbounded l, ElfW(Word) reloc_arg) { const ElfW(Sym) *const symtab = (const void *) D_PTR (l, l_info[DT_SYMTAB]); @@ -130,6 +136,9 @@ _dl_fixup ( /* And now perhaps the relocation addend. */ value = elf_machine_plt_value (l, reloc, value); + if (__builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)) + value = ((DL_FIXUP_VALUE_TYPE (*) (void)) value) (); + /* Finally, fix up the plt itself. */ if (__builtin_expect (GLRO(dl_bind_not), 0)) return value; @@ -139,22 +148,20 @@ _dl_fixup ( #endif #if !defined PROF && !defined ELF_MACHINE_NO_PLT && !__BOUNDED_POINTERS__ - DL_FIXUP_VALUE_TYPE __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE _dl_profile_fixup ( #ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS ELF_MACHINE_RUNTIME_FIXUP_ARGS, #endif - struct link_map *l, ElfW(Word) reloc_offset, + struct link_map *l, ElfW(Word) reloc_arg, ElfW(Addr) retaddr, void *regs, long int *framesizep) { void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = INTUSE(_dl_mcount); /* This is the address in the array where we store the result of previous relocations. */ - struct reloc_result *reloc_result - = &l->l_reloc_result[reloc_offset / sizeof (PLTREL)]; + struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index]; DL_FIXUP_VALUE_TYPE *resultp = &reloc_result->addr; DL_FIXUP_VALUE_TYPE value = *resultp; @@ -215,12 +222,21 @@ _dl_profile_fixup ( defsym != NULL ? LOOKUP_VALUE_ADDRESS (result) + defsym->st_value : 0); + + if (__builtin_expect (ELFW(ST_TYPE) (defsym->st_info) + == STT_GNU_IFUNC, 0)) + value = ((DL_FIXUP_VALUE_TYPE (*) (void)) value) (); } else { /* We already found the symbol. The module (and therefore its load address) is also known. */ value = DL_FIXUP_MAKE_VALUE (l, l->l_addr + refsym->st_value); + + if (__builtin_expect (ELFW(ST_TYPE) (refsym->st_info) + == STT_GNU_IFUNC, 0)) + value = ((DL_FIXUP_VALUE_TYPE (*) (void)) value) (); + result = l; } /* And now perhaps the relocation addend. */ @@ -403,7 +419,7 @@ _dl_profile_fixup ( #include <stdio.h> void ARCH_FIXUP_ATTRIBUTE -_dl_call_pltexit (struct link_map *l, ElfW(Word) reloc_offset, +_dl_call_pltexit (struct link_map *l, ElfW(Word) reloc_arg, const void *inregs, void *outregs) { #ifdef SHARED @@ -411,8 +427,7 @@ _dl_call_pltexit (struct link_map *l, ElfW(Word) reloc_offset, relocations. */ // XXX Maybe the bound information must be stored on the stack since // XXX with bind_not a new value could have been stored in the meantime. - struct reloc_result *reloc_result - = &l->l_reloc_result[reloc_offset / sizeof (PLTREL)]; + struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index]; ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound, l_info[DT_SYMTAB]) + reloc_result->boundndx); diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c index a44bee7086..db1001253c 100644 --- a/elf/dl-sysdep.c +++ b/elf/dl-sysdep.c @@ -269,36 +269,37 @@ _dl_show_auxv (void) { static const struct { - const char label[20]; - enum { unknown = 0, dec, hex, str, ignore } form; + const char label[17]; + enum { unknown = 0, dec, hex, str, ignore } form : 8; } auxvars[] = { - [AT_EXECFD - 2] = { "AT_EXECFD: ", dec }, - [AT_EXECFN - 2] = { "AT_EXECFN: ", str }, - [AT_PHDR - 2] = { "AT_PHDR: 0x", hex }, - [AT_PHENT - 2] = { "AT_PHENT: ", dec }, - [AT_PHNUM - 2] = { "AT_PHNUM: ", dec }, - [AT_PAGESZ - 2] = { "AT_PAGESZ: ", dec }, - [AT_BASE - 2] = { "AT_BASE: 0x", hex }, - [AT_FLAGS - 2] = { "AT_FLAGS: 0x", hex }, - [AT_ENTRY - 2] = { "AT_ENTRY: 0x", hex }, - [AT_NOTELF - 2] = { "AT_NOTELF: ", hex }, - [AT_UID - 2] = { "AT_UID: ", dec }, - [AT_EUID - 2] = { "AT_EUID: ", dec }, - [AT_GID - 2] = { "AT_GID: ", dec }, - [AT_EGID - 2] = { "AT_EGID: ", dec }, - [AT_PLATFORM - 2] = { "AT_PLATFORM: ", str }, - [AT_HWCAP - 2] = { "AT_HWCAP: ", hex }, - [AT_CLKTCK - 2] = { "AT_CLKTCK: ", dec }, - [AT_FPUCW - 2] = { "AT_FPUCW: ", hex }, - [AT_DCACHEBSIZE - 2] = { "AT_DCACHEBSIZE: 0x", hex }, - [AT_ICACHEBSIZE - 2] = { "AT_ICACHEBSIZE: 0x", hex }, - [AT_UCACHEBSIZE - 2] = { "AT_UCACHEBSIZE: 0x", hex }, - [AT_IGNOREPPC - 2] = { "AT_IGNOREPPC", ignore }, - [AT_SECURE - 2] = { "AT_SECURE: ", dec }, - [AT_SYSINFO - 2] = { "AT_SYSINFO: 0x", hex }, - [AT_SYSINFO_EHDR - 2] = { "AT_SYSINFO_EHDR: 0x", hex }, - [AT_RANDOM - 2] = { "AT_RANDOM: 0x", hex }, + [AT_EXECFD - 2] = { "EXECFD: ", dec }, + [AT_EXECFN - 2] = { "EXECFN: ", str }, + [AT_PHDR - 2] = { "PHDR: 0x", hex }, + [AT_PHENT - 2] = { "PHENT: ", dec }, + [AT_PHNUM - 2] = { "PHNUM: ", dec }, + [AT_PAGESZ - 2] = { "PAGESZ: ", dec }, + [AT_BASE - 2] = { "BASE: 0x", hex }, + [AT_FLAGS - 2] = { "FLAGS: 0x", hex }, + [AT_ENTRY - 2] = { "ENTRY: 0x", hex }, + [AT_NOTELF - 2] = { "NOTELF: ", hex }, + [AT_UID - 2] = { "UID: ", dec }, + [AT_EUID - 2] = { "EUID: ", dec }, + [AT_GID - 2] = { "GID: ", dec }, + [AT_EGID - 2] = { "EGID: ", dec }, + [AT_PLATFORM - 2] = { "PLATFORM: ", str }, + [AT_HWCAP - 2] = { "HWCAP: ", hex }, + [AT_CLKTCK - 2] = { "CLKTCK: ", dec }, + [AT_FPUCW - 2] = { "FPUCW: ", hex }, + [AT_DCACHEBSIZE - 2] = { "DCACHEBSIZE: 0x", hex }, + [AT_ICACHEBSIZE - 2] = { "ICACHEBSIZE: 0x", hex }, + [AT_UCACHEBSIZE - 2] = { "UCACHEBSIZE: 0x", hex }, + [AT_IGNOREPPC - 2] = { "IGNOREPPC", ignore }, + [AT_SECURE - 2] = { "SECURE: ", dec }, + [AT_BASE_PLATFORM - 2] = { "BASE_PLATFORM:", str }, + [AT_SYSINFO - 2] = { "SYSINFO: 0x", hex }, + [AT_SYSINFO_EHDR - 2] = { "SYSINFO_EHDR: 0x", hex }, + [AT_RANDOM - 2] = { "RANDOM: 0x", hex }, }; unsigned int idx = (unsigned int) (av->a_type - 2); @@ -327,7 +328,7 @@ _dl_show_auxv (void) val = _itoa ((unsigned long int) av->a_un.a_val, buf + sizeof buf - 1, 16, 0); - _dl_printf ("%s%s\n", auxvars[idx].label, val); + _dl_printf ("AT_%s%s\n", auxvars[idx].label, val); continue; } diff --git a/elf/do-lookup.h b/elf/do-lookup.h index ebb9ed5b47..41e5fc137c 100644 --- a/elf/do-lookup.h +++ b/elf/do-lookup.h @@ -1,5 +1,5 @@ /* Look up a symbol in the loaded objects. - Copyright (C) 1995-2004, 2005, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 1995-2007, 2008 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 @@ -88,10 +88,12 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash, if (__builtin_expect (ELFW(ST_TYPE) (sym->st_info) > STT_FUNC && ELFW(ST_TYPE) (sym->st_info) != STT_COMMON - && ELFW(ST_TYPE) (sym->st_info) != STT_TLS, 0)) - /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC, and STT_COMMON - entries (and STT_TLS if TLS is supported) since these - are no code/data definitions. */ + && ELFW(ST_TYPE) (sym->st_info) != STT_TLS + && ELFW(ST_TYPE) (sym->st_info) != STT_GNU_IFUNC, + 0)) + /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC, STT_COMMON, + STT_TLS, and STT_GNU_IFUNC since these are no code/data + definitions. */ return NULL; if (sym != ref && strcmp (strtab + sym->st_name, undef_name)) @@ -459,6 +459,7 @@ typedef struct #define STT_TLS 6 /* Symbol is thread-local data object*/ #define STT_NUM 7 /* Number of defined types. */ #define STT_LOOS 10 /* Start of OS-specific */ +#define STT_GNU_IFUNC 10 /* Symbol is indirect code object */ #define STT_HIOS 12 /* End of OS-specific */ #define STT_LOPROC 13 /* Start of processor-specific */ #define STT_HIPROC 15 /* End of processor-specific */ diff --git a/elf/rtld.c b/elf/rtld.c index aa4c030f73..bfe9564463 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -574,7 +574,7 @@ _dl_start (void *arg) struct relocate_args { struct link_map *l; - int lazy; + int reloc_mode; }; struct map_args @@ -613,7 +613,7 @@ relocate_doit (void *a) { struct relocate_args *args = (struct relocate_args *) a; - _dl_relocate_object (args->l, args->l->l_scope, args->lazy, 0); + _dl_relocate_object (args->l, args->l->l_scope, args->reloc_mode, 0); } static void @@ -1011,7 +1011,8 @@ of this helper program; chances are you did not intend to run this program.\n\ --library-path PATH use given PATH instead of content of the environment\n\ variable LD_LIBRARY_PATH\n\ --inhibit-rpath LIST ignore RUNPATH and RPATH information in object names\n\ - in LIST\n"); + in LIST\n\ + --audit LIST use objects named in LIST as auditors\n"); ++_dl_skip_args; --_dl_argc; @@ -1908,7 +1909,9 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", struct link_map *l = main_map; /* Relocate the main executable. */ - struct relocate_args args = { .l = l, .lazy = GLRO(dl_lazy) }; + struct relocate_args args = { .l = l, + .reloc_mode = (GLRO(dl_lazy) + ? RTLD_LAZY : 0) }; _dl_receive_error (print_unresolved, relocate_doit, &args); /* This loop depends on the dependencies of the executable to @@ -1985,7 +1988,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", struct relocate_args args; struct link_map *l; - args.lazy = GLRO(dl_lazy); + args.reloc_mode = GLRO(dl_lazy) ? RTLD_LAZY : 0; l = main_map; while (l->l_next != NULL) @@ -2225,7 +2228,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", } if (l != &GL(dl_rtld_map)) - _dl_relocate_object (l, l->l_scope, GLRO(dl_lazy), + _dl_relocate_object (l, l->l_scope, GLRO(dl_lazy) ? RTLD_LAZY : 0, consider_profiling); /* Add object to slot information data if necessasy. */ diff --git a/fedora/branch.mk b/fedora/branch.mk index bb315585f2..1466977998 100644 --- a/fedora/branch.mk +++ b/fedora/branch.mk @@ -3,5 +3,5 @@ glibc-branch := fedora glibc-base := HEAD DIST_BRANCH := devel COLLECTION := dist-f8 -fedora-sync-date := 2009-03-10 19:25 UTC -fedora-sync-tag := fedora-glibc-20090310T1925 +fedora-sync-date := 2009-03-20 19:44 UTC +fedora-sync-tag := fedora-glibc-20090320T1944 diff --git a/fedora/glibc.spec.in b/fedora/glibc.spec.in index cec16002d3..4dd603da07 100644 --- a/fedora/glibc.spec.in +++ b/fedora/glibc.spec.in @@ -19,7 +19,7 @@ Summary: The GNU libc libraries Name: glibc Version: @glibcversion@ -Release: 10 +Release: 11 # GPLv2+ is used in a bunch of programs, LGPLv2+ is used for libraries. # Things that are linked directly into dynamically linked programs # and shared libraries (e.g. crt files, lib*_nonshared.a) have an additional @@ -1009,6 +1009,12 @@ rm -f *.filelist* %endif %changelog +* Fri Mar 20 2009 Jakub Jelinek <jakub@redhat.com> 2.9.90-11 +- update from trunk + - POSIX 2008 prototype adjustments for scandir{,64}, alphasort{,64} and + versionsort{,64} + - fix libthread_db (#491197) + * Tue Mar 10 2009 Jakub Jelinek <jakub@redhat.com> 2.9.90-10 - update from trunk - fix atexit/__cxa_atexit diff --git a/include/dirent.h b/include/dirent.h index 8f23aee234..3f6c4b9ae5 100644 --- a/include/dirent.h +++ b/include/dirent.h @@ -17,14 +17,16 @@ extern int __readdir64_r (DIR *__dirp, struct dirent64 *__entry, extern int __scandir64 (__const char * __dir, struct dirent64 *** __namelist, int (*__selector) (__const struct dirent64 *), - int (*__cmp) (__const void *, __const void *)); + int (*__cmp) (__const struct dirent64 **, + __const struct dirent64 **)); extern __ssize_t __getdents (int __fd, char *__buf, size_t __nbytes) internal_function; extern __ssize_t __getdents64 (int __fd, char *__buf, size_t __nbytes) internal_function; -extern int __alphasort64 (const void *a, const void *b) +extern int __alphasort64 (const struct dirent64 **a, const struct dirent64 **b) __attribute_pure__; -extern int __versionsort64 (const void *a, const void *b) +extern int __versionsort64 (const struct dirent64 **a, + const struct dirent64 **b) __attribute_pure__; extern DIR *__alloc_dir (int fd, bool close_fd, const struct stat64 *statp) internal_function; diff --git a/include/libc-symbols.h b/include/libc-symbols.h index a2faeafb32..d53bcb9b77 100644 --- a/include/libc-symbols.h +++ b/include/libc-symbols.h @@ -1,7 +1,6 @@ /* Support macros for making weak and strong aliases for symbols, and for using symbol sets and linker warnings with GNU ld. - Copyright (C) 1995-1998,2000-2003,2004,2005,2006 - Free Software Foundation, Inc. + Copyright (C) 1995-1998, 2000-2006, 2008 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 @@ -835,4 +834,15 @@ for linking") # define compat_data_section .section ".data.compat", "aw"; #endif +/* Marker used for indirection function symbols. */ +#define libc_ifunc(name, expr) \ + extern void *name##_ifunc (void) __asm__ (#name); \ + void *name##_ifunc (void) \ + { \ + INIT_ARCH (); \ + __typeof (name) *res = expr; \ + return res; \ + } \ + __asm__ (".type " #name ", %gnu_indirect_function"); + #endif /* libc-symbols.h */ diff --git a/inet/Makefile b/inet/Makefile index 16b2aae683..37985940ae 100644 --- a/inet/Makefile +++ b/inet/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1991-2006, 2007 Free Software Foundation, Inc. +# Copyright (C) 1991-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 @@ -53,7 +53,7 @@ aux := check_pf check_native ifreq tests := htontest test_ifindex tst-ntoa tst-ether_aton tst-network \ tst-gethnm test-ifaddrs bug-if1 test-inet6_opt tst-ether_line \ - tst-getni1 tst-getni2 + tst-getni1 tst-getni2 tst-inet6_rth include ../Rules diff --git a/inet/inet6_rth.c b/inet/inet6_rth.c index 15f8240909..36269fc6a4 100644 --- a/inet/inet6_rth.c +++ b/inet/inet6_rth.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 Free Software Foundation, Inc. +/* Copyright (C) 2006, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2006. @@ -93,6 +93,9 @@ inet6_rth_add (void *bp, const struct in6_addr *addr) struct ip6_rthdr0 *rthdr0; case IPV6_RTHDR_TYPE_0: rthdr0 = (struct ip6_rthdr0 *) rthdr; + if (rthdr0->ip6r0_len * 8 / sizeof (struct in6_addr) + - rthdr0->ip6r0_segleft < 1) + return -1; memcpy (&rthdr0->ip6r0_addr[rthdr0->ip6r0_segleft++], addr, sizeof (struct in6_addr)); @@ -127,7 +130,7 @@ inet6_rth_reverse (const void *in, void *out) /* Copy header, not the addresses. The memory regions can overlap. */ memmove (out_rthdr0, in_rthdr0, sizeof (struct ip6_rthdr0)); - int total = in_rthdr0->ip6r0_segleft * 8 / sizeof (struct in6_addr); + int total = in_rthdr0->ip6r0_len * 8 / sizeof (struct in6_addr); for (int i = 0; i < total / 2; ++i) { /* Remember, IN_RTHDR0 and OUT_RTHDR0 might overlap. */ @@ -138,6 +141,8 @@ inet6_rth_reverse (const void *in, void *out) if (total % 2 != 0 && in != out) out_rthdr0->ip6r0_addr[total / 2] = in_rthdr0->ip6r0_addr[total / 2]; + out_rthdr0->ip6r0_segleft = total; + return 0; } diff --git a/inet/tst-inet6_rth.c b/inet/tst-inet6_rth.c new file mode 100644 index 0000000000..4c5c90ac01 --- /dev/null +++ b/inet/tst-inet6_rth.c @@ -0,0 +1,188 @@ +#include <stdio.h> +#include <string.h> +#include <arpa/inet.h> +#include <netinet/ip6.h> + +static int +do_test (void) +{ + int res = 0; + char buf[1000]; + void *p = inet6_rth_init (buf, 24, IPV6_RTHDR_TYPE_0, 0); + if (p == NULL) + { + puts ("first inet6_rth_init failed"); + res = 1; + } + else if (inet6_rth_add (p, &in6addr_any) == 0) + { + puts ("first inet6_rth_add succeeded"); + res = 1; + } + + p = inet6_rth_init (buf, 24, IPV6_RTHDR_TYPE_0, 1); + if (p == NULL) + { + puts ("second inet6_rth_init failed"); + res = 1; + } + else if (inet6_rth_add (p, &in6addr_any) != 0) + { + puts ("second inet6_rth_add failed"); + res = 1; + } + + for (int nseg = 4; nseg < 6; ++nseg) + { + printf ("nseg = %d\n", nseg); + + p = inet6_rth_init (buf, sizeof (buf), IPV6_RTHDR_TYPE_0, nseg); + if (p == NULL) + { + puts ("third inet6_rth_init failed"); + res = 1; + } + else + { + struct in6_addr tmp; + memset (&tmp, '\0', sizeof (tmp)); + + for (int i = 0; i < nseg; ++i) + { + tmp.s6_addr[0] = i; + if (inet6_rth_add (p, &tmp) != 0) + { + printf ("call %d of third inet6_rth_add failed\n", i + 1); + res = 1; + goto out; + } + } + ((struct ip6_rthdr0 *) p)->ip6r0_segleft = 0; + if (inet6_rth_segments (p) != nseg) + { + puts ("\ +inet6_rth_segments returned wrong value after loop with third inet6_rth_add"); + res = 1; + goto out; + } + + char buf2[1000]; + if (inet6_rth_reverse (p, buf2) != 0) + { + puts ("first inet6_rth_reverse call failed"); + res = 1; + goto out; + } + if (((struct ip6_rthdr0 *) buf2)->ip6r0_segleft != nseg) + { + puts ("segleft after first inet6_rth_reverse wrong"); + res = 1; + } + + if (inet6_rth_segments (p) != inet6_rth_segments (buf2)) + { + puts ("number of seconds after first inet6_rth_reverse differs"); + res = 1; + goto out; + } + + for (int i = 0; i < nseg; ++i) + { + struct in6_addr *addr = inet6_rth_getaddr (buf2, i); + if (addr == NULL) + { + printf ("call %d of first inet6_rth_getaddr failed\n", + i + 1); + res = 1; + } + else if (addr->s6_addr[0] != nseg - 1 - i + || memcmp (&addr->s6_addr[1], &in6addr_any.s6_addr[1], + sizeof (in6addr_any) + - sizeof (in6addr_any.s6_addr[0])) != 0) + { + char addrbuf[100]; + inet_ntop (AF_INET6, addr, addrbuf, sizeof (addrbuf)); + printf ("\ +address %d after first inet6_rth_reverse wrong (%s)\n", + i + 1, addrbuf); + res = 1; + } + } + out: + ; + } + + p = inet6_rth_init (buf, sizeof (buf), IPV6_RTHDR_TYPE_0, nseg); + if (p == NULL) + { + puts ("fourth inet6_rth_init failed"); + res = 1; + } + else + { + struct in6_addr tmp; + memset (&tmp, '\0', sizeof (tmp)); + + for (int i = 0; i < nseg; ++i) + { + tmp.s6_addr[0] = i; + if (inet6_rth_add (p, &tmp) != 0) + { + printf ("call %d of fourth inet6_rth_add failed\n", i + 1); + res = 1; + goto out2; + } + } + ((struct ip6_rthdr0 *) p)->ip6r0_segleft = 0; + if (inet6_rth_segments (p) != nseg) + { + puts ("\ +inet6_rth_segments returned wrong value after loop with fourth inet6_rth_add"); + res = 1; + goto out2; + } + + if (inet6_rth_reverse (p, p) != 0) + { + puts ("second inet6_rth_reverse call failed"); + res = 1; + goto out2; + } + if (((struct ip6_rthdr0 *) p)->ip6r0_segleft != nseg) + { + puts ("segleft after second inet6_rth_reverse wrong"); + res = 1; + } + + for (int i = 0; i < nseg; ++i) + { + struct in6_addr *addr = inet6_rth_getaddr (p, i); + if (addr == NULL) + { + printf ("call %d of second inet6_rth_getaddr failed\n", + i + 1); + res = 1; + } + else if (addr->s6_addr[0] != nseg - 1 - i + || memcmp (&addr->s6_addr[1], &in6addr_any.s6_addr[1], + sizeof (in6addr_any) + - sizeof (in6addr_any.s6_addr[0])) != 0) + { + char addrbuf[100]; + inet_ntop (AF_INET6, addr, addrbuf, sizeof (addrbuf)); + printf ("\ +address %d after second inet6_rth_reverse wrong (%s)\n", + i + 1, addrbuf); + res = 1; + } + } + out2: + ; + } + } + + return res; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/locale/iso-639.def b/locale/iso-639.def index 6d88767c8a..de78aa1c0d 100644 --- a/locale/iso-639.def +++ b/locale/iso-639.def @@ -303,6 +303,7 @@ DEFINE_LANGUAGE_CODE3 ("Mayan languages", myn, myn) DEFINE_LANGUAGE_CODE3 ("Mende", men, men) DEFINE_LANGUAGE_CODE3 ("Mi'kmaq; Micmac", mic, mic) DEFINE_LANGUAGE_CODE3 ("Minangkabau", min, min) +DEFINE_LANGUAGE_CODE3 ("Min Nan", nan, nan) DEFINE_LANGUAGE_CODE3 ("Mirandese", mwl, mwl) DEFINE_LANGUAGE_CODE3 ("Miscellaneous languages", mis, mis) DEFINE_LANGUAGE_CODE3 ("Mohawk", moh, moh) diff --git a/localedata/ChangeLog b/localedata/ChangeLog index 801a2a5dae..17f26f68c1 100644 --- a/localedata/ChangeLog +++ b/localedata/ChangeLog @@ -1,3 +1,22 @@ +2009-03-15 Ulrich Drepper <drepper@redhat.com> + + [BZ #9844] + * locales/iso14651_t1_common: Move U0138 entry. + + [BZ #9833] + * locales/ko_KR: Fix noexpr. Add nostr. + + [BZ #9891] + * locales/mt_MT: Fix spelling of August (Awwissu). + Patch by Martin Pitt. + +2009-03-14 Ulrich Drepper <drepper@redhat.com> + + [BZ #9916] + * SUPPORTED (SUPPORTED-LOCALES): Add nan_TW@latin. + * locales/nan_TW@latin: New file. + Contributed by Arne Goetje. + 2009-02-11 Ulrich Drepper <drepper@redhat.com> * locales/iso14651_t1_common: Add rules for sorting Malayalam. diff --git a/localedata/SUPPORTED b/localedata/SUPPORTED index cbf73a70c9..9a9cbd1275 100644 --- a/localedata/SUPPORTED +++ b/localedata/SUPPORTED @@ -290,6 +290,7 @@ ms_MY.UTF-8/UTF-8 \ ms_MY/ISO-8859-1 \ mt_MT.UTF-8/UTF-8 \ mt_MT/ISO-8859-3 \ +nan_TW@latin/UTF-8 \ nb_NO.UTF-8/UTF-8 \ nb_NO/ISO-8859-1 \ nds_DE/UTF-8 \ diff --git a/localedata/locales/iso14651_t1_common b/localedata/locales/iso14651_t1_common index 1c9963aaf6..6bdc795f4a 100644 --- a/localedata/locales/iso14651_t1_common +++ b/localedata/locales/iso14651_t1_common @@ -917,7 +917,7 @@ collating-symbol <k-ai_lenght_mark> # mlvw- denotes Malayalam vowel # ml-visarga - dentos Malayalam Visarga # consonant + virama is considered half of consonant or consonant without vowel part -# so it consonant + virama should be considered as cluster and should be +# so it consonant + virama should be considered as cluster and should be # sorted before the consonant. All consonants are considered to have an implicit a vowel # part associated with it. collating-element <ml-chillu-n> from "<U0D28><U0D4D>" @@ -2362,7 +2362,6 @@ endif <U1E33> <k>;<BPT>;<MIN>;IGNORE # 337 ḳ <U1E35> <k>;<BMA>;<MIN>;IGNORE # 338 ḵ <U0199> <k>;<CRL>;<MIN>;IGNORE # 339 Æ™ -<U0138> <k>;<PCL>;<MIN>;IGNORE # 340 <kk> <U006C> <l>;<BAS>;<MIN>;IGNORE # 341 l <U013A> <l>;<ACA>;<MIN>;IGNORE # 342 <l'> <U013E> <l>;<CAR>;<MIN>;IGNORE # 343 <l<> @@ -2436,6 +2435,7 @@ endif <U1E55> <p>;<ACA>;<MIN>;IGNORE # 411 <p'> <U1E57> <p>;<PCT>;<MIN>;IGNORE # 412 <p.> <U0071> <q>;<BAS>;<MIN>;IGNORE # 413 q +<U0138> <q>;<PCL>;<MIN>;IGNORE # 340 <kk> <U0072> <r>;<BAS>;<MIN>;IGNORE # 414 r <U0155> <r>;<ACA>;<MIN>;IGNORE # 415 <r'> <U0159> <r>;<CAR>;<MIN>;IGNORE # 416 <r<> @@ -4309,7 +4309,7 @@ order_start <MALAYALAM>;forward;forward;forward;forward,position <ml-dh> "<ml-dha><ml-virama>";<BAS>;<MIN>;IGNORE <U0D22> "<ml-dha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE <ml-chillu-nn> "<ml-nna><ml-virama>";<BAS>;<MIN>;IGNORE # à´£àµâ€ = à´£ + ൠ+ zwj -<U0D23> "<ml-nna><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # à´£ = à´£ + ൠ+ à´… +<U0D23> "<ml-nna><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # à´£ = à´£ + ൠ+ à´… <ml-th> "<ml-tha><ml-virama>";<BAS>;<MIN>;IGNORE <U0D24> "<ml-tha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE <ml-thh> "<ml-thha><ml-virama>";<BAS>;<MIN>;IGNORE @@ -4329,14 +4329,14 @@ order_start <MALAYALAM>;forward;forward;forward;forward,position <ml-bh> "<ml-bha><ml-virama>";<BAS>;<MIN>;IGNORE <U0D2D> "<ml-bha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE <U0D02> "<ml-ma><ml-virama>";<BAS>;<MIN>;IGNORE # à´‚ = à´® + ൠ-<ml-m> "<ml-ma><ml-virama>";"<BAS><ml-virama>";<MIN>;IGNORE # à´‚ = à´® + ൠ-<U0D2E> "<ml-ma><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # à´® = à´® + ൠ+ à´… +<ml-m> "<ml-ma><ml-virama>";"<BAS><ml-virama>";<MIN>;IGNORE # à´‚ = à´® + ൠ+<U0D2E> "<ml-ma><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # à´® = à´® + ൠ+ à´… <ml-y> "<ml-ya><ml-virama>";<BAS>;<MIN>;IGNORE <U0D2F> "<ml-ya><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE <ml-chillu-r> "<ml-ra><ml-virama>";<BAS>;<MIN>;IGNORE # à´° = à´° + ൠ+ zwj -<U0D30> "<ml-ra><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # à´° = à´° + ൠ+ à´… +<U0D30> "<ml-ra><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # à´° = à´° + ൠ+ à´… <ml-chillu-l> <ml-la>;<BAS>;<MIN>;IGNORE # à´²àµâ€ = à´² + ൠ+ zwj -<U0D32> "<ml-la><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # à´² = à´² + ൠ+ à´… +<U0D32> "<ml-la><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # à´² = à´² + ൠ+ à´… <ml-v> "<ml-va><ml-virama>";<BAS>;<MIN>;IGNORE <U0D35> "<ml-va><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE <ml-ss> "<ml-ssa><ml-virama>";<BAS>;<MIN>;IGNORE @@ -4348,7 +4348,7 @@ order_start <MALAYALAM>;forward;forward;forward;forward,position <ml-h> "<ml-ha><ml-virama>";<BAS>;<MIN>;IGNORE <U0D39> "<ml-ha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE <ml-chillu-ll> "<ml-lla><ml-virama>";<BAS>;<MIN>;IGNORE # à´³àµâ€ = à´³ + ൠ+ zwj -<U0D33> "<ml-lla><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # à´³ = à´³ + ൠ+ à´… +<U0D33> "<ml-lla><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # à´³ = à´³ + ൠ+ à´… <ml-zh> "<ml-zha><ml-virama>";<BAS>;<MIN>;IGNORE <U0D34> "<ml-zha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE <ml-rr> "<ml-rra><ml-virama>";<BAS>;<MIN>;IGNORE diff --git a/localedata/locales/ko_KR b/localedata/locales/ko_KR index 43915c2a82..59653ad188 100644 --- a/localedata/locales/ko_KR +++ b/localedata/locales/ko_KR @@ -6202,7 +6202,9 @@ LC_MESSAGES yesexpr "<U005E><U005B><U0079><U0059><UC608><U005D>" -noexpr "<U005E><U005B><U006E><U004E><UC544><UB2C8><UC624><U005D>" +noexpr "<U005E><U005B><U006E><U004E><UC544><U005D>" + +nostr "<UC544><UB2C8><UC624>" END LC_MESSAGES diff --git a/localedata/locales/mt_MT b/localedata/locales/mt_MT index 81c134fde1..d6af96b1ef 100644 --- a/localedata/locales/mt_MT +++ b/localedata/locales/mt_MT @@ -188,7 +188,7 @@ day "<U0069><U006C><U002D><U0126><U0061><U0064><U0064>";/ abmon "<U004A><U0061><U006E>";"<U0046><U0072><U0061>";/ "<U004D><U0061><U0072>";"<U0041><U0070><U0072>";/ "<U004D><U0065><U006A>";"<U0120><U0075><U006E>";/ - "<U004C><U0075><U006C>";"<U0041><U0077><U0069>";/ + "<U004C><U0075><U006C>";"<U0041><U0077><U0077>";/ "<U0053><U0065><U0074>";"<U004F><U0074><U0074>";/ "<U004E><U006F><U0076>";"<U0044><U0069><U010B>" % @@ -200,7 +200,7 @@ mon "<U004A><U0061><U006E><U006E><U0061><U0072>";/ "<U004D><U0065><U006A><U006A><U0075>";/ "<U0120><U0075><U006E><U006A><U0075>";/ "<U004C><U0075><U006C><U006A><U0075>";/ - "<U0041><U0077><U0069><U0073><U0073><U0075>";/ + "<U0041><U0077><U0077><U0069><U0073><U0073><U0075>";/ "<U0053><U0065><U0074><U0074><U0065><U006D><U0062><U0072><U0075>";/ "<U004F><U0074><U0074><U0075><U0062><U0072><U0075>";/ "<U004E><U006F><U0076><U0065><U006D><U0062><U0072><U0075>";/ diff --git a/localedata/locales/nan_TW@latin b/localedata/locales/nan_TW@latin new file mode 100644 index 0000000000..bf8a6cd903 --- /dev/null +++ b/localedata/locales/nan_TW@latin @@ -0,0 +1,205 @@ +comment_char % +escape_char / +% +% Minnan Language Locale for Taiwan +% Source: +% Contact: Arne Goetje +% Email: arne@ubuntu.com +% Language: nan +% Territory: TW +% Revision: 0.1 +% Date: 2008-06-16 +% Users: general +% Charset: UTF-8 +% Distribution and use is free, also +% for commercial purposes. + +LC_IDENTIFICATION +title "Minnan language locale for Taiwan" +source "" +address "" +contact "Arne Goetje" +email "arne@canonical.com" +tel "" +fax "" +language "Minnan" +territory "Taiwan" +revision "0.1" +date "2008-06-16" + +category "nan_TW@latin:2000";LC_IDENTIFICATION +category "nan_TW@latin:2000";LC_CTYPE +category "nan_TW@latin:2000";LC_COLLATE +category "nan_TW@latin:2000";LC_TIME +category "nan_TW@latin:2000";LC_NUMERIC +category "nan_TW@latin:2000";LC_PAPER +category "nan_TW@latin:2000";LC_TELEPHONE +category "nan_TW@latin:2000";LC_MEASUREMENT +category "nan_TW@latin:2000";LC_ADDRESS +category "nan_TW@latin:2000";LC_MESSAGES +category "nan_TW@latin:2000";LC_MONETARY + +END LC_IDENTIFICATION + +LC_CTYPE +copy "i18n" + +translit_start + +% accents are simply omitted if they cannot be represented. +include "translit_combining";"" + +translit_end + +END LC_CTYPE + +LC_COLLATE +copy "iso14651_t1" + +%% a b c d e f g h i j k l m n o o͘ p q r s t u v w x y z â¿ + +collating-element <oo> from "<U006F><U0358>" +collating-element <OO> from "<U004F><U0358>" +collating-element <nn> from "<U207F>" + +collating-symbol <CAP-MIN> +collating-symbol <MIN-CAP> + +reorder-after <MIN> +<MIN-CAP> +reorder-after <CAP> +<CAP-MIN> + +reorder-after <U006E> +<oo> +reorder-after <U004E> +<OO> +reorder-after <U007A> +<nn> +reorder-after <U005A> +<nn> + +reorder-end + +END LC_COLLATE + +LC_MONETARY +copy "zh_TW" +END LC_MONETARY + +LC_NUMERIC +copy "zh_TW" +END LC_NUMERIC + +LC_TIME +abday "<U006C><U0070>";/ + "<U0070><U0031>";/ + "<U0070><U0032>";/ + "<U0070><U0033>";/ + "<U0070><U0034>";/ + "<U0070><U0035>";/ + "<U0070><U0036>" +day "<U006C><U00E9><U002D><U0070><U00E0><U0069><U002D><U006A><U0069><U030D><U0074>";/ + "<U0070><U00E0><U0069><U002D><U0069><U0074>";/ + "<U0070><U00E0><U0069><U002D><U006A><U012B>";/ + "<U0070><U00E0><U0069><U002D><U0073><U0061><U207F>";/ + "<U0070><U00E0><U0069><U002D><U0073><U00EC>";/ + "<U0070><U00E0><U0069><U002D><U0067><U014D><U0358>";/ + "<U0070><U00E0><U0069><U002D><U006C><U0061><U030D><U006B>" +abmon "<U0031><U0067>";/ + "<U0032><U0067>";/ + "<U0033><U0067>";/ + "<U0034><U0067>";/ + "<U0035><U0067>";/ + "<U0036><U0067>";/ + "<U0037><U0067>";/ + "<U0038><U0067>";/ + "<U0039><U0067>";/ + "<U0031><U0030><U0067>";/ + "<U0031><U0031><U0067>";/ + "<U0031><U0032><U0067>" +mon "<U0031><U0067><U006F><U0065><U030D><U0068>";/ + "<U0032><U0067><U006F><U0065><U030D><U0068>";/ + "<U0033><U0067><U006F><U0065><U030D><U0068>";/ + "<U0034><U0067><U006F><U0065><U030D><U0068>";/ + "<U0035><U0067><U006F><U0065><U030D><U0068>";/ + "<U0036><U0067><U006F><U0065><U030D><U0068>";/ + "<U0037><U0067><U006F><U0065><U030D><U0068>";/ + "<U0038><U0067><U006F><U0065><U030D><U0068>";/ + "<U0039><U0067><U006F><U0065><U030D><U0068>";/ + "<U0031><U0030><U0067><U006F><U0065><U030D><U0068>";/ + "<U0031><U0031><U0067><U006F><U0065><U030D><U0068>";/ + "<U0031><U0032><U0067><U006F><U0065><U030D><U0068>" +% +d_t_fmt "<U0025><U0059><U0020><U0025><U0062><U0020><U0025><U0064><U0020><U0028><U0025><U0061><U0029><U0020><U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A>" +d_fmt "<U0025><U0046>" +t_fmt "<U0025><U0072>" +am_pm "<U0074><U00E9><U006E><U0067><U002D><U0070><U006F><U0358>";"<U0113><U002D><U0070><U006F><U0358>" +t_fmt_ampm "<U0025><U0049><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U0070>" +timezone "<U0054><U0053><U0054><U002D><U0038>" +date_fmt "<U0025><U0059><U0020><U0025><U0062><U0020><U0025><U0064><U0020><U0028><U0025><U0061><U0029><U0020><U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A>" +END LC_TIME + +LC_MESSAGES + +% "^[sS].*" for "Yes" +yesexpr "<U005E><U005B><U0073><U0053><U005D><U002E><U002A>" + +% "^[mM].*" for "No" +noexpr "<U005E><U005B><U006D><U004D><U005D><U002E><U002A>" + +% "SÄ«" for "Yes" +yesstr "<U0053><U012B>" + +% "MÌ„-sÄ«" for "No" +nostr "<U004D><U0304><U002D><U0053><U012B>" + +END LC_MESSAGES + +LC_PAPER +height 297 +width 210 +END LC_PAPER + +LC_MEASUREMENT +measurement 1 +END LC_MEASUREMENT + +LC_NAME +%FIXME +name_fmt "<U0025><U0064><U0025><U0074><U0025><U0067><U0025><U0074>/ +<U0025><U006D><U0025><U0074><U0025><U0066>" +name_miss "<U006B><U006F><U0358><U002D><U006E><U0069><U00FB>" +name_mr "<U0073><U0069><U0061><U006E><U002D><U0073><U0069><U207F>" +name_mrs "<U006C><U00FA><U002D><U0073><U016B>" +name_ms "<U0073><U0069><U00F3><U002D><U0063><U0068><U0069><U00E1>" +END LC_NAME + +LC_ADDRESS +% postal_fmt: "%f%N%a%N%d%N%b%N%r %e %h %s%N%z %T%N%c%N" +postal_fmt "<U0025><U0066><U0025><U004E><U0025><U0061><U0025><U004E>/ +<U0025><U0064><U0025><U004E><U0025><U0062><U0025><U004E><U0025><U0072>/ +<U0020><U0025><U0065><U0020><U0025><U0068><U0020><U0025><U0073><U0025>/ +<U004E><U0025><U007A><U0020><U0025><U0054><U0025>/ +<U004E><U0025><U0063><U0025><U004E>" +% Reference: http://www.un.org/Depts/unsd/methods/m49alpha.htm +% http://www.isbn.spk-berlin.de/html/prefix.htm +% country_ab2: TW +% country_ab3: TWN +% country_isbn: 957 +country_name "<U0054><U00E2><U0069><U002D><U006F><U00E2><U006E>" +%country_post "FIXME" +country_ab2 "<U0054><U0057>" +country_ab3 "<U0054><U0057><U004E>" +country_num 158 +%country_car "FIXME" +country_isbn "<U0039><U0035><U0037>" +%lang_name "Bân-lâm-gú, HÅ-ló-oÄ“" +lang_name "<U0042><U00E2><U006E><U002D><U006C><U00E2><U006D><U002D><U0067><U00FA><U002C><U0020><U0048><U014D><U002D><U006C><U00F3><U002D><U006F><U0113>" +lang_term "<U006E><U0061><U006E>" +lang_lib "<U006E><U0061><U006E>" +END LC_ADDRESS + +LC_TELEPHONE +copy "zh_TW" +END LC_TELEPHONE diff --git a/malloc/Makefile b/malloc/Makefile index 22b14eac77..1099335fff 100644 --- a/malloc/Makefile +++ b/malloc/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1991-1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007 +# Copyright (C) 1991-1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2009 # Free Software Foundation, Inc. # This file is part of the GNU C Library. @@ -124,6 +124,9 @@ endif tst-mcheck-ENV = MALLOC_CHECK_=3 +ifeq ($(experimental-malloc),yes) +CPPFLAGS-malloc.c += -DPER_THREAD -DATOMIC_FASTBINS +endif # Uncomment this for test releases. For public releases it is too expensive. #CPPFLAGS-malloc.o += -DMALLOC_DEBUG=1 diff --git a/malloc/arena.c b/malloc/arena.c index cc03dc4a5b..f280d38811 100644 --- a/malloc/arena.c +++ b/malloc/arena.c @@ -1,5 +1,5 @@ /* Malloc implementation for multiple threads without lock contention. - Copyright (C) 2001,2002,2003,2004,2005,2006,2007 + Copyright (C) 2001,2002,2003,2004,2005,2006,2007,2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Wolfram Gloger <wg@malloc.de>, 2001. @@ -78,6 +78,10 @@ extern int sanity_check_heap_info_alignment[(sizeof (heap_info) static tsd_key_t arena_key; static mutex_t list_lock; +#ifdef PER_THREAD +static size_t narenas; +static mstate free_list; +#endif #if THREAD_STATS static int stat_n_heaps; @@ -105,13 +109,30 @@ int __malloc_initialized = -1; in the new arena. */ #define arena_get(ptr, size) do { \ + arena_lookup(ptr); \ + arena_lock(ptr, size); \ +} while(0) + +#define arena_lookup(ptr) do { \ Void_t *vptr = NULL; \ ptr = (mstate)tsd_getspecific(arena_key, vptr); \ +} while(0) + +#ifdef PER_THREAD +#define arena_lock(ptr, size) do { \ + if(ptr) \ + (void)mutex_lock(&ptr->mutex); \ + else \ + ptr = arena_get2(ptr, (size)); \ +} while(0) +#else +#define arena_lock(ptr, size) do { \ if(ptr && !mutex_trylock(&ptr->mutex)) { \ THREAD_STAT(++(ptr->stat_lock_direct)); \ } else \ ptr = arena_get2(ptr, (size)); \ } while(0) +#endif /* find the heap and corresponding arena for a given ptr */ @@ -219,6 +240,11 @@ free_atfork(Void_t* mem, const Void_t *caller) } #endif +#ifdef ATOMIC_FASTBINS + ar_ptr = arena_for_chunk(p); + tsd_getspecific(arena_key, vptr); + _int_free(ar_ptr, p, vptr == ATFORK_ARENA_PTR); +#else ar_ptr = arena_for_chunk(p); tsd_getspecific(arena_key, vptr); if(vptr != ATFORK_ARENA_PTR) @@ -226,6 +252,7 @@ free_atfork(Void_t* mem, const Void_t *caller) _int_free(ar_ptr, p); if(vptr != ATFORK_ARENA_PTR) (void)mutex_unlock(&ar_ptr->mutex); +#endif } @@ -312,8 +339,17 @@ ptmalloc_unlock_all2 (void) __malloc_hook = save_malloc_hook; __free_hook = save_free_hook; #endif +#ifdef PER_THREAD + free_list = NULL; +#endif for(ar_ptr = &main_arena;;) { mutex_init(&ar_ptr->mutex); +#ifdef PER_THREAD + if (ar_ptr != save_arena) { + ar_ptr->next_free = free_list; + free_list = ar_ptr; + } +#endif ar_ptr = ar_ptr->next; if(ar_ptr == &main_arena) break; } @@ -377,6 +413,11 @@ ptmalloc_init_minimal (void) mp_.mmap_threshold = DEFAULT_MMAP_THRESHOLD; mp_.trim_threshold = DEFAULT_TRIM_THRESHOLD; mp_.pagesize = malloc_getpagesize; +#ifdef PER_THREAD +# define NARENAS_FROM_NCORES(n) ((n) * (sizeof(long) == 4 ? 2 : 8)) + mp_.arena_test = NARENAS_FROM_NCORES (1); + narenas = 1; +#endif } @@ -529,9 +570,25 @@ ptmalloc_init (void) } break; case 9: - if (! secure && memcmp (envline, "MMAP_MAX_", 9) == 0) - mALLOPt(M_MMAP_MAX, atoi(&envline[10])); + if (! secure) + { + if (memcmp (envline, "MMAP_MAX_", 9) == 0) + mALLOPt(M_MMAP_MAX, atoi(&envline[10])); +#ifdef PER_THREAD + else if (memcmp (envline, "ARENA_MAX", 9) == 0) + mALLOPt(M_ARENA_MAX, atoi(&envline[10])); +#endif + } break; +#ifdef PER_THREAD + case 10: + if (! secure) + { + if (memcmp (envline, "ARENA_TEST", 10) == 0) + mALLOPt(M_ARENA_TEST, atoi(&envline[11])); + } + break; +#endif case 15: if (! secure) { @@ -875,9 +932,110 @@ _int_new_arena(size_t size) top(a) = (mchunkptr)ptr; set_head(top(a), (((char*)h + h->size) - ptr) | PREV_INUSE); + tsd_setspecific(arena_key, (Void_t *)a); + mutex_init(&a->mutex); + (void)mutex_lock(&a->mutex); + +#ifdef PER_THREAD + (void)mutex_lock(&list_lock); +#endif + + /* Add the new arena to the global list. */ + a->next = main_arena.next; + atomic_write_barrier (); + main_arena.next = a; + +#ifdef PER_THREAD + ++narenas; + + (void)mutex_unlock(&list_lock); +#endif + + THREAD_STAT(++(a->stat_lock_loop)); + return a; } + +#ifdef PER_THREAD +static mstate +get_free_list (void) +{ + mstate result = free_list; + if (result != NULL) + { + (void)mutex_lock(&list_lock); + result = free_list; + if (result != NULL) + free_list = result->next_free; + (void)mutex_unlock(&list_lock); + + if (result != NULL) + { + (void)mutex_lock(&result->mutex); + tsd_setspecific(arena_key, (Void_t *)result); + THREAD_STAT(++(result->stat_lock_loop)); + } + } + + return result; +} + + +static mstate +reused_arena (void) +{ + if (narenas <= mp_.arena_test) + return NULL; + + static int narenas_limit; + if (narenas_limit == 0) + { + if (mp_.arena_max != 0) + narenas_limit = mp_.arena_max; + else + { + int n = __get_nprocs (); + + if (n >= 1) + narenas_limit = NARENAS_FROM_NCORES (n); + else + /* We have no information about the system. Assume two + cores. */ + narenas_limit = NARENAS_FROM_NCORES (2); + } + } + + if (narenas < narenas_limit) + return NULL; + + mstate result; + static mstate next_to_use; + if (next_to_use == NULL) + next_to_use = &main_arena; + + result = next_to_use; + do + { + if (!mutex_trylock(&result->mutex)) + goto out; + + result = result->next; + } + while (result != next_to_use); + + /* No arena available. Wait for the next in line. */ + (void)mutex_lock(&result->mutex); + + out: + tsd_setspecific(arena_key, (Void_t *)result); + THREAD_STAT(++(result->stat_lock_loop)); + next_to_use = result->next; + + return result; +} +#endif + static mstate internal_function #if __STD_C @@ -888,6 +1046,12 @@ arena_get2(a_tsd, size) mstate a_tsd; size_t size; { mstate a; +#ifdef PER_THREAD + if ((a = get_free_list ()) == NULL + && (a = reused_arena ()) == NULL) + /* Nothing immediately available, so generate a new arena. */ + a = _int_new_arena(size); +#else if(!a_tsd) a = a_tsd = &main_arena; else { @@ -930,24 +1094,31 @@ arena_get2(a_tsd, size) mstate a_tsd; size_t size; /* Nothing immediately available, so generate a new arena. */ a = _int_new_arena(size); - if(a) - { - tsd_setspecific(arena_key, (Void_t *)a); - mutex_init(&a->mutex); - mutex_lock(&a->mutex); /* remember result */ - - /* Add the new arena to the global list. */ - a->next = main_arena.next; - atomic_write_barrier (); - main_arena.next = a; - - THREAD_STAT(++(a->stat_lock_loop)); - } (void)mutex_unlock(&list_lock); +#endif return a; } +#ifdef PER_THREAD +static void __attribute__ ((section ("__libc_thread_freeres_fn"))) +arena_thread_freeres (void) +{ + Void_t *vptr = NULL; + mstate a = tsd_getspecific(arena_key, vptr); + tsd_setspecific(arena_key, NULL); + + if (a != NULL) + { + (void)mutex_lock(&list_lock); + a->next_free = free_list; + free_list = a; + (void)mutex_unlock(&list_lock); + } +} +text_set_element (__libc_thread_subfreeres, arena_thread_freeres); +#endif + #endif /* USE_ARENAS */ /* diff --git a/malloc/hooks.c b/malloc/hooks.c index 9659ec5fbe..fe89db83f4 100644 --- a/malloc/hooks.c +++ b/malloc/hooks.c @@ -275,17 +275,13 @@ free_check(mem, caller) Void_t* mem; const Void_t *caller; mchunkptr p; if(!mem) return; - (void)mutex_lock(&main_arena.mutex); p = mem2chunk_check(mem, NULL); if(!p) { - (void)mutex_unlock(&main_arena.mutex); - malloc_printerr(check_action, "free(): invalid pointer", mem); return; } #if HAVE_MMAP if (chunk_is_mmapped(p)) { - (void)mutex_unlock(&main_arena.mutex); munmap_chunk(p); return; } @@ -293,8 +289,13 @@ free_check(mem, caller) Void_t* mem; const Void_t *caller; #if 0 /* Erase freed memory. */ memset(mem, 0, chunksize(p) - (SIZE_SZ+1)); #endif +#ifdef ATOMIC_FASTBINS + _int_free(&main_arena, p, 0); +#else + (void)mutex_lock(&main_arena.mutex); _int_free(&main_arena, p); (void)mutex_unlock(&main_arena.mutex); +#endif } static Void_t* @@ -472,7 +473,11 @@ free_starter(mem, caller) Void_t* mem; const Void_t *caller; return; } #endif +#ifdef ATOMIC_FASTBINS + _int_free(&main_arena, p, 1); +#else _int_free(&main_arena, p); +#endif } # endif /* !defiend NO_STARTER */ @@ -584,7 +589,7 @@ public_sET_STATe(Void_t* msptr) clear_fastchunks(&main_arena); set_max_fast(DEFAULT_MXFAST); for (i=0; i<NFASTBINS; ++i) - main_arena.fastbins[i] = 0; + fastbin (&main_arena, i) = 0; for (i=0; i<BINMAPSIZE; ++i) main_arena.binmap[i] = 0; top(&main_arena) = ms->av[2]; diff --git a/malloc/malloc.c b/malloc/malloc.c index 12e23b0f9b..bb7ea36c80 100644 --- a/malloc/malloc.c +++ b/malloc/malloc.c @@ -208,7 +208,7 @@ Tuning options that are also dynamically changeable via mallopt: - DEFAULT_MXFAST 64 + DEFAULT_MXFAST 64 (for 32bit), 128 (for 64bit) DEFAULT_TRIM_THRESHOLD 128 * 1024 DEFAULT_TOP_PAD 0 DEFAULT_MMAP_THRESHOLD 128 * 1024 @@ -254,8 +254,12 @@ #include <malloc-machine.h> #ifdef _LIBC +#ifdef ATOMIC_FASTBINS +#include <atomic.h> +#endif #include <stdio-common/_itoa.h> #include <bits/wordsize.h> +#include <sys/sysinfo.h> #endif #ifdef __cplusplus @@ -321,12 +325,7 @@ extern "C" { or other mallocs available that do this. */ -#if MALLOC_DEBUG #include <assert.h> -#else -#undef assert -#define assert(x) ((void)0) -#endif /* @@ -1308,7 +1307,7 @@ int __posix_memalign(void **, size_t, size_t); #endif #ifndef DEFAULT_MXFAST -#define DEFAULT_MXFAST 64 +#define DEFAULT_MXFAST (64 * SIZE_SZ / 4) #endif @@ -1582,7 +1581,11 @@ typedef struct malloc_chunk* mchunkptr; #if __STD_C static Void_t* _int_malloc(mstate, size_t); +#ifdef ATOMIC_FASTBINS +static void _int_free(mstate, mchunkptr, int); +#else static void _int_free(mstate, mchunkptr); +#endif static Void_t* _int_realloc(mstate, mchunkptr, INTERNAL_SIZE_T); static Void_t* _int_memalign(mstate, size_t, size_t); static Void_t* _int_valloc(mstate, size_t); @@ -2239,12 +2242,15 @@ typedef struct malloc_chunk* mbinptr; */ typedef struct malloc_chunk* mfastbinptr; +#define fastbin(ar_ptr, idx) ((ar_ptr)->fastbinsY[idx]) /* offset 2 to use otherwise unindexable first 2 bins */ -#define fastbin_index(sz) ((((unsigned int)(sz)) >> 3) - 2) +#define fastbin_index(sz) \ + ((((unsigned int)(sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2) + /* The maximum fastbin request size we support */ -#define MAX_FAST_SIZE 80 +#define MAX_FAST_SIZE (80 * SIZE_SZ / 4) #define NFASTBINS (fastbin_index(request2size(MAX_FAST_SIZE))+1) @@ -2279,8 +2285,13 @@ typedef struct malloc_chunk* mfastbinptr; #define FASTCHUNKS_BIT (1U) #define have_fastchunks(M) (((M)->flags & FASTCHUNKS_BIT) == 0) +#ifdef ATOMIC_FASTBINS +#define clear_fastchunks(M) catomic_or (&(M)->flags, FASTCHUNKS_BIT) +#define set_fastchunks(M) catomic_and (&(M)->flags, ~FASTCHUNKS_BIT) +#else #define clear_fastchunks(M) ((M)->flags |= FASTCHUNKS_BIT) #define set_fastchunks(M) ((M)->flags &= ~FASTCHUNKS_BIT) +#endif /* NONCONTIGUOUS_BIT indicates that MORECORE does not return contiguous @@ -2327,7 +2338,7 @@ struct malloc_state { #endif /* Fastbins */ - mfastbinptr fastbins[NFASTBINS]; + mfastbinptr fastbinsY[NFASTBINS]; /* Base of the topmost chunk -- not otherwise kept in a bin */ mchunkptr top; @@ -2344,6 +2355,11 @@ struct malloc_state { /* Linked list */ struct malloc_state *next; +#ifdef PER_THREAD + /* Linked list for free arenas. */ + struct malloc_state *next_free; +#endif + /* Memory allocated from the system in this arena. */ INTERNAL_SIZE_T system_mem; INTERNAL_SIZE_T max_system_mem; @@ -2354,6 +2370,10 @@ struct malloc_par { unsigned long trim_threshold; INTERNAL_SIZE_T top_pad; INTERNAL_SIZE_T mmap_threshold; +#ifdef PER_THREAD + INTERNAL_SIZE_T arena_test; + INTERNAL_SIZE_T arena_max; +#endif /* Memory map support */ int n_mmaps; @@ -2391,6 +2411,13 @@ static struct malloc_state main_arena; static struct malloc_par mp_; +#ifdef PER_THREAD +/* Non public mallopt parameters. */ +#define M_ARENA_TEST -7 +#define M_ARENA_MAX -8 +#endif + + /* Maximum size of memory handled in fastbins. */ static INTERNAL_SIZE_T global_max_fast; @@ -3037,8 +3064,10 @@ static Void_t* sYSMALLOc(nb, av) INTERNAL_SIZE_T nb; mstate av; /* Precondition: not enough current space to satisfy nb request */ assert((unsigned long)(old_size) < (unsigned long)(nb + MINSIZE)); +#ifndef ATOMIC_FASTBINS /* Precondition: all fastbins are consolidated */ assert(!have_fastchunks(av)); +#endif if (av != &main_arena) { @@ -3084,7 +3113,11 @@ static Void_t* sYSMALLOc(nb, av) INTERNAL_SIZE_T nb; mstate av; set_head(chunk_at_offset(old_top, old_size), (2*SIZE_SZ)|PREV_INUSE); set_foot(chunk_at_offset(old_top, old_size), (2*SIZE_SZ)); set_head(old_top, old_size|PREV_INUSE|NON_MAIN_ARENA); +#ifdef ATOMIC_FASTBINS + _int_free(av, old_top, 1); +#else _int_free(av, old_top); +#endif } else { set_head(old_top, (old_size + 2*SIZE_SZ)|PREV_INUSE); set_foot(old_top, (old_size + 2*SIZE_SZ)); @@ -3323,7 +3356,11 @@ static Void_t* sYSMALLOc(nb, av) INTERNAL_SIZE_T nb; mstate av; /* If possible, release the rest. */ if (old_size >= MINSIZE) { +#ifdef ATOMIC_FASTBINS + _int_free(av, old_top, 1); +#else _int_free(av, old_top); +#endif } } @@ -3545,7 +3582,40 @@ public_mALLOc(size_t bytes) if (__builtin_expect (hook != NULL, 0)) return (*hook)(bytes, RETURN_ADDRESS (0)); - arena_get(ar_ptr, bytes); + arena_lookup(ar_ptr); +#if 0 + // XXX We need double-word CAS and fastbins must be extended to also + // XXX hold a generation counter for each entry. + if (ar_ptr) { + INTERNAL_SIZE_T nb; /* normalized request size */ + checked_request2size(bytes, nb); + if (nb <= get_max_fast ()) { + long int idx = fastbin_index(nb); + mfastbinptr* fb = &fastbin (ar_ptr, idx); + mchunkptr pp = *fb; + mchunkptr v; + do + { + v = pp; + if (v == NULL) + break; + } + while ((pp = catomic_compare_and_exchange_val_acq (fb, v->fd, v)) != v); + if (v != 0) { + if (__builtin_expect (fastbin_index (chunksize (v)) != idx, 0)) + malloc_printerr (check_action, "malloc(): memory corruption (fast)", + chunk2mem (v)); + check_remalloced_chunk(ar_ptr, v, nb); + void *p = chunk2mem(v); + if (__builtin_expect (perturb_byte, 0)) + alloc_perturb (p, bytes); + return p; + } + } + } +#endif + + arena_lock(ar_ptr, bytes); if(!ar_ptr) return 0; victim = _int_malloc(ar_ptr, bytes); @@ -3612,18 +3682,22 @@ public_fREe(Void_t* mem) #endif ar_ptr = arena_for_chunk(p); -#if THREAD_STATS +#ifdef ATOMIC_FASTBINS + _int_free(ar_ptr, p, 0); +#else +# if THREAD_STATS if(!mutex_trylock(&ar_ptr->mutex)) ++(ar_ptr->stat_lock_direct); else { (void)mutex_lock(&ar_ptr->mutex); ++(ar_ptr->stat_lock_wait); } -#else +# else (void)mutex_lock(&ar_ptr->mutex); -#endif +# endif _int_free(ar_ptr, p); (void)mutex_unlock(&ar_ptr->mutex); +#endif } #ifdef libc_hidden_def libc_hidden_def (public_fREe) @@ -3699,7 +3773,7 @@ public_rEALLOc(Void_t* oldmem, size_t bytes) (void)mutex_lock(&ar_ptr->mutex); #endif -#ifndef NO_THREADS +#if !defined NO_THREADS && !defined PER_THREAD /* As in malloc(), remember this arena for the next allocation. */ tsd_setspecific(arena_key, (Void_t *)ar_ptr); #endif @@ -3717,18 +3791,22 @@ public_rEALLOc(Void_t* oldmem, size_t bytes) if (newp != NULL) { MALLOC_COPY (newp, oldmem, oldsize - SIZE_SZ); -#if THREAD_STATS +#ifdef ATOMIC_FASTBINS + _int_free(ar_ptr, oldp, 0); +#else +# if THREAD_STATS if(!mutex_trylock(&ar_ptr->mutex)) ++(ar_ptr->stat_lock_direct); else { (void)mutex_lock(&ar_ptr->mutex); ++(ar_ptr->stat_lock_wait); } -#else +# else (void)mutex_lock(&ar_ptr->mutex); -#endif +# endif _int_free(ar_ptr, oldp); (void)mutex_unlock(&ar_ptr->mutex); +#endif } } @@ -4130,7 +4208,6 @@ _int_malloc(mstate av, size_t bytes) INTERNAL_SIZE_T nb; /* normalized request size */ unsigned int idx; /* associated bin index */ mbinptr bin; /* associated bin */ - mfastbinptr* fb; /* associated fastbin */ mchunkptr victim; /* inspected/selected chunk */ INTERNAL_SIZE_T size; /* its size */ @@ -4164,13 +4241,28 @@ _int_malloc(mstate av, size_t bytes) */ if ((unsigned long)(nb) <= (unsigned long)(get_max_fast ())) { - long int idx = fastbin_index(nb); - fb = &(av->fastbins[idx]); - if ( (victim = *fb) != 0) { + idx = fastbin_index(nb); + mfastbinptr* fb = &fastbin (av, idx); +#ifdef ATOMIC_FASTBINS + mchunkptr pp = *fb; + do + { + victim = pp; + if (victim == NULL) + break; + } + while ((pp = catomic_compare_and_exchange_val_acq (fb, victim->fd, victim)) + != victim); +#else + victim = *fb; +#endif + if (victim != 0) { if (__builtin_expect (fastbin_index (chunksize (victim)) != idx, 0)) malloc_printerr (check_action, "malloc(): memory corruption (fast)", chunk2mem (victim)); +#ifndef ATOMIC_FASTBINS *fb = victim->fd; +#endif check_remalloced_chunk(av, victim, nb); void *p = chunk2mem(victim); if (__builtin_expect (perturb_byte, 0)) @@ -4560,6 +4652,18 @@ _int_malloc(mstate av, size_t bytes) return p; } +#ifdef ATOMIC_FASTBINS + /* When we are using atomic ops to free fast chunks we can get + here for all block sizes. */ + else if (have_fastchunks(av)) { + malloc_consolidate(av); + /* restore original bin index */ + if (in_smallbin_range(nb)) + idx = smallbin_index(nb); + else + idx = largebin_index(nb); + } +#else /* If there is space available in fastbins, consolidate and retry, to possibly avoid expanding memory. This can occur only if nb is @@ -4571,6 +4675,7 @@ _int_malloc(mstate av, size_t bytes) malloc_consolidate(av); idx = smallbin_index(nb); /* restore original bin index */ } +#endif /* Otherwise, relay to handle system-dependent cases @@ -4589,7 +4694,11 @@ _int_malloc(mstate av, size_t bytes) */ static void +#ifdef ATOMIC_FASTBINS +_int_free(mstate av, mchunkptr p, int have_lock) +#else _int_free(mstate av, mchunkptr p) +#endif { INTERNAL_SIZE_T size; /* its size */ mfastbinptr* fb; /* associated fastbin */ @@ -4601,6 +4710,9 @@ _int_free(mstate av, mchunkptr p) mchunkptr fwd; /* misc temp for linking */ const char *errstr = NULL; +#ifdef ATOMIC_FASTBINS + int locked = 0; +#endif size = chunksize(p); @@ -4613,6 +4725,10 @@ _int_free(mstate av, mchunkptr p) { errstr = "free(): invalid pointer"; errout: +#ifdef ATOMIC_FASTBINS + if (! have_lock && locked) + (void)mutex_unlock(&av->mutex); +#endif malloc_printerr (check_action, errstr, chunk2mem(p)); return; } @@ -4649,8 +4765,28 @@ _int_free(mstate av, mchunkptr p) goto errout; } + if (__builtin_expect (perturb_byte, 0)) + free_perturb (chunk2mem(p), size - SIZE_SZ); + set_fastchunks(av); - fb = &(av->fastbins[fastbin_index(size)]); + fb = &fastbin (av, fastbin_index(size)); + +#ifdef ATOMIC_FASTBINS + mchunkptr fd; + mchunkptr old = *fb; + do + { + /* Another simple check: make sure 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; + } + p->fd = fd = old; + } + while ((old = catomic_compare_and_exchange_val_acq (fb, p, fd)) != fd); +#else /* Another simple check: make sure the top of the bin is not the record we are going to add (i.e., double free). */ if (__builtin_expect (*fb == p, 0)) @@ -4659,11 +4795,9 @@ _int_free(mstate av, mchunkptr p) goto errout; } - if (__builtin_expect (perturb_byte, 0)) - free_perturb (chunk2mem(p), size - SIZE_SZ); - p->fd = *fb; *fb = p; +#endif } /* @@ -4671,6 +4805,22 @@ _int_free(mstate av, mchunkptr p) */ else if (!chunk_is_mmapped(p)) { +#ifdef ATOMIC_FASTBINS + if (! have_lock) { +# if THREAD_STATS + if(!mutex_trylock(&av->mutex)) + ++(av->stat_lock_direct); + else { + (void)mutex_lock(&av->mutex); + ++(av->stat_lock_wait); + } +# else + (void)mutex_lock(&av->mutex); +# endif + locked = 1; + } +#endif + nextchunk = chunk_at_offset(p, size); /* Lightweight tests: check whether the block is already the @@ -4794,6 +4944,12 @@ _int_free(mstate av, mchunkptr p) } } +#ifdef ATOMIC_FASTBINS + if (! have_lock) { + assert (locked); + (void)mutex_unlock(&av->mutex); + } +#endif } /* If the chunk was allocated via mmap, release via munmap(). Note @@ -4869,15 +5025,21 @@ static void malloc_consolidate(av) mstate av; because, except for the main arena, all the others might have blocks in the high fast bins. It's not worth it anyway, just search all bins all the time. */ - maxfb = &(av->fastbins[fastbin_index(get_max_fast ())]); + maxfb = &fastbin (av, fastbin_index(get_max_fast ())); #else - maxfb = &(av->fastbins[NFASTBINS - 1]); + maxfb = &fastbin (av, NFASTBINS - 1); #endif - fb = &(av->fastbins[0]); + fb = &fastbin (av, 0); do { - if ( (p = *fb) != 0) { - *fb = 0; - +#ifdef ATOMIC_FASTBINS + p = atomic_exchange_acq (fb, 0); +#else + p = *fb; +#endif + if (p != 0) { +#ifndef ATOMIC_FASTBINS + *fb = 0; +#endif do { check_inuse_chunk(av, p); nextp = p->fd; @@ -5070,7 +5232,11 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T nb) } } +#ifdef ATOMIC_FASTBINS + _int_free(av, oldp, 1); +#else _int_free(av, oldp); +#endif check_inuse_chunk(av, newp); return chunk2mem(newp); } @@ -5094,7 +5260,11 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T nb) (av != &main_arena ? NON_MAIN_ARENA : 0)); /* Mark remainder as inuse so free() won't complain */ set_inuse_bit_at_offset(remainder, remainder_size); +#ifdef ATOMIC_FASTBINS + _int_free(av, remainder, 1); +#else _int_free(av, remainder); +#endif } check_inuse_chunk(av, newp); @@ -5153,7 +5323,11 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T nb) newmem = _int_malloc(av, nb - MALLOC_ALIGN_MASK); if (newmem != 0) { MALLOC_COPY(newmem, chunk2mem(oldp), oldsize - 2*SIZE_SZ); +#ifdef ATOMIC_FASTBINS + _int_free(av, oldp, 1); +#else _int_free(av, oldp); +#endif } } return newmem; @@ -5247,7 +5421,11 @@ _int_memalign(mstate av, size_t alignment, size_t bytes) (av != &main_arena ? NON_MAIN_ARENA : 0)); set_inuse_bit_at_offset(newp, newsize); set_head_size(p, leadsize | (av != &main_arena ? NON_MAIN_ARENA : 0)); +#ifdef ATOMIC_FASTBINS + _int_free(av, p, 1); +#else _int_free(av, p); +#endif p = newp; assert (newsize >= nb && @@ -5263,7 +5441,11 @@ _int_memalign(mstate av, size_t alignment, size_t bytes) set_head(remainder, remainder_size | PREV_INUSE | (av != &main_arena ? NON_MAIN_ARENA : 0)); set_head_size(p, nb); +#ifdef ATOMIC_FASTBINS + _int_free(av, remainder, 1); +#else _int_free(av, remainder); +#endif } } @@ -5650,7 +5832,7 @@ struct mallinfo mALLINFo(mstate av) fastavail = 0; for (i = 0; i < NFASTBINS; ++i) { - for (p = av->fastbins[i]; p != 0; p = p->fd) { + for (p = fastbin (av, i); p != 0; p = p->fd) { ++nfastblocks; fastavail += chunksize(p); } @@ -5818,6 +6000,18 @@ int mALLOPt(param_number, value) int param_number; int value; case M_PERTURB: perturb_byte = value; break; + +#ifdef PER_THREAD + case M_ARENA_TEST: + if (value > 0) + mp_.arena_test = value; + break; + + case M_ARENA_MAX: + if (value > 0) + mp_.arena_max = value; + break; +#endif } (void)mutex_unlock(&av->mutex); return res; diff --git a/malloc/malloc.h b/malloc/malloc.h index b6d7a8afaf..2c0ee35c4e 100644 --- a/malloc/malloc.h +++ b/malloc/malloc.h @@ -1,5 +1,5 @@ /* Prototypes and definition for malloc implementation. - Copyright (C) 1996, 1997, 1999, 2000, 2002-2004, 2005, 2007 + Copyright (C) 1996, 1997, 1999, 2000, 2002-2004, 2005, 2007, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -127,6 +127,8 @@ extern struct mallinfo mallinfo __MALLOC_P ((void)); #define M_MMAP_MAX -4 #define M_CHECK_ACTION -5 #define M_PERTURB -6 +#define M_ARENA_TEST -7 +#define M_ARENA_MAX -8 /* General SVID/XPG interface to tunable parameters. */ extern int mallopt __MALLOC_P ((int __param, int __val)); diff --git a/nptl/ChangeLog b/nptl/ChangeLog index 7b9999860d..60adce37d9 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,13 @@ +2009-03-15 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Change to use cfi directives instead of + hand-coded unwind sections. + +2009-03-10 Ulrich Drepper <drepper@redhat.com> + + * init.c (nptl_freeres): Compile only for SHARED. + 2009-03-09 Jakub Jelinek <jakub@redhat.com> * sysdeps/unix/sysv/linux/sparc/lowlevellock.h: Define diff --git a/nptl/init.c b/nptl/init.c index ba3caeead8..5e9c250ff7 100644 --- a/nptl/init.c +++ b/nptl/init.c @@ -67,10 +67,10 @@ static const char nptl_version[] __attribute_used__ = VERSION; extern void __libc_setup_tls (size_t tcbsize, size_t tcbalign); #endif +#ifdef SHARED static void nptl_freeres (void); -#ifdef SHARED static const struct pthread_functions pthread_functions = { .ptr_pthread_attr_destroy = __pthread_attr_destroy, @@ -138,16 +138,16 @@ static const struct pthread_functions pthread_functions = #endif +#ifdef SHARED /* This function is called indirectly from the freeres code in libc. */ static void __libc_freeres_fn_section nptl_freeres (void) { -#ifdef SHARED __unwind_freeres (); -#endif __free_stacks (0); } +#endif /* For asynchronous cancellation we use a signal. This is the handler. */ diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S index 20bc59db9c..ddcf106a6d 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc. +/* Copyright (C) 2002-2005, 2007, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -37,16 +37,19 @@ .type __pthread_cond_timedwait, @function .align 16 __pthread_cond_timedwait: -.LSTARTCODE: + cfi_startproc pushq %r12 -.Lpush_r12: + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r12, 0) pushq %r13 -.Lpush_r13: + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r13, 0) pushq %r14 -.Lpush_r14: + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r14, 0) #define FRAME_SIZE 80 subq $FRAME_SIZE, %rsp -.Lsubq: + cfi_adjust_cfa_offset(FRAME_SIZE) cmpq $1000000000, 8(%rdx) movl $EINVAL, %eax @@ -305,19 +308,25 @@ __pthread_cond_timedwait: cmoveq %r14, %rax 18: addq $FRAME_SIZE, %rsp -.Laddq: + cfi_adjust_cfa_offset(-FRAME_SIZE) popq %r14 -.Lpop_r14: + cfi_adjust_cfa_offset(-8) + cfi_restore(%r14) popq %r13 -.Lpop_r13: + cfi_adjust_cfa_offset(-8) + cfi_restore(%r13) popq %r12 -.Lpop_r12: + cfi_adjust_cfa_offset(-8) + cfi_restore(%r12) retq /* Initial locking failed. */ 1: -.LSbl1: + cfi_adjust_cfa_offset(3 * 8 + FRAME_SIZE) + cfi_rel_offset(%r12, FRAME_SIZE + 16) + cfi_rel_offset(%r13, FRAME_SIZE + 8) + cfi_rel_offset(%r14, FRAME_SIZE) #if cond_lock != 0 addq $cond_lock, %rdi #endif @@ -414,97 +423,7 @@ __pthread_cond_timedwait: js 6b jmp 21b #endif -.LENDCODE: + cfi_endproc .size __pthread_cond_timedwait, .-__pthread_cond_timedwait versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait, GLIBC_2_3_2) - - - .section .eh_frame,"a",@progbits -.LSTARTFRAME: - .long L(ENDCIE)-L(STARTCIE) # Length of the CIE. -.LSTARTCIE: - .long 0 # CIE ID. - .byte 1 # Version number. -#ifdef SHARED - .string "zR" # NUL-terminated augmentation - # string. -#else - .ascii "\0" # NUL-terminated augmentation - # string. -#endif - .uleb128 1 # Code alignment factor. - .sleb128 -8 # Data alignment factor. - .byte 16 # Return address register - # column. -#ifdef SHARED - .uleb128 1 # Augmentation value length. - .byte 0x1b # Encoding: DW_EH_PE_pcrel - # + DW_EH_PE_sdata4. -#endif - .byte 0x0c # DW_CFA_def_cfa - .uleb128 7 - .uleb128 8 - .byte 0x90 # DW_CFA_offset, column 0x8 - .uleb128 1 - .align 8 -.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. -#ifdef SHARED - .uleb128 0 # No augmentation data. -#endif - .byte 0x40+.Lpush_r12-.LSTARTCODE # DW_CFA_advance_loc+N - .byte 14 # DW_CFA_def_cfa_offset - .uleb128 16 - .byte 0x8c # DW_CFA_offset %r12 - .uleb128 2 - .byte 0x40+.Lpush_r13-.Lpush_r12 # DW_CFA_advance_loc+N - .byte 14 # DW_CFA_def_cfa_offset - .uleb128 24 - .byte 0x8d # DW_CFA_offset %r13 - .uleb128 3 - .byte 0x40+.Lpush_r14-.Lpush_r13 # DW_CFA_advance_loc+N - .byte 14 # DW_CFA_def_cfa_offset - .uleb128 32 - .byte 0x84 # DW_CFA_offset %r14 - .uleb128 4 - .byte 0x40+.Lsubq-.Lpush_r14 # DW_CFA_advance_loc+N - .byte 14 # DW_CFA_def_cfa_offset - .uleb128 32+FRAME_SIZE - .byte 3 # DW_CFA_advance_loc2 - .2byte .Laddq-.Lsubq - .byte 14 # DW_CFA_def_cfa_offset - .uleb128 32 - .byte 0x40+.Lpop_r14-.Laddq # DW_CFA_advance_loc+N - .byte 14 # DW_CFA_def_cfa_offset - .uleb128 24 - .byte 0xce # DW_CFA_restore %r14 - .byte 0x40+.Lpop_r13-.Lpop_r14 # DW_CFA_advance_loc+N - .byte 14 # DW_CFA_def_cfa_offset - .uleb128 16 - .byte 0xcd # DW_CFA_restore %r13 - .byte 0x40+.Lpop_r12-.Lpop_r13 # DW_CFA_advance_loc+N - .byte 14 # DW_CFA_def_cfa_offset - .uleb128 8 - .byte 0xcc # DW_CFA_restore %r12 - .byte 0x40+.LSbl1-.Lpop_r12 # DW_CFA_advance_loc+N - .byte 14 # DW_CFA_def_cfa_offset - .uleb128 32+FRAME_SIZE - .byte 0x8c # DW_CFA_offset %r12 - .uleb128 2 - .byte 0x8d # DW_CFA_offset %r13 - .uleb128 3 - .byte 0x84 # DW_CFA_offset %r14 - .uleb128 4 - .align 8 -.LENDFDE: diff --git a/nptl_db/ChangeLog b/nptl_db/ChangeLog index 610ca9dbb6..8c07d9f32f 100644 --- a/nptl_db/ChangeLog +++ b/nptl_db/ChangeLog @@ -1,3 +1,8 @@ +2009-03-19 Roland McGrath <roland@redhat.com> + + * td_symbol_list.c (DB_LOOKUP_NAME, DB_LOOKUP_NAME_TH_UNIQUE): + Use STRINGIFY macro in place of #argument. + 2009-02-27 Roland McGrath <roland@redhat.com> * td_symbol_list.c (symbol_list_arr): Move initializer guts to ... diff --git a/nptl_db/td_symbol_list.c b/nptl_db/td_symbol_list.c index 79498404cb..474251d627 100644 --- a/nptl_db/td_symbol_list.c +++ b/nptl_db/td_symbol_list.c @@ -24,8 +24,8 @@ static const char *symbol_list_arr[] = { -# define DB_LOOKUP_NAME(idx, name) [idx] = #name, -# define DB_LOOKUP_NAME_TH_UNIQUE(idx, name) [idx] = #name, +# define DB_LOOKUP_NAME(idx, name) [idx] = STRINGIFY (name), +# define DB_LOOKUP_NAME_TH_UNIQUE(idx, name) [idx] = STRINGIFY (name), # include "db-symbols.h" # undef DB_LOOKUP_NAME # undef DB_LOOKUP_NAME_TH_UNIQUE diff --git a/nscd/connections.c b/nscd/connections.c index 3d0727f33b..234e289f00 100644 --- a/nscd/connections.c +++ b/nscd/connections.c @@ -1418,7 +1418,22 @@ cannot change to old working directory: %s; disabling paranoia mode"), } /* The preparations are done. */ - execv ("/proc/self/exe", argv); +#ifdef PATH_MAX + char pathbuf[PATH_MAX]; +#else + char pathbuf[256]; +#endif + /* Try to exec the real nscd program so the process name (as reported + in /proc/PID/status) will be 'nscd', but fall back to /proc/self/exe + if readlink fails */ + ssize_t n = readlink ("/proc/self/exe", pathbuf, sizeof (pathbuf) - 1); + if (n == -1) + execv ("/proc/self/exe", argv); + else + { + pathbuf[n] = '\0'; + execv (pathbuf, argv); + } /* If we come here, we will never be able to re-exec. */ dbg_log (_("re-exec failed: %s; disabling paranoia mode"), diff --git a/string/Makefile b/string/Makefile index cccd68cf45..127e25fbd9 100644 --- a/string/Makefile +++ b/string/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1991-2002, 2005-2007, 2008 Free Software Foundation, Inc. +# Copyright (C) 1991-2002, 2005-2008, 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 @@ -54,7 +54,7 @@ tests := tester inl-tester noinl-tester testcopy test-ffs \ bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap \ tst-strtok tst-strxfrm bug-strcoll1 tst-strfry \ bug-strtok1 $(addprefix test-,$(strop-tests)) \ - bug-envz1 tst-strxfrm2 tst-endian + bug-envz1 tst-strxfrm2 tst-endian tst-svc2 distribute := memcopy.h pagecopy.h tst-svc.expect test-string.h \ str-two-way.h diff --git a/string/strlen.c b/string/strlen.c index 9bc9db68f7..5f22ce9509 100644 --- a/string/strlen.c +++ b/string/strlen.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1993, 1997, 2000, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1991,1993,1997,2000,2003,2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Torbjorn Granlund (tege@sics.se), with help from Dan Sahlin (dan@sics.se); @@ -32,7 +32,7 @@ strlen (str) { const char *char_ptr; const unsigned long int *longword_ptr; - unsigned long int longword, magic_bits, himagic, lomagic; + unsigned long int longword, himagic, lomagic; /* Handle the first few characters by reading one character at a time. Do this until CHAR_PTR is aligned on a longword boundary. */ @@ -56,14 +56,12 @@ strlen (str) The 1-bits make sure that carries propagate to the next 0-bit. The 0-bits provide holes for carries to fall into. */ - magic_bits = 0x7efefeffL; himagic = 0x80808080L; lomagic = 0x01010101L; if (sizeof (longword) > 4) { /* 64-bit version of the magic. */ /* Do the shift in two steps to avoid a warning if long has 32 bits. */ - magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; himagic = ((himagic << 16) << 16) | himagic; lomagic = ((lomagic << 16) << 16) | lomagic; } @@ -75,53 +73,9 @@ strlen (str) if *any of the four* bytes in the longword in question are zero. */ for (;;) { - /* We tentatively exit the loop if adding MAGIC_BITS to - LONGWORD fails to change any of the hole bits of LONGWORD. - - 1) Is this safe? Will it catch all the zero bytes? - Suppose there is a byte with all zeros. Any carry bits - propagating from its left will fall into the hole at its - least significant bit and stop. Since there will be no - carry from its most significant bit, the LSB of the - byte to the left will be unchanged, and the zero will be - detected. - - 2) Is this worthwhile? Will it ignore everything except - zero bytes? Suppose every byte of LONGWORD has a bit set - somewhere. There will be a carry into bit 8. If bit 8 - is set, this will carry into bit 16. If bit 8 is clear, - one of bits 9-15 must be set, so there will be a carry - into bit 16. Similarly, there will be a carry into bit - 24. If one of bits 24-30 is set, there will be a carry - into bit 31, so all of the hole bits will be changed. - - The one misfire occurs when bits 24-30 are clear and bit - 31 is set; in this case, the hole at bit 31 is not - changed. If we had access to the processor carry flag, - we could close this loophole by putting the fourth hole - at bit 32! - - So it ignores everything except 128's, when they're aligned - properly. */ - longword = *longword_ptr++; - if ( -#if 0 - /* Add MAGIC_BITS to LONGWORD. */ - (((longword + magic_bits) - - /* Set those bits that were unchanged by the addition. */ - ^ ~longword) - - /* Look at only the hole bits. If any of the hole bits - are unchanged, most likely one of the bytes was a - zero. */ - & ~magic_bits) -#else - ((longword - lomagic) & himagic) -#endif - != 0) + if (((longword - lomagic) & ~longword & himagic) != 0) { /* Which of the bytes was the zero? If none of them were, it was a misfire; continue the search. */ diff --git a/string/strverscmp.c b/string/strverscmp.c index 8efac30383..2b7ebcb8a8 100644 --- a/string/strverscmp.c +++ b/string/strverscmp.c @@ -1,5 +1,5 @@ /* Compare strings while treating digits characters numerically. - Copyright (C) 1997, 2002 Free Software Foundation, Inc. + Copyright (C) 1997, 2002, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jean-François Bignolles <bignolle@ecoledoc.ibp.fr>, 1997. @@ -18,15 +18,16 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include <stdint.h> #include <string.h> #include <ctype.h> /* states: S_N: normal, S_I: comparing integral part, S_F: comparing fractionnal parts, S_Z: idem but with leading Zeroes only */ #define S_N 0x0 -#define S_I 0x4 -#define S_F 0x8 -#define S_Z 0xC +#define S_I 0x3 +#define S_F 0x6 +#define S_Z 0x9 /* result_type: CMP: return diff; LEN: compare using len_diff/diff */ #define CMP 2 @@ -45,53 +46,49 @@ __strverscmp (s1, s2) { const unsigned char *p1 = (const unsigned char *) s1; const unsigned char *p2 = (const unsigned char *) s2; - unsigned char c1, c2; - int state; - int diff; - /* Symbol(s) 0 [1-9] others (padding) - Transition (10) 0 (01) d (00) x (11) - */ - static const unsigned int next_state[] = + /* Symbol(s) 0 [1-9] others + Transition (10) 0 (01) d (00) x */ + static const uint8_t next_state[] = { - /* state x d 0 - */ - /* S_N */ S_N, S_I, S_Z, S_N, - /* S_I */ S_N, S_I, S_I, S_I, - /* S_F */ S_N, S_F, S_F, S_F, - /* S_Z */ S_N, S_F, S_Z, S_Z + /* state x d 0 */ + /* S_N */ S_N, S_I, S_Z, + /* S_I */ S_N, S_I, S_I, + /* S_F */ S_N, S_F, S_F, + /* S_Z */ S_N, S_F, S_Z }; - static const int result_type[] = + static const int8_t result_type[] = { - /* state x/x x/d x/0 x/- d/x d/d d/0 d/- - 0/x 0/d 0/0 0/- -/x -/d -/0 -/- */ - - /* S_N */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP, - CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, - /* S_I */ CMP, -1, -1, CMP, +1, LEN, LEN, CMP, - +1, LEN, LEN, CMP, CMP, CMP, CMP, CMP, - /* S_F */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP, - CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, - /* S_Z */ CMP, +1, +1, CMP, -1, CMP, CMP, CMP, - -1, CMP, CMP, CMP + /* state x/x x/d x/0 d/x d/d d/0 0/x 0/d 0/0 */ + + /* S_N */ CMP, CMP, CMP, CMP, LEN, CMP, CMP, CMP, CMP, + /* S_I */ CMP, -1, -1, +1, LEN, LEN, +1, LEN, LEN, + /* S_F */ CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, + /* S_Z */ CMP, +1, +1, -1, CMP, CMP, -1, CMP, CMP }; if (p1 == p2) return 0; - c1 = *p1++; - c2 = *p2++; + unsigned char c1 = *p1++; + unsigned char c2 = *p2++; /* Hint: '0' is a digit too. */ - state = S_N | ((c1 == '0') + (isdigit (c1) != 0)); + int state = S_N | ((c1 == '0') + (isdigit (c1) != 0)); - while ((diff = c1 - c2) == 0 && c1 != '\0') + int diff; + while ((diff = c1 - c2) == 0) { + if (c1 == '\0') + return diff; + state = next_state[state]; c1 = *p1++; c2 = *p2++; state |= (c1 == '0') + (isdigit (c1) != 0); } - state = result_type[state << 2 | (((c2 == '0') + (isdigit (c2) != 0)))]; + state = result_type[state * 3 | (((c2 == '0') + (isdigit (c2) != 0)))]; switch (state) { diff --git a/string/tst-svc2.c b/string/tst-svc2.c new file mode 100644 index 0000000000..12c88aa2b8 --- /dev/null +++ b/string/tst-svc2.c @@ -0,0 +1,62 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + + +static struct +{ + const char *str1; + const char *str2; +} tests[] = + { + { "B0075022800016.gbp.corp.com", "B007502280067.gbp.corp.com" }, + { "B0075022800016.gbp.corp.com", "B007502357019.GBP.CORP.COM" }, + { "B007502280067.gbp.corp.com", "B007502357019.GBP.CORP.COM" } + }; +#define ntests (sizeof (tests) / sizeof (tests[0])) + + +int +compare (const char *str1, const char *str2, int exp) +{ + int c = strverscmp (str1, str2); + if (c != 0) + c /= abs (c); + return c != exp; +} + + +static int +do_test (void) +{ + int res = 0; + for (int i = 0; i < ntests; ++i) + { + if (compare (tests[i].str1, tests[i].str2, -1)) + { + printf ("FAIL: \"%s\" > \"%s\"\n", tests[i].str1, tests[i].str2); + res = 1; + } + if (compare (tests[i].str2, tests[i].str1, +1)) + { + printf ("FAIL: \"%s\" > \"%s\"\n", tests[i].str2, tests[i].str1); + res = 1; + } + char *copy1 = strdupa (tests[i].str1); + if (compare (tests[i].str1, copy1, 0)) + { + printf ("FAIL: \"%s\" != \"%s\"\n", tests[i].str1, copy1); + res = 1; + } + char *copy2 = strdupa (tests[i].str2); + if (compare (tests[i].str2, copy2, 0)) + { + printf ("FAIL: \"%s\" != \"%s\"\n", tests[i].str2, copy2); + res = 1; + } + } + return res; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index e00b173f49..943369bb24 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -882,10 +882,10 @@ extern struct link_map *_dl_new_object (char *realname, const char *libname, /* Relocate the given object (if it hasn't already been). SCOPE is passed to _dl_lookup_symbol in symbol lookups. - If LAZY is nonzero, don't relocate its PLT. */ + If RTLD_LAZY is set in RELOC-MODE, don't relocate its PLT. */ extern void _dl_relocate_object (struct link_map *map, struct r_scope_elem *scope[], - int lazy, int consider_profiling) + int reloc_mode, int consider_profiling) attribute_hidden; /* Protect PT_GNU_RELRO area. */ diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h index e3342d8e12..0e15878d4e 100644 --- a/sysdeps/i386/dl-machine.h +++ b/sysdeps/i386/dl-machine.h @@ -1,5 +1,5 @@ /* Machine-dependent ELF dynamic relocation inline functions. i386 version. - Copyright (C) 1995-2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1995-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 @@ -316,34 +316,39 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, Elf32_Addr *const reloc_addr = reloc_addr_arg; const unsigned int r_type = ELF32_R_TYPE (reloc->r_info); -#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC +# if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC if (__builtin_expect (r_type == R_386_RELATIVE, 0)) { -# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC +# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC /* This is defined in rtld.c, but nowhere in the static libc.a; make the reference weak so static programs can still link. This declaration cannot be done when compiling rtld.c (i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the common defn for _dl_rtld_map, which is incompatible with a weak decl in the same file. */ -# ifndef SHARED +# ifndef SHARED weak_extern (_dl_rtld_map); -# endif +# endif if (map != &GL(dl_rtld_map)) /* Already done in rtld itself. */ -# endif +# endif *reloc_addr += map->l_addr; } -# ifndef RTLD_BOOTSTRAP +# ifndef RTLD_BOOTSTRAP else if (__builtin_expect (r_type == R_386_NONE, 0)) return; -# endif +# endif else -#endif /* !RTLD_BOOTSTRAP and have no -z combreloc */ +# endif /* !RTLD_BOOTSTRAP and have no -z combreloc */ { const Elf32_Sym *const refsym = sym; struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type); Elf32_Addr value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value; + if (sym != NULL + && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, + 0)) + value = ((Elf32_Addr (*) (void)) value) (); + switch (r_type) { case R_386_GLOB_DAT: @@ -351,44 +356,44 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, *reloc_addr = value; break; -#if !defined RTLD_BOOTSTRAP || USE___THREAD +# if !defined RTLD_BOOTSTRAP || USE___THREAD case R_386_TLS_DTPMOD32: -# ifdef RTLD_BOOTSTRAP +# ifdef RTLD_BOOTSTRAP /* During startup the dynamic linker is always the module with index 1. XXX If this relocation is necessary move before RESOLVE call. */ *reloc_addr = 1; -# else +# else /* Get the information from the link map returned by the resolv function. */ if (sym_map != NULL) *reloc_addr = sym_map->l_tls_modid; -# endif +# endif break; case R_386_TLS_DTPOFF32: -# ifndef RTLD_BOOTSTRAP +# ifndef RTLD_BOOTSTRAP /* During relocation all TLS symbols are defined and used. Therefore the offset is already correct. */ if (sym != NULL) *reloc_addr = sym->st_value; -# endif +# endif break; case R_386_TLS_DESC: { struct tlsdesc volatile *td = (struct tlsdesc volatile *)reloc_addr; -# ifndef RTLD_BOOTSTRAP +# ifndef RTLD_BOOTSTRAP if (! sym) td->entry = _dl_tlsdesc_undefweak; else -# endif +# endif { -# ifndef RTLD_BOOTSTRAP -# ifndef SHARED +# ifndef RTLD_BOOTSTRAP +# ifndef SHARED CHECK_STATIC_TLS (map, sym_map); -# else +# else if (!TRY_STATIC_TLS (map, sym_map)) { td->arg = _dl_make_tlsdesc_dynamic @@ -396,8 +401,8 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, td->entry = _dl_tlsdesc_dynamic; } else +# endif # endif -# endif { td->arg = (void*)(sym->st_value - sym_map->l_tls_offset + (ElfW(Word))td->arg); @@ -408,9 +413,9 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, } case R_386_TLS_TPOFF32: /* The offset is positive, backward from the thread pointer. */ -# ifdef RTLD_BOOTSTRAP +# ifdef RTLD_BOOTSTRAP *reloc_addr += map->l_tls_offset - sym->st_value; -# else +# else /* We know the offset of object the symbol is contained in. It is a positive value which will be subtracted from the thread pointer. To get the variable position in the TLS @@ -420,13 +425,13 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, CHECK_STATIC_TLS (map, sym_map); *reloc_addr += sym_map->l_tls_offset - sym->st_value; } -# endif +# endif break; case R_386_TLS_TPOFF: /* The offset is negative, forward from the thread pointer. */ -# ifdef RTLD_BOOTSTRAP +# ifdef RTLD_BOOTSTRAP *reloc_addr += sym->st_value - map->l_tls_offset; -# else +# else /* We know the offset of object the symbol is contained in. It is a negative value which will be added to the thread pointer. */ @@ -435,11 +440,11 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, CHECK_STATIC_TLS (map, sym_map); *reloc_addr += sym->st_value - sym_map->l_tls_offset; } -# endif +# endif break; -#endif /* use TLS */ +# endif /* use TLS */ -#ifndef RTLD_BOOTSTRAP +# ifndef RTLD_BOOTSTRAP case R_386_32: *reloc_addr += value; break; @@ -469,12 +474,12 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, default: _dl_reloc_bad_type (map, r_type, 0); break; -#endif /* !RTLD_BOOTSTRAP */ +# endif /* !RTLD_BOOTSTRAP */ } } } -#ifndef RTLD_BOOTSTRAP +# ifndef RTLD_BOOTSTRAP auto inline void __attribute__ ((always_inline)) elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, @@ -488,12 +493,17 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, *reloc_addr = map->l_addr + reloc->r_addend; else if (r_type != R_386_NONE) { -# ifndef RESOLVE_CONFLICT_FIND_MAP +# ifndef RESOLVE_CONFLICT_FIND_MAP const Elf32_Sym *const refsym = sym; -# endif +# endif struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type); Elf32_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value; + if (sym != NULL + && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, + 0)) + value = ((Elf32_Addr (*) (void)) value) (); + switch (ELF32_R_TYPE (reloc->r_info)) { case R_386_GLOB_DAT: @@ -501,7 +511,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, case R_386_32: *reloc_addr = value + reloc->r_addend; break; -# ifndef RESOLVE_CONFLICT_FIND_MAP +# ifndef RESOLVE_CONFLICT_FIND_MAP /* Not needed for dl-conflict.c. */ case R_386_PC32: *reloc_addr = (value + reloc->r_addend - (Elf32_Addr) reloc_addr); @@ -523,19 +533,19 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, struct tlsdesc volatile *td = (struct tlsdesc volatile *)reloc_addr; -# ifndef RTLD_BOOTSTRAP +# ifndef RTLD_BOOTSTRAP if (!sym) { td->arg = (void*)reloc->r_addend; td->entry = _dl_tlsdesc_undefweak; } else -# endif +# endif { -# ifndef RTLD_BOOTSTRAP -# ifndef SHARED +# ifndef RTLD_BOOTSTRAP +# ifndef SHARED CHECK_STATIC_TLS (map, sym_map); -# else +# else if (!TRY_STATIC_TLS (map, sym_map)) { td->arg = _dl_make_tlsdesc_dynamic @@ -543,8 +553,8 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, td->entry = _dl_tlsdesc_dynamic; } else -# endif -# endif +# endif +# endif { td->arg = (void*)(sym->st_value - sym_map->l_tls_offset + reloc->r_addend); @@ -598,7 +608,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, memcpy (reloc_addr_arg, (void *) value, MIN (sym->st_size, refsym->st_size)); break; -# endif /* !RESOLVE_CONFLICT_FIND_MAP */ +# endif /* !RESOLVE_CONFLICT_FIND_MAP */ default: /* We add these checks in the version to relocate ld.so only if we are still debugging. */ @@ -607,7 +617,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, } } } -#endif /* !RTLD_BOOTSTRAP */ +# endif /* !RTLD_BOOTSTRAP */ auto inline void __attribute ((always_inline)) @@ -619,7 +629,7 @@ elf_machine_rel_relative (Elf32_Addr l_addr, const Elf32_Rel *reloc, *reloc_addr += l_addr; } -#ifndef RTLD_BOOTSTRAP +# ifndef RTLD_BOOTSTRAP auto inline void __attribute__ ((always_inline)) elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc, @@ -628,7 +638,7 @@ elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc, Elf32_Addr *const reloc_addr = reloc_addr_arg; *reloc_addr = l_addr + reloc->r_addend; } -#endif /* !RTLD_BOOTSTRAP */ +# endif /* !RTLD_BOOTSTRAP */ auto inline void __attribute__ ((always_inline)) @@ -672,12 +682,12 @@ elf_machine_lazy_rel (struct link_map *map, const ElfW(Sym) *const symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]); -#ifdef RTLD_BOOTSTRAP +# ifdef RTLD_BOOTSTRAP /* The dynamic linker always uses versioning. */ assert (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL); -#else +# else if (map->l_info[VERSYMIDX (DT_VERSYM)]) -#endif +# endif { const ElfW(Half) *const version = (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]); @@ -686,18 +696,18 @@ elf_machine_lazy_rel (struct link_map *map, &map->l_versions[ndx], (void *) (l_addr + r->r_offset)); } -#ifndef RTLD_BOOTSTRAP +# ifndef RTLD_BOOTSTRAP else elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL, (void *) (l_addr + r->r_offset)); -#endif +# endif } } else _dl_reloc_bad_type (map, r_type, 1); } -#ifndef RTLD_BOOTSTRAP +# ifndef RTLD_BOOTSTRAP auto inline void __attribute__ ((always_inline)) @@ -720,6 +730,6 @@ elf_machine_lazy_rela (struct link_map *map, _dl_reloc_bad_type (map, r_type, 1); } -#endif /* !RTLD_BOOTSTRAP */ +# endif /* !RTLD_BOOTSTRAP */ #endif /* RESOLVE_MAP */ diff --git a/sysdeps/powerpc/powerpc32/power7/fpu/Implies b/sysdeps/powerpc/powerpc32/power7/fpu/Implies new file mode 100644 index 0000000000..819a7d7979 --- /dev/null +++ b/sysdeps/powerpc/powerpc32/power7/fpu/Implies @@ -0,0 +1 @@ +powerpc/powerpc32/power5/fpu diff --git a/sysdeps/unix/sysv/linux/i386/alphasort64.c b/sysdeps/unix/sysv/linux/i386/alphasort64.c index 221aedc16b..33e2fcd435 100644 --- a/sysdeps/unix/sysv/linux/i386/alphasort64.c +++ b/sysdeps/unix/sysv/linux/i386/alphasort64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1992, 1997, 1998, 2000, 2004 Free Software Foundation, Inc. +/* Copyright (C) 1992, 1997,1998,2000,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 @@ -20,10 +20,9 @@ #include <string.h> int -__alphasort64 (const void *a, const void *b) +__alphasort64 (const struct dirent64 **a, const struct dirent64 **b) { - return strcoll ((*(const struct dirent64 **) a)->d_name, - (*(const struct dirent64 **) b)->d_name); + return strcoll ((*a)->d_name, (*b)->d_name); } #include <shlib-compat.h> @@ -35,14 +34,15 @@ versioned_symbol (libc, __alphasort64, alphasort64, GLIBC_2_2); #include <sysdeps/unix/sysv/linux/i386/olddirent.h> int -__old_alphasort64 (const void *a, const void *b); +__old_alphasort64 (const struct __old_dirent64 **a, + const struct __old_dirent64 **b); int attribute_compat_text_section -__old_alphasort64 (const void *a, const void *b) +__old_alphasort64 (const struct __old_dirent64 **a, + const struct __old_dirent64 **b) { - return strcoll ((*(const struct __old_dirent64 **) a)->d_name, - (*(const struct __old_dirent64 **) b)->d_name); + return strcoll ((*a)->d_name, (*b)->d_name); } compat_symbol (libc, __old_alphasort64, alphasort64, GLIBC_2_1); diff --git a/sysdeps/unix/sysv/linux/i386/olddirent.h b/sysdeps/unix/sysv/linux/i386/olddirent.h index f9a79b2352..4f73197e53 100644 --- a/sysdeps/unix/sysv/linux/i386/olddirent.h +++ b/sysdeps/unix/sysv/linux/i386/olddirent.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 Free Software Foundation, Inc. +/* Copyright (C) 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 @@ -39,6 +39,7 @@ extern __ssize_t __old_getdents64 (int __fd, char *__buf, size_t __nbytes) int __old_scandir64 (__const char * __dir, struct __old_dirent64 *** __namelist, int (*__selector) (__const struct __old_dirent64 *), - int (*__cmp) (__const void *, __const void *)); + int (*__cmp) (__const struct __old_dirent64 **, + __const struct __old_dirent64 **)); #endif diff --git a/sysdeps/unix/sysv/linux/i386/versionsort64.c b/sysdeps/unix/sysv/linux/i386/versionsort64.c index 3efce692f7..be635f918a 100644 --- a/sysdeps/unix/sysv/linux/i386/versionsort64.c +++ b/sysdeps/unix/sysv/linux/i386/versionsort64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1992, 1997, 1998, 2000, 2004 Free Software Foundation, Inc. +/* Copyright (C) 1992,1997,1998,2000,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 @@ -20,10 +20,9 @@ #include <string.h> int -__versionsort64 (const void *a, const void *b) +__versionsort64 (const struct dirent64 **a, const struct dirent64 **b) { - return __strverscmp ((*(const struct dirent64 **) a)->d_name, - (*(const struct dirent64 **) b)->d_name); + return __strverscmp ((*a)->d_name, (*b)->d_name); } #include <shlib-compat.h> @@ -35,14 +34,15 @@ versioned_symbol (libc, __versionsort64, versionsort64, GLIBC_2_2); #include <sysdeps/unix/sysv/linux/i386/olddirent.h> int -__old_versionsort64 (const void *a, const void *b); +__old_versionsort64 (const struct __old_dirent64 **a, + const struct __old_dirent64 **b); int attribute_compat_text_section -__old_versionsort64 (const void *a, const void *b) +__old_versionsort64 (const struct __old_dirent64 **a, + const struct __old_dirent64 **b) { - return __strverscmp ((*(const struct __old_dirent64 **) a)->d_name, - (*(const struct __old_dirent64 **) b)->d_name); + return __strverscmp ((*a)->d_name, (*b)->d_name); } compat_symbol (libc, __old_versionsort64, versionsort64, GLIBC_2_1); diff --git a/sysdeps/wordsize-64/alphasort.c b/sysdeps/wordsize-64/alphasort.c index 5096166625..edc410129d 100644 --- a/sysdeps/wordsize-64/alphasort.c +++ b/sysdeps/wordsize-64/alphasort.c @@ -1,3 +1,7 @@ +#define alphasort64 rename_alphasort64 + #include "../../dirent/alphasort.c" +#undef alphasort64 + weak_alias (alphasort, alphasort64) diff --git a/sysdeps/wordsize-64/versionsort.c b/sysdeps/wordsize-64/versionsort.c index 90365a4b25..bb25550d3d 100644 --- a/sysdeps/wordsize-64/versionsort.c +++ b/sysdeps/wordsize-64/versionsort.c @@ -1,3 +1,7 @@ +#define versionsort64 rename_versionsort64 + #include "../../dirent/versionsort.c" +#undef versionsort64 + weak_alias (versionsort, versionsort64) diff --git a/sysdeps/x86_64/cacheinfo.c b/sysdeps/x86_64/cacheinfo.c index a7e3fc7633..8769e9c966 100644 --- a/sysdeps/x86_64/cacheinfo.c +++ b/sysdeps/x86_64/cacheinfo.c @@ -23,6 +23,10 @@ #include <stdlib.h> #include <unistd.h> +#ifdef USE_MULTIARCH +# include "multiarch/init-arch.h" +#endif + static const struct intel_02_cache_info { unsigned int idx; @@ -443,19 +447,32 @@ init_cacheinfo (void) unsigned int ebx; unsigned int ecx; unsigned int edx; - int max_cpuid; int max_cpuid_ex; long int data = -1; long int shared = -1; unsigned int level; unsigned int threads = 0; +#ifdef USE_MULTIARCH + if (__cpu_features.kind == arch_kind_unknown) + __init_cpu_features (); +# define is_intel __cpu_features.kind == arch_kind_intel +# define is_amd __cpu_features.kind == arch_kind_amd +# define max_cpuid __cpu_features.max_cpuid +#else + int max_cpuid; asm volatile ("cpuid" : "=a" (max_cpuid), "=b" (ebx), "=c" (ecx), "=d" (edx) : "0" (0)); - /* This spells out "GenuineIntel". */ - if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69) +# define is_intel \ + ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69 + /* This spells out "AuthenticAMD". */ +# define is_amd \ + ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65 +#endif + + if (is_intel) { data = handle_intel (_SC_LEVEL1_DCACHE_SIZE, max_cpuid); @@ -470,9 +487,16 @@ init_cacheinfo (void) shared = handle_intel (_SC_LEVEL2_CACHE_SIZE, max_cpuid); } +#ifdef USE_MULTIARCH + eax = __cpu_features.cpuid[INTEL_CPUID_INDEX_1].eax; + ebx = __cpu_features.cpuid[INTEL_CPUID_INDEX_1].ebx; + ecx = __cpu_features.cpuid[INTEL_CPUID_INDEX_1].ecx; + edx = __cpu_features.cpuid[INTEL_CPUID_INDEX_1].edx; +#else asm volatile ("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "0" (1)); +#endif /* Intel prefers SSSE3 instructions for memory/string routines if they are avaiable. */ @@ -519,7 +543,7 @@ init_cacheinfo (void) shared /= threads; } /* This spells out "AuthenticAMD". */ - else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65) + else if (is_amd) { data = handle_amd (_SC_LEVEL1_DCACHE_SIZE); long int core = handle_amd (_SC_LEVEL2_CACHE_SIZE); diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h index 959b1328d7..8c67b5b5f9 100644 --- a/sysdeps/x86_64/dl-machine.h +++ b/sysdeps/x86_64/dl-machine.h @@ -1,5 +1,5 @@ /* Machine-dependent ELF dynamic relocation inline functions. x86-64 version. - Copyright (C) 2001-2005, 2006 Free Software Foundation, Inc. + Copyright (C) 2001-2005, 2006, 2008, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Andreas Jaeger <aj@suse.de>. @@ -266,40 +266,45 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc, Elf64_Addr *const reloc_addr = reloc_addr_arg; const unsigned long int r_type = ELF64_R_TYPE (reloc->r_info); -#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC +# if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC if (__builtin_expect (r_type == R_X86_64_RELATIVE, 0)) { -# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC +# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC /* This is defined in rtld.c, but nowhere in the static libc.a; make the reference weak so static programs can still link. This declaration cannot be done when compiling rtld.c (i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the common defn for _dl_rtld_map, which is incompatible with a weak decl in the same file. */ -# ifndef SHARED +# ifndef SHARED weak_extern (GL(dl_rtld_map)); -# endif +# endif if (map != &GL(dl_rtld_map)) /* Already done in rtld itself. */ -# endif +# endif *reloc_addr = map->l_addr + reloc->r_addend; } else -#endif +# endif if (__builtin_expect (r_type == R_X86_64_NONE, 0)) return; else { -#ifndef RTLD_BOOTSTRAP +# ifndef RTLD_BOOTSTRAP const Elf64_Sym *const refsym = sym; -#endif +# endif struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type); Elf64_Addr value = (sym == NULL ? 0 : (Elf64_Addr) sym_map->l_addr + sym->st_value); -#if defined RTLD_BOOTSTRAP && !USE___THREAD + if (sym != NULL + && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, + 0)) + value = ((Elf64_Addr (*) (void)) value) (); + +# if defined RTLD_BOOTSTRAP && !USE___THREAD assert (r_type == R_X86_64_GLOB_DAT || r_type == R_X86_64_JUMP_SLOT); *reloc_addr = value + reloc->r_addend; -#else +# else switch (r_type) { case R_X86_64_GLOB_DAT: @@ -307,47 +312,47 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc, *reloc_addr = value + reloc->r_addend; break; -#ifndef RESOLVE_CONFLICT_FIND_MAP +# ifndef RESOLVE_CONFLICT_FIND_MAP case R_X86_64_DTPMOD64: -# ifdef RTLD_BOOTSTRAP +# ifdef RTLD_BOOTSTRAP /* During startup the dynamic linker is always the module with index 1. XXX If this relocation is necessary move before RESOLVE call. */ *reloc_addr = 1; -# else +# else /* Get the information from the link map returned by the resolve function. */ if (sym_map != NULL) *reloc_addr = sym_map->l_tls_modid; -# endif +# endif break; case R_X86_64_DTPOFF64: -# ifndef RTLD_BOOTSTRAP +# ifndef RTLD_BOOTSTRAP /* During relocation all TLS symbols are defined and used. Therefore the offset is already correct. */ if (sym != NULL) *reloc_addr = sym->st_value + reloc->r_addend; -# endif +# endif break; case R_X86_64_TLSDESC: { struct tlsdesc volatile *td = (struct tlsdesc volatile *)reloc_addr; -# ifndef RTLD_BOOTSTRAP +# ifndef RTLD_BOOTSTRAP if (! sym) { td->arg = (void*)reloc->r_addend; td->entry = _dl_tlsdesc_undefweak; } else -# endif +# endif { -# ifndef RTLD_BOOTSTRAP -# ifndef SHARED +# ifndef RTLD_BOOTSTRAP +# ifndef SHARED CHECK_STATIC_TLS (map, sym_map); -# else +# else if (!TRY_STATIC_TLS (map, sym_map)) { td->arg = _dl_make_tlsdesc_dynamic @@ -355,8 +360,8 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc, td->entry = _dl_tlsdesc_dynamic; } else +# endif # endif -# endif { td->arg = (void*)(sym->st_value - sym_map->l_tls_offset + reloc->r_addend); @@ -367,13 +372,13 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc, } case R_X86_64_TPOFF64: /* The offset is negative, forward from the thread pointer. */ -# ifndef RTLD_BOOTSTRAP +# ifndef RTLD_BOOTSTRAP if (sym != NULL) -# endif +# endif { -# ifndef RTLD_BOOTSTRAP +# ifndef RTLD_BOOTSTRAP CHECK_STATIC_TLS (map, sym_map); -# endif +# endif /* We know the offset of the object the symbol is contained in. It is a negative value which will be added to the thread pointer. */ @@ -381,42 +386,41 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc, - sym_map->l_tls_offset); } break; -#endif +# endif -#ifndef RTLD_BOOTSTRAP +# ifndef RTLD_BOOTSTRAP case R_X86_64_64: *reloc_addr = value + reloc->r_addend; break; case R_X86_64_32: - *(unsigned int *) reloc_addr = value + reloc->r_addend; - if (value + reloc->r_addend > UINT_MAX) + value += reloc->r_addend; + *(unsigned int *) reloc_addr = value; + + const char *fmt; + if (__builtin_expect (value > UINT_MAX, 0)) { const char *strtab; + fmt = "\ +%s: Symbol `%s' causes overflow in R_X86_64_32 relocation\n"; + print_err: strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]); - _dl_error_printf ("\ -%s: Symbol `%s' causes overflow in R_X86_64_32 relocation\n", + _dl_error_printf (fmt, rtld_progname ?: "<program name unknown>", strtab + refsym->st_name); } break; -# ifndef RESOLVE_CONFLICT_FIND_MAP +# ifndef RESOLVE_CONFLICT_FIND_MAP /* Not needed for dl-conflict.c. */ case R_X86_64_PC32: - *(unsigned int *) reloc_addr = value + reloc->r_addend - - (Elf64_Addr) reloc_addr; - if (value + reloc->r_addend - (Elf64_Addr) reloc_addr - != (int)(value + reloc->r_addend - (Elf64_Addr) reloc_addr)) + value += reloc->r_addend - (Elf64_Addr) reloc_addr; + *(unsigned int *) reloc_addr = value; + if (__builtin_expect (value != (unsigned int) value, 0)) { - const char *strtab; - - strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]); - - _dl_error_printf ("\ -%s: Symbol `%s' causes overflow in R_X86_64_PC32 relocation\n", - rtld_progname ?: "<program name unknown>", - strtab + refsym->st_name); + fmt = "\ +%s: Symbol `%s' causes overflow in R_X86_64_PC32 relocation\n"; + goto print_err; } break; case R_X86_64_COPY: @@ -424,26 +428,22 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc, /* This can happen in trace mode if an object could not be found. */ break; + memcpy (reloc_addr_arg, (void *) value, + MIN (sym->st_size, refsym->st_size)); if (__builtin_expect (sym->st_size > refsym->st_size, 0) || (__builtin_expect (sym->st_size < refsym->st_size, 0) && GLRO(dl_verbose))) { - const char *strtab; - - strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]); - _dl_error_printf ("\ -%s: Symbol `%s' has different size in shared object, consider re-linking\n", - rtld_progname ?: "<program name unknown>", - strtab + refsym->st_name); + fmt = "\ +%s: Symbol `%s' has different size in shared object, consider re-linking\n"; + goto print_err; } - memcpy (reloc_addr_arg, (void *) value, - MIN (sym->st_size, refsym->st_size)); break; -# endif +# endif default: _dl_reloc_bad_type (map, r_type, 0); break; -#endif +# endif } #endif } diff --git a/sysdeps/x86_64/dl-runtime.c b/sysdeps/x86_64/dl-runtime.c new file mode 100644 index 0000000000..b625d1e882 --- /dev/null +++ b/sysdeps/x86_64/dl-runtime.c @@ -0,0 +1,9 @@ +/* The ABI calls for the PLT stubs to pass the index of the relocation + and not its offset. In _dl_profile_fixup and _dl_call_pltexit we + also use the index. Therefore it is wasteful to compute the offset + in the trampoline just to reverse the operation immediately + afterwards. */ +#define reloc_offset reloc_arg * sizeof (PLTREL) +#define reloc_index reloc_arg + +#include <elf/dl-runtime.c> diff --git a/sysdeps/x86_64/dl-trampoline.S b/sysdeps/x86_64/dl-trampoline.S index 3e2d182758..d8d9bc12a4 100644 --- a/sysdeps/x86_64/dl-trampoline.S +++ b/sysdeps/x86_64/dl-trampoline.S @@ -1,5 +1,5 @@ /* PLT trampolines. x86-64 version. - Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 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 @@ -35,11 +35,7 @@ _dl_runtime_resolve: movq %r8, 40(%rsp) movq %r9, 48(%rsp) movq 64(%rsp), %rsi # Copy args pushed by PLT in register. - movq %rsi, %r11 # Multiply by 24 - addq %r11, %rsi - addq %r11, %rsi - shlq $3, %rsi - movq 56(%rsp), %rdi # %rdi: link_map, %rsi: reloc_offset + movq 56(%rsp), %rdi # %rdi: link_map, %rsi: reloc_index call _dl_fixup # Call resolver. movq %rax, %r11 # Save return value movq 48(%rsp), %r9 # Get register content back. @@ -61,132 +57,165 @@ _dl_runtime_resolve: .type _dl_runtime_profile, @function .align 16 cfi_startproc + _dl_runtime_profile: - subq $88, %rsp - cfi_adjust_cfa_offset(104) # Incorporate PLT - movq %rax, (%rsp) # Preserve registers otherwise clobbered. - movq %rdx, 8(%rsp) - movq %r8, 16(%rsp) - movq %r9, 24(%rsp) - movq %rcx, 32(%rsp) - movq %rsi, 40(%rsp) - movq %rdi, 48(%rsp) - movq %rbp, 56(%rsp) # Information for auditors. - leaq 104(%rsp), %rax - movq %rax, 64(%rsp) - leaq 8(%rsp), %rcx - movq 104(%rsp), %rdx # Load return address if needed - movq 96(%rsp), %rsi # Copy args pushed by PLT in register. - movq %rsi,%r11 # Multiply by 24 - addq %r11,%rsi - addq %r11,%rsi - shlq $3, %rsi - movq 88(%rsp), %rdi # %rdi: link_map, %rsi: reloc_offset - leaq 72(%rsp), %r8 + /* The La_x86_64_regs data structure pointed to by the + fourth paramater must be 16-byte aligned. This must + be explicitly enforced. We have the set up a dynamically + sized stack frame. %rbx points to the top half which + has a fixed size and preserves the original stack pointer. */ + + subq $32, %rsp # Allocate the local storage. + cfi_adjust_cfa_offset(48) # Incorporate PLT + movq %rbx, (%rsp) + cfi_rel_offset(%rbx, 0) + + /* On the stack: + 56(%rbx) parameter #1 + 48(%rbx) return address + + 40(%rbx) reloc index + 32(%rbx) link_map + + 24(%rbx) La_x86_64_regs pointer + 16(%rbx) framesize + 8(%rbx) rax + (%rbx) rbx + */ + + movq %rax, 8(%rsp) + movq %rsp, %rbx + cfi_def_cfa_register(%rbx) + + /* Actively align the La_x86_64_regs structure. */ + andq $0xfffffffffffffff0, %rsp + subq $192, %rsp # sizeof(La_x86_64_regs) + movq %rsp, 24(%rbx) + + movq %rdx, (%rsp) # Fill the La_x86_64_regs structure. + movq %r8, 8(%rsp) + movq %r9, 16(%rsp) + movq %rcx, 24(%rsp) + movq %rsi, 32(%rsp) + movq %rdi, 40(%rsp) + movq %rbp, 48(%rsp) + leaq 48(%rbx), %rax + movq %rax, 56(%rsp) + movaps %xmm0, 64(%rsp) + movaps %xmm1, 80(%rsp) + movaps %xmm2, 96(%rsp) + movaps %xmm3, 112(%rsp) + movaps %xmm4, 128(%rsp) + movaps %xmm5, 144(%rsp) + movaps %xmm7, 160(%rsp) + + movq %rsp, %rcx # La_x86_64_regs pointer to %rcx. + movq 48(%rbx), %rdx # Load return address if needed. + movq 40(%rbx), %rsi # Copy args pushed by PLT in register. + movq 32(%rbx), %rdi # %rdi: link_map, %rsi: reloc_index + leaq 16(%rbx), %r8 call _dl_profile_fixup # Call resolver. - movq %rax, %r11 # Save return value - movq 8(%rsp), %rdx # Get back register content. - movq 16(%rsp), %r8 - movq 24(%rsp), %r9 - movq (%rsp),%rax - movq 72(%rsp), %r10 + + movq %rax, %r11 # Save return value. + + movq 8(%rbx), %rax # Get back register content. + movq (%rsp), %rdx + movq 8(%rsp), %r8 + movq 16(%rsp), %r9 + movaps 64(%rsp), %xmm0 + movaps 80(%rsp), %xmm1 + movaps 96(%rsp), %xmm2 + movaps 112(%rsp), %xmm3 + movaps 128(%rsp), %xmm4 + movaps 144(%rsp), %xmm5 + movaps 160(%rsp), %xmm7 + + movq 16(%rbx), %r10 # Anything in framesize? testq %r10, %r10 jns 1f - movq 32(%rsp), %rcx - movq 40(%rsp), %rsi - movq 48(%rsp), %rdi - addq $104,%rsp # Adjust stack - cfi_adjust_cfa_offset (-104) + + /* There's nothing in the frame size, so there + will be no call to the _dl_call_pltexit. */ + + movq 24(%rsp), %rcx # Get back registers content. + movq 32(%rsp), %rsi + movq 40(%rsp), %rdi + + movq %rbx, %rsp + movq (%rsp), %rbx + cfi_restore(rbx) + cfi_def_cfa_register(%rsp) + + addq $48, %rsp # Adjust the stack to the return value + # (eats the reloc index and link_map) + cfi_adjust_cfa_offset(-48) jmp *%r11 # Jump to function address. - /* - +104 return address - +96 PLT2 - +88 PLT1 - +80 free - +72 free - +64 %rsp - +56 %rbp - +48 %rdi - +40 %rsi - +32 %rcx - +24 %r9 - +16 %r8 - +8 %rdx - %rsp %rax - */ - cfi_adjust_cfa_offset (104) -1: movq %rbx, 72(%rsp) - cfi_rel_offset (rbx, 72) - leaq 112(%rsp), %rsi - movq %rsp, %rbx - cfi_def_cfa_register (%rbx) - movq %r10, %rcx +1: + cfi_adjust_cfa_offset(48) + cfi_rel_offset(%rbx, 0) + cfi_def_cfa_register(%rbx) + + /* At this point we need to prepare new stack for the function + which has to be called. We copy the original stack to a + temporary buffer of the size specified by the 'framesize' + returned from _dl_profile_fixup */ + + leaq 56(%rbx), %rsi # stack addq $8, %r10 andq $0xfffffffffffffff0, %r10 + movq %r10, %rcx subq %r10, %rsp movq %rsp, %rdi shrq $3, %rcx rep movsq - movq 32(%rbx), %rcx - movq 40(%rbx), %rsi - movq 48(%rbx), %rdi + + movq 24(%rdi), %rcx # Get back register content. + movq 32(%rdi), %rsi + movq 40(%rdi), %rdi + call *%r11 - movq %rbx, %rsp - cfi_def_cfa_register (%rsp) - subq $72, %rsp - cfi_adjust_cfa_offset (72) - movq %rsp, %rcx - movq %rax, (%rcx) + + mov 24(%rbx), %rsp # Drop the copied stack content + + /* Now we have to prepare the La_x86_64_retval structure for the + _dl_call_pltexit. The La_x86_64_regs is being pointed by rsp now, + so we just need to allocate the sizeof(La_x86_64_retval) space on + the stack, since the alignment has already been taken care of. */ + + subq $80, %rsp # sizeof(La_x86_64_retval) + movq %rsp, %rcx # La_x86_64_retval argument to %rcx. + + movq %rax, (%rcx) # Fill in the La_x86_64_retval structure. movq %rdx, 8(%rcx) - /* Even though the stack is correctly aligned to allow using movaps - we use movups. Some callers might provide an incorrectly aligned - stack and we do not want to have it blow up here. */ - movups %xmm0, 16(%rcx) - movups %xmm1, 32(%rcx) + movaps %xmm0, 16(%rcx) + movaps %xmm1, 32(%rcx) fstpt 48(%rcx) fstpt 64(%rcx) - /* - +176 return address - +168 PLT2 - +160 PLT1 - +152 free - +144 free - +136 %rsp - +128 %rbp - +120 %rdi - +112 %rsi - +104 %rcx - +96 %r9 - +88 %r8 - +80 %rdx - +64 %st1 result - +48 %st result - +32 %xmm1 result - +16 %xmm0 result - +8 %rdx result - %rsp %rax result - */ - leaq 80(%rsp), %rdx - movq 144(%rsp), %rbx - cfi_restore (rbx) - movq 168(%rsp), %rsi # Copy args pushed by PLT in register. - movq %rsi,%r11 # Multiply by 24 - addq %r11,%rsi - addq %r11,%rsi - shlq $3, %rsi - movq 160(%rsp), %rdi # %rdi: link_map, %rsi: reloc_offset + + movq 24(%rbx), %rdx # La_x86_64_regs argument to %rdx. + movq 40(%rbx), %rsi # Copy args pushed by PLT in register. + movq 32(%rbx), %rdi # %rdi: link_map, %rsi: reloc_index call _dl_call_pltexit - movq (%rsp), %rax + + movq (%rsp), %rax # Restore return registers. movq 8(%rsp), %rdx - movups 16(%rsp), %xmm0 - movups 32(%rsp), %xmm1 + movaps 16(%rsp), %xmm0 + movaps 32(%rsp), %xmm1 fldt 64(%rsp) fldt 48(%rsp) - addq $176, %rsp - cfi_adjust_cfa_offset (-176) + + movq %rbx, %rsp + movq (%rsp), %rbx + cfi_restore(rbx) + cfi_def_cfa_register(%rsp) + + addq $48, %rsp # Adjust the stack to the return value + # (eats the reloc index and link_map) + cfi_adjust_cfa_offset(-48) retq + cfi_endproc .size _dl_runtime_profile, .-_dl_runtime_profile #endif diff --git a/sysdeps/x86_64/multiarch/Makefile b/sysdeps/x86_64/multiarch/Makefile new file mode 100644 index 0000000000..2a1e910e06 --- /dev/null +++ b/sysdeps/x86_64/multiarch/Makefile @@ -0,0 +1,3 @@ +ifeq ($(subdir),csu) +aux += init-arch +endif diff --git a/sysdeps/x86_64/multiarch/init-arch.c b/sysdeps/x86_64/multiarch/init-arch.c new file mode 100644 index 0000000000..eb4365fe32 --- /dev/null +++ b/sysdeps/x86_64/multiarch/init-arch.c @@ -0,0 +1,65 @@ +/* Initialize CPU feature data. + This file is part of the GNU C Library. + Copyright (C) 2008 Free Software Foundation, Inc. + Contributed by Ulrich Drepper <drepper@redhat.com>. + + 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 "init-arch.h" + + +struct cpu_features __cpu_features attribute_hidden; + + +void +__init_cpu_features (void) +{ + unsigned int ebx; + unsigned int ecx; + unsigned int edx; + + asm volatile ("cpuid" + : "=a" (__cpu_features.max_cpuid), "=b" (ebx), "=c" (ecx), + "=d" (edx) + : "0" (0)); + + /* This spells out "GenuineIntel". */ + if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69) + { + __cpu_features.kind = arch_kind_intel; + + asm volatile ("cpuid" + : "=a" (__cpu_features.cpuid[INTEL_CPUID_INDEX_1].eax), + "=b" (__cpu_features.cpuid[INTEL_CPUID_INDEX_1].ebx), + "=c" (__cpu_features.cpuid[INTEL_CPUID_INDEX_1].ecx), + "=d" (__cpu_features.cpuid[INTEL_CPUID_INDEX_1].edx) + : "0" (1)); + } + /* This spells out "AuthenticAMD". */ + else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65) + { + __cpu_features.kind = arch_kind_amd; + + asm volatile ("cpuid" + : "=a" (__cpu_features.cpuid[AMD_CPUID_INDEX_1].eax), + "=b" (__cpu_features.cpuid[AMD_CPUID_INDEX_1].ebx), + "=c" (__cpu_features.cpuid[AMD_CPUID_INDEX_1].ecx), + "=d" (__cpu_features.cpuid[AMD_CPUID_INDEX_1].edx) + : "0" (1)); + } + else + __cpu_features.kind = arch_kind_other; +} diff --git a/sysdeps/x86_64/multiarch/init-arch.h b/sysdeps/x86_64/multiarch/init-arch.h new file mode 100644 index 0000000000..86cd83dc4c --- /dev/null +++ b/sysdeps/x86_64/multiarch/init-arch.h @@ -0,0 +1,70 @@ +/* This file is part of the GNU C Library. + Copyright (C) 2008 Free Software Foundation, Inc. + + 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 <sys/param.h> + +enum + { + INTEL_CPUID_INDEX_1 = 0, + /* Keep the following line at the end. */ + INTEL_CPUID_INDEX_MAX + }; + +enum + { + AMD_CPUID_INDEX_1 = 0, + /* Keep the following line at the end. */ + AMD_CPUID_INDEX_MAX + }; + +extern struct cpu_features +{ + enum + { + arch_kind_unknown = 0, + arch_kind_intel, + arch_kind_amd, + arch_kind_other + } kind; + int max_cpuid; + struct + { + unsigned int eax; + unsigned int ebx; + unsigned int ecx; + unsigned int edx; + } cpuid[MAX (INTEL_CPUID_INDEX_MAX, AMD_CPUID_INDEX_MAX)]; +} __cpu_features attribute_hidden; + + +extern void __init_cpu_features (void) attribute_hidden; +#define INIT_ARCH()\ + do \ + if (__cpu_features.kind == arch_kind_unknown) \ + __init_cpu_features (); \ + while (0) + +/* Following are the feature tests used throughout libc. */ + +#define INTEL_HAS_POPCOUNT \ + (__cpu_features.kind == arch_kind_intel \ + && (__cpu_features.cpuid[INTEL_CPUID_INDEX_1].ecx & (1 << 23)) != 0) + +#define AMD_HAS_POPCOUNT \ + (__cpu_features.kind == arch_kind_amd \ + && (__cpu_features.cpuid[AMD_CPUID_INDEX_1].ecx & (1 << 23)) != 0) diff --git a/sysdeps/x86_64/multiarch/sched_cpucount.c b/sysdeps/x86_64/multiarch/sched_cpucount.c new file mode 100644 index 0000000000..dc20182df4 --- /dev/null +++ b/sysdeps/x86_64/multiarch/sched_cpucount.c @@ -0,0 +1,42 @@ +/* Count bits in CPU set. x86-64 multi-arch version. + This file is part of the GNU C Library. + Copyright (C) 2008 Free Software Foundation, Inc. + Contributed by Ulrich Drepper <drepper@redhat.com>. + + 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. */ + +#ifdef SHARED +# include <sched.h> +# include "init-arch.h" + +# define __sched_cpucount static generic_cpucount +# include <posix/sched_cpucount.c> +# undef __sched_cpucount + +# define POPCNT(l) \ + ({ __cpu_mask r; \ + asm ("popcntq %1, %0" : "=r" (r) : "0" (l));\ + r; }) +# define __sched_cpucount static popcount_cpucount +# include <posix/sched_cpucount.c> +# undef __sched_cpucount + +libc_ifunc (__sched_cpucount, + INTEL_HAS_POPCOUNT || AMD_HAS_POPCOUNT + ? popcount_cpucount : generic_cpucount); +#else +# include_next <sched_cpucount.c> +#endif |