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