95 // Java heap filename 96 #define ZFILENAME_HEAP "java_heap" 97 98 // Preferred tmpfs mount points, ordered by priority 99 static const char* z_preferred_tmpfs_mountpoints[] = { 100 "/dev/shm", 101 "/run/shm", 102 NULL 103 }; 104 105 // Preferred hugetlbfs mount points, ordered by priority 106 static const char* z_preferred_hugetlbfs_mountpoints[] = { 107 "/dev/hugepages", 108 "/hugepages", 109 NULL 110 }; 111 112 static int z_fallocate_hugetlbfs_attempts = 3; 113 static bool z_fallocate_supported = true; 114 115 ZPhysicalMemoryBacking::ZPhysicalMemoryBacking() : 116 _fd(-1), 117 _size(0), 118 _filesystem(0), 119 _block_size(0), 120 _available(0), 121 _initialized(false) { 122 123 // Create backing file 124 _fd = create_fd(ZFILENAME_HEAP); 125 if (_fd == -1) { 126 return; 127 } 128 129 // Get filesystem statistics 130 struct statfs buf; 131 if (fstatfs(_fd, &buf) == -1) { 132 ZErrno err; 133 log_error(gc)("Failed to determine filesystem type for backing file (%s)", err.to_string()); 134 return; 135 } 136 137 _filesystem = buf.f_type; 138 _block_size = buf.f_bsize; 139 _available = buf.f_bavail * _block_size; 140 141 log_info(gc, init)("Heap Backing Filesystem: %s (0x" UINT64_FORMAT_X ")", 142 is_tmpfs() ? ZFILESYSTEM_TMPFS : is_hugetlbfs() ? ZFILESYSTEM_HUGETLBFS : "other", _filesystem); 143 144 // Make sure the filesystem type matches requested large page type 145 if (ZLargePages::is_transparent() && !is_tmpfs()) { 146 log_error(gc)("-XX:+UseTransparentHugePages can only be enabled when using a %s filesystem", 147 ZFILESYSTEM_TMPFS); 148 return; 344 const size_t required_max_map_count = (max / ZGranuleSize) * 3 * 1.2; 345 if (actual_max_map_count < required_max_map_count) { 346 log_warning(gc)("***** WARNING! INCORRECT SYSTEM CONFIGURATION DETECTED! *****"); 347 log_warning(gc)("The system limit on number of memory mappings per process might be too low for the given"); 348 log_warning(gc)("max Java heap size (" SIZE_FORMAT "M). Please adjust %s to allow for at", 349 max / M, filename); 350 log_warning(gc)("least " SIZE_FORMAT " mappings (current limit is " SIZE_FORMAT "). Continuing execution " 351 "with the current", required_max_map_count, actual_max_map_count); 352 log_warning(gc)("limit could lead to a fatal error, due to failure to map memory."); 353 } 354 } 355 356 void ZPhysicalMemoryBacking::warn_commit_limits(size_t max) const { 357 // Warn if available space is too low 358 warn_available_space(max); 359 360 // Warn if max map count is too low 361 warn_max_map_count(max); 362 } 363 364 size_t ZPhysicalMemoryBacking::size() const { 365 return _size; 366 } 367 368 bool ZPhysicalMemoryBacking::is_tmpfs() const { 369 return _filesystem == TMPFS_MAGIC; 370 } 371 372 bool ZPhysicalMemoryBacking::is_hugetlbfs() const { 373 return _filesystem == HUGETLBFS_MAGIC; 374 } 375 376 bool ZPhysicalMemoryBacking::tmpfs_supports_transparent_huge_pages() const { 377 // If the shmem_enabled file exists and is readable then we 378 // know the kernel supports transparent huge pages for tmpfs. 379 return access(ZFILENAME_SHMEM_ENABLED, R_OK) == 0; 380 } 381 382 ZErrno ZPhysicalMemoryBacking::fallocate_compat_ftruncate(size_t size) const { 383 while (ftruncate(_fd, size) == -1) { 384 if (errno != EINTR) { 385 // Failed 386 return errno; 387 } 388 } 389 390 // Success 391 return 0; 392 } 393 394 ZErrno ZPhysicalMemoryBacking::fallocate_compat_mmap_hugetlbfs(size_t offset, size_t length, bool touch) const { 395 // On hugetlbfs, mapping a file segment will fail immediately, without 396 // the need to touch the mapped pages first, if there aren't enough huge 397 // pages available to back the mapping. 398 void* const addr = mmap(0, length, PROT_READ|PROT_WRITE, MAP_SHARED, _fd, offset); 399 if (addr == MAP_FAILED) { 400 // Failed 401 return errno; 402 } 403 404 // Once mapped, the huge pages are only reserved. We need to touch them 405 // to associate them with the file segment. Note that we can not punch 406 // hole in file segments which only have reserved pages. 407 if (touch) { 408 char* const start = (char*)addr; 409 char* const end = start + length; 410 os::pretouch_memory(start, end, _block_size); 411 } 412 413 // Unmap again. From now on, the huge pages that were mapped are allocated 472 ZErrno ZPhysicalMemoryBacking::fallocate_compat_pwrite(size_t offset, size_t length) const { 473 uint8_t data = 0; 474 475 // Allocate backing memory by writing to each block 476 for (size_t pos = offset; pos < offset + length; pos += _block_size) { 477 if (pwrite(_fd, &data, sizeof(data), pos) == -1) { 478 // Failed 479 return errno; 480 } 481 } 482 483 // Success 484 return 0; 485 } 486 487 ZErrno ZPhysicalMemoryBacking::fallocate_fill_hole_compat(size_t offset, size_t length) { 488 // fallocate(2) is only supported by tmpfs since Linux 3.5, and by hugetlbfs 489 // since Linux 4.3. When fallocate(2) is not supported we emulate it using 490 // mmap/munmap (for hugetlbfs and tmpfs with transparent huge pages) or pwrite 491 // (for tmpfs without transparent huge pages and other filesystem types). 492 493 const size_t end = offset + length; 494 if (end > _size) { 495 // Increase file size 496 const ZErrno err = fallocate_compat_ftruncate(end); 497 if (err) { 498 // Failed 499 return err; 500 } 501 } 502 503 // Allocate backing memory 504 const ZErrno err = ZLargePages::is_explicit() 505 ? fallocate_compat_mmap_hugetlbfs(offset, length, false /* touch */) 506 : (ZLargePages::is_transparent() 507 ? fallocate_compat_mmap_tmpfs(offset, length) 508 : fallocate_compat_pwrite(offset, length)); 509 510 if (err) { 511 if (end > _size) { 512 // Restore file size 513 fallocate_compat_ftruncate(_size); 514 } 515 516 // Failed 517 return err; 518 } 519 520 if (end > _size) { 521 // Record new file size 522 _size = end; 523 } 524 525 // Success 526 return 0; 527 } 528 529 ZErrno ZPhysicalMemoryBacking::fallocate_fill_hole_syscall(size_t offset, size_t length) { 530 const int mode = 0; // Allocate 531 const int res = ZSyscall::fallocate(_fd, mode, offset, length); 532 if (res == -1) { 533 // Failed 534 return errno; 535 } 536 537 const size_t end = offset + length; 538 if (end > _size) { 539 // Record new file size 540 _size = end; 541 } 542 543 // Success 544 return 0; 545 } 546 547 ZErrno ZPhysicalMemoryBacking::fallocate_fill_hole(size_t offset, size_t length) { 548 // Using compat mode is more efficient when allocating space on hugetlbfs. 549 // Note that allocating huge pages this way will only reserve them, and not 550 // associate them with segments of the file. We must guarantee that we at 551 // some point touch these segments, otherwise we can not punch hole in them. 552 // Also note that we need to use compat mode when using transparent huge pages, 553 // since we need to use madvise(2) on the mapping before the page is allocated. 554 if (z_fallocate_supported && !ZLargePages::is_enabled()) { 555 const ZErrno err = fallocate_fill_hole_syscall(offset, length); 556 if (!err) { 557 // Success 558 return 0; 559 } 560 | 95 // Java heap filename 96 #define ZFILENAME_HEAP "java_heap" 97 98 // Preferred tmpfs mount points, ordered by priority 99 static const char* z_preferred_tmpfs_mountpoints[] = { 100 "/dev/shm", 101 "/run/shm", 102 NULL 103 }; 104 105 // Preferred hugetlbfs mount points, ordered by priority 106 static const char* z_preferred_hugetlbfs_mountpoints[] = { 107 "/dev/hugepages", 108 "/hugepages", 109 NULL 110 }; 111 112 static int z_fallocate_hugetlbfs_attempts = 3; 113 static bool z_fallocate_supported = true; 114 115 ZPhysicalMemoryBacking::ZPhysicalMemoryBacking(size_t max_capacity) : 116 _fd(-1), 117 _filesystem(0), 118 _block_size(0), 119 _available(0), 120 _initialized(false) { 121 122 // Create backing file 123 _fd = create_fd(ZFILENAME_HEAP); 124 if (_fd == -1) { 125 return; 126 } 127 128 // Truncate backing file 129 if (ftruncate(_fd, max_capacity) == -1) { 130 ZErrno err; 131 log_error(gc)("Failed to truncate backing file (%s)", err.to_string()); 132 return; 133 } 134 135 // Get filesystem statistics 136 struct statfs buf; 137 if (fstatfs(_fd, &buf) == -1) { 138 ZErrno err; 139 log_error(gc)("Failed to determine filesystem type for backing file (%s)", err.to_string()); 140 return; 141 } 142 143 _filesystem = buf.f_type; 144 _block_size = buf.f_bsize; 145 _available = buf.f_bavail * _block_size; 146 147 log_info(gc, init)("Heap Backing Filesystem: %s (0x" UINT64_FORMAT_X ")", 148 is_tmpfs() ? ZFILESYSTEM_TMPFS : is_hugetlbfs() ? ZFILESYSTEM_HUGETLBFS : "other", _filesystem); 149 150 // Make sure the filesystem type matches requested large page type 151 if (ZLargePages::is_transparent() && !is_tmpfs()) { 152 log_error(gc)("-XX:+UseTransparentHugePages can only be enabled when using a %s filesystem", 153 ZFILESYSTEM_TMPFS); 154 return; 350 const size_t required_max_map_count = (max / ZGranuleSize) * 3 * 1.2; 351 if (actual_max_map_count < required_max_map_count) { 352 log_warning(gc)("***** WARNING! INCORRECT SYSTEM CONFIGURATION DETECTED! *****"); 353 log_warning(gc)("The system limit on number of memory mappings per process might be too low for the given"); 354 log_warning(gc)("max Java heap size (" SIZE_FORMAT "M). Please adjust %s to allow for at", 355 max / M, filename); 356 log_warning(gc)("least " SIZE_FORMAT " mappings (current limit is " SIZE_FORMAT "). Continuing execution " 357 "with the current", required_max_map_count, actual_max_map_count); 358 log_warning(gc)("limit could lead to a fatal error, due to failure to map memory."); 359 } 360 } 361 362 void ZPhysicalMemoryBacking::warn_commit_limits(size_t max) const { 363 // Warn if available space is too low 364 warn_available_space(max); 365 366 // Warn if max map count is too low 367 warn_max_map_count(max); 368 } 369 370 bool ZPhysicalMemoryBacking::is_tmpfs() const { 371 return _filesystem == TMPFS_MAGIC; 372 } 373 374 bool ZPhysicalMemoryBacking::is_hugetlbfs() const { 375 return _filesystem == HUGETLBFS_MAGIC; 376 } 377 378 bool ZPhysicalMemoryBacking::tmpfs_supports_transparent_huge_pages() const { 379 // If the shmem_enabled file exists and is readable then we 380 // know the kernel supports transparent huge pages for tmpfs. 381 return access(ZFILENAME_SHMEM_ENABLED, R_OK) == 0; 382 } 383 384 ZErrno ZPhysicalMemoryBacking::fallocate_compat_mmap_hugetlbfs(size_t offset, size_t length, bool touch) const { 385 // On hugetlbfs, mapping a file segment will fail immediately, without 386 // the need to touch the mapped pages first, if there aren't enough huge 387 // pages available to back the mapping. 388 void* const addr = mmap(0, length, PROT_READ|PROT_WRITE, MAP_SHARED, _fd, offset); 389 if (addr == MAP_FAILED) { 390 // Failed 391 return errno; 392 } 393 394 // Once mapped, the huge pages are only reserved. We need to touch them 395 // to associate them with the file segment. Note that we can not punch 396 // hole in file segments which only have reserved pages. 397 if (touch) { 398 char* const start = (char*)addr; 399 char* const end = start + length; 400 os::pretouch_memory(start, end, _block_size); 401 } 402 403 // Unmap again. From now on, the huge pages that were mapped are allocated 462 ZErrno ZPhysicalMemoryBacking::fallocate_compat_pwrite(size_t offset, size_t length) const { 463 uint8_t data = 0; 464 465 // Allocate backing memory by writing to each block 466 for (size_t pos = offset; pos < offset + length; pos += _block_size) { 467 if (pwrite(_fd, &data, sizeof(data), pos) == -1) { 468 // Failed 469 return errno; 470 } 471 } 472 473 // Success 474 return 0; 475 } 476 477 ZErrno ZPhysicalMemoryBacking::fallocate_fill_hole_compat(size_t offset, size_t length) { 478 // fallocate(2) is only supported by tmpfs since Linux 3.5, and by hugetlbfs 479 // since Linux 4.3. When fallocate(2) is not supported we emulate it using 480 // mmap/munmap (for hugetlbfs and tmpfs with transparent huge pages) or pwrite 481 // (for tmpfs without transparent huge pages and other filesystem types). 482 if (ZLargePages::is_explicit()) { 483 return fallocate_compat_mmap_hugetlbfs(offset, length, false /* touch */); 484 } else if (ZLargePages::is_transparent()) { 485 return fallocate_compat_mmap_tmpfs(offset, length); 486 } else { 487 return fallocate_compat_pwrite(offset, length); 488 } 489 } 490 491 ZErrno ZPhysicalMemoryBacking::fallocate_fill_hole_syscall(size_t offset, size_t length) { 492 const int mode = 0; // Allocate 493 const int res = ZSyscall::fallocate(_fd, mode, offset, length); 494 if (res == -1) { 495 // Failed 496 return errno; 497 } 498 499 // Success 500 return 0; 501 } 502 503 ZErrno ZPhysicalMemoryBacking::fallocate_fill_hole(size_t offset, size_t length) { 504 // Using compat mode is more efficient when allocating space on hugetlbfs. 505 // Note that allocating huge pages this way will only reserve them, and not 506 // associate them with segments of the file. We must guarantee that we at 507 // some point touch these segments, otherwise we can not punch hole in them. 508 // Also note that we need to use compat mode when using transparent huge pages, 509 // since we need to use madvise(2) on the mapping before the page is allocated. 510 if (z_fallocate_supported && !ZLargePages::is_enabled()) { 511 const ZErrno err = fallocate_fill_hole_syscall(offset, length); 512 if (!err) { 513 // Success 514 return 0; 515 } 516 |