Wed, 24 Apr 2013 14:55:04 -0400
8011218: Kitchensink hanged, likely NMT is to blame
Summary: Made NMT query safepoint aware.
Reviewed-by: dholmes, coleenp
1.1 --- a/src/share/vm/services/memBaseline.cpp Wed Apr 24 09:00:04 2013 -0400 1.2 +++ b/src/share/vm/services/memBaseline.cpp Wed Apr 24 14:55:04 2013 -0400 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -23,9 +23,12 @@ 1.11 */ 1.12 #include "precompiled.hpp" 1.13 #include "memory/allocation.hpp" 1.14 +#include "runtime/safepoint.hpp" 1.15 +#include "runtime/thread.inline.hpp" 1.16 #include "services/memBaseline.hpp" 1.17 #include "services/memTracker.hpp" 1.18 1.19 + 1.20 MemType2Name MemBaseline::MemType2NameMap[NUMBER_OF_MEMORY_TYPE] = { 1.21 {mtJavaHeap, "Java Heap"}, 1.22 {mtClass, "Class"}, 1.23 @@ -149,6 +152,14 @@ 1.24 return true; 1.25 } 1.26 1.27 +// check if there is a safepoint in progress, if so, block the thread 1.28 +// for the safepoint 1.29 +void MemBaseline::check_safepoint(JavaThread* thr) { 1.30 + if (SafepointSynchronize::is_synchronizing()) { 1.31 + SafepointSynchronize::block(thr); 1.32 + } 1.33 +} 1.34 + 1.35 // baseline mmap'd memory records, generate overall summary and summaries by 1.36 // memory types 1.37 bool MemBaseline::baseline_vm_summary(const MemPointerArray* vm_records) { 1.38 @@ -306,7 +317,7 @@ 1.39 committed_rec->pc() != vm_ptr->pc()) { 1.40 if (!_vm_map->append(vm_ptr)) { 1.41 return false; 1.42 - } 1.43 + } 1.44 committed_rec = (VMMemRegionEx*)_vm_map->at(_vm_map->length() - 1); 1.45 } else { 1.46 committed_rec->expand_region(vm_ptr->addr(), vm_ptr->size()); 1.47 @@ -344,16 +355,27 @@ 1.48 1.49 // baseline a snapshot. If summary_only = false, memory usages aggregated by 1.50 // callsites are also baselined. 1.51 +// The method call can be lengthy, especially when detail tracking info is 1.52 +// requested. So the method checks for safepoint explicitly. 1.53 bool MemBaseline::baseline(MemSnapshot& snapshot, bool summary_only) { 1.54 - MutexLockerEx snapshot_locker(snapshot._lock, true); 1.55 + Thread* THREAD = Thread::current(); 1.56 + assert(THREAD->is_Java_thread(), "must be a JavaThread"); 1.57 + MutexLocker snapshot_locker(snapshot._lock); 1.58 reset(); 1.59 - _baselined = baseline_malloc_summary(snapshot._alloc_ptrs) && 1.60 - baseline_vm_summary(snapshot._vm_ptrs); 1.61 + _baselined = baseline_malloc_summary(snapshot._alloc_ptrs); 1.62 + if (_baselined) { 1.63 + check_safepoint((JavaThread*)THREAD); 1.64 + _baselined = baseline_vm_summary(snapshot._vm_ptrs); 1.65 + } 1.66 _number_of_classes = snapshot.number_of_classes(); 1.67 1.68 if (!summary_only && MemTracker::track_callsite() && _baselined) { 1.69 - _baselined = baseline_malloc_details(snapshot._alloc_ptrs) && 1.70 - baseline_vm_details(snapshot._vm_ptrs); 1.71 + check_safepoint((JavaThread*)THREAD); 1.72 + _baselined = baseline_malloc_details(snapshot._alloc_ptrs); 1.73 + if (_baselined) { 1.74 + check_safepoint((JavaThread*)THREAD); 1.75 + _baselined = baseline_vm_details(snapshot._vm_ptrs); 1.76 + } 1.77 } 1.78 return _baselined; 1.79 }
2.1 --- a/src/share/vm/services/memBaseline.hpp Wed Apr 24 09:00:04 2013 -0400 2.2 +++ b/src/share/vm/services/memBaseline.hpp Wed Apr 24 14:55:04 2013 -0400 2.3 @@ -1,5 +1,5 @@ 2.4 /* 2.5 - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 2.6 + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. 2.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.8 * 2.9 * This code is free software; you can redistribute it and/or modify it 2.10 @@ -330,6 +330,9 @@ 2.11 // should not use copy constructor 2.12 MemBaseline(MemBaseline& copy) { ShouldNotReachHere(); } 2.13 2.14 + // check and block at a safepoint 2.15 + static inline void check_safepoint(JavaThread* thr); 2.16 + 2.17 public: 2.18 // create a memory baseline 2.19 MemBaseline();
3.1 --- a/src/share/vm/services/memTracker.cpp Wed Apr 24 09:00:04 2013 -0400 3.2 +++ b/src/share/vm/services/memTracker.cpp Wed Apr 24 14:55:04 2013 -0400 3.3 @@ -573,7 +573,7 @@ 3.4 3.5 // baseline current memory snapshot 3.6 bool MemTracker::baseline() { 3.7 - MutexLockerEx lock(_query_lock, true); 3.8 + MutexLocker lock(_query_lock); 3.9 MemSnapshot* snapshot = get_snapshot(); 3.10 if (snapshot != NULL) { 3.11 return _baseline.baseline(*snapshot, false); 3.12 @@ -584,7 +584,7 @@ 3.13 // print memory usage from current snapshot 3.14 bool MemTracker::print_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) { 3.15 MemBaseline baseline; 3.16 - MutexLockerEx lock(_query_lock, true); 3.17 + MutexLocker lock(_query_lock); 3.18 MemSnapshot* snapshot = get_snapshot(); 3.19 if (snapshot != NULL && baseline.baseline(*snapshot, summary_only)) { 3.20 BaselineReporter reporter(out, unit); 3.21 @@ -597,7 +597,7 @@ 3.22 // Whitebox API for blocking until the current generation of NMT data has been merged 3.23 bool MemTracker::wbtest_wait_for_data_merge() { 3.24 // NMT can't be shutdown while we're holding _query_lock 3.25 - MutexLockerEx lock(_query_lock, true); 3.26 + MutexLocker lock(_query_lock); 3.27 assert(_worker_thread != NULL, "Invalid query"); 3.28 // the generation at query time, so NMT will spin till this generation is processed 3.29 unsigned long generation_at_query_time = SequenceGenerator::current_generation(); 3.30 @@ -641,7 +641,7 @@ 3.31 3.32 // compare memory usage between current snapshot and baseline 3.33 bool MemTracker::compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) { 3.34 - MutexLockerEx lock(_query_lock, true); 3.35 + MutexLocker lock(_query_lock); 3.36 if (_baseline.baselined()) { 3.37 MemBaseline baseline; 3.38 MemSnapshot* snapshot = get_snapshot();