[PATCH v4 1/6] hugepages: Move THP helpers to generic hugepages abstraction

WANG Rui wangrui@loongson.cn
Thu Mar 5 02:57:57 GMT 2026


The helpers for determining the default transparent huge page size
and THP mode are currently implemented in malloc-hugepages. However,
these interfaces are not malloc-specific and are also needed by other
subsystems (e.g. the dynamic loader for segment alignment).

Introduce a new generic hugepages abstraction and move the THP mode
detection and default page size probing there. The malloc code now
calls into the generic helpers instead of duplicating the sysfs
parsing.

There is no functional change. This is a pure refactoring to make
the THP detection reusable outside of malloc.

* malloc/arena.c (__ptmalloc_init):
Rename DEFAULT_THP_PAGESIZE to MALLOC_DEFAULT_THP_PAGESIZE.
Rename malloc_thp_mode_madvise to hugepages_thp_mode_madvise.
* malloc/malloc.c (malloc_par): Use hugepages_thp_mode_t.
(madvise_thp): Adjust enum usage.
(do_set_hugetlb): Use __hugepages_thp_mode and updated enum.
* sysdeps/generic/hugepages.h: New file.
Define hugepages_thp_mode_t and declare helpers.
* sysdeps/generic/hugepages.c: New file.
Provide generic stubs.
* sysdeps/unix/sysv/linux/hugepages.c: New file.
Provide Linux implementation reading THP sysfs files.
* sysdeps/generic/malloc-hugepages.c
(__malloc_default_thp_pagesize): Delegate to
__hugepages_default_thp_pagesize.
* sysdeps/generic/malloc-hugepages.h:
Include <hugepages.h>.
Rename DEFAULT_THP_PAGESIZE to MALLOC_DEFAULT_THP_PAGESIZE.
Remove malloc_thp_mode_t and __malloc_thp_mode.
* sysdeps/unix/sysv/linux/malloc-hugepages.c
(__malloc_default_thp_pagesize): Use
MALLOC_DEFAULT_THP_PAGESIZE and __hugepages_default_thp_pagesize.
* sysdeps/unix/sysv/linux/aarch64/malloc-hugepages.h:
Rename DEFAULT_THP_PAGESIZE to MALLOC_DEFAULT_THP_PAGESIZE.
* sysdeps/generic/Makefile: Add hugepages to sysdep routines.

Signed-off-by: WANG Rui <wangrui@loongson.cn>
---
 malloc/arena.c                                | 12 +--
 malloc/malloc.c                               | 14 ++--
 sysdeps/generic/Makefile                      |  8 +-
 sysdeps/generic/hugepages.c                   | 31 ++++++++
 sysdeps/generic/hugepages.h                   | 35 +++++++++
 sysdeps/generic/malloc-hugepages.c            |  8 +-
 sysdeps/generic/malloc-hugepages.h            | 15 +---
 .../sysv/linux/aarch64/malloc-hugepages.h     |  2 +-
 sysdeps/unix/sysv/linux/hugepages.c           | 77 +++++++++++++++++++
 sysdeps/unix/sysv/linux/malloc-hugepages.c    | 59 +-------------
 10 files changed, 171 insertions(+), 90 deletions(-)
 create mode 100644 sysdeps/generic/hugepages.c
 create mode 100644 sysdeps/generic/hugepages.h
 create mode 100644 sysdeps/unix/sysv/linux/hugepages.c

diff --git a/malloc/arena.c b/malloc/arena.c
index 75f2f32b5f6..8576222d82d 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -275,13 +275,13 @@ __ptmalloc_init (void)
     __always_fail_morecore = true;
 #endif
 
-  /* Enable THP if DEFAULT_THP_PAGESIZE is non-zero.  Avoid quering the THP
-     page size or mode since accessing /sys/kernel/mm is relatively slow and
-     might not be accessible in containers.  */
-  if (DEFAULT_THP_PAGESIZE > 0)
+  /* Enable THP if MALLOC_DEFAULT_THP_PAGESIZE is non-zero.  Avoid quering
+     the THP page size or mode since accessing /sys/kernel/mm is relatively
+     slow and might not be accessible in containers.  */
+  if (MALLOC_DEFAULT_THP_PAGESIZE > 0)
     {
-      mp_.thp_mode = malloc_thp_mode_madvise;
-      mp_.thp_pagesize = DEFAULT_THP_PAGESIZE;
+      mp_.thp_mode = hugepages_thp_mode_madvise;
+      mp_.thp_pagesize = MALLOC_DEFAULT_THP_PAGESIZE;
     }
 
   thread_arena = &main_arena;
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 0037d1fd2d5..e080a04ad33 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -1762,7 +1762,7 @@ struct malloc_par
   INTERNAL_SIZE_T arena_max;
 
   /* Transparent Large Page support.  */
-  enum malloc_thp_mode_t thp_mode;
+  enum hugepages_thp_mode_t thp_mode;
   INTERNAL_SIZE_T thp_pagesize;
   /* A value different than 0 means to align mmap allocation to hp_pagesize
      add hp_flags on flags.  */
@@ -1817,7 +1817,7 @@ static struct malloc_par mp_ =
   .trim_threshold = DEFAULT_TRIM_THRESHOLD,
 #define NARENAS_FROM_NCORES(n) ((n) * (sizeof (long) == 4 ? 2 : 8))
   .arena_test = NARENAS_FROM_NCORES (1),
-  .thp_mode = malloc_thp_mode_not_supported
+  .thp_mode = hugepages_thp_mode_not_supported
 #if USE_TCACHE
   ,
   .tcache_count = TCACHE_FILL_COUNT,
@@ -1899,7 +1899,7 @@ madvise_thp (void *p, INTERNAL_SIZE_T size)
 
   /* Only use __madvise if the system is using 'madvise' mode and the size
      is at least a huge page, otherwise the call is wasteful. */
-  if (mp_.thp_mode != malloc_thp_mode_madvise || size < mp_.thp_pagesize)
+  if (mp_.thp_mode != hugepages_thp_mode_madvise || size < mp_.thp_pagesize)
     return;
 
   /* Linux requires the input address to be page-aligned, and unaligned
@@ -5040,12 +5040,12 @@ static __always_inline int
 do_set_hugetlb (size_t value)
 {
   if (value == 0)
-    mp_.thp_mode = malloc_thp_mode_never;
+    mp_.thp_mode = hugepages_thp_mode_never;
   else if (value == 1)
     {
-      mp_.thp_mode = __malloc_thp_mode ();
-      if (mp_.thp_mode == malloc_thp_mode_madvise
-          || mp_.thp_mode == malloc_thp_mode_always)
+      mp_.thp_mode = __hugepages_thp_mode ();
+      if (mp_.thp_mode == hugepages_thp_mode_madvise
+          || mp_.thp_mode == hugepages_thp_mode_always)
 	mp_.thp_pagesize = __malloc_default_thp_pagesize ();
     }
   else if (value >= 2)
diff --git a/sysdeps/generic/Makefile b/sysdeps/generic/Makefile
index 0c25592f35b..9704e3f21fe 100644
--- a/sysdeps/generic/Makefile
+++ b/sysdeps/generic/Makefile
@@ -32,9 +32,13 @@ endif
 endif
 
 ifeq ($(subdir),malloc)
-sysdep_malloc_debug_routines += malloc-hugepages
+sysdep_malloc_debug_routines += \
+  hugepages \
+  malloc-hugepages
 endif
 
 ifeq ($(subdir),misc)
-sysdep_routines += malloc-hugepages
+sysdep_routines += \
+  hugepages \
+  malloc-hugepages
 endif
diff --git a/sysdeps/generic/hugepages.c b/sysdeps/generic/hugepages.c
new file mode 100644
index 00000000000..961a256c152
--- /dev/null
+++ b/sysdeps/generic/hugepages.c
@@ -0,0 +1,31 @@
+/* Huge Page support.  Generic implementation.
+   Copyright (C) 2021-2026 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <https://www.gnu.org/licenses/>.  */
+
+#include <hugepages.h>
+
+unsigned long int
+__hugepages_default_thp_pagesize (void)
+{
+  return 0;
+}
+
+enum hugepages_thp_mode_t
+__hugepages_thp_mode (void)
+{
+  return hugepages_thp_mode_not_supported;
+}
diff --git a/sysdeps/generic/hugepages.h b/sysdeps/generic/hugepages.h
new file mode 100644
index 00000000000..f9e2569e9b5
--- /dev/null
+++ b/sysdeps/generic/hugepages.h
@@ -0,0 +1,35 @@
+/* Huge page support.  Generic implementation.
+   Copyright (C) 2021-2026 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <https://www.gnu.org/licenses/>.  */
+
+#ifndef _HUGEPAGES_H
+#define _HUGEPAGES_H
+
+/* Return the default transparent huge page size.  */
+unsigned long int __hugepages_default_thp_pagesize (void) attribute_hidden;
+
+enum hugepages_thp_mode_t
+{
+  hugepages_thp_mode_always,
+  hugepages_thp_mode_madvise,
+  hugepages_thp_mode_never,
+  hugepages_thp_mode_not_supported
+};
+
+enum hugepages_thp_mode_t __hugepages_thp_mode (void) attribute_hidden;
+
+#endif /* _HUGEPAGES_H */
diff --git a/sysdeps/generic/malloc-hugepages.c b/sysdeps/generic/malloc-hugepages.c
index 57b82a2438d..2a64a6596ca 100644
--- a/sysdeps/generic/malloc-hugepages.c
+++ b/sysdeps/generic/malloc-hugepages.c
@@ -1,4 +1,4 @@
-/* Huge Page support.  Generic implementation.
+/* Malloc huge Page support.  Generic implementation.
    Copyright (C) 2021-2026 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -24,12 +24,6 @@ __malloc_default_thp_pagesize (void)
   return 0;
 }
 
-enum malloc_thp_mode_t
-__malloc_thp_mode (void)
-{
-  return malloc_thp_mode_not_supported;
-}
-
 /* Return the default transparent huge page size.  */
 void
 __malloc_hugepage_config (size_t requested, size_t *pagesize, int *flags)
diff --git a/sysdeps/generic/malloc-hugepages.h b/sysdeps/generic/malloc-hugepages.h
index ab2690f7b8a..7dcab39047e 100644
--- a/sysdeps/generic/malloc-hugepages.h
+++ b/sysdeps/generic/malloc-hugepages.h
@@ -20,20 +20,11 @@
 #define _MALLOC_HUGEPAGES_H
 
 #include <stddef.h>
+#include <hugepages.h>
 
 /* Return the default transparent huge page size.  */
 unsigned long int __malloc_default_thp_pagesize (void) attribute_hidden;
 
-enum malloc_thp_mode_t
-{
-  malloc_thp_mode_always,
-  malloc_thp_mode_madvise,
-  malloc_thp_mode_never,
-  malloc_thp_mode_not_supported
-};
-
-enum malloc_thp_mode_t __malloc_thp_mode (void) attribute_hidden;
-
 /* Return the supported huge page size from the REQUESTED sizes on PAGESIZE
    along with the required extra mmap flags on FLAGS,  Requesting the value
    of 0 returns the default huge page size, otherwise the value will be
@@ -41,8 +32,8 @@ enum malloc_thp_mode_t __malloc_thp_mode (void) attribute_hidden;
 void __malloc_hugepage_config (size_t requested, size_t *pagesize, int *flags)
      attribute_hidden;
 
-#ifndef DEFAULT_THP_PAGESIZE
-# define DEFAULT_THP_PAGESIZE	0
+#ifndef MALLOC_DEFAULT_THP_PAGESIZE
+# define MALLOC_DEFAULT_THP_PAGESIZE	0
 #endif
 
 #endif /* _MALLOC_HUGEPAGES_H */
diff --git a/sysdeps/unix/sysv/linux/aarch64/malloc-hugepages.h b/sysdeps/unix/sysv/linux/aarch64/malloc-hugepages.h
index 2204112e4e5..55f913b5d3b 100644
--- a/sysdeps/unix/sysv/linux/aarch64/malloc-hugepages.h
+++ b/sysdeps/unix/sysv/linux/aarch64/malloc-hugepages.h
@@ -16,6 +16,6 @@
    License along with the GNU C Library; see the file COPYING.LIB.  If
    not, see <https://www.gnu.org/licenses/>.  */
 
-#define DEFAULT_THP_PAGESIZE	(1UL << 21)
+#define MALLOC_DEFAULT_THP_PAGESIZE	(1UL << 21)
 
 #include_next <malloc-hugepages.h>
diff --git a/sysdeps/unix/sysv/linux/hugepages.c b/sysdeps/unix/sysv/linux/hugepages.c
new file mode 100644
index 00000000000..20ddca343f7
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/hugepages.c
@@ -0,0 +1,77 @@
+/* Huge Page support.  Linux implementation.
+   Copyright (C) 2021-2026 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <https://www.gnu.org/licenses/>.  */
+
+#include <hugepages.h>
+#include <intprops.h>
+#include <not-cancel.h>
+
+unsigned long int
+__hugepages_default_thp_pagesize (void)
+{
+  int fd = __open64_nocancel (
+    "/sys/kernel/mm/transparent_hugepage/hpage_pmd_size", O_RDONLY);
+  if (fd == -1)
+    return 0;
+
+  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;
+
+  unsigned long int r = 0;
+  for (ssize_t i = 0; i < s; i++)
+    {
+      if (str[i] == '\n')
+	break;
+      r *= 10;
+      r += str[i] - '0';
+    }
+  return r;
+}
+
+enum hugepages_thp_mode_t
+__hugepages_thp_mode (void)
+{
+  int fd = __open64_nocancel ("/sys/kernel/mm/transparent_hugepage/enabled",
+			      O_RDONLY);
+  if (fd == -1)
+    return hugepages_thp_mode_not_supported;
+
+  static const char mode_always[]  = "[always] madvise never\n";
+  static const char mode_madvise[] = "always [madvise] never\n";
+  static const char mode_never[]   = "always madvise [never]\n";
+
+  char str[sizeof(mode_always)];
+  ssize_t s = __read_nocancel (fd, str, sizeof (str));
+  if (s >= sizeof str || s < 0)
+    return hugepages_thp_mode_not_supported;
+  str[s] = '\0';
+  __close_nocancel (fd);
+
+  if (s == sizeof (mode_always) - 1)
+    {
+      if (strcmp (str, mode_always) == 0)
+	return hugepages_thp_mode_always;
+      else if (strcmp (str, mode_madvise) == 0)
+	return hugepages_thp_mode_madvise;
+      else if (strcmp (str, mode_never) == 0)
+	return hugepages_thp_mode_never;
+    }
+  return hugepages_thp_mode_not_supported;
+}
diff --git a/sysdeps/unix/sysv/linux/malloc-hugepages.c b/sysdeps/unix/sysv/linux/malloc-hugepages.c
index 77b49374e60..d0b2c53740c 100644
--- a/sysdeps/unix/sysv/linux/malloc-hugepages.c
+++ b/sysdeps/unix/sysv/linux/malloc-hugepages.c
@@ -1,4 +1,4 @@
-/* Huge Page support.  Linux implementation.
+/* Malloc huge Page support.  Linux implementation.
    Copyright (C) 2021-2026 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -16,7 +16,6 @@
    License along with the GNU C Library; see the file COPYING.LIB.  If
    not, see <https://www.gnu.org/licenses/>.  */
 
-#include <intprops.h>
 #include <dirent.h>
 #include <malloc-hugepages.h>
 #include <not-cancel.h>
@@ -25,60 +24,10 @@
 unsigned long int
 __malloc_default_thp_pagesize (void)
 {
-  if (DEFAULT_THP_PAGESIZE != 0)
-    return DEFAULT_THP_PAGESIZE;
+  if (MALLOC_DEFAULT_THP_PAGESIZE != 0)
+    return MALLOC_DEFAULT_THP_PAGESIZE;
 
-  int fd = __open64_nocancel (
-    "/sys/kernel/mm/transparent_hugepage/hpage_pmd_size", O_RDONLY);
-  if (fd == -1)
-    return 0;
-
-  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;
-
-  unsigned long int r = 0;
-  for (ssize_t i = 0; i < s; i++)
-    {
-      if (str[i] == '\n')
-	break;
-      r *= 10;
-      r += str[i] - '0';
-    }
-  return r;
-}
-
-enum malloc_thp_mode_t
-__malloc_thp_mode (void)
-{
-  int fd = __open64_nocancel ("/sys/kernel/mm/transparent_hugepage/enabled",
-			      O_RDONLY);
-  if (fd == -1)
-    return malloc_thp_mode_not_supported;
-
-  static const char mode_always[]  = "[always] madvise never\n";
-  static const char mode_madvise[] = "always [madvise] never\n";
-  static const char mode_never[]   = "always madvise [never]\n";
-
-  char str[sizeof(mode_always)];
-  ssize_t s = __read_nocancel (fd, str, sizeof (str));
-  if (s >= sizeof str || s < 0)
-    return malloc_thp_mode_not_supported;
-  str[s] = '\0';
-  __close_nocancel (fd);
-
-  if (s == sizeof (mode_always) - 1)
-    {
-      if (strcmp (str, mode_always) == 0)
-	return malloc_thp_mode_always;
-      else if (strcmp (str, mode_madvise) == 0)
-	return malloc_thp_mode_madvise;
-      else if (strcmp (str, mode_never) == 0)
-	return malloc_thp_mode_never;
-    }
-  return malloc_thp_mode_not_supported;
+  return __hugepages_default_thp_pagesize ();
 }
 
 static size_t
-- 
2.53.0



More information about the Libc-alpha mailing list