| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/trace_event/memory_dump_manager.h" | 5 #include "base/trace_event/memory_dump_manager.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/allocator/features.h" | 10 #include "base/allocator/features.h" |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 | 414 |
| 415 void MemoryDumpManager::RegisterPollingMDPOnDumpThread( | 415 void MemoryDumpManager::RegisterPollingMDPOnDumpThread( |
| 416 scoped_refptr<MemoryDumpManager::MemoryDumpProviderInfo> mdpinfo) { | 416 scoped_refptr<MemoryDumpManager::MemoryDumpProviderInfo> mdpinfo) { |
| 417 AutoLock lock(lock_); | 417 AutoLock lock(lock_); |
| 418 dump_providers_for_polling_.insert(mdpinfo); | 418 dump_providers_for_polling_.insert(mdpinfo); |
| 419 | 419 |
| 420 // Notify ready for polling when first polling supported provider is | 420 // Notify ready for polling when first polling supported provider is |
| 421 // registered. This handles the case where OnTraceLogEnabled() did not notify | 421 // registered. This handles the case where OnTraceLogEnabled() did not notify |
| 422 // ready since no polling supported mdp has yet been registered. | 422 // ready since no polling supported mdp has yet been registered. |
| 423 if (dump_providers_for_polling_.size() == 1) | 423 if (dump_providers_for_polling_.size() == 1) |
| 424 dump_scheduler_->NotifyPollingSupported(); | 424 MemoryDumpScheduler::GetInstance()->EnablePollingIfNeeded(); |
| 425 } | 425 } |
| 426 | 426 |
| 427 void MemoryDumpManager::UnregisterPollingMDPOnDumpThread( | 427 void MemoryDumpManager::UnregisterPollingMDPOnDumpThread( |
| 428 scoped_refptr<MemoryDumpManager::MemoryDumpProviderInfo> mdpinfo) { | 428 scoped_refptr<MemoryDumpManager::MemoryDumpProviderInfo> mdpinfo) { |
| 429 mdpinfo->dump_provider->SuspendFastMemoryPolling(); | 429 mdpinfo->dump_provider->SuspendFastMemoryPolling(); |
| 430 | 430 |
| 431 AutoLock lock(lock_); | 431 AutoLock lock(lock_); |
| 432 dump_providers_for_polling_.erase(mdpinfo); | 432 dump_providers_for_polling_.erase(mdpinfo); |
| 433 DCHECK(!dump_providers_for_polling_.empty()) | 433 DCHECK(!dump_providers_for_polling_.empty()) |
| 434 << "All polling MDPs cannot be unregistered."; | 434 << "All polling MDPs cannot be unregistered."; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 pmd_async_state.reset(new ProcessMemoryDumpAsyncState( | 508 pmd_async_state.reset(new ProcessMemoryDumpAsyncState( |
| 509 args, dump_providers_, session_state_, callback, | 509 args, dump_providers_, session_state_, callback, |
| 510 dump_thread_ ? dump_thread_->task_runner() : nullptr)); | 510 dump_thread_ ? dump_thread_->task_runner() : nullptr)); |
| 511 | 511 |
| 512 // Safety check to prevent reaching here without calling RequestGlobalDump, | 512 // Safety check to prevent reaching here without calling RequestGlobalDump, |
| 513 // with disallowed modes. If |session_state_| is null then tracing is | 513 // with disallowed modes. If |session_state_| is null then tracing is |
| 514 // disabled. | 514 // disabled. |
| 515 CHECK(!session_state_ || | 515 CHECK(!session_state_ || |
| 516 session_state_->IsDumpModeAllowed(args.level_of_detail)); | 516 session_state_->IsDumpModeAllowed(args.level_of_detail)); |
| 517 | 517 |
| 518 if (dump_scheduler_) | 518 MemoryDumpScheduler::GetInstance()->NotifyDumpTriggered(); |
| 519 dump_scheduler_->NotifyDumpTriggered(); | |
| 520 } | 519 } |
| 521 | 520 |
| 522 TRACE_EVENT_WITH_FLOW0(kTraceCategory, "MemoryDumpManager::CreateProcessDump", | 521 TRACE_EVENT_WITH_FLOW0(kTraceCategory, "MemoryDumpManager::CreateProcessDump", |
| 523 TRACE_ID_MANGLE(args.dump_guid), | 522 TRACE_ID_MANGLE(args.dump_guid), |
| 524 TRACE_EVENT_FLAG_FLOW_OUT); | 523 TRACE_EVENT_FLAG_FLOW_OUT); |
| 525 | 524 |
| 526 // Start the process dump. This involves task runner hops as specified by the | 525 // Start the process dump. This involves task runner hops as specified by the |
| 527 // MemoryDumpProvider(s) in RegisterDumpProvider()). | 526 // MemoryDumpProvider(s) in RegisterDumpProvider()). |
| 528 SetupNextMemoryDump(std::move(pmd_async_state)); | 527 SetupNextMemoryDump(std::move(pmd_async_state)); |
| 529 } | 528 } |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 822 MakeUnique<SessionStateConvertableProxy<StackFrameDeduplicator>>( | 821 MakeUnique<SessionStateConvertableProxy<StackFrameDeduplicator>>( |
| 823 session_state, &MemoryDumpSessionState::stack_frame_deduplicator)); | 822 session_state, &MemoryDumpSessionState::stack_frame_deduplicator)); |
| 824 | 823 |
| 825 TRACE_EVENT_API_ADD_METADATA_EVENT( | 824 TRACE_EVENT_API_ADD_METADATA_EVENT( |
| 826 TraceLog::GetCategoryGroupEnabled("__metadata"), "typeNames", | 825 TraceLog::GetCategoryGroupEnabled("__metadata"), "typeNames", |
| 827 "typeNames", | 826 "typeNames", |
| 828 MakeUnique<SessionStateConvertableProxy<TypeNameDeduplicator>>( | 827 MakeUnique<SessionStateConvertableProxy<TypeNameDeduplicator>>( |
| 829 session_state, &MemoryDumpSessionState::type_name_deduplicator)); | 828 session_state, &MemoryDumpSessionState::type_name_deduplicator)); |
| 830 } | 829 } |
| 831 | 830 |
| 832 std::unique_ptr<MemoryDumpScheduler> dump_scheduler( | |
| 833 new MemoryDumpScheduler(this, dump_thread->task_runner())); | |
| 834 DCHECK_LE(memory_dump_config.triggers.size(), 3u); | |
| 835 for (const auto& trigger : memory_dump_config.triggers) { | |
| 836 if (!session_state->IsDumpModeAllowed(trigger.level_of_detail)) { | |
| 837 NOTREACHED(); | |
| 838 continue; | |
| 839 } | |
| 840 dump_scheduler->AddTrigger(trigger.trigger_type, trigger.level_of_detail, | |
| 841 trigger.min_time_between_dumps_ms); | |
| 842 } | |
| 843 | |
| 844 { | 831 { |
| 845 AutoLock lock(lock_); | 832 AutoLock lock(lock_); |
| 846 | 833 |
| 847 DCHECK(delegate_); // At this point we must have a delegate. | 834 DCHECK(delegate_); // At this point we must have a delegate. |
| 848 session_state_ = session_state; | 835 session_state_ = session_state; |
| 849 | 836 |
| 850 DCHECK(!dump_thread_); | 837 DCHECK(!dump_thread_); |
| 851 dump_thread_ = std::move(dump_thread); | 838 dump_thread_ = std::move(dump_thread); |
| 852 dump_scheduler_ = std::move(dump_scheduler); | |
| 853 | 839 |
| 854 subtle::NoBarrier_Store(&memory_tracing_enabled_, 1); | 840 subtle::NoBarrier_Store(&memory_tracing_enabled_, 1); |
| 855 | 841 |
| 856 dump_providers_for_polling_.clear(); | 842 dump_providers_for_polling_.clear(); |
| 857 for (const auto& mdpinfo : dump_providers_) { | 843 for (const auto& mdpinfo : dump_providers_) { |
| 858 if (mdpinfo->options.is_fast_polling_supported) | 844 if (mdpinfo->options.is_fast_polling_supported) |
| 859 dump_providers_for_polling_.insert(mdpinfo); | 845 dump_providers_for_polling_.insert(mdpinfo); |
| 860 } | 846 } |
| 847 |
| 848 MemoryDumpScheduler* dump_scheduler = MemoryDumpScheduler::GetInstance(); |
| 849 dump_scheduler->Setup(this, dump_thread_->task_runner()); |
| 850 DCHECK_LE(memory_dump_config.triggers.size(), 3u); |
| 851 for (const auto& trigger : memory_dump_config.triggers) { |
| 852 if (!session_state_->IsDumpModeAllowed(trigger.level_of_detail)) { |
| 853 NOTREACHED(); |
| 854 continue; |
| 855 } |
| 856 dump_scheduler->AddTrigger(trigger.trigger_type, trigger.level_of_detail, |
| 857 trigger.min_time_between_dumps_ms); |
| 858 } |
| 859 |
| 861 // Notify polling supported only if some polling supported provider was | 860 // Notify polling supported only if some polling supported provider was |
| 862 // registered, else RegisterPollingMDPOnDumpThread() will notify when first | 861 // registered, else RegisterPollingMDPOnDumpThread() will notify when first |
| 863 // polling MDP registers. | 862 // polling MDP registers. |
| 864 if (!dump_providers_for_polling_.empty()) | 863 if (!dump_providers_for_polling_.empty()) |
| 865 dump_scheduler_->NotifyPollingSupported(); | 864 dump_scheduler->EnablePollingIfNeeded(); |
| 866 | 865 |
| 867 // Only coordinator process triggers periodic global memory dumps. | 866 // Only coordinator process triggers periodic global memory dumps. |
| 868 if (is_coordinator_) | 867 if (is_coordinator_) |
| 869 dump_scheduler_->NotifyPeriodicTriggerSupported(); | 868 dump_scheduler->EnablePeriodicTriggerIfNeeded(); |
| 870 } | 869 } |
| 871 | 870 |
| 872 } | 871 } |
| 873 | 872 |
| 874 void MemoryDumpManager::OnTraceLogDisabled() { | 873 void MemoryDumpManager::OnTraceLogDisabled() { |
| 875 // There might be a memory dump in progress while this happens. Therefore, | 874 // There might be a memory dump in progress while this happens. Therefore, |
| 876 // ensure that the MDM state which depends on the tracing enabled / disabled | 875 // ensure that the MDM state which depends on the tracing enabled / disabled |
| 877 // state is always accessed by the dumping methods holding the |lock_|. | 876 // state is always accessed by the dumping methods holding the |lock_|. |
| 878 if (!subtle::NoBarrier_Load(&memory_tracing_enabled_)) | 877 if (!subtle::NoBarrier_Load(&memory_tracing_enabled_)) |
| 879 return; | 878 return; |
| 880 subtle::NoBarrier_Store(&memory_tracing_enabled_, 0); | 879 subtle::NoBarrier_Store(&memory_tracing_enabled_, 0); |
| 881 std::unique_ptr<Thread> dump_thread; | 880 std::unique_ptr<Thread> dump_thread; |
| 882 std::unique_ptr<MemoryDumpScheduler> scheduler; | |
| 883 { | 881 { |
| 884 AutoLock lock(lock_); | 882 AutoLock lock(lock_); |
| 885 dump_thread = std::move(dump_thread_); | 883 dump_thread = std::move(dump_thread_); |
| 886 session_state_ = nullptr; | 884 session_state_ = nullptr; |
| 887 scheduler = std::move(dump_scheduler_); | 885 MemoryDumpScheduler::GetInstance()->DisableAllTriggers(); |
| 888 } | 886 } |
| 889 scheduler->DisableAllTriggers(); | |
| 890 | 887 |
| 891 // Thread stops are blocking and must be performed outside of the |lock_| | 888 // Thread stops are blocking and must be performed outside of the |lock_| |
| 892 // or will deadlock (e.g., if SetupNextMemoryDump() tries to acquire it). | 889 // or will deadlock (e.g., if SetupNextMemoryDump() tries to acquire it). |
| 893 if (dump_thread) | 890 if (dump_thread) |
| 894 dump_thread->Stop(); | 891 dump_thread->Stop(); |
| 895 | 892 |
| 896 // |dump_providers_for_polling_| must be cleared only after the dump thread is | 893 // |dump_providers_for_polling_| must be cleared only after the dump thread is |
| 897 // stopped (polling tasks are done). | 894 // stopped (polling tasks are done). |
| 898 { | 895 { |
| 899 AutoLock lock(lock_); | 896 AutoLock lock(lock_); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 968 if (iter == process_dumps.end()) { | 965 if (iter == process_dumps.end()) { |
| 969 std::unique_ptr<ProcessMemoryDump> new_pmd( | 966 std::unique_ptr<ProcessMemoryDump> new_pmd( |
| 970 new ProcessMemoryDump(session_state, dump_args)); | 967 new ProcessMemoryDump(session_state, dump_args)); |
| 971 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; | 968 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; |
| 972 } | 969 } |
| 973 return iter->second.get(); | 970 return iter->second.get(); |
| 974 } | 971 } |
| 975 | 972 |
| 976 } // namespace trace_event | 973 } // namespace trace_event |
| 977 } // namespace base | 974 } // namespace base |
| OLD | NEW |