On Fri, 2007-10-12 at 15:26 +1000, David Gibson wrote:

> Actually, it doesn't necessarily need using named hugepage files: we
> could fork() after obtaining the fd, but before mapping it.

Adam pointed that out to me as I was re-working this patch to use your
fork() suggestion. Sorry, I've been sitting on this patch while working
on the other half of a problem.


elflink: prevent segfault on 32bit PPC apps with large stack

[PPC] Prior to memory slices being added in 2.6.22, our temporary hugetlbfs
mappings are created in the segment below the stack. If a 32-bit PPC app
grows its stack larger than one segment, it will segfault because the
neighboring segment has been marked as "hugepage-only".

Providing a hint address for our temporary mappings is unreliable because,
prior to 2.6.22, if the hint address is invalid get_unmapped_area()
simplistically started at the top of the address space and searched down.
This means we could end up with the kernel picking an address that's higher
than the hint address.

To get around this limitation, David Gibson suggested forking a child to
perform the temporary hugetlbfs mappings in its own address space to avoid
tainting segments in the parent's. I have also measured a small performance
improvement, which Adam believes may be due to SLBs.

Signed-off-by: Steve Fox <[EMAIL PROTECTED]>
---

diff --git a/elflink.c b/elflink.c
index 4fce9b9..f7f5ebb 100644
--- a/elflink.c
+++ b/elflink.c
@@ -32,6 +32,7 @@
 #include <sys/file.h>
 #include <linux/unistd.h>
 #include <sys/mman.h>
+#include <sys/wait.h>
 #include <errno.h>
 #include <limits.h>
 #include <elf.h>
@@ -881,6 +882,41 @@ static int find_or_prepare_shared_file(struct seg_info 
*htlb_seg_info)
        return -1;
 }
 
+#if defined (__powerpc__) && !defined (__LP64__)
+static int arch_prepare_segment(struct seg_info *htlb_seg_info)
+{
+       int ret, pid, status;
+
+       /* Prior to 2.6.22 (which added slices), our temporary hugepage mappings
+        * are placed in the segment before the stack. This 'taints' that 
segment
+        * for be hugepage-only for the lifetime of the process, resulting in a
+        * maximum stack size of 256MB.
+        * If we instead create our hugepage mappings in a child process, we can
+        * avoid this problem.
+        */
+       if ((pid = fork()) < 0) {
+               DEBUG("fork failed");
+               return -1;
+       }
+       if (pid == 0) {
+               ret = prepare_segment(htlb_seg_info);
+               if (ret < 0)
+                       exit(1);
+               else
+                       exit(0);
+       }
+       ret = waitpid(pid, &status, 0);
+       if (ret == -1) {
+               DEBUG("waitpid failed");
+               return -1;
+       }
+
+       return 0;
+}
+#else
+#define arch_prepare_segment prepare_segment
+#endif
+
 /**
  * obtain_prepared_file - multiplex callers depending on if
  * sharing or not
@@ -909,7 +945,7 @@ static int obtain_prepared_file(struct seg_info 
*htlb_seg_info)
                return -1;
        htlb_seg_info->fd = fd;
 
-       ret = prepare_segment(htlb_seg_info);
+       ret = arch_prepare_segment(htlb_seg_info);
        if (ret < 0) {
                DEBUG("Failed to prepare segment\n");
                return -1;


-- 

Steve Fox
IBM Linux Technology Center

-------------------------------------------------------------------------
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