hugetlbfs_prefault relies on having a file descriptor associated with the huge page backed region to prefault the huge pages. This patch gives an alternative for prefaulting which will be used when the kernel supports MAP_HUGETLB.
Signed-off-by: Eric B Munson <[email protected]> --- hugeutils.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 62 insertions(+), 15 deletions(-) diff --git a/hugeutils.c b/hugeutils.c index 5616d60..f8c3421 100644 --- a/hugeutils.c +++ b/hugeutils.c @@ -52,6 +52,8 @@ struct libhugeopts_t __hugetlb_opts; static int hugepagesize_errno; /* = 0 */ +static int has_segv; /* = 0 */ + #define MAX_HPAGE_SIZES 10 static struct hpage_size hpage_sizes[MAX_HPAGE_SIZES]; static int nr_hpage_sizes; @@ -947,30 +949,41 @@ int hugetlbfs_unlinked_fd(void) return -1; } +static void handle_segv(int signal) +{ + has_segv = 1; +} + #define IOV_LEN 64 int hugetlbfs_prefault(int fd, void *addr, size_t length) { + size_t offset; + int ret; + + if (!__hugetlbfs_prefault) + return 0; + /* * The NUMA users of libhugetlbfs' malloc feature are * expected to use the numactl program to specify an * appropriate policy for hugepage allocation - * - * Use readv(2) to instantiate the hugepages unless HUGETLB_NO_PREFAULT - * is set. If we instead returned a hugepage mapping with insufficient - * hugepages, the VM system would kill the process when the - * process tried to access the missing memory. - * - * The value of this environment variable is read during library - * initialisation and sets __hugetlbfs_prefault accordingly. If - * prefaulting is enabled and we can't get all that were requested, - * -ENOMEM is returned. The caller is expected to release the entire - * mapping and optionally it may recover by mapping base pages instead. */ - if (__hugetlbfs_prefault) { - int i; - size_t offset; + + if (fd >= 0) { + /* + * Use readv(2) to instantiate the hugepages unless HUGETLB_NO_PREFAULT + * is set. If we instead returned a hugepage mapping with insufficient + * hugepages, the VM system would kill the process when the + * process tried to access the missing memory. + * + * The value of this environment variable is read during library + * initialisation and sets __hugetlbfs_prefault accordingly. If + * prefaulting is enabled and we can't get all that were requested, + * -ENOMEM is returned. The caller is expected to release the entire + * mapping and optionally it may recover by mapping base pages instead. + */ struct iovec iov[IOV_LEN]; - int ret; + int i; for (offset = 0; offset < length; ) { for (i = 0; i < IOV_LEN && offset < length; i++) { @@ -988,6 +1001,40 @@ int hugetlbfs_prefault(int fd, void *addr, size_t length) return -ENOMEM; } } + + } else { + /* + * Because the region was mmap'd with MAP_HUGETLB instead of + * using hugetlbfs_unlinked_fd we cannot use the readv trick + * to prefault each page. So instead we protect ourselves + * from SIGSEGV and try to read from and write to the first + * byte of each huge page to fault it. If we receive a + * SIGSEGV then we return -ENOMEM + */ + sighandler_t orig = signal(SIGSEGV, handle_segv); + if (orig == SIG_ERR) { + ret = errno; + WARNING("Unable to reserve %ld huge pages " + "for new region\n", + length / gethugepagesize()); + return ret; + } + + for (offset = 0; offset < length && !has_segv; + offset += gethugepagesize()) { + char *page_start = (char *)(addr + offset); + *page_start = *page_start; + } + + signal(SIGSEGV, orig); + + if (has_segv) { + has_segv = 0; + WARNING("Unable to reserve %ld huge pages " + "for new region\n", + length / gethugepagesize()); + return -ENOMEM; + } } return 0; -- 1.7.1 ------------------------------------------------------------------------------ The Next 800 Companies to Lead America's Growth: New Video Whitepaper David G. Thomson, author of the best-selling book "Blueprint to a Billion" shares his insights and actions to help propel your business during the next growth cycle. Listen Now! http://p.sf.net/sfu/SAP-dev2dev _______________________________________________ Libhugetlbfs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/libhugetlbfs-devel
