< prev index next >
src/hotspot/os/linux/os_linux.cpp
Print this page
*** 2961,2974 ****
uintptr_t res = (uintptr_t) ::mmap(addr, size, PROT_NONE,
MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0);
return res != (uintptr_t) MAP_FAILED;
}
! static address get_stack_commited_bottom(address bottom, size_t size) {
! address nbot = bottom;
! address ntop = bottom + size;
!
size_t page_sz = os::vm_page_size();
unsigned pages = size / page_sz;
unsigned char vec[1];
unsigned imin = 1, imax = pages + 1, imid;
--- 2961,2976 ----
uintptr_t res = (uintptr_t) ::mmap(addr, size, PROT_NONE,
MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0);
return res != (uintptr_t) MAP_FAILED;
}
! // If there is no page mapped/committed, top (bottom + size) is returned
! static address get_stack_mapped_bottom(address bottom,
! size_t size,
! bool committed_only /* must have backing pages */) {
! // address used to test if the page is mapped/committed
! address test_addr = bottom + size;
size_t page_sz = os::vm_page_size();
unsigned pages = size / page_sz;
unsigned char vec[1];
unsigned imin = 1, imax = pages + 1, imid;
*** 2976,3018 ****
assert(imin <= imax, "Unexpected page size");
while (imin < imax) {
imid = (imax + imin) / 2;
! nbot = ntop - (imid * page_sz);
// Use a trick with mincore to check whether the page is mapped or not.
// mincore sets vec to 1 if page resides in memory and to 0 if page
// is swapped output but if page we are asking for is unmapped
// it returns -1,ENOMEM
! mincore_return_value = mincore(nbot, page_sz, vec);
! if (mincore_return_value == -1) {
! // Page is not mapped go up
! // to find first mapped page
! if (errno != EAGAIN) {
! assert(errno == ENOMEM, "Unexpected mincore errno");
! imax = imid;
}
} else {
! // Page is mapped go down
! // to find first not mapped page
! imin = imid + 1;
}
}
! nbot = nbot + page_sz;
!
! // Adjust stack bottom one page up if last checked page is not mapped
! if (mincore_return_value == -1) {
! nbot = nbot + page_sz;
}
! return nbot;
}
-
// Linux uses a growable mapping for the stack, and if the mapping for
// the stack guard pages is not removed when we detach a thread the
// stack cannot grow beyond the pages where the stack guard was
// mapped. If at some point later in the process the stack expands to
// that point, the Linux kernel cannot expand the stack any further
--- 2978,3017 ----
assert(imin <= imax, "Unexpected page size");
while (imin < imax) {
imid = (imax + imin) / 2;
! test_addr = bottom + (imid * page_sz);
// Use a trick with mincore to check whether the page is mapped or not.
// mincore sets vec to 1 if page resides in memory and to 0 if page
// is swapped output but if page we are asking for is unmapped
// it returns -1,ENOMEM
! mincore_return_value = mincore(test_addr, page_sz, vec);
!
! if (mincore_return_value == -1 || (committed_only && (vec[0] & 0x01) == 0)) {
! // Page is not mapped/committed go up
! // to find first mapped/committed page
! if (errno != EAGAIN || (committed_only && (vec[0] & 0x01) == 0)) {
! assert(mincore_return_value != -1 || errno == ENOMEM, "Unexpected mincore errno");
! imin = imid + 1;
}
} else {
! // mapped/committed, go down
! imax= imid;
}
}
! // Adjust stack bottom one page up if last checked page is not mapped/committed
! if (mincore_return_value == -1 || (committed_only && (vec[0] & 0x01) == 0)) {
! test_addr = test_addr + page_sz;
}
! return test_addr;
}
// Linux uses a growable mapping for the stack, and if the mapping for
// the stack guard pages is not removed when we detach a thread the
// stack cannot grow beyond the pages where the stack guard was
// mapped. If at some point later in the process the stack expands to
// that point, the Linux kernel cannot expand the stack any further
*** 3045,3057 ****
uintptr_t stack_extent = (uintptr_t) os::Linux::initial_thread_stack_bottom();
unsigned char vec[1];
if (mincore((address)stack_extent, os::vm_page_size(), vec) == -1) {
// Fallback to slow path on all errors, including EAGAIN
! stack_extent = (uintptr_t) get_stack_commited_bottom(
! os::Linux::initial_thread_stack_bottom(),
! (size_t)addr - stack_extent);
}
if (stack_extent < (uintptr_t)addr) {
::munmap((void*)stack_extent, (uintptr_t)(addr - stack_extent));
}
--- 3044,3056 ----
uintptr_t stack_extent = (uintptr_t) os::Linux::initial_thread_stack_bottom();
unsigned char vec[1];
if (mincore((address)stack_extent, os::vm_page_size(), vec) == -1) {
// Fallback to slow path on all errors, including EAGAIN
! stack_extent = (uintptr_t) get_stack_mapped_bottom(os::Linux::initial_thread_stack_bottom(),
! (size_t)addr - stack_extent,
! false /* committed_only */);
}
if (stack_extent < (uintptr_t)addr) {
::munmap((void*)stack_extent, (uintptr_t)(addr - stack_extent));
}
*** 3074,3083 ****
--- 3073,3087 ----
}
return os::uncommit_memory(addr, size);
}
+ size_t os::pd_committed_stack_size(address bottom, size_t size) {
+ address bot = get_stack_mapped_bottom(bottom, size, true /* committed_only */);
+ return size_t(bottom + size - bot);
+ }
+
// If 'fixed' is true, anon_mmap() will attempt to reserve anonymous memory
// at 'requested_addr'. If there are existing memory mappings at the same
// location, however, they will be overwritten. If 'fixed' is false,
// 'requested_addr' is only treated as a hint, the return value may or
// may not start from the requested address. Unlike Linux mmap(), this
< prev index next >