@@ -64,6 +64,11 @@ glibc {
env_alias: MALLOC_MMAP_MAX_
security_level: SXID_IGNORE
}
+ heap_max {
+ type: INT_32
+ env_alias: MALLOC_HEAP_MAX_
+ security_level: SXID_IGNORE
+ }
arena_max {
type: SIZE_T
env_alias: MALLOC_ARENA_MAX
@@ -26,14 +26,7 @@
/* Compile-time constants. */
-#define HEAP_MIN_SIZE (32 * 1024)
-#ifndef HEAP_MAX_SIZE
-# ifdef DEFAULT_MMAP_THRESHOLD_MAX
-# define HEAP_MAX_SIZE (2 * DEFAULT_MMAP_THRESHOLD_MAX)
-# else
-# define HEAP_MAX_SIZE (1024 * 1024) /* must be a power of two */
-# endif
-#endif
+#define HEAP_MAX_SIZE (mp_.heap_max)
/* HEAP_MIN_SIZE and HEAP_MAX_SIZE limit the size of mmap()ed heaps
that are dynamically created for multi-threaded programs. The
@@ -226,6 +219,7 @@ TUNABLE_CALLBACK (__name) (tunable_val_t *valp) \
TUNABLE_CALLBACK_FNDECL (set_mmap_threshold, size_t)
TUNABLE_CALLBACK_FNDECL (set_mmaps_max, int32_t)
+TUNABLE_CALLBACK_FNDECL (set_heap_max, int32_t)
TUNABLE_CALLBACK_FNDECL (set_top_pad, size_t)
TUNABLE_CALLBACK_FNDECL (set_perturb_byte, int32_t)
TUNABLE_CALLBACK_FNDECL (set_trim_threshold, size_t)
@@ -316,6 +310,7 @@ ptmalloc_init (void)
TUNABLE_GET (mmap_threshold, size_t, TUNABLE_CALLBACK (set_mmap_threshold));
TUNABLE_GET (trim_threshold, size_t, TUNABLE_CALLBACK (set_trim_threshold));
TUNABLE_GET (mmap_max, int32_t, TUNABLE_CALLBACK (set_mmaps_max));
+ TUNABLE_GET (heap_max, int32_t, TUNABLE_CALLBACK (set_heap_max));
TUNABLE_GET (arena_max, size_t, TUNABLE_CALLBACK (set_arena_max));
TUNABLE_GET (arena_test, size_t, TUNABLE_CALLBACK (set_arena_test));
# if USE_TCACHE
@@ -365,6 +360,8 @@ ptmalloc_init (void)
__libc_mallopt (M_MMAP_MAX, atoi (&envline[10]));
else if (memcmp (envline, "ARENA_MAX", 9) == 0)
__libc_mallopt (M_ARENA_MAX, atoi (&envline[10]));
+ else if (memcmp (envline, "HEAP_MAX_", 9) == 0)
+ __libc_mallopt (M_HEAP_MAX, atoi (&envline[10]));
}
break;
case 10:
@@ -472,7 +469,7 @@ new_heap (size_t size, size_t top_pad)
mapping (on Linux, this is the case for all non-writable mappings
anyway). */
p2 = MAP_FAILED;
- if (aligned_heap_area)
+ if (aligned_heap_area && !mp_.heap_max_specified)
{
p2 = (char *) MMAP (aligned_heap_area, HEAP_MAX_SIZE, PROT_NONE,
MAP_NORESERVE);
@@ -493,7 +490,7 @@ new_heap (size_t size, size_t top_pad)
ul = p2 - p1;
if (ul)
__munmap (p1, ul);
- else
+ else if (!mp_.heap_max_specified)
aligned_heap_area = p2 + HEAP_MAX_SIZE;
__munmap (p2 + HEAP_MAX_SIZE, HEAP_MAX_SIZE - ul);
}
@@ -981,6 +981,13 @@ int __posix_memalign(void **, size_t, size_t);
#define DEFAULT_MMAP_MAX (65536)
#endif
+#ifdef HEAP_MAX_SIZE
+# define DEFAULT_HEAP_MAX_SIZE (2 * DEFAULT_MMAP_THREASHOLD_MAX)
+#else
+# define DEFAULT_HEAP_MAX_SIZE (1024 * 1024) /* must be power of two */
+#endif
+#define HEAP_MIN_SIZE (32 * 1024)
+
#include <malloc.h>
#ifndef RETURN_ADDRESS
@@ -1713,6 +1720,8 @@ struct malloc_par
it manually, at which point we need to disable any
dynamic behavior. */
int no_dyn_threshold;
+ int heap_max;
+ int heap_max_specified;
/* Statistics */
INTERNAL_SIZE_T mmapped_mem;
@@ -1766,6 +1775,8 @@ static struct malloc_par mp_ =
.top_pad = DEFAULT_TOP_PAD,
.n_mmaps_max = DEFAULT_MMAP_MAX,
.mmap_threshold = DEFAULT_MMAP_THRESHOLD,
+ .heap_max = DEFAULT_HEAP_MAX_SIZE,
+ .heap_max_specified = 0,
.trim_threshold = DEFAULT_TRIM_THRESHOLD,
#define NARENAS_FROM_NCORES(n) ((n) * (sizeof (long) == 4 ? 2 : 8))
.arena_test = NARENAS_FROM_NCORES (1)
@@ -5052,6 +5063,16 @@ do_set_mmaps_max (int32_t value)
return 1;
}
+static __always_inline int
+do_set_heap_max (int32_t value)
+{
+ LIBC_PROBE (memory_mallopt_heap_max, 3, value, mp_.heap_max,
+ mp_.no_dyn_threshold);
+ mp_.heap_max = value;
+ mp_.heap_max_specified = 1;
+ return 1;
+}
+
static __always_inline int
do_set_mallopt_check (int32_t value)
{
@@ -5166,6 +5187,10 @@ __libc_mallopt (int param_number, int value)
do_set_mmaps_max (value);
break;
+ case M_HEAP_MAX:
+ do_set_heap_max (value);
+ break;
+
case M_CHECK_ACTION:
do_set_mallopt_check (value);
break;
@@ -124,6 +124,7 @@ extern struct mallinfo mallinfo (void) __THROW;
#define M_PERTURB -6
#define M_ARENA_TEST -7
#define M_ARENA_MAX -8
+#define M_HEAP_MAX -9
/* General SVID/XPG interface to tunable parameters. */
extern int mallopt (int __param, int __val) __THROW;
This patch is mainly to show the idea and to get feedback. Probably there might be a better implementation. This patch introduce tunable to makes heap allocator friendly to LibOS. It allows a way for the LibOS to adjust allocation size. LibOS may have its own virtual address space layout (duto software or hardware e.g. SGX) and as a result, it may have the limited heap. If heap allocator tries to allocate too large memory, ENOMEM on startup. Signed-off-by: Isaku Yamahata <isaku.yamahata@gmail.com> --- elf/dl-tunables.list | 5 +++++ malloc/arena.c | 17 +++++++---------- malloc/malloc.c | 25 +++++++++++++++++++++++++ malloc/malloc.h | 1 + 4 files changed, 38 insertions(+), 10 deletions(-)