Adjust the kernel's idea of the end of the data segment (the 'brk' value)
to match user space when we remap the data segment onto hugepages.

Signed-off-by: Andrew Hastings <[EMAIL PROTECTED]> on behalf of Cray Inc.
---

While I was running some of the libhugetlbfs linker tests under strace,
I noticed brk() was failing.  Poking around in /proc/self/maps I
discovered why.

Breaking brk() (no pun intended) is bad because (1) it causes malloc to
make two system calls every time it needs to grow the heap (a failing
sbrk and then an mmap) and (2) the process's address space ends up with
lots of little VMAs.

Tested both 32- and 64-bit binaries under SUSE 10 on x86-64.

-Andrew Hastings
 Cray Inc.

diff -ruNp libhugetlbfs-1.2/elflink.c libhugetlbfs-1.2-modified/elflink.c
--- libhugetlbfs-1.2/elflink.c  2007-09-10 08:27:44.000000000 -0500
+++ libhugetlbfs-1.2-modified/elflink.c 2007-09-18 12:17:04.932081000 -0500
@@ -923,6 +923,23 @@ static void remap_segments(struct seg_in
        long hpage_size = gethugepagesize();
        int i;
        void *p;
+       void *oldbrk, *newbrk;
+
+       /*
+        * Adjust the brk value to the end of the data segment.
+        */
+       newbrk = oldbrk = sbrk(0);
+       DEBUG("Current brk=%p\n", oldbrk);
+       for (i = 0; i < num; i++) {
+               unsigned long mapsize = ALIGN(seg[i].memsz, hpage_size);
+
+               DEBUG("%p - %p\n", seg[i].vaddr, seg[i].vaddr + mapsize);
+               if (seg[i].vaddr <= oldbrk && oldbrk < seg[i].vaddr + mapsize)
+                       newbrk = seg[i].vaddr + mapsize;
+       }
+       DEBUG("New brk=%p\n", newbrk);
+       if (newbrk != oldbrk)
+               brk(newbrk);
 
        /*
         * XXX: The bogus call to mmap below forces ld.so to resolve the
diff -ruNp libhugetlbfs-1.2/tests/Makefile 
libhugetlbfs-1.2-modified/tests/Makefile
--- libhugetlbfs-1.2/tests/Makefile     2007-09-10 08:27:44.000000000 -0500
+++ libhugetlbfs-1.2-modified/tests/Makefile    2007-09-18 12:25:43.005889000 
-0500
@@ -11,7 +11,7 @@ LIB_TESTS_64 = straddle_4GB huge_at_4GB_
        huge_below_4GB_normal_above
 NOLIB_TESTS = malloc malloc_manysmall dummy
 LDSCRIPT_TESTS = zero_filesize_segment
-HUGELINK_TESTS = linkhuge linkhuge_nofd linkshare
+HUGELINK_TESTS = linkhuge linkhuge_nofd linkshare brk-align
 STRESS_TESTS = mmap-gettest mmap-cow shm-gettest shm-getraw shm-fork
 HELPERS = get_hugetlbfs_path
 BADTOOLCHAIN = bad-toolchain.sh
diff -ruNp libhugetlbfs-1.2/tests/brk-align.c 
libhugetlbfs-1.2-modified/tests/brk-align.c
--- libhugetlbfs-1.2/tests/brk-align.c  1969-12-31 18:00:00.000000000 -0600
+++ libhugetlbfs-1.2-modified/tests/brk-align.c 2007-09-18 12:25:42.983191000 
-0500
@@ -0,0 +1,36 @@
+/*
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License.  See the file "LGPL-2.1" in the main directory of this
+ * archive for more details.
+ *
+ * Copyright 2007 Cray Inc. All Rights Reserved.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "hugetests.h"
+
+/*
+ * This test verifies that libhugetlbfs adjusts the brk value to the
+ * end of the data segment when it remaps the data segment onto hugepages.
+ */
+
+static int data = 1;
+
+int main(int argc, char **argv)
+{
+       int pagesize;
+       
+       test_init(argc, argv);
+
+       if (test_addr_huge(&data) != 1)
+               CONFIG("Data segment not on hugepage");
+
+       pagesize = getpagesize();
+       if (sbrk(pagesize) == (void *)-1)
+               FAIL("sbrk(%d) failed", pagesize);
+
+       PASS();
+}
diff -ruNp libhugetlbfs-1.2/tests/run_tests.sh 
libhugetlbfs-1.2-modified/tests/run_tests.sh
--- libhugetlbfs-1.2/tests/run_tests.sh 2007-09-10 08:27:44.000000000 -0500
+++ libhugetlbfs-1.2-modified/tests/run_tests.sh        2007-09-18 
12:04:56.933928000 -0500
@@ -169,6 +169,7 @@ functional_tests () {
     preload_test HUGETLB_MORECORE=yes malloc_manysmall
     elflink_test HUGETLB_VERBOSE=0 linkhuge_nofd # Lib error msgs expected
     elflink_test linkhuge
+    run_test xBDT.brk-align
 
 # Sharing tests
     elfshare_test linkshare

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Libhugetlbfs-devel mailing list
Libhugetlbfs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libhugetlbfs-devel

Reply via email to