# HG changeset patch # User zgu # Date 1366829704 14400 # Node ID fbca7eaeac2e8e2f167c5d83cc3a5c874bd1e605 # Parent cc70cbbd422edb11ac72523440154101c6acdd4f 8011218: Kitchensink hanged, likely NMT is to blame Summary: Made NMT query safepoint aware. Reviewed-by: dholmes, coleenp diff -r cc70cbbd422e -r fbca7eaeac2e src/share/vm/services/memBaseline.cpp --- a/src/share/vm/services/memBaseline.cpp Wed Apr 24 09:00:04 2013 -0400 +++ b/src/share/vm/services/memBaseline.cpp Wed Apr 24 14:55:04 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,9 +23,12 @@ */ #include "precompiled.hpp" #include "memory/allocation.hpp" +#include "runtime/safepoint.hpp" +#include "runtime/thread.inline.hpp" #include "services/memBaseline.hpp" #include "services/memTracker.hpp" + MemType2Name MemBaseline::MemType2NameMap[NUMBER_OF_MEMORY_TYPE] = { {mtJavaHeap, "Java Heap"}, {mtClass, "Class"}, @@ -149,6 +152,14 @@ return true; } +// check if there is a safepoint in progress, if so, block the thread +// for the safepoint +void MemBaseline::check_safepoint(JavaThread* thr) { + if (SafepointSynchronize::is_synchronizing()) { + SafepointSynchronize::block(thr); + } +} + // baseline mmap'd memory records, generate overall summary and summaries by // memory types bool MemBaseline::baseline_vm_summary(const MemPointerArray* vm_records) { @@ -306,7 +317,7 @@ committed_rec->pc() != vm_ptr->pc()) { if (!_vm_map->append(vm_ptr)) { return false; - } + } committed_rec = (VMMemRegionEx*)_vm_map->at(_vm_map->length() - 1); } else { committed_rec->expand_region(vm_ptr->addr(), vm_ptr->size()); @@ -344,16 +355,27 @@ // baseline a snapshot. If summary_only = false, memory usages aggregated by // callsites are also baselined. +// The method call can be lengthy, especially when detail tracking info is +// requested. So the method checks for safepoint explicitly. bool MemBaseline::baseline(MemSnapshot& snapshot, bool summary_only) { - MutexLockerEx snapshot_locker(snapshot._lock, true); + Thread* THREAD = Thread::current(); + assert(THREAD->is_Java_thread(), "must be a JavaThread"); + MutexLocker snapshot_locker(snapshot._lock); reset(); - _baselined = baseline_malloc_summary(snapshot._alloc_ptrs) && - baseline_vm_summary(snapshot._vm_ptrs); + _baselined = baseline_malloc_summary(snapshot._alloc_ptrs); + if (_baselined) { + check_safepoint((JavaThread*)THREAD); + _baselined = baseline_vm_summary(snapshot._vm_ptrs); + } _number_of_classes = snapshot.number_of_classes(); if (!summary_only && MemTracker::track_callsite() && _baselined) { - _baselined = baseline_malloc_details(snapshot._alloc_ptrs) && - baseline_vm_details(snapshot._vm_ptrs); + check_safepoint((JavaThread*)THREAD); + _baselined = baseline_malloc_details(snapshot._alloc_ptrs); + if (_baselined) { + check_safepoint((JavaThread*)THREAD); + _baselined = baseline_vm_details(snapshot._vm_ptrs); + } } return _baselined; } diff -r cc70cbbd422e -r fbca7eaeac2e src/share/vm/services/memBaseline.hpp --- a/src/share/vm/services/memBaseline.hpp Wed Apr 24 09:00:04 2013 -0400 +++ b/src/share/vm/services/memBaseline.hpp Wed Apr 24 14:55:04 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -330,6 +330,9 @@ // should not use copy constructor MemBaseline(MemBaseline& copy) { ShouldNotReachHere(); } + // check and block at a safepoint + static inline void check_safepoint(JavaThread* thr); + public: // create a memory baseline MemBaseline(); diff -r cc70cbbd422e -r fbca7eaeac2e src/share/vm/services/memTracker.cpp --- a/src/share/vm/services/memTracker.cpp Wed Apr 24 09:00:04 2013 -0400 +++ b/src/share/vm/services/memTracker.cpp Wed Apr 24 14:55:04 2013 -0400 @@ -573,7 +573,7 @@ // baseline current memory snapshot bool MemTracker::baseline() { - MutexLockerEx lock(_query_lock, true); + MutexLocker lock(_query_lock); MemSnapshot* snapshot = get_snapshot(); if (snapshot != NULL) { return _baseline.baseline(*snapshot, false); @@ -584,7 +584,7 @@ // print memory usage from current snapshot bool MemTracker::print_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) { MemBaseline baseline; - MutexLockerEx lock(_query_lock, true); + MutexLocker lock(_query_lock); MemSnapshot* snapshot = get_snapshot(); if (snapshot != NULL && baseline.baseline(*snapshot, summary_only)) { BaselineReporter reporter(out, unit); @@ -597,7 +597,7 @@ // Whitebox API for blocking until the current generation of NMT data has been merged bool MemTracker::wbtest_wait_for_data_merge() { // NMT can't be shutdown while we're holding _query_lock - MutexLockerEx lock(_query_lock, true); + MutexLocker lock(_query_lock); assert(_worker_thread != NULL, "Invalid query"); // the generation at query time, so NMT will spin till this generation is processed unsigned long generation_at_query_time = SequenceGenerator::current_generation(); @@ -641,7 +641,7 @@ // compare memory usage between current snapshot and baseline bool MemTracker::compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) { - MutexLockerEx lock(_query_lock, true); + MutexLocker lock(_query_lock); if (_baseline.baselined()) { MemBaseline baseline; MemSnapshot* snapshot = get_snapshot();