6969#include " signals_posix.hpp"
7070#include " utilities/align.hpp"
7171#include " utilities/checkedCast.hpp"
72+ #include " utilities/debug.hpp"
7273#include " utilities/decoder.hpp"
7374#include " utilities/defaultStream.hpp"
7475#include " utilities/events.hpp"
9697#include < sys/ioctl.h>
9798#include < sys/ipc.h>
9899#include < sys/mman.h>
100+ // sys/mman.h defines MAP_ANON_64K beginning with AIX7.3 TL1
101+ #ifndef MAP_ANON_64K
102+ #define MAP_ANON_64K 0x400
103+ #else
104+ STATIC_ASSERT (MAP_ANON_64K == 0x400 );
105+ #endif
99106#include < sys/resource.h>
100107#include < sys/select.h>
101108#include < sys/shm.h>
@@ -217,21 +224,22 @@ static address g_brk_at_startup = nullptr;
217224// http://publib.boulder.ibm.com/infocenter/aix/v6r1/index.jsp?topic=/com.ibm.aix.prftungd/doc/prftungd/multiple_page_size_app_support.htm
218225//
219226static struct {
220- size_t pagesize; // sysconf _SC_PAGESIZE (4K)
221- size_t datapsize; // default data page size (LDR_CNTRL DATAPSIZE)
222- size_t shmpsize; // default shared memory page size (LDR_CNTRL SHMPSIZE)
223- size_t pthr_stack_pagesize; // stack page size of pthread threads
224- size_t textpsize; // default text page size (LDR_CNTRL STACKPSIZE)
225- bool can_use_64K_pages; // True if we can alloc 64K pages dynamically with Sys V shm.
226- bool can_use_16M_pages; // True if we can alloc 16M pages dynamically with Sys V shm.
227- int error; // Error describing if something went wrong at multipage init.
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+ bool can_use_64K_mmap_pages; // True if we can alloc 64K pages dynamically with mmap.
235+ int error; // Error describing if something went wrong at multipage init.
228236} g_multipage_support = {
229237 (size_t ) -1 ,
230238 (size_t ) -1 ,
231239 (size_t ) -1 ,
232240 (size_t ) -1 ,
233241 (size_t ) -1 ,
234- false , false ,
242+ false , false , false ,
235243 0
236244};
237245
@@ -366,12 +374,16 @@ static void query_multipage_support() {
366374 // our own page size after allocated.
367375 {
368376 const int shmid = ::shmget (IPC_PRIVATE, 1 , IPC_CREAT | S_IRUSR | S_IWUSR);
369- guarantee (shmid != -1 , " shmget failed" );
370- void * p = ::shmat (shmid, nullptr , 0 );
371- ::shmctl (shmid, IPC_RMID, nullptr );
372- guarantee (p != (void *) -1 , " shmat failed" );
373- g_multipage_support.shmpsize = os::Aix::query_pagesize (p);
374- ::shmdt (p);
377+ assert (shmid != -1 , " shmget failed" );
378+ if (shmid != -1 ) {
379+ void * p = ::shmat (shmid, nullptr , 0 );
380+ ::shmctl (shmid, IPC_RMID, nullptr );
381+ assert (p != (void *) -1 , " shmat failed" );
382+ if (p != (void *) -1 ) {
383+ g_multipage_support.shmpsize = os::Aix::query_pagesize (p);
384+ ::shmdt (p);
385+ }
386+ }
375387 }
376388
377389 // Before querying the stack page size, make sure we are not running as primordial
@@ -421,26 +433,30 @@ static void query_multipage_support() {
421433 trcVerbose (" Probing support for %s pages..." , describe_pagesize (pagesize));
422434 const int shmid = ::shmget (IPC_PRIVATE, pagesize,
423435 IPC_CREAT | S_IRUSR | S_IWUSR);
424- guarantee0 (shmid != -1 ); // Should always work.
425- // Try to set pagesize.
426- struct shmid_ds shm_buf = { };
427- shm_buf.shm_pagesize = pagesize;
428- if (::shmctl (shmid, SHM_PAGESIZE, &shm_buf) != 0 ) {
429- const int en = errno;
430- ::shmctl (shmid, IPC_RMID, nullptr ); // As early as possible!
431- log_warning (pagesize)(" shmctl(SHM_PAGESIZE) failed with errno=%d" , errno);
432- } else {
433- // Attach and double check pageisze.
434- void * p = ::shmat (shmid, nullptr , 0 );
435- ::shmctl (shmid, IPC_RMID, nullptr ); // As early as possible!
436- guarantee0 (p != (void *) -1 ); // Should always work.
437- const size_t real_pagesize = os::Aix::query_pagesize (p);
438- if (real_pagesize != pagesize) {
439- log_warning (pagesize)(" real page size (" SIZE_FORMAT_X " ) differs." , real_pagesize);
436+ assert (shmid != -1 , " shmget failed" );
437+ if (shmid != -1 ) {
438+ // Try to set pagesize.
439+ struct shmid_ds shm_buf = { };
440+ shm_buf.shm_pagesize = pagesize;
441+ if (::shmctl (shmid, SHM_PAGESIZE, &shm_buf) != 0 ) {
442+ const int en = errno;
443+ ::shmctl (shmid, IPC_RMID, nullptr ); // As early as possible!
444+ log_warning (pagesize)(" shmctl(SHM_PAGESIZE) failed with errno=%d" , errno);
440445 } else {
441- can_use = true ;
446+ // Attach and double check pageisze.
447+ void * p = ::shmat (shmid, nullptr , 0 );
448+ ::shmctl (shmid, IPC_RMID, nullptr ); // As early as possible!
449+ assert (p != (void *) -1 , " shmat failed" );
450+ if (p != (void *) -1 ) {
451+ const size_t real_pagesize = os::Aix::query_pagesize (p);
452+ if (real_pagesize != pagesize) {
453+ log_warning (pagesize)(" real page size (" SIZE_FORMAT_X " ) differs." , real_pagesize);
454+ } else {
455+ can_use = true ;
456+ }
457+ ::shmdt (p);
458+ }
442459 }
443- ::shmdt (p);
444460 }
445461 trcVerbose (" Can use: %s" , (can_use ? " yes" : " no" ));
446462 if (pagesize == 64 *K) {
@@ -450,6 +466,16 @@ static void query_multipage_support() {
450466 }
451467 }
452468
469+ // Can we use mmap with 64K pages? (Should be available with AIX7.3 TL1)
470+ {
471+ void * p = mmap (NULL , 64 *K, PROT_READ | PROT_WRITE, MAP_ANON_64K | MAP_ANONYMOUS | MAP_SHARED, -1 , 0 );
472+ assert (p != (void *) -1 , " mmap failed" );
473+ if (p != (void *) -1 ) {
474+ g_multipage_support.can_use_64K_mmap_pages = (64 *K == os::Aix::query_pagesize (p));
475+ munmap (p, 64 *K);
476+ }
477+ }
478+
453479 } // end: check which pages can be used for shared memory
454480
455481query_multipage_support_end:
@@ -462,6 +488,8 @@ static void query_multipage_support() {
462488 describe_pagesize (g_multipage_support.textpsize ));
463489 trcVerbose (" Thread stack page size (pthread): %s" ,
464490 describe_pagesize (g_multipage_support.pthr_stack_pagesize ));
491+ trcVerbose (" Can use 64K pages with mmap memory: %s" ,
492+ (g_multipage_support.can_use_64K_mmap_pages ? " yes" :" no" ));
465493 trcVerbose (" Default shared memory page size: %s" ,
466494 describe_pagesize (g_multipage_support.shmpsize ));
467495 trcVerbose (" Can use 64K pages dynamically with shared memory: %s" ,
@@ -1133,6 +1161,8 @@ void os::print_memory_info(outputStream* st) {
11331161 describe_pagesize (g_multipage_support.textpsize ));
11341162 st->print_cr (" Thread stack page size (pthread): %s" ,
11351163 describe_pagesize (g_multipage_support.pthr_stack_pagesize ));
1164+ st->print_cr (" Can use 64K pages with mmap memory: %s" ,
1165+ (g_multipage_support.can_use_64K_mmap_pages ? " yes" :" no" ));
11361166 st->print_cr (" Default shared memory page size: %s" ,
11371167 describe_pagesize (g_multipage_support.shmpsize ));
11381168 st->print_cr (" Can use 64K pages dynamically with shared memory: %s" ,
@@ -1612,6 +1642,10 @@ static char* reserve_mmaped_memory(size_t bytes, char* requested_addr) {
16121642 // later use msync(MS_INVALIDATE) (see os::uncommit_memory).
16131643 int flags = MAP_ANONYMOUS | MAP_SHARED;
16141644
1645+ if (os::vm_page_size () == 64 *K && g_multipage_support.can_use_64K_mmap_pages ) {
1646+ flags |= MAP_ANON_64K;
1647+ }
1648+
16151649 // MAP_FIXED is needed to enforce requested_addr - manpage is vague about what
16161650 // it means if wishaddress is given but MAP_FIXED is not set.
16171651 //
@@ -1661,7 +1695,11 @@ static char* reserve_mmaped_memory(size_t bytes, char* requested_addr) {
16611695 p2i (addr), p2i (addr + bytes), bytes);
16621696
16631697 // bookkeeping
1664- vmembk_add (addr, size, 4 *K, VMEM_MAPPED);
1698+ if (os::vm_page_size () == 64 *K && g_multipage_support.can_use_64K_mmap_pages ) {
1699+ vmembk_add (addr, size, 64 *K, VMEM_MAPPED);
1700+ } else {
1701+ vmembk_add (addr, size, 4 *K, VMEM_MAPPED);
1702+ }
16651703
16661704 // Test alignment, see above.
16671705 assert0 (is_aligned_to (addr, os::vm_page_size ()));
@@ -1854,8 +1892,8 @@ char* os::pd_reserve_memory(size_t bytes, bool exec) {
18541892 bytes = align_up (bytes, os::vm_page_size ());
18551893
18561894 // In 4K mode always use mmap.
1857- // In 64K mode allocate small sizes with mmap, large ones with 64K shmatted.
1858- if (os::vm_page_size () == 4 *K) {
1895+ // In 64K mode allocate with mmap if it supports 64K pages, otherwise use 64K shmatted.
1896+ if (os::vm_page_size () == 4 *K || g_multipage_support. can_use_64K_mmap_pages ) {
18591897 return reserve_mmaped_memory (bytes, nullptr /* requested_addr */ );
18601898 } else {
18611899 return reserve_shmated_memory (bytes, nullptr /* requested_addr */ );
@@ -2042,8 +2080,8 @@ char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool
20422080 bytes = align_up (bytes, os::vm_page_size ());
20432081
20442082 // In 4K mode always use mmap.
2045- // In 64K mode allocate small sizes with mmap, large ones with 64K shmatted.
2046- if (os::vm_page_size () == 4 *K) {
2083+ // In 64K mode allocate with mmap if it supports 64K pages, otherwise use 64K shmatted.
2084+ if (os::vm_page_size () == 4 *K || g_multipage_support. can_use_64K_mmap_pages ) {
20472085 return reserve_mmaped_memory (bytes, requested_addr);
20482086 } else {
20492087 return reserve_shmated_memory (bytes, requested_addr);
@@ -2183,18 +2221,18 @@ void os::init(void) {
21832221 // and should be allocated with 64k pages.
21842222 //
21852223 // So, we do the following:
2186- // LDR_CNTRL can_use_64K_pages_dynamically what we do remarks
2187- // 4K no 4K old systems (aix 5.2) or new systems with AME activated
2188- // 4k yes 64k (treat 4k stacks as 64k) different loader than java and standard settings
2224+ // LDR_CNTRL can_use_64K_pages_dynamically(mmap or shm) what we do remarks
2225+ // 4K no 4K old systems (aix 5.2) or new systems with AME activated
2226+ // 4k yes 64k (treat 4k stacks as 64k) different loader than java and standard settings
21892227 // 64k no --- AIX 5.2 ? ---
2190- // 64k yes 64k new systems and standard java loader (we set datapsize=64k when linking)
2228+ // 64k yes 64k new systems and standard java loader (we set datapsize=64k when linking)
21912229
21922230 // We explicitly leave no option to change page size, because only upgrading would work,
21932231 // not downgrading (if stack page size is 64k you cannot pretend its 4k).
21942232
21952233 if (g_multipage_support.datapsize == 4 *K) {
21962234 // datapsize = 4K. Data segment, thread stacks are 4K paged.
2197- if (g_multipage_support.can_use_64K_pages ) {
2235+ if (g_multipage_support.can_use_64K_pages || g_multipage_support. can_use_64K_mmap_pages ) {
21982236 // .. but we are able to use 64K pages dynamically.
21992237 // This would be typical for java launchers which are not linked
22002238 // with datapsize=64K (like, any other launcher but our own).
@@ -2224,7 +2262,7 @@ void os::init(void) {
22242262 // This normally means that we can allocate 64k pages dynamically.
22252263 // (There is one special case where this may be false: EXTSHM=on.
22262264 // but we decided to not support that mode).
2227- assert0 (g_multipage_support.can_use_64K_pages );
2265+ assert0 (g_multipage_support.can_use_64K_pages || g_multipage_support. can_use_64K_mmap_pages );
22282266 set_page_size (64 *K);
22292267 trcVerbose (" 64K page mode" );
22302268 FLAG_SET_ERGO (Use64KPages, true );
@@ -2709,6 +2747,10 @@ void os::Aix::initialize_libperfstat() {
27092747 }
27102748}
27112749
2750+ bool os::Aix::supports_64K_mmap_pages () {
2751+ return g_multipage_support.can_use_64K_mmap_pages ;
2752+ }
2753+
27122754// ///////////////////////////////////////////////////////////////////////////
27132755// thread stack
27142756
0 commit comments