@@ -2346,6 +2346,9 @@ void os::print_memory_info(outputStream* st) {
2346
2346
st->print (" (" UINT64_FORMAT " k free)" ,
2347
2347
((jlong)si.freeswap * si.mem_unit ) >> 10 );
2348
2348
st->cr ();
2349
+ st->print (" Page Sizes: " );
2350
+ _page_sizes.print_on (st);
2351
+ st->cr ();
2349
2352
}
2350
2353
2351
2354
// Print the first "model name" line and the first "flags" line
@@ -3504,6 +3507,25 @@ bool os::Linux::hugetlbfs_sanity_check(bool warn, size_t page_size) {
3504
3507
// Mapping succeeded, sanity check passed.
3505
3508
munmap (p, page_size);
3506
3509
return true ;
3510
+ } else {
3511
+ log_info (pagesize)(" Large page size (" SIZE_FORMAT " %s) failed sanity check, "
3512
+ " checking if smaller large page sizes are usable" ,
3513
+ byte_size_in_exact_unit (page_size),
3514
+ exact_unit_for_byte_size (page_size));
3515
+ for (size_t page_size_ = _page_sizes.next_smaller (page_size);
3516
+ page_size_ != (size_t )os::vm_page_size ();
3517
+ page_size_ = _page_sizes.next_smaller (page_size_)) {
3518
+ flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_HUGETLB | hugetlbfs_page_size_flag (page_size_);
3519
+ p = mmap (NULL , page_size_, PROT_READ|PROT_WRITE, flags, -1 , 0 );
3520
+ if (p != MAP_FAILED) {
3521
+ // Mapping succeeded, sanity check passed.
3522
+ munmap (p, page_size_);
3523
+ log_info (pagesize)(" Large page size (" SIZE_FORMAT " %s) passed sanity check" ,
3524
+ byte_size_in_exact_unit (page_size_),
3525
+ exact_unit_for_byte_size (page_size_));
3526
+ return true ;
3527
+ }
3528
+ }
3507
3529
}
3508
3530
3509
3531
if (warn) {
@@ -3578,35 +3600,20 @@ static void set_coredump_filter(CoredumpFilterBit bit) {
3578
3600
3579
3601
static size_t _large_page_size = 0 ;
3580
3602
3581
- size_t os::Linux::find_default_large_page_size () {
3582
- if (_default_large_page_size != 0 ) {
3583
- return _default_large_page_size;
3584
- }
3585
- size_t large_page_size = 0 ;
3603
+ static size_t scan_default_large_page_size () {
3604
+ size_t default_large_page_size = 0 ;
3586
3605
3587
3606
// large_page_size on Linux is used to round up heap size. x86 uses either
3588
3607
// 2M or 4M page, depending on whether PAE (Physical Address Extensions)
3589
3608
// mode is enabled. AMD64/EM64T uses 2M page in 64bit mode. IA64 can use
3590
- // page as large as 256M .
3609
+ // page as large as 1G .
3591
3610
//
3592
3611
// Here we try to figure out page size by parsing /proc/meminfo and looking
3593
3612
// for a line with the following format:
3594
3613
// Hugepagesize: 2048 kB
3595
3614
//
3596
3615
// If we can't determine the value (e.g. /proc is not mounted, or the text
3597
- // format has been changed), we'll use the largest page size supported by
3598
- // the processor.
3599
-
3600
- #ifndef ZERO
3601
- large_page_size =
3602
- AARCH64_ONLY (2 * M)
3603
- AMD64_ONLY (2 * M)
3604
- ARM32_ONLY (2 * M)
3605
- IA32_ONLY (4 * M)
3606
- IA64_ONLY (256 * M)
3607
- PPC_ONLY (4 * M)
3608
- S390_ONLY (1 * M);
3609
- #endif // ZERO
3616
+ // format has been changed), we'll set largest page size to 0
3610
3617
3611
3618
FILE *fp = fopen (" /proc/meminfo" , " r" );
3612
3619
if (fp) {
@@ -3615,7 +3622,7 @@ size_t os::Linux::find_default_large_page_size() {
3615
3622
char buf[16 ];
3616
3623
if (fscanf (fp, " Hugepagesize: %d" , &x) == 1 ) {
3617
3624
if (x && fgets (buf, sizeof (buf), fp) && strcmp (buf, " kB\n " ) == 0 ) {
3618
- large_page_size = x * K;
3625
+ default_large_page_size = x * K;
3619
3626
break ;
3620
3627
}
3621
3628
} else {
@@ -3628,65 +3635,50 @@ size_t os::Linux::find_default_large_page_size() {
3628
3635
}
3629
3636
fclose (fp);
3630
3637
}
3631
- return large_page_size;
3638
+
3639
+ return default_large_page_size;
3632
3640
}
3633
3641
3634
- size_t os::Linux::find_large_page_size (size_t large_page_size) {
3635
- if (_default_large_page_size == 0 ) {
3636
- _default_large_page_size = Linux::find_default_large_page_size ();
3637
- }
3638
- // We need to scan /sys/kernel/mm/hugepages
3642
+ static os::PageSizes scan_multiple_page_support () {
3643
+ // Scan /sys/kernel/mm/hugepages
3639
3644
// to discover the available page sizes
3640
3645
const char * sys_hugepages = " /sys/kernel/mm/hugepages" ;
3646
+ os::PageSizes page_sizes;
3641
3647
3642
3648
DIR *dir = opendir (sys_hugepages);
3643
- if (dir == NULL ) {
3644
- return _default_large_page_size;
3645
- }
3646
3649
3647
3650
struct dirent *entry;
3648
3651
size_t page_size;
3649
3652
while ((entry = readdir (dir)) != NULL ) {
3650
3653
if (entry->d_type == DT_DIR &&
3651
3654
sscanf (entry->d_name , " hugepages-%zukB" , &page_size) == 1 ) {
3652
3655
// The kernel is using kB, hotspot uses bytes
3653
- if (large_page_size == page_size * K) {
3654
- closedir (dir);
3655
- return large_page_size;
3656
- }
3656
+ // Add each found Large Page Size to page_sizes
3657
+ page_sizes.add (page_size * K);
3657
3658
}
3658
3659
}
3659
3660
closedir (dir);
3660
- return _default_large_page_size;
3661
- }
3662
-
3663
- size_t os::Linux::setup_large_page_size () {
3664
- _default_large_page_size = Linux::find_default_large_page_size ();
3665
-
3666
- if (!FLAG_IS_DEFAULT (LargePageSizeInBytes) && LargePageSizeInBytes != _default_large_page_size ) {
3667
- _large_page_size = find_large_page_size (LargePageSizeInBytes);
3668
- if (_large_page_size == _default_large_page_size) {
3669
- warning (" Setting LargePageSizeInBytes=" SIZE_FORMAT " has no effect on this OS. Using the default large page size "
3670
- SIZE_FORMAT " %s." ,
3671
- LargePageSizeInBytes,
3672
- byte_size_in_proper_unit (_large_page_size), proper_unit_for_byte_size (_large_page_size));
3673
- }
3674
- } else {
3675
- _large_page_size = _default_large_page_size;
3676
- }
3677
3661
3678
- const size_t default_page_size = (size_t )Linux::page_size ();
3679
- if (_large_page_size > default_page_size) {
3680
- _page_sizes.add (_large_page_size);
3662
+ LogTarget (Debug, pagesize) lt;
3663
+ if (lt.is_enabled ()) {
3664
+ LogStream ls (lt);
3665
+ ls.print (" Large Page sizes: " );
3666
+ page_sizes.print_on (&ls);
3681
3667
}
3682
3668
3683
- return _large_page_size ;
3669
+ return page_sizes ;
3684
3670
}
3685
3671
3686
3672
size_t os::Linux::default_large_page_size () {
3687
3673
return _default_large_page_size;
3688
3674
}
3689
3675
3676
+ void warn_no_large_pages_configured () {
3677
+ if (!FLAG_IS_DEFAULT (UseLargePages)) {
3678
+ log_warning (pagesize)(" UseLargePages disabled, no large pages configured and available on the system." );
3679
+ }
3680
+ }
3681
+
3690
3682
bool os::Linux::setup_large_page_type (size_t page_size) {
3691
3683
if (FLAG_IS_DEFAULT (UseHugeTLBFS) &&
3692
3684
FLAG_IS_DEFAULT (UseSHM) &&
@@ -3729,13 +3721,13 @@ bool os::Linux::setup_large_page_type(size_t page_size) {
3729
3721
UseSHM = false ;
3730
3722
}
3731
3723
3732
- if (!FLAG_IS_DEFAULT (UseLargePages)) {
3733
- log_warning (pagesize)(" UseLargePages disabled, no large pages configured and available on the system." );
3734
- }
3724
+ warn_no_large_pages_configured ();
3735
3725
return false ;
3736
3726
}
3737
3727
3738
3728
void os::large_page_init () {
3729
+ // 1) Handle the case where we do not want to use huge pages and hence
3730
+ // there is no need to scan the OS for related info
3739
3731
if (!UseLargePages &&
3740
3732
!UseTransparentHugePages &&
3741
3733
!UseHugeTLBFS &&
@@ -3753,8 +3745,73 @@ void os::large_page_init() {
3753
3745
return ;
3754
3746
}
3755
3747
3756
- size_t large_page_size = Linux::setup_large_page_size ();
3757
- UseLargePages = Linux::setup_large_page_type (large_page_size);
3748
+ // 2) Scan OS info
3749
+ size_t default_large_page_size = scan_default_large_page_size ();
3750
+ os::Linux::_default_large_page_size = default_large_page_size;
3751
+ if (default_large_page_size == 0 ) {
3752
+ // No large pages configured, return.
3753
+ warn_no_large_pages_configured ();
3754
+ UseLargePages = false ;
3755
+ UseTransparentHugePages = false ;
3756
+ UseHugeTLBFS = false ;
3757
+ UseSHM = false ;
3758
+ return ;
3759
+ }
3760
+ os::PageSizes all_large_pages = scan_multiple_page_support ();
3761
+
3762
+ // 3) Consistency check and post-processing
3763
+
3764
+ // It is unclear if /sys/kernel/mm/hugepages/ and /proc/meminfo could disagree. Manually
3765
+ // re-add the default page size to the list of page sizes to be sure.
3766
+ all_large_pages.add (default_large_page_size);
3767
+
3768
+ // Check LargePageSizeInBytes matches an available page size and if so set _large_page_size
3769
+ // using LargePageSizeInBytes as the maximum allowed large page size. If LargePageSizeInBytes
3770
+ // doesn't match an available page size set _large_page_size to default_large_page_size
3771
+ // and use it as the maximum.
3772
+ if (FLAG_IS_DEFAULT (LargePageSizeInBytes) ||
3773
+ LargePageSizeInBytes == 0 ||
3774
+ LargePageSizeInBytes == default_large_page_size) {
3775
+ _large_page_size = default_large_page_size;
3776
+ log_info (pagesize)(" Using the default large page size: " SIZE_FORMAT " %s" ,
3777
+ byte_size_in_exact_unit (_large_page_size),
3778
+ exact_unit_for_byte_size (_large_page_size));
3779
+ } else {
3780
+ if (all_large_pages.contains (LargePageSizeInBytes)) {
3781
+ _large_page_size = LargePageSizeInBytes;
3782
+ log_info (pagesize)(" Overriding default large page size (" SIZE_FORMAT " %s) "
3783
+ " using LargePageSizeInBytes: " SIZE_FORMAT " %s" ,
3784
+ byte_size_in_exact_unit (default_large_page_size),
3785
+ exact_unit_for_byte_size (default_large_page_size),
3786
+ byte_size_in_exact_unit (_large_page_size),
3787
+ exact_unit_for_byte_size (_large_page_size));
3788
+ } else {
3789
+ _large_page_size = default_large_page_size;
3790
+ log_info (pagesize)(" LargePageSizeInBytes is not a valid large page size (" SIZE_FORMAT " %s) "
3791
+ " using the default large page size: " SIZE_FORMAT " %s" ,
3792
+ byte_size_in_exact_unit (LargePageSizeInBytes),
3793
+ exact_unit_for_byte_size (LargePageSizeInBytes),
3794
+ byte_size_in_exact_unit (_large_page_size),
3795
+ exact_unit_for_byte_size (_large_page_size));
3796
+ }
3797
+ }
3798
+
3799
+ // Populate _page_sizes with large page sizes less than or equal to
3800
+ // _large_page_size.
3801
+ for (size_t page_size = _large_page_size; page_size != 0 ;
3802
+ page_size = all_large_pages.next_smaller (page_size)) {
3803
+ _page_sizes.add (page_size);
3804
+ }
3805
+
3806
+ LogTarget (Info, pagesize) lt;
3807
+ if (lt.is_enabled ()) {
3808
+ LogStream ls (lt);
3809
+ ls.print (" Usable page sizes: " );
3810
+ _page_sizes.print_on (&ls);
3811
+ }
3812
+
3813
+ // Now determine the type of large pages to use:
3814
+ UseLargePages = os::Linux::setup_large_page_type (_large_page_size);
3758
3815
3759
3816
set_coredump_filter (LARGEPAGES_BIT);
3760
3817
}
@@ -3965,6 +4022,7 @@ char* os::Linux::reserve_memory_special_huge_tlbfs(size_t bytes,
3965
4022
assert (is_aligned (req_addr, page_size), " Must be" );
3966
4023
assert (is_aligned (alignment, os::vm_allocation_granularity ()), " Must be" );
3967
4024
assert (_page_sizes.contains (page_size), " Must be a valid page size" );
4025
+ assert (page_size > (size_t )os::vm_page_size (), " Must be a large page size" );
3968
4026
assert (bytes >= page_size, " Shouldn't allocate large pages for small sizes" );
3969
4027
3970
4028
// We only end up here when at least 1 large page can be used.
0 commit comments