static int metal_init_page_sizes(void) { const int max_sizes = MAX_PAGE_SIZES - 1; long sizes[max_sizes]; /* Determine system page size. */ sizes[0] = getpagesize(); if (sizes[0] <= 0) { metal_log(METAL_LOG_ERROR, "failed to get page size\n"); return -ENOSYS; } _metal.page_size = sizes[0]; _metal.page_shift = metal_log2(sizes[0]); metal_add_page_size(_metal.tmp_path, _metal.page_shift, 0); #ifdef HAVE_HUGETLBFS_H #ifndef MAP_HUGE_SHIFT /* System does not support multiple huge page sizes. */ sizes[0] = gethugepagesize(); if (sizes[0] > 0) { metal_add_page_size(hugetlbfs_find_path(), metal_log2(sizes[0]), MAP_HUGETLB); } #else if (gethugepagesize() >= 0) { int i, count; /* System supports multiple huge page sizes. */ count = gethugepagesizes(sizes, max_sizes); for (i = 0; i < count; i++) { int shift = metal_log2(sizes[i]); if ((shift & MAP_HUGE_MASK) != shift) continue; metal_add_page_size( hugetlbfs_find_path_for_size(sizes[i]), shift, (MAP_HUGETLB | (shift << MAP_HUGE_SHIFT))); } } #endif #endif /* Finally sort the resulting array by size. */ qsort(_metal.page_sizes, _metal.num_page_sizes, sizeof(struct metal_page_size), metal_pagesize_compare); return 0; }
void hugetlbfs_setup_morecore(void) { char *ep; unsigned long heapaddr; if (! __hugetlb_opts.morecore) return; if (strcasecmp(__hugetlb_opts.morecore, "no") == 0) { INFO("HUGETLB_MORECORE=%s, not setting up morecore\n", __hugetlb_opts.morecore); return; } /* * Determine the page size that will be used for the heap. * This can be set explicitly by setting HUGETLB_MORECORE to a valid * page size string or by setting HUGETLB_DEFAULT_PAGE_SIZE. */ 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); if (hpage_size <= 0) { if (errno == ENOSYS) WARNING("Hugepages unavailable\n"); else if (errno == EOVERFLOW || errno == ERANGE) WARNING("Hugepage size too large\n"); else if (errno == EINVAL) WARNING("Invalid huge page size\n"); else WARNING("Hugepage size (%s)\n", strerror(errno)); return; } /* * 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)) { WARNING("Hugepage size %li unavailable", hpage_size); return; } heap_fd = hugetlbfs_unlinked_fd_for_size(hpage_size); if (heap_fd < 0) { WARNING("Couldn't open hugetlbfs file for morecore\n"); return; } } /* * THP morecore uses sbrk to allocate more heap space, counting on the * kernel to back the area with THP. So setting heapbase is * meaningless if thp_morecore is used. */ if (!__hugetlb_opts.thp_morecore && __hugetlb_opts.heapbase) { heapaddr = strtoul(__hugetlb_opts.heapbase, &ep, 16); if (*ep != '\0') { WARNING("Can't parse HUGETLB_MORECORE_HEAPBASE: %s\n", __hugetlb_opts.heapbase); return; } } else { heapaddr = (unsigned long)sbrk(0); if (!__hugetlb_opts.thp_morecore) heapaddr = hugetlbfs_next_addr(heapaddr); } INFO("setup_morecore(): heapaddr = 0x%lx\n", heapaddr); heaptop = heapbase = (void *)heapaddr; if (__hugetlb_opts.thp_morecore) __morecore = &thp_morecore; else __morecore = &hugetlbfs_morecore; /* Set some allocator options more appropriate for hugepages */ if (__hugetlb_opts.shrink_ok) mallopt(M_TRIM_THRESHOLD, hpage_size / 2); else mallopt(M_TRIM_THRESHOLD, -1); mallopt(M_TOP_PAD, hpage_size / 2); /* we always want to use our morecore, not ordinary mmap(). * This doesn't appear to prohibit malloc() from falling back * to mmap() if we run out of hugepages. */ mallopt(M_MMAP_MAX, 0); }