Transparent huge pages (THP) give another option for access to huge pages for
anonymous mappings.  This patch adds the ability to specify that the process
heap should be aligned and (if requested madvised) to be merged into huge pages
by khugepaged.  For more information on THP see
linux-2.6/Documentation/transhuge.txt.

Signed-off-by: Eric B Munson <emun...@mgebm.net>
---
 HOWTO                   |    7 +++-
 hugeutils.c             |    9 +++++
 libhugetlbfs_internal.h |    1 +
 morecore.c              |   84 ++++++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 96 insertions(+), 5 deletions(-)

diff --git a/HOWTO b/HOWTO
index 3c1f124..b0727a7 100644
--- a/HOWTO
+++ b/HOWTO
@@ -2,7 +2,7 @@ libhugetlbfs HOWTO
 ==================
 
 Author: David Gibson <d...@au1.ibm.com>, Adam Litke <a...@us.ibm.com>, and 
others
-Last updated: February 1st, 2011
+Last updated: July 11, 2011
 
 Introduction
 ============
@@ -264,6 +264,11 @@ environment variables:
   To use a specific huge page size:
        HUGETLB_MORECORE=<pagesize>
 
+  To use Transparent Huge Pages (THP):
+       HUGETLB_MORECORE=thp
+
+Note: This option requires a kernel that supports Transparent Huge Pages
+
 Usually it's preferable to set these environment variables on the
 command line of the program you wish to run, rather than using
 "export", because you'll only want to enable the hugepage malloc() for
diff --git a/hugeutils.c b/hugeutils.c
index b28bd0a..a7ccda0 100644
--- a/hugeutils.c
+++ b/hugeutils.c
@@ -335,6 +335,15 @@ void hugetlbfs_setup_env()
        __hugetlb_opts.morecore = getenv("HUGETLB_MORECORE");
        __hugetlb_opts.heapbase = getenv("HUGETLB_MORECORE_HEAPBASE");
 
+       if (__hugetlb_opts.morecore)
+               __hugetlb_opts.thp_morecore =
+                       (strcasecmp(__hugetlb_opts.morecore, "thp") == 0);
+
+       if (__hugetlb_opts.thp_morecore && __hugetlb_opts.heapbase) {
+               DEBUG("Heapbase specified with THP for morecore, ignoring 
heapbase\n");
+               __hugetlb_opts.heapbase = NULL;
+       }
+
        env = getenv("HUGETLB_FORCE_ELFMAP");
        if (env && (strcasecmp(env, "yes") == 0))
                __hugetlb_opts.force_elfmap = 1;
diff --git a/libhugetlbfs_internal.h b/libhugetlbfs_internal.h
index 97b19fa..ae8d7bc 100644
--- a/libhugetlbfs_internal.h
+++ b/libhugetlbfs_internal.h
@@ -63,6 +63,7 @@ struct libhugeopts_t {
        bool            shm_enabled;
        bool            no_reserve;
        bool            map_hugetlb;
+       bool            thp_morecore;
        unsigned long   force_elfmap;
        char            *ld_preload;
        char            *elfmap;
diff --git a/morecore.c b/morecore.c
index 6b4364c..c2a445c 100644
--- a/morecore.c
+++ b/morecore.c
@@ -202,6 +202,72 @@ static void *hugetlbfs_morecore(ptrdiff_t increment)
        return p;
 }
 
+static void *thp_morecore(ptrdiff_t increment)
+{
+       void *p;
+       long delta;
+
+       INFO("thp_morecore(%ld) = ...\n", (long)increment);
+
+       delta = (heaptop - heapbase) + increment - mapsize;
+       delta = ALIGN(delta, hpage_size);
+
+       if (delta > 0) {
+               /*
+                * This first time we expand the mapping we need to account for
+                * the initial heap mapping not necessarily being huge page
+                * aligned
+                */
+               if (!mapsize)
+                       delta = hugetlbfs_next_addr((long)heapbase + delta) -
+                                       (unsigned long)heapbase;
+
+               INFO("Adding %ld bytes to heap\n", delta);
+
+               p = sbrk(delta);
+               if (p == (void *)-1) {
+                       WARNING("sbrk returned ENOMEM\n");
+                       return NULL;
+               }
+
+               if (!mapsize) {
+                       if (heapbase && (heapbase != p)) {
+                               WARNING("Heap originates at %p instead of %p\n",
+                                       p, heapbase);
+                               if (__hugetlbfs_debug)
+                                       dump_proc_pid_maps();
+                       }
+                       heapbase = heaptop = p;
+               }
+
+               mapsize += delta;
+#ifdef MADV_HUGEPAGE
+               madvise(p, delta, MADV_HUGEPAGE);
+#endif
+       } else if (delta < 0) {
+               /* shrinking the heap */
+               if (!mapsize) {
+                       WARNING("Can't shrink an empty heap\n");
+                       return NULL;
+               }
+
+               INFO("Attempting to shrink heap by %ld bytes with sbrk\n",
+                       -delta);
+               p = sbrk(delta);
+               if (p == (void *)-1) {
+                       WARNING("Unable to shrink heap\n");
+                       return heaptop;
+               }
+
+               mapsize += delta;
+       }
+
+       p = heaptop;
+       heaptop += increment;
+       INFO("... = %p\n", p);
+       return p;
+}
+
 void hugetlbfs_setup_morecore(void)
 {
        char *ep;
@@ -222,6 +288,8 @@ void hugetlbfs_setup_morecore(void)
         */
        if (strncasecmp(__hugetlb_opts.morecore, "y", 1) == 0)
                hpage_size = gethugepagesize();
+       else if (__hugetlb_opts.thp_morecore)
+               hpage_size = kernel_default_hugepage_size();
        else
                hpage_size = parse_page_size(__hugetlb_opts.morecore);
 
@@ -237,8 +305,12 @@ void hugetlbfs_setup_morecore(void)
                return;
        }
 
-       if(__hugetlb_opts.map_hugetlb &&
-                       hpage_size == kernel_default_hugepage_size()) {
+       /*
+        * We won't need an fd for the heap mmaps if we are using MAP_HUGETLB
+        * or we are depending on transparent huge pages
+        */
+       if(__hugetlb_opts.thp_morecore || (__hugetlb_opts.map_hugetlb &&
+                       hpage_size == kernel_default_hugepage_size())) {
                heap_fd = -1;
        } else {
                if (!hugetlbfs_find_path_for_size(hpage_size)) {
@@ -262,13 +334,17 @@ void hugetlbfs_setup_morecore(void)
                }
        } else {
                heapaddr = (unsigned long)sbrk(0);
-               heapaddr = hugetlbfs_next_addr(heapaddr);
+               if (!__hugetlb_opts.thp_morecore)
+                       heapaddr = hugetlbfs_next_addr(heapaddr);
        }
 
        INFO("setup_morecore(): heapaddr = 0x%lx\n", heapaddr);
 
        heaptop = heapbase = (void *)heapaddr;
-       __morecore = &hugetlbfs_morecore;
+       if (__hugetlb_opts.thp_morecore)
+               __morecore = &thp_morecore;
+       else
+               __morecore = &hugetlbfs_morecore;
 
        /* Set some allocator options more appropriate for hugepages */
 
-- 
1.7.4.1


------------------------------------------------------------------------------
BlackBerry&reg; DevCon Americas, Oct. 18-20, San Francisco, CA
Learn about the latest advances in developing for the 
BlackBerry&reg; mobile platform with sessions, labs & more.
See new tools and technologies. Register for BlackBerry&reg; DevCon today!
http://p.sf.net/sfu/rim-devcon-copy1 
_______________________________________________
Libhugetlbfs-devel mailing list
Libhugetlbfs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libhugetlbfs-devel

Reply via email to