Exemple #1
0
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 check_free_huge_pages(int nr_pages_needed)
{
	long hpage_size = gethugepagesize();
	int freepages = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
	if (freepages < nr_pages_needed)
		CONFIG("Must have at least %i free hugepages", nr_pages_needed);
}
Exemple #3
0
/**
 * get_hugepage_region - Allocate an amount of memory backed by huge pages
 *
 * len: Size of the region to allocate
 * flags: Flags specifying the behaviour of the function
 *
 * This function allocates a region of memory backed by huge pages. Care should
 * be taken when using this function as a drop-in replacement for malloc() as
 * memory can be wasted if the length is not hugepage-aligned. This function
 * is more relaxed than get_huge_pages() in that it allows fallback to small
 * pages when requested.
 */
void *get_hugepage_region(size_t len, ghr_t flags)
{
	size_t aligned_len, wastage;
	void *buf;

	/* Catch an altogether-too easy typo */
	if (flags & GHP_MASK)
		ERROR("Improper use of GHP_* in get_hugepage_region()\n");

	/* Align the len parameter to a hugepage boundary and allocate */
	aligned_len = ALIGN(len, gethugepagesize());
	buf = get_huge_pages(aligned_len, GHP_DEFAULT);
	if (buf == NULL && (flags & GHR_FALLBACK)) {
		aligned_len = ALIGN(len, getpagesize());
		buf = fallback_base_pages(len, flags);
	}

	/* Calculate wastage for coloring */
	wastage = aligned_len - len;
	if (wastage != 0 && !(flags & GHR_COLOR))
		DEBUG("get_hugepage_region: Wasted %zd bytes due to alignment\n",
			wastage);

	/* Only colour if requested */
	if (flags & GHR_COLOR)
		buf = cachecolor(buf, len, wastage);

	return buf;
}
Exemple #4
0
int main(void)
{
	PS = getpagesize();
	HPS = gethugepagesize();

	unsigned count = hardware_corrupted();
	if (!hugetlbfs_root(hugetlbfsdir))
		err("hugetlbfs_root");
	anonymous("anonymous", 0);
	check(&count, "anonymous", 1);
	anonymous("anonymous mlock", MAP_LOCKED);
	check(&count, "anonymous mlock", 1);
	disk_backed("disk backed", 0);
	check(&count, "disk backed", 1);
	disk_backed("disk backed mlock", 0);
	check(&count, "disk backed mlock", 1);
	shm_hugepage("shm hugepage", 0);
	check(&count, "shm hugepage", HPS / PS);
	anonymous_hugepage("anonymous hugepage", 0);
	check(&count, "anonymous hugepage", HPS / PS);
	filebacked_hugepage("file backed hugepage", 0);
	check(&count, "file backed hugepage", HPS / PS);
	// add more test cases here

	return exitcode;
}
/* WARNING: This function relies on the hugetlb pool counters in a way that
 * is known to be racy.  Due to the expected usage of hugetlbfs test cases, the
 * risk of a race is acceptible.  This function should NOT be used for real
 * applications.
 */
int kernel_has_private_reservations(void)
{
	int fd;
	long t, f, r, s;
	long nt, nf, nr, ns;
	long hpage_size = gethugepagesize();
	void *map;

	/* Read pool counters */
	t = get_huge_page_counter(hpage_size, HUGEPAGES_TOTAL);
	f = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
	r = get_huge_page_counter(hpage_size, HUGEPAGES_RSVD);
	s = get_huge_page_counter(hpage_size, HUGEPAGES_SURP);

	fd = hugetlbfs_unlinked_fd();
	if (fd < 0) {
		ERROR("kernel_has_private_reservations: hugetlbfs_unlinked_fd: "
			"%s\n", strerror(errno));
		return -1;
	}
	map = mmap(NULL, hpage_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
	if (map == MAP_FAILED) {
		ERROR("kernel_has_private_reservations: mmap: %s\n",
			strerror(errno));
		return -1;
	}

	/* Recheck the counters */
	nt = get_huge_page_counter(hpage_size, HUGEPAGES_TOTAL);
	nf = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
	nr = get_huge_page_counter(hpage_size, HUGEPAGES_RSVD);
	ns = get_huge_page_counter(hpage_size, HUGEPAGES_SURP);

	munmap(map, hpage_size);
	close(fd);

	/*
	 * There are only three valid cases:
	 * 1) If a surplus page was allocated to create a reservation, all
	 *    four pool counters increment
	 * 2) All counters remain the same except for Hugepages_Rsvd, then
	 *    a reservation was created using an existing pool page.
	 * 3) All counters remain the same, indicates that no reservation has
	 *    been created
	 */
	if ((nt == t + 1) && (nf == f + 1) && (ns == s + 1) && (nr == r + 1)) {
		return 1;
	} else if ((nt == t) && (nf == f) && (ns == s)) {
		if (nr == r + 1)
			return 1;
		else if (nr == r)
			return 0;
	} else {
		ERROR("kernel_has_private_reservations: bad counter state - "
		      "T:%li F:%li R:%li S:%li -> T:%li F:%li R:%li S:%li\n",
			t, f, r, s, nt, nf, nr, ns);
	}
	return -1;
}
static void HPX_CONSTRUCTOR _system_init(void) {
  _hugepage_fd = hugetlbfs_unlinked_fd();
  if (_hugepage_fd < 0) {
    log_error("could not get huge tlb file descriptor.\n");
  }
  _hugepage_size = gethugepagesize();
  _hugepage_mask = _hugepage_size - 1;
}
Exemple #7
0
int main(int argc, char *argv[])
{
	long hpage_size;

	test_init(argc, argv);

	hpage_size = gethugepagesize();
	if (hpage_size == -1)
		PASS();

	FAIL("Mysteriously found a hugepage size of %ld\n", hpage_size);
}
Exemple #8
0
/**
 * check_swap shouldn't change the behavior of any of its
 * callers, it only prints a message to the user if something
 * is being done that might fail without swap available.  i.e.
 * resizing a huge page pool
 */
void check_swap()
{
	long swap_sz;
	long swap_total;

	swap_total = read_meminfo(SWAP_TOTAL);
	if (swap_total <= 0) {
		WARNING("There is no swap space configured, resizing hugepage pool may fail\n");
		WARNING("Use --add-temp-swap option to temporarily add swap during the resize\n");
		return;
	}

	swap_sz = read_meminfo(SWAP_FREE);
	/* meminfo keeps values in kb, but we use bytes for hpage sizes */
	swap_sz *= 1024;
	if (swap_sz <= gethugepagesize()) {
		WARNING("There is very little swap space free, resizing hugepage pool may fail\n");
		WARNING("Use --add-temp-swap option to temporarily add swap during the resize\n");
	}
}
Exemple #9
0
/**
 * get_huge_pages - Allocate an amount of memory backed by huge pages
 * len: Size of the region to allocate, must be hugepage-aligned
 * flags: Flags specifying the behaviour of the function
 *
 * This function allocates a region of memory that is backed by huge pages
 * and hugepage-aligned. This is not a suitable drop-in for malloc() but a
 * a malloc library could use this function to create a new fixed-size heap
 * similar in principal to what morecore does for glibc malloc.
 */
void *get_huge_pages(size_t len, ghp_t flags)
{
	void *buf;
	int buf_fd = -1;
	int mmap_reserve = __hugetlb_opts.no_reserve ? MAP_NORESERVE : 0;
	int mmap_hugetlb = 0;
	int ret;

	/* Catch an altogether-too easy typo */
	if (flags & GHR_MASK)
		ERROR("Improper use of GHR_* in get_huge_pages()\n");

#ifdef MAP_HUGETLB
	mmap_hugetlb = MAP_HUGETLB;
#endif

	if (__hugetlb_opts.map_hugetlb &&
			gethugepagesize() == kernel_default_hugepage_size()) {
		/* Because we can use MAP_HUGETLB, we simply mmap the region */
		buf = mmap(NULL, len, PROT_READ|PROT_WRITE,
			MAP_PRIVATE|MAP_ANONYMOUS|mmap_hugetlb|mmap_reserve,
			0, 0);
	} else {
		/* Create a file descriptor for the new region */
		buf_fd = hugetlbfs_unlinked_fd();
		if (buf_fd < 0) {
			WARNING("Couldn't open hugetlbfs file for %zd-sized buffer\n",
					len);
			return NULL;
		}

		/* Map the requested region */
		buf = mmap(NULL, len, PROT_READ|PROT_WRITE,
			MAP_PRIVATE|mmap_reserve, buf_fd, 0);
	}

	if (buf == MAP_FAILED) {
		if (buf_fd >= 0)
			close(buf_fd);

		WARNING("get_huge_pages: New region mapping failed (flags: 0x%lX): %s\n",
			flags, strerror(errno));
		return NULL;
	}

	/* Fault the region to ensure accesses succeed */
	ret = hugetlbfs_prefault(buf, len);
	if (ret != 0) {
		munmap(buf, len);
		if (buf_fd >= 0)
			close(buf_fd);

		WARNING("get_huge_pages: Prefaulting failed (flags: 0x%lX): %s\n",
			flags, strerror(ret));
		return NULL;
	}

	/* Close the file so we do not have to track the descriptor */
	if (buf_fd >= 0 && close(buf_fd) != 0) {
		WARNING("Failed to close new buffer fd: %s\n", strerror(errno));
		munmap(buf, len);
		return NULL;
	}

	/* woo, new buffer of shiny */
	return buf;
}
Exemple #10
0
static void __free_huge_pages(void *ptr, int aligned)
{
	FILE *fd;
	char line[MAPS_BUF_SZ];
	unsigned long start = 0, end = 0;
	unsigned long palign = 0, hpalign = 0;
	unsigned long hpalign_end = 0;

	/*
	 * /proc/self/maps is used to determine the length of the original
	 * allocation. As mappings are based on different files, we can
	 * assume that maps will not merge. If the hugepages were truly
	 * anonymous, this assumption would be broken.
	 */
	fd = fopen("/proc/self/maps", "r");
	if (!fd) {
		ERROR("Failed to open /proc/self/maps\n");
		return;
	}

	/*
	 * An unaligned address allocated by get_hugepage_region()
	 * could be either page or hugepage aligned
	 */
	if (!aligned) {
		palign = ALIGN_DOWN((unsigned long)ptr, getpagesize());
		hpalign = ALIGN_DOWN((unsigned long)ptr, gethugepagesize());
	}

	/* Parse /proc/maps for address ranges line by line */
	while (!feof(fd)) {
		char *bufptr;
		char *saveptr = NULL;

		/* Read a line of input */
		if (fgets(line, MAPS_BUF_SZ, fd) == NULL)
			break;

		/* Parse the line to get the start and end of each mapping */
		bufptr = strtok_r(line, " ", &saveptr);
		bufptr = strtok_r(bufptr, "-", &saveptr);
		start = strtoull(bufptr, NULL, 16);
		bufptr = strtok_r(NULL, "-", &saveptr);

		/* If the correct mapping is found, remove it */
		if (start == (unsigned long)ptr) {
			end = strtoull(bufptr, NULL, 16);
			munmap(ptr, end - start);
			break;
		}

		/* If the passed address is aligned, just move along */
		if (aligned)
			continue;

		/*
		 * If an address is hpage-aligned, record it but keep looking.
		 * We might find a page-aligned or exact address later
		 */
		if (start == hpalign) {
			hpalign_end = strtoull(bufptr, NULL, 16);
			continue;
		}

		/* If an address is page-aligned, free it */
		if (start == palign) {
			end = strtoull(bufptr, NULL, 16);
			munmap((void *)start, end - start);
			break;
		}

	}

	/*
	 * If no exact or page-aligned address was found, check for a
	 * hpage-aligned address. If found, free it, otherwise warn that
	 * the ptr pointed nowhere
	 */
	if (end == 0) {
		if (hpalign_end == 0)
			ERROR("hugepages_free using invalid or double free\n");
		else
			munmap((void *)hpalign, hpalign_end - hpalign);
	}

	fclose(fd);
}
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);
}
size_t chpl_comm_ofi_hp_gethugepagesize(void) {
  return gethugepagesize();
}