27 #include "runtime/atomic.hpp" |
27 #include "runtime/atomic.hpp" |
28 #include "runtime/interfaceSupport.hpp" |
28 #include "runtime/interfaceSupport.hpp" |
29 #include "runtime/mutexLocker.hpp" |
29 #include "runtime/mutexLocker.hpp" |
30 #include "runtime/safepoint.hpp" |
30 #include "runtime/safepoint.hpp" |
31 #include "runtime/threadCritical.hpp" |
31 #include "runtime/threadCritical.hpp" |
|
32 #include "runtime/vm_operations.hpp" |
32 #include "services/memPtr.hpp" |
33 #include "services/memPtr.hpp" |
33 #include "services/memReporter.hpp" |
34 #include "services/memReporter.hpp" |
34 #include "services/memTracker.hpp" |
35 #include "services/memTracker.hpp" |
35 #include "utilities/decoder.hpp" |
36 #include "utilities/decoder.hpp" |
36 #include "utilities/globalDefinitions.hpp" |
37 #include "utilities/globalDefinitions.hpp" |
63 MemTracker::NMTLevel MemTracker::_tracking_level = MemTracker::NMT_off; |
64 MemTracker::NMTLevel MemTracker::_tracking_level = MemTracker::NMT_off; |
64 volatile MemTracker::NMTStates MemTracker::_state = NMT_uninited; |
65 volatile MemTracker::NMTStates MemTracker::_state = NMT_uninited; |
65 MemTracker::ShutdownReason MemTracker::_reason = NMT_shutdown_none; |
66 MemTracker::ShutdownReason MemTracker::_reason = NMT_shutdown_none; |
66 int MemTracker::_thread_count = 255; |
67 int MemTracker::_thread_count = 255; |
67 volatile jint MemTracker::_pooled_recorder_count = 0; |
68 volatile jint MemTracker::_pooled_recorder_count = 0; |
|
69 volatile unsigned long MemTracker::_processing_generation = 0; |
|
70 volatile bool MemTracker::_worker_thread_idle = false; |
68 debug_only(intx MemTracker::_main_thread_tid = 0;) |
71 debug_only(intx MemTracker::_main_thread_tid = 0;) |
69 NOT_PRODUCT(volatile jint MemTracker::_pending_recorder_count = 0;) |
72 NOT_PRODUCT(volatile jint MemTracker::_pending_recorder_count = 0;) |
70 |
73 |
71 void MemTracker::init_tracking_options(const char* option_line) { |
74 void MemTracker::init_tracking_options(const char* option_line) { |
72 _tracking_level = NMT_off; |
75 _tracking_level = NMT_off; |
568 return true; |
571 return true; |
569 } |
572 } |
570 return false; |
573 return false; |
571 } |
574 } |
572 |
575 |
|
576 // Whitebox API for blocking until the current generation of NMT data has been merged |
|
577 bool MemTracker::wbtest_wait_for_data_merge() { |
|
578 // NMT can't be shutdown while we're holding _query_lock |
|
579 MutexLockerEx lock(_query_lock, true); |
|
580 assert(_worker_thread != NULL, "Invalid query"); |
|
581 // the generation at query time, so NMT will spin till this generation is processed |
|
582 unsigned long generation_at_query_time = SequenceGenerator::current_generation(); |
|
583 unsigned long current_processing_generation = _processing_generation; |
|
584 // if generation counter overflown |
|
585 bool generation_overflown = (generation_at_query_time < current_processing_generation); |
|
586 long generations_to_wrap = MAX_UNSIGNED_LONG - current_processing_generation; |
|
587 // spin |
|
588 while (!shutdown_in_progress()) { |
|
589 if (!generation_overflown) { |
|
590 if (current_processing_generation > generation_at_query_time) { |
|
591 return true; |
|
592 } |
|
593 } else { |
|
594 assert(generations_to_wrap >= 0, "Sanity check"); |
|
595 long current_generations_to_wrap = MAX_UNSIGNED_LONG - current_processing_generation; |
|
596 assert(current_generations_to_wrap >= 0, "Sanity check"); |
|
597 // to overflow an unsigned long should take long time, so to_wrap check should be sufficient |
|
598 if (current_generations_to_wrap > generations_to_wrap && |
|
599 current_processing_generation > generation_at_query_time) { |
|
600 return true; |
|
601 } |
|
602 } |
|
603 |
|
604 // if worker thread is idle, but generation is not advancing, that means |
|
605 // there is not safepoint to let NMT advance generation, force one. |
|
606 if (_worker_thread_idle) { |
|
607 VM_ForceSafepoint vfs; |
|
608 VMThread::execute(&vfs); |
|
609 } |
|
610 MemSnapshot* snapshot = get_snapshot(); |
|
611 if (snapshot == NULL) { |
|
612 return false; |
|
613 } |
|
614 snapshot->wait(1000); |
|
615 current_processing_generation = _processing_generation; |
|
616 } |
|
617 // We end up here if NMT is shutting down before our data has been merged |
|
618 return false; |
|
619 } |
|
620 |
573 // compare memory usage between current snapshot and baseline |
621 // compare memory usage between current snapshot and baseline |
574 bool MemTracker::compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) { |
622 bool MemTracker::compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) { |
575 MutexLockerEx lock(_query_lock, true); |
623 MutexLockerEx lock(_query_lock, true); |
576 if (_baseline.baselined()) { |
624 if (_baseline.baselined()) { |
577 MemBaseline baseline; |
625 MemBaseline baseline; |