< 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 >