[PATCH] malloc: Don't call __get_thp_mode/__get_thp_size twice

H.J. Lu hjl.tools@gmail.com
Tue Jun 16 22:58:21 GMT 2026


This patch is on top of

commit 8c84793bab32868e557615c2e74b65ea06c0cd85
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Mon Apr 13 08:23:05 2026 +0800

    elf: Support THP segment load with madvise enabled THP

https://patchwork.sourceware.org/project/glibc/list/?series=62321

--
Both ld.so and malloc track kernel THP mode and THP page size when THP
in ld.so is enabled by

GLIBC_TUNABLES=glibc.elf.thp=1

and THP in malloc is enabled by

GLIBC_TUNABLES=glibc.malloc.hugetlb=1

But DL_MAP_DEFAULT_THP_PAGESIZE and MALLOC_DEFAULT_THP_PAGESIZE may be
different when they are defined in <hugepages.h>.

If THP in ld.so is enabled, change malloc to use kernel THP mode from
ld.so, instead of calling __get_thp_mode, and use THP page size from
ld.so if it came from __get_thp_size.  This avoids calling __get_thp_mode
and __get_thp_size again, which are quite expensive:

1. Initialize mp_.thp_mode and GL(dl_thp_mode) to thp_mode_unknown.
2. Set mp_.thp_mode to GL(dl_thp_mode) if GL(dl_thp_mode) isn't
thp_mode_unknown.  Otherwise call __get_thp_mode to set mp_.thp_mode.
3. GL(dl_elf_thp_pagesize) is set to DL_MAP_DEFAULT_THP_PAGESIZE without
calling __get_thp_size and THP page size for malloc may be different from
THP page size for ld.so.  Set mp_.thp_pagesize to GL(dl_elf_thp_pagesize)
if DL_MAP_DEFAULT_THP_PAGESIZE is defined.  Otherwise call __get_thp_size
to set mp_.thp_pagesize.

This fixes BZ #34083.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
---
 malloc/malloc.c             | 56 +++++++++++++++++++++++++++++++++----
 sysdeps/generic/hugepages.h |  3 +-
 2 files changed, 53 insertions(+), 6 deletions(-)

diff --git a/malloc/malloc.c b/malloc/malloc.c
index a354576aca..f0ed95213f 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -1529,7 +1529,7 @@ static struct malloc_par mp_ =
   .mmap_threshold = DEFAULT_MMAP_THRESHOLD,
   .trim_threshold = DEFAULT_TRIM_THRESHOLD,
   .arena_test = sizeof (long) == 4 ? 2 : 8,
-  .thp_mode = thp_mode_not_supported
+  .thp_mode = thp_mode_unknown
 #if USE_TCACHE
   ,
   .tcache_count = TCACHE_FILL_COUNT,
@@ -4657,13 +4657,41 @@ do_set_mxfast (size_t value)
   return 1;
 }
 
+#ifdef HAVE_THP
+static __always_inline enum thp_mode_t
+get_dl_thp_mode (void)
+{
+  return GL(dl_thp_mode);
+}
+
+static __always_inline unsigned long int
+get_dl_elf_thp_pagesize (void)
+{
+  return GL(dl_elf_thp_pagesize);
+}
+#else
+# define get_dl_thp_mode()		__get_thp_mode ()
+# define get_dl_elf_thp_pagesize()	__get_thp_size ()
+#endif
+
 static __always_inline int
 do_set_hugetlb (size_t value)
 {
+  /* If __get_thp_mode and __get_thp_size have been called during
+     startup, don't call them again here.  */
+  enum thp_mode_t thp_mode = get_dl_thp_mode ();
+
   /* Enable THP if MALLOC_DEFAULT_THP_PAGESIZE is non-zero.  */
   if (MALLOC_DEFAULT_THP_PAGESIZE > 0)
     {
-      mp_.thp_mode = thp_mode_madvise;
+      /* If thp_mode is unknown, THP segment load is disabled by
+	 GLIBC_TUNABLES=glibc.elf.thp=0.  In this case, set
+	 mp_.thp_mode to madvise.  Otherwise, set it to thp_mode to
+	 keep mp_.thp_mode in sync with GL(dl_thp_mode).  */
+      if (thp_mode == thp_mode_unknown)
+	mp_.thp_mode = thp_mode_madvise;
+      else
+	mp_.thp_mode = thp_mode;
       mp_.thp_pagesize = MALLOC_DEFAULT_THP_PAGESIZE;
     }
 
@@ -4680,9 +4708,27 @@ do_set_hugetlb (size_t value)
       if (MALLOC_DEFAULT_THP_PAGESIZE > 0)
 	return 0;
 
-      mp_.thp_mode = __get_thp_mode ();
-      if (mp_.thp_mode == thp_mode_madvise || mp_.thp_mode == thp_mode_always)
-	mp_.thp_pagesize = __get_thp_size ();
+      if (thp_mode == thp_mode_unknown)
+	{
+	  /* Call __get_thp_mode and __get_thp_size when THP segment load
+	     is disabled.  */
+	  mp_.thp_mode = __get_thp_mode ();
+	  if (mp_.thp_mode == thp_mode_madvise
+	      || mp_.thp_mode == thp_mode_always)
+	    mp_.thp_pagesize = __get_thp_size ();
+	}
+      else
+	{
+	  /* THP segment load is enabled.  GL(dl_elf_thp_pagesize) is
+	     set to DL_MAP_DEFAULT_THP_PAGESIZE if it isn't zero .  In
+	     this case, call __get_thp_size () instead of using
+	     DL_MAP_DEFAULT_THP_PAGESIZE for malloc.  */
+	  mp_.thp_mode = thp_mode;
+	  if (DL_MAP_DEFAULT_THP_PAGESIZE != 0)
+	    mp_.thp_pagesize = __get_thp_size ();
+	  else
+	    mp_.thp_pagesize = get_dl_elf_thp_pagesize ();
+	}
     }
   else if (value >= 2)
     __get_hugepage_config (value == 2 ? 0 : value, &mp_.hp_pagesize,
diff --git a/sysdeps/generic/hugepages.h b/sysdeps/generic/hugepages.h
index 8e54661527..49251d94ab 100644
--- a/sysdeps/generic/hugepages.h
+++ b/sysdeps/generic/hugepages.h
@@ -37,7 +37,8 @@ unsigned long int __get_thp_size (void) attribute_hidden;
 
 enum thp_mode_t
 {
-  thp_mode_not_supported = 0,
+  thp_mode_unknown = 0,
+  thp_mode_not_supported,
   thp_mode_always,
   thp_mode_madvise,
   thp_mode_never
-- 
2.54.0



More information about the Libc-alpha mailing list