[PATCH v8] elf: Support THP segment load with madvise enabled THP

Wilco Dijkstra Wilco.Dijkstra@arm.com
Fri May 15 23:00:39 GMT 2026


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);

+  /* 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).

+    }
+}


 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.
 

+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?

+
+/* 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
   && _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


More information about the Libc-alpha mailing list