# HG changeset patch # User zgu # Date 1342703750 14400 # Node ID 58a04a45a549a359c1830154017b59cf87f9898b # Parent d5bc62fcfac757695724b27e5c5ee4dc17d9d997# Parent 04a9b3789683264847f9f4cb7a20765c53c2b3bf Merge diff -r 04a9b3789683 -r 58a04a45a549 src/share/vm/services/memRecorder.cpp --- a/src/share/vm/services/memRecorder.cpp Mon Jul 16 14:05:34 2012 -0400 +++ b/src/share/vm/services/memRecorder.cpp Thu Jul 19 09:15:50 2012 -0400 @@ -45,11 +45,11 @@ } -debug_only(volatile jint MemRecorder::_instance_count = 0;) +volatile jint MemRecorder::_instance_count = 0; MemRecorder::MemRecorder() { assert(MemTracker::is_on(), "Native memory tracking is off"); - debug_only(Atomic::inc(&_instance_count);) + Atomic::inc(&_instance_count); debug_only(set_generation();) if (MemTracker::track_callsite()) { @@ -83,9 +83,7 @@ delete _next; } -#ifdef ASSERT Atomic::dec(&_instance_count); -#endif } // Sorting order: diff -r 04a9b3789683 -r 58a04a45a549 src/share/vm/services/memRecorder.hpp --- a/src/share/vm/services/memRecorder.hpp Mon Jul 16 14:05:34 2012 -0400 +++ b/src/share/vm/services/memRecorder.hpp Thu Jul 19 09:15:50 2012 -0400 @@ -249,9 +249,9 @@ SequencedRecordIterator pointer_itr(); - public: + protected: // number of MemRecorder instance - debug_only(static volatile jint _instance_count;) + static volatile jint _instance_count; private: // sorting function, sort records into following order diff -r 04a9b3789683 -r 58a04a45a549 src/share/vm/services/memSnapshot.cpp --- a/src/share/vm/services/memSnapshot.cpp Mon Jul 16 14:05:34 2012 -0400 +++ b/src/share/vm/services/memSnapshot.cpp Thu Jul 19 09:15:50 2012 -0400 @@ -173,7 +173,7 @@ _staging_area = new (std::nothrow)MemPointerArrayImpl(); } - _lock = new (std::nothrow) Mutex(Monitor::native, "memSnapshotLock"); + _lock = new (std::nothrow) Mutex(Monitor::max_nonleaf - 1, "memSnapshotLock"); NOT_PRODUCT(_untracked_count = 0;) } diff -r 04a9b3789683 -r 58a04a45a549 src/share/vm/services/memTrackWorker.hpp --- a/src/share/vm/services/memTrackWorker.hpp Mon Jul 16 14:05:34 2012 -0400 +++ b/src/share/vm/services/memTrackWorker.hpp Thu Jul 19 09:15:50 2012 -0400 @@ -67,7 +67,7 @@ NOT_PRODUCT(int _last_gen_in_use;) inline int generations_in_use() const { - return (_tail <= _head ? (_head - _tail + 1) : (MAX_GENERATIONS - (_tail - _head) + 1)); + return (_tail >= _head ? (_tail - _head + 1) : (MAX_GENERATIONS - (_head - _tail) + 1)); } }; diff -r 04a9b3789683 -r 58a04a45a549 src/share/vm/services/memTracker.cpp --- a/src/share/vm/services/memTracker.cpp Mon Jul 16 14:05:34 2012 -0400 +++ b/src/share/vm/services/memTracker.cpp Thu Jul 19 09:15:50 2012 -0400 @@ -54,7 +54,7 @@ MemRecorder* MemTracker::_global_recorder = NULL; MemSnapshot* MemTracker::_snapshot = NULL; MemBaseline MemTracker::_baseline; -Mutex MemTracker::_query_lock(Monitor::native, "NMT_queryLock"); +Mutex* MemTracker::_query_lock = NULL; volatile MemRecorder* MemTracker::_merge_pending_queue = NULL; volatile MemRecorder* MemTracker::_pooled_recorders = NULL; MemTrackWorker* MemTracker::_worker_thread = NULL; @@ -89,6 +89,12 @@ return; } + _query_lock = new (std::nothrow) Mutex(Monitor::max_nonleaf, "NMT_queryLock"); + if (_query_lock == NULL) { + shutdown(NMT_out_of_memory); + return; + } + debug_only(_main_thread_tid = os::current_thread_id();) _state = NMT_bootstrapping_single_thread; NMT_track_callsite = (_tracking_level == NMT_detail && can_walk_stack()); @@ -164,7 +170,7 @@ { // shared baseline and snapshot are the only objects needed to // create query results - MutexLockerEx locker(&_query_lock, true); + MutexLockerEx locker(_query_lock, true); // cleanup baseline data and snapshot _baseline.clear(); delete _snapshot; @@ -351,15 +357,17 @@ } if (thread != NULL) { - // for a JavaThread, if it is running in native state, we need to transition it to - // VM state, so it can stop at safepoint. JavaThread running in VM state does not - // need lock to write records. if (thread->is_Java_thread() && ((JavaThread*)thread)->is_safepoint_visible()) { - if (((JavaThread*)thread)->thread_state() == _thread_in_native) { - ThreadInVMfromNative trans((JavaThread*)thread); - create_record_in_recorder(addr, flags, size, pc, thread); + JavaThread* java_thread = static_cast(thread); + JavaThreadState state = java_thread->thread_state(); + if (SafepointSynchronize::safepoint_safe(java_thread, state)) { + // JavaThreads that are safepoint safe, can run through safepoint, + // so ThreadCritical is needed to ensure no threads at safepoint create + // new records while the records are being gathered and the sequence number is changing + ThreadCritical tc; + create_record_in_recorder(addr, flags, size, pc, java_thread); } else { - create_record_in_recorder(addr, flags, size, pc, thread); + create_record_in_recorder(addr, flags, size, pc, java_thread); } } else { // other threads, such as worker and watcher threads, etc. need to @@ -384,10 +392,9 @@ // write a record to proper recorder. No lock can be taken from this method // down. void MemTracker::create_record_in_recorder(address addr, MEMFLAGS flags, - size_t size, address pc, Thread* thread) { - assert(thread == NULL || thread->is_Java_thread(), "wrong thread"); + size_t size, address pc, JavaThread* thread) { - MemRecorder* rc = get_thread_recorder((JavaThread*)thread); + MemRecorder* rc = get_thread_recorder(thread); if (rc != NULL) { rc->record(addr, flags, size, pc); } @@ -454,17 +461,18 @@ } } _sync_point_skip_count = 0; - // walk all JavaThreads to collect recorders - SyncThreadRecorderClosure stc; - Threads::threads_do(&stc); - - _thread_count = stc.get_thread_count(); - MemRecorder* pending_recorders = get_pending_recorders(); - { // This method is running at safepoint, with ThreadCritical lock, // it should guarantee that NMT is fully sync-ed. ThreadCritical tc; + + // walk all JavaThreads to collect recorders + SyncThreadRecorderClosure stc; + Threads::threads_do(&stc); + + _thread_count = stc.get_thread_count(); + MemRecorder* pending_recorders = get_pending_recorders(); + if (_global_recorder != NULL) { _global_recorder->set_next(pending_recorders); pending_recorders = _global_recorder; @@ -480,8 +488,6 @@ // now, it is the time to shut whole things off if (_state == NMT_final_shutdown) { - _tracking_level = NMT_off; - // walk all JavaThreads to delete all recorders SyncThreadRecorderClosure stc; Threads::threads_do(&stc); @@ -493,8 +499,16 @@ _global_recorder = NULL; } } - - _state = NMT_shutdown; + MemRecorder* pending_recorders = get_pending_recorders(); + if (pending_recorders != NULL) { + delete pending_recorders; + } + // try at a later sync point to ensure MemRecorder instance drops to zero to + // completely shutdown NMT + if (MemRecorder::_instance_count == 0) { + _state = NMT_shutdown; + _tracking_level = NMT_off; + } } } @@ -528,7 +542,7 @@ // baseline current memory snapshot bool MemTracker::baseline() { - MutexLockerEx lock(&_query_lock, true); + MutexLockerEx lock(_query_lock, true); MemSnapshot* snapshot = get_snapshot(); if (snapshot != NULL) { return _baseline.baseline(*snapshot, false); @@ -539,7 +553,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); + MutexLockerEx lock(_query_lock, true); MemSnapshot* snapshot = get_snapshot(); if (snapshot != NULL && baseline.baseline(*snapshot, summary_only)) { BaselineReporter reporter(out, unit); @@ -551,7 +565,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); + MutexLockerEx lock(_query_lock, true); if (_baseline.baselined()) { MemBaseline baseline; MemSnapshot* snapshot = get_snapshot(); diff -r 04a9b3789683 -r 58a04a45a549 src/share/vm/services/memTracker.hpp --- a/src/share/vm/services/memTracker.hpp Mon Jul 16 14:05:34 2012 -0400 +++ b/src/share/vm/services/memTracker.hpp Thu Jul 19 09:15:50 2012 -0400 @@ -126,6 +126,8 @@ return "Native memory tracking has been shutdown by user"; case NMT_normal: return "Native memory tracking has been shutdown due to process exiting"; + case NMT_out_of_memory: + return "Native memory tracking has been shutdown due to out of native memory"; case NMT_initialization: return "Native memory tracking failed to initialize"; case NMT_error_reporting: @@ -326,7 +328,7 @@ static void create_memory_record(address addr, MEMFLAGS type, size_t size, address pc, Thread* thread); static void create_record_in_recorder(address addr, MEMFLAGS type, - size_t size, address pc, Thread* thread); + size_t size, address pc, JavaThread* thread); private: // global memory snapshot @@ -336,7 +338,7 @@ static MemBaseline _baseline; // query lock - static Mutex _query_lock; + static Mutex* _query_lock; // a thread can start to allocate memory before it is attached // to VM 'Thread', those memory activities are recorded here.