mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 11:34:38 +02:00
7182543: NMT ON: Aggregate a few NMT related bugs
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
This commit is contained in:
parent
559278381b
commit
f9083712dd
5 changed files with 35 additions and 35 deletions
|
@ -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() {
|
||||||
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> {
|
||||||
|
|
||||||
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 {
|
||||||
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
// 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() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_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() {
|
||||||
|
|
||||||
// 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() {
|
||||||
_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 {
|
||||||
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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue