mirror of
https://github.com/openjdk/jdk.git
synced 2026-06-06 10:42:45 +00:00
8334403: Unify behavior of os::committed_in_range across OSes
Reviewed-by: stuefe, jsjolen
This commit is contained in:
parent
7a7f37f0e5
commit
79923019f5
@ -167,11 +167,11 @@ void os::check_core_dump_prerequisites(char* buffer, size_t bufferSize, bool che
|
||||
}
|
||||
}
|
||||
|
||||
bool os::committed_in_range(address start, size_t size, address& committed_start, size_t& committed_size) {
|
||||
bool os::first_resident_in_range(address start, size_t size, address& resident_start, size_t& resident_size) {
|
||||
|
||||
#ifdef _AIX
|
||||
committed_start = start;
|
||||
committed_size = size;
|
||||
resident_start = start;
|
||||
resident_size = size;
|
||||
return true;
|
||||
#else
|
||||
|
||||
@ -188,10 +188,10 @@ bool os::committed_in_range(address start, size_t size, address& committed_start
|
||||
assert(is_aligned(start, page_sz), "Start address must be page aligned");
|
||||
assert(is_aligned(size, page_sz), "Size must be page aligned");
|
||||
|
||||
committed_start = nullptr;
|
||||
resident_start = nullptr;
|
||||
|
||||
int loops = checked_cast<int>((pages + stripe - 1) / stripe);
|
||||
int committed_pages = 0;
|
||||
int resident_pages = 0;
|
||||
address loop_base = start;
|
||||
bool found_range = false;
|
||||
|
||||
@ -210,7 +210,7 @@ bool os::committed_in_range(address start, size_t size, address& committed_start
|
||||
|
||||
// During shutdown, some memory goes away without properly notifying NMT,
|
||||
// E.g. ConcurrentGCThread/WatcherThread can exit without deleting thread object.
|
||||
// Bailout and return as not committed for now.
|
||||
// Bailout and return as not resident for now.
|
||||
if (mincore_return_value == -1 && errno == ENOMEM) {
|
||||
return false;
|
||||
}
|
||||
@ -224,32 +224,32 @@ bool os::committed_in_range(address start, size_t size, address& committed_start
|
||||
assert(mincore_return_value == 0, "Range must be valid");
|
||||
// Process this stripe
|
||||
for (uintx vecIdx = 0; vecIdx < pages_to_query; vecIdx ++) {
|
||||
if ((vec[vecIdx] & 0x01) == 0) { // not committed
|
||||
if ((vec[vecIdx] & 0x01) == 0) { // not resident
|
||||
// End of current contiguous region
|
||||
if (committed_start != nullptr) {
|
||||
if (resident_start != nullptr) {
|
||||
found_range = true;
|
||||
break;
|
||||
}
|
||||
} else { // committed
|
||||
} else { // resident
|
||||
// Start of region
|
||||
if (committed_start == nullptr) {
|
||||
committed_start = loop_base + page_sz * vecIdx;
|
||||
if (resident_start == nullptr) {
|
||||
resident_start = loop_base + page_sz * vecIdx;
|
||||
}
|
||||
committed_pages ++;
|
||||
resident_pages ++;
|
||||
}
|
||||
}
|
||||
|
||||
loop_base += pages_to_query * page_sz;
|
||||
}
|
||||
|
||||
if (committed_start != nullptr) {
|
||||
assert(committed_pages > 0, "Must have committed region");
|
||||
assert(committed_pages <= int(size / page_sz), "Can not commit more than it has");
|
||||
assert(committed_start >= start && committed_start < start + size, "Out of range");
|
||||
committed_size = page_sz * committed_pages;
|
||||
if (resident_start != nullptr) {
|
||||
assert(resident_pages > 0, "Must have a resident region");
|
||||
assert(resident_pages <= int(size / page_sz), "Resident size exceeds region size");
|
||||
assert(resident_start >= start && resident_start < start + size, "Out of range");
|
||||
resident_size = page_sz * resident_pages;
|
||||
return true;
|
||||
} else {
|
||||
assert(committed_pages == 0, "Should not have committed region");
|
||||
assert(resident_pages == 0, "Should not have a resident region");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -465,36 +465,63 @@ void os::current_stack_base_and_size(address* stack_base, size_t* stack_size) {
|
||||
*stack_size = size;
|
||||
}
|
||||
|
||||
bool os::committed_in_range(address start, size_t size, address& committed_start, size_t& committed_size) {
|
||||
MEMORY_BASIC_INFORMATION minfo;
|
||||
committed_start = nullptr;
|
||||
committed_size = 0;
|
||||
address top = start + size;
|
||||
const address start_addr = start;
|
||||
while (start < top) {
|
||||
VirtualQuery(start, &minfo, sizeof(minfo));
|
||||
if ((minfo.State & MEM_COMMIT) == 0) { // not committed
|
||||
if (committed_start != nullptr) {
|
||||
break;
|
||||
}
|
||||
} else { // committed
|
||||
if (committed_start == nullptr) {
|
||||
committed_start = start;
|
||||
}
|
||||
size_t offset = start - (address)minfo.BaseAddress;
|
||||
committed_size += minfo.RegionSize - offset;
|
||||
}
|
||||
start = (address)minfo.BaseAddress + minfo.RegionSize;
|
||||
}
|
||||
bool os::first_resident_in_range(address start, size_t size, address& resident_start, size_t& resident_size) {
|
||||
constexpr size_t stripe = 1024; // query this many pages each time
|
||||
PSAPI_WORKING_SET_EX_INFORMATION wsinfo[stripe];
|
||||
|
||||
if (committed_start == nullptr) {
|
||||
assert(committed_size == 0, "Sanity");
|
||||
return false;
|
||||
} else {
|
||||
assert(committed_start >= start_addr && committed_start < top, "Out of range");
|
||||
// current region may go beyond the limit, trim to the limit
|
||||
committed_size = MIN2(committed_size, size_t(top - committed_start));
|
||||
size_t page_sz = os::vm_page_size();
|
||||
uintx pages_left = size / page_sz;
|
||||
|
||||
assert(is_aligned(start, page_sz), "Start address must be page aligned");
|
||||
assert(is_aligned(size, page_sz), "Size must be page aligned");
|
||||
|
||||
resident_start = nullptr;
|
||||
|
||||
uintx loops = (pages_left + stripe - 1) / stripe;
|
||||
uintx resident_pages = 0;
|
||||
address pos = start;
|
||||
bool found_range = false;
|
||||
|
||||
for (uintx index = 0; index < loops && !found_range; index++) {
|
||||
assert(pages_left > 0, "Nothing to do");
|
||||
uintx pages_to_query = MIN2(pages_left, stripe);
|
||||
pages_left -= pages_to_query;
|
||||
|
||||
for (uintx i = 0; i < pages_to_query; i++) {
|
||||
wsinfo[i].VirtualAddress = (PVOID)(pos + i * page_sz);
|
||||
}
|
||||
|
||||
BOOL success = QueryWorkingSetEx(GetCurrentProcess(), wsinfo, pages_to_query * sizeof(PSAPI_WORKING_SET_EX_INFORMATION));
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uintx i = 0; i < pages_to_query; i++) {
|
||||
if (wsinfo[i].VirtualAttributes.Valid == 0) {
|
||||
if (resident_start != nullptr) {
|
||||
found_range = true;
|
||||
break;
|
||||
}
|
||||
// Still searching for start of resident region
|
||||
} else {
|
||||
if (resident_start == nullptr) {
|
||||
// Found first resident page in region
|
||||
resident_start = pos + i * page_sz;
|
||||
}
|
||||
resident_pages++;
|
||||
}
|
||||
}
|
||||
pos += pages_to_query * page_sz;
|
||||
}
|
||||
if (resident_start != nullptr) {
|
||||
assert(resident_pages > 0, "Must have a resident region");
|
||||
assert(resident_pages <= size / page_sz, "Resident size exceeds region size");
|
||||
assert(resident_start >= start && resident_start < start + size, "Out of range");
|
||||
resident_size = page_sz * resident_pages;
|
||||
return true;
|
||||
} else {
|
||||
assert(resident_pages == 0, "Should not have a resident region");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -283,7 +283,7 @@ bool RegionIterator::next_committed(address& committed_start, size_t& committed_
|
||||
|
||||
const size_t page_sz = os::vm_page_size();
|
||||
const size_t current_size = end() - _current_start;
|
||||
if (os::committed_in_range(_current_start, current_size, committed_start, committed_size)) {
|
||||
if (os::first_resident_in_range(_current_start, current_size, committed_start, committed_size)) {
|
||||
assert(committed_start != nullptr, "Must be");
|
||||
assert(committed_size > 0 && is_aligned(committed_size, os::vm_page_size()), "Must be");
|
||||
|
||||
|
||||
@ -440,9 +440,9 @@ class os: AllStatic {
|
||||
public:
|
||||
// get allowed minimum java stack size
|
||||
static jlong get_minimum_java_stack_size();
|
||||
// Find committed memory region within specified range (start, start + size),
|
||||
// return true if found any
|
||||
static bool committed_in_range(address start, size_t size, address& committed_start, size_t& committed_size);
|
||||
// Find the first resident memory region within the specified range (start, start + size) beginning at the start address.
|
||||
// Returns true if successful or false if none are found.
|
||||
static bool first_resident_in_range(address start, size_t size, address& resident_start, size_t& resident_size);
|
||||
|
||||
// OS interface to Virtual Memory
|
||||
|
||||
|
||||
@ -169,8 +169,8 @@ public:
|
||||
|
||||
static void test_partial_region() {
|
||||
bool result;
|
||||
size_t committed_size;
|
||||
address committed_start;
|
||||
size_t resident_size;
|
||||
address resident_start;
|
||||
size_t index;
|
||||
|
||||
const size_t page_sz = os::vm_page_size();
|
||||
@ -187,36 +187,36 @@ public:
|
||||
}
|
||||
|
||||
// Test whole range
|
||||
result = os::committed_in_range((address)base, size, committed_start, committed_size);
|
||||
result = os::first_resident_in_range((address)base, size, resident_start, resident_size);
|
||||
ASSERT_TRUE(result);
|
||||
ASSERT_EQ(num_pages * page_sz, committed_size);
|
||||
ASSERT_EQ(committed_start, (address)base);
|
||||
ASSERT_EQ(num_pages * page_sz, resident_size);
|
||||
ASSERT_EQ(resident_start, (address)base);
|
||||
|
||||
// Test beginning of the range
|
||||
result = os::committed_in_range((address)base, 2 * page_sz, committed_start, committed_size);
|
||||
result = os::first_resident_in_range((address)base, 2 * page_sz, resident_start, resident_size);
|
||||
ASSERT_TRUE(result);
|
||||
ASSERT_EQ(2 * page_sz, committed_size);
|
||||
ASSERT_EQ(committed_start, (address)base);
|
||||
ASSERT_EQ(2 * page_sz, resident_size);
|
||||
ASSERT_EQ(resident_start, (address)base);
|
||||
|
||||
// Test end of the range
|
||||
result = os::committed_in_range((address)(base + page_sz), 3 * page_sz, committed_start, committed_size);
|
||||
result = os::first_resident_in_range((address)(base + page_sz), 3 * page_sz, resident_start, resident_size);
|
||||
ASSERT_TRUE(result);
|
||||
ASSERT_EQ(3 * page_sz, committed_size);
|
||||
ASSERT_EQ(committed_start, (address)(base + page_sz));
|
||||
ASSERT_EQ(3 * page_sz, resident_size);
|
||||
ASSERT_EQ(resident_start, (address)(base + page_sz));
|
||||
|
||||
// Test middle of the range
|
||||
result = os::committed_in_range((address)(base + page_sz), 2 * page_sz, committed_start, committed_size);
|
||||
result = os::first_resident_in_range((address)(base + page_sz), 2 * page_sz, resident_start, resident_size);
|
||||
ASSERT_TRUE(result);
|
||||
ASSERT_EQ(2 * page_sz, committed_size);
|
||||
ASSERT_EQ(committed_start, (address)(base + page_sz));
|
||||
ASSERT_EQ(2 * page_sz, resident_size);
|
||||
ASSERT_EQ(resident_start, (address)(base + page_sz));
|
||||
|
||||
os::release_memory(base, size);
|
||||
}
|
||||
|
||||
static void test_committed_in_range(size_t num_pages, size_t pages_to_touch) {
|
||||
static void test_first_resident_in_range(size_t num_pages, size_t pages_to_touch) {
|
||||
bool result;
|
||||
size_t committed_size;
|
||||
address committed_start;
|
||||
size_t resident_size;
|
||||
address resident_start;
|
||||
size_t index;
|
||||
|
||||
const size_t page_sz = os::vm_page_size();
|
||||
@ -228,7 +228,7 @@ public:
|
||||
result = os::commit_memory(base, size, !ExecMem);
|
||||
ASSERT_TRUE(result);
|
||||
|
||||
result = os::committed_in_range((address)base, size, committed_start, committed_size);
|
||||
result = os::first_resident_in_range((address)base, size, resident_start, resident_size);
|
||||
ASSERT_FALSE(result);
|
||||
|
||||
// Touch pages
|
||||
@ -236,14 +236,14 @@ public:
|
||||
base[index * page_sz] = 'a';
|
||||
}
|
||||
|
||||
result = os::committed_in_range((address)base, size, committed_start, committed_size);
|
||||
result = os::first_resident_in_range((address)base, size, resident_start, resident_size);
|
||||
ASSERT_TRUE(result);
|
||||
ASSERT_EQ(pages_to_touch * page_sz, committed_size);
|
||||
ASSERT_EQ(committed_start, (address)base);
|
||||
ASSERT_EQ(pages_to_touch * page_sz, resident_size);
|
||||
ASSERT_EQ(resident_start, (address)base);
|
||||
|
||||
os::uncommit_memory(base, size, false);
|
||||
|
||||
result = os::committed_in_range((address)base, size, committed_start, committed_size);
|
||||
result = os::first_resident_in_range((address)base, size, resident_start, resident_size);
|
||||
ASSERT_FALSE(result);
|
||||
|
||||
os::release_memory(base, size);
|
||||
@ -266,9 +266,9 @@ TEST_VM(NMTCommittedVirtualMemoryTracker, test_committed_virtualmemory_region) {
|
||||
|
||||
}
|
||||
|
||||
#if !defined(_WINDOWS) && !defined(_AIX)
|
||||
TEST_VM(NMTCommittedVirtualMemory, test_committed_in_range){
|
||||
CommittedVirtualMemoryTest::test_committed_in_range(1024, 1024);
|
||||
CommittedVirtualMemoryTest::test_committed_in_range(2, 1);
|
||||
#if !defined(_AIX)
|
||||
TEST_VM(NMTCommittedVirtualMemory, test_first_resident_in_range){
|
||||
CommittedVirtualMemoryTest::test_first_resident_in_range(1024, 1024);
|
||||
CommittedVirtualMemoryTest::test_first_resident_in_range(2, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user