@@ -385,9 +385,9 @@ bool ZPhysicalMemoryBacking::tmpfs_supports_transparent_huge_pages() const {
385385 return access (ZFILENAME_SHMEM_ENABLED, R_OK) == 0 ;
386386}
387387
388- ZErrno ZPhysicalMemoryBacking::fallocate_compat_mmap_hugetlbfs (zbacking_offset offset, size_t length, bool touch ) const {
388+ ZErrno ZPhysicalMemoryBacking::fallocate_compat_mmap_hugetlbfs (zbacking_offset offset, size_t length, bool force_touch ) const {
389389 // On hugetlbfs, mapping a file segment will fail immediately, without
390- // the need to touch the mapped pages first, if there aren't enough huge
390+ // the need to touch the mapped pages first, if there aren't enough large
391391 // pages available to back the mapping.
392392 void * const addr = mmap (nullptr , length, PROT_READ|PROT_WRITE, MAP_SHARED, _fd, untype (offset));
393393 if (addr == MAP_FAILED) {
@@ -396,44 +396,34 @@ ZErrno ZPhysicalMemoryBacking::fallocate_compat_mmap_hugetlbfs(zbacking_offset o
396396 }
397397
398398 // Once mapped, the huge pages are only reserved. We need to touch them
399- // to associate them with the file segment. Note that we can not punch
400- // hole in file segments which only have reserved pages.
401- if (touch) {
402- char * const start = (char *)addr;
403- char * const end = start + length;
404- os::pretouch_memory (start, end, _block_size);
399+ // to associate them with the file segment. This needs to be done immediately
400+ // if running on a NUMA system, where shared memory may overreserve the number
401+ // of large pages available.
402+ const bool should_touch = force_touch || ZNUMA::is_numa_system ();
403+ bool touched = false ;
404+
405+ if (should_touch) {
406+ // Touch the large pages safely
407+ touched = os::Linux::safe_touch_memory (addr, length, ZGranuleSize);
405408 }
406409
407- // Unmap again. From now on, the huge pages that were mapped are allocated
408- // to this file. There's no risk of getting a SIGBUS when mapping and
409- // touching these pages again.
410+ // Unmap again
410411 if (munmap (addr, length) == -1 ) {
411412 // Failed
412413 return errno;
413414 }
414415
415- // Success
416- return 0 ;
417- }
418-
419- static bool safe_touch_mapping (void * addr, size_t length, size_t page_size) {
420- char * const start = (char *)addr;
421- char * const end = start + length;
422-
423- // Touching a mapping that can't be backed by memory will generate a
424- // SIGBUS. By using SafeFetch32 any SIGBUS will be safely caught and
425- // handled. On tmpfs, doing a fetch (rather than a store) is enough
426- // to cause backing pages to be allocated (there's no zero-page to
427- // worry about).
428- for (char *p = start; p < end; p += page_size) {
429- if (SafeFetch32 ((int *)p, -1 ) == -1 ) {
430- // Failed
431- return false ;
432- }
416+ if (should_touch && !touched) {
417+ // Failed to touch all large pages
418+ return errno;
433419 }
434420
421+ // From now on, the large pages that were mapped are allocated to this file.
422+ // There's no risk of getting a SIGBUS when mapping and touching these pages
423+ // again.
424+
435425 // Success
436- return true ;
426+ return 0 ;
437427}
438428
439429ZErrno ZPhysicalMemoryBacking::fallocate_compat_mmap_tmpfs (zbacking_offset offset, size_t length) const {
@@ -451,7 +441,7 @@ ZErrno ZPhysicalMemoryBacking::fallocate_compat_mmap_tmpfs(zbacking_offset offse
451441 }
452442
453443 // Touch the mapping (safely) to make sure it's backed by memory
454- const bool backed = safe_touch_mapping (addr, length, _block_size);
444+ const bool backed = os::Linux::safe_touch_memory (addr, length, _block_size);
455445
456446 // Unmap again. If successfully touched, the backing memory will
457447 // be allocated to this file. There's no risk of getting a SIGBUS
@@ -461,7 +451,7 @@ ZErrno ZPhysicalMemoryBacking::fallocate_compat_mmap_tmpfs(zbacking_offset offse
461451 return errno;
462452 }
463453
464- // Success
454+ // Success?
465455 return backed ? 0 : ENOMEM;
466456}
467457
@@ -486,7 +476,7 @@ ZErrno ZPhysicalMemoryBacking::fallocate_fill_hole_compat(zbacking_offset offset
486476 // mmap/munmap (for hugetlbfs and tmpfs with transparent huge pages) or pwrite
487477 // (for tmpfs without transparent huge pages and other filesystem types).
488478 if (ZLargePages::is_explicit ()) {
489- return fallocate_compat_mmap_hugetlbfs (offset, length, false /* touch */ );
479+ return fallocate_compat_mmap_hugetlbfs (offset, length, false /* force_touch */ );
490480 } else if (ZLargePages::is_transparent ()) {
491481 return fallocate_compat_mmap_tmpfs (offset, length);
492482 } else {
@@ -534,14 +524,16 @@ ZErrno ZPhysicalMemoryBacking::fallocate_fill_hole(zbacking_offset offset, size_
534524}
535525
536526ZErrno ZPhysicalMemoryBacking::fallocate_punch_hole (zbacking_offset offset, size_t length) const {
537- if (ZLargePages::is_explicit ()) {
527+ // On a NUMA system we have to touch all the large pages when committing, so
528+ // there is no need to touch them again here.
529+ if (ZLargePages::is_explicit () && !ZNUMA::is_numa_system ()) {
538530 // We can only punch hole in pages that have been touched. Non-touched
539531 // pages are only reserved, and not associated with any specific file
540532 // segment. We don't know which pages have been previously touched, so
541533 // we always touch them here to guarantee that we can punch hole.
542- const ZErrno err = fallocate_compat_mmap_hugetlbfs (offset, length, true /* touch */ );
534+ //
535+ const ZErrno err = fallocate_compat_mmap_hugetlbfs (offset, length, true /* force_touch */ );
543536 if (err) {
544- // Failed
545537 return err;
546538 }
547539 }
@@ -665,9 +657,7 @@ size_t ZPhysicalMemoryBacking::commit_default(zbacking_offset offset, size_t len
665657}
666658
667659size_t ZPhysicalMemoryBacking::commit (zbacking_offset offset, size_t length, uint32_t numa_id) const {
668- if (ZNUMA::is_enabled () && !ZLargePages::is_explicit ()) {
669- // The memory is required to be preferred at the time it is paged in. As a
670- // consequence we must prefer the memory when committing non-large pages.
660+ if (ZNUMA::is_enabled ()) {
671661 return commit_numa_preferred (offset, length, numa_id);
672662 }
673663
0 commit comments