[PATCH v8] elf: Support THP segment load with madvise enabled THP
H.J. Lu
hjl.tools@gmail.com
Sat May 16 00:04:07 GMT 2026
On Sat, May 16, 2026 at 7:01 AM Wilco Dijkstra <Wilco.Dijkstra@arm.com> wrote:
>
> Hi HJ,
>
> A few comments:
>
> +static inline void
> +_dl_get_thp_config (void)
> +{
> + /* Check if there is GLIBC_TUNABLES=glibc.elf.thp=[0|1]. */
> + if (TUNABLE_IS_INITIALIZED_FULL (glibc, elf, thp))
> + GL(dl_elf_thp_control) = TUNABLE_GET_FULL (glibc, elf, thp, int32_t,
> + NULL);
> + else
> + GL(dl_elf_thp_control) = 0;
>
> Wouldn't it be easier to do:
>
> GL(dl_elf_thp_control) = TUNABLE_GET_FULL (glibc, elf, thp, int32_t, NULL);
Fixed.
> + /* Return if THP is disabled by GLIBC_TUNABLES=glibc.elf.thp=0. */
> + if (GL(dl_elf_thp_control) == 0)
> + return;
> +
> + _Static_assert (DL_MAP_DEFAULT_THP_PAGESIZE <= MAX_THP_PAGESIZE,
> + "DL_MAP_DEFAULT_THP_PAGESIZE <= MAX_THP_PAGESIZE");
> +
> + /* NB: Accessing /sys/kernel/mm files is quite expensive and the file
> + may not be accessible in containers. If DL_MAP_DEFAULT_THP_PAGESIZE
> + is non-zero, assume THP mode is madvise and always call madvise.
> + Since madvise is a fast systemcall, it adds only a small overhead
> + compared to the cost of accessing /sys/kernel/mm files. */
> + if (DL_MAP_DEFAULT_THP_PAGESIZE != 0)
> + {
> + GL(dl_elf_thp_pagesize) = DL_MAP_DEFAULT_THP_PAGESIZE;
> + GL(dl_thp_mode) = thp_mode_madvise;
> + }
> + else
> + {
> + GL(dl_elf_thp_pagesize) = __get_thp_size ();
> + GL(dl_thp_mode) = __get_thp_mode ();
> + /* We cap the huge page size at MAX_THP_PAGESIZE to avoid
> + over-aligning on systems with very large normal pages
> + (like 64K pages with 512M huge pages). */
> + if (GL(dl_elf_thp_pagesize) > MAX_THP_PAGESIZE)
> + GL(dl_elf_thp_control) = 0;
>
> Should also check if GL(dl_elf_thp_pagesize) == 0 (for if __get_thp_size() fails).
>
> + /* NB: Enable THP if THP is always enabled in the kernel. */
> + else if (GL(dl_thp_mode) == thp_mode_always)
> + GL(dl_elf_thp_control) = 1;
>
> This does not make sense. It's already 1 if we get here. This should check
> mode is madvise or always and set dl_elf_thp_control = 0 if not (since we
> can get thp_mode_not_supported too).
>
> And in both cases we should reset dl_elf_thp_pagesize and dl_thp_mode since
> there are some uses that do not first check dl_elf_thp_control > 0 (eg.
> _dl_postprocess_loadcmd_extra_needed).
I changed it to
GL(dl_elf_thp_pagesize) = __get_thp_size ();
GL(dl_thp_mode) = __get_thp_mode ();
/* We cap the huge page size at MAX_THP_PAGESIZE to avoid
over-aligning on systems with very large normal pages
(like 64K pages with 512M huge pages). */
if (GL(dl_elf_thp_pagesize) == 0
|| GL(dl_elf_thp_pagesize) > MAX_THP_PAGESIZE
|| GL(dl_thp_mode) == thp_mode_never
|| GL(dl_thp_mode) == thp_mode_not_supported)
{
GL(dl_elf_thp_pagesize) = 0;
GL(dl_elf_thp_control) = 0;
}
> + }
> +}
>
>
> ElfW (Addr)
> _dl_map_segment_align (const struct loadcmd *c, ElfW (Addr) p_align_max)
> {
> - static enum thp_mode_t thp_mode = thp_mode_not_supported;
> - static unsigned long int thp_pagesize;
> + enum thp_mode_t thp_mode = GL(dl_thp_mode);
> + size_t thp_pagesize = GL(dl_elf_thp_pagesize);
>
> - if (TUNABLE_GET (glibc, elf, thp, int32_t, NULL) == 0)
> + if (GL(dl_elf_thp_control) <= 0
> + || p_align_max >= thp_pagesize
> + || !(thp_mode == thp_mode_always || thp_mode == thp_mode_madvise))
> return p_align_max;
>
> Now this check for thp_mode is no longer needed.
Dropped.
>
> +static inline bool
> +_dl_postprocess_loadcmd_extra_needed (void)
> +{
> + return GL(dl_thp_mode) == thp_mode_madvise;
> +}
>
> I don't see the point of this interface. It's evaluated, the result passed around,
> and then eventually _dl_postprocess_loadcmd_extra is called. Why not call it
> unconditionally and do the check before calling _dl_segment_thp_eligible?
It is done this way since the generic version returns false unconditionally
and I don't want to call _dl_segment_thp_eligible in this case.
> +
> +/* After L has been mapped in, call madvise with MADV_HUGEPAGE if L is
> + THP eligible. */
> +
> +static inline void
> +_dl_postprocess_loadcmd_extra (struct link_map *l, const struct loadcmd *c)
> +{
> + if (_dl_segment_thp_eligible (c, GL(dl_elf_thp_pagesize)))
>
> Why not do:
>
> if (GL(dl_thp_mode) == thp_mode_madvise
This will be evaluated for every PT_LOAD segment. With
_dl_postprocess_loadcmd_extra_needed, it is evaluated only
once in an object.
> && _dl_segment_thp_eligible (c, GL(dl_elf_thp_pagesize)))
>
> + __madvise ((void *) (l->l_addr + c->mapstart),
> + c->mapend - c->mapstart, MADV_HUGEPAGE);
> +}
>
> Cheers,
> Wilco
Thanks.
--
H.J.
More information about the Libc-alpha
mailing list