[PATCH] hugepages: cache THP mode and page size [BZ #34083]

H.J. Lu hjl.tools@gmail.com
Fri May 1 22:27:02 GMT 2026


On Sat, May 2, 2026 at 4:59 AM Shamil Abdulaev <ashamil435@gmail.com> wrote:
>
> __get_thp_mode and __get_thp_size read /sys files and are used by
> both the dynamic linker and malloc.  Cache their results in rtld_global
> so the expensive THP probes are performed once per process.
>
> Tested on x86_64-linux-gnu.  No new test failures.

I took a different approach:

https://gitlab.com/x86-glibc/glibc/-/commits/users/hjl/hugepage/pr34083

since 2 THP optimizations can be controlled independently.   They share
the same THP mode only if both are enabled.

> Signed-off-by: Shamil Abdulaev <ashamil435@gmail.com>
> ---
>  elf/dl-support.c                    |  6 +++
>  sysdeps/generic/hugepages.h         |  7 ++++
>  sysdeps/generic/ldsodefs.h          |  6 +++
>  sysdeps/unix/sysv/linux/hugepages.c | 58 ++++++++++++++++++++++++-----
>  4 files changed, 68 insertions(+), 9 deletions(-)
>
> diff --git a/elf/dl-support.c b/elf/dl-support.c
> index 0508d6113b..ec77cb3e7a 100644
> --- a/elf/dl-support.c
> +++ b/elf/dl-support.c
> @@ -144,6 +144,12 @@ int _dl_inhibit_cache;
>  /* All known directories in sorted order.  */
>  struct r_search_path_elem *_dl_all_dirs;
>
> +/* Cached Transparent Huge Page mode and page size.  */
> +int _dl_thp_mode;
> +unsigned long int _dl_thp_pagesize;
> +int _dl_thp_mode_state;
> +int _dl_thp_pagesize_state;
> +
>  /* All directories after startup.  */
>  struct r_search_path_elem *_dl_init_all_dirs;
>
> diff --git a/sysdeps/generic/hugepages.h b/sysdeps/generic/hugepages.h
> index 5fc9b5c8de..68be2ee242 100644
> --- a/sysdeps/generic/hugepages.h
> +++ b/sysdeps/generic/hugepages.h
> @@ -32,6 +32,13 @@ enum thp_mode_t
>    thp_mode_not_supported
>  };
>
> +enum thp_cache_state_t
> +{
> +  thp_cache_uninitialized,
> +  thp_cache_initializing,
> +  thp_cache_initialized
> +};
> +
>  enum thp_mode_t __get_thp_mode (void) attribute_hidden;
>
>  /* Return the supported huge page size from the REQUESTED sizes on PAGESIZE
> diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
> index 15c4659853..4b2e337a81 100644
> --- a/sysdeps/generic/ldsodefs.h
> +++ b/sysdeps/generic/ldsodefs.h
> @@ -395,6 +395,12 @@ struct rtld_global
>    /* List of search directories.  */
>    EXTERN struct r_search_path_elem *_dl_all_dirs;
>
> +  /* Cached Transparent Huge Page mode and page size.  */
> +  EXTERN int _dl_thp_mode;
> +  EXTERN unsigned long int _dl_thp_pagesize;
> +  EXTERN int _dl_thp_mode_state;
> +  EXTERN int _dl_thp_pagesize_state;
> +
>    /* Get architecture specific definitions.  */
>  #define PROCINFO_DECL
>  #ifndef PROCINFO_CLASS
> diff --git a/sysdeps/unix/sysv/linux/hugepages.c b/sysdeps/unix/sysv/linux/hugepages.c
> index 46e05151a3..c32127f6a4 100644
> --- a/sysdeps/unix/sysv/linux/hugepages.c
> +++ b/sysdeps/unix/sysv/linux/hugepages.c
> @@ -16,6 +16,8 @@
>     License along with the GNU C Library; see the file COPYING.LIB.  If
>     not, see <https://www.gnu.org/licenses/>.  */
>
> +#include <atomic.h>
> +#include <ldsodefs.h>
>  #include <intprops.h>
>  #include <dirent.h>
>  #include <hugepages.h>
> @@ -25,18 +27,32 @@
>  unsigned long int
>  __get_thp_size (void)
>  {
> +  if (atomic_load_acquire (&GL (dl_thp_pagesize_state))
> +      == thp_cache_initialized)
> +    return GL (dl_thp_pagesize);
> +
> +  int state = thp_cache_uninitialized;
> +  if (!atomic_compare_exchange_acquire (&GL (dl_thp_pagesize_state),
> +                                       &state, thp_cache_initializing))
> +    {
> +      while (atomic_load_acquire (&GL (dl_thp_pagesize_state))
> +            != thp_cache_initialized)
> +       atomic_spin_nop ();
> +      return GL (dl_thp_pagesize);
> +    }
> +
> +  unsigned long int r = 0;
>    int fd = __open64_nocancel (
>      "/sys/kernel/mm/transparent_hugepage/hpage_pmd_size", O_RDONLY);
>    if (fd == -1)
> -    return 0;
> +    goto out;
>
>    char str[INT_BUFSIZE_BOUND (unsigned long int)];
>    ssize_t s = __read_nocancel (fd, str, sizeof (str));
>    __close_nocancel (fd);
>    if (s < 0)
> -    return 0;
> +    goto out;
>
> -  unsigned long int r = 0;
>    for (ssize_t i = 0; i < s; i++)
>      {
>        if (str[i] == '\n')
> @@ -44,16 +60,36 @@ __get_thp_size (void)
>        r *= 10;
>        r += str[i] - '0';
>      }
> +
> +out:
> +  GL (dl_thp_pagesize) = r;
> +  atomic_store_release (&GL (dl_thp_pagesize_state),
> +                       thp_cache_initialized);
>    return r;
>  }
>
>  enum thp_mode_t
>  __get_thp_mode (void)
>  {
> +  if (atomic_load_acquire (&GL (dl_thp_mode_state))
> +      == thp_cache_initialized)
> +    return (enum thp_mode_t) GL (dl_thp_mode);
> +
> +  int state = thp_cache_uninitialized;
> +  if (!atomic_compare_exchange_acquire (&GL (dl_thp_mode_state),
> +                                       &state, thp_cache_initializing))
> +    {
> +      while (atomic_load_acquire (&GL (dl_thp_mode_state))
> +            != thp_cache_initialized)
> +       atomic_spin_nop ();
> +      return (enum thp_mode_t) GL (dl_thp_mode);
> +    }
> +
> +  enum thp_mode_t mode = thp_mode_not_supported;
>    int fd = __open64_nocancel ("/sys/kernel/mm/transparent_hugepage/enabled",
>                               O_RDONLY);
>    if (fd == -1)
> -    return thp_mode_not_supported;
> +    goto out;
>
>    static const char mode_always[]  = "[always] madvise never\n";
>    static const char mode_madvise[] = "always [madvise] never\n";
> @@ -63,19 +99,23 @@ __get_thp_mode (void)
>    ssize_t s = __read_nocancel (fd, str, sizeof (str));
>    __close_nocancel (fd);
>    if (s >= sizeof str || s < 0)
> -    return thp_mode_not_supported;
> +    goto out;
>    str[s] = '\0';
>
>    if (s == sizeof (mode_always) - 1)
>      {
>        if (strcmp (str, mode_always) == 0)
> -       return thp_mode_always;
> +       mode = thp_mode_always;
>        else if (strcmp (str, mode_madvise) == 0)
> -       return thp_mode_madvise;
> +       mode = thp_mode_madvise;
>        else if (strcmp (str, mode_never) == 0)
> -       return thp_mode_never;
> +       mode = thp_mode_never;
>      }
> -  return thp_mode_not_supported;
> +
> +out:
> +  GL (dl_thp_mode) = mode;
> +  atomic_store_release (&GL (dl_thp_mode_state), thp_cache_initialized);
> +  return mode;
>  }
>
>  #if !IS_IN (rtld)
> --
> 2.54.0
>


-- 
H.J.


More information about the Libc-alpha mailing list