8011218: Kitchensink hanged, likely NMT is to blame

Wed, 24 Apr 2013 14:55:04 -0400

author
zgu
date
Wed, 24 Apr 2013 14:55:04 -0400
changeset 4980
fbca7eaeac2e
parent 4979
cc70cbbd422e
child 4982
d66a24adbe3f

8011218: Kitchensink hanged, likely NMT is to blame
Summary: Made NMT query safepoint aware.
Reviewed-by: dholmes, coleenp

src/share/vm/services/memBaseline.cpp file | annotate | diff | comparison | revisions
src/share/vm/services/memBaseline.hpp file | annotate | diff | comparison | revisions
src/share/vm/services/memTracker.cpp file | annotate | diff | comparison | revisions
     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();

mercurial