Chromium Code Reviews| 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 <inttypes.h> | 7 #include <inttypes.h> |
| 8 #include <stdio.h> | 8 #include <stdio.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 150 LeakySingletonTraits<MemoryDumpManager>>::get(); | 150 LeakySingletonTraits<MemoryDumpManager>>::get(); |
| 151 } | 151 } |
| 152 | 152 |
| 153 // static | 153 // static |
| 154 void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) { | 154 void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) { |
| 155 g_instance_for_testing = instance; | 155 g_instance_for_testing = instance; |
| 156 } | 156 } |
| 157 | 157 |
| 158 MemoryDumpManager::MemoryDumpManager() | 158 MemoryDumpManager::MemoryDumpManager() |
| 159 : is_coordinator_(false), | 159 : is_coordinator_(false), |
| 160 is_enabled_(0), | |
| 161 tracing_process_id_(kInvalidTracingProcessId), | 160 tracing_process_id_(kInvalidTracingProcessId), |
| 162 dumper_registrations_ignored_for_testing_(false), | 161 dumper_registrations_ignored_for_testing_(false), |
| 163 heap_profiling_enabled_(false) { | 162 heap_profiling_enabled_(false) { |
| 164 g_next_guid.GetNext(); // Make sure that first guid is not zero. | 163 g_next_guid.GetNext(); // Make sure that first guid is not zero. |
| 165 | 164 |
| 166 // At this point the command line may not be initialized but we try to | 165 // At this point the command line may not be initialized but we try to |
| 167 // enable the heap profiler to capture allocations as soon as possible. | 166 // enable the heap profiler to capture allocations as soon as possible. |
| 168 EnableHeapProfilingIfNeeded(); | 167 EnableHeapProfilingIfNeeded(); |
| 169 } | 168 } |
| 170 | 169 |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 397 // to just skip it, without actually invoking the |mdp|, which might be | 396 // to just skip it, without actually invoking the |mdp|, which might be |
| 398 // destroyed by the caller soon after this method returns. | 397 // destroyed by the caller soon after this method returns. |
| 399 (*mdp_iter)->disabled = true; | 398 (*mdp_iter)->disabled = true; |
| 400 dump_providers_.erase(mdp_iter); | 399 dump_providers_.erase(mdp_iter); |
| 401 } | 400 } |
| 402 | 401 |
| 403 void MemoryDumpManager::RequestGlobalDump( | 402 void MemoryDumpManager::RequestGlobalDump( |
| 404 MemoryDumpType dump_type, | 403 MemoryDumpType dump_type, |
| 405 MemoryDumpLevelOfDetail level_of_detail, | 404 MemoryDumpLevelOfDetail level_of_detail, |
| 406 const GlobalMemoryDumpCallback& callback) { | 405 const GlobalMemoryDumpCallback& callback) { |
| 407 // Bail out immediately if tracing is not enabled at all or if the dump mode | 406 if (!IsDumpModeAllowed(level_of_detail) && |
| 408 // is not allowed. | 407 dump_type != MemoryDumpType::SUMMARY_ONLY) { |
| 409 if (!UNLIKELY(subtle::NoBarrier_Load(&is_enabled_)) || | 408 VLOG(1) << kLogPrefix |
| 410 !IsDumpModeAllowed(level_of_detail)) { | 409 << " failed because the requested dump mode is " |
| 411 VLOG(1) << kLogPrefix << " failed because " << kTraceCategory | |
| 412 << " tracing category is not enabled or the requested dump mode is " | |
| 413 "not allowed by trace config."; | 410 "not allowed by trace config."; |
| 414 if (!callback.is_null()) | 411 callback.Run(0u /* guid */, false /* success */); |
| 415 callback.Run(0u /* guid */, false /* success */); | |
| 416 return; | 412 return; |
| 417 } | 413 } |
| 418 | 414 |
|
ssid
2017/05/04 22:00:22
DCHECK(dump_type != SUMMARY_ONLY || level_of_detai
hjd
2017/05/05 14:54:52
Done.
| |
| 419 const uint64_t guid = | 415 const uint64_t guid = |
| 420 TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext()); | 416 TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext()); |
| 421 | 417 |
| 422 // Creates an async event to keep track of the global dump evolution. | 418 // Creates an async event to keep track of the global dump evolution. |
| 423 // The |wrapped_callback| will generate the ASYNC_END event and then invoke | 419 // The |wrapped_callback| will generate the ASYNC_END event and then invoke |
| 424 // the real |callback| provided by the caller. | 420 // the real |callback| provided by the caller. |
| 425 TRACE_EVENT_NESTABLE_ASYNC_BEGIN2( | 421 TRACE_EVENT_NESTABLE_ASYNC_BEGIN2( |
| 426 kTraceCategory, "GlobalMemoryDump", TRACE_ID_LOCAL(guid), "dump_type", | 422 kTraceCategory, "GlobalMemoryDump", TRACE_ID_LOCAL(guid), "dump_type", |
| 427 MemoryDumpTypeToString(dump_type), "level_of_detail", | 423 MemoryDumpTypeToString(dump_type), "level_of_detail", |
| 428 MemoryDumpLevelOfDetailToString(level_of_detail)); | 424 MemoryDumpLevelOfDetailToString(level_of_detail)); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 491 if (TraceLog::GetInstance() | 487 if (TraceLog::GetInstance() |
| 492 ->GetCurrentTraceConfig() | 488 ->GetCurrentTraceConfig() |
| 493 .IsArgumentFilterEnabled()) { | 489 .IsArgumentFilterEnabled()) { |
| 494 CHECK_EQ(MemoryDumpLevelOfDetail::BACKGROUND, args.level_of_detail); | 490 CHECK_EQ(MemoryDumpLevelOfDetail::BACKGROUND, args.level_of_detail); |
| 495 } | 491 } |
| 496 | 492 |
| 497 std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state; | 493 std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state; |
| 498 { | 494 { |
| 499 AutoLock lock(lock_); | 495 AutoLock lock(lock_); |
| 500 | 496 |
| 497 if (args.level_of_detail == MemoryDumpLevelOfDetail::DETAILED && | |
|
ssid
2017/05/04 22:00:22
Comment here saying:
MDM could have been disabled
hjd
2017/05/05 14:54:52
Done.
| |
| 498 heap_profiling_enabled_ && !session_state_) { | |
| 499 callback.Run(args.dump_guid, false /* success */, base::nullopt); | |
| 500 return; | |
| 501 } | |
| 502 | |
| 501 pmd_async_state.reset(new ProcessMemoryDumpAsyncState( | 503 pmd_async_state.reset(new ProcessMemoryDumpAsyncState( |
| 502 args, dump_providers_, session_state_, callback, | 504 args, dump_providers_, session_state_, callback, |
| 503 GetOrCreateBgTaskRunnerLocked())); | 505 GetOrCreateBgTaskRunnerLocked())); |
| 504 | 506 |
| 505 // Safety check to prevent reaching here without calling RequestGlobalDump, | 507 // Safety check to prevent reaching here without calling RequestGlobalDump, |
| 506 // with disallowed modes. If |session_state_| is null then tracing is | 508 // with disallowed modes. If |session_state_| is null then tracing is |
| 507 // disabled. | 509 // disabled. |
| 508 CHECK(!session_state_ || | 510 CHECK(!session_state_ || |
| 509 session_state_->IsDumpModeAllowed(args.level_of_detail)); | 511 session_state_->IsDumpModeAllowed(args.level_of_detail)); |
| 510 | 512 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 527 // |lock_| is used in these functions purely to ensure consistency w.r.t. | 529 // |lock_| is used in these functions purely to ensure consistency w.r.t. |
| 528 // (un)registrations of |dump_providers_|. | 530 // (un)registrations of |dump_providers_|. |
| 529 void MemoryDumpManager::SetupNextMemoryDump( | 531 void MemoryDumpManager::SetupNextMemoryDump( |
| 530 std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state) { | 532 std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state) { |
| 531 HEAP_PROFILER_SCOPED_IGNORE; | 533 HEAP_PROFILER_SCOPED_IGNORE; |
| 532 // Initalizes the ThreadLocalEventBuffer to guarantee that the TRACE_EVENTs | 534 // Initalizes the ThreadLocalEventBuffer to guarantee that the TRACE_EVENTs |
| 533 // in the PostTask below don't end up registering their own dump providers | 535 // in the PostTask below don't end up registering their own dump providers |
| 534 // (for discounting trace memory overhead) while holding the |lock_|. | 536 // (for discounting trace memory overhead) while holding the |lock_|. |
| 535 TraceLog::GetInstance()->InitializeThreadLocalEventBufferIfSupported(); | 537 TraceLog::GetInstance()->InitializeThreadLocalEventBufferIfSupported(); |
| 536 | 538 |
| 537 // MDM might have been disabled before getting to this point. | |
| 538 // Anyway either MDM is disabled or this was the last hop, create a trace | |
| 539 // event, add it to the trace and finalize process dump invoking the callback. | |
| 540 if (!subtle::NoBarrier_Load(&is_enabled_)) { | |
| 541 if (pmd_async_state->pending_dump_providers.empty()) { | |
| 542 VLOG(1) << kLogPrefix << " failed because MemoryDumpManager was disabled" | |
| 543 << " before finalizing the dump"; | |
| 544 } else { | |
| 545 VLOG(1) << kLogPrefix << " failed because MemoryDumpManager was disabled" | |
| 546 << " before dumping " | |
| 547 << pmd_async_state->pending_dump_providers.back().get()->name; | |
| 548 } | |
| 549 pmd_async_state->dump_successful = false; | |
| 550 pmd_async_state->pending_dump_providers.clear(); | |
| 551 } | |
| 552 | |
| 553 if (pmd_async_state->pending_dump_providers.empty()) | 539 if (pmd_async_state->pending_dump_providers.empty()) |
| 554 return FinalizeDumpAndAddToTrace(std::move(pmd_async_state)); | 540 return FinalizeDumpAndAddToTrace(std::move(pmd_async_state)); |
| 555 | 541 |
| 556 // Read MemoryDumpProviderInfo thread safety considerations in | 542 // Read MemoryDumpProviderInfo thread safety considerations in |
| 557 // memory_dump_manager.h when accessing |mdpinfo| fields. | 543 // memory_dump_manager.h when accessing |mdpinfo| fields. |
| 558 MemoryDumpProviderInfo* mdpinfo = | 544 MemoryDumpProviderInfo* mdpinfo = |
| 559 pmd_async_state->pending_dump_providers.back().get(); | 545 pmd_async_state->pending_dump_providers.back().get(); |
| 560 | 546 |
| 561 // If we are in background tracing, we should invoke only the whitelisted | 547 // If we are in background tracing, we should invoke only the whitelisted |
| 562 // providers. Ignore other providers and continue. | 548 // providers. Ignore other providers and continue. |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 802 MakeUnique<SessionStateConvertableProxy<TypeNameDeduplicator>>( | 788 MakeUnique<SessionStateConvertableProxy<TypeNameDeduplicator>>( |
| 803 session_state, &MemoryDumpSessionState::type_name_deduplicator)); | 789 session_state, &MemoryDumpSessionState::type_name_deduplicator)); |
| 804 } | 790 } |
| 805 | 791 |
| 806 AutoLock lock(lock_); | 792 AutoLock lock(lock_); |
| 807 | 793 |
| 808 // At this point we must have the ability to request global dumps. | 794 // At this point we must have the ability to request global dumps. |
| 809 DCHECK(!request_dump_function_.is_null()); | 795 DCHECK(!request_dump_function_.is_null()); |
| 810 session_state_ = session_state; | 796 session_state_ = session_state; |
| 811 | 797 |
| 812 subtle::NoBarrier_Store(&is_enabled_, 1); | |
| 813 | |
| 814 MemoryDumpScheduler::Config periodic_config; | 798 MemoryDumpScheduler::Config periodic_config; |
| 815 bool peak_detector_configured = false; | 799 bool peak_detector_configured = false; |
| 816 for (const auto& trigger : memory_dump_config.triggers) { | 800 for (const auto& trigger : memory_dump_config.triggers) { |
| 817 if (!session_state_->IsDumpModeAllowed(trigger.level_of_detail)) { | 801 if (!session_state_->IsDumpModeAllowed(trigger.level_of_detail)) { |
| 818 NOTREACHED(); | 802 NOTREACHED(); |
| 819 continue; | 803 continue; |
| 820 } | 804 } |
| 821 if (trigger.trigger_type == MemoryDumpType::PERIODIC_INTERVAL) { | 805 if (trigger.trigger_type == MemoryDumpType::PERIODIC_INTERVAL) { |
| 822 if (periodic_config.triggers.empty()) { | 806 if (periodic_config.triggers.empty()) { |
| 823 periodic_config.callback = BindRepeating(&OnPeriodicSchedulerTick); | 807 periodic_config.callback = BindRepeating(&OnPeriodicSchedulerTick); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 854 if (is_coordinator_ && !periodic_config.triggers.empty()) { | 838 if (is_coordinator_ && !periodic_config.triggers.empty()) { |
| 855 MemoryDumpScheduler::GetInstance()->Start(periodic_config, | 839 MemoryDumpScheduler::GetInstance()->Start(periodic_config, |
| 856 GetOrCreateBgTaskRunnerLocked()); | 840 GetOrCreateBgTaskRunnerLocked()); |
| 857 } | 841 } |
| 858 } | 842 } |
| 859 | 843 |
| 860 void MemoryDumpManager::Disable() { | 844 void MemoryDumpManager::Disable() { |
| 861 // There might be a memory dump in progress while this happens. Therefore, | 845 // There might be a memory dump in progress while this happens. Therefore, |
| 862 // ensure that the MDM state which depends on the tracing enabled / disabled | 846 // ensure that the MDM state which depends on the tracing enabled / disabled |
| 863 // state is always accessed by the dumping methods holding the |lock_|. | 847 // state is always accessed by the dumping methods holding the |lock_|. |
| 864 if (!subtle::NoBarrier_Load(&is_enabled_)) | 848 AutoLock lock(lock_); |
| 865 return; | 849 |
| 866 subtle::NoBarrier_Store(&is_enabled_, 0); | 850 MemoryDumpScheduler::GetInstance()->Stop(); |
| 867 { | 851 MemoryPeakDetector::GetInstance()->TearDown(); |
| 868 AutoLock lock(lock_); | 852 session_state_ = nullptr; |
| 869 MemoryDumpScheduler::GetInstance()->Stop(); | |
| 870 MemoryPeakDetector::GetInstance()->TearDown(); | |
| 871 session_state_ = nullptr; | |
| 872 } | |
| 873 } | 853 } |
| 874 | 854 |
| 875 bool MemoryDumpManager::IsDumpModeAllowed(MemoryDumpLevelOfDetail dump_mode) { | 855 bool MemoryDumpManager::IsDumpModeAllowed(MemoryDumpLevelOfDetail dump_mode) { |
| 876 AutoLock lock(lock_); | 856 AutoLock lock(lock_); |
| 877 if (!session_state_) | 857 if (!session_state_) |
| 878 return false; | 858 return false; |
| 879 return session_state_->IsDumpModeAllowed(dump_mode); | 859 return session_state_->IsDumpModeAllowed(dump_mode); |
| 880 } | 860 } |
| 881 | 861 |
| 882 MemoryDumpManager::ProcessMemoryDumpAsyncState::ProcessMemoryDumpAsyncState( | 862 MemoryDumpManager::ProcessMemoryDumpAsyncState::ProcessMemoryDumpAsyncState( |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 905 if (iter == process_dumps.end()) { | 885 if (iter == process_dumps.end()) { |
| 906 std::unique_ptr<ProcessMemoryDump> new_pmd( | 886 std::unique_ptr<ProcessMemoryDump> new_pmd( |
| 907 new ProcessMemoryDump(session_state, dump_args)); | 887 new ProcessMemoryDump(session_state, dump_args)); |
| 908 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; | 888 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; |
| 909 } | 889 } |
| 910 return iter->second.get(); | 890 return iter->second.get(); |
| 911 } | 891 } |
| 912 | 892 |
| 913 } // namespace trace_event | 893 } // namespace trace_event |
| 914 } // namespace base | 894 } // namespace base |
| OLD | NEW |