summarylogtreecommitdiffstats
path: root/glibc-34fb5f61d3c3f4b8fc616ea259fa19168b58ecd4.patch
diff options
context:
space:
mode:
Diffstat (limited to 'glibc-34fb5f61d3c3f4b8fc616ea259fa19168b58ecd4.patch')
-rw-r--r--glibc-34fb5f61d3c3f4b8fc616ea259fa19168b58ecd4.patch4059
1 files changed, 0 insertions, 4059 deletions
diff --git a/glibc-34fb5f61d3c3f4b8fc616ea259fa19168b58ecd4.patch b/glibc-34fb5f61d3c3f4b8fc616ea259fa19168b58ecd4.patch
deleted file mode 100644
index fa7f94c4a793..000000000000
--- a/glibc-34fb5f61d3c3f4b8fc616ea259fa19168b58ecd4.patch
+++ /dev/null
@@ -1,4059 +0,0 @@
-diff --git a/ChangeLog b/ChangeLog
-index 59dab18463..20b650e026 100644
---- a/ChangeLog
-+++ b/ChangeLog
-@@ -1,3 +1,219 @@
-+2019-06-20 Dmitry V. Levin <ldv@altlinux.org>
-+ Florian Weimer <fweimer@redhat.com>
-+
-+ [BZ #24228]
-+ * libio/genops.c (_IO_unbuffer_all)
-+ [SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)]: Do not attempt to free wide
-+ buffers and access _IO_FILE_complete members of legacy libio streams.
-+ * libio/tst-bz24228.c: New file.
-+ * libio/tst-bz24228.map: Likewise.
-+ * libio/Makefile [build-shared] (tests): Add tst-bz24228.
-+ [build-shared] (generated): Add tst-bz24228.mtrace and
-+ tst-bz24228.check.
-+ [run-built-tests && build-shared] (tests-special): Add
-+ $(objpfx)tst-bz24228-mem.out.
-+ (LDFLAGS-tst-bz24228, tst-bz24228-ENV): New variables.
-+ ($(objpfx)tst-bz24228-mem.out): New rule.
-+
-+2019-03-13 Zack Weinberg <zackw@panix.com>
-+
-+ * scripts/check-obsolete-constructs.py: New test script.
-+ * scripts/check-installed-headers.sh: Remove tests for
-+ obsolete typedefs, superseded by check-obsolete-constructs.py.
-+ * Rules: Run scripts/check-obsolete-constructs.py over $(headers)
-+ as a special test. Update commentary.
-+ * posix/bits/types.h (__SQUAD_TYPE, __S64_TYPE): Define as __int64_t.
-+ (__UQUAD_TYPE, __U64_TYPE): Define as __uint64_t.
-+ Update commentary.
-+ * posix/sys/types.h (__u_intN_t): Remove.
-+ (u_int8_t): Typedef using __uint8_t.
-+ (u_int16_t): Typedef using __uint16_t.
-+ (u_int32_t): Typedef using __uint32_t.
-+ (u_int64_t): Typedef using __uint64_t.
-+
-+2019-04-18 Adhemerval Zanella <adhemerval.zanella@linaro.org>
-+
-+ * malloc/tst-memalign.c (do_test): Disable
-+ -Walloc-size-larger-than= around tests of malloc with negative
-+ sizes.
-+ * malloc/tst-malloc-too-large.c (do_test): Likewise.
-+
-+2019-05-22 Wilco Dijkstra <wdijkstr@arm.com>
-+
-+ [BZ #24531]
-+ * malloc/malloc.c (MAX_TCACHE_COUNT): New define.
-+ (do_set_tcache_count): Only update if count is small enough.
-+ * manual/tunables.texi (glibc.malloc.tcache_count): Document max value.
-+
-+2019-05-15 Mark Wielaard <mark@klomp.org>
-+
-+ [BZ#24476]
-+ * dlfcn/dlerror.c (__dlerror_main_freeres): Guard using
-+ __libc_once_get (once) and static_buf == NULL.
-+ (__dlerror): Check we have a valid key, set result to static_buf
-+ otherwise.
-+
-+2019-05-15 Andreas Schwab <schwab@suse.de>
-+
-+ [BZ #20568]
-+ * libio/wfileops.c (_IO_wfile_sync): Correct last argument to
-+ __codecvt_do_length.
-+ * libio/Makefile (tests): Add tst-wfile-sync.
-+ ($(objpfx)tst-wfile-sync.out): Depend on $(gen-locales).
-+ * libio/tst-wfile-sync.c: New file.
-+ * libio/tst-wfile-sync.input: New file.
-+
-+2019-04-23 Adhemerval Zanella <adhemerval.zanella@linaro.org>
-+
-+ [BZ #18035]
-+ * elf/Makefile (tests-container): Add tst-pldd.
-+ * elf/pldd-xx.c: Use _Static_assert in of pldd_assert.
-+ (E(find_maps)): Avoid use alloca, use default read file operations
-+ instead of explicit LFS names, and fix infinite loop.
-+ * elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers.
-+ (get_process_info): Use _Static_assert instead of assert, use default
-+ directory operations instead of explicit LFS names, and free some
-+ leadek pointers.
-+ * elf/tst-pldd.c: New file.
-+
-+2019-04-17 Adhemerval Zanella <adhemerval.zanella@linaro.org>
-+
-+ * support/Makefile (libsupport-routines): Add support_subprocess,
-+ xposix_spawn, xposix_spawn_file_actions_addclose, and
-+ xposix_spawn_file_actions_adddup2.
-+ (tst-support_capture_subprocess-ARGS): New rule.
-+ * support/capture_subprocess.h (support_capture_subprogram): New
-+ prototype.
-+ * support/support_capture_subprocess.c (support_capture_subprocess):
-+ Refactor to use support_subprocess and support_capture_poll.
-+ (support_capture_subprogram): New function.
-+ * support/tst-support_capture_subprocess.c (write_mode_to_str,
-+ str_to_write_mode, test_common, parse_int, handle_restart,
-+ do_subprocess, do_subprogram, do_multiple_tests): New functions.
-+ (do_test): Add support_capture_subprogram tests.
-+ * support/subprocess.h: New file.
-+ * support/support_subprocess.c: Likewise.
-+ * support/xposix_spawn.c: Likewise.
-+ * support/xposix_spawn_file_actions_addclose.c: Likewise.
-+ * support/xposix_spawn_file_actions_adddup2.c: Likewise.
-+ * support/xspawn.h: Likewise.
-+
-+2019-04-09 Carlos O'Donell <carlos@redhat.com>
-+ Kwok Cheung Yeung <kcy@codesourcery.com>
-+
-+ [BZ #16573]
-+ * malloc/mtrace.c: Define prototypes for all hooks.
-+ (set_default_hooks): New function.
-+ (set_trace_hooks): Likewise.
-+ (save_default_hooks): Likewise.
-+ (tr_freehook): Use new s*_hooks functions.
-+ (tr_mallochook): Likewise.
-+ (tr_reallochook): Likewise.
-+ (tr_memalignhook): Likewise.
-+ (mtrace): Likewise.
-+ (muntrace): Likewise.
-+
-+2019-04-02 TAMUKI Shoichi <tamuki@linet.gr.jp>
-+
-+ [BZ #22964]
-+ * localedata/locales/ja_JP (LC_TIME): Add entry for the new Japanese
-+ era.
-+
-+2019-03-02 TAMUKI Shoichi <tamuki@linet.gr.jp>
-+
-+ [BZ #24162]
-+ * localedata/locales/ja_JP (LC_TIME): Change the offset for Taisho
-+ gan-nen from 2 to 1. Problem reported by Morimitsu, Junji.
-+
-+2019-03-21 Stefan Liebler <stli@linux.ibm.com>
-+
-+ * sysdeps/s390/dl-procinfo.h (HWCAP_IMPORTANT):
-+ Add HWCAP_S390_VX and HWCAP_S390_VXE.
-+
-+2019-01-31 Paul Eggert <eggert@cs.ucla.edu>
-+
-+ CVE-2019-9169
-+ regex: fix read overrun [BZ #24114]
-+ Problem found by AddressSanitizer, reported by Hongxu Chen in:
-+ https://debbugs.gnu.org/34140
-+ * posix/regexec.c (proceed_next_node):
-+ Do not read past end of input buffer.
-+
-+2019-03-13 Stefan Liebler <stli@linux.ibm.com>
-+
-+ * elf/dl-sysdep.c (_dl_show_auxv): Remove condition and always
-+ call _dl_procinfo.
-+ * sysdeps/unix/sysv/linux/s390/dl-procinfo.h (_dl_procinfo):
-+ Ignore types other than AT_HWCAP.
-+ * sysdeps/sparc/dl-procinfo.h (_dl_procinfo): Likewise.
-+ * sysdeps/unix/sysv/linux/i386/dl-procinfo.h (_dl_procinfo):
-+ Likewise.
-+ * sysdeps/powerpc/dl-procinfo.h (_dl_procinfo): Adjust comment
-+ in the case of falling back to generic output mechanism.
-+ * sysdeps/unix/sysv/linux/arm/dl-procinfo.h (_dl_procinfo):
-+ Likewise.
-+
-+2019-02-15 Florian Weimer <fweimer@redhat.com>
-+
-+ [BZ #24211]
-+ * nptl/pthread_join_common.c (__pthread_timedjoin_ex): Do not read
-+ pd->result after the thread descriptor has been freed.
-+
-+2019-02-08 Florian Weimer <fweimer@redhat.com>
-+
-+ [BZ #24161]
-+ * sysdeps/nptl/fork.h (__run_fork_handlers): Add multiple_threads
-+ argument.
-+ * nptl/register-atfork.c (__run_fork_handlers): Only perform
-+ locking if the new do_locking argument is true.
-+ * sysdeps/nptl/fork.c (__libc_fork): Pass multiple_threads to
-+ __run_fork_handlers.
-+
-+2019-02-07 Stefan Liebler <stli@linux.ibm.com>
-+
-+ [BZ #24180]
-+ * nptl/pthread_mutex_trylock.c (__pthread_mutex_trylock):
-+ Add compiler barriers and comments.
-+
-+2019-02-05 Florian Weimer <fweimer@redhat.com>
-+
-+ [BZ #24164]
-+ arm: Use "nr" constraint for Systemtap probes, to avoid the
-+ compiler using memory operands for constants, due to the "o"
-+ alternative in the default "nor" constraint.
-+ * include/stap-probe.h [USE_STAP_PROBE]: Include
-+ <stap-probe-machine.h>
-+ * sysdeps/generic/stap-probe-machine.h: New file.
-+ * sysdeps/arm/stap-probe-machine.h: Likewise.
-+
-+2019-02-04 H.J. Lu <hongjiu.lu@intel.com>
-+
-+ [BZ #24155]
-+ CVE-2019-7309
-+ * NEWS: Updated for CVE-2019-7309.
-+ * sysdeps/x86_64/memcmp.S: Use RDX_LP for size. Clear the
-+ upper 32 bits of RDX register for x32. Use unsigned Jcc
-+ instructions, instead of signed.
-+ * sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memcmp-2.
-+ * sysdeps/x86_64/x32/tst-size_t-memcmp-2.c: New test.
-+
-+2019-01-31 Carlos O'Donell <carlos@redhat.com>
-+ Torvald Riegel <triegel@redhat.com>
-+ Rik Prohaska <prohaska7@gmail.com>
-+
-+ [BZ# 23844]
-+ * nptl/Makefile (tests): Add tst-rwlock-tryrdlock-stall, and
-+ tst-rwlock-trywrlock-stall.
-+ * nptl/pthread_rwlock_tryrdlock.c (__pthread_rwlock_tryrdlock):
-+ Wake waiters if PTHREAD_RWLOCK_FUTEX_USED is set.
-+ * nptl/pthread_rwlock_trywrlock.c (__pthread_rwlock_trywrlock):
-+ Set __wrphase_fute to 1 only if we started the write phase.
-+ * nptl/tst-rwlock-tryrdlock-stall.c: New file.
-+ * nptl/tst-rwlock-trywrlock-stall.c: New file.
-+ * support/Makefile (libsupport-routines): Add xpthread_rwlock_destroy.
-+ * support/xpthread_rwlock_destroy.c: New file.
-+ * support/xthread.h: Declare xpthread_rwlock_destroy.
-+
- 2019-01-31 Siddhesh Poyarekar <siddhesh@sourceware.org>
-
- * version.h (RELEASE): Set to "stable".
-diff --git a/NEWS b/NEWS
-index 912a9bdc0f..68d88b1036 100644
---- a/NEWS
-+++ b/NEWS
-@@ -4,6 +4,39 @@ See the end for copying conditions.
-
- Please send GNU C library bug reports via <https://sourceware.org/bugzilla/>
- using `glibc' in the "product" field.
-+
-+Version 2.29.1
-+
-+Major new features:
-+
-+* The entry for the new Japanese era has been added for ja_JP locale.
-+
-+The following bugs are resolved with this release:
-+
-+ [16573] malloc: Set and reset all hooks for tracing
-+ [18035] Fix pldd hang
-+ [20568] Fix crash in _IO_wfile_sync
-+ [24155] x32 memcmp can treat positive length as 0 (if sign bit in RDX is set) (CVE-2019-7309)
-+ [24164] Systemtap probes need to use "nr" constraint on 32-bit Arm
-+ [24161] __run_fork_handlers self-deadlocks in malloc/tst-mallocfork2
-+ [24211] Use-after-free in Systemtap probe in pthread_join
-+ [24228] old x86 applications that use legacy libio crash on exit
-+ [24476] dlfcn: Guard __dlerror_main_freeres with __libc_once_get (once)
-+
-+Security related changes:
-+
-+ CVE-2019-7309: x86-64 memcmp used signed Jcc instructions to check
-+ size. For x86-64, memcmp on an object size larger than SSIZE_MAX
-+ has undefined behavior. On x32, the size_t argument may be passed
-+ in the lower 32 bits of the 64-bit RDX register with non-zero upper
-+ 32 bits. When it happened with the sign bit of RDX register set,
-+ memcmp gave the wrong result since it treated the size argument as
-+ zero. Reported by H.J. Lu.
-+
-+ CVE-2019-9169: Attempted case-insensitive regular-expression match
-+ via proceed_next_node in posix/regexec.c leads to heap-based buffer
-+ over-read. Reported by Hongxu Chen.
-+
-
- Version 2.29
-
-diff --git a/Rules b/Rules
-index 1562f2ce6d..16afa6acaa 100644
---- a/Rules
-+++ b/Rules
-@@ -82,7 +82,8 @@ $(common-objpfx)dummy.c:
- common-generated += dummy.o dummy.c
-
- ifneq "$(headers)" ""
--# Special test of all the installed headers in this directory.
-+# Test that all of the headers installed by this directory can be compiled
-+# in isolation.
- tests-special += $(objpfx)check-installed-headers-c.out
- libof-check-installed-headers-c := testsuite
- $(objpfx)check-installed-headers-c.out: \
-@@ -93,6 +94,8 @@ $(objpfx)check-installed-headers-c.out: \
- $(evaluate-test)
-
- ifneq "$(CXX)" ""
-+# If a C++ compiler is available, also test that they can be compiled
-+# in isolation as C++.
- tests-special += $(objpfx)check-installed-headers-cxx.out
- libof-check-installed-headers-cxx := testsuite
- $(objpfx)check-installed-headers-cxx.out: \
-diff --git a/dlfcn/dlerror.c b/dlfcn/dlerror.c
-index 27376582d0..ca42c126c1 100644
---- a/dlfcn/dlerror.c
-+++ b/dlfcn/dlerror.c
-@@ -72,9 +72,16 @@ __dlerror (void)
- __libc_once (once, init);
-
- /* Get error string. */
-- result = (struct dl_action_result *) __libc_getspecific (key);
-- if (result == NULL)
-- result = &last_result;
-+ if (static_buf != NULL)
-+ result = static_buf;
-+ else
-+ {
-+ /* init () has been run and we don't use the static buffer.
-+ So we have a valid key. */
-+ result = (struct dl_action_result *) __libc_getspecific (key);
-+ if (result == NULL)
-+ result = &last_result;
-+ }
-
- /* Test whether we already returned the string. */
- if (result->returned != 0)
-@@ -230,13 +237,19 @@ free_key_mem (void *mem)
- void
- __dlerror_main_freeres (void)
- {
-- void *mem;
- /* Free the global memory if used. */
- check_free (&last_result);
-- /* Free the TSD memory if used. */
-- mem = __libc_getspecific (key);
-- if (mem != NULL)
-- free_key_mem (mem);
-+
-+ if (__libc_once_get (once) && static_buf == NULL)
-+ {
-+ /* init () has been run and we don't use the static buffer.
-+ So we have a valid key. */
-+ void *mem;
-+ /* Free the TSD memory if used. */
-+ mem = __libc_getspecific (key);
-+ if (mem != NULL)
-+ free_key_mem (mem);
-+ }
- }
-
- struct dlfcn_hook *_dlfcn_hook __attribute__((nocommon));
-diff --git a/elf/Makefile b/elf/Makefile
-index 9cf5cd8dfd..e7457e809f 100644
---- a/elf/Makefile
-+++ b/elf/Makefile
-@@ -194,6 +194,7 @@ tests-internal += loadtest unload unload2 circleload1 \
- tst-tls3 tst-tls6 tst-tls7 tst-tls8 tst-dlmopen2 \
- tst-ptrguard1 tst-stackguard1 tst-libc_dlvsym \
- tst-create_format1
-+tests-container += tst-pldd
- ifeq ($(build-hardcoded-path-in-tests),yes)
- tests += tst-dlopen-aout
- tst-dlopen-aout-no-pie = yes
-diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c
-index 5f6c679a3f..5d19b100b2 100644
---- a/elf/dl-sysdep.c
-+++ b/elf/dl-sysdep.c
-@@ -328,14 +328,9 @@ _dl_show_auxv (void)
- assert (AT_NULL == 0);
- assert (AT_IGNORE == 1);
-
-- if (av->a_type == AT_HWCAP || av->a_type == AT_HWCAP2
-- || AT_L1I_CACHEGEOMETRY || AT_L1D_CACHEGEOMETRY
-- || AT_L2_CACHEGEOMETRY || AT_L3_CACHEGEOMETRY)
-- {
-- /* These are handled in a special way per platform. */
-- if (_dl_procinfo (av->a_type, av->a_un.a_val) == 0)
-- continue;
-- }
-+ /* Some entries are handled in a special way per platform. */
-+ if (_dl_procinfo (av->a_type, av->a_un.a_val) == 0)
-+ continue;
-
- if (idx < sizeof (auxvars) / sizeof (auxvars[0])
- && auxvars[idx].form != unknown)
-diff --git a/elf/pldd-xx.c b/elf/pldd-xx.c
-index 547f840ee1..756f6d7a1c 100644
---- a/elf/pldd-xx.c
-+++ b/elf/pldd-xx.c
-@@ -23,10 +23,6 @@
- #define EW_(e, w, t) EW__(e, w, _##t)
- #define EW__(e, w, t) e##w##t
-
--#define pldd_assert(name, exp) \
-- typedef int __assert_##name[((exp) != 0) - 1]
--
--
- struct E(link_map)
- {
- EW(Addr) l_addr;
-@@ -39,12 +35,12 @@ struct E(link_map)
- EW(Addr) l_libname;
- };
- #if CLASS == __ELF_NATIVE_CLASS
--pldd_assert (l_addr, (offsetof (struct link_map, l_addr)
-- == offsetof (struct E(link_map), l_addr)));
--pldd_assert (l_name, (offsetof (struct link_map, l_name)
-- == offsetof (struct E(link_map), l_name)));
--pldd_assert (l_next, (offsetof (struct link_map, l_next)
-- == offsetof (struct E(link_map), l_next)));
-+_Static_assert (offsetof (struct link_map, l_addr)
-+ == offsetof (struct E(link_map), l_addr), "l_addr");
-+_Static_assert (offsetof (struct link_map, l_name)
-+ == offsetof (struct E(link_map), l_name), "l_name");
-+_Static_assert (offsetof (struct link_map, l_next)
-+ == offsetof (struct E(link_map), l_next), "l_next");
- #endif
-
-
-@@ -54,10 +50,10 @@ struct E(libname_list)
- EW(Addr) next;
- };
- #if CLASS == __ELF_NATIVE_CLASS
--pldd_assert (name, (offsetof (struct libname_list, name)
-- == offsetof (struct E(libname_list), name)));
--pldd_assert (next, (offsetof (struct libname_list, next)
-- == offsetof (struct E(libname_list), next)));
-+_Static_assert (offsetof (struct libname_list, name)
-+ == offsetof (struct E(libname_list), name), "name");
-+_Static_assert (offsetof (struct libname_list, next)
-+ == offsetof (struct E(libname_list), next), "next");
- #endif
-
- struct E(r_debug)
-@@ -69,16 +65,17 @@ struct E(r_debug)
- EW(Addr) r_map;
- };
- #if CLASS == __ELF_NATIVE_CLASS
--pldd_assert (r_version, (offsetof (struct r_debug, r_version)
-- == offsetof (struct E(r_debug), r_version)));
--pldd_assert (r_map, (offsetof (struct r_debug, r_map)
-- == offsetof (struct E(r_debug), r_map)));
-+_Static_assert (offsetof (struct r_debug, r_version)
-+ == offsetof (struct E(r_debug), r_version), "r_version");
-+_Static_assert (offsetof (struct r_debug, r_map)
-+ == offsetof (struct E(r_debug), r_map), "r_map");
- #endif
-
-
- static int
-
--E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
-+E(find_maps) (const char *exe, int memfd, pid_t pid, void *auxv,
-+ size_t auxv_size)
- {
- EW(Addr) phdr = 0;
- unsigned int phnum = 0;
-@@ -104,12 +101,9 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
- if (phdr == 0 || phnum == 0 || phent == 0)
- error (EXIT_FAILURE, 0, gettext ("cannot find program header of process"));
-
-- EW(Phdr) *p = alloca (phnum * phent);
-- if (pread64 (memfd, p, phnum * phent, phdr) != phnum * phent)
-- {
-- error (0, 0, gettext ("cannot read program header"));
-- return EXIT_FAILURE;
-- }
-+ EW(Phdr) *p = xmalloc (phnum * phent);
-+ if (pread (memfd, p, phnum * phent, phdr) != phnum * phent)
-+ error (EXIT_FAILURE, 0, gettext ("cannot read program header"));
-
- /* Determine the load offset. We need this for interpreting the
- other program header entries so we do this in a separate loop.
-@@ -129,24 +123,18 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
- if (p[i].p_type == PT_DYNAMIC)
- {
- EW(Dyn) *dyn = xmalloc (p[i].p_filesz);
-- if (pread64 (memfd, dyn, p[i].p_filesz, offset + p[i].p_vaddr)
-+ if (pread (memfd, dyn, p[i].p_filesz, offset + p[i].p_vaddr)
- != p[i].p_filesz)
-- {
-- error (0, 0, gettext ("cannot read dynamic section"));
-- return EXIT_FAILURE;
-- }
-+ error (EXIT_FAILURE, 0, gettext ("cannot read dynamic section"));
-
- /* Search for the DT_DEBUG entry. */
- for (unsigned int j = 0; j < p[i].p_filesz / sizeof (EW(Dyn)); ++j)
- if (dyn[j].d_tag == DT_DEBUG && dyn[j].d_un.d_ptr != 0)
- {
- struct E(r_debug) r;
-- if (pread64 (memfd, &r, sizeof (r), dyn[j].d_un.d_ptr)
-+ if (pread (memfd, &r, sizeof (r), dyn[j].d_un.d_ptr)
- != sizeof (r))
-- {
-- error (0, 0, gettext ("cannot read r_debug"));
-- return EXIT_FAILURE;
-- }
-+ error (EXIT_FAILURE, 0, gettext ("cannot read r_debug"));
-
- if (r.r_map != 0)
- {
-@@ -160,13 +148,10 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
- }
- else if (p[i].p_type == PT_INTERP)
- {
-- interp = alloca (p[i].p_filesz);
-- if (pread64 (memfd, interp, p[i].p_filesz, offset + p[i].p_vaddr)
-+ interp = xmalloc (p[i].p_filesz);
-+ if (pread (memfd, interp, p[i].p_filesz, offset + p[i].p_vaddr)
- != p[i].p_filesz)
-- {
-- error (0, 0, gettext ("cannot read program interpreter"));
-- return EXIT_FAILURE;
-- }
-+ error (EXIT_FAILURE, 0, gettext ("cannot read program interpreter"));
- }
-
- if (list == 0)
-@@ -174,14 +159,16 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
- if (interp == NULL)
- {
- // XXX check whether the executable itself is the loader
-- return EXIT_FAILURE;
-+ exit (EXIT_FAILURE);
- }
-
- // XXX perhaps try finding ld.so and _r_debug in it
--
-- return EXIT_FAILURE;
-+ exit (EXIT_FAILURE);
- }
-
-+ free (p);
-+ free (interp);
-+
- /* Print the PID and program name first. */
- printf ("%lu:\t%s\n", (unsigned long int) pid, exe);
-
-@@ -192,47 +179,27 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
- do
- {
- struct E(link_map) m;
-- if (pread64 (memfd, &m, sizeof (m), list) != sizeof (m))
-- {
-- error (0, 0, gettext ("cannot read link map"));
-- status = EXIT_FAILURE;
-- goto out;
-- }
-+ if (pread (memfd, &m, sizeof (m), list) != sizeof (m))
-+ error (EXIT_FAILURE, 0, gettext ("cannot read link map"));
-
- EW(Addr) name_offset = m.l_name;
-- again:
- while (1)
- {
-- ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
-+ ssize_t n = pread (memfd, tmpbuf.data, tmpbuf.length, name_offset);
- if (n == -1)
-- {
-- error (0, 0, gettext ("cannot read object name"));
-- status = EXIT_FAILURE;
-- goto out;
-- }
-+ error (EXIT_FAILURE, 0, gettext ("cannot read object name"));
-
- if (memchr (tmpbuf.data, '\0', n) != NULL)
- break;
-
- if (!scratch_buffer_grow (&tmpbuf))
-- {
-- error (0, 0, gettext ("cannot allocate buffer for object name"));
-- status = EXIT_FAILURE;
-- goto out;
-- }
-+ error (EXIT_FAILURE, 0,
-+ gettext ("cannot allocate buffer for object name"));
- }
-
-- if (((char *)tmpbuf.data)[0] == '\0' && name_offset == m.l_name
-- && m.l_libname != 0)
-- {
-- /* Try the l_libname element. */
-- struct E(libname_list) ln;
-- if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
-- {
-- name_offset = ln.name;
-- goto again;
-- }
-- }
-+ /* The m.l_name and m.l_libname.name for loader linkmap points to same
-+ values (since BZ#387 fix). Trying to use l_libname name as the
-+ shared object name might lead to an infinite loop (BZ#18035). */
-
- /* Skip over the executable. */
- if (((char *)tmpbuf.data)[0] != '\0')
-@@ -242,7 +209,6 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
- }
- while (list != 0);
-
-- out:
- scratch_buffer_free (&tmpbuf);
- return status;
- }
-diff --git a/elf/pldd.c b/elf/pldd.c
-index f3fac4e487..69629bd5d2 100644
---- a/elf/pldd.c
-+++ b/elf/pldd.c
-@@ -17,23 +17,17 @@
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
--#include <alloca.h>
-+#define _FILE_OFFSET_BITS 64
-+
- #include <argp.h>
--#include <assert.h>
- #include <dirent.h>
--#include <elf.h>
--#include <errno.h>
- #include <error.h>
- #include <fcntl.h>
- #include <libintl.h>
--#include <link.h>
--#include <stddef.h>
- #include <stdio.h>
- #include <stdlib.h>
--#include <string.h>
- #include <unistd.h>
- #include <sys/ptrace.h>
--#include <sys/stat.h>
- #include <sys/wait.h>
- #include <scratch_buffer.h>
-
-@@ -76,14 +70,9 @@ static struct argp argp =
- options, parse_opt, args_doc, doc, NULL, more_help, NULL
- };
-
--// File descriptor of /proc/*/mem file.
--static int memfd;
--
--/* Name of the executable */
--static char *exe;
-
- /* Local functions. */
--static int get_process_info (int dfd, long int pid);
-+static int get_process_info (const char *exe, int dfd, long int pid);
- static void wait_for_ptrace_stop (long int pid);
-
-
-@@ -102,8 +91,10 @@ main (int argc, char *argv[])
- return 1;
- }
-
-- assert (sizeof (pid_t) == sizeof (int)
-- || sizeof (pid_t) == sizeof (long int));
-+ _Static_assert (sizeof (pid_t) == sizeof (int)
-+ || sizeof (pid_t) == sizeof (long int),
-+ "sizeof (pid_t) != sizeof (int) or sizeof (long int)");
-+
- char *endp;
- errno = 0;
- long int pid = strtol (argv[remaining], &endp, 10);
-@@ -119,25 +110,24 @@ main (int argc, char *argv[])
- if (dfd == -1)
- error (EXIT_FAILURE, errno, gettext ("cannot open %s"), buf);
-
-- struct scratch_buffer exebuf;
-- scratch_buffer_init (&exebuf);
-+ /* Name of the executable */
-+ struct scratch_buffer exe;
-+ scratch_buffer_init (&exe);
- ssize_t nexe;
- while ((nexe = readlinkat (dfd, "exe",
-- exebuf.data, exebuf.length)) == exebuf.length)
-+ exe.data, exe.length)) == exe.length)
- {
-- if (!scratch_buffer_grow (&exebuf))
-+ if (!scratch_buffer_grow (&exe))
- {
- nexe = -1;
- break;
- }
- }
- if (nexe == -1)
-- exe = (char *) "<program name undetermined>";
-+ /* Default stack allocation is at least 1024. */
-+ snprintf (exe.data, exe.length, "<program name undetermined>");
- else
-- {
-- exe = exebuf.data;
-- exe[nexe] = '\0';
-- }
-+ ((char*)exe.data)[nexe] = '\0';
-
- /* Stop all threads since otherwise the list of loaded modules might
- change while we are reading it. */
-@@ -155,8 +145,8 @@ main (int argc, char *argv[])
- error (EXIT_FAILURE, errno, gettext ("cannot prepare reading %s/task"),
- buf);
-
-- struct dirent64 *d;
-- while ((d = readdir64 (dir)) != NULL)
-+ struct dirent *d;
-+ while ((d = readdir (dir)) != NULL)
- {
- if (! isdigit (d->d_name[0]))
- continue;
-@@ -182,7 +172,7 @@ main (int argc, char *argv[])
-
- wait_for_ptrace_stop (tid);
-
-- struct thread_list *newp = alloca (sizeof (*newp));
-+ struct thread_list *newp = xmalloc (sizeof (*newp));
- newp->tid = tid;
- newp->next = thread_list;
- thread_list = newp;
-@@ -190,17 +180,22 @@ main (int argc, char *argv[])
-
- closedir (dir);
-
-- int status = get_process_info (dfd, pid);
-+ if (thread_list == NULL)
-+ error (EXIT_FAILURE, 0, gettext ("no valid %s/task entries"), buf);
-+
-+ int status = get_process_info (exe.data, dfd, pid);
-
-- assert (thread_list != NULL);
- do
- {
- ptrace (PTRACE_DETACH, thread_list->tid, NULL, NULL);
-+ struct thread_list *prev = thread_list;
- thread_list = thread_list->next;
-+ free (prev);
- }
- while (thread_list != NULL);
-
- close (dfd);
-+ scratch_buffer_free (&exe);
-
- return status;
- }
-@@ -281,9 +276,10 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-
-
- static int
--get_process_info (int dfd, long int pid)
-+get_process_info (const char *exe, int dfd, long int pid)
- {
-- memfd = openat (dfd, "mem", O_RDONLY);
-+ /* File descriptor of /proc/<pid>/mem file. */
-+ int memfd = openat (dfd, "mem", O_RDONLY);
- if (memfd == -1)
- goto no_info;
-
-@@ -333,9 +329,9 @@ get_process_info (int dfd, long int pid)
-
- int retval;
- if (e_ident[EI_CLASS] == ELFCLASS32)
-- retval = find_maps32 (pid, auxv, auxv_size);
-+ retval = find_maps32 (exe, memfd, pid, auxv, auxv_size);
- else
-- retval = find_maps64 (pid, auxv, auxv_size);
-+ retval = find_maps64 (exe, memfd, pid, auxv, auxv_size);
-
- free (auxv);
- close (memfd);
-diff --git a/elf/tst-pldd.c b/elf/tst-pldd.c
-new file mode 100644
-index 0000000000..ed19cedd05
---- /dev/null
-+++ b/elf/tst-pldd.c
-@@ -0,0 +1,118 @@
-+/* Basic tests for pldd program.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+#include <stdio.h>
-+#include <string.h>
-+#include <unistd.h>
-+#include <stdint.h>
-+#include <libgen.h>
-+#include <stdbool.h>
-+
-+#include <array_length.h>
-+#include <gnu/lib-names.h>
-+
-+#include <support/subprocess.h>
-+#include <support/capture_subprocess.h>
-+#include <support/check.h>
-+
-+static void
-+target_process (void *arg)
-+{
-+ pause ();
-+}
-+
-+/* The test runs in a container because pldd does not support tracing
-+ a binary started by the loader iself (as with testrun.sh). */
-+
-+static int
-+do_test (void)
-+{
-+ /* Create a copy of current test to check with pldd. */
-+ struct support_subprocess target = support_subprocess (target_process, NULL);
-+
-+ /* Run 'pldd' on test subprocess. */
-+ struct support_capture_subprocess pldd;
-+ {
-+ /* Three digits per byte plus null terminator. */
-+ char pid[3 * sizeof (uint32_t) + 1];
-+ snprintf (pid, array_length (pid), "%d", target.pid);
-+
-+ const char prog[] = "/usr/bin/pldd";
-+
-+ pldd = support_capture_subprogram (prog,
-+ (char *const []) { (char *) prog, pid, NULL });
-+
-+ support_capture_subprocess_check (&pldd, "pldd", 0, sc_allow_stdout);
-+ }
-+
-+ /* Check 'pldd' output. The test is expected to be linked against only
-+ loader and libc. */
-+ {
-+ pid_t pid;
-+ char buffer[512];
-+#define STRINPUT(size) "%" # size "s"
-+
-+ FILE *out = fmemopen (pldd.out.buffer, pldd.out.length, "r");
-+ TEST_VERIFY (out != NULL);
-+
-+ /* First line is in the form of <pid>: <full path of executable> */
-+ TEST_COMPARE (fscanf (out, "%u: " STRINPUT (512), &pid, buffer), 2);
-+
-+ TEST_COMPARE (pid, target.pid);
-+ TEST_COMPARE (strcmp (basename (buffer), "tst-pldd"), 0);
-+
-+ /* It expects only one loader and libc loaded by the program. */
-+ bool interpreter_found = false, libc_found = false;
-+ while (fgets (buffer, array_length (buffer), out) != NULL)
-+ {
-+ /* Ignore vDSO. */
-+ if (buffer[0] != '/')
-+ continue;
-+
-+ /* Remove newline so baseline (buffer) can compare against the
-+ LD_SO and LIBC_SO macros unmodified. */
-+ if (buffer[strlen(buffer)-1] == '\n')
-+ buffer[strlen(buffer)-1] = '\0';
-+
-+ if (strcmp (basename (buffer), LD_SO) == 0)
-+ {
-+ TEST_COMPARE (interpreter_found, false);
-+ interpreter_found = true;
-+ continue;
-+ }
-+
-+ if (strcmp (basename (buffer), LIBC_SO) == 0)
-+ {
-+ TEST_COMPARE (libc_found, false);
-+ libc_found = true;
-+ continue;
-+ }
-+ }
-+ TEST_COMPARE (interpreter_found, true);
-+ TEST_COMPARE (libc_found, true);
-+
-+ fclose (out);
-+ }
-+
-+ support_capture_subprocess_free (&pldd);
-+ support_process_terminate (&target);
-+
-+ return 0;
-+}
-+
-+#include <support/test-driver.c>
-diff --git a/include/stap-probe.h b/include/stap-probe.h
-index c53dd86592..8c26292edd 100644
---- a/include/stap-probe.h
-+++ b/include/stap-probe.h
-@@ -21,6 +21,7 @@
-
- #ifdef USE_STAP_PROBE
-
-+# include <stap-probe-machine.h>
- # include <sys/sdt.h>
-
- /* Our code uses one macro LIBC_PROBE (name, n, arg1, ..., argn).
-diff --git a/libio/Makefile b/libio/Makefile
-index 5bee83e55c..9626a16b01 100644
---- a/libio/Makefile
-+++ b/libio/Makefile
-@@ -65,7 +65,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
- tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \
- tst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler \
- tst-ftell-append tst-fputws tst-bz22415 tst-fgetc-after-eof \
-- tst-sprintf-ub tst-sprintf-chk-ub
-+ tst-sprintf-ub tst-sprintf-chk-ub tst-wfile-sync
-
- tests-internal = tst-vtables tst-vtables-interposed tst-readline
-
-@@ -73,6 +73,9 @@ ifeq (yes,$(build-shared))
- # Add test-fopenloc only if shared library is enabled since it depends on
- # shared localedata objects.
- tests += tst-fopenloc
-+# Add tst-bz24228 only if shared library is enabled since it can never meet its
-+# objective with static linking because the relevant code just is not there.
-+tests += tst-bz24228
- endif
- test-srcs = test-freopen
-
-@@ -157,11 +160,14 @@ CFLAGS-tst_putwc.c += -DOBJPFX=\"$(objpfx)\"
- CFLAGS-tst-sprintf-ub.c += -Wno-restrict
- CFLAGS-tst-sprintf-chk-ub.c += -Wno-restrict
-
-+LDFLAGS-tst-bz24228 = -Wl,--version-script=tst-bz24228.map
-+
- tst_wprintf2-ARGS = "Some Text"
-
- test-fmemopen-ENV = MALLOC_TRACE=$(objpfx)test-fmemopen.mtrace
- tst-fopenloc-ENV = MALLOC_TRACE=$(objpfx)tst-fopenloc.mtrace
- tst-bz22415-ENV = MALLOC_TRACE=$(objpfx)tst-bz22415.mtrace
-+tst-bz24228-ENV = MALLOC_TRACE=$(objpfx)tst-bz24228.mtrace
-
- generated += test-fmemopen.mtrace test-fmemopen.check
- generated += tst-fopenloc.mtrace tst-fopenloc.check
-@@ -170,6 +176,7 @@ generated += tst-bz22415.mtrace tst-bz22415.check
- aux := fileops genops stdfiles stdio strops
-
- ifeq ($(build-shared),yes)
-+generated += tst-bz24228.mtrace tst-bz24228.check
- aux += oldfileops oldstdfiles
- endif
-
-@@ -184,7 +191,8 @@ tests-special += $(objpfx)test-freopen.out $(objpfx)test-fmemopen-mem.out \
- ifeq (yes,$(build-shared))
- # Run tst-fopenloc-cmp.out and tst-openloc-mem.out only if shared
- # library is enabled since they depend on tst-fopenloc.out.
--tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out
-+tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
-+ $(objpfx)tst-bz24228-mem.out
- endif
- endif
-
-@@ -212,6 +220,7 @@ $(objpfx)tst-ungetwc1.out: $(gen-locales)
- $(objpfx)tst-ungetwc2.out: $(gen-locales)
- $(objpfx)tst-widetext.out: $(gen-locales)
- $(objpfx)tst_wprintf2.out: $(gen-locales)
-+$(objpfx)tst-wfile-sync.out: $(gen-locales)
- endif
-
- $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
-@@ -235,3 +244,7 @@ $(objpfx)tst-fopenloc-mem.out: $(objpfx)tst-fopenloc.out
- $(objpfx)tst-bz22415-mem.out: $(objpfx)tst-bz22415.out
- $(common-objpfx)malloc/mtrace $(objpfx)tst-bz22415.mtrace > $@; \
- $(evaluate-test)
-+
-+$(objpfx)tst-bz24228-mem.out: $(objpfx)tst-bz24228.out
-+ $(common-objpfx)malloc/mtrace $(objpfx)tst-bz24228.mtrace > $@; \
-+ $(evaluate-test)
-diff --git a/libio/genops.c b/libio/genops.c
-index 2a0d9b81df..11a15549e8 100644
---- a/libio/genops.c
-+++ b/libio/genops.c
-@@ -789,9 +789,16 @@ _IO_unbuffer_all (void)
-
- for (fp = (FILE *) _IO_list_all; fp; fp = fp->_chain)
- {
-+ int legacy = 0;
-+
-+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
-+ if (__glibc_unlikely (_IO_vtable_offset (fp) != 0))
-+ legacy = 1;
-+#endif
-+
- if (! (fp->_flags & _IO_UNBUFFERED)
- /* Iff stream is un-orientated, it wasn't used. */
-- && fp->_mode != 0)
-+ && (legacy || fp->_mode != 0))
- {
- #ifdef _IO_MTSAFE_IO
- int cnt;
-@@ -805,7 +812,7 @@ _IO_unbuffer_all (void)
- __sched_yield ();
- #endif
-
-- if (! dealloc_buffers && !(fp->_flags & _IO_USER_BUF))
-+ if (! legacy && ! dealloc_buffers && !(fp->_flags & _IO_USER_BUF))
- {
- fp->_flags |= _IO_USER_BUF;
-
-@@ -816,7 +823,7 @@ _IO_unbuffer_all (void)
-
- _IO_SETBUF (fp, NULL, 0);
-
-- if (fp->_mode > 0)
-+ if (! legacy && fp->_mode > 0)
- _IO_wsetb (fp, NULL, NULL, 0);
-
- #ifdef _IO_MTSAFE_IO
-@@ -827,7 +834,8 @@ _IO_unbuffer_all (void)
-
- /* Make sure that never again the wide char functions can be
- used. */
-- fp->_mode = -1;
-+ if (! legacy)
-+ fp->_mode = -1;
- }
-
- #ifdef _IO_MTSAFE_IO
-diff --git a/libio/tst-bz24228.c b/libio/tst-bz24228.c
-new file mode 100644
-index 0000000000..6a74500d47
---- /dev/null
-+++ b/libio/tst-bz24228.c
-@@ -0,0 +1,29 @@
-+/* BZ #24228 check for memory corruption in legacy libio
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <https://www.gnu.org/licenses/>. */
-+
-+#include <mcheck.h>
-+#include <support/test-driver.h>
-+
-+static int
-+do_test (void)
-+{
-+ mtrace ();
-+ return 0;
-+}
-+
-+#include <support/test-driver.c>
-diff --git a/libio/tst-bz24228.map b/libio/tst-bz24228.map
-new file mode 100644
-index 0000000000..4383e0817d
---- /dev/null
-+++ b/libio/tst-bz24228.map
-@@ -0,0 +1,5 @@
-+# Hide the symbol from libc.so.6 to switch to the libio/oldfileops.c
-+# implementation when it is available for the architecture.
-+{
-+ local: _IO_stdin_used;
-+};
-diff --git a/libio/tst-wfile-sync.c b/libio/tst-wfile-sync.c
-new file mode 100644
-index 0000000000..618682064d
---- /dev/null
-+++ b/libio/tst-wfile-sync.c
-@@ -0,0 +1,39 @@
-+/* Test that _IO_wfile_sync does not crash (bug 20568).
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+#include <locale.h>
-+#include <stdio.h>
-+#include <wchar.h>
-+#include <support/check.h>
-+#include <support/xunistd.h>
-+
-+static int
-+do_test (void)
-+{
-+ TEST_VERIFY_EXIT (setlocale (LC_ALL, "de_DE.UTF-8") != NULL);
-+ /* Fill the stdio buffer and advance the read pointer. */
-+ TEST_VERIFY_EXIT (fgetwc (stdin) != WEOF);
-+ /* This calls _IO_wfile_sync, it should not crash. */
-+ TEST_VERIFY_EXIT (setvbuf (stdin, NULL, _IONBF, 0) == 0);
-+ /* Verify that the external file offset has been synchronized. */
-+ TEST_COMPARE (xlseek (0, 0, SEEK_CUR), 1);
-+
-+ return 0;
-+}
-+
-+#include <support/test-driver.c>
-diff --git a/libio/tst-wfile-sync.input b/libio/tst-wfile-sync.input
-new file mode 100644
-index 0000000000..12d0958f7a
---- /dev/null
-+++ b/libio/tst-wfile-sync.input
-@@ -0,0 +1 @@
-+This is a test of _IO_wfile_sync.
-diff --git a/libio/wfileops.c b/libio/wfileops.c
-index 78f20486e5..bab2ba4892 100644
---- a/libio/wfileops.c
-+++ b/libio/wfileops.c
-@@ -508,11 +508,12 @@ _IO_wfile_sync (FILE *fp)
- generate the wide characters up to the current reading
- position. */
- int nread;
--
-+ size_t wnread = (fp->_wide_data->_IO_read_ptr
-+ - fp->_wide_data->_IO_read_base);
- fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
- nread = (*cv->__codecvt_do_length) (cv, &fp->_wide_data->_IO_state,
- fp->_IO_read_base,
-- fp->_IO_read_end, delta);
-+ fp->_IO_read_end, wnread);
- fp->_IO_read_ptr = fp->_IO_read_base + nread;
- delta = -(fp->_IO_read_end - fp->_IO_read_base - nread);
- }
-diff --git a/localedata/locales/ja_JP b/localedata/locales/ja_JP
-index 1fd2fee44b..c64aaaff55 100644
---- a/localedata/locales/ja_JP
-+++ b/localedata/locales/ja_JP
-@@ -14946,12 +14946,14 @@ am_pm "<U5348><U524D>";"<U5348><U5F8C>"
-
- t_fmt_ampm "%p%I<U6642>%M<U5206>%S<U79D2>"
-
--era "+:2:1990//01//01:+*:<U5E73><U6210>:%EC%Ey<U5E74>";/
-+era "+:2:2020//01//01:+*:<U4EE4><U548C>:%EC%Ey<U5E74>";/
-+ "+:1:2019//05//01:2019//12//31:<U4EE4><U548C>:%EC<U5143><U5E74>";/
-+ "+:2:1990//01//01:2019//04//30:<U5E73><U6210>:%EC%Ey<U5E74>";/
- "+:1:1989//01//08:1989//12//31:<U5E73><U6210>:%EC<U5143><U5E74>";/
- "+:2:1927//01//01:1989//01//07:<U662D><U548C>:%EC%Ey<U5E74>";/
- "+:1:1926//12//25:1926//12//31:<U662D><U548C>:%EC<U5143><U5E74>";/
- "+:2:1913//01//01:1926//12//24:<U5927><U6B63>:%EC%Ey<U5E74>";/
-- "+:2:1912//07//30:1912//12//31:<U5927><U6B63>:%EC<U5143><U5E74>";/
-+ "+:1:1912//07//30:1912//12//31:<U5927><U6B63>:%EC<U5143><U5E74>";/
- "+:6:1873//01//01:1912//07//29:<U660E><U6CBB>:%EC%Ey<U5E74>";/
- "+:1:0001//01//01:1872//12//31:<U897F><U66A6>:%EC%Ey<U5E74>";/
- "+:1:-0001//12//31:-*:<U7D00><U5143><U524D>:%EC%Ey<U5E74>"
-diff --git a/malloc/malloc.c b/malloc/malloc.c
-index feaf7ee0bf..0abd653be2 100644
---- a/malloc/malloc.c
-+++ b/malloc/malloc.c
-@@ -2919,6 +2919,8 @@ typedef struct tcache_perthread_struct
- tcache_entry *entries[TCACHE_MAX_BINS];
- } tcache_perthread_struct;
-
-+#define MAX_TCACHE_COUNT 127 /* Maximum value of counts[] entries. */
-+
- static __thread bool tcache_shutting_down = false;
- static __thread tcache_perthread_struct *tcache = NULL;
-
-@@ -3876,10 +3878,14 @@ _int_malloc (mstate av, size_t bytes)
- {
- victim->fd_nextsize = fwd;
- victim->bk_nextsize = fwd->bk_nextsize;
-+ if (__glibc_unlikely (fwd->bk_nextsize->fd_nextsize != fwd))
-+ malloc_printerr ("malloc(): largebin double linked list corrupted (nextsize)");
- fwd->bk_nextsize = victim;
- victim->bk_nextsize->fd_nextsize = victim;
- }
- bck = fwd->bk;
-+ if (bck->fd != fwd)
-+ malloc_printerr ("malloc(): largebin double linked list corrupted (bk)");
- }
- }
- else
-@@ -5120,8 +5126,11 @@ static inline int
- __always_inline
- do_set_tcache_count (size_t value)
- {
-- LIBC_PROBE (memory_tunable_tcache_count, 2, value, mp_.tcache_count);
-- mp_.tcache_count = value;
-+ if (value <= MAX_TCACHE_COUNT)
-+ {
-+ LIBC_PROBE (memory_tunable_tcache_count, 2, value, mp_.tcache_count);
-+ mp_.tcache_count = value;
-+ }
- return 1;
- }
-
-diff --git a/malloc/mtrace.c b/malloc/mtrace.c
-index a2facf65ea..2fda262508 100644
---- a/malloc/mtrace.c
-+++ b/malloc/mtrace.c
-@@ -121,6 +121,41 @@ lock_and_info (const void *caller, Dl_info *mem)
- return res;
- }
-
-+static void tr_freehook (void *, const void *);
-+static void * tr_mallochook (size_t, const void *);
-+static void * tr_reallochook (void *, size_t, const void *);
-+static void * tr_memalignhook (size_t, size_t, const void *);
-+
-+/* Set all the default non-trace hooks. */
-+static __always_inline void
-+set_default_hooks (void)
-+{
-+ __free_hook = tr_old_free_hook;
-+ __malloc_hook = tr_old_malloc_hook;
-+ __realloc_hook = tr_old_realloc_hook;
-+ __memalign_hook = tr_old_memalign_hook;
-+}
-+
-+/* Set all of the tracing hooks used for mtrace. */
-+static __always_inline void
-+set_trace_hooks (void)
-+{
-+ __free_hook = tr_freehook;
-+ __malloc_hook = tr_mallochook;
-+ __realloc_hook = tr_reallochook;
-+ __memalign_hook = tr_memalignhook;
-+}
-+
-+/* Save the current set of hooks as the default hooks. */
-+static __always_inline void
-+save_default_hooks (void)
-+{
-+ tr_old_free_hook = __free_hook;
-+ tr_old_malloc_hook = __malloc_hook;
-+ tr_old_realloc_hook = __realloc_hook;
-+ tr_old_memalign_hook = __memalign_hook;
-+}
-+
- static void
- tr_freehook (void *ptr, const void *caller)
- {
-@@ -138,12 +173,12 @@ tr_freehook (void *ptr, const void *caller)
- tr_break ();
- __libc_lock_lock (lock);
- }
-- __free_hook = tr_old_free_hook;
-+ set_default_hooks ();
- if (tr_old_free_hook != NULL)
- (*tr_old_free_hook)(ptr, caller);
- else
- free (ptr);
-- __free_hook = tr_freehook;
-+ set_trace_hooks ();
- __libc_lock_unlock (lock);
- }
-
-@@ -155,12 +190,12 @@ tr_mallochook (size_t size, const void *caller)
- Dl_info mem;
- Dl_info *info = lock_and_info (caller, &mem);
-
-- __malloc_hook = tr_old_malloc_hook;
-+ set_default_hooks ();
- if (tr_old_malloc_hook != NULL)
- hdr = (void *) (*tr_old_malloc_hook)(size, caller);
- else
- hdr = (void *) malloc (size);
-- __malloc_hook = tr_mallochook;
-+ set_trace_hooks ();
-
- tr_where (caller, info);
- /* We could be printing a NULL here; that's OK. */
-@@ -185,16 +220,12 @@ tr_reallochook (void *ptr, size_t size, const void *caller)
- Dl_info mem;
- Dl_info *info = lock_and_info (caller, &mem);
-
-- __free_hook = tr_old_free_hook;
-- __malloc_hook = tr_old_malloc_hook;
-- __realloc_hook = tr_old_realloc_hook;
-+ set_default_hooks ();
- if (tr_old_realloc_hook != NULL)
- hdr = (void *) (*tr_old_realloc_hook)(ptr, size, caller);
- else
- hdr = (void *) realloc (ptr, size);
-- __free_hook = tr_freehook;
-- __malloc_hook = tr_mallochook;
-- __realloc_hook = tr_reallochook;
-+ set_trace_hooks ();
-
- tr_where (caller, info);
- if (hdr == NULL)
-@@ -230,14 +261,12 @@ tr_memalignhook (size_t alignment, size_t size, const void *caller)
- Dl_info mem;
- Dl_info *info = lock_and_info (caller, &mem);
-
-- __memalign_hook = tr_old_memalign_hook;
-- __malloc_hook = tr_old_malloc_hook;
-+ set_default_hooks ();
- if (tr_old_memalign_hook != NULL)
- hdr = (void *) (*tr_old_memalign_hook)(alignment, size, caller);
- else
- hdr = (void *) memalign (alignment, size);
-- __memalign_hook = tr_memalignhook;
-- __malloc_hook = tr_mallochook;
-+ set_trace_hooks ();
-
- tr_where (caller, info);
- /* We could be printing a NULL here; that's OK. */
-@@ -305,14 +334,8 @@ mtrace (void)
- malloc_trace_buffer = mtb;
- setvbuf (mallstream, malloc_trace_buffer, _IOFBF, TRACE_BUFFER_SIZE);
- fprintf (mallstream, "= Start\n");
-- tr_old_free_hook = __free_hook;
-- __free_hook = tr_freehook;
-- tr_old_malloc_hook = __malloc_hook;
-- __malloc_hook = tr_mallochook;
-- tr_old_realloc_hook = __realloc_hook;
-- __realloc_hook = tr_reallochook;
-- tr_old_memalign_hook = __memalign_hook;
-- __memalign_hook = tr_memalignhook;
-+ save_default_hooks ();
-+ set_trace_hooks ();
- #ifdef _LIBC
- if (!added_atexit_handler)
- {
-@@ -338,10 +361,7 @@ muntrace (void)
- file. */
- FILE *f = mallstream;
- mallstream = NULL;
-- __free_hook = tr_old_free_hook;
-- __malloc_hook = tr_old_malloc_hook;
-- __realloc_hook = tr_old_realloc_hook;
-- __memalign_hook = tr_old_memalign_hook;
-+ set_default_hooks ();
-
- fprintf (f, "= End\n");
- fclose (f);
-diff --git a/malloc/tst-malloc-too-large.c b/malloc/tst-malloc-too-large.c
-index 15e25f558e..51d42cee81 100644
---- a/malloc/tst-malloc-too-large.c
-+++ b/malloc/tst-malloc-too-large.c
-@@ -72,13 +72,28 @@ test_large_allocations (size_t size)
- void * ptr_to_realloc;
-
- test_setup ();
-+ DIAG_PUSH_NEEDS_COMMENT;
-+#if __GNUC_PREREQ (7, 0)
-+ /* GCC 7 warns about too-large allocations; here we want to test
-+ that they fail. */
-+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
-+#endif
- TEST_VERIFY (malloc (size) == NULL);
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_POP_NEEDS_COMMENT;
-+#endif
- TEST_VERIFY (errno == ENOMEM);
-
- ptr_to_realloc = malloc (16);
- TEST_VERIFY_EXIT (ptr_to_realloc != NULL);
- test_setup ();
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
-+#endif
- TEST_VERIFY (realloc (ptr_to_realloc, size) == NULL);
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_POP_NEEDS_COMMENT;
-+#endif
- TEST_VERIFY (errno == ENOMEM);
- free (ptr_to_realloc);
-
-@@ -135,7 +150,13 @@ test_large_aligned_allocations (size_t size)
- for (align = 1; align <= pagesize; align *= 2)
- {
- test_setup ();
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
-+#endif
- TEST_VERIFY (memalign (align, size) == NULL);
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_POP_NEEDS_COMMENT;
-+#endif
- TEST_VERIFY (errno == ENOMEM);
-
- /* posix_memalign expects an alignment that is a power of 2 *and* a
-@@ -151,7 +172,13 @@ test_large_aligned_allocations (size_t size)
- if ((size % align) == 0)
- {
- test_setup ();
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
-+#endif
- TEST_VERIFY (aligned_alloc (align, size) == NULL);
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_POP_NEEDS_COMMENT;
-+#endif
- TEST_VERIFY (errno == ENOMEM);
- }
- }
-@@ -159,11 +186,23 @@ test_large_aligned_allocations (size_t size)
- /* Both valloc and pvalloc return page-aligned memory. */
-
- test_setup ();
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
-+#endif
- TEST_VERIFY (valloc (size) == NULL);
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_POP_NEEDS_COMMENT;
-+#endif
- TEST_VERIFY (errno == ENOMEM);
-
- test_setup ();
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
-+#endif
- TEST_VERIFY (pvalloc (size) == NULL);
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_POP_NEEDS_COMMENT;
-+#endif
- TEST_VERIFY (errno == ENOMEM);
- }
-
-diff --git a/malloc/tst-memalign.c b/malloc/tst-memalign.c
-index a6a9140a3d..e7997518cb 100644
---- a/malloc/tst-memalign.c
-+++ b/malloc/tst-memalign.c
-@@ -21,6 +21,7 @@
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
-+#include <libc-diag.h>
-
- static int errors = 0;
-
-@@ -41,9 +42,18 @@ do_test (void)
-
- errno = 0;
-
-+ DIAG_PUSH_NEEDS_COMMENT;
-+#if __GNUC_PREREQ (7, 0)
-+ /* GCC 7 warns about too-large allocations; here we want to test
-+ that they fail. */
-+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
-+#endif
- /* An attempt to allocate a huge value should return NULL and set
- errno to ENOMEM. */
- p = memalign (sizeof (void *), -1);
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_POP_NEEDS_COMMENT;
-+#endif
-
- save = errno;
-
-diff --git a/manual/tunables.texi b/manual/tunables.texi
-index af820820e0..8edfea4edd 100644
---- a/manual/tunables.texi
-+++ b/manual/tunables.texi
-@@ -189,8 +189,8 @@ per-thread cache. The default (and maximum) value is 1032 bytes on
-
- @deftp Tunable glibc.malloc.tcache_count
- The maximum number of chunks of each size to cache. The default is 7.
--There is no upper limit, other than available system memory. If set
--to zero, the per-thread cache is effectively disabled.
-+The upper limit is 127. If set to zero, the per-thread cache is effectively
-+disabled.
-
- The approximate maximum overhead of the per-thread cache is thus equal
- to the number of bins times the chunk count in each bin times the size
-diff --git a/nptl/Makefile b/nptl/Makefile
-index 340282c6cb..0e316edfac 100644
---- a/nptl/Makefile
-+++ b/nptl/Makefile
-@@ -319,7 +319,8 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
- tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
- tst-cnd-timedwait tst-thrd-detach tst-mtx-basic tst-thrd-sleep \
- tst-mtx-recursive tst-tss-basic tst-call-once tst-mtx-timedlock \
-- tst-rwlock-pwn
-+ tst-rwlock-pwn \
-+ tst-rwlock-tryrdlock-stall tst-rwlock-trywrlock-stall
-
- tests-internal := tst-rwlock19 tst-rwlock20 \
- tst-sem11 tst-sem12 tst-sem13 \
-diff --git a/nptl/pthread_join_common.c b/nptl/pthread_join_common.c
-index ecb78ffba5..366feb376b 100644
---- a/nptl/pthread_join_common.c
-+++ b/nptl/pthread_join_common.c
-@@ -86,6 +86,7 @@ __pthread_timedjoin_ex (pthread_t threadid, void **thread_return,
- pthread_cleanup_pop (0);
- }
-
-+ void *pd_result = pd->result;
- if (__glibc_likely (result == 0))
- {
- /* We mark the thread as terminated and as joined. */
-@@ -93,7 +94,7 @@ __pthread_timedjoin_ex (pthread_t threadid, void **thread_return,
-
- /* Store the return value if the caller is interested. */
- if (thread_return != NULL)
-- *thread_return = pd->result;
-+ *thread_return = pd_result;
-
- /* Free the TCB. */
- __free_tcb (pd);
-@@ -101,7 +102,7 @@ __pthread_timedjoin_ex (pthread_t threadid, void **thread_return,
- else
- pd->joinid = NULL;
-
-- LIBC_PROBE (pthread_join_ret, 3, threadid, result, pd->result);
-+ LIBC_PROBE (pthread_join_ret, 3, threadid, result, pd_result);
-
- return result;
- }
-diff --git a/nptl/pthread_mutex_trylock.c b/nptl/pthread_mutex_trylock.c
-index 8fe43b8f0f..bf2869eca2 100644
---- a/nptl/pthread_mutex_trylock.c
-+++ b/nptl/pthread_mutex_trylock.c
-@@ -94,6 +94,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
- case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP:
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
- &mutex->__data.__list.__next);
-+ /* We need to set op_pending before starting the operation. Also
-+ see comments at ENQUEUE_MUTEX. */
-+ __asm ("" ::: "memory");
-
- oldval = mutex->__data.__lock;
- do
-@@ -119,7 +122,12 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
- /* But it is inconsistent unless marked otherwise. */
- mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
-
-+ /* We must not enqueue the mutex before we have acquired it.
-+ Also see comments at ENQUEUE_MUTEX. */
-+ __asm ("" ::: "memory");
- ENQUEUE_MUTEX (mutex);
-+ /* We need to clear op_pending after we enqueue the mutex. */
-+ __asm ("" ::: "memory");
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
-
- /* Note that we deliberately exist here. If we fall
-@@ -135,6 +143,8 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
- int kind = PTHREAD_MUTEX_TYPE (mutex);
- if (kind == PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP)
- {
-+ /* We do not need to ensure ordering wrt another memory
-+ access. Also see comments at ENQUEUE_MUTEX. */
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
- NULL);
- return EDEADLK;
-@@ -142,6 +152,8 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
-
- if (kind == PTHREAD_MUTEX_ROBUST_RECURSIVE_NP)
- {
-+ /* We do not need to ensure ordering wrt another memory
-+ access. */
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
- NULL);
-
-@@ -160,6 +172,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
- id, 0);
- if (oldval != 0 && (oldval & FUTEX_OWNER_DIED) == 0)
- {
-+ /* We haven't acquired the lock as it is already acquired by
-+ another owner. We do not need to ensure ordering wrt another
-+ memory access. */
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
-
- return EBUSY;
-@@ -173,13 +188,20 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
- if (oldval == id)
- lll_unlock (mutex->__data.__lock,
- PTHREAD_ROBUST_MUTEX_PSHARED (mutex));
-+ /* FIXME This violates the mutex destruction requirements. See
-+ __pthread_mutex_unlock_full. */
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
- return ENOTRECOVERABLE;
- }
- }
- while ((oldval & FUTEX_OWNER_DIED) != 0);
-
-+ /* We must not enqueue the mutex before we have acquired it.
-+ Also see comments at ENQUEUE_MUTEX. */
-+ __asm ("" ::: "memory");
- ENQUEUE_MUTEX (mutex);
-+ /* We need to clear op_pending after we enqueue the mutex. */
-+ __asm ("" ::: "memory");
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
-
- mutex->__data.__owner = id;
-@@ -211,10 +233,15 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
- }
-
- if (robust)
-- /* Note: robust PI futexes are signaled by setting bit 0. */
-- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
-- (void *) (((uintptr_t) &mutex->__data.__list.__next)
-- | 1));
-+ {
-+ /* Note: robust PI futexes are signaled by setting bit 0. */
-+ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
-+ (void *) (((uintptr_t) &mutex->__data.__list.__next)
-+ | 1));
-+ /* We need to set op_pending before starting the operation. Also
-+ see comments at ENQUEUE_MUTEX. */
-+ __asm ("" ::: "memory");
-+ }
-
- oldval = mutex->__data.__lock;
-
-@@ -223,12 +250,16 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
- {
- if (kind == PTHREAD_MUTEX_ERRORCHECK_NP)
- {
-+ /* We do not need to ensure ordering wrt another memory
-+ access. */
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
- return EDEADLK;
- }
-
- if (kind == PTHREAD_MUTEX_RECURSIVE_NP)
- {
-+ /* We do not need to ensure ordering wrt another memory
-+ access. */
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
-
- /* Just bump the counter. */
-@@ -250,6 +281,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
- {
- if ((oldval & FUTEX_OWNER_DIED) == 0)
- {
-+ /* We haven't acquired the lock as it is already acquired by
-+ another owner. We do not need to ensure ordering wrt another
-+ memory access. */
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
-
- return EBUSY;
-@@ -270,6 +304,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
- if (INTERNAL_SYSCALL_ERROR_P (e, __err)
- && INTERNAL_SYSCALL_ERRNO (e, __err) == EWOULDBLOCK)
- {
-+ /* The kernel has not yet finished the mutex owner death.
-+ We do not need to ensure ordering wrt another memory
-+ access. */
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
-
- return EBUSY;
-@@ -287,7 +324,12 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
- /* But it is inconsistent unless marked otherwise. */
- mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
-
-+ /* We must not enqueue the mutex before we have acquired it.
-+ Also see comments at ENQUEUE_MUTEX. */
-+ __asm ("" ::: "memory");
- ENQUEUE_MUTEX (mutex);
-+ /* We need to clear op_pending after we enqueue the mutex. */
-+ __asm ("" ::: "memory");
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
-
- /* Note that we deliberately exit here. If we fall
-@@ -310,13 +352,20 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
- PTHREAD_ROBUST_MUTEX_PSHARED (mutex)),
- 0, 0);
-
-+ /* To the kernel, this will be visible after the kernel has
-+ acquired the mutex in the syscall. */
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
- return ENOTRECOVERABLE;
- }
-
- if (robust)
- {
-+ /* We must not enqueue the mutex before we have acquired it.
-+ Also see comments at ENQUEUE_MUTEX. */
-+ __asm ("" ::: "memory");
- ENQUEUE_MUTEX_PI (mutex);
-+ /* We need to clear op_pending after we enqueue the mutex. */
-+ __asm ("" ::: "memory");
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
- }
-
-diff --git a/nptl/pthread_rwlock_tryrdlock.c b/nptl/pthread_rwlock_tryrdlock.c
-index 368862ff07..2f94f17f36 100644
---- a/nptl/pthread_rwlock_tryrdlock.c
-+++ b/nptl/pthread_rwlock_tryrdlock.c
-@@ -94,15 +94,22 @@ __pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock)
- /* Same as in __pthread_rwlock_rdlock_full:
- We started the read phase, so we are also responsible for
- updating the write-phase futex. Relaxed MO is sufficient.
-- Note that there can be no other reader that we have to wake
-- because all other readers will see the read phase started by us
-- (or they will try to start it themselves); if a writer started
-- the read phase, we cannot have started it. Furthermore, we
-- cannot discard a PTHREAD_RWLOCK_FUTEX_USED flag because we will
-- overwrite the value set by the most recent writer (or the readers
-- before it in case of explicit hand-over) and we know that there
-- are no waiting readers. */
-- atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 0);
-+ We have to do the same steps as a writer would when handing over the
-+ read phase to use because other readers cannot distinguish between
-+ us and the writer.
-+ Note that __pthread_rwlock_tryrdlock callers will not have to be
-+ woken up because they will either see the read phase started by us
-+ or they will try to start it themselves; however, callers of
-+ __pthread_rwlock_rdlock_full just increase the reader count and then
-+ check what state the lock is in, so they cannot distinguish between
-+ us and a writer that acquired and released the lock in the
-+ meantime. */
-+ if ((atomic_exchange_relaxed (&rwlock->__data.__wrphase_futex, 0)
-+ & PTHREAD_RWLOCK_FUTEX_USED) != 0)
-+ {
-+ int private = __pthread_rwlock_get_private (rwlock);
-+ futex_wake (&rwlock->__data.__wrphase_futex, INT_MAX, private);
-+ }
- }
-
- return 0;
-diff --git a/nptl/pthread_rwlock_trywrlock.c b/nptl/pthread_rwlock_trywrlock.c
-index fd37a71ce4..fae475cc70 100644
---- a/nptl/pthread_rwlock_trywrlock.c
-+++ b/nptl/pthread_rwlock_trywrlock.c
-@@ -46,8 +46,15 @@ __pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock)
- &rwlock->__data.__readers, &r,
- r | PTHREAD_RWLOCK_WRPHASE | PTHREAD_RWLOCK_WRLOCKED))
- {
-+ /* We have become the primary writer and we cannot have shared
-+ the PTHREAD_RWLOCK_FUTEX_USED flag with someone else, so we
-+ can simply enable blocking (see full wrlock code). */
- atomic_store_relaxed (&rwlock->__data.__writers_futex, 1);
-- atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1);
-+ /* If we started a write phase, we need to enable readers to
-+ wait. If we did not, we must not change it because other threads
-+ may have set the PTHREAD_RWLOCK_FUTEX_USED in the meantime. */
-+ if ((r & PTHREAD_RWLOCK_WRPHASE) == 0)
-+ atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1);
- atomic_store_relaxed (&rwlock->__data.__cur_writer,
- THREAD_GETMEM (THREAD_SELF, tid));
- return 0;
-diff --git a/nptl/register-atfork.c b/nptl/register-atfork.c
-index bc797b761a..80a1becb5f 100644
---- a/nptl/register-atfork.c
-+++ b/nptl/register-atfork.c
-@@ -107,13 +107,14 @@ __unregister_atfork (void *dso_handle)
- }
-
- void
--__run_fork_handlers (enum __run_fork_handler_type who)
-+__run_fork_handlers (enum __run_fork_handler_type who, _Bool do_locking)
- {
- struct fork_handler *runp;
-
- if (who == atfork_run_prepare)
- {
-- lll_lock (atfork_lock, LLL_PRIVATE);
-+ if (do_locking)
-+ lll_lock (atfork_lock, LLL_PRIVATE);
- size_t sl = fork_handler_list_size (&fork_handlers);
- for (size_t i = sl; i > 0; i--)
- {
-@@ -133,7 +134,8 @@ __run_fork_handlers (enum __run_fork_handler_type who)
- else if (who == atfork_run_parent && runp->parent_handler)
- runp->parent_handler ();
- }
-- lll_unlock (atfork_lock, LLL_PRIVATE);
-+ if (do_locking)
-+ lll_unlock (atfork_lock, LLL_PRIVATE);
- }
- }
-
-diff --git a/nptl/tst-rwlock-tryrdlock-stall.c b/nptl/tst-rwlock-tryrdlock-stall.c
-new file mode 100644
-index 0000000000..5e476da2b8
---- /dev/null
-+++ b/nptl/tst-rwlock-tryrdlock-stall.c
-@@ -0,0 +1,355 @@
-+/* Bug 23844: Test for pthread_rwlock_tryrdlock stalls.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+/* For a full analysis see comment:
-+ https://sourceware.org/bugzilla/show_bug.cgi?id=23844#c14
-+
-+ Provided here for reference:
-+
-+ --- Analysis of pthread_rwlock_tryrdlock() stall ---
-+ A read lock begins to execute.
-+
-+ In __pthread_rwlock_rdlock_full:
-+
-+ We can attempt a read lock, but find that the lock is
-+ in a write phase (PTHREAD_RWLOCK_WRPHASE, or WP-bit
-+ is set), and the lock is held by a primary writer
-+ (PTHREAD_RWLOCK_WRLOCKED is set). In this case we must
-+ wait for explicit hand over from the writer to us or
-+ one of the other waiters. The read lock threads are
-+ about to execute:
-+
-+ 341 r = (atomic_fetch_add_acquire (&rwlock->__data.__readers,
-+ 342 (1 << PTHREAD_RWLOCK_READER_SHIFT))
-+ 343 + (1 << PTHREAD_RWLOCK_READER_SHIFT));
-+
-+ An unlock beings to execute.
-+
-+ Then in __pthread_rwlock_wrunlock:
-+
-+ 547 unsigned int r = atomic_load_relaxed (&rwlock->__data.__readers);
-+ ...
-+ 549 while (!atomic_compare_exchange_weak_release
-+ 550 (&rwlock->__data.__readers, &r,
-+ 551 ((r ^ PTHREAD_RWLOCK_WRLOCKED)
-+ 552 ^ ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0 ? 0
-+ 553 : PTHREAD_RWLOCK_WRPHASE))))
-+ 554 {
-+ ...
-+ 556 }
-+
-+ We clear PTHREAD_RWLOCK_WRLOCKED, and if there are
-+ no readers so we leave the lock in PTHRAD_RWLOCK_WRPHASE.
-+
-+ Back in the read lock.
-+
-+ The read lock adjusts __readres as above.
-+
-+ 383 while ((r & PTHREAD_RWLOCK_WRPHASE) != 0
-+ 384 && (r & PTHREAD_RWLOCK_WRLOCKED) == 0)
-+ 385 {
-+ ...
-+ 390 if (atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers, &r,
-+ 391 r ^ PTHREAD_RWLOCK_WRPHASE))
-+ 392 {
-+
-+ And then attemps to start the read phase.
-+
-+ Assume there happens to be a tryrdlock at this point, noting
-+ that PTHREAD_RWLOCK_WRLOCKED is clear, and PTHREAD_RWLOCK_WRPHASE
-+ is 1. So the try lock attemps to start the read phase.
-+
-+ In __pthread_rwlock_tryrdlock:
-+
-+ 44 if ((r & PTHREAD_RWLOCK_WRPHASE) == 0)
-+ 45 {
-+ ...
-+ 49 if (((r & PTHREAD_RWLOCK_WRLOCKED) != 0)
-+ 50 && (rwlock->__data.__flags
-+ 51 == PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP))
-+ 52 return EBUSY;
-+ 53 rnew = r + (1 << PTHREAD_RWLOCK_READER_SHIFT);
-+ 54 }
-+ ...
-+ 89 while (!atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers,
-+ 90 &r, rnew));
-+
-+ And succeeds.
-+
-+ Back in the write unlock:
-+
-+ 557 if ((r >> PTHREAD_RWLOCK_READER_SHIFT) != 0)
-+ 558 {
-+ ...
-+ 563 if ((atomic_exchange_relaxed (&rwlock->__data.__wrphase_futex, 0)
-+ 564 & PTHREAD_RWLOCK_FUTEX_USED) != 0)
-+ 565 futex_wake (&rwlock->__data.__wrphase_futex, INT_MAX, private);
-+ 566 }
-+
-+ We note that PTHREAD_RWLOCK_FUTEX_USED is non-zero
-+ and don't wake anyone. This is OK because we handed
-+ over to the trylock. It will be the trylock's responsibility
-+ to wake any waiters.
-+
-+ Back in the read lock:
-+
-+ The read lock fails to install PTHRAD_REWLOCK_WRPHASE as 0 because
-+ the __readers value was adjusted by the trylock, and so it falls through
-+ to waiting on the lock for explicit handover from either a new writer
-+ or a new reader.
-+
-+ 448 int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
-+ 449 1 | PTHREAD_RWLOCK_FUTEX_USED,
-+ 450 abstime, private);
-+
-+ We use PTHREAD_RWLOCK_FUTEX_USED to indicate the futex
-+ is in use.
-+
-+ At this point we have readers waiting on the read lock
-+ to unlock. The wrlock is done. The trylock is finishing
-+ the installation of the read phase.
-+
-+ 92 if ((r & PTHREAD_RWLOCK_WRPHASE) != 0)
-+ 93 {
-+ ...
-+ 105 atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 0);
-+ 106 }
-+
-+ The trylock does note that we were the one that
-+ installed the read phase, but the comments are not
-+ correct, the execution ordering above shows that
-+ readers might indeed be waiting, and they are.
-+
-+ The atomic_store_relaxed throws away PTHREAD_RWLOCK_FUTEX_USED,
-+ and the waiting reader is never worken becuase as noted
-+ above it is conditional on the futex being used.
-+
-+ The solution is for the trylock thread to inspect
-+ PTHREAD_RWLOCK_FUTEX_USED and wake the waiting readers.
-+
-+ --- Analysis of pthread_rwlock_trywrlock() stall ---
-+
-+ A write lock begins to execute, takes the write lock,
-+ and then releases the lock...
-+
-+ In pthread_rwlock_wrunlock():
-+
-+ 547 unsigned int r = atomic_load_relaxed (&rwlock->__data.__readers);
-+ ...
-+ 549 while (!atomic_compare_exchange_weak_release
-+ 550 (&rwlock->__data.__readers, &r,
-+ 551 ((r ^ PTHREAD_RWLOCK_WRLOCKED)
-+ 552 ^ ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0 ? 0
-+ 553 : PTHREAD_RWLOCK_WRPHASE))))
-+ 554 {
-+ ...
-+ 556 }
-+
-+ ... leaving it in the write phase with zero readers
-+ (the case where we leave the write phase in place
-+ during a write unlock).
-+
-+ A write trylock begins to execute.
-+
-+ In __pthread_rwlock_trywrlock:
-+
-+ 40 while (((r & PTHREAD_RWLOCK_WRLOCKED) == 0)
-+ 41 && (((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0)
-+ 42 || (prefer_writer && ((r & PTHREAD_RWLOCK_WRPHASE) != 0))))
-+ 43 {
-+
-+ The lock is not locked.
-+
-+ There are no readers.
-+
-+ 45 if (atomic_compare_exchange_weak_acquire (
-+ 46 &rwlock->__data.__readers, &r,
-+ 47 r | PTHREAD_RWLOCK_WRPHASE | PTHREAD_RWLOCK_WRLOCKED))
-+
-+ We atomically install the write phase and we take the
-+ exclusive write lock.
-+
-+ 48 {
-+ 49 atomic_store_relaxed (&rwlock->__data.__writers_futex, 1);
-+
-+ We get this far.
-+
-+ A reader lock begins to execute.
-+
-+ In pthread_rwlock_rdlock:
-+
-+ 437 for (;;)
-+ 438 {
-+ 439 while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex))
-+ 440 | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED))
-+ 441 {
-+ 442 int private = __pthread_rwlock_get_private (rwlock);
-+ 443 if (((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0)
-+ 444 && (!atomic_compare_exchange_weak_relaxed
-+ 445 (&rwlock->__data.__wrphase_futex,
-+ 446 &wpf, wpf | PTHREAD_RWLOCK_FUTEX_USED)))
-+ 447 continue;
-+ 448 int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
-+ 449 1 | PTHREAD_RWLOCK_FUTEX_USED,
-+ 450 abstime, private);
-+
-+ We are in a write phase, so the while() on line 439 is true.
-+
-+ The value of wpf does not have PTHREAD_RWLOCK_FUTEX_USED set
-+ since this is the first reader to lock.
-+
-+ The atomic operation sets wpf with PTHREAD_RELOCK_FUTEX_USED
-+ on the expectation that this reader will be woken during
-+ the handoff.
-+
-+ Back in pthread_rwlock_trywrlock:
-+
-+ 50 atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1);
-+ 51 atomic_store_relaxed (&rwlock->__data.__cur_writer,
-+ 52 THREAD_GETMEM (THREAD_SELF, tid));
-+ 53 return 0;
-+ 54 }
-+ ...
-+ 57 }
-+
-+ We write 1 to __wrphase_futex discarding PTHREAD_RWLOCK_FUTEX_USED,
-+ and so in the unlock we will not awaken the waiting reader.
-+
-+ The solution to this is to realize that if we did not start the write
-+ phase we need not write 1 or any other value to __wrphase_futex.
-+ This ensures that any readers (which saw __wrphase_futex != 0) can
-+ set PTHREAD_RWLOCK_FUTEX_USED and this can be used at unlock to
-+ wake them.
-+
-+ If we installed the write phase then all other readers are looping
-+ here:
-+
-+ In __pthread_rwlock_rdlock_full:
-+
-+ 437 for (;;)
-+ 438 {
-+ 439 while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex))
-+ 440 | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED))
-+ 441 {
-+ ...
-+ 508 }
-+
-+ waiting for the write phase to be installed or removed before they
-+ can begin waiting on __wrphase_futex (part of the algorithm), or
-+ taking a concurrent read lock, and thus we can safely write 1 to
-+ __wrphase_futex.
-+
-+ If we did not install the write phase then the readers may already
-+ be waiting on the futex, the original writer wrote 1 to __wrphase_futex
-+ as part of starting the write phase, and we cannot also write 1
-+ without loosing the PTHREAD_RWLOCK_FUTEX_USED bit.
-+
-+ ---
-+
-+ Summary for the pthread_rwlock_tryrdlock() stall:
-+
-+ The stall is caused by pthread_rwlock_tryrdlock failing to check
-+ that PTHREAD_RWLOCK_FUTEX_USED is set in the __wrphase_futex futex
-+ and then waking the futex.
-+
-+ The fix for bug 23844 ensures that waiters on __wrphase_futex are
-+ correctly woken. Before the fix the test stalls as readers can
-+ wait forever on __wrphase_futex. */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <pthread.h>
-+#include <support/xthread.h>
-+#include <errno.h>
-+
-+/* We need only one lock to reproduce the issue. We will need multiple
-+ threads to get the exact case where we have a read, try, and unlock
-+ all interleaving to produce the case where the readers are waiting
-+ and the try fails to wake them. */
-+pthread_rwlock_t onelock;
-+
-+/* The number of threads is arbitrary but empirically chosen to have
-+ enough threads that we see the condition where waiting readers are
-+ not woken by a successful tryrdlock. */
-+#define NTHREADS 32
-+
-+_Atomic int do_exit;
-+
-+void *
-+run_loop (void *arg)
-+{
-+ int i = 0, ret;
-+ while (!do_exit)
-+ {
-+ /* Arbitrarily choose if we are the writer or reader. Choose a
-+ high enough ratio of readers to writers to make it likely
-+ that readers block (and eventually are susceptable to
-+ stalling).
-+
-+ If we are a writer, take the write lock, and then unlock.
-+ If we are a reader, try the lock, then lock, then unlock. */
-+ if ((i % 8) != 0)
-+ xpthread_rwlock_wrlock (&onelock);
-+ else
-+ {
-+ if ((ret = pthread_rwlock_tryrdlock (&onelock)) != 0)
-+ {
-+ if (ret == EBUSY)
-+ xpthread_rwlock_rdlock (&onelock);
-+ else
-+ exit (EXIT_FAILURE);
-+ }
-+ }
-+ /* Thread does some work and then unlocks. */
-+ xpthread_rwlock_unlock (&onelock);
-+ i++;
-+ }
-+ return NULL;
-+}
-+
-+int
-+do_test (void)
-+{
-+ int i;
-+ pthread_t tids[NTHREADS];
-+ xpthread_rwlock_init (&onelock, NULL);
-+ for (i = 0; i < NTHREADS; i++)
-+ tids[i] = xpthread_create (NULL, run_loop, NULL);
-+ /* Run for some amount of time. Empirically speaking exercising
-+ the stall via pthread_rwlock_tryrdlock is much harder, and on
-+ a 3.5GHz 4 core x86_64 VM system it takes somewhere around
-+ 20-200s to stall, approaching 100% stall past 200s. We can't
-+ wait that long for a regression test so we just test for 20s,
-+ and expect the stall to happen with a 5-10% chance (enough for
-+ developers to see). */
-+ sleep (20);
-+ /* Then exit. */
-+ printf ("INFO: Exiting...\n");
-+ do_exit = 1;
-+ /* If any readers stalled then we will timeout waiting for them. */
-+ for (i = 0; i < NTHREADS; i++)
-+ xpthread_join (tids[i]);
-+ printf ("INFO: Done.\n");
-+ xpthread_rwlock_destroy (&onelock);
-+ printf ("PASS: No pthread_rwlock_tryrdlock stalls detected.\n");
-+ return 0;
-+}
-+
-+#define TIMEOUT 30
-+#include <support/test-driver.c>
-diff --git a/nptl/tst-rwlock-trywrlock-stall.c b/nptl/tst-rwlock-trywrlock-stall.c
-new file mode 100644
-index 0000000000..14d27cbcbc
---- /dev/null
-+++ b/nptl/tst-rwlock-trywrlock-stall.c
-@@ -0,0 +1,108 @@
-+/* Bug 23844: Test for pthread_rwlock_trywrlock stalls.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+/* For a full analysis see comments in tst-rwlock-tryrdlock-stall.c.
-+
-+ Summary for the pthread_rwlock_trywrlock() stall:
-+
-+ The stall is caused by pthread_rwlock_trywrlock setting
-+ __wrphase_futex futex to 1 and loosing the
-+ PTHREAD_RWLOCK_FUTEX_USED bit.
-+
-+ The fix for bug 23844 ensures that waiters on __wrphase_futex are
-+ correctly woken. Before the fix the test stalls as readers can
-+ wait forever on __wrphase_futex. */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <pthread.h>
-+#include <support/xthread.h>
-+#include <errno.h>
-+
-+/* We need only one lock to reproduce the issue. We will need multiple
-+ threads to get the exact case where we have a read, try, and unlock
-+ all interleaving to produce the case where the readers are waiting
-+ and the try clears the PTHREAD_RWLOCK_FUTEX_USED bit and a
-+ subsequent unlock fails to wake them. */
-+pthread_rwlock_t onelock;
-+
-+/* The number of threads is arbitrary but empirically chosen to have
-+ enough threads that we see the condition where waiting readers are
-+ not woken by a successful unlock. */
-+#define NTHREADS 32
-+
-+_Atomic int do_exit;
-+
-+void *
-+run_loop (void *arg)
-+{
-+ int i = 0, ret;
-+ while (!do_exit)
-+ {
-+ /* Arbitrarily choose if we are the writer or reader. Choose a
-+ high enough ratio of readers to writers to make it likely
-+ that readers block (and eventually are susceptable to
-+ stalling).
-+
-+ If we are a writer, take the write lock, and then unlock.
-+ If we are a reader, try the lock, then lock, then unlock. */
-+ if ((i % 8) != 0)
-+ {
-+ if ((ret = pthread_rwlock_trywrlock (&onelock)) != 0)
-+ {
-+ if (ret == EBUSY)
-+ xpthread_rwlock_wrlock (&onelock);
-+ else
-+ exit (EXIT_FAILURE);
-+ }
-+ }
-+ else
-+ xpthread_rwlock_rdlock (&onelock);
-+ /* Thread does some work and then unlocks. */
-+ xpthread_rwlock_unlock (&onelock);
-+ i++;
-+ }
-+ return NULL;
-+}
-+
-+int
-+do_test (void)
-+{
-+ int i;
-+ pthread_t tids[NTHREADS];
-+ xpthread_rwlock_init (&onelock, NULL);
-+ for (i = 0; i < NTHREADS; i++)
-+ tids[i] = xpthread_create (NULL, run_loop, NULL);
-+ /* Run for some amount of time. The pthread_rwlock_tryrwlock stall
-+ is very easy to trigger and happens in seconds under the test
-+ conditions. */
-+ sleep (10);
-+ /* Then exit. */
-+ printf ("INFO: Exiting...\n");
-+ do_exit = 1;
-+ /* If any readers stalled then we will timeout waiting for them. */
-+ for (i = 0; i < NTHREADS; i++)
-+ xpthread_join (tids[i]);
-+ printf ("INFO: Done.\n");
-+ xpthread_rwlock_destroy (&onelock);
-+ printf ("PASS: No pthread_rwlock_tryrwlock stalls detected.\n");
-+ return 0;
-+}
-+
-+#include <support/test-driver.c>
-diff --git a/posix/bits/types.h b/posix/bits/types.h
-index 27e065c3be..0de6c59bb4 100644
---- a/posix/bits/types.h
-+++ b/posix/bits/types.h
-@@ -87,7 +87,7 @@ __extension__ typedef unsigned long long int __uintmax_t;
- 32 -- "natural" 32-bit type (always int)
- 64 -- "natural" 64-bit type (long or long long)
- LONG32 -- 32-bit type, traditionally long
-- QUAD -- 64-bit type, always long long
-+ QUAD -- 64-bit type, traditionally long long
- WORD -- natural type of __WORDSIZE bits (int or long)
- LONGWORD -- type of __WORDSIZE bits, traditionally long
-
-@@ -113,14 +113,14 @@ __extension__ typedef unsigned long long int __uintmax_t;
- #define __SLONGWORD_TYPE long int
- #define __ULONGWORD_TYPE unsigned long int
- #if __WORDSIZE == 32
--# define __SQUAD_TYPE __quad_t
--# define __UQUAD_TYPE __u_quad_t
-+# define __SQUAD_TYPE __int64_t
-+# define __UQUAD_TYPE __uint64_t
- # define __SWORD_TYPE int
- # define __UWORD_TYPE unsigned int
- # define __SLONG32_TYPE long int
- # define __ULONG32_TYPE unsigned long int
--# define __S64_TYPE __quad_t
--# define __U64_TYPE __u_quad_t
-+# define __S64_TYPE __int64_t
-+# define __U64_TYPE __uint64_t
- /* We want __extension__ before typedef's that use nonstandard base types
- such as `long long' in C89 mode. */
- # define __STD_TYPE __extension__ typedef
-diff --git a/posix/regexec.c b/posix/regexec.c
-index 91d5a797b8..084b1222d9 100644
---- a/posix/regexec.c
-+++ b/posix/regexec.c
-@@ -1293,8 +1293,10 @@ proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs,
- else if (naccepted)
- {
- char *buf = (char *) re_string_get_buffer (&mctx->input);
-- if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx,
-- naccepted) != 0)
-+ if (mctx->input.valid_len - *pidx < naccepted
-+ || (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx,
-+ naccepted)
-+ != 0))
- return -1;
- }
- }
-diff --git a/posix/sys/types.h b/posix/sys/types.h
-index 27129c5c23..0e37b1ce6a 100644
---- a/posix/sys/types.h
-+++ b/posix/sys/types.h
-@@ -154,37 +154,20 @@ typedef unsigned int uint;
-
- #include <bits/stdint-intn.h>
-
--#if !__GNUC_PREREQ (2, 7)
--
- /* These were defined by ISO C without the first `_'. */
--typedef unsigned char u_int8_t;
--typedef unsigned short int u_int16_t;
--typedef unsigned int u_int32_t;
--# if __WORDSIZE == 64
--typedef unsigned long int u_int64_t;
--# else
--__extension__ typedef unsigned long long int u_int64_t;
--# endif
--
--typedef int register_t;
--
--#else
--
--/* For GCC 2.7 and later, we can use specific type-size attributes. */
--# define __u_intN_t(N, MODE) \
-- typedef unsigned int u_int##N##_t __attribute__ ((__mode__ (MODE)))
--
--__u_intN_t (8, __QI__);
--__u_intN_t (16, __HI__);
--__u_intN_t (32, __SI__);
--__u_intN_t (64, __DI__);
-+typedef __uint8_t u_int8_t;
-+typedef __uint16_t u_int16_t;
-+typedef __uint32_t u_int32_t;
-+typedef __uint64_t u_int64_t;
-
-+#if __GNUC_PREREQ (2, 7)
- typedef int register_t __attribute__ ((__mode__ (__word__)));
--
-+#else
-+typedef int register_t;
-+#endif
-
- /* Some code from BIND tests this macro to see if the types above are
- defined. */
--#endif
- #define __BIT_TYPES_DEFINED__ 1
-
-
-diff --git a/scripts/check-installed-headers.sh b/scripts/check-installed-headers.sh
-index 8e7beffd82..63bc8d4fa6 100644
---- a/scripts/check-installed-headers.sh
-+++ b/scripts/check-installed-headers.sh
-@@ -16,11 +16,9 @@
- # License along with the GNU C Library; if not, see
- # <http://www.gnu.org/licenses/>.
-
--# Check installed headers for cleanliness. For each header, confirm
--# that it's possible to compile a file that includes that header and
--# does nothing else, in several different compilation modes. Also,
--# scan the header for a set of obsolete typedefs that should no longer
--# appear.
-+# For each installed header, confirm that it's possible to compile a
-+# file that includes that header and does nothing else, in several
-+# different compilation modes.
-
- # These compilation switches assume GCC or compatible, which is probably
- # fine since we also assume that when _building_ glibc.
-@@ -31,13 +29,6 @@ cxx_modes="-std=c++98 -std=gnu++98 -std=c++11 -std=gnu++11"
- # These are probably the most commonly used three.
- lib_modes="-D_DEFAULT_SOURCE=1 -D_GNU_SOURCE=1 -D_XOPEN_SOURCE=700"
-
--# sys/types.h+bits/types.h have to define the obsolete types.
--# rpc(svc)/* have the obsolete types too deeply embedded in their API
--# to remove.
--skip_obsolete_type_check='*/sys/types.h|*/bits/types.h|*/rpc/*|*/rpcsvc/*'
--obsolete_type_re=\
--'\<((__)?(quad_t|u(short|int|long|_(char|short|int([0-9]+_t)?|long|quad_t))))\>'
--
- if [ $# -lt 3 ]; then
- echo "usage: $0 c|c++ \"compile command\" header header header..." >&2
- exit 2
-@@ -46,14 +37,10 @@ case "$1" in
- (c)
- lang_modes="$c_modes"
- cih_test_c=$(mktemp ${TMPDIR-/tmp}/cih_test_XXXXXX.c)
-- already="$skip_obsolete_type_check"
- ;;
- (c++)
- lang_modes="$cxx_modes"
- cih_test_c=$(mktemp ${TMPDIR-/tmp}/cih_test_XXXXXX.cc)
-- # The obsolete-type check can be skipped for C++; it is
-- # sufficient to do it for C.
-- already="*"
- ;;
- (*)
- echo "usage: $0 c|c++ \"compile command\" header header header..." >&2
-@@ -151,22 +138,8 @@ $expanded_lib_mode
- int avoid_empty_translation_unit;
- EOF
- if $cc_cmd -fsyntax-only $lang_mode "$cih_test_c" 2>&1
-- then
-- includes=$($cc_cmd -fsyntax-only -H $lang_mode \
-- "$cih_test_c" 2>&1 | sed -ne 's/^[.][.]* //p')
-- for h in $includes; do
-- # Don't repeat work.
-- eval 'case "$h" in ('"$already"') continue;; esac'
--
-- if grep -qE "$obsolete_type_re" "$h"; then
-- echo "*** Obsolete types detected:"
-- grep -HE "$obsolete_type_re" "$h"
-- failed=1
-- fi
-- already="$already|$h"
-- done
-- else
-- failed=1
-+ then :
-+ else failed=1
- fi
- done
- done
-diff --git a/scripts/check-obsolete-constructs.py b/scripts/check-obsolete-constructs.py
-new file mode 100755
-index 0000000000..ce5c72251f
---- /dev/null
-+++ b/scripts/check-obsolete-constructs.py
-@@ -0,0 +1,466 @@
-+#! /usr/bin/python3
-+# Copyright (C) 2019 Free Software Foundation, Inc.
-+# This file is part of the GNU C Library.
-+#
-+# The GNU C Library is free software; you can redistribute it and/or
-+# modify it under the terms of the GNU Lesser General Public
-+# License as published by the Free Software Foundation; either
-+# version 2.1 of the License, or (at your option) any later version.
-+#
-+# The GNU C Library is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+# Lesser General Public License for more details.
-+#
-+# You should have received a copy of the GNU Lesser General Public
-+# License along with the GNU C Library; if not, see
-+# <http://www.gnu.org/licenses/>.
-+
-+"""Verifies that installed headers do not use any obsolete constructs:
-+ * legacy BSD typedefs superseded by <stdint.h>:
-+ ushort uint ulong u_char u_short u_int u_long u_intNN_t quad_t u_quad_t
-+ (sys/types.h is allowed to _define_ these types, but not to use them
-+ to define anything else).
-+"""
-+
-+import argparse
-+import collections
-+import re
-+import sys
-+
-+# Simplified lexical analyzer for C preprocessing tokens.
-+# Does not implement trigraphs.
-+# Does not implement backslash-newline in the middle of any lexical
-+# item other than a string literal.
-+# Does not implement universal-character-names in identifiers.
-+# Treats prefixed strings (e.g. L"...") as two tokens (L and "...")
-+# Accepts non-ASCII characters only within comments and strings.
-+
-+# Caution: The order of the outermost alternation matters.
-+# STRING must be before BAD_STRING, CHARCONST before BAD_CHARCONST,
-+# BLOCK_COMMENT before BAD_BLOCK_COM before PUNCTUATOR, and OTHER must
-+# be last.
-+# Caution: There should be no capturing groups other than the named
-+# captures in the outermost alternation.
-+
-+# For reference, these are all of the C punctuators as of C11:
-+# [ ] ( ) { } , ; ? ~
-+# ! != * *= / /= ^ ^= = ==
-+# # ##
-+# % %= %> %: %:%:
-+# & &= &&
-+# | |= ||
-+# + += ++
-+# - -= -- ->
-+# . ...
-+# : :>
-+# < <% <: << <<= <=
-+# > >= >> >>=
-+
-+# The BAD_* tokens are not part of the official definition of pp-tokens;
-+# they match unclosed strings, character constants, and block comments,
-+# so that the regex engine doesn't have to backtrack all the way to the
-+# beginning of a broken construct and then emit dozens of junk tokens.
-+
-+PP_TOKEN_RE_ = re.compile(r"""
-+ (?P<STRING> \"(?:[^\"\\\r\n]|\\(?:[\r\n -~]|\r\n))*\")
-+ |(?P<BAD_STRING> \"(?:[^\"\\\r\n]|\\[ -~])*)
-+ |(?P<CHARCONST> \'(?:[^\'\\\r\n]|\\(?:[\r\n -~]|\r\n))*\')
-+ |(?P<BAD_CHARCONST> \'(?:[^\'\\\r\n]|\\[ -~])*)
-+ |(?P<BLOCK_COMMENT> /\*(?:\*(?!/)|[^*])*\*/)
-+ |(?P<BAD_BLOCK_COM> /\*(?:\*(?!/)|[^*])*\*?)
-+ |(?P<LINE_COMMENT> //[^\r\n]*)
-+ |(?P<IDENT> [_a-zA-Z][_a-zA-Z0-9]*)
-+ |(?P<PP_NUMBER> \.?[0-9](?:[0-9a-df-oq-zA-DF-OQ-Z_.]|[eEpP][+-]?)*)
-+ |(?P<PUNCTUATOR>
-+ [,;?~(){}\[\]]
-+ | [!*/^=]=?
-+ | \#\#?
-+ | %(?:[=>]|:(?:%:)?)?
-+ | &[=&]?
-+ |\|[=|]?
-+ |\+[=+]?
-+ | -[=->]?
-+ |\.(?:\.\.)?
-+ | :>?
-+ | <(?:[%:]|<(?:=|<=?)?)?
-+ | >(?:=|>=?)?)
-+ |(?P<ESCNL> \\(?:\r|\n|\r\n))
-+ |(?P<WHITESPACE> [ \t\n\r\v\f]+)
-+ |(?P<OTHER> .)
-+""", re.DOTALL | re.VERBOSE)
-+
-+HEADER_NAME_RE_ = re.compile(r"""
-+ < [^>\r\n]+ >
-+ | " [^"\r\n]+ "
-+""", re.DOTALL | re.VERBOSE)
-+
-+ENDLINE_RE_ = re.compile(r"""\r|\n|\r\n""")
-+
-+# based on the sample code in the Python re documentation
-+Token_ = collections.namedtuple("Token", (
-+ "kind", "text", "line", "column", "context"))
-+Token_.__doc__ = """
-+ One C preprocessing token, comment, or chunk of whitespace.
-+ 'kind' identifies the token type, which will be one of:
-+ STRING, CHARCONST, BLOCK_COMMENT, LINE_COMMENT, IDENT,
-+ PP_NUMBER, PUNCTUATOR, ESCNL, WHITESPACE, HEADER_NAME,
-+ or OTHER. The BAD_* alternatives in PP_TOKEN_RE_ are
-+ handled within tokenize_c, below.
-+
-+ 'text' is the sequence of source characters making up the token;
-+ no decoding whatsoever is performed.
-+
-+ 'line' and 'column' give the position of the first character of the
-+ token within the source file. They are both 1-based.
-+
-+ 'context' indicates whether or not this token occurred within a
-+ preprocessing directive; it will be None for running text,
-+ '<null>' for the leading '#' of a directive line (because '#'
-+ all by itself on a line is a "null directive"), or the name of
-+ the directive for tokens within a directive line, starting with
-+ the IDENT for the name itself.
-+"""
-+
-+def tokenize_c(file_contents, reporter):
-+ """Yield a series of Token objects, one for each preprocessing
-+ token, comment, or chunk of whitespace within FILE_CONTENTS.
-+ The REPORTER object is expected to have one method,
-+ reporter.error(token, message), which will be called to
-+ indicate a lexical error at the position of TOKEN.
-+ If MESSAGE contains the four-character sequence '{!r}', that
-+ is expected to be replaced by repr(token.text).
-+ """
-+
-+ Token = Token_
-+ PP_TOKEN_RE = PP_TOKEN_RE_
-+ ENDLINE_RE = ENDLINE_RE_
-+ HEADER_NAME_RE = HEADER_NAME_RE_
-+
-+ line_num = 1
-+ line_start = 0
-+ pos = 0
-+ limit = len(file_contents)
-+ directive = None
-+ at_bol = True
-+ while pos < limit:
-+ if directive == "include":
-+ mo = HEADER_NAME_RE.match(file_contents, pos)
-+ if mo:
-+ kind = "HEADER_NAME"
-+ directive = "after_include"
-+ else:
-+ mo = PP_TOKEN_RE.match(file_contents, pos)
-+ kind = mo.lastgroup
-+ if kind != "WHITESPACE":
-+ directive = "after_include"
-+ else:
-+ mo = PP_TOKEN_RE.match(file_contents, pos)
-+ kind = mo.lastgroup
-+
-+ text = mo.group()
-+ line = line_num
-+ column = mo.start() - line_start
-+ adj_line_start = 0
-+ # only these kinds can contain a newline
-+ if kind in ("WHITESPACE", "BLOCK_COMMENT", "LINE_COMMENT",
-+ "STRING", "CHARCONST", "BAD_BLOCK_COM", "ESCNL"):
-+ for tmo in ENDLINE_RE.finditer(text):
-+ line_num += 1
-+ adj_line_start = tmo.end()
-+ if adj_line_start:
-+ line_start = mo.start() + adj_line_start
-+
-+ # Track whether or not we are scanning a preprocessing directive.
-+ if kind == "LINE_COMMENT" or (kind == "WHITESPACE" and adj_line_start):
-+ at_bol = True
-+ directive = None
-+ else:
-+ if kind == "PUNCTUATOR" and text == "#" and at_bol:
-+ directive = "<null>"
-+ elif kind == "IDENT" and directive == "<null>":
-+ directive = text
-+ at_bol = False
-+
-+ # Report ill-formed tokens and rewrite them as their well-formed
-+ # equivalents, so downstream processing doesn't have to know about them.
-+ # (Rewriting instead of discarding provides better error recovery.)
-+ if kind == "BAD_BLOCK_COM":
-+ reporter.error(Token("BAD_BLOCK_COM", "", line, column+1, ""),
-+ "unclosed block comment")
-+ text += "*/"
-+ kind = "BLOCK_COMMENT"
-+ elif kind == "BAD_STRING":
-+ reporter.error(Token("BAD_STRING", "", line, column+1, ""),
-+ "unclosed string")
-+ text += "\""
-+ kind = "STRING"
-+ elif kind == "BAD_CHARCONST":
-+ reporter.error(Token("BAD_CHARCONST", "", line, column+1, ""),
-+ "unclosed char constant")
-+ text += "'"
-+ kind = "CHARCONST"
-+
-+ tok = Token(kind, text, line, column+1,
-+ "include" if directive == "after_include" else directive)
-+ # Do not complain about OTHER tokens inside macro definitions.
-+ # $ and @ appear in macros defined by headers intended to be
-+ # included from assembly language, e.g. sysdeps/mips/sys/asm.h.
-+ if kind == "OTHER" and directive != "define":
-+ self.error(tok, "stray {!r} in program")
-+
-+ yield tok
-+ pos = mo.end()
-+
-+#
-+# Base and generic classes for individual checks.
-+#
-+
-+class ConstructChecker:
-+ """Scan a stream of C preprocessing tokens and possibly report
-+ problems with them. The REPORTER object passed to __init__ has
-+ one method, reporter.error(token, message), which should be
-+ called to indicate a problem detected at the position of TOKEN.
-+ If MESSAGE contains the four-character sequence '{!r}' then that
-+ will be replaced with a textual representation of TOKEN.
-+ """
-+ def __init__(self, reporter):
-+ self.reporter = reporter
-+
-+ def examine(self, tok):
-+ """Called once for each token in a header file.
-+ Call self.reporter.error if a problem is detected.
-+ """
-+ raise NotImplementedError
-+
-+ def eof(self):
-+ """Called once at the end of the stream. Subclasses need only
-+ override this if it might have something to do."""
-+ pass
-+
-+class NoCheck(ConstructChecker):
-+ """Generic checker class which doesn't do anything. Substitute this
-+ class for a real checker when a particular check should be skipped
-+ for some file."""
-+
-+ def examine(self, tok):
-+ pass
-+
-+#
-+# Check for obsolete type names.
-+#
-+
-+# The obsolete type names we're looking for:
-+OBSOLETE_TYPE_RE_ = re.compile(r"""\A
-+ (__)?
-+ ( quad_t
-+ | u(?: short | int | long
-+ | _(?: char | short | int(?:[0-9]+_t)? | long | quad_t )))
-+\Z""", re.VERBOSE)
-+
-+class ObsoleteNotAllowed(ConstructChecker):
-+ """Don't allow any use of the obsolete typedefs."""
-+ def examine(self, tok):
-+ if OBSOLETE_TYPE_RE_.match(tok.text):
-+ self.reporter.error(tok, "use of {!r}")
-+
-+class ObsoletePrivateDefinitionsAllowed(ConstructChecker):
-+ """Allow definitions of the private versions of the
-+ obsolete typedefs; that is, 'typedef [anything] __obsolete;'
-+ """
-+ def __init__(self, reporter):
-+ super().__init__(reporter)
-+ self.in_typedef = False
-+ self.prev_token = None
-+
-+ def examine(self, tok):
-+ # bits/types.h hides 'typedef' in a macro sometimes.
-+ if (tok.kind == "IDENT"
-+ and tok.text in ("typedef", "__STD_TYPE")
-+ and tok.context is None):
-+ self.in_typedef = True
-+ elif tok.kind == "PUNCTUATOR" and tok.text == ";" and self.in_typedef:
-+ self.in_typedef = False
-+ if self.prev_token.kind == "IDENT":
-+ m = OBSOLETE_TYPE_RE_.match(self.prev_token.text)
-+ if m and m.group(1) != "__":
-+ self.reporter.error(self.prev_token, "use of {!r}")
-+ self.prev_token = None
-+ else:
-+ self._check_prev()
-+
-+ self.prev_token = tok
-+
-+ def eof(self):
-+ self._check_prev()
-+
-+ def _check_prev(self):
-+ if (self.prev_token is not None
-+ and self.prev_token.kind == "IDENT"
-+ and OBSOLETE_TYPE_RE_.match(self.prev_token.text)):
-+ self.reporter.error(self.prev_token, "use of {!r}")
-+
-+class ObsoletePublicDefinitionsAllowed(ConstructChecker):
-+ """Allow definitions of the public versions of the obsolete
-+ typedefs. Only specific forms of definition are allowed:
-+
-+ typedef __obsolete obsolete; // identifiers must agree
-+ typedef __uintN_t u_intN_t; // N must agree
-+ typedef unsigned long int ulong;
-+ typedef unsigned short int ushort;
-+ typedef unsigned int uint;
-+ """
-+ def __init__(self, reporter):
-+ super().__init__(reporter)
-+ self.typedef_tokens = []
-+
-+ def examine(self, tok):
-+ if tok.kind in ("WHITESPACE", "BLOCK_COMMENT",
-+ "LINE_COMMENT", "NL", "ESCNL"):
-+ pass
-+
-+ elif (tok.kind == "IDENT" and tok.text == "typedef"
-+ and tok.context is None):
-+ if self.typedef_tokens:
-+ self.reporter.error(tok, "typedef inside typedef")
-+ self._reset()
-+ self.typedef_tokens.append(tok)
-+
-+ elif tok.kind == "PUNCTUATOR" and tok.text == ";":
-+ self._finish()
-+
-+ elif self.typedef_tokens:
-+ self.typedef_tokens.append(tok)
-+
-+ def eof(self):
-+ self._reset()
-+
-+ def _reset(self):
-+ while self.typedef_tokens:
-+ tok = self.typedef_tokens.pop(0)
-+ if tok.kind == "IDENT" and OBSOLETE_TYPE_RE_.match(tok.text):
-+ self.reporter.error(tok, "use of {!r}")
-+
-+ def _finish(self):
-+ if not self.typedef_tokens: return
-+ if self.typedef_tokens[-1].kind == "IDENT":
-+ m = OBSOLETE_TYPE_RE_.match(self.typedef_tokens[-1].text)
-+ if m:
-+ if self._permissible_public_definition(m):
-+ self.typedef_tokens.clear()
-+ self._reset()
-+
-+ def _permissible_public_definition(self, m):
-+ if m.group(1) == "__": return False
-+ name = m.group(2)
-+ toks = self.typedef_tokens
-+ ntok = len(toks)
-+ if ntok == 3 and toks[1].kind == "IDENT":
-+ defn = toks[1].text
-+ n = OBSOLETE_TYPE_RE_.match(defn)
-+ if n and n.group(1) == "__" and n.group(2) == name:
-+ return True
-+
-+ if (name[:5] == "u_int" and name[-2:] == "_t"
-+ and defn[:6] == "__uint" and defn[-2:] == "_t"
-+ and name[5:-2] == defn[6:-2]):
-+ return True
-+
-+ return False
-+
-+ if (name == "ulong" and ntok == 5
-+ and toks[1].kind == "IDENT" and toks[1].text == "unsigned"
-+ and toks[2].kind == "IDENT" and toks[2].text == "long"
-+ and toks[3].kind == "IDENT" and toks[3].text == "int"):
-+ return True
-+
-+ if (name == "ushort" and ntok == 5
-+ and toks[1].kind == "IDENT" and toks[1].text == "unsigned"
-+ and toks[2].kind == "IDENT" and toks[2].text == "short"
-+ and toks[3].kind == "IDENT" and toks[3].text == "int"):
-+ return True
-+
-+ if (name == "uint" and ntok == 4
-+ and toks[1].kind == "IDENT" and toks[1].text == "unsigned"
-+ and toks[2].kind == "IDENT" and toks[2].text == "int"):
-+ return True
-+
-+ return False
-+
-+def ObsoleteTypedefChecker(reporter, fname):
-+ """Factory: produce an instance of the appropriate
-+ obsolete-typedef checker for FNAME."""
-+
-+ # The obsolete rpc/ and rpcsvc/ headers are allowed to use the
-+ # obsolete types, because it would be more trouble than it's
-+ # worth to remove them from headers that we intend to stop
-+ # installing eventually anyway.
-+ if (fname.startswith("rpc/")
-+ or fname.startswith("rpcsvc/")
-+ or "/rpc/" in fname
-+ or "/rpcsvc/" in fname):
-+ return NoCheck(reporter)
-+
-+ # bits/types.h is allowed to define the __-versions of the
-+ # obsolete types.
-+ if (fname == "bits/types.h"
-+ or fname.endswith("/bits/types.h")):
-+ return ObsoletePrivateDefinitionsAllowed(reporter)
-+
-+ # sys/types.h is allowed to use the __-versions of the
-+ # obsolete types, but only to define the unprefixed versions.
-+ if (fname == "sys/types.h"
-+ or fname.endswith("/sys/types.h")):
-+ return ObsoletePublicDefinitionsAllowed(reporter)
-+
-+ return ObsoleteNotAllowed(reporter)
-+
-+#
-+# Master control
-+#
-+
-+class HeaderChecker:
-+ """Perform all of the checks on each header. This is also the
-+ "reporter" object expected by tokenize_c and ConstructChecker.
-+ """
-+ def __init__(self):
-+ self.fname = None
-+ self.status = 0
-+
-+ def error(self, tok, message):
-+ self.status = 1
-+ if '{!r}' in message:
-+ message = message.format(tok.text)
-+ sys.stderr.write("{}:{}:{}: error: {}\n".format(
-+ self.fname, tok.line, tok.column, message))
-+
-+ def check(self, fname):
-+ self.fname = fname
-+ try:
-+ with open(fname, "rt") as fp:
-+ contents = fp.read()
-+ except OSError as e:
-+ sys.stderr.write("{}: {}\n".format(fname, e.strerror))
-+ self.status = 1
-+ return
-+
-+ typedef_checker = ObsoleteTypedefChecker(self, self.fname)
-+
-+ for tok in tokenize_c(contents, self):
-+ typedef_checker.examine(tok)
-+
-+def main():
-+ ap = argparse.ArgumentParser(description=__doc__)
-+ ap.add_argument("headers", metavar="header", nargs="+",
-+ help="one or more headers to scan for obsolete constructs")
-+ args = ap.parse_args()
-+
-+ checker = HeaderChecker()
-+ for fname in args.headers:
-+ # Headers whose installed name begins with "finclude/" contain
-+ # Fortran, not C, and this program should completely ignore them.
-+ if not (fname.startswith("finclude/") or "/finclude/" in fname):
-+ checker.check(fname)
-+ sys.exit(checker.status)
-+
-+main()
-diff --git a/support/Makefile b/support/Makefile
-index 432cf2fe6c..8d61de6c57 100644
---- a/support/Makefile
-+++ b/support/Makefile
-@@ -63,6 +63,7 @@ libsupport-routines = \
- support_record_failure \
- support_run_diff \
- support_shared_allocate \
-+ support_subprocess \
- support_test_compare_blob \
- support_test_compare_failure \
- support_test_compare_string \
-@@ -129,6 +130,7 @@ libsupport-routines = \
- xpthread_mutexattr_settype \
- xpthread_once \
- xpthread_rwlock_init \
-+ xpthread_rwlock_destroy \
- xpthread_rwlock_rdlock \
- xpthread_rwlock_unlock \
- xpthread_rwlock_wrlock \
-@@ -147,6 +149,9 @@ libsupport-routines = \
- xsignal \
- xsigstack \
- xsocket \
-+ xposix_spawn \
-+ xposix_spawn_file_actions_addclose \
-+ xposix_spawn_file_actions_adddup2 \
- xstrdup \
- xstrndup \
- xsymlink \
-@@ -222,4 +227,6 @@ endif
-
- $(objpfx)tst-support_format_dns_packet: $(common-objpfx)resolv/libresolv.so
-
-+tst-support_capture_subprocess-ARGS = -- $(host-test-program-cmd)
-+
- include ../Rules
-diff --git a/support/capture_subprocess.h b/support/capture_subprocess.h
-index 2dce42e3a3..2832cfc635 100644
---- a/support/capture_subprocess.h
-+++ b/support/capture_subprocess.h
-@@ -35,6 +35,12 @@ struct support_capture_subprocess
- struct support_capture_subprocess support_capture_subprocess
- (void (*callback) (void *), void *closure);
-
-+/* Issue FILE with ARGV arguments by using posix_spawn and capture standard
-+ output, standard error, and the exit status. The out.buffer and err.buffer
-+ are handle as support_capture_subprocess. */
-+struct support_capture_subprocess support_capture_subprogram
-+ (const char *file, char *const argv[]);
-+
- /* Deallocate the subprocess data captured by
- support_capture_subprocess. */
- void support_capture_subprocess_free (struct support_capture_subprocess *);
-diff --git a/support/subprocess.h b/support/subprocess.h
-new file mode 100644
-index 0000000000..c031878d94
---- /dev/null
-+++ b/support/subprocess.h
-@@ -0,0 +1,49 @@
-+/* Create a subprocess.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+#ifndef SUPPORT_SUBPROCESS_H
-+#define SUPPORT_SUBPROCESS_H
-+
-+#include <sys/types.h>
-+
-+struct support_subprocess
-+{
-+ int stdout_pipe[2];
-+ int stderr_pipe[2];
-+ pid_t pid;
-+};
-+
-+/* Invoke CALLBACK (CLOSURE) in a subprocess created with fork and return
-+ its PID, a pipe redirected to STDOUT, and a pipe redirected to STDERR. */
-+struct support_subprocess support_subprocess
-+ (void (*callback) (void *), void *closure);
-+
-+/* Issue FILE with ARGV arguments by using posix_spawn and return is PID, a
-+ pipe redirected to STDOUT, and a pipe redirected to STDERR. */
-+struct support_subprocess support_subprogram
-+ (const char *file, char *const argv[]);
-+
-+/* Wait for the subprocess indicated by PROC::PID. Return the status
-+ indicate by waitpid call. */
-+int support_process_wait (struct support_subprocess *proc);
-+
-+/* Terminate the subprocess indicated by PROC::PID, first with a SIGTERM and
-+ then with a SIGKILL. Return the status as for waitpid call. */
-+int support_process_terminate (struct support_subprocess *proc);
-+
-+#endif
-diff --git a/support/support_capture_subprocess.c b/support/support_capture_subprocess.c
-index 167514faf1..948ce5a0c6 100644
---- a/support/support_capture_subprocess.c
-+++ b/support/support_capture_subprocess.c
-@@ -16,6 +16,7 @@
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-+#include <support/subprocess.h>
- #include <support/capture_subprocess.h>
-
- #include <errno.h>
-@@ -23,6 +24,7 @@
- #include <support/check.h>
- #include <support/xunistd.h>
- #include <support/xsocket.h>
-+#include <support/xspawn.h>
-
- static void
- transfer (const char *what, struct pollfd *pfd, struct xmemstream *stream)
-@@ -50,59 +52,53 @@ transfer (const char *what, struct pollfd *pfd, struct xmemstream *stream)
- }
- }
-
--struct support_capture_subprocess
--support_capture_subprocess (void (*callback) (void *), void *closure)
-+static void
-+support_capture_poll (struct support_capture_subprocess *result,
-+ struct support_subprocess *proc)
- {
-- struct support_capture_subprocess result;
-- xopen_memstream (&result.out);
-- xopen_memstream (&result.err);
--
-- int stdout_pipe[2];
-- xpipe (stdout_pipe);
-- TEST_VERIFY (stdout_pipe[0] > STDERR_FILENO);
-- TEST_VERIFY (stdout_pipe[1] > STDERR_FILENO);
-- int stderr_pipe[2];
-- xpipe (stderr_pipe);
-- TEST_VERIFY (stderr_pipe[0] > STDERR_FILENO);
-- TEST_VERIFY (stderr_pipe[1] > STDERR_FILENO);
--
-- TEST_VERIFY (fflush (stdout) == 0);
-- TEST_VERIFY (fflush (stderr) == 0);
--
-- pid_t pid = xfork ();
-- if (pid == 0)
-- {
-- xclose (stdout_pipe[0]);
-- xclose (stderr_pipe[0]);
-- xdup2 (stdout_pipe[1], STDOUT_FILENO);
-- xdup2 (stderr_pipe[1], STDERR_FILENO);
-- xclose (stdout_pipe[1]);
-- xclose (stderr_pipe[1]);
-- callback (closure);
-- _exit (0);
-- }
-- xclose (stdout_pipe[1]);
-- xclose (stderr_pipe[1]);
--
- struct pollfd fds[2] =
- {
-- { .fd = stdout_pipe[0], .events = POLLIN },
-- { .fd = stderr_pipe[0], .events = POLLIN },
-+ { .fd = proc->stdout_pipe[0], .events = POLLIN },
-+ { .fd = proc->stderr_pipe[0], .events = POLLIN },
- };
-
- do
- {
- xpoll (fds, 2, -1);
-- transfer ("stdout", &fds[0], &result.out);
-- transfer ("stderr", &fds[1], &result.err);
-+ transfer ("stdout", &fds[0], &result->out);
-+ transfer ("stderr", &fds[1], &result->err);
- }
- while (fds[0].events != 0 || fds[1].events != 0);
-- xclose (stdout_pipe[0]);
-- xclose (stderr_pipe[0]);
-
-- xfclose_memstream (&result.out);
-- xfclose_memstream (&result.err);
-- xwaitpid (pid, &result.status, 0);
-+ xfclose_memstream (&result->out);
-+ xfclose_memstream (&result->err);
-+
-+ result->status = support_process_wait (proc);
-+}
-+
-+struct support_capture_subprocess
-+support_capture_subprocess (void (*callback) (void *), void *closure)
-+{
-+ struct support_capture_subprocess result;
-+ xopen_memstream (&result.out);
-+ xopen_memstream (&result.err);
-+
-+ struct support_subprocess proc = support_subprocess (callback, closure);
-+
-+ support_capture_poll (&result, &proc);
-+ return result;
-+}
-+
-+struct support_capture_subprocess
-+support_capture_subprogram (const char *file, char *const argv[])
-+{
-+ struct support_capture_subprocess result;
-+ xopen_memstream (&result.out);
-+ xopen_memstream (&result.err);
-+
-+ struct support_subprocess proc = support_subprogram (file, argv);
-+
-+ support_capture_poll (&result, &proc);
- return result;
- }
-
-diff --git a/support/support_subprocess.c b/support/support_subprocess.c
-new file mode 100644
-index 0000000000..0c8cc6af30
---- /dev/null
-+++ b/support/support_subprocess.c
-@@ -0,0 +1,152 @@
-+/* Create subprocess.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+#include <stdio.h>
-+#include <signal.h>
-+#include <time.h>
-+#include <sys/wait.h>
-+#include <stdbool.h>
-+#include <support/xspawn.h>
-+#include <support/check.h>
-+#include <support/xunistd.h>
-+#include <support/subprocess.h>
-+
-+static struct support_subprocess
-+support_suprocess_init (void)
-+{
-+ struct support_subprocess result;
-+
-+ xpipe (result.stdout_pipe);
-+ TEST_VERIFY (result.stdout_pipe[0] > STDERR_FILENO);
-+ TEST_VERIFY (result.stdout_pipe[1] > STDERR_FILENO);
-+
-+ xpipe (result.stderr_pipe);
-+ TEST_VERIFY (result.stderr_pipe[0] > STDERR_FILENO);
-+ TEST_VERIFY (result.stderr_pipe[1] > STDERR_FILENO);
-+
-+ TEST_VERIFY (fflush (stdout) == 0);
-+ TEST_VERIFY (fflush (stderr) == 0);
-+
-+ return result;
-+}
-+
-+struct support_subprocess
-+support_subprocess (void (*callback) (void *), void *closure)
-+{
-+ struct support_subprocess result = support_suprocess_init ();
-+
-+ result.pid = xfork ();
-+ if (result.pid == 0)
-+ {
-+ xclose (result.stdout_pipe[0]);
-+ xclose (result.stderr_pipe[0]);
-+ xdup2 (result.stdout_pipe[1], STDOUT_FILENO);
-+ xdup2 (result.stderr_pipe[1], STDERR_FILENO);
-+ xclose (result.stdout_pipe[1]);
-+ xclose (result.stderr_pipe[1]);
-+ callback (closure);
-+ _exit (0);
-+ }
-+ xclose (result.stdout_pipe[1]);
-+ xclose (result.stderr_pipe[1]);
-+
-+ return result;
-+}
-+
-+struct support_subprocess
-+support_subprogram (const char *file, char *const argv[])
-+{
-+ struct support_subprocess result = support_suprocess_init ();
-+
-+ posix_spawn_file_actions_t fa;
-+ /* posix_spawn_file_actions_init does not fail. */
-+ posix_spawn_file_actions_init (&fa);
-+
-+ xposix_spawn_file_actions_addclose (&fa, result.stdout_pipe[0]);
-+ xposix_spawn_file_actions_addclose (&fa, result.stderr_pipe[0]);
-+ xposix_spawn_file_actions_adddup2 (&fa, result.stdout_pipe[1], STDOUT_FILENO);
-+ xposix_spawn_file_actions_adddup2 (&fa, result.stderr_pipe[1], STDERR_FILENO);
-+ xposix_spawn_file_actions_addclose (&fa, result.stdout_pipe[1]);
-+ xposix_spawn_file_actions_addclose (&fa, result.stderr_pipe[1]);
-+
-+ result.pid = xposix_spawn (file, &fa, NULL, argv, NULL);
-+
-+ xclose (result.stdout_pipe[1]);
-+ xclose (result.stderr_pipe[1]);
-+
-+ return result;
-+}
-+
-+int
-+support_process_wait (struct support_subprocess *proc)
-+{
-+ xclose (proc->stdout_pipe[0]);
-+ xclose (proc->stderr_pipe[0]);
-+
-+ int status;
-+ xwaitpid (proc->pid, &status, 0);
-+ return status;
-+}
-+
-+
-+static bool
-+support_process_kill (int pid, int signo, int *status)
-+{
-+ /* Kill the whole process group. */
-+ kill (-pid, signo);
-+ /* In case setpgid failed in the child, kill it individually too. */
-+ kill (pid, signo);
-+
-+ /* Wait for it to terminate. */
-+ pid_t killed;
-+ for (int i = 0; i < 5; ++i)
-+ {
-+ int status;
-+ killed = xwaitpid (pid, &status, WNOHANG|WUNTRACED);
-+ if (killed != 0)
-+ break;
-+
-+ /* Delay, give the system time to process the kill. If the
-+ nanosleep() call return prematurely, all the better. We
-+ won't restart it since this probably means the child process
-+ finally died. */
-+ nanosleep (&((struct timespec) { 0, 100000000 }), NULL);
-+ }
-+ if (killed != 0 && killed != pid)
-+ return false;
-+
-+ return true;
-+}
-+
-+int
-+support_process_terminate (struct support_subprocess *proc)
-+{
-+ xclose (proc->stdout_pipe[0]);
-+ xclose (proc->stderr_pipe[0]);
-+
-+ int status;
-+ pid_t killed = xwaitpid (proc->pid, &status, WNOHANG|WUNTRACED);
-+ if (killed != 0 && killed == proc->pid)
-+ return status;
-+
-+ /* Subprocess is still running, terminate it. */
-+ if (!support_process_kill (proc->pid, SIGTERM, &status) )
-+ support_process_kill (proc->pid, SIGKILL, &status);
-+
-+ return status;
-+}
-diff --git a/support/tst-support_capture_subprocess.c b/support/tst-support_capture_subprocess.c
-index d8ba42ea8b..ab363e41ac 100644
---- a/support/tst-support_capture_subprocess.c
-+++ b/support/tst-support_capture_subprocess.c
-@@ -23,8 +23,20 @@
- #include <support/capture_subprocess.h>
- #include <support/check.h>
- #include <support/support.h>
-+#include <support/temp_file.h>
- #include <sys/wait.h>
- #include <unistd.h>
-+#include <paths.h>
-+#include <getopt.h>
-+#include <limits.h>
-+#include <errno.h>
-+#include <array_length.h>
-+
-+/* Nonzero if the program gets called via 'exec'. */
-+static int restart;
-+
-+/* Hold the four initial argument used to respawn the process. */
-+static char *initial_argv[5];
-
- /* Write one byte at *P to FD and advance *P. Do nothing if *P is
- '\0'. */
-@@ -42,6 +54,30 @@ transfer (const unsigned char **p, int fd)
- enum write_mode { out_first, err_first, interleave,
- write_mode_last = interleave };
-
-+static const char *
-+write_mode_to_str (enum write_mode mode)
-+{
-+ switch (mode)
-+ {
-+ case out_first: return "out_first";
-+ case err_first: return "err_first";
-+ case interleave: return "interleave";
-+ default: return "write_mode_last";
-+ }
-+}
-+
-+static enum write_mode
-+str_to_write_mode (const char *mode)
-+{
-+ if (strcmp (mode, "out_first") == 0)
-+ return out_first;
-+ else if (strcmp (mode, "err_first") == 0)
-+ return err_first;
-+ else if (strcmp (mode, "interleave") == 0)
-+ return interleave;
-+ return write_mode_last;
-+}
-+
- /* Describe what to write in the subprocess. */
- struct test
- {
-@@ -52,11 +88,9 @@ struct test
- int status;
- };
-
--/* For use with support_capture_subprocess. */
--static void
--callback (void *closure)
-+_Noreturn static void
-+test_common (const struct test *test)
- {
-- const struct test *test = closure;
- bool mode_ok = false;
- switch (test->write_mode)
- {
-@@ -95,6 +129,40 @@ callback (void *closure)
- exit (test->status);
- }
-
-+static int
-+parse_int (const char *str)
-+{
-+ char *endptr;
-+ long int ret = strtol (str, &endptr, 10);
-+ TEST_COMPARE (errno, 0);
-+ TEST_VERIFY (ret >= 0 && ret <= INT_MAX);
-+ return ret;
-+}
-+
-+/* For use with support_capture_subprogram. */
-+_Noreturn static void
-+handle_restart (char *out, char *err, const char *write_mode,
-+ const char *signal, const char *status)
-+{
-+ struct test test =
-+ {
-+ out,
-+ err,
-+ str_to_write_mode (write_mode),
-+ parse_int (signal),
-+ parse_int (status)
-+ };
-+ test_common (&test);
-+}
-+
-+/* For use with support_capture_subprocess. */
-+_Noreturn static void
-+callback (void *closure)
-+{
-+ const struct test *test = closure;
-+ test_common (test);
-+}
-+
- /* Create a heap-allocated random string of letters. */
- static char *
- random_string (size_t length)
-@@ -130,12 +198,59 @@ check_stream (const char *what, const struct xmemstream *stream,
- }
- }
-
-+static struct support_capture_subprocess
-+do_subprocess (struct test *test)
-+{
-+ return support_capture_subprocess (callback, test);
-+}
-+
-+static struct support_capture_subprocess
-+do_subprogram (const struct test *test)
-+{
-+ /* Three digits per byte plus null terminator. */
-+ char signalstr[3 * sizeof(int) + 1];
-+ snprintf (signalstr, sizeof (signalstr), "%d", test->signal);
-+ char statusstr[3 * sizeof(int) + 1];
-+ snprintf (statusstr, sizeof (statusstr), "%d", test->status);
-+
-+ int argc = 0;
-+ enum {
-+ /* 4 elements from initial_argv (path to ld.so, '--library-path', the
-+ path', and application name'), 2 for restart argument ('--direct',
-+ '--restart'), 5 arguments plus NULL. */
-+ argv_size = 12
-+ };
-+ char *args[argv_size];
-+
-+ for (char **arg = initial_argv; *arg != NULL; arg++)
-+ args[argc++] = *arg;
-+
-+ args[argc++] = (char*) "--direct";
-+ args[argc++] = (char*) "--restart";
-+
-+ args[argc++] = test->out;
-+ args[argc++] = test->err;
-+ args[argc++] = (char*) write_mode_to_str (test->write_mode);
-+ args[argc++] = signalstr;
-+ args[argc++] = statusstr;
-+ args[argc] = NULL;
-+ TEST_VERIFY (argc < argv_size);
-+
-+ return support_capture_subprogram (args[0], args);
-+}
-+
-+enum test_type
-+{
-+ subprocess,
-+ subprogram,
-+};
-+
- static int
--do_test (void)
-+do_multiple_tests (enum test_type type)
- {
- const int lengths[] = {0, 1, 17, 512, 20000, -1};
-
-- /* Test multiple combinations of support_capture_subprocess.
-+ /* Test multiple combinations of support_capture_sub{process,program}.
-
- length_idx_stdout: Index into the lengths array above,
- controls how many bytes are written by the subprocess to
-@@ -164,8 +279,10 @@ do_test (void)
- TEST_VERIFY (strlen (test.out) == lengths[length_idx_stdout]);
- TEST_VERIFY (strlen (test.err) == lengths[length_idx_stderr]);
-
-- struct support_capture_subprocess result
-- = support_capture_subprocess (callback, &test);
-+ struct support_capture_subprocess result
-+ = type == subprocess ? do_subprocess (&test)
-+ : do_subprogram (&test);
-+
- check_stream ("stdout", &result.out, test.out);
- check_stream ("stderr", &result.err, test.err);
-
-@@ -199,4 +316,54 @@ do_test (void)
- return 0;
- }
-
-+static int
-+do_test (int argc, char *argv[])
-+{
-+ /* We must have either:
-+
-+ - one or four parameters if called initially:
-+ + argv[1]: path for ld.so optional
-+ + argv[2]: "--library-path" optional
-+ + argv[3]: the library path optional
-+ + argv[4]: the application name
-+
-+ - six parameters left if called through re-execution:
-+ + argv[1]: the application name
-+ + argv[2]: the stdout to print
-+ + argv[3]: the stderr to print
-+ + argv[4]: the write mode to use
-+ + argv[5]: the signal to issue
-+ + argv[6]: the exit status code to use
-+
-+ * When built with --enable-hardcoded-path-in-tests or issued without
-+ using the loader directly.
-+ */
-+
-+ if (argc != (restart ? 6 : 5) && argc != (restart ? 6 : 2))
-+ FAIL_EXIT1 ("wrong number of arguments (%d)", argc);
-+
-+ if (restart)
-+ {
-+ handle_restart (argv[1], /* stdout */
-+ argv[2], /* stderr */
-+ argv[3], /* write_mode */
-+ argv[4], /* signal */
-+ argv[5]); /* status */
-+ }
-+
-+ initial_argv[0] = argv[1]; /* path for ld.so */
-+ initial_argv[1] = argv[2]; /* "--library-path" */
-+ initial_argv[2] = argv[3]; /* the library path */
-+ initial_argv[3] = argv[4]; /* the application name */
-+ initial_argv[4] = NULL;
-+
-+ do_multiple_tests (subprocess);
-+ do_multiple_tests (subprogram);
-+
-+ return 0;
-+}
-+
-+#define CMDLINE_OPTIONS \
-+ { "restart", no_argument, &restart, 1 },
-+#define TEST_FUNCTION_ARGV do_test
- #include <support/test-driver.c>
-diff --git a/support/xposix_spawn.c b/support/xposix_spawn.c
-new file mode 100644
-index 0000000000..e846017632
---- /dev/null
-+++ b/support/xposix_spawn.c
-@@ -0,0 +1,32 @@
-+/* xposix_spawn implementation.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+#include <support/xspawn.h>
-+#include <support/check.h>
-+
-+pid_t
-+xposix_spawn (const char *file, const posix_spawn_file_actions_t *fa,
-+ const posix_spawnattr_t *attr, char *const args[],
-+ char *const envp[])
-+{
-+ pid_t pid;
-+ int status = posix_spawn (&pid, file, fa, attr, args, envp);
-+ if (status != 0)
-+ FAIL_EXIT1 ("posix_spawn to %s file failed: %m", file);
-+ return pid;
-+}
-diff --git a/support/xposix_spawn_file_actions_addclose.c b/support/xposix_spawn_file_actions_addclose.c
-new file mode 100644
-index 0000000000..eed54a6514
---- /dev/null
-+++ b/support/xposix_spawn_file_actions_addclose.c
-@@ -0,0 +1,29 @@
-+/* xposix_spawn_file_actions_addclose implementation.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+#include <support/xspawn.h>
-+#include <support/check.h>
-+
-+int
-+xposix_spawn_file_actions_addclose (posix_spawn_file_actions_t *fa, int fd)
-+{
-+ int status = posix_spawn_file_actions_addclose (fa, fd);
-+ if (status == -1)
-+ FAIL_EXIT1 ("posix_spawn_file_actions_addclose failed: %m\n");
-+ return status;
-+}
-diff --git a/support/xposix_spawn_file_actions_adddup2.c b/support/xposix_spawn_file_actions_adddup2.c
-new file mode 100644
-index 0000000000..a43b6490be
---- /dev/null
-+++ b/support/xposix_spawn_file_actions_adddup2.c
-@@ -0,0 +1,30 @@
-+/* xposix_spawn_file_actions_adddup2 implementation.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+#include <support/xspawn.h>
-+#include <support/check.h>
-+
-+int
-+xposix_spawn_file_actions_adddup2 (posix_spawn_file_actions_t *fa, int fd,
-+ int newfd)
-+{
-+ int status = posix_spawn_file_actions_adddup2 (fa, fd, newfd);
-+ if (status == -1)
-+ FAIL_EXIT1 ("posix_spawn_file_actions_adddup2 failed: %m\n");
-+ return status;
-+}
-diff --git a/support/xpthread_rwlock_destroy.c b/support/xpthread_rwlock_destroy.c
-new file mode 100644
-index 0000000000..6d6e953569
---- /dev/null
-+++ b/support/xpthread_rwlock_destroy.c
-@@ -0,0 +1,26 @@
-+/* pthread_rwlock_destroy with error checking.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+#include <support/xthread.h>
-+
-+void
-+xpthread_rwlock_destroy (pthread_rwlock_t *rwlock)
-+{
-+ xpthread_check_return ("pthread_rwlock_destroy",
-+ pthread_rwlock_destroy (rwlock));
-+}
-diff --git a/support/xspawn.h b/support/xspawn.h
-new file mode 100644
-index 0000000000..bbf89132e4
---- /dev/null
-+++ b/support/xspawn.h
-@@ -0,0 +1,34 @@
-+/* posix_spawn with support checks.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+#ifndef SUPPORT_XSPAWN_H
-+#define SUPPORT_XSPAWN_H
-+
-+#include <spawn.h>
-+
-+__BEGIN_DECLS
-+
-+int xposix_spawn_file_actions_addclose (posix_spawn_file_actions_t *, int);
-+int xposix_spawn_file_actions_adddup2 (posix_spawn_file_actions_t *, int, int);
-+
-+pid_t xposix_spawn (const char *, const posix_spawn_file_actions_t *,
-+ const posix_spawnattr_t *, char *const [], char *const []);
-+
-+__END_DECLS
-+
-+#endif
-diff --git a/support/xthread.h b/support/xthread.h
-index 47c23235f3..9fe1f68b3b 100644
---- a/support/xthread.h
-+++ b/support/xthread.h
-@@ -84,6 +84,7 @@ void xpthread_rwlockattr_setkind_np (pthread_rwlockattr_t *attr, int pref);
- void xpthread_rwlock_wrlock (pthread_rwlock_t *rwlock);
- void xpthread_rwlock_rdlock (pthread_rwlock_t *rwlock);
- void xpthread_rwlock_unlock (pthread_rwlock_t *rwlock);
-+void xpthread_rwlock_destroy (pthread_rwlock_t *rwlock);
-
- __END_DECLS
-
-diff --git a/sysdeps/arm/stap-probe-machine.h b/sysdeps/arm/stap-probe-machine.h
-new file mode 100644
-index 0000000000..d27ca22040
---- /dev/null
-+++ b/sysdeps/arm/stap-probe-machine.h
-@@ -0,0 +1,22 @@
-+/* Macros for customizing Systemtap <sys/sdt.h>. Arm version.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+/* The default "nor" constraint produces unparseable memory references
-+ for constants. Omit the problematic "o" constraint. See bug 24164
-+ and GCC PR 89146. */
-+#define STAP_SDT_ARG_CONSTRAINT nr
-diff --git a/sysdeps/generic/stap-probe-machine.h b/sysdeps/generic/stap-probe-machine.h
-new file mode 100644
-index 0000000000..2e5790c3b2
---- /dev/null
-+++ b/sysdeps/generic/stap-probe-machine.h
-@@ -0,0 +1,19 @@
-+/* Macros for customizing Systemtap <sys/sdt.h>. Generic version.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+/* By default, there are no customizations. */
-diff --git a/sysdeps/nptl/fork.c b/sysdeps/nptl/fork.c
-index bd68f18b45..14b69a6f89 100644
---- a/sysdeps/nptl/fork.c
-+++ b/sysdeps/nptl/fork.c
-@@ -55,7 +55,7 @@ __libc_fork (void)
- but our current fork implementation is not. */
- bool multiple_threads = THREAD_GETMEM (THREAD_SELF, header.multiple_threads);
-
-- __run_fork_handlers (atfork_run_prepare);
-+ __run_fork_handlers (atfork_run_prepare, multiple_threads);
-
- /* If we are not running multiple threads, we do not have to
- preserve lock state. If fork runs from a signal handler, only
-@@ -134,7 +134,7 @@ __libc_fork (void)
- __rtld_lock_initialize (GL(dl_load_lock));
-
- /* Run the handlers registered for the child. */
-- __run_fork_handlers (atfork_run_child);
-+ __run_fork_handlers (atfork_run_child, multiple_threads);
- }
- else
- {
-@@ -149,7 +149,7 @@ __libc_fork (void)
- }
-
- /* Run the handlers registered for the parent. */
-- __run_fork_handlers (atfork_run_parent);
-+ __run_fork_handlers (atfork_run_parent, multiple_threads);
- }
-
- return pid;
-diff --git a/sysdeps/nptl/fork.h b/sysdeps/nptl/fork.h
-index a1c3b26b68..99ed76034b 100644
---- a/sysdeps/nptl/fork.h
-+++ b/sysdeps/nptl/fork.h
-@@ -52,9 +52,11 @@ enum __run_fork_handler_type
- - atfork_run_child: run all the CHILD_HANDLER and unlocks the internal
- lock.
- - atfork_run_parent: run all the PARENT_HANDLER and unlocks the internal
-- lock. */
--extern void __run_fork_handlers (enum __run_fork_handler_type who)
-- attribute_hidden;
-+ lock.
-+
-+ Perform locking only if DO_LOCKING. */
-+extern void __run_fork_handlers (enum __run_fork_handler_type who,
-+ _Bool do_locking) attribute_hidden;
-
- /* C library side function to register new fork handlers. */
- extern int __register_atfork (void (*__prepare) (void),
-diff --git a/sysdeps/powerpc/dl-procinfo.h b/sysdeps/powerpc/dl-procinfo.h
-index f542f7318f..dfc3b33a72 100644
---- a/sysdeps/powerpc/dl-procinfo.h
-+++ b/sysdeps/powerpc/dl-procinfo.h
-@@ -225,7 +225,7 @@ _dl_procinfo (unsigned int type, unsigned long int word)
- break;
- }
- default:
-- /* This should not happen. */
-+ /* Fallback to generic output mechanism. */
- return -1;
- }
- _dl_printf ("\n");
-diff --git a/sysdeps/s390/dl-procinfo.h b/sysdeps/s390/dl-procinfo.h
-index b4b81fc70a..99697ae649 100644
---- a/sysdeps/s390/dl-procinfo.h
-+++ b/sysdeps/s390/dl-procinfo.h
-@@ -57,7 +57,8 @@ enum
- };
-
- #define HWCAP_IMPORTANT (HWCAP_S390_ZARCH | HWCAP_S390_LDISP \
-- | HWCAP_S390_EIMM | HWCAP_S390_DFP)
-+ | HWCAP_S390_EIMM | HWCAP_S390_DFP \
-+ | HWCAP_S390_VX | HWCAP_S390_VXE)
-
- /* We cannot provide a general printing function. */
- #define _dl_procinfo(type, word) -1
-diff --git a/sysdeps/sparc/dl-procinfo.h b/sysdeps/sparc/dl-procinfo.h
-index 282b8c5117..64ee267fc7 100644
---- a/sysdeps/sparc/dl-procinfo.h
-+++ b/sysdeps/sparc/dl-procinfo.h
-@@ -31,8 +31,8 @@ _dl_procinfo (unsigned int type, unsigned long int word)
- {
- int i;
-
-- /* Fallback to unknown output mechanism. */
-- if (type == AT_HWCAP2)
-+ /* Fallback to generic output mechanism. */
-+ if (type != AT_HWCAP)
- return -1;
-
- _dl_printf ("AT_HWCAP: ");
-diff --git a/sysdeps/unix/sysv/linux/arm/dl-procinfo.h b/sysdeps/unix/sysv/linux/arm/dl-procinfo.h
-index 66c00297b7..05c62c8687 100644
---- a/sysdeps/unix/sysv/linux/arm/dl-procinfo.h
-+++ b/sysdeps/unix/sysv/linux/arm/dl-procinfo.h
-@@ -67,7 +67,7 @@ _dl_procinfo (unsigned int type, unsigned long int word)
- break;
- }
- default:
-- /* This should not happen. */
-+ /* Fallback to generic output mechanism. */
- return -1;
- }
- _dl_printf ("\n");
-diff --git a/sysdeps/unix/sysv/linux/i386/dl-procinfo.h b/sysdeps/unix/sysv/linux/i386/dl-procinfo.h
-index 22b43431bc..0585cdaa9c 100644
---- a/sysdeps/unix/sysv/linux/i386/dl-procinfo.h
-+++ b/sysdeps/unix/sysv/linux/i386/dl-procinfo.h
-@@ -30,8 +30,8 @@ _dl_procinfo (unsigned int type, unsigned long int word)
- in the kernel sources. */
- int i;
-
-- /* Fallback to unknown output mechanism. */
-- if (type == AT_HWCAP2)
-+ /* Fallback to generic output mechanism. */
-+ if (type != AT_HWCAP)
- return -1;
-
- _dl_printf ("AT_HWCAP: ");
-diff --git a/sysdeps/unix/sysv/linux/s390/dl-procinfo.h b/sysdeps/unix/sysv/linux/s390/dl-procinfo.h
-index 19329a335b..d67fde368f 100644
---- a/sysdeps/unix/sysv/linux/s390/dl-procinfo.h
-+++ b/sysdeps/unix/sysv/linux/s390/dl-procinfo.h
-@@ -32,8 +32,8 @@ _dl_procinfo (unsigned int type, unsigned long int word)
- in the kernel sources. */
- int i;
-
-- /* Fallback to unknown output mechanism. */
-- if (type == AT_HWCAP2)
-+ /* Fallback to generic output mechanism. */
-+ if (type != AT_HWCAP)
- return -1;
-
- _dl_printf ("AT_HWCAP: ");
-diff --git a/sysdeps/x86_64/memcmp.S b/sysdeps/x86_64/memcmp.S
-index 1fc487caa5..1322bb3b92 100644
---- a/sysdeps/x86_64/memcmp.S
-+++ b/sysdeps/x86_64/memcmp.S
-@@ -21,14 +21,18 @@
-
- .text
- ENTRY (memcmp)
-- test %rdx, %rdx
-+#ifdef __ILP32__
-+ /* Clear the upper 32 bits. */
-+ movl %edx, %edx
-+#endif
-+ test %RDX_LP, %RDX_LP
- jz L(finz)
- cmpq $1, %rdx
-- jle L(finr1b)
-+ jbe L(finr1b)
- subq %rdi, %rsi
- movq %rdx, %r10
- cmpq $32, %r10
-- jge L(gt32)
-+ jae L(gt32)
- /* Handle small chunks and last block of less than 32 bytes. */
- L(small):
- testq $1, %r10
-@@ -156,7 +160,7 @@ L(A32):
- movq %r11, %r10
- andq $-32, %r10
- cmpq %r10, %rdi
-- jge L(mt16)
-+ jae L(mt16)
- /* Pre-unroll to be ready for unrolled 64B loop. */
- testq $32, %rdi
- jz L(A64)
-@@ -178,7 +182,7 @@ L(A64):
- movq %r11, %r10
- andq $-64, %r10
- cmpq %r10, %rdi
-- jge L(mt32)
-+ jae L(mt32)
-
- L(A64main):
- movdqu (%rdi,%rsi), %xmm0
-@@ -216,7 +220,7 @@ L(mt32):
- movq %r11, %r10
- andq $-32, %r10
- cmpq %r10, %rdi
-- jge L(mt16)
-+ jae L(mt16)
-
- L(A32main):
- movdqu (%rdi,%rsi), %xmm0
-@@ -254,7 +258,7 @@ L(ATR):
- movq %r11, %r10
- andq $-32, %r10
- cmpq %r10, %rdi
-- jge L(mt16)
-+ jae L(mt16)
- testq $16, %rdi
- jz L(ATR32)
-
-@@ -325,7 +329,7 @@ L(ATR64main):
- movq %r11, %r10
- andq $-32, %r10
- cmpq %r10, %rdi
-- jge L(mt16)
-+ jae L(mt16)
-
- L(ATR32res):
- movdqa (%rdi,%rsi), %xmm0
-diff --git a/sysdeps/x86_64/x32/Makefile b/sysdeps/x86_64/x32/Makefile
-index 1557724b0c..8748956563 100644
---- a/sysdeps/x86_64/x32/Makefile
-+++ b/sysdeps/x86_64/x32/Makefile
-@@ -8,7 +8,8 @@ endif
- ifeq ($(subdir),string)
- tests += tst-size_t-memchr tst-size_t-memcmp tst-size_t-memcpy \
- tst-size_t-memrchr tst-size_t-memset tst-size_t-strncasecmp \
-- tst-size_t-strncmp tst-size_t-strncpy tst-size_t-strnlen
-+ tst-size_t-strncmp tst-size_t-strncpy tst-size_t-strnlen \
-+ tst-size_t-memcmp-2
- endif
-
- ifeq ($(subdir),wcsmbs)
-diff --git a/sysdeps/x86_64/x32/tst-size_t-memcmp-2.c b/sysdeps/x86_64/x32/tst-size_t-memcmp-2.c
-new file mode 100644
-index 0000000000..d8ae1a0813
---- /dev/null
-+++ b/sysdeps/x86_64/x32/tst-size_t-memcmp-2.c
-@@ -0,0 +1,79 @@
-+/* Test memcmp with size_t in the lower 32 bits of 64-bit register.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+#define TEST_MAIN
-+#ifdef WIDE
-+# define TEST_NAME "wmemcmp"
-+#else
-+# define TEST_NAME "memcmp"
-+#endif
-+
-+#include "test-size_t.h"
-+
-+#ifdef WIDE
-+# include <inttypes.h>
-+# include <wchar.h>
-+
-+# define MEMCMP wmemcmp
-+# define CHAR wchar_t
-+#else
-+# define MEMCMP memcmp
-+# define CHAR char
-+#endif
-+
-+IMPL (MEMCMP, 1)
-+
-+typedef int (*proto_t) (const CHAR *, const CHAR *, size_t);
-+
-+static int
-+__attribute__ ((noinline, noclone))
-+do_memcmp (parameter_t a, parameter_t b)
-+{
-+ return CALL (&b, a.p, b.p, a.len);
-+}
-+
-+static int
-+test_main (void)
-+{
-+ test_init ();
-+
-+ parameter_t dest = { { page_size / sizeof (CHAR) }, buf1 };
-+ parameter_t src = { { 0 }, buf2 };
-+
-+ memcpy (buf1, buf2, page_size);
-+
-+ CHAR *p = (CHAR *) buf1;
-+ p[page_size / sizeof (CHAR) - 1] = (CHAR) 1;
-+
-+ int ret = 0;
-+ FOR_EACH_IMPL (impl, 0)
-+ {
-+ src.fn = impl->fn;
-+ int res = do_memcmp (dest, src);
-+ if (res >= 0)
-+ {
-+ error (0, 0, "Wrong result in function %s: %i >= 0",
-+ impl->name, res);
-+ ret = 1;
-+ }
-+ }
-+
-+ return ret ? EXIT_FAILURE : EXIT_SUCCESS;
-+}
-+
-+#include <support/test-driver.c>