7474#include " services/runtimeService.hpp"
7575#include " signals_posix.hpp"
7676#include " utilities/align.hpp"
77+ #include " utilities/debug.hpp"
7778#include " utilities/decoder.hpp"
7879#include " utilities/defaultStream.hpp"
7980#include " utilities/events.hpp"
100101#include < sys/ioctl.h>
101102#include < sys/ipc.h>
102103#include < sys/mman.h>
104+ // sys/mman.h defines MAP_ANON_64K beginning with AIX7.3 TL1
105+ #ifndef MAP_ANON_64K
106+ #define MAP_ANON_64K 0x400
107+ #else
108+ STATIC_ASSERT (MAP_ANON_64K == 0x400 );
109+ #endif
103110#include < sys/resource.h>
104111#include < sys/select.h>
105112#include < sys/shm.h>
@@ -224,21 +231,22 @@ static address g_brk_at_startup = nullptr;
224231// http://publib.boulder.ibm.com/infocenter/aix/v6r1/index.jsp?topic=/com.ibm.aix.prftungd/doc/prftungd/multiple_page_size_app_support.htm
225232//
226233static struct {
227- size_t pagesize; // sysconf _SC_PAGESIZE (4K)
228- size_t datapsize; // default data page size (LDR_CNTRL DATAPSIZE)
229- size_t shmpsize; // default shared memory page size (LDR_CNTRL SHMPSIZE)
230- size_t pthr_stack_pagesize; // stack page size of pthread threads
231- size_t textpsize; // default text page size (LDR_CNTRL STACKPSIZE)
232- bool can_use_64K_pages; // True if we can alloc 64K pages dynamically with Sys V shm.
233- bool can_use_16M_pages; // True if we can alloc 16M pages dynamically with Sys V shm.
234- int error; // Error describing if something went wrong at multipage init.
234+ size_t pagesize; // sysconf _SC_PAGESIZE (4K)
235+ size_t datapsize; // default data page size (LDR_CNTRL DATAPSIZE)
236+ size_t shmpsize; // default shared memory page size (LDR_CNTRL SHMPSIZE)
237+ size_t pthr_stack_pagesize; // stack page size of pthread threads
238+ size_t textpsize; // default text page size (LDR_CNTRL STACKPSIZE)
239+ bool can_use_64K_pages; // True if we can alloc 64K pages dynamically with Sys V shm.
240+ bool can_use_16M_pages; // True if we can alloc 16M pages dynamically with Sys V shm.
241+ bool can_use_64K_mmap_pages; // True if we can alloc 64K pages dynamically with mmap.
242+ int error; // Error describing if something went wrong at multipage init.
235243} g_multipage_support = {
236244 (size_t ) -1 ,
237245 (size_t ) -1 ,
238246 (size_t ) -1 ,
239247 (size_t ) -1 ,
240248 (size_t ) -1 ,
241- false , false ,
249+ false , false , false ,
242250 0
243251};
244252
@@ -393,12 +401,16 @@ static void query_multipage_support() {
393401 // our own page size after allocated.
394402 {
395403 const int shmid = ::shmget (IPC_PRIVATE, 1 , IPC_CREAT | S_IRUSR | S_IWUSR);
396- guarantee (shmid != -1 , " shmget failed" );
397- void * p = ::shmat (shmid, nullptr , 0 );
398- ::shmctl (shmid, IPC_RMID, nullptr );
399- guarantee (p != (void *) -1 , " shmat failed" );
400- g_multipage_support.shmpsize = os::Aix::query_pagesize (p);
401- ::shmdt (p);
404+ assert (shmid != -1 , " shmget failed" );
405+ if (shmid != -1 ) {
406+ void * p = ::shmat (shmid, nullptr , 0 );
407+ ::shmctl (shmid, IPC_RMID, nullptr );
408+ assert (p != (void *) -1 , " shmat failed" );
409+ if (p != (void *) -1 ) {
410+ g_multipage_support.shmpsize = os::Aix::query_pagesize (p);
411+ ::shmdt (p);
412+ }
413+ }
402414 }
403415
404416 // Before querying the stack page size, make sure we are not running as primordial
@@ -458,26 +470,30 @@ static void query_multipage_support() {
458470 trcVerbose (" Probing support for %s pages..." , describe_pagesize (pagesize));
459471 const int shmid = ::shmget (IPC_PRIVATE, pagesize,
460472 IPC_CREAT | S_IRUSR | S_IWUSR);
461- guarantee0 (shmid != -1 ); // Should always work.
462- // Try to set pagesize.
463- struct shmid_ds shm_buf = { };
464- shm_buf.shm_pagesize = pagesize;
465- if (::shmctl (shmid, SHM_PAGESIZE, &shm_buf) != 0 ) {
466- const int en = errno;
467- ::shmctl (shmid, IPC_RMID, nullptr ); // As early as possible!
468- trcVerbose (" shmctl(SHM_PAGESIZE) failed with errno=%d" , errno);
469- } else {
470- // Attach and double check pageisze.
471- void * p = ::shmat (shmid, nullptr , 0 );
472- ::shmctl (shmid, IPC_RMID, nullptr ); // As early as possible!
473- guarantee0 (p != (void *) -1 ); // Should always work.
474- const size_t real_pagesize = os::Aix::query_pagesize (p);
475- if (real_pagesize != pagesize) {
476- trcVerbose (" real page size (" SIZE_FORMAT_X " ) differs." , real_pagesize);
473+ assert (shmid != -1 , " shmget failed" );
474+ if (shmid != -1 ) {
475+ // Try to set pagesize.
476+ struct shmid_ds shm_buf = { };
477+ shm_buf.shm_pagesize = pagesize;
478+ if (::shmctl (shmid, SHM_PAGESIZE, &shm_buf) != 0 ) {
479+ const int en = errno;
480+ ::shmctl (shmid, IPC_RMID, nullptr ); // As early as possible!
481+ trcVerbose (" shmctl(SHM_PAGESIZE) failed with errno=%d" , errno);
477482 } else {
478- can_use = true ;
483+ // Attach and double check pageisze.
484+ void * p = ::shmat (shmid, nullptr , 0 );
485+ ::shmctl (shmid, IPC_RMID, nullptr ); // As early as possible!
486+ assert (p != (void *) -1 , " shmat failed" );
487+ if (p != (void *) -1 ) {
488+ const size_t real_pagesize = os::Aix::query_pagesize (p);
489+ if (real_pagesize != pagesize) {
490+ log_warning (pagesize)(" real page size (" SIZE_FORMAT_X " ) differs." , real_pagesize);
491+ } else {
492+ can_use = true ;
493+ }
494+ ::shmdt (p);
495+ }
479496 }
480- ::shmdt (p);
481497 }
482498 trcVerbose (" Can use: %s" , (can_use ? " yes" : " no" ));
483499 if (pagesize == 64 *K) {
@@ -487,6 +503,16 @@ static void query_multipage_support() {
487503 }
488504 }
489505
506+ // Can we use mmap with 64K pages? (Should be available with AIX7.3 TL1)
507+ {
508+ void * p = mmap (NULL , 64 *K, PROT_READ | PROT_WRITE, MAP_ANON_64K | MAP_ANONYMOUS | MAP_SHARED, -1 , 0 );
509+ assert (p != (void *) -1 , " mmap failed" );
510+ if (p != (void *) -1 ) {
511+ g_multipage_support.can_use_64K_mmap_pages = (64 *K == os::Aix::query_pagesize (p));
512+ munmap (p, 64 *K);
513+ }
514+ }
515+
490516 } // end: check which pages can be used for shared memory
491517
492518query_multipage_support_end:
@@ -499,6 +525,8 @@ static void query_multipage_support() {
499525 describe_pagesize (g_multipage_support.textpsize ));
500526 trcVerbose (" Thread stack page size (pthread): %s" ,
501527 describe_pagesize (g_multipage_support.pthr_stack_pagesize ));
528+ trcVerbose (" Can use 64K pages with mmap memory: %s" ,
529+ (g_multipage_support.can_use_64K_mmap_pages ? " yes" :" no" ));
502530 trcVerbose (" Default shared memory page size: %s" ,
503531 describe_pagesize (g_multipage_support.shmpsize ));
504532 trcVerbose (" Can use 64K pages dynamically with shared memory: %s" ,
@@ -1230,6 +1258,8 @@ void os::print_memory_info(outputStream* st) {
12301258 describe_pagesize (g_multipage_support.textpsize ));
12311259 st->print_cr (" Thread stack page size (pthread): %s" ,
12321260 describe_pagesize (g_multipage_support.pthr_stack_pagesize ));
1261+ st->print_cr (" Can use 64K pages with mmap memory: %s" ,
1262+ (g_multipage_support.can_use_64K_mmap_pages ? " yes" :" no" ));
12331263 st->print_cr (" Default shared memory page size: %s" ,
12341264 describe_pagesize (g_multipage_support.shmpsize ));
12351265 st->print_cr (" Can use 64K pages dynamically with shared memory: %s" ,
@@ -1689,6 +1719,10 @@ static char* reserve_mmaped_memory(size_t bytes, char* requested_addr) {
16891719 // later use msync(MS_INVALIDATE) (see os::uncommit_memory).
16901720 int flags = MAP_ANONYMOUS | MAP_SHARED;
16911721
1722+ if (os::vm_page_size () == 64 *K && g_multipage_support.can_use_64K_mmap_pages ) {
1723+ flags |= MAP_ANON_64K;
1724+ }
1725+
16921726 // MAP_FIXED is needed to enforce requested_addr - manpage is vague about what
16931727 // it means if wishaddress is given but MAP_FIXED is not set.
16941728 //
@@ -1732,7 +1766,11 @@ static char* reserve_mmaped_memory(size_t bytes, char* requested_addr) {
17321766 p2i (addr), p2i (addr + bytes), bytes);
17331767
17341768 // bookkeeping
1735- vmembk_add (addr, size, 4 *K, VMEM_MAPPED);
1769+ if (os::vm_page_size () == 64 *K && g_multipage_support.can_use_64K_mmap_pages ) {
1770+ vmembk_add (addr, size, 64 *K, VMEM_MAPPED);
1771+ } else {
1772+ vmembk_add (addr, size, 4 *K, VMEM_MAPPED);
1773+ }
17361774
17371775 // Test alignment, see above.
17381776 assert0 (is_aligned_to (addr, os::vm_page_size ()));
@@ -1921,8 +1959,8 @@ char* os::pd_reserve_memory(size_t bytes, bool exec) {
19211959 bytes = align_up (bytes, os::vm_page_size ());
19221960
19231961 // In 4K mode always use mmap.
1924- // In 64K mode allocate small sizes with mmap, large ones with 64K shmatted.
1925- if (os::vm_page_size () == 4 *K) {
1962+ // In 64K mode allocate with mmap if it supports 64K pages, otherwise use 64K shmatted.
1963+ if (os::vm_page_size () == 4 *K || g_multipage_support. can_use_64K_mmap_pages ) {
19261964 return reserve_mmaped_memory (bytes, nullptr /* requested_addr */ );
19271965 } else {
19281966 if (bytes >= Use64KPagesThreshold) {
@@ -2139,8 +2177,8 @@ char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool
21392177 bytes = align_up (bytes, os::vm_page_size ());
21402178
21412179 // In 4K mode always use mmap.
2142- // In 64K mode allocate small sizes with mmap, large ones with 64K shmatted.
2143- if (os::vm_page_size () == 4 *K) {
2180+ // In 64K mode allocate with mmap if it supports 64K pages, otherwise use 64K shmatted.
2181+ if (os::vm_page_size () == 4 *K || g_multipage_support. can_use_64K_mmap_pages ) {
21442182 return reserve_mmaped_memory (bytes, requested_addr);
21452183 } else {
21462184 if (bytes >= Use64KPagesThreshold) {
@@ -2277,18 +2315,18 @@ void os::init(void) {
22772315 // and should be allocated with 64k pages.
22782316 //
22792317 // So, we do the following:
2280- // LDR_CNTRL can_use_64K_pages_dynamically what we do remarks
2281- // 4K no 4K old systems (aix 5.2, as/400 v5r4 ) or new systems with AME activated
2282- // 4k yes 64k (treat 4k stacks as 64k) different loader than java and standard settings
2318+ // LDR_CNTRL can_use_64K_pages_dynamically(mmap or shm) what we do remarks
2319+ // 4K no 4K old systems (aix 5.2) or new systems with AME activated
2320+ // 4k yes 64k (treat 4k stacks as 64k) different loader than java and standard settings
22832321 // 64k no --- AIX 5.2 ? ---
2284- // 64k yes 64k new systems and standard java loader (we set datapsize=64k when linking)
2322+ // 64k yes 64k new systems and standard java loader (we set datapsize=64k when linking)
22852323
22862324 // We explicitly leave no option to change page size, because only upgrading would work,
22872325 // not downgrading (if stack page size is 64k you cannot pretend its 4k).
22882326
22892327 if (g_multipage_support.datapsize == 4 *K) {
22902328 // datapsize = 4K. Data segment, thread stacks are 4K paged.
2291- if (g_multipage_support.can_use_64K_pages ) {
2329+ if (g_multipage_support.can_use_64K_pages || g_multipage_support. can_use_64K_mmap_pages ) {
22922330 // .. but we are able to use 64K pages dynamically.
22932331 // This would be typical for java launchers which are not linked
22942332 // with datapsize=64K (like, any other launcher but our own).
@@ -2318,7 +2356,7 @@ void os::init(void) {
23182356 // This normally means that we can allocate 64k pages dynamically.
23192357 // (There is one special case where this may be false: EXTSHM=on.
23202358 // but we decided to not support that mode).
2321- assert0 (g_multipage_support.can_use_64K_pages );
2359+ assert0 (g_multipage_support.can_use_64K_pages || g_multipage_support. can_use_64K_mmap_pages );
23222360 set_page_size (64 *K);
23232361 trcVerbose (" 64K page mode" );
23242362 FLAG_SET_ERGO (Use64KPages, true );
@@ -2919,6 +2957,10 @@ void os::Aix::initialize_libperfstat() {
29192957 }
29202958}
29212959
2960+ bool os::Aix::supports_64K_mmap_pages () {
2961+ return g_multipage_support.can_use_64K_mmap_pages ;
2962+ }
2963+
29222964// ///////////////////////////////////////////////////////////////////////////
29232965// thread stack
29242966
0 commit comments