mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-29 16:21:07 +00:00
11bf311edc
2007-01-11 Jakub Jelinek <jakub@redhat.com> * sysdeps/i386/soft-fp/sfp-machine.h: Remove. * sysdeps/x86_64/soft-fp/sfp-machine.h: Likewise. 2007-01-10 Ulrich Drepper <drepper@redhat.com> * io/fts.c: Make sure fts_cur is always valid after return from fts_read. Patch by Miloslav Trmac <mitr@redhat.com>. 2006-10-27 Richard Sandiford <richard@codesourcery.com> * elf/elf.h (R_MIPS_GLOB_DAT): Define. (R_MIPS_NUM): Bump by 1. 2007-01-03 Jakub Jelinek <jakub@redhat.com> * posix/execvp.c: Include alloca.h. (allocate_scripts_argv): Renamed to... (scripts_argv): ... this. Don't allocate buffer here nor count arguments. (execvp): Use alloca if possible. * posix/Makefile: Add rules to build and run tst-vfork3 test. * posix/tst-vfork3.c: New test. * stdlib/Makefile (tst-strtod3-ENV): Define. 2007-01-02 Ulrich Drepper <drepper@redhat.com> * posix/getconf.c: Update copyright year. * nss/getent.c: Likewise. * iconv/iconvconfig.c: Likewise. * iconv/iconv_prog.c: Likewise. * elf/ldconfig.c: Likewise. * catgets/gencat.c: Likewise. * csu/version.c: Likewise. * elf/ldd.bash.in: Likewise. * elf/sprof.c (print_version): Likewise. * locale/programs/locale.c: Likewise. * locale/programs/localedef.c: Likewise. * nscd/nscd.c (print_version): Likewise. * debug/xtrace.sh: Likewise. * malloc/memusage.sh: Likewise. * malloc/mtrace.pl: Likewise. * debug/catchsegv.sh: Likewise. 2006-12-24 Ulrich Drepper <drepper@redhat.com> * malloc/malloc.c (sYSMALLOc): Remove some unnecessary alignment attempts. 2006-12-23 Ulrich Drepper <drepper@redhat.com> * posix/wordexp.c: Remove some unnecessary tests. 2006-12-20 SUGIOKA Toshinobu <sugioka@itonet.co.jp> * sysdeps/unix/sysv/linux/sh/bits/shm.h: New file. * nss/getXXbyYY_r.c: Include atomic.h. (INTERNAL (REENTRANT_NAME)): Write startp after start_fct, add atomic_write_barrier () in between. 2006-11-28 Jakub Jelinek <jakub@redhat.com> * elf/dl-support.c: Include dl-procinfo.h. * sysdeps/powerpc/dl-procinfo.h (PPC_PLATFORM_POWER4, PPC_PLATFORM_PPC970, PPC_PLATFORM_POWER5, PPC_PLATFORM_POWER5_PLUS, PPC_PLATFORM_POWER6, PPC_PLATFORM_CELL_BE, PPC_PLATFORM_POWER6X): Define. (_dl_string_platform): Use PPC_PLATFORM_* macros instead of hardcoded constants. * sysdeps/powerpc/dl-procinfo.c (_dl_powerpc_platform): Use PPC_PLATFORM_* macros for array designators. 2006-11-11 Steven Munroe <sjmunroe@us.ibm.com> * sysdeps/powerpc/dl-procinfo.c (_dl_powerpc_cap_flags): Add 3 new cap names to the beginning. (_dl_powerpc_platforms): Add "power6x". * sysdeps/powerpc/dl-procinfo.h (_DL_HWCAP_FIRST): Decrease. (HWCAP_IMPORTANT): Add PPC_FEATURE_HAS_DFP. (_DL_PLATFORMS_COUNT): Increase. (_dl_string_platform): Handle power6x case. * sysdeps/powerpc/sysdep.h (PPC_FEATURE_PA6T, PPC_FEATURE_HAS_DFP, PPC_FEATURE_POWER6_EXT): Define. (PPC_FEATURE_POWER5, PPC_FEATURE_POWER5_PLUS): Correct Comment. [-2^31 .. 2^31) range. * sysdeps/unix/sysv/linux/bits/statvfs.h: Define ST_RELATIME. * sysdeps/unix/sysv/linux/internal_statvfs.c (__statvfs_getflags): Handle relatime mount option. 2006-12-13 Jakub Jelinek <jakub@redhat.com> * sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext.S: Include kernel-features.h. 2006-12-11 Ulrich Drepper <drepper@redhat.com> * stdlib/strtod_l.c (____STRTOF_INTERNAL): Parse thousand separators also if no non-zero digits found. * stdlib/Makefile (tests): Add tst-strtod3. [BZ #3664] * stdlib/strtod_l.c (____STRTOF_INTERNAL): Fix test to recognize empty parsed strings. * stdlib/Makefile (tests): Add tst-strtod2. * stdlib/tst-strtod2.c: New file. [BZ #3673] * stdlib/strtod_l.c (____STRTOF_INTERNAL): Fix exp_limit computation. * stdlib/Makefile (tests): Add tst-atof2. * stdlib/tst-atof2.c: New file. [BZ #3674] * stdlib/strtod_l.c (____STRTOF_INTERNAL): Adjust exponent value correctly if removing trailing zero of hex-float. * stdlib/Makefile (tests): Add tst-atof1. * stdlib/tst-atof1.c: New file. * misc/mntent_r.c (__hasmntopt): Check p[optlen] even when p == rest. Start searching for next comma at p rather than rest. * misc/Makefile (tests): Add tst-mntent2. * misc/tst-mntent2.c: New test. 2006-12-08 Ulrich Drepper <drepper@redhat.com> * malloc/memusage.c: Handle realloc with new size of zero and non-NULL pointer correctly. (me): Really write first record twice. (struct entry): Make format bi-arch safe. (dest): Write out more realloc statistics. * malloc/memusagestat.c (struct entry): Make format bi-arch safe. 2006-12-05 Jakub Jelinek <jakub@redhat.com> * nis/nis_subr.c (nis_getnames): Revert last change. 2006-12-03 Kaz Kojima <kkojima@rr.iij4u.or.jp> * sysdeps/unix/sysv/linux/sh/sys/io.h: Removed. 2006-11-30 H.J. Lu <hongjiu.lu@intel.com> * sysdeps/i386/i686/memcmp.S: Use jump table as the base of jump table entries. 2006-11-30 Jan Kratochvil <jan.kratochvil@redhat.com> * sysdeps/unix/sysv/linux/i386/clone.S: Provide CFI for the outermost `clone' function to ensure proper unwinding stop of gdb. * sysdeps/unix/sysv/linux/x86_64/clone.S: Likewise. 2006-12-01 Ulrich Drepper <drepper@redhat.com> * nscd/nscd.init: Remove obsolete and commented-out -S option handling. 2006-11-23 Jakub Jelinek <jakub@redhat.com> [BZ #3514] * manual/string.texi (strncmp): Fix pastos from wcscmp description. [BZ #3515] * manual/string.texi (strtok): Remove duplicate paragraph. 2006-12-01 Jan Kratochvil <jan.kratochvil@redhat.com> * sysdeps/unix/sysv/linux/x86_64/sigaction.c: Fix compatibility with libgcc not supporting `rflags' unwinding (register # >= 17). 2006-11-30 Jakub Jelinek <jakub@redhat.com> * sunrpc/svc_run.c (svc_run): Set my_pollfd to new_pollfd if realloc succeeded. 2006-11-29 Daniel Jacobowitz <dan@codesourcery.com> Jakub Jelinek <jakub@redhat.com> Jan Kratochvil <jan.kratochvil@redhat.com> * sysdeps/unix/sysv/linux/x86_64/sigaction.c (restore_rt): Add correct unwind information. * sysdeps/unix/sysv/linux/x86_64/Makefile: Provide symbols for 'restore_rt' even in the 'signal' directory. * sysdeps/unix/sysv/linux/x86_64/ucontext_i.sym: Extend the regs list. malloc crashed. Don't allocate memory unnecessarily in each loop. 2006-10-21 Jakub Jelinek <jakub@redhat.com> * resolv/mapv4v6addr.h (map_v4v6_address): Fix last change. 2006-11-20 Ulrich Drepper <drepper@redhat.com> * resolv/mapv4v6addr.h (map_v4v6_address): Optimize a bit. 2006-11-18 Bruno Haible <bruno@clisp.org> * sysdeps/unix/sysv/linux/i386/getgroups.c (__getgroups): Invoke __sysconf only after having tried to call getgroups32. 2006-11-19 Ulrich Drepper <drepper@redhat.com> * nss/nss_files/files-hosts.c (LINE_PARSER): Support IPv6-style addresses for IPv4 queries if they can be mapped. 2006-11-16 Jakub Jelinek <jakub@redhat.com> * sysdeps/x86_64/fpu/s_copysignf.S (__copysignf): Switch to .text. * sysdeps/x86_64/fpu/s_copysign.S (__copysign): Likewise. (signmask): Add .size directive. (othermask): Add .type directive. 2006-11-14 Ulrich Drepper <drepper@redhat.com> * po/nl.po: Update from translation team. * timezone/zdump.c: Redo fix for BZ #3137. 2006-11-14 Jakub Jelinek <jakub@redhat.com> * nss/nss_files/files-alias.c (get_next_alias): Set line back to first_unused after parsing :include: file. * timezone/africa: Update from tzdata2006o. * timezone/antarctica: Likewise. * timezone/asia: Likewise. * timezone/australasia: Likewise. * timezone/backward: Likewise. * timezone/europe: Likewise. * timezone/iso3166.tab: Likewise. * timezone/northamerica: Likewise. * timezone/southamerica: Likewise. * timezone/zone.tab: Likewise. * time/tzfile.c (__tzfile_read): Extend to handle new file format on machines with 64-bit time_t. * timezone/checktab.awk: Update from tzcode2006o. * timezone/ialloc.c: Likewise. * timezone/private.h: Likewise. * timezone/scheck.c: Likewise. * timezone/tzfile.h: Likewise. * timezone/tzselect.ksh: Likewise. * timezone/zdump.c: Likewise. * timezone/zic.c: Likewise. [BZ #3483] * elf/ldconfig.c (main): Call setlocale and textdomain. Patch mostly by Benno Schulenberg <bensberg@justemail.net>. [BZ #3480] * manual/argp.texi: Fix typos. * manual/charset.texi: Likewise. * manual/errno.texi: Likewise. * manual/filesys.texi: Likewise. * manual/lang.texi: Likewise. * manual/maint.texi: Likewise. * manual/memory.texi: Likewise. * manual/message.texi: Likewise. * manual/resource.texi: Likewise. * manual/search.texi: Likewise. * manual/signal.texi: Likewise. * manual/startup.texi: Likewise. * manual/stdio.texi: Likewise. * manual/sysinfo.texi: Likewise. * manual/syslog.texi: Likewise. * manual/time.texi: Likewise. Patch by Ralf Wildenhues <Ralf.Wildenhues@gmx.de>. [BZ #3465] * sunrpc/clnt_raw.c: Minimal message improvements. * sunrpc/pm_getmaps.c: Likewise. * nis/nss_nisplus/nisplus-publickey.c: Likewise. * nis/nis_print_group_entry.c: Likewise. * locale/programs/repertoire.c: Likewise. * locale/programs/charmap.c: Likewise. * malloc/memusage.sh: Likewise. * elf/dl-deps.c: Likewise. * locale/programs/ld-collate.c: Likewise. * libio/vswprintf.c: Likewise. * malloc/memusagestat.c: Likewise. * sunrpc/auth_unix.c: Likewise. * sunrpc/rpc_main.c: Likewise. * nscd/cache.c: Likewise. * locale/programs/repertoire.c: Unify output messages. * locale/programs/charmap.c: Likewise. * locale/programs/ld-ctype.c: Likewise. * locale/programs/ld-monetary.c: Likewise. * locale/programs/ld-numeric.c: Likewise. * locale/programs/ld-time.c: Likewise. * elf/ldconfig.c: Likewise. * nscd/selinux.c: Likewise. * elf/cache.c: Likewise. Patch mostly by Benno Schulenberg <bensberg@justemail.net>. 2006-11-10 Jakub Jelinek <jakub@redhat.com> * string/strxfrm_l.c (STRXFRM): Fix trailing \1 optimization if N is one bigger than return value. * string/tst-strxfrm2.c (do_test): Also test strxfrm with l1 + 1 and l1 last arguments, if buf is defined, verify the return value equals to strlen (buf) and verify no byte beyond passed length is modified. 2006-11-10 Ulrich Drepper <drepper@redhat.com> * po/sv.po: Update from translation team. * sysdeps/gnu/siglist.c (__old_sys_siglist, __old_sys_sigabbrev): Use __new_sys_siglist instead of _sys_siglist_internal as second macro argument. (_old_sys_siglist): Use declare_symbol_alias macro instead of strong_alias. 2006-11-09 Ulrich Drepper <drepper@redhat.com> [BZ #3493] * posix/unistd.h (sysconf): Remove const attribute. * sysdeps/posix/getaddrinfo.c (getaddrinfo): Fix test for temporary or deprecated addresses. Patch by Sridhar Samudrala <sri@us.ibm.com>. * string/Makefile (tests): Add tst-strxfrm2. * string/tst-strxfrm2.c: New file. 2006-10-09 Jakub Jelinek <jakub@redhat.com> * elf/dl-debug.c (_dl_debug_initialize): Check r->r_map for 0 rather than r->r_brk. * string/strxfrm_l.c (STRXFRM): Do the trailing \1 removal optimization even if needed > n. 2006-11-07 Jakub Jelinek <jakub@redhat.com> * include/libc-symbols.h (declare_symbol): Rename to... (declare_symbol_alias): ... this. Add ORIGINAL argument, imply strong_alias (ORIGINAL, SYMBOL) in asm to make sure it preceedes .size directive. * sysdeps/gnu/errlist-compat.awk: Adjust for declare_symbol_alias changes. * sysdeps/gnu/siglist.c: Likewise. 2006-11-03 Steven Munroe <sjmunroe@us.ibm.com> * sysdeps/powerpc/fpu/bits/mathinline.h [__LIBC_INTERNAL_MATH_INLINES]: Moved to ... * sysdeps/powerpc/fpu/math_private.h: ...here. New file. 2006-11-05 Ulrich Drepper <drepper@redhat.com> * sysdeps/unix/sysv/linux/i386/sysconf.c (intel_check_word): Update handling of cache descriptor 0x49 for new models. * sysdeps/unix/sysv/linux/x86_64/sysconf.c (intel_check_word): Likewise. 2006-11-02 Ulrich Drepper <drepper@redhat.com> * configure.in: Work around ld --help change and avoid -z relro test completely if the architecture doesn't care about security. 2006-11-01 Ulrich Drepper <drepper@redhat.com> * po/sv.po: Update from translation team. 2006-10-31 Ulrich Drepper <drepper@redhat.com> * stdlib/atexit.c (atexit): Don't mark as hidden when used to generate compatibility version. 2006-10-29 Ulrich Drepper <drepper@redhat.com> * configure.in: Relax -z relro requirement a bit. * po/sv.po: Update from translation team. 2006-10-29 Jakub Jelinek <jakub@redhat.com> * elf/dl-sym.c (do_sym): Use RTLD_SINGLE_THREAD_P. * elf/dl-runtime.c (_dl_fixup, _dl_profile_fixup): Likewise. * elf/dl-close.c (_dl_close_worker): Likewise. * elf/dl-open.c (_dl_open_worker): Likewise. * sysdeps/generic/sysdep-cancel.h (RTLD_SINGLE_THREAD_P): Define. * configure.in: Require assembler support for visibility, compiler support for visibility and aliases, linker support for various -z options. * Makeconfig: Remove conditional code which now is unnecessary. * config.h.in: Likewise. * config.make.in: Likewise. * dlfcn/Makefile: Likewise. * elf/Makefile: Likewise. * elf/dl-load.c: Likewise. * elf/rtld.c: Likewise. * include/libc-symbols.h: Likewise. * include/stdio.h: Likewise. * io/Makefile: Likewise. * io/fstat.c: Likewise. * io/fstat64.c: Likewise. * io/fstatat.c: Likewise. * io/fstatat64.c: Likewise. * io/lstat.c: Likewise. * io/lstat64.c: Likewise. * io/mknod.c: Likewise. * io/mknodat.c: Likewise. * io/stat.c: Likewise. * io/stat64.c: Likewise. * libio/stdio.c: Likewise. * nscd/Makefile: Likewise. * stdlib/Makefile: Likewise. * stdlib/atexit.c: Likewise. * sysdeps/generic/ldsodefs.h: Likewise. * sysdeps/i386/dl-machine.h: Likewise. * sysdeps/i386/sysdep.h: Likewise. * sysdeps/i386/i686/memcmp.S: Likewise. * sysdeps/powerpc/powerpc32/sysdep.h: Likewise. * sysdeps/unix/sysv/linux/i386/sigaction.c: Likewise. * sysdeps/unix/sysv/linux/x86_64/sigaction.c: Likewise. * Makerules: USE_TLS support is now default. * tls.make.c: Likewise. * csu/Versions: Likewise. * csu/libc-start.c: Likewise. * csu/libc-tls.c: Likewise. * csu/version.c: Likewise. * dlfcn/dlinfo.c: Likewise. * elf/dl-addr.c: Likewise. * elf/dl-cache.c: Likewise. * elf/dl-close.c: Likewise. * elf/dl-iteratephdr.c: Likewise. * elf/dl-load.c: Likewise. * elf/dl-lookup.c: Likewise. * elf/dl-object.c: Likewise. * elf/dl-open.c: Likewise. * elf/dl-reloc.c: Likewise. * elf/dl-support.c: Likewise. * elf/dl-sym.c: Likewise. * elf/dl-sysdep.c: Likewise. * elf/dl-tls.c: Likewise. * elf/ldconfig.c: Likewise. * elf/rtld.c: Likewise. * elf/tst-tls-dlinfo.c: Likewise. * elf/tst-tls1.c: Likewise. * elf/tst-tls10.h: Likewise. * elf/tst-tls14.c: Likewise. * elf/tst-tls2.c: Likewise. * elf/tst-tls3.c: Likewise. * elf/tst-tls4.c: Likewise. * elf/tst-tls5.c: Likewise. * elf/tst-tls6.c: Likewise. * elf/tst-tls7.c: Likewise. * elf/tst-tls8.c: Likewise. * elf/tst-tls9.c: Likewise. * elf/tst-tlsmod1.c: Likewise. * elf/tst-tlsmod13.c: Likewise. * elf/tst-tlsmod13a.c: Likewise. * elf/tst-tlsmod14a.c: Likewise. * elf/tst-tlsmod2.c: Likewise. * elf/tst-tlsmod3.c: Likewise. * elf/tst-tlsmod4.c: Likewise. * elf/tst-tlsmod5.c: Likewise. * elf/tst-tlsmod6.c: Likewise. * include/errno.h: Likewise. * include/link.h: Likewise. * include/tls.h: Likewise. * locale/global-locale.c: Likewise. * locale/localeinfo.h: Likewise. * malloc/arena.c: Likewise. * malloc/hooks.c: Likewise. * malloc/malloc.c: Likewise. * resolv/Versions: Likewise. * sysdeps/alpha/dl-machine.h: Likewise. * sysdeps/alpha/libc-tls.c: Likewise. * sysdeps/generic/ldsodefs.h: Likewise. * sysdeps/generic/tls.h: Likewise. * sysdeps/i386/dl-machine.h: Likewise. * sysdeps/ia64/dl-machine.h: Likewise. * sysdeps/ia64/libc-tls.c: Likewise. * sysdeps/mach/hurd/fork.c: Likewise. * sysdeps/mach/hurd/i386/tls.h: Likewise. * sysdeps/powerpc/powerpc32/dl-machine.c: Likwise. * sysdeps/powerpc/powerpc32/dl-machine.h: Likewise. * sysdeps/powerpc/powerpc64/dl-machine.h: Likewise. * sysdeps/s390/libc-tls.c: Likewise. * sysdeps/s390/s390-32/dl-machine.h: Likewise. * sysdeps/s390/s390-64/dl-machine.h: Likewise. * sysdeps/sh/dl-machine.h: Likewise. * sysdeps/sparc/sparc32/dl-machine.h: Likewise. * sysdeps/sparc/sparc64/dl-machine.h: Likewise. * sysdeps/x86_64/dl-machine.h: Likewise. [BZ #3426] * stdlib/stdlib.h: Adjust comment for canonicalize_file_name to reality. 2006-10-27 Jakub Jelinek <jakub@redhat.com> * elf/dl-lookup.c (_dl_debug_bindings): Remove unused symbol_scope argument. (_dl_lookup_symbol_x): Adjust caller. * sysdeps/generic/ldsodefs.h (struct link_namespaces): Remove _ns_global_scope. * elf/rtld.c (dl_main): Don't initialize _ns_global_scope. * elf/dl-libc.c: Revert l_scope name changes. * elf/dl-load.c: Likewise. * elf/dl-object.c: Likewise. * elf/rtld.c: Likewise. * elf/dl-close.c (_dl_close): Likewise. * elf/dl-open.c (dl_open_worker): Likewise. If not SINGLE_THREAD_P, always use __rtld_mrlock_{change,done}. Always free old scope list here if not l_scope_mem. * elf/dl-runtime.c (_dl_fixup, _dl_profile_fixup): Revert l_scope name change. Never free scope list here. Just __rtld_mrlock_lock before the lookup and __rtld_mrlock_unlock it after the lookup. * elf/dl-sym.c: Likewise. * include/link.h (struct r_scoperec): Remove. (struct link_map): Replace l_scoperec with l_scope, l_scoperec_mem with l_scope_mem and l_scoperec_lock with l_scope_lock. 2006-10-25 Ulrich Drepper <drepper@redhat.com> * sysdeps/gnu/netinet/tcp.h: Define TCP_CONGESTION. 2006-10-18 Ulrich Drepper <drepper@redhat.com> * configure.in: Disable building profile libraries by default. 2006-10-18 Ulrich Drepper <drepper@redhat.com> * elf/dl-lookup.c (_dl_lookup_symbol_x): Add warning to _dl_lookup_symbol_x code. 2006-10-17 Jakub Jelinek <jakub@redhat.com> * elf/dl-runtime.c: Include sysdep-cancel.h. (_dl_fixup, _dl_profile_fixup): Use __rtld_mrlock_* and scoperec->nusers only if !SINGLE_THREAD_P. Use atomic_* instead of catomic_* macros. * elf/dl-sym.c: Include sysdep-cancel.h. (do_sym): Use __rtld_mrlock_* and scoperec->nusers only if !SINGLE_THREAD_P. Use atomic_* instead of catomic_* macros. * elf/dl-close.c: Include sysdep-cancel.h. (_dl_close): Use __rtld_mrlock_* and scoperec->nusers only if !SINGLE_THREAD_P. Use atomic_* instead of catomic_* macros. * elf/dl-open.c: Include sysdep-cancel.h. (dl_open_worker): Use __rtld_mrlock_* and scoperec->nusers only if !SINGLE_THREAD_P. Use atomic_* instead of catomic_* macros. 2006-10-17 Jakub Jelinek <jakub@redhat.com> [BZ #3313] * malloc/malloc.c (malloc_consolidate): Set maxfb to address of last fastbin rather than end of fastbin array. 2006-10-18 Ulrich Drepper <drepper@redhat.com> * sysdeps/i386/i486/bits/atomic.h (catomic_decrement): Use correct body macro. * sysdeps/x86_64/bits/atomic.h (__arch_c_compare_and_exchange_val_64_acq): Add missing casts. (catomic_decrement): Use correct body macro. 2006-10-17 Jakub Jelinek <jakub@redhat.com> * include/atomic.h: Add a unique prefix to all local variables in macros. * csu/tst-atomic.c (do_test): Test also catomic_* macros. 2006-10-14 Ulrich Drepper <drepper@redhat.com> * resolv/arpa/nameser.h: Document that ns_t_a6 is deprecated. [BZ #3313] * malloc/malloc.c (malloc_consolidate): Don't use get_fast_max to determine highest fast bin to consolidate, always look into all of them. (do_check_malloc_state): Only require for empty bins for large sizes in main arena. * libio/stdio.h: Add more __wur attributes. 2006-11-12 Andreas Jaeger <aj@suse.de> [BZ #2510] * manual/search.texi (Hash Search Function): Clarify. (Array Search Function): Clarify. 2006-11-12 Joseph Myers <joseph@codesourcery.com> [BZ #2830] * math/atest-exp.c (main): Cast hex value to mp_limb_t before shifting. * math/atest-exp2.c (read_mpn_hex): Likewise. * math/atest-sincos.c (main): Likewise. * sysdeps/unix/sysv/linux/syscalls.list: Add epoll_pwait. * sysdeps/unix/sysv/linux/sys/epoll.h: Declare epoll_pwait. * sysdeps/unix/sysv/linux/Versions (libc): Add epoll_pwait for version GLIBC_2.6. * Versions.def: Add GLIBC_2.6 for libc. * sysdeps/i386/i486/bits/atomic.h: Add catomic_* support. 2006-10-11 Jakub Jelinek <jakub@redhat.com> * malloc/malloc.c (_int_malloc): Remove unused any_larger variable. * nis/nis_defaults.c (__nis_default_access): Don't call getenv twice. * nis/nis_subr.c (nis_getnames): Use __secure_getenv instead of getenv. * sysdeps/generic/unsecvars.h: Add NIS_PATH. 2006-10-11 Ulrich Drepper <drepper@redhat.com> * include/atomic.c: Define catomic_* operations. * sysdeps/x86_64/bits/atomic.h: Likewise. Fix a few minor problems. * stdlib/cxa_finalize.c: Use catomic_* operations instead of atomic_*. * malloc/memusage.c: Likewise. * gmon/mcount.c: Likewise. * elf/dl-close.c: Likewise. * elf/dl-open.c: Likewise. * elf/dl-profile.c: Likewise. * elf/dl-sym.c: Likewise. * elf/dl-runtime.c: Likewise. * elf/dl-fptr.c: Likewise. * resolv/res_libc.c: Likewise. 2006-10-10 Roland McGrath <roland@frob.com> * sysdeps/mach/hurd/utimes.c: Use a union to avoid an improper cast. * sysdeps/mach/hurd/futimes.c: Likewise. * sysdeps/mach/hurd/lutimes.c: Likewise. 2006-10-09 Ulrich Drepper <drepper@redhat.com> Jakub Jelinek <jakub@redhat.com> Implement reference counting of scope records. * elf/dl-close.c (_dl_close): Remove all scopes from removed objects from the list in objects which remain. Always allocate new scope record. * elf/dl-open.c (dl_open_worker): When growing array for scopes, don't resize, allocate a new one. * elf/dl-runtime.c: Update reference counters before using a scope array. * elf/dl-sym.c: Likewise. * elf/dl-libc.c: Adjust for l_scope name change. * elf/dl-load.c: Likewise. * elf/dl-object.c: Likewise. * elf/rtld.c: Likewise. * include/link.h: Include <rtld-lowlevel.h>. Define struct r_scoperec. Replace r_scope with pointer to r_scoperec structure. Add l_scoperec_lock. * sysdeps/generic/ldsodefs.h: Include <rtld-lowlevel.h>. * sysdeps/generic/rtld-lowlevel.h: New file. * include/atomic.h: Rename atomic_and to atomic_and_val and atomic_or to atomic_or_val. Define new macros atomic_and and atomic_or which do not return values. * sysdeps/x86_64/bits/atomic.h: Define atomic_and and atomic_or. Various cleanups. * sysdeps/i386/i486/bits/atomic.h: Likewise. * po/sv.po: Update from translation team. 2006-10-07 Ulrich Drepper <drepper@redhat.com> * Versions.def: Add GLIBC_2.6 to libpthread. * include/shlib-compat.h (SHLIB_COMPAT): Expand parameters before use. (versioned_symbol): Likewise. (compat_symbol): Likewise. * po/tr.po: Update from translation team. * nis/Banner: Removed. It's been integral part forever and the author info is incomplete anyway. * libio/Banner: Likewise. 2006-10-06 Ulrich Drepper <drepper@redhat.com> * version.h (VERSION): Bump to 2.5.90 for new development tree.
985 lines
27 KiB
C
985 lines
27 KiB
C
/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
|
This file is part of the GNU C Library.
|
|
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
The GNU C Library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with the GNU C Library; if not, write to the Free
|
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
02111-1307 USA. */
|
|
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <signal.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/param.h>
|
|
#include <dl-sysdep.h>
|
|
#include <tls.h>
|
|
#include <lowlevellock.h>
|
|
|
|
|
|
#ifndef NEED_SEPARATE_REGISTER_STACK
|
|
|
|
/* Most architectures have exactly one stack pointer. Some have more. */
|
|
# define STACK_VARIABLES void *stackaddr = NULL
|
|
|
|
/* How to pass the values to the 'create_thread' function. */
|
|
# define STACK_VARIABLES_ARGS stackaddr
|
|
|
|
/* How to declare function which gets there parameters. */
|
|
# define STACK_VARIABLES_PARMS void *stackaddr
|
|
|
|
/* How to declare allocate_stack. */
|
|
# define ALLOCATE_STACK_PARMS void **stack
|
|
|
|
/* This is how the function is called. We do it this way to allow
|
|
other variants of the function to have more parameters. */
|
|
# define ALLOCATE_STACK(attr, pd) allocate_stack (attr, pd, &stackaddr)
|
|
|
|
#else
|
|
|
|
/* We need two stacks. The kernel will place them but we have to tell
|
|
the kernel about the size of the reserved address space. */
|
|
# define STACK_VARIABLES void *stackaddr = NULL; size_t stacksize = 0
|
|
|
|
/* How to pass the values to the 'create_thread' function. */
|
|
# define STACK_VARIABLES_ARGS stackaddr, stacksize
|
|
|
|
/* How to declare function which gets there parameters. */
|
|
# define STACK_VARIABLES_PARMS void *stackaddr, size_t stacksize
|
|
|
|
/* How to declare allocate_stack. */
|
|
# define ALLOCATE_STACK_PARMS void **stack, size_t *stacksize
|
|
|
|
/* This is how the function is called. We do it this way to allow
|
|
other variants of the function to have more parameters. */
|
|
# define ALLOCATE_STACK(attr, pd) \
|
|
allocate_stack (attr, pd, &stackaddr, &stacksize)
|
|
|
|
#endif
|
|
|
|
|
|
/* Default alignment of stack. */
|
|
#ifndef STACK_ALIGN
|
|
# define STACK_ALIGN __alignof__ (long double)
|
|
#endif
|
|
|
|
/* Default value for minimal stack size after allocating thread
|
|
descriptor and guard. */
|
|
#ifndef MINIMAL_REST_STACK
|
|
# define MINIMAL_REST_STACK 4096
|
|
#endif
|
|
|
|
|
|
/* Let the architecture add some flags to the mmap() call used to
|
|
allocate stacks. */
|
|
#ifndef ARCH_MAP_FLAGS
|
|
# define ARCH_MAP_FLAGS 0
|
|
#endif
|
|
|
|
/* This yields the pointer that TLS support code calls the thread pointer. */
|
|
#if TLS_TCB_AT_TP
|
|
# define TLS_TPADJ(pd) (pd)
|
|
#elif TLS_DTV_AT_TP
|
|
# define TLS_TPADJ(pd) ((struct pthread *)((char *) (pd) + TLS_PRE_TCB_SIZE))
|
|
#endif
|
|
|
|
/* Cache handling for not-yet free stacks. */
|
|
|
|
/* Maximum size in kB of cache. */
|
|
static size_t stack_cache_maxsize = 40 * 1024 * 1024; /* 40MiBi by default. */
|
|
static size_t stack_cache_actsize;
|
|
|
|
/* Mutex protecting this variable. */
|
|
static lll_lock_t stack_cache_lock = LLL_LOCK_INITIALIZER;
|
|
|
|
/* List of queued stack frames. */
|
|
static LIST_HEAD (stack_cache);
|
|
|
|
/* List of the stacks in use. */
|
|
static LIST_HEAD (stack_used);
|
|
|
|
/* List of the threads with user provided stacks in use. No need to
|
|
initialize this, since it's done in __pthread_initialize_minimal. */
|
|
list_t __stack_user __attribute__ ((nocommon));
|
|
hidden_data_def (__stack_user)
|
|
|
|
#if COLORING_INCREMENT != 0
|
|
/* Number of threads created. */
|
|
static unsigned int nptl_ncreated;
|
|
#endif
|
|
|
|
|
|
/* Check whether the stack is still used or not. */
|
|
#define FREE_P(descr) ((descr)->tid <= 0)
|
|
|
|
|
|
/* We create a double linked list of all cache entries. Double linked
|
|
because this allows removing entries from the end. */
|
|
|
|
|
|
/* Get a stack frame from the cache. We have to match by size since
|
|
some blocks might be too small or far too large. */
|
|
static struct pthread *
|
|
get_cached_stack (size_t *sizep, void **memp)
|
|
{
|
|
size_t size = *sizep;
|
|
struct pthread *result = NULL;
|
|
list_t *entry;
|
|
|
|
lll_lock (stack_cache_lock);
|
|
|
|
/* Search the cache for a matching entry. We search for the
|
|
smallest stack which has at least the required size. Note that
|
|
in normal situations the size of all allocated stacks is the
|
|
same. As the very least there are only a few different sizes.
|
|
Therefore this loop will exit early most of the time with an
|
|
exact match. */
|
|
list_for_each (entry, &stack_cache)
|
|
{
|
|
struct pthread *curr;
|
|
|
|
curr = list_entry (entry, struct pthread, list);
|
|
if (FREE_P (curr) && curr->stackblock_size >= size)
|
|
{
|
|
if (curr->stackblock_size == size)
|
|
{
|
|
result = curr;
|
|
break;
|
|
}
|
|
|
|
if (result == NULL
|
|
|| result->stackblock_size > curr->stackblock_size)
|
|
result = curr;
|
|
}
|
|
}
|
|
|
|
if (__builtin_expect (result == NULL, 0)
|
|
/* Make sure the size difference is not too excessive. In that
|
|
case we do not use the block. */
|
|
|| __builtin_expect (result->stackblock_size > 4 * size, 0))
|
|
{
|
|
/* Release the lock. */
|
|
lll_unlock (stack_cache_lock);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* Dequeue the entry. */
|
|
list_del (&result->list);
|
|
|
|
/* And add to the list of stacks in use. */
|
|
list_add (&result->list, &stack_used);
|
|
|
|
/* And decrease the cache size. */
|
|
stack_cache_actsize -= result->stackblock_size;
|
|
|
|
/* Release the lock early. */
|
|
lll_unlock (stack_cache_lock);
|
|
|
|
/* Report size and location of the stack to the caller. */
|
|
*sizep = result->stackblock_size;
|
|
*memp = result->stackblock;
|
|
|
|
/* Cancellation handling is back to the default. */
|
|
result->cancelhandling = 0;
|
|
result->cleanup = NULL;
|
|
|
|
/* No pending event. */
|
|
result->nextevent = NULL;
|
|
|
|
/* Clear the DTV. */
|
|
dtv_t *dtv = GET_DTV (TLS_TPADJ (result));
|
|
memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t));
|
|
|
|
/* Re-initialize the TLS. */
|
|
_dl_allocate_tls_init (TLS_TPADJ (result));
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/* Free stacks until cache size is lower than LIMIT. */
|
|
static void
|
|
free_stacks (size_t limit)
|
|
{
|
|
/* We reduce the size of the cache. Remove the last entries until
|
|
the size is below the limit. */
|
|
list_t *entry;
|
|
list_t *prev;
|
|
|
|
/* Search from the end of the list. */
|
|
list_for_each_prev_safe (entry, prev, &stack_cache)
|
|
{
|
|
struct pthread *curr;
|
|
|
|
curr = list_entry (entry, struct pthread, list);
|
|
if (FREE_P (curr))
|
|
{
|
|
/* Unlink the block. */
|
|
list_del (entry);
|
|
|
|
/* Account for the freed memory. */
|
|
stack_cache_actsize -= curr->stackblock_size;
|
|
|
|
/* Free the memory associated with the ELF TLS. */
|
|
_dl_deallocate_tls (TLS_TPADJ (curr), false);
|
|
|
|
/* Remove this block. This should never fail. If it does
|
|
something is really wrong. */
|
|
if (munmap (curr->stackblock, curr->stackblock_size) != 0)
|
|
abort ();
|
|
|
|
/* Maybe we have freed enough. */
|
|
if (stack_cache_actsize <= limit)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* Add a stack frame which is not used anymore to the stack. Must be
|
|
called with the cache lock held. */
|
|
static inline void
|
|
__attribute ((always_inline))
|
|
queue_stack (struct pthread *stack)
|
|
{
|
|
/* We unconditionally add the stack to the list. The memory may
|
|
still be in use but it will not be reused until the kernel marks
|
|
the stack as not used anymore. */
|
|
list_add (&stack->list, &stack_cache);
|
|
|
|
stack_cache_actsize += stack->stackblock_size;
|
|
if (__builtin_expect (stack_cache_actsize > stack_cache_maxsize, 0))
|
|
free_stacks (stack_cache_maxsize);
|
|
}
|
|
|
|
|
|
/* This function is called indirectly from the freeres code in libc. */
|
|
void
|
|
__free_stack_cache (void)
|
|
{
|
|
free_stacks (0);
|
|
}
|
|
|
|
|
|
static int
|
|
internal_function
|
|
change_stack_perm (struct pthread *pd
|
|
#ifdef NEED_SEPARATE_REGISTER_STACK
|
|
, size_t pagemask
|
|
#endif
|
|
)
|
|
{
|
|
#ifdef NEED_SEPARATE_REGISTER_STACK
|
|
void *stack = (pd->stackblock
|
|
+ (((((pd->stackblock_size - pd->guardsize) / 2)
|
|
& pagemask) + pd->guardsize) & pagemask));
|
|
size_t len = pd->stackblock + pd->stackblock_size - stack;
|
|
#else
|
|
void *stack = pd->stackblock + pd->guardsize;
|
|
size_t len = pd->stackblock_size - pd->guardsize;
|
|
#endif
|
|
if (mprotect (stack, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
|
|
return errno;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int
|
|
allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
|
ALLOCATE_STACK_PARMS)
|
|
{
|
|
struct pthread *pd;
|
|
size_t size;
|
|
size_t pagesize_m1 = __getpagesize () - 1;
|
|
void *stacktop;
|
|
|
|
assert (attr != NULL);
|
|
assert (powerof2 (pagesize_m1 + 1));
|
|
assert (TCB_ALIGNMENT >= STACK_ALIGN);
|
|
|
|
/* Get the stack size from the attribute if it is set. Otherwise we
|
|
use the default we determined at start time. */
|
|
size = attr->stacksize ?: __default_stacksize;
|
|
|
|
/* Get memory for the stack. */
|
|
if (__builtin_expect (attr->flags & ATTR_FLAG_STACKADDR, 0))
|
|
{
|
|
uintptr_t adj;
|
|
|
|
/* If the user also specified the size of the stack make sure it
|
|
is large enough. */
|
|
if (attr->stacksize != 0
|
|
&& attr->stacksize < (__static_tls_size + MINIMAL_REST_STACK))
|
|
return EINVAL;
|
|
|
|
/* Adjust stack size for alignment of the TLS block. */
|
|
#if TLS_TCB_AT_TP
|
|
adj = ((uintptr_t) attr->stackaddr - TLS_TCB_SIZE)
|
|
& __static_tls_align_m1;
|
|
assert (size > adj + TLS_TCB_SIZE);
|
|
#elif TLS_DTV_AT_TP
|
|
adj = ((uintptr_t) attr->stackaddr - __static_tls_size)
|
|
& __static_tls_align_m1;
|
|
assert (size > adj);
|
|
#endif
|
|
|
|
/* The user provided some memory. Let's hope it matches the
|
|
size... We do not allocate guard pages if the user provided
|
|
the stack. It is the user's responsibility to do this if it
|
|
is wanted. */
|
|
#if TLS_TCB_AT_TP
|
|
pd = (struct pthread *) ((uintptr_t) attr->stackaddr
|
|
- TLS_TCB_SIZE - adj);
|
|
#elif TLS_DTV_AT_TP
|
|
pd = (struct pthread *) (((uintptr_t) attr->stackaddr
|
|
- __static_tls_size - adj)
|
|
- TLS_PRE_TCB_SIZE);
|
|
#endif
|
|
|
|
/* The user provided stack memory needs to be cleared. */
|
|
memset (pd, '\0', sizeof (struct pthread));
|
|
|
|
/* The first TSD block is included in the TCB. */
|
|
pd->specific[0] = pd->specific_1stblock;
|
|
|
|
/* Remember the stack-related values. */
|
|
pd->stackblock = (char *) attr->stackaddr - size;
|
|
pd->stackblock_size = size;
|
|
|
|
/* This is a user-provided stack. It will not be queued in the
|
|
stack cache nor will the memory (except the TLS memory) be freed. */
|
|
pd->user_stack = true;
|
|
|
|
/* This is at least the second thread. */
|
|
pd->header.multiple_threads = 1;
|
|
#ifndef TLS_MULTIPLE_THREADS_IN_TCB
|
|
__pthread_multiple_threads = *__libc_multiple_threads_ptr = 1;
|
|
#endif
|
|
|
|
#ifdef NEED_DL_SYSINFO
|
|
/* Copy the sysinfo value from the parent. */
|
|
THREAD_SYSINFO(pd) = THREAD_SELF_SYSINFO;
|
|
#endif
|
|
|
|
/* The process ID is also the same as that of the caller. */
|
|
pd->pid = THREAD_GETMEM (THREAD_SELF, pid);
|
|
|
|
/* Allocate the DTV for this thread. */
|
|
if (_dl_allocate_tls (TLS_TPADJ (pd)) == NULL)
|
|
{
|
|
/* Something went wrong. */
|
|
assert (errno == ENOMEM);
|
|
return EAGAIN;
|
|
}
|
|
|
|
|
|
/* Prepare to modify global data. */
|
|
lll_lock (stack_cache_lock);
|
|
|
|
/* And add to the list of stacks in use. */
|
|
list_add (&pd->list, &__stack_user);
|
|
|
|
lll_unlock (stack_cache_lock);
|
|
}
|
|
else
|
|
{
|
|
/* Allocate some anonymous memory. If possible use the cache. */
|
|
size_t guardsize;
|
|
size_t reqsize;
|
|
void *mem;
|
|
const int prot = (PROT_READ | PROT_WRITE
|
|
| ((GL(dl_stack_flags) & PF_X) ? PROT_EXEC : 0));
|
|
|
|
#if COLORING_INCREMENT != 0
|
|
/* Add one more page for stack coloring. Don't do it for stacks
|
|
with 16 times pagesize or larger. This might just cause
|
|
unnecessary misalignment. */
|
|
if (size <= 16 * pagesize_m1)
|
|
size += pagesize_m1 + 1;
|
|
#endif
|
|
|
|
/* Adjust the stack size for alignment. */
|
|
size &= ~__static_tls_align_m1;
|
|
assert (size != 0);
|
|
|
|
/* Make sure the size of the stack is enough for the guard and
|
|
eventually the thread descriptor. */
|
|
guardsize = (attr->guardsize + pagesize_m1) & ~pagesize_m1;
|
|
if (__builtin_expect (size < ((guardsize + __static_tls_size
|
|
+ MINIMAL_REST_STACK + pagesize_m1)
|
|
& ~pagesize_m1),
|
|
0))
|
|
/* The stack is too small (or the guard too large). */
|
|
return EINVAL;
|
|
|
|
/* Try to get a stack from the cache. */
|
|
reqsize = size;
|
|
pd = get_cached_stack (&size, &mem);
|
|
if (pd == NULL)
|
|
{
|
|
/* To avoid aliasing effects on a larger scale than pages we
|
|
adjust the allocated stack size if necessary. This way
|
|
allocations directly following each other will not have
|
|
aliasing problems. */
|
|
#if MULTI_PAGE_ALIASING != 0
|
|
if ((size % MULTI_PAGE_ALIASING) == 0)
|
|
size += pagesize_m1 + 1;
|
|
#endif
|
|
|
|
mem = mmap (NULL, size, prot,
|
|
MAP_PRIVATE | MAP_ANONYMOUS | ARCH_MAP_FLAGS, -1, 0);
|
|
|
|
if (__builtin_expect (mem == MAP_FAILED, 0))
|
|
{
|
|
#ifdef ARCH_RETRY_MMAP
|
|
mem = ARCH_RETRY_MMAP (size);
|
|
if (__builtin_expect (mem == MAP_FAILED, 0))
|
|
#endif
|
|
return errno;
|
|
}
|
|
|
|
/* SIZE is guaranteed to be greater than zero.
|
|
So we can never get a null pointer back from mmap. */
|
|
assert (mem != NULL);
|
|
|
|
#if COLORING_INCREMENT != 0
|
|
/* Atomically increment NCREATED. */
|
|
unsigned int ncreated = atomic_increment_val (&nptl_ncreated);
|
|
|
|
/* We chose the offset for coloring by incrementing it for
|
|
every new thread by a fixed amount. The offset used
|
|
module the page size. Even if coloring would be better
|
|
relative to higher alignment values it makes no sense to
|
|
do it since the mmap() interface does not allow us to
|
|
specify any alignment for the returned memory block. */
|
|
size_t coloring = (ncreated * COLORING_INCREMENT) & pagesize_m1;
|
|
|
|
/* Make sure the coloring offsets does not disturb the alignment
|
|
of the TCB and static TLS block. */
|
|
if (__builtin_expect ((coloring & __static_tls_align_m1) != 0, 0))
|
|
coloring = (((coloring + __static_tls_align_m1)
|
|
& ~(__static_tls_align_m1))
|
|
& ~pagesize_m1);
|
|
#else
|
|
/* Unless specified we do not make any adjustments. */
|
|
# define coloring 0
|
|
#endif
|
|
|
|
/* Place the thread descriptor at the end of the stack. */
|
|
#if TLS_TCB_AT_TP
|
|
pd = (struct pthread *) ((char *) mem + size - coloring) - 1;
|
|
#elif TLS_DTV_AT_TP
|
|
pd = (struct pthread *) ((((uintptr_t) mem + size - coloring
|
|
- __static_tls_size)
|
|
& ~__static_tls_align_m1)
|
|
- TLS_PRE_TCB_SIZE);
|
|
#endif
|
|
|
|
/* Remember the stack-related values. */
|
|
pd->stackblock = mem;
|
|
pd->stackblock_size = size;
|
|
|
|
/* We allocated the first block thread-specific data array.
|
|
This address will not change for the lifetime of this
|
|
descriptor. */
|
|
pd->specific[0] = pd->specific_1stblock;
|
|
|
|
/* This is at least the second thread. */
|
|
pd->header.multiple_threads = 1;
|
|
#ifndef TLS_MULTIPLE_THREADS_IN_TCB
|
|
__pthread_multiple_threads = *__libc_multiple_threads_ptr = 1;
|
|
#endif
|
|
|
|
#ifdef NEED_DL_SYSINFO
|
|
/* Copy the sysinfo value from the parent. */
|
|
THREAD_SYSINFO(pd) = THREAD_SELF_SYSINFO;
|
|
#endif
|
|
|
|
/* The process ID is also the same as that of the caller. */
|
|
pd->pid = THREAD_GETMEM (THREAD_SELF, pid);
|
|
|
|
/* Allocate the DTV for this thread. */
|
|
if (_dl_allocate_tls (TLS_TPADJ (pd)) == NULL)
|
|
{
|
|
/* Something went wrong. */
|
|
assert (errno == ENOMEM);
|
|
|
|
/* Free the stack memory we just allocated. */
|
|
(void) munmap (mem, size);
|
|
|
|
return EAGAIN;
|
|
}
|
|
|
|
|
|
/* Prepare to modify global data. */
|
|
lll_lock (stack_cache_lock);
|
|
|
|
/* And add to the list of stacks in use. */
|
|
list_add (&pd->list, &stack_used);
|
|
|
|
lll_unlock (stack_cache_lock);
|
|
|
|
|
|
/* There might have been a race. Another thread might have
|
|
caused the stacks to get exec permission while this new
|
|
stack was prepared. Detect if this was possible and
|
|
change the permission if necessary. */
|
|
if (__builtin_expect ((GL(dl_stack_flags) & PF_X) != 0
|
|
&& (prot & PROT_EXEC) == 0, 0))
|
|
{
|
|
int err = change_stack_perm (pd
|
|
#ifdef NEED_SEPARATE_REGISTER_STACK
|
|
, ~pagesize_m1
|
|
#endif
|
|
);
|
|
if (err != 0)
|
|
{
|
|
/* Free the stack memory we just allocated. */
|
|
(void) munmap (mem, size);
|
|
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
/* Note that all of the stack and the thread descriptor is
|
|
zeroed. This means we do not have to initialize fields
|
|
with initial value zero. This is specifically true for
|
|
the 'tid' field which is always set back to zero once the
|
|
stack is not used anymore and for the 'guardsize' field
|
|
which will be read next. */
|
|
}
|
|
|
|
/* Create or resize the guard area if necessary. */
|
|
if (__builtin_expect (guardsize > pd->guardsize, 0))
|
|
{
|
|
#ifdef NEED_SEPARATE_REGISTER_STACK
|
|
char *guard = mem + (((size - guardsize) / 2) & ~pagesize_m1);
|
|
#else
|
|
char *guard = mem;
|
|
#endif
|
|
if (mprotect (guard, guardsize, PROT_NONE) != 0)
|
|
{
|
|
int err;
|
|
mprot_error:
|
|
err = errno;
|
|
|
|
lll_lock (stack_cache_lock);
|
|
|
|
/* Remove the thread from the list. */
|
|
list_del (&pd->list);
|
|
|
|
lll_unlock (stack_cache_lock);
|
|
|
|
/* Get rid of the TLS block we allocated. */
|
|
_dl_deallocate_tls (TLS_TPADJ (pd), false);
|
|
|
|
/* Free the stack memory regardless of whether the size
|
|
of the cache is over the limit or not. If this piece
|
|
of memory caused problems we better do not use it
|
|
anymore. Uh, and we ignore possible errors. There
|
|
is nothing we could do. */
|
|
(void) munmap (mem, size);
|
|
|
|
return err;
|
|
}
|
|
|
|
pd->guardsize = guardsize;
|
|
}
|
|
else if (__builtin_expect (pd->guardsize - guardsize > size - reqsize,
|
|
0))
|
|
{
|
|
/* The old guard area is too large. */
|
|
|
|
#ifdef NEED_SEPARATE_REGISTER_STACK
|
|
char *guard = mem + (((size - guardsize) / 2) & ~pagesize_m1);
|
|
char *oldguard = mem + (((size - pd->guardsize) / 2) & ~pagesize_m1);
|
|
|
|
if (oldguard < guard
|
|
&& mprotect (oldguard, guard - oldguard, prot) != 0)
|
|
goto mprot_error;
|
|
|
|
if (mprotect (guard + guardsize,
|
|
oldguard + pd->guardsize - guard - guardsize,
|
|
prot) != 0)
|
|
goto mprot_error;
|
|
#else
|
|
if (mprotect ((char *) mem + guardsize, pd->guardsize - guardsize,
|
|
prot) != 0)
|
|
goto mprot_error;
|
|
#endif
|
|
|
|
pd->guardsize = guardsize;
|
|
}
|
|
/* The pthread_getattr_np() calls need to get passed the size
|
|
requested in the attribute, regardless of how large the
|
|
actually used guardsize is. */
|
|
pd->reported_guardsize = guardsize;
|
|
}
|
|
|
|
/* Initialize the lock. We have to do this unconditionally since the
|
|
stillborn thread could be canceled while the lock is taken. */
|
|
pd->lock = LLL_LOCK_INITIALIZER;
|
|
|
|
/* The robust mutex lists also need to be initialized
|
|
unconditionally because the cleanup for the previous stack owner
|
|
might have happened in the kernel. */
|
|
pd->robust_head.futex_offset = (offsetof (pthread_mutex_t, __data.__lock)
|
|
- offsetof (pthread_mutex_t,
|
|
__data.__list.__next));
|
|
pd->robust_head.list_op_pending = NULL;
|
|
#ifdef __PTHREAD_MUTEX_HAVE_PREV
|
|
pd->robust_prev = &pd->robust_head;
|
|
#endif
|
|
pd->robust_head.list = &pd->robust_head;
|
|
|
|
/* We place the thread descriptor at the end of the stack. */
|
|
*pdp = pd;
|
|
|
|
#if TLS_TCB_AT_TP
|
|
/* The stack begins before the TCB and the static TLS block. */
|
|
stacktop = ((char *) (pd + 1) - __static_tls_size);
|
|
#elif TLS_DTV_AT_TP
|
|
stacktop = (char *) (pd - 1);
|
|
#endif
|
|
|
|
#ifdef NEED_SEPARATE_REGISTER_STACK
|
|
*stack = pd->stackblock;
|
|
*stacksize = stacktop - *stack;
|
|
#else
|
|
*stack = stacktop;
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
void
|
|
internal_function
|
|
__deallocate_stack (struct pthread *pd)
|
|
{
|
|
lll_lock (stack_cache_lock);
|
|
|
|
/* Remove the thread from the list of threads with user defined
|
|
stacks. */
|
|
list_del (&pd->list);
|
|
|
|
/* Not much to do. Just free the mmap()ed memory. Note that we do
|
|
not reset the 'used' flag in the 'tid' field. This is done by
|
|
the kernel. If no thread has been created yet this field is
|
|
still zero. */
|
|
if (__builtin_expect (! pd->user_stack, 1))
|
|
(void) queue_stack (pd);
|
|
else
|
|
/* Free the memory associated with the ELF TLS. */
|
|
_dl_deallocate_tls (TLS_TPADJ (pd), false);
|
|
|
|
lll_unlock (stack_cache_lock);
|
|
}
|
|
|
|
|
|
int
|
|
internal_function
|
|
__make_stacks_executable (void **stack_endp)
|
|
{
|
|
/* First the main thread's stack. */
|
|
int err = _dl_make_stack_executable (stack_endp);
|
|
if (err != 0)
|
|
return err;
|
|
|
|
#ifdef NEED_SEPARATE_REGISTER_STACK
|
|
const size_t pagemask = ~(__getpagesize () - 1);
|
|
#endif
|
|
|
|
lll_lock (stack_cache_lock);
|
|
|
|
list_t *runp;
|
|
list_for_each (runp, &stack_used)
|
|
{
|
|
err = change_stack_perm (list_entry (runp, struct pthread, list)
|
|
#ifdef NEED_SEPARATE_REGISTER_STACK
|
|
, pagemask
|
|
#endif
|
|
);
|
|
if (err != 0)
|
|
break;
|
|
}
|
|
|
|
/* Also change the permission for the currently unused stacks. This
|
|
might be wasted time but better spend it here than adding a check
|
|
in the fast path. */
|
|
if (err == 0)
|
|
list_for_each (runp, &stack_cache)
|
|
{
|
|
err = change_stack_perm (list_entry (runp, struct pthread, list)
|
|
#ifdef NEED_SEPARATE_REGISTER_STACK
|
|
, pagemask
|
|
#endif
|
|
);
|
|
if (err != 0)
|
|
break;
|
|
}
|
|
|
|
lll_unlock (stack_cache_lock);
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
/* In case of a fork() call the memory allocation in the child will be
|
|
the same but only one thread is running. All stacks except that of
|
|
the one running thread are not used anymore. We have to recycle
|
|
them. */
|
|
void
|
|
__reclaim_stacks (void)
|
|
{
|
|
struct pthread *self = (struct pthread *) THREAD_SELF;
|
|
|
|
/* No locking necessary. The caller is the only stack in use. */
|
|
|
|
/* Mark all stacks except the still running one as free. */
|
|
list_t *runp;
|
|
list_for_each (runp, &stack_used)
|
|
{
|
|
struct pthread *curp = list_entry (runp, struct pthread, list);
|
|
if (curp != self)
|
|
{
|
|
/* This marks the stack as free. */
|
|
curp->tid = 0;
|
|
|
|
/* The PID field must be initialized for the new process. */
|
|
curp->pid = self->pid;
|
|
|
|
/* Account for the size of the stack. */
|
|
stack_cache_actsize += curp->stackblock_size;
|
|
}
|
|
}
|
|
|
|
/* Reset the PIDs in any cached stacks. */
|
|
list_for_each (runp, &stack_cache)
|
|
{
|
|
struct pthread *curp = list_entry (runp, struct pthread, list);
|
|
curp->pid = self->pid;
|
|
}
|
|
|
|
/* Add the stack of all running threads to the cache. */
|
|
list_splice (&stack_used, &stack_cache);
|
|
|
|
/* Remove the entry for the current thread to from the cache list
|
|
and add it to the list of running threads. Which of the two
|
|
lists is decided by the user_stack flag. */
|
|
list_del (&self->list);
|
|
|
|
/* Re-initialize the lists for all the threads. */
|
|
INIT_LIST_HEAD (&stack_used);
|
|
INIT_LIST_HEAD (&__stack_user);
|
|
|
|
if (__builtin_expect (THREAD_GETMEM (self, user_stack), 0))
|
|
list_add (&self->list, &__stack_user);
|
|
else
|
|
list_add (&self->list, &stack_used);
|
|
|
|
/* There is one thread running. */
|
|
__nptl_nthreads = 1;
|
|
|
|
/* Initialize the lock. */
|
|
stack_cache_lock = LLL_LOCK_INITIALIZER;
|
|
}
|
|
|
|
|
|
#if HP_TIMING_AVAIL
|
|
# undef __find_thread_by_id
|
|
/* Find a thread given the thread ID. */
|
|
attribute_hidden
|
|
struct pthread *
|
|
__find_thread_by_id (pid_t tid)
|
|
{
|
|
struct pthread *result = NULL;
|
|
|
|
lll_lock (stack_cache_lock);
|
|
|
|
/* Iterate over the list with system-allocated threads first. */
|
|
list_t *runp;
|
|
list_for_each (runp, &stack_used)
|
|
{
|
|
struct pthread *curp;
|
|
|
|
curp = list_entry (runp, struct pthread, list);
|
|
|
|
if (curp->tid == tid)
|
|
{
|
|
result = curp;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
/* Now the list with threads using user-allocated stacks. */
|
|
list_for_each (runp, &__stack_user)
|
|
{
|
|
struct pthread *curp;
|
|
|
|
curp = list_entry (runp, struct pthread, list);
|
|
|
|
if (curp->tid == tid)
|
|
{
|
|
result = curp;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
out:
|
|
lll_unlock (stack_cache_lock);
|
|
|
|
return result;
|
|
}
|
|
#endif
|
|
|
|
|
|
static void
|
|
internal_function
|
|
setxid_signal_thread (struct xid_command *cmdp, struct pthread *t)
|
|
{
|
|
if (! IS_DETACHED (t))
|
|
{
|
|
int ch;
|
|
do
|
|
{
|
|
ch = t->cancelhandling;
|
|
|
|
/* If the thread is exiting right now, ignore it. */
|
|
if ((ch & EXITING_BITMASK) != 0)
|
|
return;
|
|
}
|
|
while (atomic_compare_and_exchange_bool_acq (&t->cancelhandling,
|
|
ch | SETXID_BITMASK, ch));
|
|
}
|
|
|
|
int val;
|
|
INTERNAL_SYSCALL_DECL (err);
|
|
#if __ASSUME_TGKILL
|
|
val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid),
|
|
t->tid, SIGSETXID);
|
|
#else
|
|
# ifdef __NR_tgkill
|
|
val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid),
|
|
t->tid, SIGSETXID);
|
|
if (INTERNAL_SYSCALL_ERROR_P (val, err)
|
|
&& INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS)
|
|
# endif
|
|
val = INTERNAL_SYSCALL (tkill, err, 2, t->tid, SIGSETXID);
|
|
#endif
|
|
|
|
if (!INTERNAL_SYSCALL_ERROR_P (val, err))
|
|
atomic_increment (&cmdp->cntr);
|
|
}
|
|
|
|
|
|
int
|
|
attribute_hidden
|
|
__nptl_setxid (struct xid_command *cmdp)
|
|
{
|
|
int result;
|
|
lll_lock (stack_cache_lock);
|
|
|
|
__xidcmd = cmdp;
|
|
cmdp->cntr = 0;
|
|
|
|
struct pthread *self = THREAD_SELF;
|
|
|
|
/* Iterate over the list with system-allocated threads first. */
|
|
list_t *runp;
|
|
list_for_each (runp, &stack_used)
|
|
{
|
|
struct pthread *t = list_entry (runp, struct pthread, list);
|
|
if (t == self)
|
|
continue;
|
|
|
|
setxid_signal_thread (cmdp, t);
|
|
}
|
|
|
|
/* Now the list with threads using user-allocated stacks. */
|
|
list_for_each (runp, &__stack_user)
|
|
{
|
|
struct pthread *t = list_entry (runp, struct pthread, list);
|
|
if (t == self)
|
|
continue;
|
|
|
|
setxid_signal_thread (cmdp, t);
|
|
}
|
|
|
|
int cur = cmdp->cntr;
|
|
while (cur != 0)
|
|
{
|
|
lll_futex_wait (&cmdp->cntr, cur);
|
|
cur = cmdp->cntr;
|
|
}
|
|
|
|
/* This must be last, otherwise the current thread might not have
|
|
permissions to send SIGSETXID syscall to the other threads. */
|
|
INTERNAL_SYSCALL_DECL (err);
|
|
result = INTERNAL_SYSCALL_NCS (cmdp->syscall_no, err, 3,
|
|
cmdp->id[0], cmdp->id[1], cmdp->id[2]);
|
|
if (INTERNAL_SYSCALL_ERROR_P (result, err))
|
|
{
|
|
__set_errno (INTERNAL_SYSCALL_ERRNO (result, err));
|
|
result = -1;
|
|
}
|
|
|
|
lll_unlock (stack_cache_lock);
|
|
return result;
|
|
}
|
|
|
|
static inline void __attribute__((always_inline))
|
|
init_one_static_tls (struct pthread *curp, struct link_map *map)
|
|
{
|
|
dtv_t *dtv = GET_DTV (TLS_TPADJ (curp));
|
|
# if TLS_TCB_AT_TP
|
|
void *dest = (char *) curp - map->l_tls_offset;
|
|
# elif TLS_DTV_AT_TP
|
|
void *dest = (char *) curp + map->l_tls_offset + TLS_PRE_TCB_SIZE;
|
|
# else
|
|
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
|
# endif
|
|
|
|
/* Fill in the DTV slot so that a later LD/GD access will find it. */
|
|
dtv[map->l_tls_modid].pointer.val = dest;
|
|
dtv[map->l_tls_modid].pointer.is_static = true;
|
|
|
|
/* Initialize the memory. */
|
|
memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
|
|
'\0', map->l_tls_blocksize - map->l_tls_initimage_size);
|
|
}
|
|
|
|
void
|
|
attribute_hidden
|
|
__pthread_init_static_tls (struct link_map *map)
|
|
{
|
|
lll_lock (stack_cache_lock);
|
|
|
|
/* Iterate over the list with system-allocated threads first. */
|
|
list_t *runp;
|
|
list_for_each (runp, &stack_used)
|
|
init_one_static_tls (list_entry (runp, struct pthread, list), map);
|
|
|
|
/* Now the list with threads using user-allocated stacks. */
|
|
list_for_each (runp, &__stack_user)
|
|
init_one_static_tls (list_entry (runp, struct pthread, list), map);
|
|
|
|
lll_unlock (stack_cache_lock);
|
|
}
|