mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-17 17:07:53 +00:00
8353564: Fail fatally if os::release_memory or os::uncommit_memory fails
Reviewed-by: stefank, stuefe, dholmes
This commit is contained in:
parent
0842782b7a
commit
9c75afb6d0
@ -1753,10 +1753,9 @@ bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool os::remove_stack_guard_pages(char* addr, size_t size) {
|
||||
void os::remove_stack_guard_pages(char* addr, size_t size) {
|
||||
// Do not call this; no need to commit stack pages on AIX.
|
||||
ShouldNotReachHere();
|
||||
return true;
|
||||
}
|
||||
|
||||
void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) {
|
||||
|
||||
@ -1782,10 +1782,8 @@ bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
|
||||
return os::commit_memory(addr, size, !ExecMem);
|
||||
}
|
||||
|
||||
// If this is a growable mapping, remove the guard pages entirely by
|
||||
// munmap()ping them. If not, just call uncommit_memory().
|
||||
bool os::remove_stack_guard_pages(char* addr, size_t size) {
|
||||
return os::uncommit_memory(addr, size);
|
||||
void os::remove_stack_guard_pages(char* addr, size_t size) {
|
||||
os::uncommit_memory(addr, size);
|
||||
}
|
||||
|
||||
// 'requested_addr' is only treated as a hint, the return value may or
|
||||
|
||||
@ -3523,6 +3523,9 @@ bool os::pd_uncommit_memory(char* addr, size_t size, bool exec) {
|
||||
log_trace(os, map)("mmap failed: " RANGEFMT " errno=(%s)",
|
||||
RANGEFMTARGS(addr, size),
|
||||
os::strerror(ep.saved_errno()));
|
||||
if (ep.saved_errno() == ENOMEM) {
|
||||
fatal("Failed to uncommit " RANGEFMT ". It is possible that the process's maximum number of mappings would have been exceeded. Try increasing the limit.", RANGEFMTARGS(addr, size));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -3633,14 +3636,16 @@ bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
|
||||
// It's safe to always unmap guard pages for primordial thread because we
|
||||
// always place it right after end of the mapped region.
|
||||
|
||||
bool os::remove_stack_guard_pages(char* addr, size_t size) {
|
||||
uintptr_t stack_extent, stack_base;
|
||||
void os::remove_stack_guard_pages(char* addr, size_t size) {
|
||||
|
||||
if (os::is_primordial_thread()) {
|
||||
return ::munmap(addr, size) == 0;
|
||||
if (::munmap(addr, size) != 0) {
|
||||
fatal("Failed to munmap " RANGEFMT, RANGEFMTARGS(addr, size));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
return os::uncommit_memory(addr, size);
|
||||
os::uncommit_memory(addr, size);
|
||||
}
|
||||
|
||||
// 'requested_addr' is only treated as a hint, the return value may or
|
||||
|
||||
@ -3281,11 +3281,10 @@ static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fi
|
||||
// Do manual alignment
|
||||
aligned_base = align_up(extra_base, alignment);
|
||||
|
||||
bool rc = (file_desc != -1) ? os::unmap_memory(extra_base, extra_size) :
|
||||
os::release_memory(extra_base, extra_size);
|
||||
assert(rc, "release failed");
|
||||
if (!rc) {
|
||||
return nullptr;
|
||||
if (file_desc != -1) {
|
||||
os::unmap_memory(extra_base, extra_size);
|
||||
} else {
|
||||
os::release_memory(extra_base, extra_size);
|
||||
}
|
||||
|
||||
// Attempt to map, into the just vacated space, the slightly smaller aligned area.
|
||||
@ -3681,8 +3680,8 @@ bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
|
||||
return os::commit_memory(addr, size, !ExecMem);
|
||||
}
|
||||
|
||||
bool os::remove_stack_guard_pages(char* addr, size_t size) {
|
||||
return os::uncommit_memory(addr, size);
|
||||
void os::remove_stack_guard_pages(char* addr, size_t size) {
|
||||
os::uncommit_memory(addr, size);
|
||||
}
|
||||
|
||||
static bool protect_pages_individually(char* addr, size_t bytes, unsigned int p, DWORD *old_status) {
|
||||
|
||||
@ -1325,9 +1325,7 @@ char* FileMapInfo::map_auxiliary_region(int region_index, bool read_only) {
|
||||
|
||||
if (VerifySharedSpaces && !r->check_region_crc(mapped_base)) {
|
||||
aot_log_error(aot)("region %d CRC error", region_index);
|
||||
if (!os::unmap_memory(mapped_base, r->used_aligned())) {
|
||||
fatal("os::unmap_memory of region %d failed", region_index);
|
||||
}
|
||||
os::unmap_memory(mapped_base, r->used_aligned());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1654,9 +1652,7 @@ void FileMapInfo::unmap_region(int i) {
|
||||
// is released. Zero it so that we don't accidentally read its content.
|
||||
aot_log_info(aot)("Region #%d (%s) is in a reserved space, it will be freed when the space is released", i, shared_region_name[i]);
|
||||
} else {
|
||||
if (!os::unmap_memory(mapped_base, size)) {
|
||||
fatal("os::unmap_memory failed");
|
||||
}
|
||||
os::unmap_memory(mapped_base, size);
|
||||
}
|
||||
}
|
||||
r->set_mapped_base(nullptr);
|
||||
|
||||
@ -78,12 +78,13 @@ bool PSVirtualSpace::shrink_by(size_t bytes) {
|
||||
}
|
||||
|
||||
char* const base_addr = committed_high_addr() - bytes;
|
||||
bool result = special() || os::uncommit_memory(base_addr, bytes);
|
||||
if (result) {
|
||||
_committed_high_addr -= bytes;
|
||||
if (!special()) {
|
||||
os::uncommit_memory(base_addr, bytes);
|
||||
}
|
||||
|
||||
return result;
|
||||
_committed_high_addr -= bytes;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
|
||||
@ -169,9 +169,7 @@ void CardTable::resize_covered_region(MemRegion new_region) {
|
||||
// Shrink.
|
||||
MemRegion delta = MemRegion(new_committed.end(),
|
||||
old_committed.word_size() - new_committed.word_size());
|
||||
bool res = os::uncommit_memory((char*)delta.start(),
|
||||
delta.byte_size());
|
||||
assert(res, "uncommit should succeed");
|
||||
os::uncommit_memory((char*)delta.start(), delta.byte_size());
|
||||
}
|
||||
|
||||
log_trace(gc, barrier)("CardTable::resize_covered_region: ");
|
||||
|
||||
@ -1775,12 +1775,7 @@ void ShenandoahHeap::scan_roots_for_iteration(ShenandoahScanObjectStack* oop_sta
|
||||
|
||||
void ShenandoahHeap::reclaim_aux_bitmap_for_iteration() {
|
||||
if (!_aux_bitmap_region_special) {
|
||||
bool success = os::uncommit_memory((char*)_aux_bitmap_region.start(), _aux_bitmap_region.byte_size());
|
||||
if (!success) {
|
||||
log_warning(gc)("Auxiliary marking bitmap uncommit failed: " PTR_FORMAT " (%zu bytes)",
|
||||
p2i(_aux_bitmap_region.start()), _aux_bitmap_region.byte_size());
|
||||
assert(false, "Auxiliary marking bitmap uncommit should always succeed");
|
||||
}
|
||||
os::uncommit_memory((char*)_aux_bitmap_region.start(), _aux_bitmap_region.byte_size());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2626,11 +2621,7 @@ void ShenandoahHeap::uncommit_bitmap_slice(ShenandoahHeapRegion *r) {
|
||||
size_t len = _bitmap_bytes_per_slice;
|
||||
|
||||
char* addr = (char*) _bitmap_region.start() + off;
|
||||
bool success = os::uncommit_memory(addr, len);
|
||||
if (!success) {
|
||||
log_warning(gc)("Bitmap slice uncommit failed: " PTR_FORMAT " (%zu bytes)", p2i(addr), len);
|
||||
assert(false, "Bitmap slice uncommit should always succeed");
|
||||
}
|
||||
os::uncommit_memory(addr, len);
|
||||
}
|
||||
|
||||
void ShenandoahHeap::forbid_uncommit() {
|
||||
|
||||
@ -816,11 +816,7 @@ void ShenandoahHeapRegion::do_commit() {
|
||||
void ShenandoahHeapRegion::do_uncommit() {
|
||||
ShenandoahHeap* heap = ShenandoahHeap::heap();
|
||||
if (!heap->is_heap_region_special()) {
|
||||
bool success = os::uncommit_memory((char *) bottom(), RegionSizeBytes);
|
||||
if (!success) {
|
||||
log_warning(gc)("Region uncommit failed: " PTR_FORMAT " (%zu bytes)", p2i(bottom()), RegionSizeBytes);
|
||||
assert(false, "Region uncommit should always succeed");
|
||||
}
|
||||
os::uncommit_memory((char *) bottom(), RegionSizeBytes);
|
||||
}
|
||||
if (!heap->is_bitmap_region_special()) {
|
||||
heap->uncommit_bitmap_slice(this);
|
||||
|
||||
@ -87,8 +87,7 @@ E* MmapArrayAllocator<E>::allocate(size_t length, MemTag mem_tag) {
|
||||
|
||||
template <class E>
|
||||
void MmapArrayAllocator<E>::free(E* addr, size_t length) {
|
||||
bool result = os::release_memory((char*)addr, size_for(length));
|
||||
assert(result, "Failed to release memory");
|
||||
os::release_memory((char*)addr, size_for(length));
|
||||
}
|
||||
|
||||
template <class E>
|
||||
|
||||
@ -99,9 +99,7 @@ static char* reserve_memory_inner(char* requested_address,
|
||||
}
|
||||
|
||||
// Base not aligned, retry.
|
||||
if (!os::release_memory(base, size)) {
|
||||
fatal("os::release_memory failed");
|
||||
}
|
||||
os::release_memory(base, size);
|
||||
|
||||
// Map using the requested alignment.
|
||||
return os::reserve_memory_aligned(size, alignment, mem_tag, exec);
|
||||
@ -231,13 +229,13 @@ ReservedSpace MemoryReserver::reserve(size_t size,
|
||||
mem_tag);
|
||||
}
|
||||
|
||||
bool MemoryReserver::release(const ReservedSpace& reserved) {
|
||||
void MemoryReserver::release(const ReservedSpace& reserved) {
|
||||
assert(reserved.is_reserved(), "Precondition");
|
||||
|
||||
if (reserved.special()) {
|
||||
return os::release_memory_special(reserved.base(), reserved.size());
|
||||
os::release_memory_special(reserved.base(), reserved.size());
|
||||
} else {
|
||||
return os::release_memory(reserved.base(), reserved.size());
|
||||
os::release_memory(reserved.base(), reserved.size());
|
||||
}
|
||||
}
|
||||
|
||||
@ -266,9 +264,7 @@ static char* map_memory_to_file(char* requested_address,
|
||||
|
||||
|
||||
// Base not aligned, retry.
|
||||
if (!os::unmap_memory(base, size)) {
|
||||
fatal("os::unmap_memory failed");
|
||||
}
|
||||
os::unmap_memory(base, size);
|
||||
|
||||
// Map using the requested alignment.
|
||||
return os::map_memory_to_file_aligned(size, alignment, fd, mem_tag);
|
||||
|
||||
@ -70,7 +70,7 @@ public:
|
||||
MemTag mem_tag);
|
||||
|
||||
// Release reserved memory
|
||||
static bool release(const ReservedSpace& reserved);
|
||||
static void release(const ReservedSpace& reserved);
|
||||
};
|
||||
|
||||
class CodeMemoryReserver : AllStatic {
|
||||
|
||||
@ -190,10 +190,7 @@ void VirtualSpaceNode::uncommit_range(MetaWord* p, size_t word_size) {
|
||||
}
|
||||
|
||||
// Uncommit...
|
||||
if (os::uncommit_memory((char*)p, word_size * BytesPerWord) == false) {
|
||||
// Note: this can actually happen, since uncommit may increase the number of mappings.
|
||||
fatal("Failed to uncommit metaspace.");
|
||||
}
|
||||
os::uncommit_memory((char*)p, word_size * BytesPerWord);
|
||||
|
||||
ASAN_POISON_MEMORY_REGION((char*)p, word_size * BytesPerWord);
|
||||
|
||||
|
||||
@ -370,34 +370,22 @@ void VirtualSpace::shrink_by(size_t size) {
|
||||
assert(middle_high_boundary() <= aligned_upper_new_high &&
|
||||
aligned_upper_new_high + upper_needs <= upper_high_boundary(),
|
||||
"must not shrink beyond region");
|
||||
if (!os::uncommit_memory(aligned_upper_new_high, upper_needs, _executable)) {
|
||||
DEBUG_ONLY(warning("os::uncommit_memory failed"));
|
||||
return;
|
||||
} else {
|
||||
_upper_high -= upper_needs;
|
||||
}
|
||||
os::uncommit_memory(aligned_upper_new_high, upper_needs, _executable);
|
||||
_upper_high -= upper_needs;
|
||||
}
|
||||
if (middle_needs > 0) {
|
||||
assert(lower_high_boundary() <= aligned_middle_new_high &&
|
||||
aligned_middle_new_high + middle_needs <= middle_high_boundary(),
|
||||
"must not shrink beyond region");
|
||||
if (!os::uncommit_memory(aligned_middle_new_high, middle_needs, _executable)) {
|
||||
DEBUG_ONLY(warning("os::uncommit_memory failed"));
|
||||
return;
|
||||
} else {
|
||||
_middle_high -= middle_needs;
|
||||
}
|
||||
os::uncommit_memory(aligned_middle_new_high, middle_needs, _executable);
|
||||
_middle_high -= middle_needs;
|
||||
}
|
||||
if (lower_needs > 0) {
|
||||
assert(low_boundary() <= aligned_lower_new_high &&
|
||||
aligned_lower_new_high + lower_needs <= lower_high_boundary(),
|
||||
"must not shrink beyond region");
|
||||
if (!os::uncommit_memory(aligned_lower_new_high, lower_needs, _executable)) {
|
||||
DEBUG_ONLY(warning("os::uncommit_memory failed"));
|
||||
return;
|
||||
} else {
|
||||
_lower_high -= lower_needs;
|
||||
}
|
||||
os::uncommit_memory(aligned_lower_new_high, lower_needs, _executable);
|
||||
_lower_high -= lower_needs;
|
||||
}
|
||||
|
||||
_high -= size;
|
||||
|
||||
@ -2293,7 +2293,7 @@ void os::commit_memory_or_exit(char* addr, size_t size, size_t alignment_hint,
|
||||
// We do not have the same lock protection for pd_commit_memory and record_virtual_memory_commit.
|
||||
// We assume that there is some external synchronization that prevents a region from being uncommitted
|
||||
// before it is finished being committed.
|
||||
bool os::uncommit_memory(char* addr, size_t bytes, bool executable) {
|
||||
void os::uncommit_memory(char* addr, size_t bytes, bool executable) {
|
||||
assert_nonempty_range(addr, bytes);
|
||||
bool res;
|
||||
if (MemTracker::enabled()) {
|
||||
@ -2306,13 +2306,10 @@ bool os::uncommit_memory(char* addr, size_t bytes, bool executable) {
|
||||
res = pd_uncommit_memory(addr, bytes, executable);
|
||||
}
|
||||
|
||||
if (res) {
|
||||
log_debug(os, map)("Uncommitted " RANGEFMT, RANGEFMTARGS(addr, bytes));
|
||||
} else {
|
||||
log_info(os, map)("Failed to uncommit " RANGEFMT, RANGEFMTARGS(addr, bytes));
|
||||
if (!res) {
|
||||
fatal("Failed to uncommit " RANGEFMT, RANGEFMTARGS(addr, bytes));
|
||||
}
|
||||
|
||||
return res;
|
||||
log_debug(os, map)("Uncommitted " RANGEFMT, RANGEFMTARGS(addr, bytes));
|
||||
}
|
||||
|
||||
// The scope of NmtVirtualMemoryLocker covers both pd_release_memory and record_virtual_memory_release because
|
||||
@ -2320,7 +2317,7 @@ bool os::uncommit_memory(char* addr, size_t bytes, bool executable) {
|
||||
// We do not have the same lock protection for pd_reserve_memory and record_virtual_memory_reserve.
|
||||
// We assume that there is some external synchronization that prevents a region from being released
|
||||
// before it is finished being reserved.
|
||||
bool os::release_memory(char* addr, size_t bytes) {
|
||||
void os::release_memory(char* addr, size_t bytes) {
|
||||
assert_nonempty_range(addr, bytes);
|
||||
bool res;
|
||||
if (MemTracker::enabled()) {
|
||||
@ -2333,11 +2330,9 @@ bool os::release_memory(char* addr, size_t bytes) {
|
||||
res = pd_release_memory(addr, bytes);
|
||||
}
|
||||
if (!res) {
|
||||
log_info(os, map)("Failed to release " RANGEFMT, RANGEFMTARGS(addr, bytes));
|
||||
} else {
|
||||
log_debug(os, map)("Released " RANGEFMT, RANGEFMTARGS(addr, bytes));
|
||||
fatal("Failed to release " RANGEFMT, RANGEFMTARGS(addr, bytes));
|
||||
}
|
||||
return res;
|
||||
log_debug(os, map)("Released " RANGEFMT, RANGEFMTARGS(addr, bytes));
|
||||
}
|
||||
|
||||
// Prints all mappings
|
||||
@ -2406,7 +2401,7 @@ char* os::map_memory(int fd, const char* file_name, size_t file_offset,
|
||||
return result;
|
||||
}
|
||||
|
||||
bool os::unmap_memory(char *addr, size_t bytes) {
|
||||
void os::unmap_memory(char *addr, size_t bytes) {
|
||||
bool result;
|
||||
if (MemTracker::enabled()) {
|
||||
MemTracker::NmtVirtualMemoryLocker nvml;
|
||||
@ -2417,7 +2412,9 @@ bool os::unmap_memory(char *addr, size_t bytes) {
|
||||
} else {
|
||||
result = pd_unmap_memory(addr, bytes);
|
||||
}
|
||||
return result;
|
||||
if (!result) {
|
||||
fatal("Failed to unmap memory " RANGEFMT, RANGEFMTARGS(addr, bytes));
|
||||
}
|
||||
}
|
||||
|
||||
void os::disclaim_memory(char *addr, size_t bytes) {
|
||||
@ -2445,7 +2442,7 @@ char* os::reserve_memory_special(size_t size, size_t alignment, size_t page_size
|
||||
return result;
|
||||
}
|
||||
|
||||
bool os::release_memory_special(char* addr, size_t bytes) {
|
||||
void os::release_memory_special(char* addr, size_t bytes) {
|
||||
bool res;
|
||||
if (MemTracker::enabled()) {
|
||||
MemTracker::NmtVirtualMemoryLocker nvml;
|
||||
@ -2456,7 +2453,9 @@ bool os::release_memory_special(char* addr, size_t bytes) {
|
||||
} else {
|
||||
res = pd_release_memory_special(addr, bytes);
|
||||
}
|
||||
return res;
|
||||
if (!res) {
|
||||
fatal("Failed to release memory special " RANGEFMT, RANGEFMTARGS(addr, bytes));
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience wrapper around naked_short_sleep to allow for longer sleep
|
||||
|
||||
@ -536,8 +536,8 @@ class os: AllStatic {
|
||||
static void commit_memory_or_exit(char* addr, size_t size,
|
||||
size_t alignment_hint,
|
||||
bool executable, const char* mesg);
|
||||
static bool uncommit_memory(char* addr, size_t bytes, bool executable = false);
|
||||
static bool release_memory(char* addr, size_t bytes);
|
||||
static void uncommit_memory(char* addr, size_t bytes, bool executable = false);
|
||||
static void release_memory(char* addr, size_t bytes);
|
||||
|
||||
// Does the platform support trimming the native heap?
|
||||
static bool can_trim_native_heap();
|
||||
@ -566,7 +566,7 @@ class os: AllStatic {
|
||||
static bool unguard_memory(char* addr, size_t bytes);
|
||||
static bool create_stack_guard_pages(char* addr, size_t bytes);
|
||||
static bool pd_create_stack_guard_pages(char* addr, size_t bytes);
|
||||
static bool remove_stack_guard_pages(char* addr, size_t bytes);
|
||||
static void remove_stack_guard_pages(char* addr, size_t bytes);
|
||||
// Helper function to create a new file with template jvmheap.XXXXXX.
|
||||
// Returns a valid fd on success or else returns -1
|
||||
static int create_file_for_heap(const char* dir);
|
||||
@ -582,7 +582,7 @@ class os: AllStatic {
|
||||
static char* map_memory(int fd, const char* file_name, size_t file_offset,
|
||||
char *addr, size_t bytes, MemTag mem_tag, bool read_only = false,
|
||||
bool allow_exec = false);
|
||||
static bool unmap_memory(char *addr, size_t bytes);
|
||||
static void unmap_memory(char *addr, size_t bytes);
|
||||
static void disclaim_memory(char *addr, size_t bytes);
|
||||
static void realign_memory(char *addr, size_t bytes, size_t alignment_hint);
|
||||
|
||||
@ -605,7 +605,7 @@ class os: AllStatic {
|
||||
// reserve, commit and pin the entire memory region
|
||||
static char* reserve_memory_special(size_t size, size_t alignment, size_t page_size,
|
||||
char* addr, bool executable);
|
||||
static bool release_memory_special(char* addr, size_t bytes);
|
||||
static void release_memory_special(char* addr, size_t bytes);
|
||||
static void large_page_init();
|
||||
static size_t large_page_size();
|
||||
static bool can_commit_large_page_memory();
|
||||
|
||||
@ -116,13 +116,8 @@ void StackOverflow::remove_stack_guard_pages() {
|
||||
size_t len = stack_guard_zone_size();
|
||||
|
||||
if (os::must_commit_stack_guard_pages()) {
|
||||
if (os::remove_stack_guard_pages((char *) low_addr, len)) {
|
||||
_stack_guard_state = stack_guard_unused;
|
||||
} else {
|
||||
log_warning(os, thread)("Attempt to deallocate stack guard pages failed ("
|
||||
PTR_FORMAT "-" PTR_FORMAT ").", p2i(low_addr), p2i(low_addr + len));
|
||||
return;
|
||||
}
|
||||
os::remove_stack_guard_pages((char *) low_addr, len);
|
||||
_stack_guard_state = stack_guard_unused;
|
||||
} else {
|
||||
if (_stack_guard_state == stack_guard_unused) return;
|
||||
if (os::unguard_memory((char *) low_addr, len)) {
|
||||
|
||||
@ -168,8 +168,7 @@ public:
|
||||
ASSERT_EQ(vmem, ZVirtualMemory(base_offset + 2 * ZGranuleSize, ZGranuleSize));
|
||||
_reserver->unreserve(vmem);
|
||||
|
||||
const bool released = os::release_memory((char*)untype(blocked), ZGranuleSize);
|
||||
ASSERT_TRUE(released);
|
||||
os::release_memory((char*)untype(blocked), ZGranuleSize);
|
||||
}
|
||||
|
||||
void test_remove_from_low() {
|
||||
|
||||
@ -34,7 +34,7 @@ namespace {
|
||||
public:
|
||||
MemoryReleaser(ReservedSpace* rs) : _rs(rs) { }
|
||||
~MemoryReleaser() {
|
||||
EXPECT_TRUE(MemoryReserver::release(*_rs));
|
||||
MemoryReserver::release(*_rs);
|
||||
}
|
||||
};
|
||||
|
||||
@ -355,9 +355,9 @@ class TestReservedSpace : AllStatic {
|
||||
|
||||
static void release_memory_for_test(ReservedSpace rs) {
|
||||
if (rs.special()) {
|
||||
EXPECT_TRUE(os::release_memory_special(rs.base(), rs.size()));
|
||||
os::release_memory_special(rs.base(), rs.size());
|
||||
} else {
|
||||
EXPECT_TRUE(os::release_memory(rs.base(), rs.size()));
|
||||
os::release_memory(rs.base(), rs.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -511,7 +511,7 @@ static inline bool can_reserve_executable_memory(void) {
|
||||
static void carefully_release_multiple(address start, int num_stripes, size_t stripe_len) {
|
||||
for (int stripe = 0; stripe < num_stripes; stripe++) {
|
||||
address q = start + (stripe * stripe_len);
|
||||
EXPECT_TRUE(os::release_memory((char*)q, stripe_len));
|
||||
os::release_memory((char*)q, stripe_len);
|
||||
}
|
||||
}
|
||||
|
||||
@ -534,7 +534,7 @@ static address reserve_multiple(int num_stripes, size_t stripe_len) {
|
||||
p = (address)os::reserve_memory(total_range_len, mtTest);
|
||||
EXPECT_NE(p, (address)nullptr);
|
||||
// .. release it...
|
||||
EXPECT_TRUE(os::release_memory((char*)p, total_range_len));
|
||||
os::release_memory((char*)p, total_range_len);
|
||||
// ... re-reserve in the same spot multiple areas...
|
||||
for (int stripe = 0; stripe < num_stripes; stripe++) {
|
||||
address q = p + (stripe * stripe_len);
|
||||
@ -627,7 +627,7 @@ TEST_VM(os, release_multi_mappings) {
|
||||
// On Windows, temporarily switch on UseNUMAInterleaving to allow release_memory to release
|
||||
// multiple mappings in one go (otherwise we assert, which we test too, see death test below).
|
||||
WINDOWS_ONLY(NUMASwitcher b(true);)
|
||||
ASSERT_TRUE(os::release_memory((char*)p_middle_stripes, middle_stripe_len));
|
||||
os::release_memory((char*)p_middle_stripes, middle_stripe_len);
|
||||
}
|
||||
PRINT_MAPPINGS("B");
|
||||
|
||||
@ -641,7 +641,7 @@ TEST_VM(os, release_multi_mappings) {
|
||||
// Clean up. Release all mappings.
|
||||
{
|
||||
WINDOWS_ONLY(NUMASwitcher b(true);) // allow release_memory to release multiple regions
|
||||
ASSERT_TRUE(os::release_memory((char*)p, total_range_len));
|
||||
os::release_memory((char*)p, total_range_len);
|
||||
}
|
||||
}
|
||||
#endif // !AIX
|
||||
@ -650,29 +650,54 @@ TEST_VM(os, release_multi_mappings) {
|
||||
// On Windows, test that we recognize bad ranges.
|
||||
// On debug this would assert. Test that too.
|
||||
// On other platforms, we are unable to recognize bad ranges.
|
||||
#ifdef ASSERT
|
||||
TEST_VM_ASSERT_MSG(os, release_bad_ranges, ".*bad release") {
|
||||
#else
|
||||
TEST_VM(os, release_bad_ranges) {
|
||||
#endif
|
||||
char* p = os::reserve_memory(4 * M, mtTest);
|
||||
ASSERT_NE(p, (char*)nullptr);
|
||||
// Release part of range
|
||||
ASSERT_FALSE(os::release_memory(p, M));
|
||||
// Release part of range
|
||||
ASSERT_FALSE(os::release_memory(p + M, M));
|
||||
// Release more than the range (explicitly switch off NUMA here
|
||||
// to make os::release_memory() test more strictly and to not
|
||||
// accidentally release neighbors)
|
||||
{
|
||||
NUMASwitcher b(false);
|
||||
ASSERT_FALSE(os::release_memory(p, M * 5));
|
||||
ASSERT_FALSE(os::release_memory(p - M, M * 5));
|
||||
ASSERT_FALSE(os::release_memory(p - M, M * 6));
|
||||
}
|
||||
|
||||
ASSERT_TRUE(os::release_memory(p, 4 * M)); // Release for real
|
||||
ASSERT_FALSE(os::release_memory(p, 4 * M)); // Again, should fail
|
||||
#ifdef ASSERT
|
||||
#define TEST_RELEASE_RANGE_ERROR(name) TEST_VM_ASSERT_MSG(os, name, ".*bad release")
|
||||
#else
|
||||
#define TEST_RELEASE_RANGE_ERROR(name) TEST_VM_FATAL_ERROR_MSG(os, name, ".*Failed to release.*")
|
||||
#endif
|
||||
|
||||
static char* setup_release_test_memory() {
|
||||
char* p = os::reserve_memory(4 * M, mtTest);
|
||||
EXPECT_NE(p, (char*)nullptr);
|
||||
return p;
|
||||
}
|
||||
|
||||
TEST_RELEASE_RANGE_ERROR(release_bad_range_start) {
|
||||
char* p = setup_release_test_memory();
|
||||
os::release_memory(p, M); // Release part of the range
|
||||
}
|
||||
|
||||
TEST_RELEASE_RANGE_ERROR(release_bad_range_middle) {
|
||||
char* p = setup_release_test_memory();
|
||||
os::release_memory(p + M, M); // Release middle part
|
||||
}
|
||||
|
||||
// Release more than the range (explicitly switch off NUMA here
|
||||
// to make os::release_memory() test more strict and to not
|
||||
// accidentally release neighbors)
|
||||
TEST_RELEASE_RANGE_ERROR(release_beyond_range1) {
|
||||
char* p = setup_release_test_memory();
|
||||
NUMASwitcher b(false);
|
||||
os::release_memory(p, M * 5);
|
||||
}
|
||||
|
||||
TEST_RELEASE_RANGE_ERROR(release_beyond_range2) {
|
||||
char* p = setup_release_test_memory();
|
||||
NUMASwitcher b(false);
|
||||
os::release_memory(p - M, M * 5);
|
||||
}
|
||||
|
||||
TEST_RELEASE_RANGE_ERROR(release_beyond_range3) {
|
||||
char* p = setup_release_test_memory();
|
||||
NUMASwitcher b(false);
|
||||
os::release_memory(p - M, M * 6);
|
||||
}
|
||||
|
||||
TEST_RELEASE_RANGE_ERROR(release_already_released) {
|
||||
char* p = setup_release_test_memory();
|
||||
os::release_memory(p, 4 * M); // Release for real
|
||||
os::release_memory(p, 4 * M); // Again, should fail
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
||||
@ -695,11 +720,11 @@ TEST_VM(os, release_one_mapping_multi_commits) {
|
||||
|
||||
ASSERT_TRUE(p2 == nullptr || p2 == border);
|
||||
|
||||
ASSERT_TRUE(os::release_memory((char*)p, total_range_len));
|
||||
os::release_memory((char*)p, total_range_len);
|
||||
PRINT_MAPPINGS("C");
|
||||
|
||||
if (p2 != nullptr) {
|
||||
ASSERT_TRUE(os::release_memory((char*)p2, stripe_len));
|
||||
os::release_memory((char*)p2, stripe_len);
|
||||
PRINT_MAPPINGS("D");
|
||||
}
|
||||
}
|
||||
@ -772,7 +797,7 @@ TEST_VM(os, find_mapping_simple) {
|
||||
if (os::win32::find_mapping(p + total_range_len, &mapping_info)) {
|
||||
ASSERT_NE(mapping_info.base, p);
|
||||
}
|
||||
ASSERT_TRUE(os::release_memory((char*)p, total_range_len));
|
||||
os::release_memory((char*)p, total_range_len);
|
||||
PRINT_MAPPINGS("B");
|
||||
ASSERT_FALSE(os::win32::find_mapping(p, &mapping_info));
|
||||
}
|
||||
@ -801,7 +826,7 @@ TEST_VM(os, find_mapping_2) {
|
||||
if (os::win32::find_mapping(p + total_range_len, &mapping_info)) {
|
||||
ASSERT_NE(mapping_info.base, p);
|
||||
}
|
||||
ASSERT_TRUE(os::release_memory((char*)p, total_range_len));
|
||||
os::release_memory((char*)p, total_range_len);
|
||||
PRINT_MAPPINGS("B");
|
||||
ASSERT_FALSE(os::win32::find_mapping(p, &mapping_info));
|
||||
}
|
||||
@ -1132,11 +1157,11 @@ TEST_VM(os, commit_memory_or_exit) {
|
||||
ASSERT_NOT_NULL(base);
|
||||
os::commit_memory_or_exit(base, size, false, "Commit failed.");
|
||||
strcpy(base, letters);
|
||||
ASSERT_TRUE(os::uncommit_memory(base, size, false));
|
||||
os::uncommit_memory(base, size, false);
|
||||
os::commit_memory_or_exit(base, size, page_sz, false, "Commit with alignment hint failed.");
|
||||
strcpy(base, letters);
|
||||
ASSERT_TRUE(os::uncommit_memory(base, size, false));
|
||||
EXPECT_TRUE(os::release_memory(base, size));
|
||||
os::uncommit_memory(base, size, false);
|
||||
os::release_memory(base, size);
|
||||
}
|
||||
|
||||
#if !defined(_AIX)
|
||||
@ -1152,7 +1177,7 @@ TEST_VM(os, map_memory_to_file) {
|
||||
char* result = os::map_memory_to_file(size, fd, mtTest);
|
||||
ASSERT_NOT_NULL(result);
|
||||
EXPECT_EQ(strcmp(letters, result), 0);
|
||||
EXPECT_TRUE(os::unmap_memory(result, size));
|
||||
os::unmap_memory(result, size);
|
||||
::close(fd);
|
||||
}
|
||||
|
||||
@ -1169,7 +1194,7 @@ TEST_VM(os, map_unmap_memory) {
|
||||
char* result = os::map_memory(fd, path, 0, nullptr, size, mtTest, true, false);
|
||||
ASSERT_NOT_NULL(result);
|
||||
EXPECT_EQ(strcmp(letters, result), 0);
|
||||
EXPECT_TRUE(os::unmap_memory(result, size));
|
||||
os::unmap_memory(result, size);
|
||||
::close(fd);
|
||||
}
|
||||
|
||||
@ -1184,7 +1209,7 @@ TEST_VM(os, map_memory_to_file_aligned) {
|
||||
char* result = os::map_memory_to_file_aligned(os::vm_allocation_granularity(), os::vm_allocation_granularity(), fd, mtTest);
|
||||
ASSERT_NOT_NULL(result);
|
||||
EXPECT_EQ(strcmp(letters, result), 0);
|
||||
EXPECT_TRUE(os::unmap_memory(result, os::vm_allocation_granularity()));
|
||||
os::unmap_memory(result, os::vm_allocation_granularity());
|
||||
::close(fd);
|
||||
}
|
||||
|
||||
|
||||
@ -379,8 +379,8 @@ TEST_VM(os_linux, pretouch_thp_and_use_concurrent) {
|
||||
for (int i = 0; i < 1000; i++)
|
||||
EXPECT_EQ(*iptr++, i);
|
||||
|
||||
EXPECT_TRUE(os::uncommit_memory(heap, size, false));
|
||||
EXPECT_TRUE(os::release_memory(heap, size));
|
||||
os::uncommit_memory(heap, size, false);
|
||||
os::release_memory(heap, size);
|
||||
UseTransparentHugePages = useThp;
|
||||
}
|
||||
|
||||
|
||||
@ -157,7 +157,7 @@ public class TestMemoryAllocationLogging {
|
||||
expectedLogs = new String[] {
|
||||
/* Debug level log */
|
||||
String.format("Reserved \\[0x.* - 0x.*\\), \\(%d bytes\\)", PAGE_SIZE),
|
||||
"Failed to uncommit \\[0x.* - 0x.*\\), \\(.* bytes\\)",
|
||||
"fatal error: Failed to uncommit \\[0x.* - 0x.*\\), \\(.* bytes\\).*",
|
||||
/* Trace level log */
|
||||
"mmap failed: \\[0x.* - 0x.*\\), \\(.* bytes\\) errno=\\(Invalid argument\\)"
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user