Major new features:
+* A new tunable, glibc.elf.thp, is added to map read-only segments with
+ Transparent Huge Pages (THP) if THP isn't disable in kernel. When
+ glibc.elf.thp is set to 1, malloc uses the actual kernel THP mode
+ instead of defaulting to madvise mode and madvise_thp will stop issuing
+ MADV_HUGEPAGE if kernel THP mode is always.
+
+* THP page size in malloc is capped to MAX_THP_PAGESIZE. If THP page
+ size is above MAX_THP_PAGESIZE, THP in malloc is disabled.
+
* Additional optimized and correctly rounded mathematical functions have
been imported from the CORE-MATH project, in particular cosh, sinh, and
tanh.
.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,
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;
}
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_capped_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_capped_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,
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
# define MAX_THP_PAGESIZE (32 * 1024 * 1024)
#endif
+/* If THP page size is above MAX_THP_PAGESIZE, return 0 to cap the THP
+ size at MAX_THP_PAGESIZE to avoid over-aligning on systems with very
+ large normal pages (like 64K pages with 512M huge pages). */
+
+static inline unsigned long int
+get_capped_thp_size (void)
+{
+ unsigned long int size = __get_thp_size ();
+ if (size > MAX_THP_PAGESIZE)
+ size = 0;
+ return size;
+}
+
#endif /* _HUGEPAGES_H */
GL(dl_thp_mode) = __get_thp_mode ();
if (GL(dl_thp_mode) == thp_mode_always
|| GL(dl_thp_mode) == thp_mode_madvise)
- {
- GL(dl_elf_thp_pagesize) = __get_thp_size ();
- /* 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_pagesize) = 0;
- }
+ GL(dl_elf_thp_pagesize) = get_capped_thp_size ();
else
GL(dl_elf_thp_pagesize) = 0;