[{"id":3678806,"web_url":"http://patchwork.ozlabs.org/comment/3678806/","msgid":"<CAHirt9hsXHVttvtkqkrF=WGn+K0h9_EeJpZnV5g1BpcJddYH2g@mail.gmail.com>","list_archive_url":null,"date":"2026-04-17T15:41:21","subject":"Re: [PATCH v2 2/2] elf: Support THP segment load with madvise enabled\n THP","submitter":{"id":85150,"url":"http://patchwork.ozlabs.org/api/people/85150/","name":"WANG Rui","email":"wangrui@loongson.cn"},"content":"On Fri, Apr 17, 2026 at 2:00 PM H.J. Lu <hjl.tools@gmail.com> wrote:\n>\n> On Fri, Apr 17, 2026 at 12:11 PM H.J. Lu <hjl.tools@gmail.com> wrote:\n> >\n> > The current THP segment load approach works only when THP is enabled\n> > with always in the kernel.  If THP is enabled with madvise in the\n> > kernel, to enable THP segment load in an application, madvise should\n> > be called with MADV_HUGEPAGE on all THP eligible PT_LOAD segments:\n> >\n> > 1. Remove _dl_map_segment_align.  Call _dl_map_segment_adjust to adjust\n> > alignments of PT_LOAD segments, which marks and aligns only THP eligible\n> > PT_LOAD segments to THP page size when loading an object. This fixes\n> > BZ #34079.\n> > 2. Rename DL_MAP_DEFAULT_THP_PAGESIZE to DL_DEFAULT_THP_PAGESIZE.  If\n> > DL_DEFAULT_THP_PAGESIZE is defined, assume that THP is enabled with\n> > madvise in the kernel.  Otherwise, call __get_thp_size to get THP page\n> > size and call __get_thp_mode to get THP mode.\n> > 3. Call _dl_executable_postprocess in rtld_setup_main_map for dynamic\n> > executables and in LIBC_START_MAIN for static executables, which calls\n> > madvise with MADV_HUGEPAGE on all THP eligible PT_LOAD segments in\n> > executable.  This fixes BZ #34080 for both dynamic and static executables.\n> > 4. Call _dl_postprocess_loadcmd_extra in _dl_postprocess_loadcmd, which\n> > calls madvise with MADV_HUGEPAGE on all THP eligible PT_LOAD segments\n> > when loading an object after they have been mapped in.  This fixes\n> > BZ #34080 for shared objects.\n> > 5. Add tests to verify that large executable PT_LOAD segments in\n> > executables and shared libraries are mapped at addresses aligned to THP\n> > page size when the kernel is configured to use THP in \"always\" mode or\n> > \"madvise\" mode by inspecting /proc/self/maps to check that the mapping\n> > address is aligned to THP page size reported by the kernel [1].  Also\n> > verify that madvise is called with MADV_HUGEPAGE when the glibc tunable\n> > glibc.elf.thp=1 is used and madvise isn't called with MADV_HUGEPAGE when\n> > the glibc tunable glibc.elf.thp=0 is used.\n> >\n> > Skip these tests if THP page size cannot be determined or if THP is not\n> > enabled in \"always\" mode nor \"madvise\" mode.\n> >\n> > Quote WANG Rui <wangrui@loongson.cn>:\n> >\n> > From benchmarking a clang build of the Linux kernel on x86_64 with\n> > your patch in THP madvise mode, I observed that iTLB misses were\n> > reduced, similar to what we see in THP always mode.\n> >\n> > [1] This is developed by WANG Rui <wangrui@loongson.cn>.\n> >\n> > Signed-off-by: H.J. Lu <hjl.tools@gmail.com>\n> > Co-developed-by: WANG Rui <wangrui@loongson.cn>\n>\n> Changes from v1:\n>\n> 1. Rebased against the v10 THP test patch from WANG Rui <wangrui@loongson.cn>.\n> 2. Keep DL_MAP_DEFAULT_THP_PAGESIZE.\n>\n> --\n> H.J.\n> ---\n> The current THP segment load approach works only when THP is enabled\n> with always in the kernel.  If THP is enabled with madvise in the\n> kernel, to enable THP segment load in an application, madvise should\n> be called with MADV_HUGEPAGE on all THP eligible PT_LOAD segments:\n>\n> 1. Remove _dl_map_segment_align.  Call _dl_map_segment_adjust to adjust\n> alignments of PT_LOAD segments, which marks and aligns only THP eligible\n> PT_LOAD segments to THP page size when loading an object. This fixes\n> BZ #34079.\n> 2. Call _dl_executable_postprocess in rtld_setup_main_map for dynamic\n> executables and in LIBC_START_MAIN for static executables, which calls\n> madvise with MADV_HUGEPAGE on all THP eligible PT_LOAD segments in\n> executable.  This fixes BZ #34080 for both dynamic and static executables.\n> 3. Call _dl_postprocess_loadcmd_extra in _dl_postprocess_loadcmd, which\n> calls madvise with MADV_HUGEPAGE on all THP eligible PT_LOAD segments\n> when loading an object after they have been mapped in.  This fixes\n> BZ #34080 for shared objects.\n> 4. Add tests to verify that large executable PT_LOAD segments in\n> executables and shared libraries are mapped at addresses aligned to THP\n> page size when the kernel is configured to use THP in \"always\" mode or\n> \"madvise\" mode by inspecting /proc/self/maps to check that the mapping\n> address is aligned to THP page size reported by the kernel [1].  Also\n> verify that madvise is called with MADV_HUGEPAGE when the glibc tunable\n> glibc.elf.thp=1 is used and madvise isn't called with MADV_HUGEPAGE when\n> the glibc tunable glibc.elf.thp=0 is used.\n>\n> Skip these tests if THP page size cannot be determined or if THP is not\n> enabled in \"always\" mode nor \"madvise\" mode.\n>\n> Quote WANG Rui <wangrui@loongson.cn>:\n>\n> From benchmarking a clang build of the Linux kernel on x86_64 with\n> your patch in THP madvise mode, I observed that iTLB misses were\n> reduced, similar to what we see in THP always mode.\n>\n> [1] This is developed by WANG Rui <wangrui@loongson.cn>.\n>\n> Signed-off-by: H.J. Lu <hjl.tools@gmail.com>\n> Co-developed-by: WANG Rui <wangrui@loongson.cn>\n> ---\n>  csu/libc-start.c                              |   4 +\n>  elf/dl-load.c                                 |  10 +-\n>  elf/dl-load.h                                 |   5 +\n>  elf/dl-support.c                              |   6 +\n>  elf/rtld.c                                    |  17 +--\n>  sysdeps/generic/dl-exec-post.h                |  34 +++++\n>  ...{dl-map-segment-align.h => dl-load-post.h} |   7 +-\n>  sysdeps/generic/dl-map-segment-adjust.h       |  30 ++++\n>  sysdeps/generic/hugepages.h                   |   4 +-\n>  sysdeps/generic/ldsodefs.h                    |  11 ++\n>  sysdeps/unix/sysv/linux/Makefile              | 124 +++++++++++++++-\n>  sysdeps/unix/sysv/linux/dl-exec-post.h        |  95 +++++++++++++\n>  sysdeps/unix/sysv/linux/dl-load-post.h        |  32 +++++\n>  .../unix/sysv/linux/dl-map-segment-adjust.c   |  67 +++++++++\n>  ...egment-align.h => dl-map-segment-adjust.h} |  10 +-\n>  .../unix/sysv/linux/dl-map-segment-align.c    |  55 --------\n>  sysdeps/unix/sysv/linux/ldsodefs.h            |   3 +\n>  sysdeps/unix/sysv/linux/loongarch/Makefile    |   3 +\n>  ...{dl-map-segment-align.h => dl-exec-post.h} |   4 +-\n>  sysdeps/unix/sysv/linux/strace-tst-thp.sh     |  56 ++++++++\n>  .../unix/sysv/linux/tst-thp-1-no-s-code-pde.c |  19 +++\n>  .../sysv/linux/tst-thp-1-no-s-code-static.c   |  19 +++\n>  sysdeps/unix/sysv/linux/tst-thp-1-no-s-code.c |  19 +++\n>  sysdeps/unix/sysv/linux/tst-thp-1-pde.c       |  19 +++\n>  sysdeps/unix/sysv/linux/tst-thp-1-static.c    |  19 +++\n>  sysdeps/unix/sysv/linux/tst-thp-1.c           |  28 ++++\n>  sysdeps/unix/sysv/linux/tst-thp-align-check.h | 132 ++++++++++++++++++\n>  sysdeps/unix/sysv/linux/tst-thp-align.c       |  36 +++++\n>  sysdeps/unix/sysv/linux/tst-thp-size-mod.S    |  24 ++++\n>  sysdeps/unix/sysv/linux/x86/dl-exec-post.h    |  22 +++\n>  30 files changed, 829 insertions(+), 85 deletions(-)\n>  create mode 100644 sysdeps/generic/dl-exec-post.h\n>  rename sysdeps/generic/{dl-map-segment-align.h => dl-load-post.h} (83%)\n>  create mode 100644 sysdeps/generic/dl-map-segment-adjust.h\n>  create mode 100644 sysdeps/unix/sysv/linux/dl-exec-post.h\n>  create mode 100644 sysdeps/unix/sysv/linux/dl-load-post.h\n>  create mode 100644 sysdeps/unix/sysv/linux/dl-map-segment-adjust.c\n>  rename sysdeps/unix/sysv/linux/{dl-map-segment-align.h => dl-map-segment-adjust.h} (79%)\n>  delete mode 100644 sysdeps/unix/sysv/linux/dl-map-segment-align.c\n>  rename sysdeps/unix/sysv/linux/loongarch/lp64/{dl-map-segment-align.h => dl-exec-post.h} (90%)\n>  create mode 100644 sysdeps/unix/sysv/linux/strace-tst-thp.sh\n>  create mode 100644 sysdeps/unix/sysv/linux/tst-thp-1-no-s-code-pde.c\n>  create mode 100644 sysdeps/unix/sysv/linux/tst-thp-1-no-s-code-static.c\n>  create mode 100644 sysdeps/unix/sysv/linux/tst-thp-1-no-s-code.c\n>  create mode 100644 sysdeps/unix/sysv/linux/tst-thp-1-pde.c\n>  create mode 100644 sysdeps/unix/sysv/linux/tst-thp-1-static.c\n>  create mode 100644 sysdeps/unix/sysv/linux/tst-thp-1.c\n>  create mode 100644 sysdeps/unix/sysv/linux/tst-thp-align-check.h\n>  create mode 100644 sysdeps/unix/sysv/linux/tst-thp-align.c\n>  create mode 100644 sysdeps/unix/sysv/linux/tst-thp-size-mod.S\n>  create mode 100644 sysdeps/unix/sysv/linux/x86/dl-exec-post.h\n>\n> diff --git a/csu/libc-start.c b/csu/libc-start.c\n> index 1c58561bce..be60831a42 100644\n> --- a/csu/libc-start.c\n> +++ b/csu/libc-start.c\n> @@ -205,6 +205,7 @@ call_fini (void *unused)\n>  #endif /* !SHARED */\n>\n>  #include <libc-start.h>\n> +#include <dl-exec-post.h>\n>\n>  STATIC int LIBC_START_MAIN (int (*main) (int, char **, char **\n>  MAIN_AUXVEC_DECL),\n> @@ -305,6 +306,9 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),\n>    __pointer_chk_guard_local = pointer_chk_guard;\n>  # endif\n>\n> +  struct link_map *main_map = _dl_get_dl_main_map ();\n> +  _dl_executable_postprocess (main_map, GL(dl_phdr), GL(dl_phnum));\n> +\n>  #endif /* !SHARED  */\n>\n>    /* Register the destructor of the dynamic linker if there is any.  */\n> diff --git a/elf/dl-load.c b/elf/dl-load.c\n> index 48575fff06..800b7ca1a6 100644\n> --- a/elf/dl-load.c\n> +++ b/elf/dl-load.c\n> @@ -71,7 +71,7 @@ struct filebuf\n>  #include <dl-dst.h>\n>  #include <dl-load.h>\n>  #include <dl-map-segments.h>\n> -#include <dl-map-segment-align.h>\n> +#include <dl-map-segment-adjust.h>\n>  #include <dl-unmap-segments.h>\n>  #include <dl-machine-reject-phdr.h>\n>  #include <dl-prop.h>\n> @@ -1173,8 +1173,8 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,\n>    /* Optimize a common case.  */\n>    c->prot = pf_to_prot (ph->p_flags);\n>\n> -   /* Architecture-specific adjustment of segment alignment. */\n> -   p_align_max = _dl_map_segment_align (c, p_align_max);\n> +   /* Initialize flags.  */\n> +   c->flags = 0;\n>    break;\n>\n>  case PT_TLS:\n> @@ -1229,9 +1229,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,\n>  goto lose;\n>        }\n>\n> -    /* Align all PT_LOAD segments to the maximum p_align.  */\n> -    for (size_t i = 0; i < nloadcmds; i++)\n> -      loadcmds[i].mapalign = p_align_max;\n> +    _dl_map_segment_adjust (loadcmds, &nloadcmds, p_align_max);\n>\n>      /* dlopen of an executable is not valid because it is not possible\n>         to perform proper relocations, handle static TLS, or run the\n> diff --git a/elf/dl-load.h b/elf/dl-load.h\n> index 897c4034c5..55edf0323c 100644\n> --- a/elf/dl-load.h\n> +++ b/elf/dl-load.h\n> @@ -78,8 +78,11 @@ struct loadcmd\n>    ElfW(Addr) mapstart, mapend, dataend, allocend, mapalign;\n>    ElfW(Off) mapoff;\n>    int prot;                             /* PROT_* bits.  */\n> +  /* May be used by _dl_postprocess_loadcmd_extra.  */\n> +  unsigned int flags;\n>  };\n>\n> +#include <dl-load-post.h>\n>\n>  /* This is a subroutine of _dl_map_segments.  It should be called for each\n>     load command, some time after L->l_addr has been set correctly.  It is\n> @@ -95,6 +98,8 @@ _dl_postprocess_loadcmd (struct link_map *l, const ElfW(Ehdr) *header,\n>      /* Found the program header in this segment.  */\n>      l->l_phdr = (void *) (uintptr_t) (c->mapstart + header->e_phoff\n>                                        - c->mapoff);\n> +\n> +  _dl_postprocess_loadcmd_extra (l, c);\n>  }\n>\n>\n> diff --git a/elf/dl-support.c b/elf/dl-support.c\n> index 0508d6113b..420e418b40 100644\n> --- a/elf/dl-support.c\n> +++ b/elf/dl-support.c\n> @@ -179,6 +179,12 @@ int _dl_stack_cache_lock;\n>  #endif\n>  struct dl_scope_free_list *_dl_scope_free_list;\n>\n> +#ifdef HAVE_THP\n> +int _dl_thp_control = -1;\n> +enum thp_mode_t _dl_thp_mode;\n> +size_t _dl_thp_pagesize;\n> +#endif\n> +\n>  #ifdef NEED_DL_SYSINFO\n>  /* Needed for improved syscall handling on at least x86/Linux.  NB: Don't\n>     initialize it here to avoid RELATIVE relocation in static PIE.  */\n> diff --git a/elf/rtld.c b/elf/rtld.c\n> index e926ec73e4..fe8d6f87e3 100644\n> --- a/elf/rtld.c\n> +++ b/elf/rtld.c\n> @@ -52,6 +52,7 @@\n>  #include <dl-find_object.h>\n>  #include <dl-audit-check.h>\n>  #include <dl-call_tls_init_tp.h>\n> +#include <dl-exec-post.h>\n>\n>  #include <assert.h>\n>\n> @@ -323,6 +324,9 @@ struct rtld_global _rtld_global =\n>      /* Generally the default presumption without further information is an\n>       * executable stack but this is not true for all platforms.  */\n>      ._dl_stack_prot_flags = DEFAULT_STACK_PROT_PERMS,\n> +#ifdef HAVE_THP\n> +    ._dl_thp_control = -1,\n> +#endif\n>  #ifdef _LIBC_REENTRANT\n>      ._dl_load_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,\n>      ._dl_load_write_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,\n> @@ -1209,14 +1213,8 @@ rtld_setup_main_map (struct link_map *main_map)\n>  main_map->l_relro_size = ph->p_memsz;\n>  break;\n>        }\n> -  /* Process program headers again, but scan them backwards since\n> -     PT_GNU_PROPERTY is close to the end of program headers.   */\n> -  for (const ElfW(Phdr) *ph = &phdr[phnum]; ph != phdr; --ph)\n> -    if (ph[-1].p_type == PT_GNU_PROPERTY)\n> -      {\n> - _dl_process_pt_gnu_property (main_map, -1, &ph[-1]);\n> - break;\n> -      }\n> +\n> +  _dl_executable_postprocess (main_map, phdr, phnum);\n>\n>    /* Adjust the address of the TLS initialization image in case\n>       the executable is actually an ET_DYN object.  */\n> @@ -1589,6 +1587,9 @@ dl_main (const ElfW(Phdr) *phdr,\n>  {\n>    RTLD_TIMING_VAR (start);\n>    rtld_timer_start (&start);\n> +#ifdef HAVE_THP\n> +   _dl_get_thp_config ();\n> +#endif\n>    _dl_map_object (NULL, rtld_progname, lt_executable, 0,\n>    __RTLD_OPENEXEC, LM_ID_BASE);\n>    rtld_timer_stop (&load_time, start);\n> diff --git a/sysdeps/generic/dl-exec-post.h b/sysdeps/generic/dl-exec-post.h\n> new file mode 100644\n> index 0000000000..f5dcdc093a\n> --- /dev/null\n> +++ b/sysdeps/generic/dl-exec-post.h\n> @@ -0,0 +1,34 @@\n> +/* _dl_executable_postprocess.  Generic version.\n> +   Copyright (C) 2026 Free Software Foundation, Inc.\n> +   Copyright The GNU Toolchain Authors.\n> +   This file is part of the GNU C Library.\n> +\n> +   The GNU C Library is free software; you can redistribute it and/or\n> +   modify it under the terms of the GNU Lesser General Public\n> +   License as published by the Free Software Foundation; either\n> +   version 2.1 of the License, or (at your option) any later version.\n> +\n> +   The GNU C Library is distributed in the hope that it will be useful,\n> +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> +   Lesser General Public License for more details.\n> +\n> +   You should have received a copy of the GNU Lesser General Public\n> +   License along with the GNU C Library; if not, see\n> +   <https://www.gnu.org/licenses/>.  */\n> +\n> +static inline void\n> +_dl_executable_postprocess (struct link_map *main_map,\n> +     const ElfW(Phdr) *phdr, ElfW(Word) phnum)\n> +{\n> +#ifdef SHARED\n> +  /* Process program headers again, but scan them backwards since\n> +     PT_GNU_PROPERTY is close to the end of program headers.   */\n> +  for (const ElfW(Phdr) *ph = &phdr[phnum]; ph != phdr; --ph)\n> +    if (ph[-1].p_type == PT_GNU_PROPERTY)\n> +      {\n> + _dl_process_pt_gnu_property (main_map, -1, &ph[-1]);\n> + break;\n> +      }\n> +#endif\n> +}\n> diff --git a/sysdeps/generic/dl-map-segment-align.h b/sysdeps/generic/dl-load-post.h\n> similarity index 83%\n> rename from sysdeps/generic/dl-map-segment-align.h\n> rename to sysdeps/generic/dl-load-post.h\n> index f4a671f25f..bfaad8ea7c 100644\n> --- a/sysdeps/generic/dl-map-segment-align.h\n> +++ b/sysdeps/generic/dl-load-post.h\n> @@ -1,4 +1,4 @@\n> -/* _dl_map_segment_align.  Generic version.\n> +/* _dl_postprocess_loadcmd_extra.  Generic version.\n>     Copyright (C) 2026 Free Software Foundation, Inc.\n>     Copyright The GNU Toolchain Authors.\n>     This file is part of the GNU C Library.\n> @@ -19,8 +19,7 @@\n>\n>  #include <dl-load.h>\n>\n> -static inline ElfW(Addr)\n> -_dl_map_segment_align (const struct loadcmd *c, ElfW(Addr) p_align_max)\n> +static inline void\n> +_dl_postprocess_loadcmd_extra (struct link_map *l, const struct loadcmd *c)\n>  {\n> -  return p_align_max;\n>  }\n> diff --git a/sysdeps/generic/dl-map-segment-adjust.h b/sysdeps/generic/dl-map-segment-adjust.h\n> new file mode 100644\n> index 0000000000..b48057ec26\n> --- /dev/null\n> +++ b/sysdeps/generic/dl-map-segment-adjust.h\n> @@ -0,0 +1,30 @@\n> +/* _dl_map_segment_adjust.  Generic version.\n> +   Copyright (C) 2026 Free Software Foundation, Inc.\n> +   Copyright The GNU Toolchain Authors.\n> +   This file is part of the GNU C Library.\n> +\n> +   The GNU C Library is free software; you can redistribute it and/or\n> +   modify it under the terms of the GNU Lesser General Public\n> +   License as published by the Free Software Foundation; either\n> +   version 2.1 of the License, or (at your option) any later version.\n> +\n> +   The GNU C Library is distributed in the hope that it will be useful,\n> +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> +   Lesser General Public License for more details.\n> +\n> +   You should have received a copy of the GNU Lesser General Public\n> +   License along with the GNU C Library; if not, see\n> +   <https://www.gnu.org/licenses/>.  */\n> +\n> +#include <dl-load.h>\n> +\n> +static inline void\n> +_dl_map_segment_adjust (struct loadcmd *load_cmds,\n> + size_t *n_load_cmds, ElfW(Addr) p_align_max)\n> +{\n> +  /* Align all PT_LOAD segments to the maximum p_align.  */\n> +  size_t n = *n_load_cmds;\n> +  for (size_t i = 0; i < n; i++)\n> +    load_cmds[i].mapalign = p_align_max;\n> +}\n> diff --git a/sysdeps/generic/hugepages.h b/sysdeps/generic/hugepages.h\n> index 5fc9b5c8de..df9ec4920b 100644\n> --- a/sysdeps/generic/hugepages.h\n> +++ b/sysdeps/generic/hugepages.h\n> @@ -26,10 +26,10 @@ unsigned long int __get_thp_size (void) attribute_hidden;\n>\n>  enum thp_mode_t\n>  {\n> +  thp_mode_not_supported = 0,\n>    thp_mode_always,\n>    thp_mode_madvise,\n> -  thp_mode_never,\n> -  thp_mode_not_supported\n> +  thp_mode_never\n>  };\n>\n>  enum thp_mode_t __get_thp_mode (void) attribute_hidden;\n> diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h\n> index 15c4659853..36f2e88ae4 100644\n> --- a/sysdeps/generic/ldsodefs.h\n> +++ b/sysdeps/generic/ldsodefs.h\n> @@ -39,6 +39,7 @@\n>  #include <libc-lock.h>\n>  #include <hp-timing.h>\n>  #include <list_t.h>\n> +#include <hugepages.h>\n>\n>  __BEGIN_DECLS\n>\n> @@ -477,6 +478,16 @@ struct rtld_global\n>    EXTERN struct __pthread **_dl_pthread_threads;\n>    __mach_rwlock_define (EXTERN, _dl_pthread_threads_lock)\n>  #endif\n> +#ifdef HAVE_THP\n> +  /* The THP segment load control:\n> +      > 0: Enabled by GLIBC_TUNABLES=glibc.elf.thp=1.\n> +        0: Disabled by GLIBC_TUNABLES=glibc.elf.thp=0.\n> +      < 0: To be enabled or disabled by GLIBC_TUNABLES.  */\n\nI think we need to treat THP-always and THP-madvise differently. For\nalways, it seems reasonable to let an architecture enable\n`glibc.elf.thp` by default. But for madvise, it should be opt-in only.\n\n> +  EXTERN int _dl_thp_control;\n> +\n> +  EXTERN enum thp_mode_t _dl_thp_mode;\n> +  EXTERN size_t _dl_thp_pagesize;\n> +#endif\n>  #ifdef SHARED\n>  };\n>  # define __rtld_global_attribute__\n> diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile\n> index b06afbdeaa..41d321c564 100644\n> --- a/sysdeps/unix/sysv/linux/Makefile\n> +++ b/sysdeps/unix/sysv/linux/Makefile\n> @@ -673,7 +673,7 @@ endif\n>\n>  ifeq ($(subdir),elf)\n>  dl-routines += \\\n> -  dl-map-segment-align \\\n> +  dl-map-segment-adjust \\\n>    dl-rseq-symbols \\\n>    # dl-routines\n>\n> @@ -698,13 +698,19 @@ $(objpfx)pldd: $(objpfx)xmalloc.o\n>  tests += \\\n>    tst-rseq-tls-range \\\n>    tst-rseq-tls-range-4096 \\\n> +  tst-thp-1 \\\n> +  tst-thp-1-pde \\\n> +  tst-thp-1-static \\\n> +  tst-thp-align \\\n>  # tests\n>  tests-static += \\\n>    tst-rseq-tls-range-4096-static \\\n>    tst-rseq-tls-range-static \\\n> +  tst-thp-1-static \\\n>  # tests-static\n>  modules-names += \\\n>    tst-rseq-tls-range-mod \\\n> +  tst-thp-size-mod \\\n>  # modules-names\n>  CFLAGS-tst-rseq-tls-range.c += -DMAIN_TLS_ALIGN=4\n>  CFLAGS-tst-rseq-tls-range-4096.c += -DMAIN_TLS_ALIGN=4096\n> @@ -724,6 +730,122 @@ tests-special += \\\n>    $(objpfx)tst-nolink-libc-2.out \\\n>    # tests-special\n>  endif\n> +\n> +ifndef THP-PAGE-SIZE\n> +# Align PT_LOAD segments in THP tests to THP page size so that kernel will\n> +# map PIE to the address aligned to THP page size.  Default THP page size\n> +# to 2MB which can be overridden in Makefile in subdirectories.\n> +THP-PAGE-SIZE = 0x200000\n> +endif\n> +\n> +THP-PAGE-SIZE-LDFLAGS = -Wl,-z,max-page-size=$(THP-PAGE-SIZE)\n> +\n> +LDFLAGS-tst-thp-size-mod.so = $(THP-PAGE-SIZE-LDFLAGS)\n> +tst-thp-align-ENV = GLIBC_TUNABLES=glibc.elf.thp=1\n> +$(objpfx)tst-thp-align.out: $(objpfx)tst-thp-size-mod.so\n> +\n> +ifeq ($(have-separate-code),yes)\n> +tests += \\\n> +  tst-thp-1-no-s-code \\\n> +  tst-thp-1-no-s-code-pde \\\n> +  tst-thp-1-no-s-code-static \\\n> +# tests\n> +tests-static += \\\n> +  tst-thp-1-no-s-code-static \\\n> +# tests-static\n> +\n> +LDFLAGS-tst-thp-1 = -Wl,-z,separate-code $(THP-PAGE-SIZE-LDFLAGS)\n> +LDFLAGS-tst-thp-1-pde = -Wl,-z,separate-code $(THP-PAGE-SIZE-LDFLAGS)\n> +LDFLAGS-tst-thp-1-static = -Wl,-z,separate-code $(THP-PAGE-SIZE-LDFLAGS)\n> +LDFLAGS-tst-thp-1-no-s-code = -Wl,-z,noseparate-code \\\n> +       $(THP-PAGE-SIZE-LDFLAGS)\n> +LDFLAGS-tst-thp-1-no-s-code-pde = -Wl,-z,noseparate-code \\\n> +   $(THP-PAGE-SIZE-LDFLAGS)\n> +LDFLAGS-tst-thp-1-no-s-code-static = -Wl,-z,noseparate-code \\\n> +      $(THP-PAGE-SIZE-LDFLAGS)\n> +\n> +$(objpfx)tst-thp-1-no-s-code: $(objpfx)tst-thp-size-mod.o\n> +$(objpfx)tst-thp-1-no-s-code-pde: $(objpfx)tst-thp-size-mod.o\n> +$(objpfx)tst-thp-1-no-s-code-static: $(objpfx)tst-thp-size-mod.o\n> +\n> +tst-thp-1-no-s-code-ENV = GLIBC_TUNABLES=glibc.elf.thp=1\n> +tst-thp-1-no-s-code-pde-ENV = GLIBC_TUNABLES=glibc.elf.thp=1\n> +tst-thp-1-no-s-code-static-ENV = GLIBC_TUNABLES=glibc.elf.thp=1\n> +\n> +tst-thp-1-no-s-code-pde-no-pie = yes\n> +endif\n> +\n> +tst-thp-1-ENV = GLIBC_TUNABLES=glibc.elf.thp=1\n> +tst-thp-1-pde-ENV = GLIBC_TUNABLES=glibc.elf.thp=1\n> +tst-thp-1-static-ENV = GLIBC_TUNABLES=glibc.elf.thp=1\n> +\n> +$(objpfx)tst-thp-1: $(objpfx)tst-thp-size-mod.o\n> +$(objpfx)tst-thp-1-pde: $(objpfx)tst-thp-size-mod.o\n> +$(objpfx)tst-thp-1-static: $(objpfx)tst-thp-size-mod.o\n> +\n> +tst-thp-1-pde-no-pie = yes\n> +\n> +thp-kernel-status = $(shell grep madvise /sys/kernel/mm/transparent_hugepage/enabled)\n> +# Verify that madvise is called with MADV_HUGEPAGE when THP is enabled\n> +# under madvise THP kernel.\n> +ifneq ($(findstring [madvise],$(thp-kernel-status)),)\n> +tests-special += \\\n> +  $(objpfx)strace-tst-thp-1-disabled.out \\\n> +  $(objpfx)strace-tst-thp-1-enabled.out \\\n> +  $(objpfx)strace-tst-thp-1-pde-disabled.out \\\n> +  $(objpfx)strace-tst-thp-1-pde-enabled.out \\\n> +  $(objpfx)strace-tst-thp-1-static-disabled.out \\\n> +  $(objpfx)strace-tst-thp-1-static-enabled.out \\\n> +# tests-special\n> +\n> +$(objpfx)strace-tst-thp-1-enabled.out: \\\n> +  $(..)sysdeps/unix/sysv/linux/strace-tst-thp.sh $(objpfx)ld.so \\\n> +  $(objpfx)tst-thp-1\n> + $(SHELL) $< $(objpfx)ld.so '$(test-wrapper-env)' \\\n> + '$(run-program-env) GLIBC_TUNABLES=glibc.elf.thp=1' \\\n> + '$(rpath-link)' $(objpfx)tst-thp-1 > $@;\n> +   $(evaluate-test)\n> +\n> +$(objpfx)strace-tst-thp-1-disabled.out: \\\n> +  $(..)sysdeps/unix/sysv/linux/strace-tst-thp.sh $(objpfx)ld.so \\\n> +  $(objpfx)tst-thp-1\n> + $(SHELL) $< $(objpfx)ld.so '$(test-wrapper-env)' \\\n> + '$(run-program-env) GLIBC_TUNABLES=glibc.elf.thp=0' \\\n> + '$(rpath-link)' $(objpfx)tst-thp-1 > $@;\n> +   $(evaluate-test)\n> +\n> +$(objpfx)strace-tst-thp-1-pde-enabled.out: \\\n> +  $(..)sysdeps/unix/sysv/linux/strace-tst-thp.sh $(objpfx)ld.so \\\n> +  $(objpfx)tst-thp-1-pde\n> + $(SHELL) $< $(objpfx)ld.so '$(test-wrapper-env)' \\\n> + '$(run-program-env) GLIBC_TUNABLES=glibc.elf.thp=1' \\\n> + '$(rpath-link)' $(objpfx)tst-thp-1-pde > $@; \\\n> +   $(evaluate-test)\n> +\n> +$(objpfx)strace-tst-thp-1-pde-disabled.out: \\\n> +  $(..)sysdeps/unix/sysv/linux/strace-tst-thp.sh $(objpfx)ld.so \\\n> +  $(objpfx)tst-thp-1-pde\n> + $(SHELL) $< $(objpfx)ld.so '$(test-wrapper-env)' \\\n> + '$(run-program-env) GLIBC_TUNABLES=glibc.elf.thp=0' \\\n> + '$(rpath-link)' $(objpfx)tst-thp-1-pde > $@; \\\n> +   $(evaluate-test)\n> +\n> +$(objpfx)strace-tst-thp-1-static-enabled.out: \\\n> +  $(..)sysdeps/unix/sysv/linux/strace-tst-thp.sh $(objpfx)ld.so \\\n> +  $(objpfx)tst-thp-1-static\n> + $(SHELL) $< $(objpfx)ld.so '$(test-wrapper-env)' \\\n> + '$(run-program-env) GLIBC_TUNABLES=glibc.elf.thp=1' \\\n> + '$(rpath-link)' $(objpfx)tst-thp-1-static > $@; \\\n> +   $(evaluate-test)\n> +\n> +$(objpfx)strace-tst-thp-1-static-disabled.out: \\\n> +  $(..)sysdeps/unix/sysv/linux/strace-tst-thp.sh $(objpfx)ld.so \\\n> +  $(objpfx)tst-thp-1-static\n> + $(SHELL) $< $(objpfx)ld.so '$(test-wrapper-env)' \\\n> + '$(run-program-env) GLIBC_TUNABLES=glibc.elf.thp=0' \\\n> + '$(rpath-link)' $(objpfx)tst-thp-1-static > $@; \\\n> +   $(evaluate-test)\n> +endif\n>  endif # $(subdir) == elf\n>\n>  ifeq ($(subdir),rt)\n> diff --git a/sysdeps/unix/sysv/linux/dl-exec-post.h b/sysdeps/unix/sysv/linux/dl-exec-post.h\n> new file mode 100644\n> index 0000000000..1ef1f6556e\n> --- /dev/null\n> +++ b/sysdeps/unix/sysv/linux/dl-exec-post.h\n> @@ -0,0 +1,95 @@\n> +/* _dl_executable_postprocess.  Linux version.\n> +   Copyright (C) 2026 Free Software Foundation, Inc.\n> +   Copyright The GNU Toolchain Authors.\n> +   This file is part of the GNU C Library.\n> +\n> +   The GNU C Library is free software; you can redistribute it and/or\n> +   modify it under the terms of the GNU Lesser General Public\n> +   License as published by the Free Software Foundation; either\n> +   version 2.1 of the License, or (at your option) any later version.\n> +\n> +   The GNU C Library is distributed in the hope that it will be useful,\n> +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> +   Lesser General Public License for more details.\n> +\n> +   You should have received a copy of the GNU Lesser General Public\n> +   License along with the GNU C Library; if not, see\n> +   <https://www.gnu.org/licenses/>.  */\n> +\n> +static inline void\n> +_dl_get_thp_config (void)\n> +{\n> +  /* Check if there is GLIBC_TUNABLES=glibc.elf.thp=[0|1].  */\n> +  if (TUNABLE_IS_INITIALIZED_FULL (glibc, elf, thp))\n> +    GL(dl_thp_control) = TUNABLE_GET_FULL (glibc, elf, thp, int32_t,\n> +    NULL);\n> +\n> +  /* Return if THP is disabled by GLIBC_TUNABLES=glibc.elf.thp=0.  */\n> +  if (GL(dl_thp_control) == 0)\n> +    return;\n> +\n> +#ifdef DL_MAP_DEFAULT_THP_PAGESIZE\n> +  /* NB: Accessing /sys/kernel/mm files is quite expensive and the file\n> +     may not be accessible in containers.  If DL_MAP_DEFAULT_THP_PAGESIZE\n> +     is defined, assume THP mode is madvise and always call madvise.\n> +     Since madvise is a fast systemcall, it adds only a small overhead\n> +     compared to the cost of accessing /sys/kernel/mm files.  */\n> +  GL(dl_thp_pagesize) = DL_MAP_DEFAULT_THP_PAGESIZE;\n> +  GL(dl_thp_mode) = thp_mode_madvise;\n> +#else\n> +  GL(dl_thp_pagesize) = __get_thp_size ();\n> +  GL(dl_thp_mode) = __get_thp_mode ();\n> +#endif\n> +}\n> +\n> +static inline void\n> +_dl_executable_postprocess (struct link_map *main_map,\n> +     const ElfW(Phdr) *phdr, ElfW(Word) phnum)\n> +{\n> +  if (GL(dl_thp_control) == -1)\n> +    _dl_get_thp_config ();\n> +\n> +  /* NB: In static executable, PT_GNU_PROPERTY is processed in target\n> +     libc-start.h if it is needed by target.  When ld.so is used, if\n> +     a target doesn't need PT_GNU_PROPERTY, _dl_process_pt_gnu_property\n> +     is an empty function.  */\n> +#ifdef SHARED\n> +  /* Process program headers again, but scan them backwards since\n> +     PT_GNU_PROPERTY is close to the end of program headers.   */\n> +  for (const ElfW(Phdr) *ph = &phdr[phnum]; ph != phdr; --ph)\n> +    if (ph[-1].p_type == PT_GNU_PROPERTY)\n> +      {\n> + _dl_process_pt_gnu_property (main_map, -1, &ph[-1]);\n> + break;\n> +      }\n> +#endif\n> +\n> +  /* Return if THP segment load isn't enabled.  */\n> +  if (GL(dl_thp_control) <= 0)\n> +    return;\n> +\n> +#ifndef DL_MAP_DEFAULT_THP_PAGESIZE\n> +  /* NB: If DL_MAP_DEFAULT_THP_PAGESIZE is defined, dl_thp_mode is always\n> +     set to thp_mode_madvise.  */\n> +  if (GL(dl_thp_mode) != thp_mode_madvise)\n> +    return;\n> +#endif\n> +\n> +  /* When we get here, the main executable have been mapped in.  Call\n> +     madvise with MADV_HUGEPAGE for all THP eligible PT_LOAD segments.  */\n> +\n> +  const ElfW(Phdr) *ph;\n> +\n> +  size_t thp_pagesize = GL(dl_thp_pagesize);\n> +\n> +  /* Call __madvise if offset and address of the PT_LOAD segment are\n> +     aligned to THP page size and it is read-only.  */\n> +  for (ph = phdr; ph < &phdr[phnum]; ++ph)\n> +    if (ph->p_type == PT_LOAD\n> + && ph->p_memsz >= thp_pagesize\n> + && ((ph->p_vaddr | ph->p_offset) & (thp_pagesize - 1)) == 0\n> + && (ph->p_flags & (PF_W | PF_R)) == PF_R)\n> +      __madvise ((void *) (main_map->l_addr + ph->p_vaddr),\n> + ph->p_memsz, MADV_HUGEPAGE);\n> +}\n> diff --git a/sysdeps/unix/sysv/linux/dl-load-post.h b/sysdeps/unix/sysv/linux/dl-load-post.h\n> new file mode 100644\n> index 0000000000..b3c4e16bb7\n> --- /dev/null\n> +++ b/sysdeps/unix/sysv/linux/dl-load-post.h\n> @@ -0,0 +1,32 @@\n> +/* _dl_postprocess_loadcmd_extra.  Linux version.\n> +   Copyright (C) 2026 Free Software Foundation, Inc.\n> +   Copyright The GNU Toolchain Authors.\n> +   This file is part of the GNU C Library.\n> +\n> +   The GNU C Library is free software; you can redistribute it and/or\n> +   modify it under the terms of the GNU Lesser General Public\n> +   License as published by the Free Software Foundation; either\n> +   version 2.1 of the License, or (at your option) any later version.\n> +\n> +   The GNU C Library is distributed in the hope that it will be useful,\n> +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> +   Lesser General Public License for more details.\n> +\n> +   You should have received a copy of the GNU Lesser General Public\n> +   License along with the GNU C Library; if not, see\n> +   <https://www.gnu.org/licenses/>.  */\n> +\n> +/* Bits in the flags field of struct loadcmd.  */\n> +#define LOADCMD_POST_MADVISE_THP (0x1 << 0)\n> +\n> +/* After L has been mapped in, call madvise with MADV_HUGEPAGE if L is\n> +   THP eligible.  */\n> +\n> +static inline void\n> +_dl_postprocess_loadcmd_extra (struct link_map *l, const struct loadcmd *c)\n> +{\n> +  if ((c->flags & LOADCMD_POST_MADVISE_THP) != 0)\n> +    __madvise ((void *) (l->l_addr + c->mapstart),\n> +        c->mapend - c->mapstart, MADV_HUGEPAGE);\n> +}\n> diff --git a/sysdeps/unix/sysv/linux/dl-map-segment-adjust.c b/sysdeps/unix/sysv/linux/dl-map-segment-adjust.c\n> new file mode 100644\n> index 0000000000..90c8ea92fe\n> --- /dev/null\n> +++ b/sysdeps/unix/sysv/linux/dl-map-segment-adjust.c\n> @@ -0,0 +1,67 @@\n> +/* _dl_map_segment_adjust.  Linux version.\n> +   Copyright (C) 2026 Free Software Foundation, Inc.\n> +   Copyright The GNU Toolchain Authors.\n> +   This file is part of the GNU C Library.\n> +\n> +   The GNU C Library is free software; you can redistribute it and/or\n> +   modify it under the terms of the GNU Lesser General Public\n> +   License as published by the Free Software Foundation; either\n> +   version 2.1 of the License, or (at your option) any later version.\n> +\n> +   The GNU C Library is distributed in the hope that it will be useful,\n> +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> +   Lesser General Public License for more details.\n> +\n> +   You should have received a copy of the GNU Lesser General Public\n> +   License along with the GNU C Library; if not, see\n> +   <https://www.gnu.org/licenses/>.  */\n> +\n> +#include <ldsodefs.h>\n> +#include <dl-map-segment-adjust.h>\n> +\n> +/* Set the mapalign field in entries in LOAD_CMDS to align PT_LOAD\n> +   segments for THP.  P_ALIGN_MAX is the maximum p_align value in all\n> +   PT_LOAD segments.  */\n> +\n> +void\n> +_dl_map_segment_adjust (struct loadcmd *load_cmds, size_t *n_load_cmds,\n> + ElfW(Addr) p_align_max)\n\nsize_t n_load_cmds?\n\n> +{\n> +  size_t n = *n_load_cmds;\n> +  size_t i;\n> +  enum thp_mode_t thp_mode = GL(dl_thp_mode);\n> +  size_t thp_pagesize = GL(dl_thp_pagesize);\n> +  struct loadcmd *c = load_cmds;\n> +\n> +  if (n == 0)\n> +    return;\n> +\n> +  /* We cap the huge page size at MAX_THP_PAGESIZE to avoid over-aligning\n> +     on systems with very large normal pages (like 64K pages with 512M\n> +     huge pages).  */\n> +  if (GL(dl_thp_control) <= 0\n> +      || p_align_max >= thp_pagesize\n> +      || !(thp_mode == thp_mode_always || thp_mode == thp_mode_madvise))\n\nMissing a check for MAX_THP_PAGESIZE?\n\n> +    {\n> +      for (i = 0; i < n; i++, c++)\n> + c->mapalign = p_align_max;\n> +      return;\n> +    }\n> +\n> +  /* Set the mapalign field to THP page size only if offset and address\n> +     of the segment are aligned to THP page size, it is read-only and\n> +     its size >= THP page size.  It helps improve THP eligibility and\n> +     reduces TLB pressure.  */\n> +  for (i = 0; i < n; i++, c++)\n> +    if (((c->mapstart | c->mapoff) & (thp_pagesize - 1)) == 0\n> + && (c->mapend - c->mapstart) >= thp_pagesize\n> + && (c->prot & PROT_WRITE) == 0)\n> +      {\n> + c->mapalign = thp_pagesize;\n> + if (thp_mode == thp_mode_madvise)\n> +   c->flags = LOADCMD_POST_MADVISE_THP;\n> +      }\n> +    else\n> +      c->mapalign = p_align_max;\n> +}\n> diff --git a/sysdeps/unix/sysv/linux/dl-map-segment-align.h b/sysdeps/unix/sysv/linux/dl-map-segment-adjust.h\n> similarity index 79%\n> rename from sysdeps/unix/sysv/linux/dl-map-segment-align.h\n> rename to sysdeps/unix/sysv/linux/dl-map-segment-adjust.h\n\nWhy rename this hook?\n\n> index d9b05181b7..2fbfc66d48 100644\n> --- a/sysdeps/unix/sysv/linux/dl-map-segment-align.h\n> +++ b/sysdeps/unix/sysv/linux/dl-map-segment-adjust.h\n> @@ -1,4 +1,4 @@\n> -/* _dl_map_segment_align.  Linux version.\n> +/* _dl_map_segment_adjust.  Linux version.\n>     Copyright (C) 2026 Free Software Foundation, Inc.\n>     Copyright The GNU Toolchain Authors.\n>     This file is part of the GNU C Library.\n> @@ -19,9 +19,5 @@\n>\n>  #include <dl-load.h>\n>\n> -#ifndef DL_MAP_DEFAULT_THP_PAGESIZE\n> -# define DL_MAP_DEFAULT_THP_PAGESIZE 0\n> -#endif\n> -\n> -extern ElfW (Addr) _dl_map_segment_align\n> -  (const struct loadcmd *, ElfW (Addr)) attribute_hidden;\n> +extern void _dl_map_segment_adjust\n> +  (struct loadcmd *, size_t *, ElfW(Addr)) attribute_hidden;\n> diff --git a/sysdeps/unix/sysv/linux/dl-map-segment-align.c b/sysdeps/unix/sysv/linux/dl-map-segment-align.c\n> deleted file mode 100644\n> index a39e74d91b..0000000000\n> --- a/sysdeps/unix/sysv/linux/dl-map-segment-align.c\n> +++ /dev/null\n> @@ -1,55 +0,0 @@\n> -/* _dl_map_segment_align.  Linux version.\n> -   Copyright (C) 2026 Free Software Foundation, Inc.\n> -   Copyright The GNU Toolchain Authors.\n> -   This file is part of the GNU C Library.\n> -\n> -   The GNU C Library is free software; you can redistribute it and/or\n> -   modify it under the terms of the GNU Lesser General Public\n> -   License as published by the Free Software Foundation; either\n> -   version 2.1 of the License, or (at your option) any later version.\n> -\n> -   The GNU C Library is distributed in the hope that it will be useful,\n> -   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> -   Lesser General Public License for more details.\n> -\n> -   You should have received a copy of the GNU Lesser General Public\n> -   License along with the GNU C Library; if not, see\n> -   <https://www.gnu.org/licenses/>.  */\n> -\n> -#include <dl-map-segment-align.h>\n> -#include <dl-tunables.h>\n> -#include <hugepages.h>\n> -\n> -ElfW (Addr)\n> -_dl_map_segment_align (const struct loadcmd *c, ElfW (Addr) p_align_max)\n> -{\n> -  static enum thp_mode_t thp_mode = thp_mode_not_supported;\n> -  static unsigned long int thp_pagesize;\n> -\n> -  if (TUNABLE_GET (glibc, elf, thp, int32_t, NULL) == 0)\n> -    return p_align_max;\n> -\n> -  if (__glibc_unlikely (thp_mode == thp_mode_not_supported\n> -                        || thp_pagesize == 0))\n> -    {\n> -      unsigned long int default_thp_pagesize = DL_MAP_DEFAULT_THP_PAGESIZE;\n> -      thp_mode = default_thp_pagesize ? thp_mode_always : __get_thp_mode ();\n> -      thp_pagesize = default_thp_pagesize ? : __get_thp_size ();\n> -    }\n> -\n> -  /* Aligning load segments that are large enough to the PMD size helps\n> -     improve THP eligibility and reduces TLB pressure.\n> -     We cap the huge page size at MAX_THP_PAGESIZE to avoid over-aligning\n> -     on systems with very large normal pages (like 64K pages with 512M\n> -     huge pages). */\n> -  if (thp_mode == thp_mode_always\n> -      && thp_pagesize <= MAX_THP_PAGESIZE\n> -      && ((c->mapstart | c->mapoff) & (thp_pagesize - 1)) == 0\n> -      && (c->mapend - c->mapstart) >= thp_pagesize\n> -      && p_align_max < thp_pagesize\n> -      && (c->prot & PROT_WRITE) == 0)\n> -    return thp_pagesize;\n> -\n> -  return p_align_max;\n> -}\n> diff --git a/sysdeps/unix/sysv/linux/ldsodefs.h b/sysdeps/unix/sysv/linux/ldsodefs.h\n> index c63b649432..e39d9afe34 100644\n> --- a/sysdeps/unix/sysv/linux/ldsodefs.h\n> +++ b/sysdeps/unix/sysv/linux/ldsodefs.h\n> @@ -21,6 +21,9 @@\n>  /* We have the auxiliary vector.  */\n>  #define HAVE_AUX_VECTOR\n>\n> +/* We have transparent huge page.  */\n> +#define HAVE_THP\n> +\n>  /* Get the real definitions.  */\n>  #include_next <ldsodefs.h>\n>\n> diff --git a/sysdeps/unix/sysv/linux/loongarch/Makefile b/sysdeps/unix/sysv/linux/loongarch/Makefile\n> index 0d5f087862..d5beb62440 100644\n> --- a/sysdeps/unix/sysv/linux/loongarch/Makefile\n> +++ b/sysdeps/unix/sysv/linux/loongarch/Makefile\n> @@ -12,3 +12,6 @@ abi-ilp32s-condition := __WORDSIZE == 32 && defined __loongarch_soft_float\n>  abi-ilp32d-condition := __WORDSIZE == 32 && defined __loongarch_double_float\n>  abi-lp64s-condition := __WORDSIZE == 64 && defined __loongarch_soft_float\n>  abi-lp64d-condition := __WORDSIZE == 64 && defined __loongarch_double_float\n> +\n> +# Align THP tests to 32MB.\n> +THP-PAGE-SIZE = 0x2000000\n> diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/dl-map-segment-align.h b/sysdeps/unix/sysv/linux/loongarch/lp64/dl-exec-post.h\n> similarity index 90%\n> rename from sysdeps/unix/sysv/linux/loongarch/lp64/dl-map-segment-align.h\n> rename to sysdeps/unix/sysv/linux/loongarch/lp64/dl-exec-post.h\n> index c51ee4ac47..fbc58d662c 100644\n> --- a/sysdeps/unix/sysv/linux/loongarch/lp64/dl-map-segment-align.h\n> +++ b/sysdeps/unix/sysv/linux/loongarch/lp64/dl-exec-post.h\n> @@ -1,4 +1,4 @@\n> -/* _dl_map_segment_align.  LoongArch64 Linux version.\n> +/* DL_MAP_DEFAULT_THP_PAGESIZE.  LoongArch64 Linux version.\n>     Copyright (C) 2026 Free Software Foundation, Inc.\n>     Copyright The GNU Toolchain Authors.\n>     This file is part of the GNU C Library.\n> @@ -19,4 +19,4 @@\n>\n>  #define DL_MAP_DEFAULT_THP_PAGESIZE (32 * 1024 * 1024)\n>\n> -#include_next <dl-map-segment-align.h>\n> +#include_next <dl-exec-post.h>\n> diff --git a/sysdeps/unix/sysv/linux/strace-tst-thp.sh b/sysdeps/unix/sysv/linux/strace-tst-thp.sh\n> new file mode 100644\n> index 0000000000..8903717fd4\n> --- /dev/null\n> +++ b/sysdeps/unix/sysv/linux/strace-tst-thp.sh\n> @@ -0,0 +1,56 @@\n> +#!/bin/sh\n> +# Run THP test under strace to verify control of the THP segment load.\n> +# Copyright (C) 2026 Free Software Foundation, Inc.\n> +# This file is part of the GNU C Library.\n> +\n> +# The GNU C Library is free software; you can redistribute it and/or\n> +# modify it under the terms of the GNU Lesser General Public\n> +# License as published by the Free Software Foundation; either\n> +# version 2.1 of the License, or (at your option) any later version.\n> +\n> +# The GNU C Library is distributed in the hope that it will be useful,\n> +# but WITHOUT ANY WARRANTY; without even the implied warranty of\n> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> +# Lesser General Public License for more details.\n> +\n> +# You should have received a copy of the GNU Lesser General Public\n> +# License along with the GNU C Library; if not, see\n> +# <https://www.gnu.org/licenses/>.\n> +\n> +set -e\n> +\n> +rtld=\"$1\"\n> +test_wrapper_env=\"$2\"\n> +run_program_env=\"$3\"\n> +library_path=\"$4\"\n> +test_prog=\"$5\"\n> +\n> +# Test whether strace is available in the test environment.  If not, skip\n> +# the test.\n> +${test_wrapper_env} ${run_program_env} \\\n> +  /bin/sh -c \"command -v strace\" || exit 77\n> +\n> +# Finally the actual test inside the test environment, using the just\n> +# build ld.so and new libraries to run the THP test under strace.\n> +if /bin/sh -c \\\n> +  \"${test_wrapper_env} ${run_program_env} strace ${rtld} \\\n> +   --library-path ${library_path} ${test_prog} 2>&1 \\\n> +   | grep -E \\\"madvise(.*, MADV_HUGEPAGE)\\\"\"; then\n> +  case x\"${run_program_env}\" in\n> +  *glibc.elf.thp=1*)\n> +    exit 0\n> +    ;;\n> +  *)\n> +    exit 1\n> +    ;;\n> +  esac\n> +else\n> +  case x\"${run_program_env}\" in\n> +  *glibc.elf.thp=0*)\n> +    exit 0\n> +    ;;\n> +  *)\n> +    exit 1\n> +    ;;\n> +  esac\n> +fi\n> diff --git a/sysdeps/unix/sysv/linux/tst-thp-1-no-s-code-pde.c b/sysdeps/unix/sysv/linux/tst-thp-1-no-s-code-pde.c\n> new file mode 100644\n> index 0000000000..3fd01e9bfe\n> --- /dev/null\n> +++ b/sysdeps/unix/sysv/linux/tst-thp-1-no-s-code-pde.c\n> @@ -0,0 +1,19 @@\n> +/* Test PDE with THP segment load linked with -Wl,-z,noseparate-code.\n> +   Copyright (C) 2026 Free Software Foundation, Inc.\n> +   This file is part of the GNU C Library.\n> +\n> +   The GNU C Library is free software; you can redistribute it and/or\n> +   modify it under the terms of the GNU Lesser General Public\n> +   License as published by the Free Software Foundation; either\n> +   version 2.1 of the License, or (at your option) any later version.\n> +\n> +   The GNU C Library is distributed in the hope that it will be useful,\n> +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> +   Lesser General Public License for more details.\n> +\n> +   You should have received a copy of the GNU Lesser General Public\n> +   License along with the GNU C Library; if not, see\n> +   <http://www.gnu.org/licenses/>.  */\n> +\n> +#include \"tst-thp-1.c\"\n> diff --git a/sysdeps/unix/sysv/linux/tst-thp-1-no-s-code-static.c b/sysdeps/unix/sysv/linux/tst-thp-1-no-s-code-static.c\n> new file mode 100644\n> index 0000000000..d0ae0f1ff0\n> --- /dev/null\n> +++ b/sysdeps/unix/sysv/linux/tst-thp-1-no-s-code-static.c\n> @@ -0,0 +1,19 @@\n> +/* Test static with THP segment load linked with -Wl,-z,noseparate-code.\n> +   Copyright (C) 2026 Free Software Foundation, Inc.\n> +   This file is part of the GNU C Library.\n> +\n> +   The GNU C Library is free software; you can redistribute it and/or\n> +   modify it under the terms of the GNU Lesser General Public\n> +   License as published by the Free Software Foundation; either\n> +   version 2.1 of the License, or (at your option) any later version.\n> +\n> +   The GNU C Library is distributed in the hope that it will be useful,\n> +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> +   Lesser General Public License for more details.\n> +\n> +   You should have received a copy of the GNU Lesser General Public\n> +   License along with the GNU C Library; if not, see\n> +   <http://www.gnu.org/licenses/>.  */\n> +\n> +#include \"tst-thp-1.c\"\n> diff --git a/sysdeps/unix/sysv/linux/tst-thp-1-no-s-code.c b/sysdeps/unix/sysv/linux/tst-thp-1-no-s-code.c\n> new file mode 100644\n> index 0000000000..5eb1e005ed\n> --- /dev/null\n> +++ b/sysdeps/unix/sysv/linux/tst-thp-1-no-s-code.c\n> @@ -0,0 +1,19 @@\n> +/* Test THP segment load linked with -Wl,-z,noseparate-code.\n> +   Copyright (C) 2026 Free Software Foundation, Inc.\n> +   This file is part of the GNU C Library.\n> +\n> +   The GNU C Library is free software; you can redistribute it and/or\n> +   modify it under the terms of the GNU Lesser General Public\n> +   License as published by the Free Software Foundation; either\n> +   version 2.1 of the License, or (at your option) any later version.\n> +\n> +   The GNU C Library is distributed in the hope that it will be useful,\n> +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> +   Lesser General Public License for more details.\n> +\n> +   You should have received a copy of the GNU Lesser General Public\n> +   License along with the GNU C Library; if not, see\n> +   <http://www.gnu.org/licenses/>.  */\n> +\n> +#include \"tst-thp-1.c\"\n> diff --git a/sysdeps/unix/sysv/linux/tst-thp-1-pde.c b/sysdeps/unix/sysv/linux/tst-thp-1-pde.c\n> new file mode 100644\n> index 0000000000..d854dd43da\n> --- /dev/null\n> +++ b/sysdeps/unix/sysv/linux/tst-thp-1-pde.c\n> @@ -0,0 +1,19 @@\n> +/* Test PDE with THP segment load linked with -Wl,-z,separate-code.\n> +   Copyright (C) 2026 Free Software Foundation, Inc.\n> +   This file is part of the GNU C Library.\n> +\n> +   The GNU C Library is free software; you can redistribute it and/or\n> +   modify it under the terms of the GNU Lesser General Public\n> +   License as published by the Free Software Foundation; either\n> +   version 2.1 of the License, or (at your option) any later version.\n> +\n> +   The GNU C Library is distributed in the hope that it will be useful,\n> +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> +   Lesser General Public License for more details.\n> +\n> +   You should have received a copy of the GNU Lesser General Public\n> +   License along with the GNU C Library; if not, see\n> +   <http://www.gnu.org/licenses/>.  */\n> +\n> +#include \"tst-thp-1.c\"\n> diff --git a/sysdeps/unix/sysv/linux/tst-thp-1-static.c b/sysdeps/unix/sysv/linux/tst-thp-1-static.c\n> new file mode 100644\n> index 0000000000..66d7e12954\n> --- /dev/null\n> +++ b/sysdeps/unix/sysv/linux/tst-thp-1-static.c\n> @@ -0,0 +1,19 @@\n> +/* Test static with THP segment load linked with -Wl,-z,separate-code.\n> +   Copyright (C) 2026 Free Software Foundation, Inc.\n> +   This file is part of the GNU C Library.\n> +\n> +   The GNU C Library is free software; you can redistribute it and/or\n> +   modify it under the terms of the GNU Lesser General Public\n> +   License as published by the Free Software Foundation; either\n> +   version 2.1 of the License, or (at your option) any later version.\n> +\n> +   The GNU C Library is distributed in the hope that it will be useful,\n> +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> +   Lesser General Public License for more details.\n> +\n> +   You should have received a copy of the GNU Lesser General Public\n> +   License along with the GNU C Library; if not, see\n> +   <http://www.gnu.org/licenses/>.  */\n> +\n> +#include \"tst-thp-1.c\"\n> diff --git a/sysdeps/unix/sysv/linux/tst-thp-1.c b/sysdeps/unix/sysv/linux/tst-thp-1.c\n> new file mode 100644\n> index 0000000000..49eea7069c\n> --- /dev/null\n> +++ b/sysdeps/unix/sysv/linux/tst-thp-1.c\n> @@ -0,0 +1,28 @@\n> +/* Test THP segment load linked with -Wl,-z,separate-code.\n> +   Copyright (C) 2026 Free Software Foundation, Inc.\n> +   This file is part of the GNU C Library.\n> +\n> +   The GNU C Library is free software; you can redistribute it and/or\n> +   modify it under the terms of the GNU Lesser General Public\n> +   License as published by the Free Software Foundation; either\n> +   version 2.1 of the License, or (at your option) any later version.\n> +\n> +   The GNU C Library is distributed in the hope that it will be useful,\n> +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> +   Lesser General Public License for more details.\n> +\n> +   You should have received a copy of the GNU Lesser General Public\n> +   License along with the GNU C Library; if not, see\n> +   <http://www.gnu.org/licenses/>.  */\n> +\n> +#include \"tst-thp-align-check.h\"\n> +\n> +static int\n> +do_test (void)\n> +{\n> +  check_align (\"tst-thp-1\");\n> +  return 0;\n> +}\n> +\n> +#include <support/test-driver.c>\n> diff --git a/sysdeps/unix/sysv/linux/tst-thp-align-check.h b/sysdeps/unix/sysv/linux/tst-thp-align-check.h\n> new file mode 100644\n> index 0000000000..bcb50c96f8\n> --- /dev/null\n> +++ b/sysdeps/unix/sysv/linux/tst-thp-align-check.h\n> @@ -0,0 +1,132 @@\n> +/* Test the THP compatible alignment of PT_LOAD segments.\n> +\n> +   Copyright (C) 2026 Free Software Foundation, Inc.\n> +\n> +   The GNU C Library is free software; you can redistribute it and/or\n> +   modify it under the terms of the GNU Lesser General Public\n> +   License as published by the Free Software Foundation; either\n> +   version 2.1 of the License, or (at your option) any later version.\n> +\n> +   The GNU C Library is distributed in the hope that it will be useful,\n> +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> +   Lesser General Public License for more details.\n> +\n> +   You should have received a copy of the GNU Lesser General Public\n> +   License along with the GNU C Library; if not, see\n> +   <https://www.gnu.org/licenses/>.  */\n> +\n> +#include <fcntl.h>\n> +#include <stdint.h>\n> +#include <stdlib.h>\n> +#include <string.h>\n> +#include <intprops.h>\n> +#include <inttypes.h>\n> +#include <support/check.h>\n> +#include <support/xstdio.h>\n> +#include <support/xunistd.h>\n> +#define attribute_hidden\n> +#include <hugepages.h> /* For enum thp_mode_t and MAX_THP_PAGESIZE.  */\n> +#undef attribute_hidden\n> +\n> +static unsigned long int\n> +get_thp_size (void)\n> +{\n> +  int fd = open (\"/sys/kernel/mm/transparent_hugepage/hpage_pmd_size\",\n> +                 O_RDONLY, 0);\n> +  if (fd == -1)\n> +    return 0;\n> +\n> +  char str[INT_BUFSIZE_BOUND (unsigned long int)];\n> +  ssize_t s = read (fd, str, sizeof (str));\n> +  close (fd);\n> +  if (s < 0)\n> +    return 0;\n> +\n> +  unsigned long int r = 0;\n> +  for (ssize_t i = 0; i < s; i++)\n> +    {\n> +      if (str[i] == '\\n')\n> +    break;\n> +      r *= 10;\n> +      r += str[i] - '0';\n> +    }\n> +  return r;\n> +}\n> +\n> +static enum thp_mode_t\n> +get_thp_mode (void)\n> +{\n> +  int fd = open (\"/sys/kernel/mm/transparent_hugepage/enabled\", O_RDONLY, 0);\n> +  if (fd == -1)\n> +    return thp_mode_not_supported;\n> +\n> +  static const char mode_always[]  = \"[always] madvise never\\n\";\n> +  static const char mode_madvise[] = \"always [madvise] never\\n\";\n> +  static const char mode_never[]   = \"always madvise [never]\\n\";\n> +\n> +  char str[sizeof(mode_always)];\n> +  ssize_t s = read (fd, str, sizeof (str));\n> +  if (s >= sizeof str || s < 0)\n> +    return thp_mode_not_supported;\n> +  str[s] = '\\0';\n> +  close (fd);\n> +\n> +  if (s == sizeof (mode_always) - 1)\n> +    {\n> +      if (strcmp (str, mode_always) == 0)\n> +    return thp_mode_always;\n> +      else if (strcmp (str, mode_madvise) == 0)\n> +    return thp_mode_madvise;\n> +      else if (strcmp (str, mode_never) == 0)\n> +    return thp_mode_never;\n> +    }\n> +  return thp_mode_not_supported;\n> +}\n> +\n> +static void\n> +check_align (const char *name)\n> +{\n> +  unsigned long int thp_size = get_thp_size ();\n> +  enum thp_mode_t thp_mode = get_thp_mode ();\n> +\n> +  if (thp_size == 0)\n> +    {\n> +      FAIL_UNSUPPORTED (\"unable to get THP size.\\n\");\n> +      return;\n> +    }\n> +\n> +  if (thp_size > MAX_THP_PAGESIZE)\n> +    {\n> +      FAIL_UNSUPPORTED (\"THP size exceeds MAX_THP_PAGESIZE.\\n\");\n> +      return;\n> +    }\n> +\n> +  if (thp_mode != thp_mode_always && thp_mode != thp_mode_madvise)\n> +    {\n> +      FAIL_UNSUPPORTED (\"THP mode is not always nor madvise.\\n\");\n> +      return;\n> +    }\n> +\n> +  FILE *f = xfopen (\"/proc/self/maps\", \"r\");\n> +  char *line = NULL;\n> +  size_t len;\n> +\n> +  while (xgetline (&line, &len, f))\n> +    {\n> +      uintptr_t from, to;\n> +      char *prot = NULL, *path = NULL;\n> +      int r = sscanf (line, \"%\" SCNxPTR \"-%\" SCNxPTR \"%ms%*s%*s%*s%ms\",\n> +                      &from, &to, &prot, &path);\n> +\n> +      TEST_VERIFY (r == 3 || r == 4);\n> +\n> +      if (strstr (prot, \"x\") && strstr (path, name))\n> +        TEST_COMPARE (from % thp_size, 0);\n> +\n> +      free (path);\n> +    }\n> +\n> +  free (line);\n> +  xfclose (f);\n> +}\n> diff --git a/sysdeps/unix/sysv/linux/tst-thp-align.c b/sysdeps/unix/sysv/linux/tst-thp-align.c\n> new file mode 100644\n> index 0000000000..2e44109ba6\n> --- /dev/null\n> +++ b/sysdeps/unix/sysv/linux/tst-thp-align.c\n> @@ -0,0 +1,36 @@\n> +/* Test the THP compatible alignment of PT_LOAD segments.\n> +\n> +   Copyright (C) 2026 Free Software Foundation, Inc.\n> +\n> +   The GNU C Library is free software; you can redistribute it and/or\n> +   modify it under the terms of the GNU Lesser General Public\n> +   License as published by the Free Software Foundation; either\n> +   version 2.1 of the License, or (at your option) any later version.\n> +\n> +   The GNU C Library is distributed in the hope that it will be useful,\n> +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> +   Lesser General Public License for more details.\n> +\n> +   You should have received a copy of the GNU Lesser General Public\n> +   License along with the GNU C Library; if not, see\n> +   <https://www.gnu.org/licenses/>.  */\n> +\n> +#include <support/xdlfcn.h>\n> +#include \"tst-thp-align-check.h\"\n> +\n> +#define THP_SIZE_MOD_NAME \"tst-thp-size-mod.so\"\n> +\n> +static int\n> +do_test (void)\n> +{\n> +  void *dl;\n> +\n> +  dl = xdlopen (THP_SIZE_MOD_NAME, RTLD_NOW);\n> +  check_align (THP_SIZE_MOD_NAME);\n> +  xdlclose (dl);\n> +\n> +  return 0;\n> +}\n> +\n> +#include <support/test-driver.c>\n> diff --git a/sysdeps/unix/sysv/linux/tst-thp-size-mod.S b/sysdeps/unix/sysv/linux/tst-thp-size-mod.S\n> new file mode 100644\n> index 0000000000..add66dfb52\n> --- /dev/null\n> +++ b/sysdeps/unix/sysv/linux/tst-thp-size-mod.S\n> @@ -0,0 +1,24 @@\n> +/* A module that provides THP code size for testing.\n> +\n> +   Copyright (C) 2026 Free Software Foundation, Inc.\n> +   This file is part of the GNU C Library.\n> +\n> +   The GNU C Library is free software; you can redistribute it and/or\n> +   modify it under the terms of the GNU Lesser General Public\n> +   License as published by the Free Software Foundation; either\n> +   version 2.1 of the License, or (at your option) any later version.\n> +\n> +   The GNU C Library is distributed in the hope that it will be useful,\n> +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> +   Lesser General Public License for more details.\n> +\n> +   You should have received a copy of the GNU Lesser General Public\n> +   License along with the GNU C Library; if not, see\n> +   <https://www.gnu.org/licenses/>.  */\n> +\n> +/* Create a 32MB text section to enable transparent huge page load.  */\n> + .text\n> + .globl thp_size\n> +thp_size:\n> + .space 32 * 1024 * 1024\n> diff --git a/sysdeps/unix/sysv/linux/x86/dl-exec-post.h b/sysdeps/unix/sysv/linux/x86/dl-exec-post.h\n> new file mode 100644\n> index 0000000000..0fa0b5e0e5\n> --- /dev/null\n> +++ b/sysdeps/unix/sysv/linux/x86/dl-exec-post.h\n> @@ -0,0 +1,22 @@\n> +/* DL_MAP_DEFAULT_THP_PAGESIZE.  Linux/x86 version.\n> +   Copyright (C) 2026 Free Software Foundation, Inc.\n> +   Copyright The GNU Toolchain Authors.\n> +   This file is part of the GNU C Library.\n> +\n> +   The GNU C Library is free software; you can redistribute it and/or\n> +   modify it under the terms of the GNU Lesser General Public\n> +   License as published by the Free Software Foundation; either\n> +   version 2.1 of the License, or (at your option) any later version.\n> +\n> +   The GNU C Library is distributed in the hope that it will be useful,\n> +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> +   Lesser General Public License for more details.\n> +\n> +   You should have received a copy of the GNU Lesser General Public\n> +   License along with the GNU C Library; if not, see\n> +   <https://www.gnu.org/licenses/>.  */\n> +\n> +#define DL_MAP_DEFAULT_THP_PAGESIZE (2 * 1024 * 1024)\n> +\n> +#include_next <dl-exec-post.h>\n> --\n> 2.53.0\n>\n\nThanks,\nRui","headers":{"Return-Path":"<libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org>","X-Original-To":["incoming@patchwork.ozlabs.org","libc-alpha@sourceware.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","libc-alpha@sourceware.org"],"Authentication-Results":["legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org;\n receiver=patchwork.ozlabs.org)","sourceware.org;\n dmarc=none (p=none dis=none) header.from=loongson.cn","sourceware.org; spf=pass smtp.mailfrom=loongson.cn","server2.sourceware.org;\n arc=none smtp.remote-ip=114.242.206.163"],"Received":["from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fxzpt5Y5Jz1yCv\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 18 Apr 2026 01:49:58 +1000 (AEST)","from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id B877E4CD200F\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 17 Apr 2026 15:49:56 +0000 (GMT)","from mail.loongson.cn (mail.loongson.cn [114.242.206.163])\n by sourceware.org (Postfix) with ESMTP id 2B3344BA2E3C\n for <libc-alpha@sourceware.org>; Fri, 17 Apr 2026 15:49:11 +0000 (GMT)","from loongson.cn (unknown [209.85.219.43])\n by gateway (Coremail) with SMTP id _____8AxJehyVuJpBYUBAA--.474S3;\n Fri, 17 Apr 2026 23:49:07 +0800 (CST)","from mail-qv1-f43.google.com (unknown [209.85.219.43])\n by front1 (Coremail) with SMTP id qMiowJBx58BtVuJpb3JvAA--.44503S2;\n Fri, 17 Apr 2026 23:49:02 +0800 (CST)","by mail-qv1-f43.google.com with SMTP id\n 6a1803df08f44-8a08fa355a1so11006656d6.0\n for <libc-alpha@sourceware.org>; Fri, 17 Apr 2026 08:49:02 -0700 (PDT)"],"DKIM-Filter":["OpenDKIM Filter v2.11.0 sourceware.org B877E4CD200F","OpenDKIM Filter v2.11.0 sourceware.org 2B3344BA2E3C"],"DMARC-Filter":"OpenDMARC Filter v1.4.2 sourceware.org 2B3344BA2E3C","ARC-Filter":"OpenARC Filter v1.0.0 sourceware.org 2B3344BA2E3C","ARC-Seal":"i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776440953; cv=none;\n b=NynAVk/3BmiWliP0uC0oiTtfZ//7ZY/PuTL9ADU9DKbBXLiMpRXRvscF0+FlL4JSQrhFUnFzgtbwD3Vjo+/pNj/NL8srP+DkeuXGexD7eFUkit9GbjOU3/IinyMwckp/Bmry3/jGyZklW7pfwE/1ntvsPnpTNkflaLlKK/9jjts=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776440953; c=relaxed/simple;\n bh=2QAPxFQsg/vXifRjrLVclYAN99iEJgkHXg5kp8+IzW8=;\n h=MIME-Version:From:Date:Message-ID:Subject:To;\n b=wIT7MitxAX6CJyMIP1M7x5uGvHhgHedlYKkpf0j/zb7la/VruuPMyuG+7p86m7SDezW13gQn9Px0fS/ctC8VfzQsqeYY3qY4jp5rTFE5oPxmwBDjJDOVGvafmEqxBRiq6TcqP8psG8j+jYxJnyu+E4g/W/Slnw+kgwLkMtBaQos=","ARC-Authentication-Results":"i=1; server2.sourceware.org","X-Gm-Message-State":"AOJu0YzdTwc99U0aeYkU5gykU5PEgnYcpA6767P0axwqKs3+DhBFHKO9\n N761zYMdhQPssUyTxdrJ2nwzOk5kIaftGsiwzm43slqpYpoKIp9XLggDtH0mgSsp3Xffbh8AUq8\n +bgGTEMNvP50w85azKavnoCPv89dtbQ+upN3tWQ0Dyg==","X-Received":"by 2002:a05:690e:1592:10b0:652:53cc:dfb3 with SMTP id\n 956f58d0204a3-65310afb82dmr2553192d50.52.1776440493670; Fri, 17 Apr 2026\n 08:41:33 -0700 (PDT)","MIME-Version":"1.0","References":"\n <CAMe9rOrVsKZz0MuqGwu1KX4MaFK=tc0idvk1kHy2+B8hOdLCVA@mail.gmail.com>\n <CAMe9rOryN0j-SZT_C4EYzEHt+B7kQTvC5t4GaQ3H8dPXG+aejg@mail.gmail.com>","In-Reply-To":"\n <CAMe9rOryN0j-SZT_C4EYzEHt+B7kQTvC5t4GaQ3H8dPXG+aejg@mail.gmail.com>","From":"WANG Rui <wangrui@loongson.cn>","Date":"Fri, 17 Apr 2026 23:41:21 +0800","X-Gmail-Original-Message-ID":"\n <CAHirt9hsXHVttvtkqkrF=WGn+K0h9_EeJpZnV5g1BpcJddYH2g@mail.gmail.com>","X-Gm-Features":"AQROBzAot-dr7kaVJQWyPelMASzSUmo46b-utMTj01fOpQjSAqidREwoOcnj8X4","Message-ID":"\n <CAHirt9hsXHVttvtkqkrF=WGn+K0h9_EeJpZnV5g1BpcJddYH2g@mail.gmail.com>","Subject":"Re: [PATCH v2 2/2] elf: Support THP segment load with madvise enabled\n THP","To":"\"H.J. Lu\" <hjl.tools@gmail.com>","Cc":"GNU C Library <libc-alpha@sourceware.org>","Content-Type":"text/plain; charset=\"UTF-8\"","Content-Transfer-Encoding":"quoted-printable","X-CM-TRANSID":"qMiowJBx58BtVuJpb3JvAA--.44503S2","X-CM-SenderInfo":"pzdqw2txl6z05rqj20fqof0/","X-Coremail-Antispam":"1Uk129KBj9fXoWDAr1kCF1DAF43ArWDJFWUtrc_yoW7Cw45Zo\n WfXF43XF4xGr1rJa13C39rJa12gr4Igr47Xa1UAr4xGr9YqF13CrWSya9xZrW3ur1F9F4x\n GFyrta43tF4FgFn3l-sFpf9Il3svdjkaLaAFLSUrUUUUUb8apTn2vfkv8UJUUUU8wcxFpf\n 9Il3svdxBIdaVrn0xqx4xG64xvF2IEw4CE5I8CrVC2j2Jv73VFW2AGmfu7bjvjm3AaLaJ3\n UjIYCTnIWjp_UUUYj7kC6x804xWl14x267AKxVWUJVW8JwAFc2x0x2IEx4CE42xK8VAvwI\n 8IcIk0rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xG\n Y2AK021l84ACjcxK6xIIjxv20xvE14v26r1j6r1xM28EF7xvwVC0I7IYx2IY6xkF7I0E14\n v26r1j6r4UM28EF7xvwVC2z280aVAFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIEc7CjxVAF\n wI0_Gr1j6F4UJwAS0I0E0xvYzxvE52x082IY62kv0487Mc804VCY07AIYIkI8VC2zVCFFI\n 0UMc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWUJVWUGwAv7VC2z280\n aVAFwI0_Jr0_Gr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcVAKI48JMxAIw28IcxkI7V\n AKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCj\n r7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUXVWUAwCIc40Y0x0EwIxGrwCI42IY6x\n IIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x0267AKxVWUJVW8JwCI42IY6xAI\n w20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z280aVCY1x\n 0267AKxVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa7IU1CPfJUUUUU==","X-BeenThere":"libc-alpha@sourceware.org","X-Mailman-Version":"2.1.30","Precedence":"list","List-Id":"Libc-alpha mailing list <libc-alpha.sourceware.org>","List-Unsubscribe":"<https://sourceware.org/mailman/options/libc-alpha>,\n <mailto:libc-alpha-request@sourceware.org?subject=unsubscribe>","List-Archive":"<https://sourceware.org/pipermail/libc-alpha/>","List-Post":"<mailto:libc-alpha@sourceware.org>","List-Help":"<mailto:libc-alpha-request@sourceware.org?subject=help>","List-Subscribe":"<https://sourceware.org/mailman/listinfo/libc-alpha>,\n <mailto:libc-alpha-request@sourceware.org?subject=subscribe>","Errors-To":"libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org"}},{"id":3678906,"web_url":"http://patchwork.ozlabs.org/comment/3678906/","msgid":"<CAMe9rOp-_96y0s=3yMi9_+8G_PsaagRAHrMqLqCHLY4QYK6XvQ@mail.gmail.com>","list_archive_url":null,"date":"2026-04-17T22:52:21","subject":"Re: [PATCH v2 2/2] elf: Support THP segment load with madvise enabled\n THP","submitter":{"id":4387,"url":"http://patchwork.ozlabs.org/api/people/4387/","name":"H.J. Lu","email":"hjl.tools@gmail.com"},"content":"On Fri, Apr 17, 2026 at 11:50 PM WANG Rui <wangrui@loongson.cn> wrote:\n>\n> On Fri, Apr 17, 2026 at 2:00 PM H.J. Lu <hjl.tools@gmail.com> wrote:\n> >\n> > On Fri, Apr 17, 2026 at 12:11 PM H.J. Lu <hjl.tools@gmail.com> wrote:\n> > >\n> > > The current THP segment load approach works only when THP is enabled\n> > > with always in the kernel.  If THP is enabled with madvise in the\n> > > kernel, to enable THP segment load in an application, madvise should\n> > > be called with MADV_HUGEPAGE on all THP eligible PT_LOAD segments:\n> > >\n> > > 1. Remove _dl_map_segment_align.  Call _dl_map_segment_adjust to adjust\n> > > alignments of PT_LOAD segments, which marks and aligns only THP eligible\n> > > PT_LOAD segments to THP page size when loading an object. This fixes\n> > > BZ #34079.\n> > > 2. Rename DL_MAP_DEFAULT_THP_PAGESIZE to DL_DEFAULT_THP_PAGESIZE.  If\n> > > DL_DEFAULT_THP_PAGESIZE is defined, assume that THP is enabled with\n> > > madvise in the kernel.  Otherwise, call __get_thp_size to get THP page\n> > > size and call __get_thp_mode to get THP mode.\n> > > 3. Call _dl_executable_postprocess in rtld_setup_main_map for dynamic\n> > > executables and in LIBC_START_MAIN for static executables, which calls\n> > > madvise with MADV_HUGEPAGE on all THP eligible PT_LOAD segments in\n> > > executable.  This fixes BZ #34080 for both dynamic and static executables.\n> > > 4. Call _dl_postprocess_loadcmd_extra in _dl_postprocess_loadcmd, which\n> > > calls madvise with MADV_HUGEPAGE on all THP eligible PT_LOAD segments\n> > > when loading an object after they have been mapped in.  This fixes\n> > > BZ #34080 for shared objects.\n> > > 5. Add tests to verify that large executable PT_LOAD segments in\n> > > executables and shared libraries are mapped at addresses aligned to THP\n> > > page size when the kernel is configured to use THP in \"always\" mode or\n> > > \"madvise\" mode by inspecting /proc/self/maps to check that the mapping\n> > > address is aligned to THP page size reported by the kernel [1].  Also\n> > > verify that madvise is called with MADV_HUGEPAGE when the glibc tunable\n> > > glibc.elf.thp=1 is used and madvise isn't called with MADV_HUGEPAGE when\n> > > the glibc tunable glibc.elf.thp=0 is used.\n> > >\n> > > Skip these tests if THP page size cannot be determined or if THP is not\n> > > enabled in \"always\" mode nor \"madvise\" mode.\n> > >\n> > > Quote WANG Rui <wangrui@loongson.cn>:\n> > >\n> > > From benchmarking a clang build of the Linux kernel on x86_64 with\n> > > your patch in THP madvise mode, I observed that iTLB misses were\n> > > reduced, similar to what we see in THP always mode.\n> > >\n> > > [1] This is developed by WANG Rui <wangrui@loongson.cn>.\n> > >\n> > > Signed-off-by: H.J. Lu <hjl.tools@gmail.com>\n> > > Co-developed-by: WANG Rui <wangrui@loongson.cn>\n> >\n> > Changes from v1:\n> >\n> > 1. Rebased against the v10 THP test patch from WANG Rui <wangrui@loongson.cn>.\n> > 2. Keep DL_MAP_DEFAULT_THP_PAGESIZE.\n> >\n> > --\n> > H.J.\n> > ---\n> > The current THP segment load approach works only when THP is enabled\n> > with always in the kernel.  If THP is enabled with madvise in the\n> > kernel, to enable THP segment load in an application, madvise should\n> > be called with MADV_HUGEPAGE on all THP eligible PT_LOAD segments:\n> >\n> > 1. Remove _dl_map_segment_align.  Call _dl_map_segment_adjust to adjust\n> > alignments of PT_LOAD segments, which marks and aligns only THP eligible\n> > PT_LOAD segments to THP page size when loading an object. This fixes\n> > BZ #34079.\n> > 2. Call _dl_executable_postprocess in rtld_setup_main_map for dynamic\n> > executables and in LIBC_START_MAIN for static executables, which calls\n> > madvise with MADV_HUGEPAGE on all THP eligible PT_LOAD segments in\n> > executable.  This fixes BZ #34080 for both dynamic and static executables.\n> > 3. Call _dl_postprocess_loadcmd_extra in _dl_postprocess_loadcmd, which\n> > calls madvise with MADV_HUGEPAGE on all THP eligible PT_LOAD segments\n> > when loading an object after they have been mapped in.  This fixes\n> > BZ #34080 for shared objects.\n> > 4. Add tests to verify that large executable PT_LOAD segments in\n> > executables and shared libraries are mapped at addresses aligned to THP\n> > page size when the kernel is configured to use THP in \"always\" mode or\n> > \"madvise\" mode by inspecting /proc/self/maps to check that the mapping\n> > address is aligned to THP page size reported by the kernel [1].  Also\n> > verify that madvise is called with MADV_HUGEPAGE when the glibc tunable\n> > glibc.elf.thp=1 is used and madvise isn't called with MADV_HUGEPAGE when\n> > the glibc tunable glibc.elf.thp=0 is used.\n> >\n> > Skip these tests if THP page size cannot be determined or if THP is not\n> > enabled in \"always\" mode nor \"madvise\" mode.\n> >\n> > Quote WANG Rui <wangrui@loongson.cn>:\n> >\n> > From benchmarking a clang build of the Linux kernel on x86_64 with\n> > your patch in THP madvise mode, I observed that iTLB misses were\n> > reduced, similar to what we see in THP always mode.\n> >\n> > [1] This is developed by WANG Rui <wangrui@loongson.cn>.\n> >\n> > Signed-off-by: H.J. Lu <hjl.tools@gmail.com>\n> > Co-developed-by: WANG Rui <wangrui@loongson.cn>\n> > ---\n> >  csu/libc-start.c                              |   4 +\n> >  elf/dl-load.c                                 |  10 +-\n> >  elf/dl-load.h                                 |   5 +\n> >  elf/dl-support.c                              |   6 +\n> >  elf/rtld.c                                    |  17 +--\n> >  sysdeps/generic/dl-exec-post.h                |  34 +++++\n> >  ...{dl-map-segment-align.h => dl-load-post.h} |   7 +-\n> >  sysdeps/generic/dl-map-segment-adjust.h       |  30 ++++\n> >  sysdeps/generic/hugepages.h                   |   4 +-\n> >  sysdeps/generic/ldsodefs.h                    |  11 ++\n> >  sysdeps/unix/sysv/linux/Makefile              | 124 +++++++++++++++-\n> >  sysdeps/unix/sysv/linux/dl-exec-post.h        |  95 +++++++++++++\n> >  sysdeps/unix/sysv/linux/dl-load-post.h        |  32 +++++\n> >  .../unix/sysv/linux/dl-map-segment-adjust.c   |  67 +++++++++\n> >  ...egment-align.h => dl-map-segment-adjust.h} |  10 +-\n> >  .../unix/sysv/linux/dl-map-segment-align.c    |  55 --------\n> >  sysdeps/unix/sysv/linux/ldsodefs.h            |   3 +\n> >  sysdeps/unix/sysv/linux/loongarch/Makefile    |   3 +\n> >  ...{dl-map-segment-align.h => dl-exec-post.h} |   4 +-\n> >  sysdeps/unix/sysv/linux/strace-tst-thp.sh     |  56 ++++++++\n> >  .../unix/sysv/linux/tst-thp-1-no-s-code-pde.c |  19 +++\n> >  .../sysv/linux/tst-thp-1-no-s-code-static.c   |  19 +++\n> >  sysdeps/unix/sysv/linux/tst-thp-1-no-s-code.c |  19 +++\n> >  sysdeps/unix/sysv/linux/tst-thp-1-pde.c       |  19 +++\n> >  sysdeps/unix/sysv/linux/tst-thp-1-static.c    |  19 +++\n> >  sysdeps/unix/sysv/linux/tst-thp-1.c           |  28 ++++\n> >  sysdeps/unix/sysv/linux/tst-thp-align-check.h | 132 ++++++++++++++++++\n> >  sysdeps/unix/sysv/linux/tst-thp-align.c       |  36 +++++\n> >  sysdeps/unix/sysv/linux/tst-thp-size-mod.S    |  24 ++++\n> >  sysdeps/unix/sysv/linux/x86/dl-exec-post.h    |  22 +++\n> >  30 files changed, 829 insertions(+), 85 deletions(-)\n> >  create mode 100644 sysdeps/generic/dl-exec-post.h\n> >  rename sysdeps/generic/{dl-map-segment-align.h => dl-load-post.h} (83%)\n> >  create mode 100644 sysdeps/generic/dl-map-segment-adjust.h\n> >  create mode 100644 sysdeps/unix/sysv/linux/dl-exec-post.h\n> >  create mode 100644 sysdeps/unix/sysv/linux/dl-load-post.h\n> >  create mode 100644 sysdeps/unix/sysv/linux/dl-map-segment-adjust.c\n> >  rename sysdeps/unix/sysv/linux/{dl-map-segment-align.h => dl-map-segment-adjust.h} (79%)\n> >  delete mode 100644 sysdeps/unix/sysv/linux/dl-map-segment-align.c\n> >  rename sysdeps/unix/sysv/linux/loongarch/lp64/{dl-map-segment-align.h => dl-exec-post.h} (90%)\n> >  create mode 100644 sysdeps/unix/sysv/linux/strace-tst-thp.sh\n> >  create mode 100644 sysdeps/unix/sysv/linux/tst-thp-1-no-s-code-pde.c\n> >  create mode 100644 sysdeps/unix/sysv/linux/tst-thp-1-no-s-code-static.c\n> >  create mode 100644 sysdeps/unix/sysv/linux/tst-thp-1-no-s-code.c\n> >  create mode 100644 sysdeps/unix/sysv/linux/tst-thp-1-pde.c\n> >  create mode 100644 sysdeps/unix/sysv/linux/tst-thp-1-static.c\n> >  create mode 100644 sysdeps/unix/sysv/linux/tst-thp-1.c\n> >  create mode 100644 sysdeps/unix/sysv/linux/tst-thp-align-check.h\n> >  create mode 100644 sysdeps/unix/sysv/linux/tst-thp-align.c\n> >  create mode 100644 sysdeps/unix/sysv/linux/tst-thp-size-mod.S\n> >  create mode 100644 sysdeps/unix/sysv/linux/x86/dl-exec-post.h\n> >\n> > diff --git a/csu/libc-start.c b/csu/libc-start.c\n> > index 1c58561bce..be60831a42 100644\n> > --- a/csu/libc-start.c\n> > +++ b/csu/libc-start.c\n> > @@ -205,6 +205,7 @@ call_fini (void *unused)\n> >  #endif /* !SHARED */\n> >\n> >  #include <libc-start.h>\n> > +#include <dl-exec-post.h>\n> >\n> >  STATIC int LIBC_START_MAIN (int (*main) (int, char **, char **\n> >  MAIN_AUXVEC_DECL),\n> > @@ -305,6 +306,9 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),\n> >    __pointer_chk_guard_local = pointer_chk_guard;\n> >  # endif\n> >\n> > +  struct link_map *main_map = _dl_get_dl_main_map ();\n> > +  _dl_executable_postprocess (main_map, GL(dl_phdr), GL(dl_phnum));\n> > +\n> >  #endif /* !SHARED  */\n> >\n> >    /* Register the destructor of the dynamic linker if there is any.  */\n> > diff --git a/elf/dl-load.c b/elf/dl-load.c\n> > index 48575fff06..800b7ca1a6 100644\n> > --- a/elf/dl-load.c\n> > +++ b/elf/dl-load.c\n> > @@ -71,7 +71,7 @@ struct filebuf\n> >  #include <dl-dst.h>\n> >  #include <dl-load.h>\n> >  #include <dl-map-segments.h>\n> > -#include <dl-map-segment-align.h>\n> > +#include <dl-map-segment-adjust.h>\n> >  #include <dl-unmap-segments.h>\n> >  #include <dl-machine-reject-phdr.h>\n> >  #include <dl-prop.h>\n> > @@ -1173,8 +1173,8 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,\n> >    /* Optimize a common case.  */\n> >    c->prot = pf_to_prot (ph->p_flags);\n> >\n> > -   /* Architecture-specific adjustment of segment alignment. */\n> > -   p_align_max = _dl_map_segment_align (c, p_align_max);\n> > +   /* Initialize flags.  */\n> > +   c->flags = 0;\n> >    break;\n> >\n> >  case PT_TLS:\n> > @@ -1229,9 +1229,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,\n> >  goto lose;\n> >        }\n> >\n> > -    /* Align all PT_LOAD segments to the maximum p_align.  */\n> > -    for (size_t i = 0; i < nloadcmds; i++)\n> > -      loadcmds[i].mapalign = p_align_max;\n> > +    _dl_map_segment_adjust (loadcmds, &nloadcmds, p_align_max);\n> >\n> >      /* dlopen of an executable is not valid because it is not possible\n> >         to perform proper relocations, handle static TLS, or run the\n> > diff --git a/elf/dl-load.h b/elf/dl-load.h\n> > index 897c4034c5..55edf0323c 100644\n> > --- a/elf/dl-load.h\n> > +++ b/elf/dl-load.h\n> > @@ -78,8 +78,11 @@ struct loadcmd\n> >    ElfW(Addr) mapstart, mapend, dataend, allocend, mapalign;\n> >    ElfW(Off) mapoff;\n> >    int prot;                             /* PROT_* bits.  */\n> > +  /* May be used by _dl_postprocess_loadcmd_extra.  */\n> > +  unsigned int flags;\n> >  };\n> >\n> > +#include <dl-load-post.h>\n> >\n> >  /* This is a subroutine of _dl_map_segments.  It should be called for each\n> >     load command, some time after L->l_addr has been set correctly.  It is\n> > @@ -95,6 +98,8 @@ _dl_postprocess_loadcmd (struct link_map *l, const ElfW(Ehdr) *header,\n> >      /* Found the program header in this segment.  */\n> >      l->l_phdr = (void *) (uintptr_t) (c->mapstart + header->e_phoff\n> >                                        - c->mapoff);\n> > +\n> > +  _dl_postprocess_loadcmd_extra (l, c);\n> >  }\n> >\n> >\n> > diff --git a/elf/dl-support.c b/elf/dl-support.c\n> > index 0508d6113b..420e418b40 100644\n> > --- a/elf/dl-support.c\n> > +++ b/elf/dl-support.c\n> > @@ -179,6 +179,12 @@ int _dl_stack_cache_lock;\n> >  #endif\n> >  struct dl_scope_free_list *_dl_scope_free_list;\n> >\n> > +#ifdef HAVE_THP\n> > +int _dl_thp_control = -1;\n> > +enum thp_mode_t _dl_thp_mode;\n> > +size_t _dl_thp_pagesize;\n> > +#endif\n> > +\n> >  #ifdef NEED_DL_SYSINFO\n> >  /* Needed for improved syscall handling on at least x86/Linux.  NB: Don't\n> >     initialize it here to avoid RELATIVE relocation in static PIE.  */\n> > diff --git a/elf/rtld.c b/elf/rtld.c\n> > index e926ec73e4..fe8d6f87e3 100644\n> > --- a/elf/rtld.c\n> > +++ b/elf/rtld.c\n> > @@ -52,6 +52,7 @@\n> >  #include <dl-find_object.h>\n> >  #include <dl-audit-check.h>\n> >  #include <dl-call_tls_init_tp.h>\n> > +#include <dl-exec-post.h>\n> >\n> >  #include <assert.h>\n> >\n> > @@ -323,6 +324,9 @@ struct rtld_global _rtld_global =\n> >      /* Generally the default presumption without further information is an\n> >       * executable stack but this is not true for all platforms.  */\n> >      ._dl_stack_prot_flags = DEFAULT_STACK_PROT_PERMS,\n> > +#ifdef HAVE_THP\n> > +    ._dl_thp_control = -1,\n> > +#endif\n> >  #ifdef _LIBC_REENTRANT\n> >      ._dl_load_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,\n> >      ._dl_load_write_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,\n> > @@ -1209,14 +1213,8 @@ rtld_setup_main_map (struct link_map *main_map)\n> >  main_map->l_relro_size = ph->p_memsz;\n> >  break;\n> >        }\n> > -  /* Process program headers again, but scan them backwards since\n> > -     PT_GNU_PROPERTY is close to the end of program headers.   */\n> > -  for (const ElfW(Phdr) *ph = &phdr[phnum]; ph != phdr; --ph)\n> > -    if (ph[-1].p_type == PT_GNU_PROPERTY)\n> > -      {\n> > - _dl_process_pt_gnu_property (main_map, -1, &ph[-1]);\n> > - break;\n> > -      }\n> > +\n> > +  _dl_executable_postprocess (main_map, phdr, phnum);\n> >\n> >    /* Adjust the address of the TLS initialization image in case\n> >       the executable is actually an ET_DYN object.  */\n> > @@ -1589,6 +1587,9 @@ dl_main (const ElfW(Phdr) *phdr,\n> >  {\n> >    RTLD_TIMING_VAR (start);\n> >    rtld_timer_start (&start);\n> > +#ifdef HAVE_THP\n> > +   _dl_get_thp_config ();\n> > +#endif\n> >    _dl_map_object (NULL, rtld_progname, lt_executable, 0,\n> >    __RTLD_OPENEXEC, LM_ID_BASE);\n> >    rtld_timer_stop (&load_time, start);\n> > diff --git a/sysdeps/generic/dl-exec-post.h b/sysdeps/generic/dl-exec-post.h\n> > new file mode 100644\n> > index 0000000000..f5dcdc093a\n> > --- /dev/null\n> > +++ b/sysdeps/generic/dl-exec-post.h\n> > @@ -0,0 +1,34 @@\n> > +/* _dl_executable_postprocess.  Generic version.\n> > +   Copyright (C) 2026 Free Software Foundation, Inc.\n> > +   Copyright The GNU Toolchain Authors.\n> > +   This file is part of the GNU C Library.\n> > +\n> > +   The GNU C Library is free software; you can redistribute it and/or\n> > +   modify it under the terms of the GNU Lesser General Public\n> > +   License as published by the Free Software Foundation; either\n> > +   version 2.1 of the License, or (at your option) any later version.\n> > +\n> > +   The GNU C Library is distributed in the hope that it will be useful,\n> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> > +   Lesser General Public License for more details.\n> > +\n> > +   You should have received a copy of the GNU Lesser General Public\n> > +   License along with the GNU C Library; if not, see\n> > +   <https://www.gnu.org/licenses/>.  */\n> > +\n> > +static inline void\n> > +_dl_executable_postprocess (struct link_map *main_map,\n> > +     const ElfW(Phdr) *phdr, ElfW(Word) phnum)\n> > +{\n> > +#ifdef SHARED\n> > +  /* Process program headers again, but scan them backwards since\n> > +     PT_GNU_PROPERTY is close to the end of program headers.   */\n> > +  for (const ElfW(Phdr) *ph = &phdr[phnum]; ph != phdr; --ph)\n> > +    if (ph[-1].p_type == PT_GNU_PROPERTY)\n> > +      {\n> > + _dl_process_pt_gnu_property (main_map, -1, &ph[-1]);\n> > + break;\n> > +      }\n> > +#endif\n> > +}\n> > diff --git a/sysdeps/generic/dl-map-segment-align.h b/sysdeps/generic/dl-load-post.h\n> > similarity index 83%\n> > rename from sysdeps/generic/dl-map-segment-align.h\n> > rename to sysdeps/generic/dl-load-post.h\n> > index f4a671f25f..bfaad8ea7c 100644\n> > --- a/sysdeps/generic/dl-map-segment-align.h\n> > +++ b/sysdeps/generic/dl-load-post.h\n> > @@ -1,4 +1,4 @@\n> > -/* _dl_map_segment_align.  Generic version.\n> > +/* _dl_postprocess_loadcmd_extra.  Generic version.\n> >     Copyright (C) 2026 Free Software Foundation, Inc.\n> >     Copyright The GNU Toolchain Authors.\n> >     This file is part of the GNU C Library.\n> > @@ -19,8 +19,7 @@\n> >\n> >  #include <dl-load.h>\n> >\n> > -static inline ElfW(Addr)\n> > -_dl_map_segment_align (const struct loadcmd *c, ElfW(Addr) p_align_max)\n> > +static inline void\n> > +_dl_postprocess_loadcmd_extra (struct link_map *l, const struct loadcmd *c)\n> >  {\n> > -  return p_align_max;\n> >  }\n> > diff --git a/sysdeps/generic/dl-map-segment-adjust.h b/sysdeps/generic/dl-map-segment-adjust.h\n> > new file mode 100644\n> > index 0000000000..b48057ec26\n> > --- /dev/null\n> > +++ b/sysdeps/generic/dl-map-segment-adjust.h\n> > @@ -0,0 +1,30 @@\n> > +/* _dl_map_segment_adjust.  Generic version.\n> > +   Copyright (C) 2026 Free Software Foundation, Inc.\n> > +   Copyright The GNU Toolchain Authors.\n> > +   This file is part of the GNU C Library.\n> > +\n> > +   The GNU C Library is free software; you can redistribute it and/or\n> > +   modify it under the terms of the GNU Lesser General Public\n> > +   License as published by the Free Software Foundation; either\n> > +   version 2.1 of the License, or (at your option) any later version.\n> > +\n> > +   The GNU C Library is distributed in the hope that it will be useful,\n> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> > +   Lesser General Public License for more details.\n> > +\n> > +   You should have received a copy of the GNU Lesser General Public\n> > +   License along with the GNU C Library; if not, see\n> > +   <https://www.gnu.org/licenses/>.  */\n> > +\n> > +#include <dl-load.h>\n> > +\n> > +static inline void\n> > +_dl_map_segment_adjust (struct loadcmd *load_cmds,\n> > + size_t *n_load_cmds, ElfW(Addr) p_align_max)\n> > +{\n> > +  /* Align all PT_LOAD segments to the maximum p_align.  */\n> > +  size_t n = *n_load_cmds;\n> > +  for (size_t i = 0; i < n; i++)\n> > +    load_cmds[i].mapalign = p_align_max;\n> > +}\n> > diff --git a/sysdeps/generic/hugepages.h b/sysdeps/generic/hugepages.h\n> > index 5fc9b5c8de..df9ec4920b 100644\n> > --- a/sysdeps/generic/hugepages.h\n> > +++ b/sysdeps/generic/hugepages.h\n> > @@ -26,10 +26,10 @@ unsigned long int __get_thp_size (void) attribute_hidden;\n> >\n> >  enum thp_mode_t\n> >  {\n> > +  thp_mode_not_supported = 0,\n> >    thp_mode_always,\n> >    thp_mode_madvise,\n> > -  thp_mode_never,\n> > -  thp_mode_not_supported\n> > +  thp_mode_never\n> >  };\n> >\n> >  enum thp_mode_t __get_thp_mode (void) attribute_hidden;\n> > diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h\n> > index 15c4659853..36f2e88ae4 100644\n> > --- a/sysdeps/generic/ldsodefs.h\n> > +++ b/sysdeps/generic/ldsodefs.h\n> > @@ -39,6 +39,7 @@\n> >  #include <libc-lock.h>\n> >  #include <hp-timing.h>\n> >  #include <list_t.h>\n> > +#include <hugepages.h>\n> >\n> >  __BEGIN_DECLS\n> >\n> > @@ -477,6 +478,16 @@ struct rtld_global\n> >    EXTERN struct __pthread **_dl_pthread_threads;\n> >    __mach_rwlock_define (EXTERN, _dl_pthread_threads_lock)\n> >  #endif\n> > +#ifdef HAVE_THP\n> > +  /* The THP segment load control:\n> > +      > 0: Enabled by GLIBC_TUNABLES=glibc.elf.thp=1.\n> > +        0: Disabled by GLIBC_TUNABLES=glibc.elf.thp=0.\n> > +      < 0: To be enabled or disabled by GLIBC_TUNABLES.  */\n>\n> I think we need to treat THP-always and THP-madvise differently. For\n> always, it seems reasonable to let an architecture enable\n> `glibc.elf.thp` by default. But for madvise, it should be opt-in only.\n\nWhen DL_MAP_DEFAULT_THP_PAGESIZE is defined, we assume\nTHP is enabled with madvise conversatively  I will change\n _dl_get_thp_config to\n\n  GL(dl_thp_pagesize) = __get_thp_size ();\n  GL(dl_thp_mode) = __get_thp_mode ();\n  /* We cap the huge page size at MAX_THP_PAGESIZE to avoid over-aligning\n     on systems with very large normal pages (like 64K pages with 512M\n     huge pages).  */\n  if (GL(dl_thp_pagesize) > MAX_THP_PAGESIZE)\n    GL(dl_thp_control) = 0;\n  /* NB: Enable THP if THP is always enabled in the kernel. */\n  else if (GL(dl_thp_mode) == thp_mode_always)\n    GL(dl_thp_control) = 1;\n\n> > +  EXTERN int _dl_thp_control;\n> > +\n> > +  EXTERN enum thp_mode_t _dl_thp_mode;\n> > +  EXTERN size_t _dl_thp_pagesize;\n> > +#endif\n> >  #ifdef SHARED\n> >  };\n> >  # define __rtld_global_attribute__\n> > diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile\n> > index b06afbdeaa..41d321c564 100644\n> > --- a/sysdeps/unix/sysv/linux/Makefile\n> > +++ b/sysdeps/unix/sysv/linux/Makefile\n> > @@ -673,7 +673,7 @@ endif\n> >\n> >  ifeq ($(subdir),elf)\n> >  dl-routines += \\\n> > -  dl-map-segment-align \\\n> > +  dl-map-segment-adjust \\\n> >    dl-rseq-symbols \\\n> >    # dl-routines\n> >\n> > @@ -698,13 +698,19 @@ $(objpfx)pldd: $(objpfx)xmalloc.o\n> >  tests += \\\n> >    tst-rseq-tls-range \\\n> >    tst-rseq-tls-range-4096 \\\n> > +  tst-thp-1 \\\n> > +  tst-thp-1-pde \\\n> > +  tst-thp-1-static \\\n> > +  tst-thp-align \\\n> >  # tests\n> >  tests-static += \\\n> >    tst-rseq-tls-range-4096-static \\\n> >    tst-rseq-tls-range-static \\\n> > +  tst-thp-1-static \\\n> >  # tests-static\n> >  modules-names += \\\n> >    tst-rseq-tls-range-mod \\\n> > +  tst-thp-size-mod \\\n> >  # modules-names\n> >  CFLAGS-tst-rseq-tls-range.c += -DMAIN_TLS_ALIGN=4\n> >  CFLAGS-tst-rseq-tls-range-4096.c += -DMAIN_TLS_ALIGN=4096\n> > @@ -724,6 +730,122 @@ tests-special += \\\n> >    $(objpfx)tst-nolink-libc-2.out \\\n> >    # tests-special\n> >  endif\n> > +\n> > +ifndef THP-PAGE-SIZE\n> > +# Align PT_LOAD segments in THP tests to THP page size so that kernel will\n> > +# map PIE to the address aligned to THP page size.  Default THP page size\n> > +# to 2MB which can be overridden in Makefile in subdirectories.\n> > +THP-PAGE-SIZE = 0x200000\n> > +endif\n> > +\n> > +THP-PAGE-SIZE-LDFLAGS = -Wl,-z,max-page-size=$(THP-PAGE-SIZE)\n> > +\n> > +LDFLAGS-tst-thp-size-mod.so = $(THP-PAGE-SIZE-LDFLAGS)\n> > +tst-thp-align-ENV = GLIBC_TUNABLES=glibc.elf.thp=1\n> > +$(objpfx)tst-thp-align.out: $(objpfx)tst-thp-size-mod.so\n> > +\n> > +ifeq ($(have-separate-code),yes)\n> > +tests += \\\n> > +  tst-thp-1-no-s-code \\\n> > +  tst-thp-1-no-s-code-pde \\\n> > +  tst-thp-1-no-s-code-static \\\n> > +# tests\n> > +tests-static += \\\n> > +  tst-thp-1-no-s-code-static \\\n> > +# tests-static\n> > +\n> > +LDFLAGS-tst-thp-1 = -Wl,-z,separate-code $(THP-PAGE-SIZE-LDFLAGS)\n> > +LDFLAGS-tst-thp-1-pde = -Wl,-z,separate-code $(THP-PAGE-SIZE-LDFLAGS)\n> > +LDFLAGS-tst-thp-1-static = -Wl,-z,separate-code $(THP-PAGE-SIZE-LDFLAGS)\n> > +LDFLAGS-tst-thp-1-no-s-code = -Wl,-z,noseparate-code \\\n> > +       $(THP-PAGE-SIZE-LDFLAGS)\n> > +LDFLAGS-tst-thp-1-no-s-code-pde = -Wl,-z,noseparate-code \\\n> > +   $(THP-PAGE-SIZE-LDFLAGS)\n> > +LDFLAGS-tst-thp-1-no-s-code-static = -Wl,-z,noseparate-code \\\n> > +      $(THP-PAGE-SIZE-LDFLAGS)\n> > +\n> > +$(objpfx)tst-thp-1-no-s-code: $(objpfx)tst-thp-size-mod.o\n> > +$(objpfx)tst-thp-1-no-s-code-pde: $(objpfx)tst-thp-size-mod.o\n> > +$(objpfx)tst-thp-1-no-s-code-static: $(objpfx)tst-thp-size-mod.o\n> > +\n> > +tst-thp-1-no-s-code-ENV = GLIBC_TUNABLES=glibc.elf.thp=1\n> > +tst-thp-1-no-s-code-pde-ENV = GLIBC_TUNABLES=glibc.elf.thp=1\n> > +tst-thp-1-no-s-code-static-ENV = GLIBC_TUNABLES=glibc.elf.thp=1\n> > +\n> > +tst-thp-1-no-s-code-pde-no-pie = yes\n> > +endif\n> > +\n> > +tst-thp-1-ENV = GLIBC_TUNABLES=glibc.elf.thp=1\n> > +tst-thp-1-pde-ENV = GLIBC_TUNABLES=glibc.elf.thp=1\n> > +tst-thp-1-static-ENV = GLIBC_TUNABLES=glibc.elf.thp=1\n> > +\n> > +$(objpfx)tst-thp-1: $(objpfx)tst-thp-size-mod.o\n> > +$(objpfx)tst-thp-1-pde: $(objpfx)tst-thp-size-mod.o\n> > +$(objpfx)tst-thp-1-static: $(objpfx)tst-thp-size-mod.o\n> > +\n> > +tst-thp-1-pde-no-pie = yes\n> > +\n> > +thp-kernel-status = $(shell grep madvise /sys/kernel/mm/transparent_hugepage/enabled)\n> > +# Verify that madvise is called with MADV_HUGEPAGE when THP is enabled\n> > +# under madvise THP kernel.\n> > +ifneq ($(findstring [madvise],$(thp-kernel-status)),)\n> > +tests-special += \\\n> > +  $(objpfx)strace-tst-thp-1-disabled.out \\\n> > +  $(objpfx)strace-tst-thp-1-enabled.out \\\n> > +  $(objpfx)strace-tst-thp-1-pde-disabled.out \\\n> > +  $(objpfx)strace-tst-thp-1-pde-enabled.out \\\n> > +  $(objpfx)strace-tst-thp-1-static-disabled.out \\\n> > +  $(objpfx)strace-tst-thp-1-static-enabled.out \\\n> > +# tests-special\n> > +\n> > +$(objpfx)strace-tst-thp-1-enabled.out: \\\n> > +  $(..)sysdeps/unix/sysv/linux/strace-tst-thp.sh $(objpfx)ld.so \\\n> > +  $(objpfx)tst-thp-1\n> > + $(SHELL) $< $(objpfx)ld.so '$(test-wrapper-env)' \\\n> > + '$(run-program-env) GLIBC_TUNABLES=glibc.elf.thp=1' \\\n> > + '$(rpath-link)' $(objpfx)tst-thp-1 > $@;\n> > +   $(evaluate-test)\n> > +\n> > +$(objpfx)strace-tst-thp-1-disabled.out: \\\n> > +  $(..)sysdeps/unix/sysv/linux/strace-tst-thp.sh $(objpfx)ld.so \\\n> > +  $(objpfx)tst-thp-1\n> > + $(SHELL) $< $(objpfx)ld.so '$(test-wrapper-env)' \\\n> > + '$(run-program-env) GLIBC_TUNABLES=glibc.elf.thp=0' \\\n> > + '$(rpath-link)' $(objpfx)tst-thp-1 > $@;\n> > +   $(evaluate-test)\n> > +\n> > +$(objpfx)strace-tst-thp-1-pde-enabled.out: \\\n> > +  $(..)sysdeps/unix/sysv/linux/strace-tst-thp.sh $(objpfx)ld.so \\\n> > +  $(objpfx)tst-thp-1-pde\n> > + $(SHELL) $< $(objpfx)ld.so '$(test-wrapper-env)' \\\n> > + '$(run-program-env) GLIBC_TUNABLES=glibc.elf.thp=1' \\\n> > + '$(rpath-link)' $(objpfx)tst-thp-1-pde > $@; \\\n> > +   $(evaluate-test)\n> > +\n> > +$(objpfx)strace-tst-thp-1-pde-disabled.out: \\\n> > +  $(..)sysdeps/unix/sysv/linux/strace-tst-thp.sh $(objpfx)ld.so \\\n> > +  $(objpfx)tst-thp-1-pde\n> > + $(SHELL) $< $(objpfx)ld.so '$(test-wrapper-env)' \\\n> > + '$(run-program-env) GLIBC_TUNABLES=glibc.elf.thp=0' \\\n> > + '$(rpath-link)' $(objpfx)tst-thp-1-pde > $@; \\\n> > +   $(evaluate-test)\n> > +\n> > +$(objpfx)strace-tst-thp-1-static-enabled.out: \\\n> > +  $(..)sysdeps/unix/sysv/linux/strace-tst-thp.sh $(objpfx)ld.so \\\n> > +  $(objpfx)tst-thp-1-static\n> > + $(SHELL) $< $(objpfx)ld.so '$(test-wrapper-env)' \\\n> > + '$(run-program-env) GLIBC_TUNABLES=glibc.elf.thp=1' \\\n> > + '$(rpath-link)' $(objpfx)tst-thp-1-static > $@; \\\n> > +   $(evaluate-test)\n> > +\n> > +$(objpfx)strace-tst-thp-1-static-disabled.out: \\\n> > +  $(..)sysdeps/unix/sysv/linux/strace-tst-thp.sh $(objpfx)ld.so \\\n> > +  $(objpfx)tst-thp-1-static\n> > + $(SHELL) $< $(objpfx)ld.so '$(test-wrapper-env)' \\\n> > + '$(run-program-env) GLIBC_TUNABLES=glibc.elf.thp=0' \\\n> > + '$(rpath-link)' $(objpfx)tst-thp-1-static > $@; \\\n> > +   $(evaluate-test)\n> > +endif\n> >  endif # $(subdir) == elf\n> >\n> >  ifeq ($(subdir),rt)\n> > diff --git a/sysdeps/unix/sysv/linux/dl-exec-post.h b/sysdeps/unix/sysv/linux/dl-exec-post.h\n> > new file mode 100644\n> > index 0000000000..1ef1f6556e\n> > --- /dev/null\n> > +++ b/sysdeps/unix/sysv/linux/dl-exec-post.h\n> > @@ -0,0 +1,95 @@\n> > +/* _dl_executable_postprocess.  Linux version.\n> > +   Copyright (C) 2026 Free Software Foundation, Inc.\n> > +   Copyright The GNU Toolchain Authors.\n> > +   This file is part of the GNU C Library.\n> > +\n> > +   The GNU C Library is free software; you can redistribute it and/or\n> > +   modify it under the terms of the GNU Lesser General Public\n> > +   License as published by the Free Software Foundation; either\n> > +   version 2.1 of the License, or (at your option) any later version.\n> > +\n> > +   The GNU C Library is distributed in the hope that it will be useful,\n> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> > +   Lesser General Public License for more details.\n> > +\n> > +   You should have received a copy of the GNU Lesser General Public\n> > +   License along with the GNU C Library; if not, see\n> > +   <https://www.gnu.org/licenses/>.  */\n> > +\n> > +static inline void\n> > +_dl_get_thp_config (void)\n> > +{\n> > +  /* Check if there is GLIBC_TUNABLES=glibc.elf.thp=[0|1].  */\n> > +  if (TUNABLE_IS_INITIALIZED_FULL (glibc, elf, thp))\n> > +    GL(dl_thp_control) = TUNABLE_GET_FULL (glibc, elf, thp, int32_t,\n> > +    NULL);\n> > +\n> > +  /* Return if THP is disabled by GLIBC_TUNABLES=glibc.elf.thp=0.  */\n> > +  if (GL(dl_thp_control) == 0)\n> > +    return;\n> > +\n> > +#ifdef DL_MAP_DEFAULT_THP_PAGESIZE\n> > +  /* NB: Accessing /sys/kernel/mm files is quite expensive and the file\n> > +     may not be accessible in containers.  If DL_MAP_DEFAULT_THP_PAGESIZE\n> > +     is defined, assume THP mode is madvise and always call madvise.\n> > +     Since madvise is a fast systemcall, it adds only a small overhead\n> > +     compared to the cost of accessing /sys/kernel/mm files.  */\n> > +  GL(dl_thp_pagesize) = DL_MAP_DEFAULT_THP_PAGESIZE;\n> > +  GL(dl_thp_mode) = thp_mode_madvise;\n> > +#else\n> > +  GL(dl_thp_pagesize) = __get_thp_size ();\n> > +  GL(dl_thp_mode) = __get_thp_mode ();\n> > +#endif\n> > +}\n> > +\n> > +static inline void\n> > +_dl_executable_postprocess (struct link_map *main_map,\n> > +     const ElfW(Phdr) *phdr, ElfW(Word) phnum)\n> > +{\n> > +  if (GL(dl_thp_control) == -1)\n> > +    _dl_get_thp_config ();\n> > +\n> > +  /* NB: In static executable, PT_GNU_PROPERTY is processed in target\n> > +     libc-start.h if it is needed by target.  When ld.so is used, if\n> > +     a target doesn't need PT_GNU_PROPERTY, _dl_process_pt_gnu_property\n> > +     is an empty function.  */\n> > +#ifdef SHARED\n> > +  /* Process program headers again, but scan them backwards since\n> > +     PT_GNU_PROPERTY is close to the end of program headers.   */\n> > +  for (const ElfW(Phdr) *ph = &phdr[phnum]; ph != phdr; --ph)\n> > +    if (ph[-1].p_type == PT_GNU_PROPERTY)\n> > +      {\n> > + _dl_process_pt_gnu_property (main_map, -1, &ph[-1]);\n> > + break;\n> > +      }\n> > +#endif\n> > +\n> > +  /* Return if THP segment load isn't enabled.  */\n> > +  if (GL(dl_thp_control) <= 0)\n> > +    return;\n> > +\n> > +#ifndef DL_MAP_DEFAULT_THP_PAGESIZE\n> > +  /* NB: If DL_MAP_DEFAULT_THP_PAGESIZE is defined, dl_thp_mode is always\n> > +     set to thp_mode_madvise.  */\n> > +  if (GL(dl_thp_mode) != thp_mode_madvise)\n> > +    return;\n> > +#endif\n> > +\n> > +  /* When we get here, the main executable have been mapped in.  Call\n> > +     madvise with MADV_HUGEPAGE for all THP eligible PT_LOAD segments.  */\n> > +\n> > +  const ElfW(Phdr) *ph;\n> > +\n> > +  size_t thp_pagesize = GL(dl_thp_pagesize);\n> > +\n> > +  /* Call __madvise if offset and address of the PT_LOAD segment are\n> > +     aligned to THP page size and it is read-only.  */\n> > +  for (ph = phdr; ph < &phdr[phnum]; ++ph)\n> > +    if (ph->p_type == PT_LOAD\n> > + && ph->p_memsz >= thp_pagesize\n> > + && ((ph->p_vaddr | ph->p_offset) & (thp_pagesize - 1)) == 0\n> > + && (ph->p_flags & (PF_W | PF_R)) == PF_R)\n> > +      __madvise ((void *) (main_map->l_addr + ph->p_vaddr),\n> > + ph->p_memsz, MADV_HUGEPAGE);\n> > +}\n> > diff --git a/sysdeps/unix/sysv/linux/dl-load-post.h b/sysdeps/unix/sysv/linux/dl-load-post.h\n> > new file mode 100644\n> > index 0000000000..b3c4e16bb7\n> > --- /dev/null\n> > +++ b/sysdeps/unix/sysv/linux/dl-load-post.h\n> > @@ -0,0 +1,32 @@\n> > +/* _dl_postprocess_loadcmd_extra.  Linux version.\n> > +   Copyright (C) 2026 Free Software Foundation, Inc.\n> > +   Copyright The GNU Toolchain Authors.\n> > +   This file is part of the GNU C Library.\n> > +\n> > +   The GNU C Library is free software; you can redistribute it and/or\n> > +   modify it under the terms of the GNU Lesser General Public\n> > +   License as published by the Free Software Foundation; either\n> > +   version 2.1 of the License, or (at your option) any later version.\n> > +\n> > +   The GNU C Library is distributed in the hope that it will be useful,\n> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> > +   Lesser General Public License for more details.\n> > +\n> > +   You should have received a copy of the GNU Lesser General Public\n> > +   License along with the GNU C Library; if not, see\n> > +   <https://www.gnu.org/licenses/>.  */\n> > +\n> > +/* Bits in the flags field of struct loadcmd.  */\n> > +#define LOADCMD_POST_MADVISE_THP (0x1 << 0)\n> > +\n> > +/* After L has been mapped in, call madvise with MADV_HUGEPAGE if L is\n> > +   THP eligible.  */\n> > +\n> > +static inline void\n> > +_dl_postprocess_loadcmd_extra (struct link_map *l, const struct loadcmd *c)\n> > +{\n> > +  if ((c->flags & LOADCMD_POST_MADVISE_THP) != 0)\n> > +    __madvise ((void *) (l->l_addr + c->mapstart),\n> > +        c->mapend - c->mapstart, MADV_HUGEPAGE);\n> > +}\n> > diff --git a/sysdeps/unix/sysv/linux/dl-map-segment-adjust.c b/sysdeps/unix/sysv/linux/dl-map-segment-adjust.c\n> > new file mode 100644\n> > index 0000000000..90c8ea92fe\n> > --- /dev/null\n> > +++ b/sysdeps/unix/sysv/linux/dl-map-segment-adjust.c\n> > @@ -0,0 +1,67 @@\n> > +/* _dl_map_segment_adjust.  Linux version.\n> > +   Copyright (C) 2026 Free Software Foundation, Inc.\n> > +   Copyright The GNU Toolchain Authors.\n> > +   This file is part of the GNU C Library.\n> > +\n> > +   The GNU C Library is free software; you can redistribute it and/or\n> > +   modify it under the terms of the GNU Lesser General Public\n> > +   License as published by the Free Software Foundation; either\n> > +   version 2.1 of the License, or (at your option) any later version.\n> > +\n> > +   The GNU C Library is distributed in the hope that it will be useful,\n> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> > +   Lesser General Public License for more details.\n> > +\n> > +   You should have received a copy of the GNU Lesser General Public\n> > +   License along with the GNU C Library; if not, see\n> > +   <https://www.gnu.org/licenses/>.  */\n> > +\n> > +#include <ldsodefs.h>\n> > +#include <dl-map-segment-adjust.h>\n> > +\n> > +/* Set the mapalign field in entries in LOAD_CMDS to align PT_LOAD\n> > +   segments for THP.  P_ALIGN_MAX is the maximum p_align value in all\n> > +   PT_LOAD segments.  */\n> > +\n> > +void\n> > +_dl_map_segment_adjust (struct loadcmd *load_cmds, size_t *n_load_cmds,\n> > + ElfW(Addr) p_align_max)\n>\n> size_t n_load_cmds?\n\nFixed.\n\n> > +{\n> > +  size_t n = *n_load_cmds;\n> > +  size_t i;\n> > +  enum thp_mode_t thp_mode = GL(dl_thp_mode);\n> > +  size_t thp_pagesize = GL(dl_thp_pagesize);\n> > +  struct loadcmd *c = load_cmds;\n> > +\n> > +  if (n == 0)\n> > +    return;\n> > +\n> > +  /* We cap the huge page size at MAX_THP_PAGESIZE to avoid over-aligning\n> > +     on systems with very large normal pages (like 64K pages with 512M\n> > +     huge pages).  */\n> > +  if (GL(dl_thp_control) <= 0\n> > +      || p_align_max >= thp_pagesize\n> > +      || !(thp_mode == thp_mode_always || thp_mode == thp_mode_madvise))\n>\n> Missing a check for MAX_THP_PAGESIZE?\n\nSee the _dl_get_thp_config change above.\n\n> > +    {\n> > +      for (i = 0; i < n; i++, c++)\n> > + c->mapalign = p_align_max;\n> > +      return;\n> > +    }\n> > +\n> > +  /* Set the mapalign field to THP page size only if offset and address\n> > +     of the segment are aligned to THP page size, it is read-only and\n> > +     its size >= THP page size.  It helps improve THP eligibility and\n> > +     reduces TLB pressure.  */\n> > +  for (i = 0; i < n; i++, c++)\n> > +    if (((c->mapstart | c->mapoff) & (thp_pagesize - 1)) == 0\n> > + && (c->mapend - c->mapstart) >= thp_pagesize\n> > + && (c->prot & PROT_WRITE) == 0)\n> > +      {\n> > + c->mapalign = thp_pagesize;\n> > + if (thp_mode == thp_mode_madvise)\n> > +   c->flags = LOADCMD_POST_MADVISE_THP;\n> > +      }\n> > +    else\n> > +      c->mapalign = p_align_max;\n> > +}\n> > diff --git a/sysdeps/unix/sysv/linux/dl-map-segment-align.h b/sysdeps/unix/sysv/linux/dl-map-segment-adjust.h\n> > similarity index 79%\n> > rename from sysdeps/unix/sysv/linux/dl-map-segment-align.h\n> > rename to sysdeps/unix/sysv/linux/dl-map-segment-adjust.h\n>\n> Why rename this hook?\n\nI will keep the name, but change and move it.\n\n>\n> > index d9b05181b7..2fbfc66d48 100644\n> > --- a/sysdeps/unix/sysv/linux/dl-map-segment-align.h\n> > +++ b/sysdeps/unix/sysv/linux/dl-map-segment-adjust.h\n> > @@ -1,4 +1,4 @@\n> > -/* _dl_map_segment_align.  Linux version.\n> > +/* _dl_map_segment_adjust.  Linux version.\n> >     Copyright (C) 2026 Free Software Foundation, Inc.\n> >     Copyright The GNU Toolchain Authors.\n> >     This file is part of the GNU C Library.\n> > @@ -19,9 +19,5 @@\n> >\n> >  #include <dl-load.h>\n> >\n> > -#ifndef DL_MAP_DEFAULT_THP_PAGESIZE\n> > -# define DL_MAP_DEFAULT_THP_PAGESIZE 0\n> > -#endif\n> > -\n> > -extern ElfW (Addr) _dl_map_segment_align\n> > -  (const struct loadcmd *, ElfW (Addr)) attribute_hidden;\n> > +extern void _dl_map_segment_adjust\n> > +  (struct loadcmd *, size_t *, ElfW(Addr)) attribute_hidden;\n> > diff --git a/sysdeps/unix/sysv/linux/dl-map-segment-align.c b/sysdeps/unix/sysv/linux/dl-map-segment-align.c\n> > deleted file mode 100644\n> > index a39e74d91b..0000000000\n> > --- a/sysdeps/unix/sysv/linux/dl-map-segment-align.c\n> > +++ /dev/null\n> > @@ -1,55 +0,0 @@\n> > -/* _dl_map_segment_align.  Linux version.\n> > -   Copyright (C) 2026 Free Software Foundation, Inc.\n> > -   Copyright The GNU Toolchain Authors.\n> > -   This file is part of the GNU C Library.\n> > -\n> > -   The GNU C Library is free software; you can redistribute it and/or\n> > -   modify it under the terms of the GNU Lesser General Public\n> > -   License as published by the Free Software Foundation; either\n> > -   version 2.1 of the License, or (at your option) any later version.\n> > -\n> > -   The GNU C Library is distributed in the hope that it will be useful,\n> > -   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> > -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> > -   Lesser General Public License for more details.\n> > -\n> > -   You should have received a copy of the GNU Lesser General Public\n> > -   License along with the GNU C Library; if not, see\n> > -   <https://www.gnu.org/licenses/>.  */\n> > -\n> > -#include <dl-map-segment-align.h>\n> > -#include <dl-tunables.h>\n> > -#include <hugepages.h>\n> > -\n> > -ElfW (Addr)\n> > -_dl_map_segment_align (const struct loadcmd *c, ElfW (Addr) p_align_max)\n> > -{\n> > -  static enum thp_mode_t thp_mode = thp_mode_not_supported;\n> > -  static unsigned long int thp_pagesize;\n> > -\n> > -  if (TUNABLE_GET (glibc, elf, thp, int32_t, NULL) == 0)\n> > -    return p_align_max;\n> > -\n> > -  if (__glibc_unlikely (thp_mode == thp_mode_not_supported\n> > -                        || thp_pagesize == 0))\n> > -    {\n> > -      unsigned long int default_thp_pagesize = DL_MAP_DEFAULT_THP_PAGESIZE;\n> > -      thp_mode = default_thp_pagesize ? thp_mode_always : __get_thp_mode ();\n> > -      thp_pagesize = default_thp_pagesize ? : __get_thp_size ();\n> > -    }\n> > -\n> > -  /* Aligning load segments that are large enough to the PMD size helps\n> > -     improve THP eligibility and reduces TLB pressure.\n> > -     We cap the huge page size at MAX_THP_PAGESIZE to avoid over-aligning\n> > -     on systems with very large normal pages (like 64K pages with 512M\n> > -     huge pages). */\n> > -  if (thp_mode == thp_mode_always\n> > -      && thp_pagesize <= MAX_THP_PAGESIZE\n> > -      && ((c->mapstart | c->mapoff) & (thp_pagesize - 1)) == 0\n> > -      && (c->mapend - c->mapstart) >= thp_pagesize\n> > -      && p_align_max < thp_pagesize\n> > -      && (c->prot & PROT_WRITE) == 0)\n> > -    return thp_pagesize;\n> > -\n> > -  return p_align_max;\n> > -}\n> > diff --git a/sysdeps/unix/sysv/linux/ldsodefs.h b/sysdeps/unix/sysv/linux/ldsodefs.h\n> > index c63b649432..e39d9afe34 100644\n> > --- a/sysdeps/unix/sysv/linux/ldsodefs.h\n> > +++ b/sysdeps/unix/sysv/linux/ldsodefs.h\n> > @@ -21,6 +21,9 @@\n> >  /* We have the auxiliary vector.  */\n> >  #define HAVE_AUX_VECTOR\n> >\n> > +/* We have transparent huge page.  */\n> > +#define HAVE_THP\n> > +\n> >  /* Get the real definitions.  */\n> >  #include_next <ldsodefs.h>\n> >\n> > diff --git a/sysdeps/unix/sysv/linux/loongarch/Makefile b/sysdeps/unix/sysv/linux/loongarch/Makefile\n> > index 0d5f087862..d5beb62440 100644\n> > --- a/sysdeps/unix/sysv/linux/loongarch/Makefile\n> > +++ b/sysdeps/unix/sysv/linux/loongarch/Makefile\n> > @@ -12,3 +12,6 @@ abi-ilp32s-condition := __WORDSIZE == 32 && defined __loongarch_soft_float\n> >  abi-ilp32d-condition := __WORDSIZE == 32 && defined __loongarch_double_float\n> >  abi-lp64s-condition := __WORDSIZE == 64 && defined __loongarch_soft_float\n> >  abi-lp64d-condition := __WORDSIZE == 64 && defined __loongarch_double_float\n> > +\n> > +# Align THP tests to 32MB.\n> > +THP-PAGE-SIZE = 0x2000000\n> > diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/dl-map-segment-align.h b/sysdeps/unix/sysv/linux/loongarch/lp64/dl-exec-post.h\n> > similarity index 90%\n> > rename from sysdeps/unix/sysv/linux/loongarch/lp64/dl-map-segment-align.h\n> > rename to sysdeps/unix/sysv/linux/loongarch/lp64/dl-exec-post.h\n> > index c51ee4ac47..fbc58d662c 100644\n> > --- a/sysdeps/unix/sysv/linux/loongarch/lp64/dl-map-segment-align.h\n> > +++ b/sysdeps/unix/sysv/linux/loongarch/lp64/dl-exec-post.h\n> > @@ -1,4 +1,4 @@\n> > -/* _dl_map_segment_align.  LoongArch64 Linux version.\n> > +/* DL_MAP_DEFAULT_THP_PAGESIZE.  LoongArch64 Linux version.\n> >     Copyright (C) 2026 Free Software Foundation, Inc.\n> >     Copyright The GNU Toolchain Authors.\n> >     This file is part of the GNU C Library.\n> > @@ -19,4 +19,4 @@\n> >\n> >  #define DL_MAP_DEFAULT_THP_PAGESIZE (32 * 1024 * 1024)\n> >\n> > -#include_next <dl-map-segment-align.h>\n> > +#include_next <dl-exec-post.h>\n> > diff --git a/sysdeps/unix/sysv/linux/strace-tst-thp.sh b/sysdeps/unix/sysv/linux/strace-tst-thp.sh\n> > new file mode 100644\n> > index 0000000000..8903717fd4\n> > --- /dev/null\n> > +++ b/sysdeps/unix/sysv/linux/strace-tst-thp.sh\n> > @@ -0,0 +1,56 @@\n> > +#!/bin/sh\n> > +# Run THP test under strace to verify control of the THP segment load.\n> > +# Copyright (C) 2026 Free Software Foundation, Inc.\n> > +# This file is part of the GNU C Library.\n> > +\n> > +# The GNU C Library is free software; you can redistribute it and/or\n> > +# modify it under the terms of the GNU Lesser General Public\n> > +# License as published by the Free Software Foundation; either\n> > +# version 2.1 of the License, or (at your option) any later version.\n> > +\n> > +# The GNU C Library is distributed in the hope that it will be useful,\n> > +# but WITHOUT ANY WARRANTY; without even the implied warranty of\n> > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> > +# Lesser General Public License for more details.\n> > +\n> > +# You should have received a copy of the GNU Lesser General Public\n> > +# License along with the GNU C Library; if not, see\n> > +# <https://www.gnu.org/licenses/>.\n> > +\n> > +set -e\n> > +\n> > +rtld=\"$1\"\n> > +test_wrapper_env=\"$2\"\n> > +run_program_env=\"$3\"\n> > +library_path=\"$4\"\n> > +test_prog=\"$5\"\n> > +\n> > +# Test whether strace is available in the test environment.  If not, skip\n> > +# the test.\n> > +${test_wrapper_env} ${run_program_env} \\\n> > +  /bin/sh -c \"command -v strace\" || exit 77\n> > +\n> > +# Finally the actual test inside the test environment, using the just\n> > +# build ld.so and new libraries to run the THP test under strace.\n> > +if /bin/sh -c \\\n> > +  \"${test_wrapper_env} ${run_program_env} strace ${rtld} \\\n> > +   --library-path ${library_path} ${test_prog} 2>&1 \\\n> > +   | grep -E \\\"madvise(.*, MADV_HUGEPAGE)\\\"\"; then\n> > +  case x\"${run_program_env}\" in\n> > +  *glibc.elf.thp=1*)\n> > +    exit 0\n> > +    ;;\n> > +  *)\n> > +    exit 1\n> > +    ;;\n> > +  esac\n> > +else\n> > +  case x\"${run_program_env}\" in\n> > +  *glibc.elf.thp=0*)\n> > +    exit 0\n> > +    ;;\n> > +  *)\n> > +    exit 1\n> > +    ;;\n> > +  esac\n> > +fi\n> > diff --git a/sysdeps/unix/sysv/linux/tst-thp-1-no-s-code-pde.c b/sysdeps/unix/sysv/linux/tst-thp-1-no-s-code-pde.c\n> > new file mode 100644\n> > index 0000000000..3fd01e9bfe\n> > --- /dev/null\n> > +++ b/sysdeps/unix/sysv/linux/tst-thp-1-no-s-code-pde.c\n> > @@ -0,0 +1,19 @@\n> > +/* Test PDE with THP segment load linked with -Wl,-z,noseparate-code.\n> > +   Copyright (C) 2026 Free Software Foundation, Inc.\n> > +   This file is part of the GNU C Library.\n> > +\n> > +   The GNU C Library is free software; you can redistribute it and/or\n> > +   modify it under the terms of the GNU Lesser General Public\n> > +   License as published by the Free Software Foundation; either\n> > +   version 2.1 of the License, or (at your option) any later version.\n> > +\n> > +   The GNU C Library is distributed in the hope that it will be useful,\n> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> > +   Lesser General Public License for more details.\n> > +\n> > +   You should have received a copy of the GNU Lesser General Public\n> > +   License along with the GNU C Library; if not, see\n> > +   <http://www.gnu.org/licenses/>.  */\n> > +\n> > +#include \"tst-thp-1.c\"\n> > diff --git a/sysdeps/unix/sysv/linux/tst-thp-1-no-s-code-static.c b/sysdeps/unix/sysv/linux/tst-thp-1-no-s-code-static.c\n> > new file mode 100644\n> > index 0000000000..d0ae0f1ff0\n> > --- /dev/null\n> > +++ b/sysdeps/unix/sysv/linux/tst-thp-1-no-s-code-static.c\n> > @@ -0,0 +1,19 @@\n> > +/* Test static with THP segment load linked with -Wl,-z,noseparate-code.\n> > +   Copyright (C) 2026 Free Software Foundation, Inc.\n> > +   This file is part of the GNU C Library.\n> > +\n> > +   The GNU C Library is free software; you can redistribute it and/or\n> > +   modify it under the terms of the GNU Lesser General Public\n> > +   License as published by the Free Software Foundation; either\n> > +   version 2.1 of the License, or (at your option) any later version.\n> > +\n> > +   The GNU C Library is distributed in the hope that it will be useful,\n> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> > +   Lesser General Public License for more details.\n> > +\n> > +   You should have received a copy of the GNU Lesser General Public\n> > +   License along with the GNU C Library; if not, see\n> > +   <http://www.gnu.org/licenses/>.  */\n> > +\n> > +#include \"tst-thp-1.c\"\n> > diff --git a/sysdeps/unix/sysv/linux/tst-thp-1-no-s-code.c b/sysdeps/unix/sysv/linux/tst-thp-1-no-s-code.c\n> > new file mode 100644\n> > index 0000000000..5eb1e005ed\n> > --- /dev/null\n> > +++ b/sysdeps/unix/sysv/linux/tst-thp-1-no-s-code.c\n> > @@ -0,0 +1,19 @@\n> > +/* Test THP segment load linked with -Wl,-z,noseparate-code.\n> > +   Copyright (C) 2026 Free Software Foundation, Inc.\n> > +   This file is part of the GNU C Library.\n> > +\n> > +   The GNU C Library is free software; you can redistribute it and/or\n> > +   modify it under the terms of the GNU Lesser General Public\n> > +   License as published by the Free Software Foundation; either\n> > +   version 2.1 of the License, or (at your option) any later version.\n> > +\n> > +   The GNU C Library is distributed in the hope that it will be useful,\n> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> > +   Lesser General Public License for more details.\n> > +\n> > +   You should have received a copy of the GNU Lesser General Public\n> > +   License along with the GNU C Library; if not, see\n> > +   <http://www.gnu.org/licenses/>.  */\n> > +\n> > +#include \"tst-thp-1.c\"\n> > diff --git a/sysdeps/unix/sysv/linux/tst-thp-1-pde.c b/sysdeps/unix/sysv/linux/tst-thp-1-pde.c\n> > new file mode 100644\n> > index 0000000000..d854dd43da\n> > --- /dev/null\n> > +++ b/sysdeps/unix/sysv/linux/tst-thp-1-pde.c\n> > @@ -0,0 +1,19 @@\n> > +/* Test PDE with THP segment load linked with -Wl,-z,separate-code.\n> > +   Copyright (C) 2026 Free Software Foundation, Inc.\n> > +   This file is part of the GNU C Library.\n> > +\n> > +   The GNU C Library is free software; you can redistribute it and/or\n> > +   modify it under the terms of the GNU Lesser General Public\n> > +   License as published by the Free Software Foundation; either\n> > +   version 2.1 of the License, or (at your option) any later version.\n> > +\n> > +   The GNU C Library is distributed in the hope that it will be useful,\n> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> > +   Lesser General Public License for more details.\n> > +\n> > +   You should have received a copy of the GNU Lesser General Public\n> > +   License along with the GNU C Library; if not, see\n> > +   <http://www.gnu.org/licenses/>.  */\n> > +\n> > +#include \"tst-thp-1.c\"\n> > diff --git a/sysdeps/unix/sysv/linux/tst-thp-1-static.c b/sysdeps/unix/sysv/linux/tst-thp-1-static.c\n> > new file mode 100644\n> > index 0000000000..66d7e12954\n> > --- /dev/null\n> > +++ b/sysdeps/unix/sysv/linux/tst-thp-1-static.c\n> > @@ -0,0 +1,19 @@\n> > +/* Test static with THP segment load linked with -Wl,-z,separate-code.\n> > +   Copyright (C) 2026 Free Software Foundation, Inc.\n> > +   This file is part of the GNU C Library.\n> > +\n> > +   The GNU C Library is free software; you can redistribute it and/or\n> > +   modify it under the terms of the GNU Lesser General Public\n> > +   License as published by the Free Software Foundation; either\n> > +   version 2.1 of the License, or (at your option) any later version.\n> > +\n> > +   The GNU C Library is distributed in the hope that it will be useful,\n> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> > +   Lesser General Public License for more details.\n> > +\n> > +   You should have received a copy of the GNU Lesser General Public\n> > +   License along with the GNU C Library; if not, see\n> > +   <http://www.gnu.org/licenses/>.  */\n> > +\n> > +#include \"tst-thp-1.c\"\n> > diff --git a/sysdeps/unix/sysv/linux/tst-thp-1.c b/sysdeps/unix/sysv/linux/tst-thp-1.c\n> > new file mode 100644\n> > index 0000000000..49eea7069c\n> > --- /dev/null\n> > +++ b/sysdeps/unix/sysv/linux/tst-thp-1.c\n> > @@ -0,0 +1,28 @@\n> > +/* Test THP segment load linked with -Wl,-z,separate-code.\n> > +   Copyright (C) 2026 Free Software Foundation, Inc.\n> > +   This file is part of the GNU C Library.\n> > +\n> > +   The GNU C Library is free software; you can redistribute it and/or\n> > +   modify it under the terms of the GNU Lesser General Public\n> > +   License as published by the Free Software Foundation; either\n> > +   version 2.1 of the License, or (at your option) any later version.\n> > +\n> > +   The GNU C Library is distributed in the hope that it will be useful,\n> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> > +   Lesser General Public License for more details.\n> > +\n> > +   You should have received a copy of the GNU Lesser General Public\n> > +   License along with the GNU C Library; if not, see\n> > +   <http://www.gnu.org/licenses/>.  */\n> > +\n> > +#include \"tst-thp-align-check.h\"\n> > +\n> > +static int\n> > +do_test (void)\n> > +{\n> > +  check_align (\"tst-thp-1\");\n> > +  return 0;\n> > +}\n> > +\n> > +#include <support/test-driver.c>\n> > diff --git a/sysdeps/unix/sysv/linux/tst-thp-align-check.h b/sysdeps/unix/sysv/linux/tst-thp-align-check.h\n> > new file mode 100644\n> > index 0000000000..bcb50c96f8\n> > --- /dev/null\n> > +++ b/sysdeps/unix/sysv/linux/tst-thp-align-check.h\n> > @@ -0,0 +1,132 @@\n> > +/* Test the THP compatible alignment of PT_LOAD segments.\n> > +\n> > +   Copyright (C) 2026 Free Software Foundation, Inc.\n> > +\n> > +   The GNU C Library is free software; you can redistribute it and/or\n> > +   modify it under the terms of the GNU Lesser General Public\n> > +   License as published by the Free Software Foundation; either\n> > +   version 2.1 of the License, or (at your option) any later version.\n> > +\n> > +   The GNU C Library is distributed in the hope that it will be useful,\n> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> > +   Lesser General Public License for more details.\n> > +\n> > +   You should have received a copy of the GNU Lesser General Public\n> > +   License along with the GNU C Library; if not, see\n> > +   <https://www.gnu.org/licenses/>.  */\n> > +\n> > +#include <fcntl.h>\n> > +#include <stdint.h>\n> > +#include <stdlib.h>\n> > +#include <string.h>\n> > +#include <intprops.h>\n> > +#include <inttypes.h>\n> > +#include <support/check.h>\n> > +#include <support/xstdio.h>\n> > +#include <support/xunistd.h>\n> > +#define attribute_hidden\n> > +#include <hugepages.h> /* For enum thp_mode_t and MAX_THP_PAGESIZE.  */\n> > +#undef attribute_hidden\n> > +\n> > +static unsigned long int\n> > +get_thp_size (void)\n> > +{\n> > +  int fd = open (\"/sys/kernel/mm/transparent_hugepage/hpage_pmd_size\",\n> > +                 O_RDONLY, 0);\n> > +  if (fd == -1)\n> > +    return 0;\n> > +\n> > +  char str[INT_BUFSIZE_BOUND (unsigned long int)];\n> > +  ssize_t s = read (fd, str, sizeof (str));\n> > +  close (fd);\n> > +  if (s < 0)\n> > +    return 0;\n> > +\n> > +  unsigned long int r = 0;\n> > +  for (ssize_t i = 0; i < s; i++)\n> > +    {\n> > +      if (str[i] == '\\n')\n> > +    break;\n> > +      r *= 10;\n> > +      r += str[i] - '0';\n> > +    }\n> > +  return r;\n> > +}\n> > +\n> > +static enum thp_mode_t\n> > +get_thp_mode (void)\n> > +{\n> > +  int fd = open (\"/sys/kernel/mm/transparent_hugepage/enabled\", O_RDONLY, 0);\n> > +  if (fd == -1)\n> > +    return thp_mode_not_supported;\n> > +\n> > +  static const char mode_always[]  = \"[always] madvise never\\n\";\n> > +  static const char mode_madvise[] = \"always [madvise] never\\n\";\n> > +  static const char mode_never[]   = \"always madvise [never]\\n\";\n> > +\n> > +  char str[sizeof(mode_always)];\n> > +  ssize_t s = read (fd, str, sizeof (str));\n> > +  if (s >= sizeof str || s < 0)\n> > +    return thp_mode_not_supported;\n> > +  str[s] = '\\0';\n> > +  close (fd);\n> > +\n> > +  if (s == sizeof (mode_always) - 1)\n> > +    {\n> > +      if (strcmp (str, mode_always) == 0)\n> > +    return thp_mode_always;\n> > +      else if (strcmp (str, mode_madvise) == 0)\n> > +    return thp_mode_madvise;\n> > +      else if (strcmp (str, mode_never) == 0)\n> > +    return thp_mode_never;\n> > +    }\n> > +  return thp_mode_not_supported;\n> > +}\n> > +\n> > +static void\n> > +check_align (const char *name)\n> > +{\n> > +  unsigned long int thp_size = get_thp_size ();\n> > +  enum thp_mode_t thp_mode = get_thp_mode ();\n> > +\n> > +  if (thp_size == 0)\n> > +    {\n> > +      FAIL_UNSUPPORTED (\"unable to get THP size.\\n\");\n> > +      return;\n> > +    }\n> > +\n> > +  if (thp_size > MAX_THP_PAGESIZE)\n> > +    {\n> > +      FAIL_UNSUPPORTED (\"THP size exceeds MAX_THP_PAGESIZE.\\n\");\n> > +      return;\n> > +    }\n> > +\n> > +  if (thp_mode != thp_mode_always && thp_mode != thp_mode_madvise)\n> > +    {\n> > +      FAIL_UNSUPPORTED (\"THP mode is not always nor madvise.\\n\");\n> > +      return;\n> > +    }\n> > +\n> > +  FILE *f = xfopen (\"/proc/self/maps\", \"r\");\n> > +  char *line = NULL;\n> > +  size_t len;\n> > +\n> > +  while (xgetline (&line, &len, f))\n> > +    {\n> > +      uintptr_t from, to;\n> > +      char *prot = NULL, *path = NULL;\n> > +      int r = sscanf (line, \"%\" SCNxPTR \"-%\" SCNxPTR \"%ms%*s%*s%*s%ms\",\n> > +                      &from, &to, &prot, &path);\n> > +\n> > +      TEST_VERIFY (r == 3 || r == 4);\n> > +\n> > +      if (strstr (prot, \"x\") && strstr (path, name))\n> > +        TEST_COMPARE (from % thp_size, 0);\n> > +\n> > +      free (path);\n> > +    }\n> > +\n> > +  free (line);\n> > +  xfclose (f);\n> > +}\n> > diff --git a/sysdeps/unix/sysv/linux/tst-thp-align.c b/sysdeps/unix/sysv/linux/tst-thp-align.c\n> > new file mode 100644\n> > index 0000000000..2e44109ba6\n> > --- /dev/null\n> > +++ b/sysdeps/unix/sysv/linux/tst-thp-align.c\n> > @@ -0,0 +1,36 @@\n> > +/* Test the THP compatible alignment of PT_LOAD segments.\n> > +\n> > +   Copyright (C) 2026 Free Software Foundation, Inc.\n> > +\n> > +   The GNU C Library is free software; you can redistribute it and/or\n> > +   modify it under the terms of the GNU Lesser General Public\n> > +   License as published by the Free Software Foundation; either\n> > +   version 2.1 of the License, or (at your option) any later version.\n> > +\n> > +   The GNU C Library is distributed in the hope that it will be useful,\n> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> > +   Lesser General Public License for more details.\n> > +\n> > +   You should have received a copy of the GNU Lesser General Public\n> > +   License along with the GNU C Library; if not, see\n> > +   <https://www.gnu.org/licenses/>.  */\n> > +\n> > +#include <support/xdlfcn.h>\n> > +#include \"tst-thp-align-check.h\"\n> > +\n> > +#define THP_SIZE_MOD_NAME \"tst-thp-size-mod.so\"\n> > +\n> > +static int\n> > +do_test (void)\n> > +{\n> > +  void *dl;\n> > +\n> > +  dl = xdlopen (THP_SIZE_MOD_NAME, RTLD_NOW);\n> > +  check_align (THP_SIZE_MOD_NAME);\n> > +  xdlclose (dl);\n> > +\n> > +  return 0;\n> > +}\n> > +\n> > +#include <support/test-driver.c>\n> > diff --git a/sysdeps/unix/sysv/linux/tst-thp-size-mod.S b/sysdeps/unix/sysv/linux/tst-thp-size-mod.S\n> > new file mode 100644\n> > index 0000000000..add66dfb52\n> > --- /dev/null\n> > +++ b/sysdeps/unix/sysv/linux/tst-thp-size-mod.S\n> > @@ -0,0 +1,24 @@\n> > +/* A module that provides THP code size for testing.\n> > +\n> > +   Copyright (C) 2026 Free Software Foundation, Inc.\n> > +   This file is part of the GNU C Library.\n> > +\n> > +   The GNU C Library is free software; you can redistribute it and/or\n> > +   modify it under the terms of the GNU Lesser General Public\n> > +   License as published by the Free Software Foundation; either\n> > +   version 2.1 of the License, or (at your option) any later version.\n> > +\n> > +   The GNU C Library is distributed in the hope that it will be useful,\n> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> > +   Lesser General Public License for more details.\n> > +\n> > +   You should have received a copy of the GNU Lesser General Public\n> > +   License along with the GNU C Library; if not, see\n> > +   <https://www.gnu.org/licenses/>.  */\n> > +\n> > +/* Create a 32MB text section to enable transparent huge page load.  */\n> > + .text\n> > + .globl thp_size\n> > +thp_size:\n> > + .space 32 * 1024 * 1024\n> > diff --git a/sysdeps/unix/sysv/linux/x86/dl-exec-post.h b/sysdeps/unix/sysv/linux/x86/dl-exec-post.h\n> > new file mode 100644\n> > index 0000000000..0fa0b5e0e5\n> > --- /dev/null\n> > +++ b/sysdeps/unix/sysv/linux/x86/dl-exec-post.h\n> > @@ -0,0 +1,22 @@\n> > +/* DL_MAP_DEFAULT_THP_PAGESIZE.  Linux/x86 version.\n> > +   Copyright (C) 2026 Free Software Foundation, Inc.\n> > +   Copyright The GNU Toolchain Authors.\n> > +   This file is part of the GNU C Library.\n> > +\n> > +   The GNU C Library is free software; you can redistribute it and/or\n> > +   modify it under the terms of the GNU Lesser General Public\n> > +   License as published by the Free Software Foundation; either\n> > +   version 2.1 of the License, or (at your option) any later version.\n> > +\n> > +   The GNU C Library is distributed in the hope that it will be useful,\n> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> > +   Lesser General Public License for more details.\n> > +\n> > +   You should have received a copy of the GNU Lesser General Public\n> > +   License along with the GNU C Library; if not, see\n> > +   <https://www.gnu.org/licenses/>.  */\n> > +\n> > +#define DL_MAP_DEFAULT_THP_PAGESIZE (2 * 1024 * 1024)\n> > +\n> > +#include_next <dl-exec-post.h>\n> > --\n> > 2.53.0\n> >\n>\n> Thanks,\n> Rui\n>\n\nThanks.","headers":{"Return-Path":"<libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org>","X-Original-To":["incoming@patchwork.ozlabs.org","libc-alpha@sourceware.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","libc-alpha@sourceware.org"],"Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=dqIyTlD1;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org;\n receiver=patchwork.ozlabs.org)","sourceware.org;\n\tdkim=pass (2048-bit key,\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=dqIyTlD1","sourceware.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com","sourceware.org; spf=pass smtp.mailfrom=gmail.com","server2.sourceware.org;\n arc=pass smtp.remote-ip=2607:f8b0:4864:20::62c"],"Received":["from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fy9Cd72v7z1yDF\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 18 Apr 2026 08:53:33 +1000 (AEST)","from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 327624CD202B\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 17 Apr 2026 22:53:31 +0000 (GMT)","from mail-pl1-x62c.google.com (mail-pl1-x62c.google.com\n [IPv6:2607:f8b0:4864:20::62c])\n by sourceware.org (Postfix) with ESMTPS id 3FFA04CD2000\n for <libc-alpha@sourceware.org>; Fri, 17 Apr 2026 22:53:00 +0000 (GMT)","by mail-pl1-x62c.google.com with SMTP id\n d9443c01a7336-2adbfab4501so5813885ad.2\n for <libc-alpha@sourceware.org>; Fri, 17 Apr 2026 15:53:00 -0700 (PDT)"],"DKIM-Filter":["OpenDKIM Filter v2.11.0 sourceware.org 327624CD202B","OpenDKIM Filter v2.11.0 sourceware.org 3FFA04CD2000"],"DMARC-Filter":"OpenDMARC Filter v1.4.2 sourceware.org 3FFA04CD2000","ARC-Filter":"OpenARC Filter v1.0.0 sourceware.org 3FFA04CD2000","ARC-Seal":["i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1776466380; cv=pass;\n b=V5s/qYfxxDcIH3p5snSKykp2Q6rV3+g8ZieQubyrLmC1S+0+QMMRChuGlJLawkMBS5CoJR+sdyG+IxYRye85AhpTg4q8i9UzG854prUScZTaXjIzsk7ZcFbB2wQjmVMFsxqOXLNmaVg4z8g09iml6HNP4estknuQcwj4rOztneo=","i=1; a=rsa-sha256; t=1776466379; cv=none;\n d=google.com; s=arc-20240605;\n b=bXyyXRp/jnv0ivCjwJrrRWyO0Am1uSARbLDDbH12m8RIiZvwAsW8/MVK3tR75wW1nF\n q6kPF/rUE7yIXwLTQL5WK+BEH0Q1cPoGgSATDUkYrz2MJ0+JN04TGe0Xj35NPU+oEVeb\n ahZiA4CjNIZ4MlNUa26+idIGlOkySvEx1NmgXFJ+8DiMoMLtYbmPluJ3q6HBkQW+6NgW\n AyB1yt4AYVY6YMNUY8SChVGZ/40tUROCZou1DzxKf52Dut20ibrLa5p6Mwibj3v692Vf\n 2kQ2Fdqmv7B0PAdQbbHPFHhvKgcePT3SHn5yxtmIvkAkkCG7Usdbaiue/Chzs9QdnJFb\n 3Cww=="],"ARC-Message-Signature":["i=2; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776466380; c=relaxed/simple;\n bh=m9QVfAjQxJwlnCofXD/nvK32eeBTzihOd4jERdDp6hY=;\n h=DKIM-Signature:MIME-Version:From:Date:Message-ID:Subject:To;\n b=nWyrnEMA1Ez9Y0olrxYF99GudUO+LlmeUIzItnK16FvhWgfE/ajnsVnhfjwOxVPBJsDnY1+9CYuNIORiSn7RMeAg/OgEnMxgb9PeZhn6XlCJ0otqmzssrLRbDNHiDu01bVAzGO2fna030iVcK5lKYnbZdaS9LIgyNBjw3YZRvyE=","i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com;\n s=arc-20240605;\n h=content-transfer-encoding:cc:to:subject:message-id:date:from\n :in-reply-to:references:mime-version:dkim-signature;\n bh=6BBumdBDNqFFkHDKyZVlKuYgkvcXBKvSnxtVkfrYPqI=;\n fh=uPRHYJz2Sfz7f3vkN42P2DuSwvsVFOP+BdP6M5Y78QU=;\n b=lsfW0hGkY2d5xFFy7xu4EEB+tTY1RnBwD+hxxkNV3Gc4rqHNFI0BXwD8278H+OqwFC\n eZgH//8zhUGkE0MKvVb3rPbQOQ7VQ+jAOp6oJwUpX8i1MZX7Wab4Y0pE0ycMwtiucoc1\n NwQcVeCF8kiYImiQHB0Shy15sQQ6VggbjHf8csIqlSex2kVOuuFB3XXSSRSChZav/MbG\n xzRONu+Tzu8vvLj3gj1x80/Xq341/XoKoDbju/mH2ufopdyjt4X3hCNLK++IeyUN/3If\n VBNERl9C4EaC38AsxSJvCRPqz9lrqPDgl6rYkMGw6moP8ZIfTFolmJxBsn5TXXbiPh/M\n FB0A==; darn=sourceware.org"],"ARC-Authentication-Results":["i=2; server2.sourceware.org","i=1; mx.google.com; arc=none"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20251104; t=1776466379; x=1777071179; darn=sourceware.org;\n h=content-transfer-encoding:cc:to:subject:message-id:date:from\n :in-reply-to:references:mime-version:from:to:cc:subject:date\n :message-id:reply-to;\n bh=6BBumdBDNqFFkHDKyZVlKuYgkvcXBKvSnxtVkfrYPqI=;\n b=dqIyTlD10TGujAe+u7z5b+P/73uxjy2G7OQBDCktENF8kk3h90ona5Hsvc20rB+5CW\n 2T6H1MFrAysZMBh4N8jJOzLD4EdlgICFjmsMyPsxLx1GSO5MCHNQ8lgh46u400/zatOB\n P2wKyy0Mw2h9gcsuxCyIzUFFhioponATb+xSGF1Q+f75DWLmbtKktLa6sro4ROhMUbNe\n 2Apa7qBbmWAZofnaclgIxJO8mgPEOAh0HZcWyIlEv0zoIUQ1TMLUaVn7W7eBLvHOnZ/x\n B3QC3Q/yeqJli/6sUSkcglKliSyvNZIdsIwJgewUEdL/pAp4T8/0rzKpolAUzY04ziQ2\n amzw==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776466379; x=1777071179;\n h=content-transfer-encoding:cc:to:subject:message-id:date:from\n :in-reply-to:references:mime-version:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=6BBumdBDNqFFkHDKyZVlKuYgkvcXBKvSnxtVkfrYPqI=;\n b=FdtDEuFHy5ODJAz8gCR2ZxN4eQDW4AS2S79Su/ScQwF/rri5FfzVwKobp6Gld+awoM\n Bye/J3481joXMa9nU5FF1woo4GM0NR0PwBPJ3W0ARBCjXQmEZjko/yWjDlrQ4LDUcrgE\n HuSh4tMg1Ws7XP44WS72nmUQseBPL5UZkTEIsDUgjvGf0pkXbJgJmFB1/+SbqFz7N7jN\n Wc4olFCWLaG2SEVmfACge/74Zij818IibP85IngL0wbKSnwmbiXVAo5bMqpweIgDrREu\n QaXsN5DNsudHxU0VVIAIIbXLIVFksmodLAFpDv9a2jv9Ef4ed2O6JAFOpCADGq6COXVY\n gY9Q==","X-Gm-Message-State":"AOJu0Yw7Ja2n+7ad12l62GDQxm8bPMr5tI3gsPHlG6NET0H5yOsKcEtj\n 6ZHmGFqHLgNwR1/AJx1J8kC4ZH3sp9jsB4RE8/3ALLP680Txrx8c9ZXiBNhlypK0RNcpRoDn1Ty\n 03eCzb3CZF5R1oW2B8qn0+cSOO6U3ufQ=","X-Gm-Gg":"AeBDieuZRNYF2GDVJuPIQ/X/zrDYvUP5xymXElMNX0W2R8RhZR59LafNu7VdXlmrMZa\n SvO9A/b86m4lIOE0IutOd75j5ldPyNHgmcbop4XFime+1OimNMflnYhccDmeMg3BQHkoZrvzRCU\n DG848PicKBX4/aUdoriQMaSjC4Fy0y2haYwCn4v5j8olXirnPN4bV9hpKZhjtSgJBzw1+sXXoeV\n BwKapyKaW/zjxz4Ew6GHXzkP/pwYVEcKrXBBSnTqLobRzqC7ZtQcPOx1InS71XiCdnVJ/SGGc2F\n RrcfsEmmXIoT5EDWQgoO2Z7zUqt5YA==","X-Received":"by 2002:a17:902:bd8c:b0:2b2:50f6:cdd9 with SMTP id\n d9443c01a7336-2b5f9ecb818mr31418465ad.8.1776466378429; Fri, 17 Apr 2026\n 15:52:58 -0700 (PDT)","MIME-Version":"1.0","References":"\n <CAMe9rOrVsKZz0MuqGwu1KX4MaFK=tc0idvk1kHy2+B8hOdLCVA@mail.gmail.com>\n <CAMe9rOryN0j-SZT_C4EYzEHt+B7kQTvC5t4GaQ3H8dPXG+aejg@mail.gmail.com>\n <CAHirt9hsXHVttvtkqkrF=WGn+K0h9_EeJpZnV5g1BpcJddYH2g@mail.gmail.com>","In-Reply-To":"\n <CAHirt9hsXHVttvtkqkrF=WGn+K0h9_EeJpZnV5g1BpcJddYH2g@mail.gmail.com>","From":"\"H.J. Lu\" <hjl.tools@gmail.com>","Date":"Sat, 18 Apr 2026 06:52:21 +0800","X-Gm-Features":"AQROBzD3t78uTdQNewmtog9-cmMWwtmoKTMhFNkG3yV19R-nUTezXGqg04iN5yY","Message-ID":"\n <CAMe9rOp-_96y0s=3yMi9_+8G_PsaagRAHrMqLqCHLY4QYK6XvQ@mail.gmail.com>","Subject":"Re: [PATCH v2 2/2] elf: Support THP segment load with madvise enabled\n THP","To":"WANG Rui <wangrui@loongson.cn>","Cc":"GNU C Library <libc-alpha@sourceware.org>","Content-Type":"text/plain; charset=\"UTF-8\"","Content-Transfer-Encoding":"quoted-printable","X-BeenThere":"libc-alpha@sourceware.org","X-Mailman-Version":"2.1.30","Precedence":"list","List-Id":"Libc-alpha mailing list <libc-alpha.sourceware.org>","List-Unsubscribe":"<https://sourceware.org/mailman/options/libc-alpha>,\n <mailto:libc-alpha-request@sourceware.org?subject=unsubscribe>","List-Archive":"<https://sourceware.org/pipermail/libc-alpha/>","List-Post":"<mailto:libc-alpha@sourceware.org>","List-Help":"<mailto:libc-alpha-request@sourceware.org?subject=help>","List-Subscribe":"<https://sourceware.org/mailman/listinfo/libc-alpha>,\n <mailto:libc-alpha-request@sourceware.org?subject=subscribe>","Errors-To":"libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org"}}]