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.

 morecore.c         |   63 ++++++++++++++++++++++++++++++++++++++---------------
 tests/Makefile     |    2 -
 tests/heapshrink.c |   48 ++++++++++++++++++++++++++++++++++++++++
 tests/run_tests.sh |    2 +
 4 files changed, 97 insertions(+), 18 deletions(-)

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-02 17:32:04.000000000 -0500
@@ -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,46 @@ 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) {
+                       WARNING("Unable to shrink heap below %p\n", heapbase);
+                       delta = -mapsize;
+                       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()\n");
+               } else {
+
+                       /*
+                        * Now shrink the hugetlbfs file.
+                        */
+                       mapsize += delta;
+                       ret = ftruncate(heap_fd, mapsize);
+                       if (ret) {
+                               WARNING("Couldn't toss pages in "
+                                       "hugetlbfs_morecore()\n");
+                       }
+               }
+
        }
 
        /* heap is continuous */
@@ -191,16 +229,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

Reply via email to