Allow hugetlbfs_morecore to shrink the heap.
Signed-off-by: Andrew Hastings <[EMAIL PROTECTED]> on behalf of Cray Inc.
---
I've run the test suite with this on x86_64 and PPC64.
This is version 2 of the patch, updated to reflect Nish's comments.
HOWTO | 4 ---
morecore.c | 67 +++++++++++++++++++++++++++++++++++++++--------------
tests/Makefile | 2 -
tests/heapshrink.c | 48 +++++++++++++++++++++++++++++++++++++
tests/run_tests.sh | 2 +
5 files changed, 101 insertions(+), 22 deletions(-)
diff -ruNp libhugetlbfs-1.2-rename-newsize/HOWTO libhugetlbfs-1.2-shrink/HOWTO
--- libhugetlbfs-1.2-rename-newsize/HOWTO 2007-11-05 18:19:31.769853000
-0600
+++ libhugetlbfs-1.2-shrink/HOWTO 2007-11-06 09:19:13.562467000 -0600
@@ -208,10 +208,6 @@ segment); for 64-bit PowerPC binaries th
multiple of 1TB. On all other platforms the address is rounded-up to
the size of a hugepage.
-Note: The current implementation of hugepage malloc disables trimming.
-Therefore hugetlb memory allocated from the system will not be returned on
-free().
-
Using hugepage text, data, or BSS
---------------------------------
diff -ruNp libhugetlbfs-1.2-rename-newsize/morecore.c
libhugetlbfs-1.2-shrink/morecore.c
--- libhugetlbfs-1.2-rename-newsize/morecore.c 2007-11-05 18:20:06.831195000
-0600
+++ libhugetlbfs-1.2-shrink/morecore.c 2007-11-06 09:27:24.139816000 -0600
@@ -70,7 +70,7 @@ static void *hugetlbfs_morecore(ptrdiff_
{
int ret;
void *p;
- long delta = 0;
+ long delta;
DEBUG("hugetlbfs_morecore(%ld) = ...\n", (long)increment);
@@ -83,13 +83,11 @@ static void *hugetlbfs_morecore(ptrdiff_
DEBUG("heapbase = %p, heaptop = %p, mapsize = %lx, delta=%ld\n",
heapbase, heaptop, mapsize, delta);
- /* growing the heap */
+ /* align to multiple of hugepagesize. */
+ delta = ALIGN(delta, blocksize);
+
if (delta > 0) {
- /*
- * convert our request to a multiple of hugepages
- * we will have more space allocated then used, basically
- */
- delta = ALIGN(delta, blocksize);
+ /* growing the heap */
DEBUG("Attempting to map %ld bytes\n", delta);
@@ -134,6 +132,50 @@ static void *hugetlbfs_morecore(ptrdiff_
/* we now have mmap'd further */
mapsize += delta;
+ } else if (delta < 0) {
+ /* shrinking the heap */
+
+ if (!mapsize) {
+ WARNING("Can't shrink empty heap!");
+ return NULL;
+ }
+
+ /*
+ * If we are forced to change the heapaddr from the
+ * original brk() value we have violated brk semantics
+ * (which we are not supposed to do). This shouldn't
+ * pose a problem until glibc tries to trim the heap to an
+ * address lower than what we aligned heapaddr to. At that
+ * point the alignment "gap" causes heap corruption.
+ * So we don't allow the heap to shrink below heapbase.
+ */
+ if (mapsize + delta < 0) { /* remember: delta is negative */
+ WARNING("Unable to shrink heap below %p\n", heapbase);
+ /* unmap just what is currently mapped */
+ delta = -mapsize;
+ /* we need heaptop + increment == heapbase, so: */
+ increment = heapbase - heaptop;
+ }
+ DEBUG("Attempting to unmap %ld bytes @ %p\n", -delta,
+ heapbase + mapsize + delta);
+ ret = munmap(heapbase + mapsize + delta, -delta);
+ if (ret) {
+ WARNING("Unmapping failed in hugetlbfs_morecore(): "
+ "%s\n", strerror(errno));
+ } else {
+
+ /*
+ * Now shrink the hugetlbfs file.
+ */
+ mapsize += delta;
+ ret = ftruncate(heap_fd, mapsize);
+ if (ret) {
+ WARNING("Couldn't truncate hugetlbfs file in "
+ "hugetlbfs_morecore(): %s\n",
+ strerror(errno));
+ }
+ }
+
}
/* heap is continuous */
@@ -191,16 +233,7 @@ static void __attribute__((constructor))
/* Set some allocator options more appropriate for hugepages */
- /* XXX: This morecore implementation does not support trimming!
- * If we are forced to change the heapaddr from the original brk()
- * value we have violated brk semantics (which we are not supposed to
- * do). This shouldn't pose a problem until glibc tries to trim the
- * heap to an address lower than what we aligned heapaddr to. At that
- * point the alignment "gap" causes heap corruption.
- *
- * So, for now, disable heap trimming.
- */
- mallopt(M_TRIM_THRESHOLD, -1);
+ mallopt(M_TRIM_THRESHOLD, blocksize / 2);
mallopt(M_TOP_PAD, blocksize / 2);
/* we always want to use our morecore, not ordinary mmap().
* This doesn't appear to prohibit malloc() from falling back
diff -ruNp libhugetlbfs-1.2-rename-newsize/tests/Makefile
libhugetlbfs-1.2-shrink/tests/Makefile
--- libhugetlbfs-1.2-rename-newsize/tests/Makefile 2007-11-05
18:19:32.078268000 -0600
+++ libhugetlbfs-1.2-shrink/tests/Makefile 2007-11-01 17:51:18.000000000
-0500
@@ -9,7 +9,7 @@ LIB_TESTS = gethugepagesize test_root fi
misaligned_offset brk_near_huge task-size-overrun stack_grow_into_huge
LIB_TESTS_64 = straddle_4GB huge_at_4GB_normal_below \
huge_below_4GB_normal_above
-NOLIB_TESTS = malloc malloc_manysmall dummy
+NOLIB_TESTS = malloc malloc_manysmall dummy heapshrink
LDSCRIPT_TESTS = zero_filesize_segment
HUGELINK_TESTS = linkhuge linkhuge_nofd linkshare
STRESS_TESTS = mmap-gettest mmap-cow shm-gettest shm-getraw shm-fork
diff -ruNp libhugetlbfs-1.2-rename-newsize/tests/heapshrink.c
libhugetlbfs-1.2-shrink/tests/heapshrink.c
--- libhugetlbfs-1.2-rename-newsize/tests/heapshrink.c 1969-12-31
18:00:00.000000000 -0600
+++ libhugetlbfs-1.2-shrink/tests/heapshrink.c 2007-11-02 14:56:11.000000000
-0500
@@ -0,0 +1,48 @@
+/*
+ * Test heap shrinking for libhugetlbfs.
+ * Copyright 2007 Cray Inc. All rights reserved.
+ *
+ * This 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
+ * of the License, or (at your option) any later version.
+ *
+ * This 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "hugetests.h"
+
+#define SIZE (32 * 1024 * 1024)
+
+int main(int argc, char **argv)
+{
+ int is_huge, have_env;
+ void *p;
+
+ test_init(argc, argv);
+
+ have_env = getenv("HUGETLB_MORECORE") != NULL;
+
+ p = malloc(SIZE);
+ memset(p, 0, SIZE);
+ is_huge = test_addr_huge(p+SIZE-1) == 1;
+ if (have_env && !is_huge)
+ FAIL("Heap not on hugepages");
+ if (!have_env && is_huge)
+ FAIL("Heap unexpectedly on hugepages");
+
+ free(p);
+ if (test_addr_huge(p+SIZE-1) == 1)
+ FAIL("Heap did not shrink");
+ PASS();
+}
diff -ruNp libhugetlbfs-1.2-rename-newsize/tests/run_tests.sh
libhugetlbfs-1.2-shrink/tests/run_tests.sh
--- libhugetlbfs-1.2-rename-newsize/tests/run_tests.sh 2007-11-05
18:19:32.013862000 -0600
+++ libhugetlbfs-1.2-shrink/tests/run_tests.sh 2007-11-01 17:51:18.000000000
-0500
@@ -167,6 +167,8 @@ functional_tests () {
preload_test HUGETLB_MORECORE=yes malloc
run_test malloc_manysmall
preload_test HUGETLB_MORECORE=yes malloc_manysmall
+ run_test heapshrink
+ preload_test HUGETLB_MORECORE=yes heapshrink
elflink_test HUGETLB_VERBOSE=0 linkhuge_nofd # Lib error msgs expected
elflink_test linkhuge
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Libhugetlbfs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libhugetlbfs-devel