7182543: NMT ON: Aggregate a few NMT related bugs

Thu, 19 Jul 2012 09:05:42 -0400

author
zgu
date
Thu, 19 Jul 2012 09:05:42 -0400
changeset 3935
7e5976e66c62
parent 3904
ace99a6ffc83
child 3937
d5bc62fcfac7

7182543: NMT ON: Aggregate a few NMT related bugs
Summary: 1) Fixed MemTrackWorker::generations_in_used() calculation 2) Ensured NMT not to leak memory recorders after shutdown 3) Used ThreadCritical to block safepoint safe threads
Reviewed-by: acorn, coleenp, dholmes, kvn

src/share/vm/services/memRecorder.cpp file | annotate | diff | comparison | revisions
src/share/vm/services/memRecorder.hpp file | annotate | diff | comparison | revisions
src/share/vm/services/memTrackWorker.hpp file | annotate | diff | comparison | revisions
src/share/vm/services/memTracker.cpp file | annotate | diff | comparison | revisions
src/share/vm/services/memTracker.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/services/memRecorder.cpp	Wed Jul 04 15:55:45 2012 -0400
     1.2 +++ b/src/share/vm/services/memRecorder.cpp	Thu Jul 19 09:05:42 2012 -0400
     1.3 @@ -45,11 +45,11 @@
     1.4  }
     1.5  
     1.6  
     1.7 -debug_only(volatile jint MemRecorder::_instance_count = 0;)
     1.8 +volatile jint MemRecorder::_instance_count = 0;
     1.9  
    1.10  MemRecorder::MemRecorder() {
    1.11    assert(MemTracker::is_on(), "Native memory tracking is off");
    1.12 -  debug_only(Atomic::inc(&_instance_count);)
    1.13 +  Atomic::inc(&_instance_count);
    1.14    debug_only(set_generation();)
    1.15  
    1.16    if (MemTracker::track_callsite()) {
    1.17 @@ -83,9 +83,7 @@
    1.18      delete _next;
    1.19    }
    1.20  
    1.21 -#ifdef ASSERT
    1.22    Atomic::dec(&_instance_count);
    1.23 -#endif
    1.24  }
    1.25  
    1.26  // Sorting order:
     2.1 --- a/src/share/vm/services/memRecorder.hpp	Wed Jul 04 15:55:45 2012 -0400
     2.2 +++ b/src/share/vm/services/memRecorder.hpp	Thu Jul 19 09:05:42 2012 -0400
     2.3 @@ -249,9 +249,9 @@
     2.4  
     2.5    SequencedRecordIterator pointer_itr();
     2.6  
     2.7 - public:
     2.8 + protected:
     2.9    // number of MemRecorder instance
    2.10 -  debug_only(static volatile jint _instance_count;)
    2.11 +  static volatile jint _instance_count;
    2.12  
    2.13   private:
    2.14    // sorting function, sort records into following order
     3.1 --- a/src/share/vm/services/memTrackWorker.hpp	Wed Jul 04 15:55:45 2012 -0400
     3.2 +++ b/src/share/vm/services/memTrackWorker.hpp	Thu Jul 19 09:05:42 2012 -0400
     3.3 @@ -67,7 +67,7 @@
     3.4    NOT_PRODUCT(int _last_gen_in_use;)
     3.5  
     3.6    inline int generations_in_use() const {
     3.7 -    return (_tail <= _head ? (_head - _tail + 1) : (MAX_GENERATIONS - (_tail - _head) + 1));
     3.8 +    return (_tail >= _head ? (_tail - _head + 1) : (MAX_GENERATIONS - (_head - _tail) + 1));
     3.9    }
    3.10  };
    3.11  
     4.1 --- a/src/share/vm/services/memTracker.cpp	Wed Jul 04 15:55:45 2012 -0400
     4.2 +++ b/src/share/vm/services/memTracker.cpp	Thu Jul 19 09:05:42 2012 -0400
     4.3 @@ -351,21 +351,17 @@
     4.4      }
     4.5  
     4.6      if (thread != NULL) {
     4.7 -#ifdef ASSERT
     4.8 -      // cause assertion on stack base. This ensures that threads call
     4.9 -      // Thread::record_stack_base_and_size() method, which will create
    4.10 -      // thread native stack records.
    4.11 -      thread->stack_base();
    4.12 -#endif
    4.13 -      // for a JavaThread, if it is running in native state, we need to transition it to
    4.14 -      // VM state, so it can stop at safepoint. JavaThread running in VM state does not
    4.15 -      // need lock to write records.
    4.16        if (thread->is_Java_thread() && ((JavaThread*)thread)->is_safepoint_visible()) {
    4.17 -        if (((JavaThread*)thread)->thread_state() == _thread_in_native) {
    4.18 -          ThreadInVMfromNative trans((JavaThread*)thread);
    4.19 -          create_record_in_recorder(addr, flags, size, pc, thread);
    4.20 +        JavaThread*      java_thread = static_cast<JavaThread*>(thread);
    4.21 +        JavaThreadState  state = java_thread->thread_state();
    4.22 +        if (SafepointSynchronize::safepoint_safe(java_thread, state)) {
    4.23 +          // JavaThreads that are safepoint safe, can run through safepoint,
    4.24 +          // so ThreadCritical is needed to ensure no threads at safepoint create
    4.25 +          // new records while the records are being gathered and the sequence number is changing
    4.26 +          ThreadCritical tc;
    4.27 +          create_record_in_recorder(addr, flags, size, pc, java_thread);
    4.28          } else {
    4.29 -          create_record_in_recorder(addr, flags, size, pc, thread);
    4.30 +          create_record_in_recorder(addr, flags, size, pc, java_thread);
    4.31          }
    4.32        } else {
    4.33          // other threads, such as worker and watcher threads, etc. need to
    4.34 @@ -390,10 +386,9 @@
    4.35  // write a record to proper recorder. No lock can be taken from this method
    4.36  // down.
    4.37  void MemTracker::create_record_in_recorder(address addr, MEMFLAGS flags,
    4.38 -    size_t size, address pc, Thread* thread) {
    4.39 -    assert(thread == NULL || thread->is_Java_thread(), "wrong thread");
    4.40 +    size_t size, address pc, JavaThread* thread) {
    4.41  
    4.42 -    MemRecorder* rc = get_thread_recorder((JavaThread*)thread);
    4.43 +    MemRecorder* rc = get_thread_recorder(thread);
    4.44      if (rc != NULL) {
    4.45        rc->record(addr, flags, size, pc);
    4.46      }
    4.47 @@ -460,17 +455,18 @@
    4.48        }
    4.49      }
    4.50      _sync_point_skip_count = 0;
    4.51 -    // walk all JavaThreads to collect recorders
    4.52 -    SyncThreadRecorderClosure stc;
    4.53 -    Threads::threads_do(&stc);
    4.54 -
    4.55 -    _thread_count = stc.get_thread_count();
    4.56 -    MemRecorder* pending_recorders = get_pending_recorders();
    4.57 -
    4.58      {
    4.59        // This method is running at safepoint, with ThreadCritical lock,
    4.60        // it should guarantee that NMT is fully sync-ed.
    4.61        ThreadCritical tc;
    4.62 +
    4.63 +      // walk all JavaThreads to collect recorders
    4.64 +      SyncThreadRecorderClosure stc;
    4.65 +      Threads::threads_do(&stc);
    4.66 +
    4.67 +      _thread_count = stc.get_thread_count();
    4.68 +      MemRecorder* pending_recorders = get_pending_recorders();
    4.69 +
    4.70        if (_global_recorder != NULL) {
    4.71          _global_recorder->set_next(pending_recorders);
    4.72          pending_recorders = _global_recorder;
    4.73 @@ -486,8 +482,6 @@
    4.74  
    4.75    // now, it is the time to shut whole things off
    4.76    if (_state == NMT_final_shutdown) {
    4.77 -    _tracking_level = NMT_off;
    4.78 -
    4.79      // walk all JavaThreads to delete all recorders
    4.80      SyncThreadRecorderClosure stc;
    4.81      Threads::threads_do(&stc);
    4.82 @@ -499,8 +493,16 @@
    4.83          _global_recorder = NULL;
    4.84        }
    4.85      }
    4.86 -
    4.87 -    _state = NMT_shutdown;
    4.88 +    MemRecorder* pending_recorders = get_pending_recorders();
    4.89 +    if (pending_recorders != NULL) {
    4.90 +      delete pending_recorders;
    4.91 +    }
    4.92 +    // try at a later sync point to ensure MemRecorder instance drops to zero to
    4.93 +    // completely shutdown NMT
    4.94 +    if (MemRecorder::_instance_count == 0) {
    4.95 +      _state = NMT_shutdown;
    4.96 +      _tracking_level = NMT_off;
    4.97 +    }
    4.98    }
    4.99  }
   4.100  
     5.1 --- a/src/share/vm/services/memTracker.hpp	Wed Jul 04 15:55:45 2012 -0400
     5.2 +++ b/src/share/vm/services/memTracker.hpp	Thu Jul 19 09:05:42 2012 -0400
     5.3 @@ -326,7 +326,7 @@
     5.4    static void create_memory_record(address addr, MEMFLAGS type,
     5.5                     size_t size, address pc, Thread* thread);
     5.6    static void create_record_in_recorder(address addr, MEMFLAGS type,
     5.7 -                   size_t size, address pc, Thread* thread);
     5.8 +                   size_t size, address pc, JavaThread* thread);
     5.9  
    5.10   private:
    5.11    // global memory snapshot

mercurial