提交 06382e86 编写于 作者: Z zgu

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
上级 f033456c
...@@ -45,11 +45,11 @@ MemPointer* SequencedRecordIterator::next_record() { ...@@ -45,11 +45,11 @@ MemPointer* SequencedRecordIterator::next_record() {
} }
debug_only(volatile jint MemRecorder::_instance_count = 0;) volatile jint MemRecorder::_instance_count = 0;
MemRecorder::MemRecorder() { MemRecorder::MemRecorder() {
assert(MemTracker::is_on(), "Native memory tracking is off"); assert(MemTracker::is_on(), "Native memory tracking is off");
debug_only(Atomic::inc(&_instance_count);) Atomic::inc(&_instance_count);
debug_only(set_generation();) debug_only(set_generation();)
if (MemTracker::track_callsite()) { if (MemTracker::track_callsite()) {
...@@ -83,9 +83,7 @@ MemRecorder::~MemRecorder() { ...@@ -83,9 +83,7 @@ MemRecorder::~MemRecorder() {
delete _next; delete _next;
} }
#ifdef ASSERT
Atomic::dec(&_instance_count); Atomic::dec(&_instance_count);
#endif
} }
// Sorting order: // Sorting order:
......
...@@ -249,9 +249,9 @@ class MemRecorder : public CHeapObj<mtNMT|otNMTRecorder> { ...@@ -249,9 +249,9 @@ class MemRecorder : public CHeapObj<mtNMT|otNMTRecorder> {
SequencedRecordIterator pointer_itr(); SequencedRecordIterator pointer_itr();
public: protected:
// number of MemRecorder instance // number of MemRecorder instance
debug_only(static volatile jint _instance_count;) static volatile jint _instance_count;
private: private:
// sorting function, sort records into following order // sorting function, sort records into following order
......
...@@ -67,7 +67,7 @@ class MemTrackWorker : public NamedThread { ...@@ -67,7 +67,7 @@ class MemTrackWorker : public NamedThread {
NOT_PRODUCT(int _last_gen_in_use;) NOT_PRODUCT(int _last_gen_in_use;)
inline int generations_in_use() const { 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));
} }
}; };
......
...@@ -351,21 +351,17 @@ void MemTracker::create_memory_record(address addr, MEMFLAGS flags, ...@@ -351,21 +351,17 @@ void MemTracker::create_memory_record(address addr, MEMFLAGS flags,
} }
if (thread != NULL) { if (thread != NULL) {
#ifdef ASSERT
// cause assertion on stack base. This ensures that threads call
// Thread::record_stack_base_and_size() method, which will create
// thread native stack records.
thread->stack_base();
#endif
// 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 (thread->is_Java_thread() && ((JavaThread*)thread)->is_safepoint_visible()) {
if (((JavaThread*)thread)->thread_state() == _thread_in_native) { JavaThread* java_thread = static_cast<JavaThread*>(thread);
ThreadInVMfromNative trans((JavaThread*)thread); JavaThreadState state = java_thread->thread_state();
create_record_in_recorder(addr, flags, size, pc, thread); 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 { } else {
create_record_in_recorder(addr, flags, size, pc, thread); create_record_in_recorder(addr, flags, size, pc, java_thread);
} }
} else { } else {
// other threads, such as worker and watcher threads, etc. need to // other threads, such as worker and watcher threads, etc. need to
...@@ -390,10 +386,9 @@ void MemTracker::create_memory_record(address addr, MEMFLAGS flags, ...@@ -390,10 +386,9 @@ void MemTracker::create_memory_record(address addr, MEMFLAGS flags,
// write a record to proper recorder. No lock can be taken from this method // write a record to proper recorder. No lock can be taken from this method
// down. // down.
void MemTracker::create_record_in_recorder(address addr, MEMFLAGS flags, void MemTracker::create_record_in_recorder(address addr, MEMFLAGS flags,
size_t size, address pc, Thread* thread) { size_t size, address pc, JavaThread* thread) {
assert(thread == NULL || thread->is_Java_thread(), "wrong thread");
MemRecorder* rc = get_thread_recorder((JavaThread*)thread); MemRecorder* rc = get_thread_recorder(thread);
if (rc != NULL) { if (rc != NULL) {
rc->record(addr, flags, size, pc); rc->record(addr, flags, size, pc);
} }
...@@ -460,17 +455,18 @@ void MemTracker::sync() { ...@@ -460,17 +455,18 @@ void MemTracker::sync() {
} }
} }
_sync_point_skip_count = 0; _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, // This method is running at safepoint, with ThreadCritical lock,
// it should guarantee that NMT is fully sync-ed. // it should guarantee that NMT is fully sync-ed.
ThreadCritical tc; 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) { if (_global_recorder != NULL) {
_global_recorder->set_next(pending_recorders); _global_recorder->set_next(pending_recorders);
pending_recorders = _global_recorder; pending_recorders = _global_recorder;
...@@ -486,8 +482,6 @@ void MemTracker::sync() { ...@@ -486,8 +482,6 @@ void MemTracker::sync() {
// now, it is the time to shut whole things off // now, it is the time to shut whole things off
if (_state == NMT_final_shutdown) { if (_state == NMT_final_shutdown) {
_tracking_level = NMT_off;
// walk all JavaThreads to delete all recorders // walk all JavaThreads to delete all recorders
SyncThreadRecorderClosure stc; SyncThreadRecorderClosure stc;
Threads::threads_do(&stc); Threads::threads_do(&stc);
...@@ -499,8 +493,16 @@ void MemTracker::sync() { ...@@ -499,8 +493,16 @@ void MemTracker::sync() {
_global_recorder = NULL; _global_recorder = NULL;
} }
} }
MemRecorder* pending_recorders = get_pending_recorders();
_state = NMT_shutdown; 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;
}
} }
} }
......
...@@ -326,7 +326,7 @@ class MemTracker : AllStatic { ...@@ -326,7 +326,7 @@ class MemTracker : AllStatic {
static void create_memory_record(address addr, MEMFLAGS type, static void create_memory_record(address addr, MEMFLAGS type,
size_t size, address pc, Thread* thread); size_t size, address pc, Thread* thread);
static void create_record_in_recorder(address addr, MEMFLAGS type, 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: private:
// global memory snapshot // global memory snapshot
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册