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 |