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 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 482 MemoryDumpProvider* provider) { | 482 MemoryDumpProvider* provider) { |
| 483 AutoLock lock(lock_); | 483 AutoLock lock(lock_); |
| 484 | 484 |
| 485 for (const auto& info : dump_providers_) { | 485 for (const auto& info : dump_providers_) { |
| 486 if (info->dump_provider == provider) | 486 if (info->dump_provider == provider) |
| 487 return true; | 487 return true; |
| 488 } | 488 } |
| 489 return false; | 489 return false; |
| 490 } | 490 } |
| 491 | 491 |
| 492 scoped_refptr<base::SingleThreadTaskRunner> MemoryDumpManager::GetTaskRunner() { | |
| 493 lock_.AssertAcquired(); | |
| 494 | |
| 495 if (dump_thread_) | |
| 496 return dump_thread_->task_runner(); | |
| 497 | |
| 498 // Spin-up the thread used to invoke unbound dump providers. | |
| 499 std::unique_ptr<Thread> dump_thread(new Thread("MemoryInfra")); | |
| 500 if (!dump_thread->Start()) { | |
|
Primiano Tucci (use gerrit)
2017/04/24 15:30:58
I'd just violently CHECK(started) here.
Trying to
hjd
2017/04/24 16:27:59
Done.
| |
| 501 LOG(ERROR) << "Failed to start the memory-infra thread for tracing"; | |
| 502 NOTREACHED(); | |
| 503 } | |
| 504 | |
| 505 dump_thread_ = std::move(dump_thread); | |
| 506 | |
| 507 return dump_thread_->task_runner(); | |
| 508 } | |
| 509 | |
| 492 void MemoryDumpManager::CreateProcessDump( | 510 void MemoryDumpManager::CreateProcessDump( |
| 493 const MemoryDumpRequestArgs& args, | 511 const MemoryDumpRequestArgs& args, |
| 494 const ProcessMemoryDumpCallback& callback) { | 512 const ProcessMemoryDumpCallback& callback) { |
| 495 char guid_str[20]; | 513 char guid_str[20]; |
| 496 sprintf(guid_str, "0x%" PRIx64, args.dump_guid); | 514 sprintf(guid_str, "0x%" PRIx64, args.dump_guid); |
| 497 TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(kTraceCategory, "ProcessMemoryDump", | 515 TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(kTraceCategory, "ProcessMemoryDump", |
| 498 TRACE_ID_LOCAL(args.dump_guid), "dump_guid", | 516 TRACE_ID_LOCAL(args.dump_guid), "dump_guid", |
| 499 TRACE_STR_COPY(guid_str)); | 517 TRACE_STR_COPY(guid_str)); |
| 500 | 518 |
| 501 // If argument filter is enabled then only background mode dumps should be | 519 // If argument filter is enabled then only background mode dumps should be |
| 502 // allowed. In case the trace config passed for background tracing session | 520 // allowed. In case the trace config passed for background tracing session |
| 503 // missed the allowed modes argument, it crashes here instead of creating | 521 // missed the allowed modes argument, it crashes here instead of creating |
| 504 // unexpected dumps. | 522 // unexpected dumps. |
| 505 if (TraceLog::GetInstance() | 523 if (TraceLog::GetInstance() |
| 506 ->GetCurrentTraceConfig() | 524 ->GetCurrentTraceConfig() |
| 507 .IsArgumentFilterEnabled()) { | 525 .IsArgumentFilterEnabled()) { |
| 508 CHECK_EQ(MemoryDumpLevelOfDetail::BACKGROUND, args.level_of_detail); | 526 CHECK_EQ(MemoryDumpLevelOfDetail::BACKGROUND, args.level_of_detail); |
| 509 } | 527 } |
| 510 | 528 |
| 511 std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state; | 529 std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state; |
| 512 { | 530 { |
| 513 AutoLock lock(lock_); | 531 AutoLock lock(lock_); |
| 514 | 532 |
| 515 // |dump_thread_| can be nullptr is tracing was disabled before reaching | |
| 516 // here. SetupNextMemoryDump() is robust enough to tolerate it and will | |
| 517 // NACK the dump. | |
| 518 pmd_async_state.reset(new ProcessMemoryDumpAsyncState( | 533 pmd_async_state.reset(new ProcessMemoryDumpAsyncState( |
| 519 args, dump_providers_, session_state_, callback, | 534 args, dump_providers_, session_state_, callback, GetTaskRunner())); |
| 520 dump_thread_ ? dump_thread_->task_runner() : nullptr)); | |
| 521 | 535 |
| 522 // Safety check to prevent reaching here without calling RequestGlobalDump, | 536 // Safety check to prevent reaching here without calling RequestGlobalDump, |
| 523 // with disallowed modes. If |session_state_| is null then tracing is | 537 // with disallowed modes. If |session_state_| is null then tracing is |
| 524 // disabled. | 538 // disabled. |
| 525 CHECK(!session_state_ || | 539 CHECK(!session_state_ || |
| 526 session_state_->IsDumpModeAllowed(args.level_of_detail)); | 540 session_state_->IsDumpModeAllowed(args.level_of_detail)); |
| 527 | 541 |
| 528 // If enabled, holds back the peak detector resetting its estimation window. | 542 // If enabled, holds back the peak detector resetting its estimation window. |
| 529 MemoryPeakDetector::GetInstance()->Throttle(); | 543 MemoryPeakDetector::GetInstance()->Throttle(); |
| 530 } | 544 } |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 544 // |lock_| is used in these functions purely to ensure consistency w.r.t. | 558 // |lock_| is used in these functions purely to ensure consistency w.r.t. |
| 545 // (un)registrations of |dump_providers_|. | 559 // (un)registrations of |dump_providers_|. |
| 546 void MemoryDumpManager::SetupNextMemoryDump( | 560 void MemoryDumpManager::SetupNextMemoryDump( |
| 547 std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state) { | 561 std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state) { |
| 548 HEAP_PROFILER_SCOPED_IGNORE; | 562 HEAP_PROFILER_SCOPED_IGNORE; |
| 549 // Initalizes the ThreadLocalEventBuffer to guarantee that the TRACE_EVENTs | 563 // Initalizes the ThreadLocalEventBuffer to guarantee that the TRACE_EVENTs |
| 550 // in the PostTask below don't end up registering their own dump providers | 564 // in the PostTask below don't end up registering their own dump providers |
| 551 // (for discounting trace memory overhead) while holding the |lock_|. | 565 // (for discounting trace memory overhead) while holding the |lock_|. |
| 552 TraceLog::GetInstance()->InitializeThreadLocalEventBufferIfSupported(); | 566 TraceLog::GetInstance()->InitializeThreadLocalEventBufferIfSupported(); |
| 553 | 567 |
| 554 // |dump_thread_| might be destroyed before getting this point. | 568 // MDM might have been disabled before getting to this point. |
| 555 // It means that tracing was disabled right before starting this dump. | 569 // Anyway either MDM is disabled or this was the last hop, create a trace |
| 556 // Anyway either tracing is stopped or this was the last hop, create a trace | |
| 557 // event, add it to the trace and finalize process dump invoking the callback. | 570 // event, add it to the trace and finalize process dump invoking the callback. |
| 558 if (!pmd_async_state->dump_thread_task_runner.get()) { | 571 if (!subtle::NoBarrier_Load(&memory_tracing_enabled_)) { |
|
Primiano Tucci (use gerrit)
2017/04/24 15:30:58
I think this extra check is superfluous. The callb
hjd
2017/04/24 16:27:59
Removing this causes a test (MemoryDumpManagerTest
ssid
2017/04/25 03:21:47
I agree with primiano. We could get to a state whe
| |
| 559 if (pmd_async_state->pending_dump_providers.empty()) { | 572 if (pmd_async_state->pending_dump_providers.empty()) { |
| 560 VLOG(1) << kLogPrefix << " failed because dump thread was destroyed" | 573 VLOG(1) << kLogPrefix << " failed because MemoryDumpManager was disabled" |
| 561 << " before finalizing the dump"; | 574 << " before finalizing the dump"; |
| 562 } else { | 575 } else { |
| 563 VLOG(1) << kLogPrefix << " failed because dump thread was destroyed" | 576 VLOG(1) << kLogPrefix << " failed because MemoryDumpManager was disabled" |
| 564 << " before dumping " | 577 << " before dumping " |
| 565 << pmd_async_state->pending_dump_providers.back().get()->name; | 578 << pmd_async_state->pending_dump_providers.back().get()->name; |
| 566 } | 579 } |
| 567 pmd_async_state->dump_successful = false; | 580 pmd_async_state->dump_successful = false; |
| 568 pmd_async_state->pending_dump_providers.clear(); | 581 pmd_async_state->pending_dump_providers.clear(); |
| 569 } | 582 } |
| 583 | |
| 570 if (pmd_async_state->pending_dump_providers.empty()) | 584 if (pmd_async_state->pending_dump_providers.empty()) |
| 571 return FinalizeDumpAndAddToTrace(std::move(pmd_async_state)); | 585 return FinalizeDumpAndAddToTrace(std::move(pmd_async_state)); |
| 572 | 586 |
| 573 // Read MemoryDumpProviderInfo thread safety considerations in | 587 // Read MemoryDumpProviderInfo thread safety considerations in |
| 574 // memory_dump_manager.h when accessing |mdpinfo| fields. | 588 // memory_dump_manager.h when accessing |mdpinfo| fields. |
| 575 MemoryDumpProviderInfo* mdpinfo = | 589 MemoryDumpProviderInfo* mdpinfo = |
| 576 pmd_async_state->pending_dump_providers.back().get(); | 590 pmd_async_state->pending_dump_providers.back().get(); |
| 577 | 591 |
| 578 // If we are in background tracing, we should invoke only the whitelisted | 592 // If we are in background tracing, we should invoke only the whitelisted |
| 579 // providers. Ignore other providers and continue. | 593 // providers. Ignore other providers and continue. |
| 580 if (pmd_async_state->req_args.level_of_detail == | 594 if (pmd_async_state->req_args.level_of_detail == |
| 581 MemoryDumpLevelOfDetail::BACKGROUND && | 595 MemoryDumpLevelOfDetail::BACKGROUND && |
| 582 !mdpinfo->whitelisted_for_background_mode) { | 596 !mdpinfo->whitelisted_for_background_mode) { |
| 583 pmd_async_state->pending_dump_providers.pop_back(); | 597 pmd_async_state->pending_dump_providers.pop_back(); |
| 584 return SetupNextMemoryDump(std::move(pmd_async_state)); | 598 return SetupNextMemoryDump(std::move(pmd_async_state)); |
| 585 } | 599 } |
| 586 | 600 |
| 587 // If the dump provider did not specify a task runner affinity, dump on | 601 // If the dump provider did not specify a task runner affinity, dump on |
| 588 // |dump_thread_| which is already checked above for presence. | 602 // |dump_thread_|. |
| 589 SequencedTaskRunner* task_runner = mdpinfo->task_runner.get(); | 603 SequencedTaskRunner* task_runner = mdpinfo->task_runner.get(); |
| 590 if (!task_runner) { | 604 if (!task_runner) { |
| 591 DCHECK(mdpinfo->options.dumps_on_single_thread_task_runner); | 605 DCHECK(mdpinfo->options.dumps_on_single_thread_task_runner); |
| 592 task_runner = pmd_async_state->dump_thread_task_runner.get(); | 606 task_runner = pmd_async_state->dump_thread_task_runner.get(); |
| 593 DCHECK(task_runner); | 607 DCHECK(task_runner); |
| 594 } | 608 } |
| 595 | 609 |
| 596 if (mdpinfo->options.dumps_on_single_thread_task_runner && | 610 if (mdpinfo->options.dumps_on_single_thread_task_runner && |
| 597 task_runner->RunsTasksOnCurrentThread()) { | 611 task_runner->RunsTasksOnCurrentThread()) { |
| 598 // If |dumps_on_single_thread_task_runner| is true then no PostTask is | 612 // If |dumps_on_single_thread_task_runner| is true then no PostTask is |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 779 pmd_async_state->callback.Run(dump_guid, dump_successful, result); | 793 pmd_async_state->callback.Run(dump_guid, dump_successful, result); |
| 780 pmd_async_state->callback.Reset(); | 794 pmd_async_state->callback.Reset(); |
| 781 } | 795 } |
| 782 | 796 |
| 783 TRACE_EVENT_NESTABLE_ASYNC_END0(kTraceCategory, "ProcessMemoryDump", | 797 TRACE_EVENT_NESTABLE_ASYNC_END0(kTraceCategory, "ProcessMemoryDump", |
| 784 TRACE_ID_LOCAL(dump_guid)); | 798 TRACE_ID_LOCAL(dump_guid)); |
| 785 } | 799 } |
| 786 | 800 |
| 787 void MemoryDumpManager::Enable( | 801 void MemoryDumpManager::Enable( |
| 788 const TraceConfig::MemoryDumpConfig& memory_dump_config) { | 802 const TraceConfig::MemoryDumpConfig& memory_dump_config) { |
| 789 // Spin-up the thread used to invoke unbound dump providers. | |
| 790 std::unique_ptr<Thread> dump_thread(new Thread("MemoryInfra")); | |
| 791 if (!dump_thread->Start()) { | |
| 792 LOG(ERROR) << "Failed to start the memory-infra thread for tracing"; | |
| 793 return; | |
| 794 } | |
| 795 | 803 |
| 796 scoped_refptr<MemoryDumpSessionState> session_state = | 804 scoped_refptr<MemoryDumpSessionState> session_state = |
| 797 new MemoryDumpSessionState; | 805 new MemoryDumpSessionState; |
| 798 session_state->SetAllowedDumpModes(memory_dump_config.allowed_dump_modes); | 806 session_state->SetAllowedDumpModes(memory_dump_config.allowed_dump_modes); |
| 799 session_state->set_heap_profiler_breakdown_threshold_bytes( | 807 session_state->set_heap_profiler_breakdown_threshold_bytes( |
| 800 memory_dump_config.heap_profiler_options.breakdown_threshold_bytes); | 808 memory_dump_config.heap_profiler_options.breakdown_threshold_bytes); |
| 801 if (heap_profiling_enabled_) { | 809 if (heap_profiling_enabled_) { |
| 802 // If heap profiling is enabled, the stack frame deduplicator and type name | 810 // If heap profiling is enabled, the stack frame deduplicator and type name |
| 803 // deduplicator will be in use. Add a metadata events to write the frames | 811 // deduplicator will be in use. Add a metadata events to write the frames |
| 804 // and type IDs. | 812 // and type IDs. |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 819 "typeNames", | 827 "typeNames", |
| 820 MakeUnique<SessionStateConvertableProxy<TypeNameDeduplicator>>( | 828 MakeUnique<SessionStateConvertableProxy<TypeNameDeduplicator>>( |
| 821 session_state, &MemoryDumpSessionState::type_name_deduplicator)); | 829 session_state, &MemoryDumpSessionState::type_name_deduplicator)); |
| 822 } | 830 } |
| 823 | 831 |
| 824 AutoLock lock(lock_); | 832 AutoLock lock(lock_); |
| 825 | 833 |
| 826 DCHECK(delegate_); // At this point we must have a delegate. | 834 DCHECK(delegate_); // At this point we must have a delegate. |
| 827 session_state_ = session_state; | 835 session_state_ = session_state; |
| 828 | 836 |
| 829 DCHECK(!dump_thread_); | |
| 830 dump_thread_ = std::move(dump_thread); | |
| 831 | |
| 832 subtle::NoBarrier_Store(&memory_tracing_enabled_, 1); | 837 subtle::NoBarrier_Store(&memory_tracing_enabled_, 1); |
| 833 | 838 |
| 834 MemoryDumpScheduler::Config periodic_config; | 839 MemoryDumpScheduler::Config periodic_config; |
| 835 bool peak_detector_configured = false; | 840 bool peak_detector_configured = false; |
| 836 for (const auto& trigger : memory_dump_config.triggers) { | 841 for (const auto& trigger : memory_dump_config.triggers) { |
| 837 if (!session_state_->IsDumpModeAllowed(trigger.level_of_detail)) { | 842 if (!session_state_->IsDumpModeAllowed(trigger.level_of_detail)) { |
| 838 NOTREACHED(); | 843 NOTREACHED(); |
| 839 continue; | 844 continue; |
| 840 } | 845 } |
| 841 if (trigger.trigger_type == MemoryDumpType::PERIODIC_INTERVAL) { | 846 if (trigger.trigger_type == MemoryDumpType::PERIODIC_INTERVAL) { |
| 842 if (periodic_config.triggers.empty()) { | 847 if (periodic_config.triggers.empty()) { |
| 843 periodic_config.callback = BindRepeating(&OnPeriodicSchedulerTick); | 848 periodic_config.callback = BindRepeating(&OnPeriodicSchedulerTick); |
| 844 } | 849 } |
| 845 periodic_config.triggers.push_back( | 850 periodic_config.triggers.push_back( |
| 846 {trigger.level_of_detail, trigger.min_time_between_dumps_ms}); | 851 {trigger.level_of_detail, trigger.min_time_between_dumps_ms}); |
| 847 } else if (trigger.trigger_type == MemoryDumpType::PEAK_MEMORY_USAGE) { | 852 } else if (trigger.trigger_type == MemoryDumpType::PEAK_MEMORY_USAGE) { |
| 848 // At most one peak trigger is allowed. | 853 // At most one peak trigger is allowed. |
| 849 CHECK(!peak_detector_configured); | 854 CHECK(!peak_detector_configured); |
| 850 peak_detector_configured = true; | 855 peak_detector_configured = true; |
| 851 MemoryPeakDetector::GetInstance()->Setup( | 856 MemoryPeakDetector::GetInstance()->Setup( |
| 852 BindRepeating(&MemoryDumpManager::GetDumpProvidersForPolling, | 857 BindRepeating(&MemoryDumpManager::GetDumpProvidersForPolling, |
| 853 Unretained(this)), | 858 Unretained(this)), |
| 854 dump_thread_->task_runner(), | 859 GetTaskRunner(), |
| 855 BindRepeating(&OnPeakDetected, trigger.level_of_detail)); | 860 BindRepeating(&OnPeakDetected, trigger.level_of_detail)); |
| 856 | 861 |
| 857 MemoryPeakDetector::Config peak_config; | 862 MemoryPeakDetector::Config peak_config; |
| 858 peak_config.polling_interval_ms = 10; | 863 peak_config.polling_interval_ms = 10; |
| 859 peak_config.min_time_between_peaks_ms = trigger.min_time_between_dumps_ms; | 864 peak_config.min_time_between_peaks_ms = trigger.min_time_between_dumps_ms; |
| 860 peak_config.enable_verbose_poll_tracing = | 865 peak_config.enable_verbose_poll_tracing = |
| 861 trigger.level_of_detail == MemoryDumpLevelOfDetail::DETAILED; | 866 trigger.level_of_detail == MemoryDumpLevelOfDetail::DETAILED; |
| 862 MemoryPeakDetector::GetInstance()->Start(peak_config); | 867 MemoryPeakDetector::GetInstance()->Start(peak_config); |
| 863 | 868 |
| 864 // When peak detection is enabled, trigger a dump straight away as it | 869 // When peak detection is enabled, trigger a dump straight away as it |
| 865 // gives a good reference point for analyzing the trace. | 870 // gives a good reference point for analyzing the trace. |
| 866 if (delegate_->IsCoordinator()) { | 871 if (delegate_->IsCoordinator()) { |
| 867 dump_thread_->task_runner()->PostTask( | 872 GetTaskRunner()->PostTask( |
| 868 FROM_HERE, BindRepeating(&OnPeakDetected, trigger.level_of_detail)); | 873 FROM_HERE, BindRepeating(&OnPeakDetected, trigger.level_of_detail)); |
| 869 } | 874 } |
| 870 } | 875 } |
| 871 } | 876 } |
| 872 | 877 |
| 873 // Only coordinator process triggers periodic global memory dumps. | 878 // Only coordinator process triggers periodic global memory dumps. |
| 874 if (delegate_->IsCoordinator() && !periodic_config.triggers.empty()) { | 879 if (delegate_->IsCoordinator() && !periodic_config.triggers.empty()) { |
| 875 MemoryDumpScheduler::GetInstance()->Start(periodic_config, | 880 MemoryDumpScheduler::GetInstance()->Start(periodic_config, GetTaskRunner()); |
| 876 dump_thread_->task_runner()); | |
| 877 } | 881 } |
| 878 } | 882 } |
| 879 | 883 |
| 880 void MemoryDumpManager::Disable() { | 884 void MemoryDumpManager::Disable() { |
| 881 // There might be a memory dump in progress while this happens. Therefore, | 885 // There might be a memory dump in progress while this happens. Therefore, |
| 882 // ensure that the MDM state which depends on the tracing enabled / disabled | 886 // ensure that the MDM state which depends on the tracing enabled / disabled |
| 883 // state is always accessed by the dumping methods holding the |lock_|. | 887 // state is always accessed by the dumping methods holding the |lock_|. |
| 884 if (!subtle::NoBarrier_Load(&memory_tracing_enabled_)) | 888 if (!subtle::NoBarrier_Load(&memory_tracing_enabled_)) |
| 885 return; | 889 return; |
| 886 subtle::NoBarrier_Store(&memory_tracing_enabled_, 0); | 890 subtle::NoBarrier_Store(&memory_tracing_enabled_, 0); |
| 887 std::unique_ptr<Thread> dump_thread; | |
| 888 { | 891 { |
| 889 AutoLock lock(lock_); | 892 AutoLock lock(lock_); |
| 890 MemoryDumpScheduler::GetInstance()->Stop(); | 893 MemoryDumpScheduler::GetInstance()->Stop(); |
| 891 MemoryPeakDetector::GetInstance()->TearDown(); | 894 MemoryPeakDetector::GetInstance()->TearDown(); |
| 892 dump_thread = std::move(dump_thread_); | |
| 893 session_state_ = nullptr; | 895 session_state_ = nullptr; |
| 894 } | 896 } |
| 895 | |
| 896 // Thread stops are blocking and must be performed outside of the |lock_| | |
| 897 // or will deadlock (e.g., if SetupNextMemoryDump() tries to acquire it). | |
| 898 if (dump_thread) | |
| 899 dump_thread->Stop(); | |
|
Primiano Tucci (use gerrit)
2017/04/24 15:30:58
\o/ This, as a side effect, should fix crbug.com/7
hjd
2017/04/24 16:27:59
Done.
ssid
2017/04/25 03:21:47
Yay
| |
| 900 } | 897 } |
| 901 | 898 |
| 902 bool MemoryDumpManager::IsDumpModeAllowed(MemoryDumpLevelOfDetail dump_mode) { | 899 bool MemoryDumpManager::IsDumpModeAllowed(MemoryDumpLevelOfDetail dump_mode) { |
| 903 AutoLock lock(lock_); | 900 AutoLock lock(lock_); |
| 904 if (!session_state_) | 901 if (!session_state_) |
| 905 return false; | 902 return false; |
| 906 return session_state_->IsDumpModeAllowed(dump_mode); | 903 return session_state_->IsDumpModeAllowed(dump_mode); |
| 907 } | 904 } |
| 908 | 905 |
| 909 MemoryDumpManager::ProcessMemoryDumpAsyncState::ProcessMemoryDumpAsyncState( | 906 MemoryDumpManager::ProcessMemoryDumpAsyncState::ProcessMemoryDumpAsyncState( |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 932 if (iter == process_dumps.end()) { | 929 if (iter == process_dumps.end()) { |
| 933 std::unique_ptr<ProcessMemoryDump> new_pmd( | 930 std::unique_ptr<ProcessMemoryDump> new_pmd( |
| 934 new ProcessMemoryDump(session_state, dump_args)); | 931 new ProcessMemoryDump(session_state, dump_args)); |
| 935 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; | 932 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; |
| 936 } | 933 } |
| 937 return iter->second.get(); | 934 return iter->second.get(); |
| 938 } | 935 } |
| 939 | 936 |
| 940 } // namespace trace_event | 937 } // namespace trace_event |
| 941 } // namespace base | 938 } // namespace base |
| OLD | NEW |