8054368: nsk/jdi/VirtualMachine/exit/exit002 crash with detail tracking on (NMT2)
authorzgu
Thu, 14 Aug 2014 09:02:51 -0400
changeset 26136 254c226e4402
parent 25949 34557722059b
child 26137 e624be1ed1fc
8054368: nsk/jdi/VirtualMachine/exit/exit002 crash with detail tracking on (NMT2) Summary: Dynamic allocate _reserved_regions instead of static object to avoid racing during process exit Reviewed-by: dholmes, coleenp
hotspot/src/share/vm/services/memTracker.cpp
hotspot/src/share/vm/services/virtualMemoryTracker.cpp
hotspot/src/share/vm/services/virtualMemoryTracker.hpp
--- a/hotspot/src/share/vm/services/memTracker.cpp	Mon Aug 11 10:18:09 2014 -0700
+++ b/hotspot/src/share/vm/services/memTracker.cpp	Thu Aug 14 09:02:51 2014 -0400
@@ -77,7 +77,12 @@
 }
 
 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");
     // Already OOM. It is unlikely, but still have to handle it.
     if (_query_lock == NULL) {
--- a/hotspot/src/share/vm/services/virtualMemoryTracker.cpp	Mon Aug 11 10:18:09 2014 -0700
+++ b/hotspot/src/share/vm/services/virtualMemoryTracker.cpp	Thu Aug 14 09:02:51 2014 -0400
@@ -34,7 +34,7 @@
   ::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) {
   return r1.compare(r2);
@@ -283,17 +283,26 @@
   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,
    const NativeCallStack& stack, MEMFLAGS flag, bool all_committed) {
   assert(base_addr != NULL, "Invalid address");
   assert(size > 0, "Invalid size");
-
+  assert(_reserved_regions != NULL, "Sanity check");
   ReservedMemoryRegion  rgn(base_addr, size, stack, flag);
-  ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn);
+  ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn);
   LinkedListNode<ReservedMemoryRegion>* node;
   if (reserved_rgn == NULL) {
     VirtualMemorySummary::record_reserved_memory(size, flag);
-    node = _reserved_regions.add(rgn);
+    node = _reserved_regions->add(rgn);
     if (node != NULL) {
       node->data()->set_all_committed(all_committed);
       return true;
@@ -338,9 +347,10 @@
 
 void VirtualMemoryTracker::set_reserved_region_type(address addr, MEMFLAGS flag) {
   assert(addr != NULL, "Invalid address");
+  assert(_reserved_regions != NULL, "Sanity check");
 
   ReservedMemoryRegion   rgn(addr, 1);
-  ReservedMemoryRegion*  reserved_rgn = _reserved_regions.find(rgn);
+  ReservedMemoryRegion*  reserved_rgn = _reserved_regions->find(rgn);
   if (reserved_rgn != NULL) {
     assert(reserved_rgn->contain_address(addr), "Containment");
     if (reserved_rgn->flag() != flag) {
@@ -354,8 +364,10 @@
   const NativeCallStack& stack) {
   assert(addr != NULL, "Invalid address");
   assert(size > 0, "Invalid size");
+  assert(_reserved_regions != NULL, "Sanity check");
+
   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->contain_region(addr, size), "Not completely contained");
@@ -365,8 +377,10 @@
 bool VirtualMemoryTracker::remove_uncommitted_region(address addr, size_t size) {
   assert(addr != NULL, "Invalid address");
   assert(size > 0, "Invalid size");
+  assert(_reserved_regions != NULL, "Sanity check");
+
   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->contain_region(addr, size), "Not completely contained");
   return reserved_rgn->remove_uncommitted_region(addr, size);
@@ -375,9 +389,10 @@
 bool VirtualMemoryTracker::remove_released_region(address addr, size_t size) {
   assert(addr != NULL, "Invalid address");
   assert(size > 0, "Invalid size");
+  assert(_reserved_regions != NULL, "Sanity check");
 
   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");
 
@@ -390,7 +405,7 @@
   VirtualMemorySummary::record_released_memory(size, reserved_rgn->flag());
 
   if (reserved_rgn->same_region(addr, size)) {
-    return _reserved_regions.remove(rgn);
+    return _reserved_regions->remove(rgn);
   } else {
     assert(reserved_rgn->contain_region(addr, size), "Not completely contained");
     if (reserved_rgn->base() == addr ||
@@ -405,7 +420,7 @@
 
       // use original region for lower region
       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) {
         return false;
       } else {
@@ -418,8 +433,9 @@
 
 
 bool VirtualMemoryTracker::walk_virtual_memory(VirtualMemoryWalker* walker) {
+  assert(_reserved_regions != NULL, "Sanity check");
   ThreadCritical tc;
-  LinkedListNode<ReservedMemoryRegion>* head = _reserved_regions.head();
+  LinkedListNode<ReservedMemoryRegion>* head = _reserved_regions->head();
   while (head != NULL) {
     const ReservedMemoryRegion* rgn = head->peek();
     if (!walker->do_allocation_site(rgn)) {
@@ -439,7 +455,10 @@
     assert(from == NMT_summary || from == NMT_detail, "Just check");
     // Clean up virtual memory tracking data structures.
     ThreadCritical tc;
-    _reserved_regions.clear();
+    if (_reserved_regions != NULL) {
+      delete _reserved_regions;
+      _reserved_regions = NULL;
+    }
   }
 
   return true;
--- a/hotspot/src/share/vm/services/virtualMemoryTracker.hpp	Mon Aug 11 10:18:09 2014 -0700
+++ b/hotspot/src/share/vm/services/virtualMemoryTracker.hpp	Thu Aug 14 09:02:51 2014 -0400
@@ -414,6 +414,9 @@
  public:
   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,
     MEMFLAGS flag = mtNone, bool all_committed = false);
 
@@ -428,7 +431,7 @@
   static bool transition(NMT_TrackingLevel from, NMT_TrackingLevel to);
 
  private:
-  static SortedLinkedList<ReservedMemoryRegion, compare_reserved_region_base> _reserved_regions;
+  static SortedLinkedList<ReservedMemoryRegion, compare_reserved_region_base>* _reserved_regions;
 };