mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 11:34:38 +02:00
8054368: nsk/jdi/VirtualMachine/exit/exit002 crash with detail tracking on (NMT2)
Dynamic allocate _reserved_regions instead of static object to avoid racing during process exit Reviewed-by: dholmes, coleenp
This commit is contained in:
parent
8a690a1250
commit
06a502d4a6
3 changed files with 41 additions and 14 deletions
|
@ -77,7 +77,12 @@ NMT_TrackingLevel MemTracker::init_tracking_level() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemTracker::init() {
|
void MemTracker::init() {
|
||||||
if (tracking_level() >= NMT_summary) {
|
NMT_TrackingLevel level = tracking_level();
|
||||||
|
if (level >= NMT_summary) {
|
||||||
|
if (!VirtualMemoryTracker::late_initialize(level)) {
|
||||||
|
shutdown();
|
||||||
|
return;
|
||||||
|
}
|
||||||
_query_lock = new (std::nothrow) Mutex(Monitor::max_nonleaf, "NMT_queryLock");
|
_query_lock = new (std::nothrow) Mutex(Monitor::max_nonleaf, "NMT_queryLock");
|
||||||
// Already OOM. It is unlikely, but still have to handle it.
|
// Already OOM. It is unlikely, but still have to handle it.
|
||||||
if (_query_lock == NULL) {
|
if (_query_lock == NULL) {
|
||||||
|
|
|
@ -34,7 +34,7 @@ void VirtualMemorySummary::initialize() {
|
||||||
::new ((void*)_snapshot) VirtualMemorySnapshot();
|
::new ((void*)_snapshot) VirtualMemorySnapshot();
|
||||||
}
|
}
|
||||||
|
|
||||||
SortedLinkedList<ReservedMemoryRegion, compare_reserved_region_base> VirtualMemoryTracker::_reserved_regions;
|
SortedLinkedList<ReservedMemoryRegion, compare_reserved_region_base>* VirtualMemoryTracker::_reserved_regions;
|
||||||
|
|
||||||
int compare_committed_region(const CommittedMemoryRegion& r1, const CommittedMemoryRegion& r2) {
|
int compare_committed_region(const CommittedMemoryRegion& r1, const CommittedMemoryRegion& r2) {
|
||||||
return r1.compare(r2);
|
return r1.compare(r2);
|
||||||
|
@ -283,17 +283,26 @@ bool VirtualMemoryTracker::initialize(NMT_TrackingLevel level) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VirtualMemoryTracker::late_initialize(NMT_TrackingLevel level) {
|
||||||
|
if (level >= NMT_summary) {
|
||||||
|
_reserved_regions = new (std::nothrow, ResourceObj::C_HEAP, mtNMT)
|
||||||
|
SortedLinkedList<ReservedMemoryRegion, compare_reserved_region_base>();
|
||||||
|
return (_reserved_regions != NULL);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool VirtualMemoryTracker::add_reserved_region(address base_addr, size_t size,
|
bool VirtualMemoryTracker::add_reserved_region(address base_addr, size_t size,
|
||||||
const NativeCallStack& stack, MEMFLAGS flag, bool all_committed) {
|
const NativeCallStack& stack, MEMFLAGS flag, bool all_committed) {
|
||||||
assert(base_addr != NULL, "Invalid address");
|
assert(base_addr != NULL, "Invalid address");
|
||||||
assert(size > 0, "Invalid size");
|
assert(size > 0, "Invalid size");
|
||||||
|
assert(_reserved_regions != NULL, "Sanity check");
|
||||||
ReservedMemoryRegion rgn(base_addr, size, stack, flag);
|
ReservedMemoryRegion rgn(base_addr, size, stack, flag);
|
||||||
ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn);
|
ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn);
|
||||||
LinkedListNode<ReservedMemoryRegion>* node;
|
LinkedListNode<ReservedMemoryRegion>* node;
|
||||||
if (reserved_rgn == NULL) {
|
if (reserved_rgn == NULL) {
|
||||||
VirtualMemorySummary::record_reserved_memory(size, flag);
|
VirtualMemorySummary::record_reserved_memory(size, flag);
|
||||||
node = _reserved_regions.add(rgn);
|
node = _reserved_regions->add(rgn);
|
||||||
if (node != NULL) {
|
if (node != NULL) {
|
||||||
node->data()->set_all_committed(all_committed);
|
node->data()->set_all_committed(all_committed);
|
||||||
return true;
|
return true;
|
||||||
|
@ -338,9 +347,10 @@ bool VirtualMemoryTracker::add_reserved_region(address base_addr, size_t size,
|
||||||
|
|
||||||
void VirtualMemoryTracker::set_reserved_region_type(address addr, MEMFLAGS flag) {
|
void VirtualMemoryTracker::set_reserved_region_type(address addr, MEMFLAGS flag) {
|
||||||
assert(addr != NULL, "Invalid address");
|
assert(addr != NULL, "Invalid address");
|
||||||
|
assert(_reserved_regions != NULL, "Sanity check");
|
||||||
|
|
||||||
ReservedMemoryRegion rgn(addr, 1);
|
ReservedMemoryRegion rgn(addr, 1);
|
||||||
ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn);
|
ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn);
|
||||||
if (reserved_rgn != NULL) {
|
if (reserved_rgn != NULL) {
|
||||||
assert(reserved_rgn->contain_address(addr), "Containment");
|
assert(reserved_rgn->contain_address(addr), "Containment");
|
||||||
if (reserved_rgn->flag() != flag) {
|
if (reserved_rgn->flag() != flag) {
|
||||||
|
@ -354,8 +364,10 @@ bool VirtualMemoryTracker::add_committed_region(address addr, size_t size,
|
||||||
const NativeCallStack& stack) {
|
const NativeCallStack& stack) {
|
||||||
assert(addr != NULL, "Invalid address");
|
assert(addr != NULL, "Invalid address");
|
||||||
assert(size > 0, "Invalid size");
|
assert(size > 0, "Invalid size");
|
||||||
|
assert(_reserved_regions != NULL, "Sanity check");
|
||||||
|
|
||||||
ReservedMemoryRegion rgn(addr, size);
|
ReservedMemoryRegion rgn(addr, size);
|
||||||
ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn);
|
ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn);
|
||||||
|
|
||||||
assert(reserved_rgn != NULL, "No reserved region");
|
assert(reserved_rgn != NULL, "No reserved region");
|
||||||
assert(reserved_rgn->contain_region(addr, size), "Not completely contained");
|
assert(reserved_rgn->contain_region(addr, size), "Not completely contained");
|
||||||
|
@ -365,8 +377,10 @@ bool VirtualMemoryTracker::add_committed_region(address addr, size_t size,
|
||||||
bool VirtualMemoryTracker::remove_uncommitted_region(address addr, size_t size) {
|
bool VirtualMemoryTracker::remove_uncommitted_region(address addr, size_t size) {
|
||||||
assert(addr != NULL, "Invalid address");
|
assert(addr != NULL, "Invalid address");
|
||||||
assert(size > 0, "Invalid size");
|
assert(size > 0, "Invalid size");
|
||||||
|
assert(_reserved_regions != NULL, "Sanity check");
|
||||||
|
|
||||||
ReservedMemoryRegion rgn(addr, size);
|
ReservedMemoryRegion rgn(addr, size);
|
||||||
ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn);
|
ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn);
|
||||||
assert(reserved_rgn != NULL, "No reserved region");
|
assert(reserved_rgn != NULL, "No reserved region");
|
||||||
assert(reserved_rgn->contain_region(addr, size), "Not completely contained");
|
assert(reserved_rgn->contain_region(addr, size), "Not completely contained");
|
||||||
return reserved_rgn->remove_uncommitted_region(addr, size);
|
return reserved_rgn->remove_uncommitted_region(addr, size);
|
||||||
|
@ -375,9 +389,10 @@ bool VirtualMemoryTracker::remove_uncommitted_region(address addr, size_t size)
|
||||||
bool VirtualMemoryTracker::remove_released_region(address addr, size_t size) {
|
bool VirtualMemoryTracker::remove_released_region(address addr, size_t size) {
|
||||||
assert(addr != NULL, "Invalid address");
|
assert(addr != NULL, "Invalid address");
|
||||||
assert(size > 0, "Invalid size");
|
assert(size > 0, "Invalid size");
|
||||||
|
assert(_reserved_regions != NULL, "Sanity check");
|
||||||
|
|
||||||
ReservedMemoryRegion rgn(addr, size);
|
ReservedMemoryRegion rgn(addr, size);
|
||||||
ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn);
|
ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn);
|
||||||
|
|
||||||
assert(reserved_rgn != NULL, "No reserved region");
|
assert(reserved_rgn != NULL, "No reserved region");
|
||||||
|
|
||||||
|
@ -390,7 +405,7 @@ bool VirtualMemoryTracker::remove_released_region(address addr, size_t size) {
|
||||||
VirtualMemorySummary::record_released_memory(size, reserved_rgn->flag());
|
VirtualMemorySummary::record_released_memory(size, reserved_rgn->flag());
|
||||||
|
|
||||||
if (reserved_rgn->same_region(addr, size)) {
|
if (reserved_rgn->same_region(addr, size)) {
|
||||||
return _reserved_regions.remove(rgn);
|
return _reserved_regions->remove(rgn);
|
||||||
} else {
|
} else {
|
||||||
assert(reserved_rgn->contain_region(addr, size), "Not completely contained");
|
assert(reserved_rgn->contain_region(addr, size), "Not completely contained");
|
||||||
if (reserved_rgn->base() == addr ||
|
if (reserved_rgn->base() == addr ||
|
||||||
|
@ -405,7 +420,7 @@ bool VirtualMemoryTracker::remove_released_region(address addr, size_t size) {
|
||||||
|
|
||||||
// use original region for lower region
|
// use original region for lower region
|
||||||
reserved_rgn->exclude_region(addr, top - addr);
|
reserved_rgn->exclude_region(addr, top - addr);
|
||||||
LinkedListNode<ReservedMemoryRegion>* new_rgn = _reserved_regions.add(high_rgn);
|
LinkedListNode<ReservedMemoryRegion>* new_rgn = _reserved_regions->add(high_rgn);
|
||||||
if (new_rgn == NULL) {
|
if (new_rgn == NULL) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -418,8 +433,9 @@ bool VirtualMemoryTracker::remove_released_region(address addr, size_t size) {
|
||||||
|
|
||||||
|
|
||||||
bool VirtualMemoryTracker::walk_virtual_memory(VirtualMemoryWalker* walker) {
|
bool VirtualMemoryTracker::walk_virtual_memory(VirtualMemoryWalker* walker) {
|
||||||
|
assert(_reserved_regions != NULL, "Sanity check");
|
||||||
ThreadCritical tc;
|
ThreadCritical tc;
|
||||||
LinkedListNode<ReservedMemoryRegion>* head = _reserved_regions.head();
|
LinkedListNode<ReservedMemoryRegion>* head = _reserved_regions->head();
|
||||||
while (head != NULL) {
|
while (head != NULL) {
|
||||||
const ReservedMemoryRegion* rgn = head->peek();
|
const ReservedMemoryRegion* rgn = head->peek();
|
||||||
if (!walker->do_allocation_site(rgn)) {
|
if (!walker->do_allocation_site(rgn)) {
|
||||||
|
@ -439,7 +455,10 @@ bool VirtualMemoryTracker::transition(NMT_TrackingLevel from, NMT_TrackingLevel
|
||||||
assert(from == NMT_summary || from == NMT_detail, "Just check");
|
assert(from == NMT_summary || from == NMT_detail, "Just check");
|
||||||
// Clean up virtual memory tracking data structures.
|
// Clean up virtual memory tracking data structures.
|
||||||
ThreadCritical tc;
|
ThreadCritical tc;
|
||||||
_reserved_regions.clear();
|
if (_reserved_regions != NULL) {
|
||||||
|
delete _reserved_regions;
|
||||||
|
_reserved_regions = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -414,6 +414,9 @@ class VirtualMemoryTracker : AllStatic {
|
||||||
public:
|
public:
|
||||||
static bool initialize(NMT_TrackingLevel level);
|
static bool initialize(NMT_TrackingLevel level);
|
||||||
|
|
||||||
|
// Late phase initialization
|
||||||
|
static bool late_initialize(NMT_TrackingLevel level);
|
||||||
|
|
||||||
static bool add_reserved_region (address base_addr, size_t size, const NativeCallStack& stack,
|
static bool add_reserved_region (address base_addr, size_t size, const NativeCallStack& stack,
|
||||||
MEMFLAGS flag = mtNone, bool all_committed = false);
|
MEMFLAGS flag = mtNone, bool all_committed = false);
|
||||||
|
|
||||||
|
@ -428,7 +431,7 @@ class VirtualMemoryTracker : AllStatic {
|
||||||
static bool transition(NMT_TrackingLevel from, NMT_TrackingLevel to);
|
static bool transition(NMT_TrackingLevel from, NMT_TrackingLevel to);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static SortedLinkedList<ReservedMemoryRegion, compare_reserved_region_base> _reserved_regions;
|
static SortedLinkedList<ReservedMemoryRegion, compare_reserved_region_base>* _reserved_regions;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue