| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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 "services/resource_coordinator/memory/coordinator/coordinator_impl.h" | 5 #include "services/resource_coordinator/memory/coordinator/coordinator_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 9 #include "base/location.h" | 9 #include "base/location.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 | 27 |
| 28 // static | 28 // static |
| 29 CoordinatorImpl* CoordinatorImpl::GetInstance() { | 29 CoordinatorImpl* CoordinatorImpl::GetInstance() { |
| 30 return g_coordinator_impl; | 30 return g_coordinator_impl; |
| 31 } | 31 } |
| 32 | 32 |
| 33 CoordinatorImpl::CoordinatorImpl(bool initialize_memory_dump_manager) | 33 CoordinatorImpl::CoordinatorImpl(bool initialize_memory_dump_manager) |
| 34 : failed_memory_dump_count_(0), | 34 : failed_memory_dump_count_(0), |
| 35 initialize_memory_dump_manager_(initialize_memory_dump_manager) { | 35 initialize_memory_dump_manager_(initialize_memory_dump_manager) { |
| 36 if (initialize_memory_dump_manager) { | 36 if (initialize_memory_dump_manager) { |
| 37 // TODO(primiano): the current state where the coordinator also creates a |
| 38 // client (ProcessLocalDumpManagerImpl) is contra-intuitive. BrowserMainLoop |
| 39 // should be doing this. |
| 37 ProcessLocalDumpManagerImpl::CreateInstance( | 40 ProcessLocalDumpManagerImpl::CreateInstance( |
| 38 ProcessLocalDumpManagerImpl::Config(this)); | 41 ProcessLocalDumpManagerImpl::Config(this, mojom::ProcessType::BROWSER)); |
| 39 base::trace_event::MemoryDumpManager::GetInstance()->set_tracing_process_id( | 42 base::trace_event::MemoryDumpManager::GetInstance()->set_tracing_process_id( |
| 40 mojom::kServiceTracingProcessId); | 43 mojom::kServiceTracingProcessId); |
| 41 } | 44 } |
| 42 g_coordinator_impl = this; | 45 g_coordinator_impl = this; |
| 43 } | 46 } |
| 44 | 47 |
| 45 CoordinatorImpl::~CoordinatorImpl() { | 48 CoordinatorImpl::~CoordinatorImpl() { |
| 46 g_coordinator_impl = nullptr; | 49 g_coordinator_impl = nullptr; |
| 47 } | 50 } |
| 48 | 51 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 74 base::trace_event::MemoryDumpType::EXPLICITLY_TRIGGERED) { | 77 base::trace_event::MemoryDumpType::EXPLICITLY_TRIGGERED) { |
| 75 for (const auto& request : queued_memory_dump_requests_) { | 78 for (const auto& request : queued_memory_dump_requests_) { |
| 76 if (request.args.level_of_detail == args.level_of_detail) { | 79 if (request.args.level_of_detail == args.level_of_detail) { |
| 77 VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix << " (" | 80 VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix << " (" |
| 78 << base::trace_event::MemoryDumpTypeToString(args.dump_type) | 81 << base::trace_event::MemoryDumpTypeToString(args.dump_type) |
| 79 << ") skipped because another dump request with the same " | 82 << ") skipped because another dump request with the same " |
| 80 "level of detail (" | 83 "level of detail (" |
| 81 << base::trace_event::MemoryDumpLevelOfDetailToString( | 84 << base::trace_event::MemoryDumpLevelOfDetailToString( |
| 82 args.level_of_detail) | 85 args.level_of_detail) |
| 83 << ") is already in the queue"; | 86 << ") is already in the queue"; |
| 84 callback.Run(args.dump_guid, false /* success */); | 87 callback.Run(args.dump_guid, false /* success */, |
| 88 nullptr /* global_memory_dump */); |
| 85 return; | 89 return; |
| 86 } | 90 } |
| 87 } | 91 } |
| 88 } | 92 } |
| 89 | 93 |
| 90 queued_memory_dump_requests_.emplace_back(args, callback); | 94 queued_memory_dump_requests_.emplace_back(args, callback); |
| 91 | 95 |
| 92 // If another dump is already in progress, this dump will automatically be | 96 // If another dump is already in progress, this dump will automatically be |
| 93 // scheduled when the other dump finishes. | 97 // scheduled when the other dump finishes. |
| 94 if (another_dump_already_in_progress) | 98 if (another_dump_already_in_progress) |
| (...skipping 19 matching lines...) Expand all Loading... |
| 114 mojom::ProcessLocalDumpManager* process_manager) { | 118 mojom::ProcessLocalDumpManager* process_manager) { |
| 115 size_t num_deleted = process_managers_.erase(process_manager); | 119 size_t num_deleted = process_managers_.erase(process_manager); |
| 116 DCHECK(num_deleted == 1); | 120 DCHECK(num_deleted == 1); |
| 117 | 121 |
| 118 // Check if we are waiting for an ack from this process-local manager. | 122 // Check if we are waiting for an ack from this process-local manager. |
| 119 if (pending_process_managers_.find(process_manager) != | 123 if (pending_process_managers_.find(process_manager) != |
| 120 pending_process_managers_.end()) { | 124 pending_process_managers_.end()) { |
| 121 DCHECK(!queued_memory_dump_requests_.empty()); | 125 DCHECK(!queued_memory_dump_requests_.empty()); |
| 122 OnProcessMemoryDumpResponse( | 126 OnProcessMemoryDumpResponse( |
| 123 process_manager, queued_memory_dump_requests_.front().args.dump_guid, | 127 process_manager, queued_memory_dump_requests_.front().args.dump_guid, |
| 124 false /* success */, | 128 false /* success */, nullptr /* process_memory_dump */); |
| 125 base::Optional<base::trace_event::MemoryDumpCallbackResult>()); | |
| 126 } | 129 } |
| 127 } | 130 } |
| 128 | 131 |
| 129 void CoordinatorImpl::PerformNextQueuedGlobalMemoryDump() { | 132 void CoordinatorImpl::PerformNextQueuedGlobalMemoryDump() { |
| 130 DCHECK(!queued_memory_dump_requests_.empty()); | 133 DCHECK(!queued_memory_dump_requests_.empty()); |
| 131 const base::trace_event::MemoryDumpRequestArgs& args = | 134 const base::trace_event::MemoryDumpRequestArgs& args = |
| 132 queued_memory_dump_requests_.front().args; | 135 queued_memory_dump_requests_.front().args; |
| 133 | 136 |
| 134 // No need to treat the service process different than other processes. The | 137 // No need to treat the service process different than other processes. The |
| 135 // service process will register itself as a ProcessLocalDumpManager and will | 138 // service process will register itself as a ProcessLocalDumpManager and will |
| 136 // be treated like other process-local managers. | 139 // be treated like other process-local managers. |
| 137 pending_process_managers_.clear(); | 140 pending_process_managers_.clear(); |
| 138 failed_memory_dump_count_ = 0; | 141 failed_memory_dump_count_ = 0; |
| 139 for (const auto& key_value : process_managers_) { | 142 for (const auto& key_value : process_managers_) { |
| 140 pending_process_managers_.insert(key_value.first); | 143 pending_process_managers_.insert(key_value.first); |
| 141 auto callback = base::Bind(&CoordinatorImpl::OnProcessMemoryDumpResponse, | 144 auto callback = base::Bind(&CoordinatorImpl::OnProcessMemoryDumpResponse, |
| 142 base::Unretained(this), key_value.first); | 145 base::Unretained(this), key_value.first); |
| 143 key_value.second->RequestProcessMemoryDump(args, callback); | 146 key_value.second->RequestProcessMemoryDump(args, callback); |
| 144 } | 147 } |
| 145 // Run the callback in case there are no process-local managers. | 148 // Run the callback in case there are no process-local managers. |
| 146 FinalizeGlobalMemoryDumpIfAllManagersReplied(); | 149 FinalizeGlobalMemoryDumpIfAllManagersReplied(); |
| 147 } | 150 } |
| 148 | 151 |
| 149 void CoordinatorImpl::OnProcessMemoryDumpResponse( | 152 void CoordinatorImpl::OnProcessMemoryDumpResponse( |
| 150 mojom::ProcessLocalDumpManager* process_manager, | 153 mojom::ProcessLocalDumpManager* process_manager, |
| 151 uint64_t dump_guid, | 154 uint64_t dump_guid, |
| 152 bool success, | 155 bool success, |
| 153 const base::Optional<base::trace_event::MemoryDumpCallbackResult>& result) { | 156 mojom::ProcessMemoryDumpPtr process_memory_dump) { |
| 154 auto it = pending_process_managers_.find(process_manager); | 157 auto it = pending_process_managers_.find(process_manager); |
| 155 | 158 |
| 156 DCHECK(!queued_memory_dump_requests_.empty()); | 159 if (queued_memory_dump_requests_.empty() || |
| 157 if (queued_memory_dump_requests_.front().args.dump_guid != dump_guid || | 160 queued_memory_dump_requests_.front().args.dump_guid != dump_guid || |
| 158 it == pending_process_managers_.end()) { | 161 it == pending_process_managers_.end()) { |
| 159 VLOG(1) << "Received unexpected memory dump response: " << dump_guid; | 162 VLOG(1) << "Received unexpected memory dump response: " << dump_guid; |
| 160 return; | 163 return; |
| 161 } | 164 } |
| 165 if (process_memory_dump) { |
| 166 queued_memory_dump_requests_.front().process_memory_dumps.push_back( |
| 167 std::move(process_memory_dump)); |
| 168 } |
| 169 |
| 162 pending_process_managers_.erase(it); | 170 pending_process_managers_.erase(it); |
| 163 | 171 |
| 164 if (!success) { | 172 if (!success) { |
| 165 ++failed_memory_dump_count_; | 173 ++failed_memory_dump_count_; |
| 166 VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix | 174 VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix |
| 167 << " failed because of NACK from provider"; | 175 << " failed because of NACK from provider"; |
| 168 } | 176 } |
| 177 |
| 169 FinalizeGlobalMemoryDumpIfAllManagersReplied(); | 178 FinalizeGlobalMemoryDumpIfAllManagersReplied(); |
| 170 } | 179 } |
| 171 | 180 |
| 172 void CoordinatorImpl::FinalizeGlobalMemoryDumpIfAllManagersReplied() { | 181 void CoordinatorImpl::FinalizeGlobalMemoryDumpIfAllManagersReplied() { |
| 173 if (pending_process_managers_.size() > 0) | 182 if (pending_process_managers_.size() > 0) |
| 174 return; | 183 return; |
| 175 | 184 |
| 176 DCHECK(!queued_memory_dump_requests_.empty()); | 185 if (queued_memory_dump_requests_.empty()) { |
| 177 { | 186 NOTREACHED(); |
| 178 const auto& callback = queued_memory_dump_requests_.front().callback; | 187 return; |
| 179 const bool global_success = failed_memory_dump_count_ == 0; | |
| 180 callback.Run(queued_memory_dump_requests_.front().args.dump_guid, | |
| 181 global_success); | |
| 182 } | 188 } |
| 189 |
| 190 // TODO(hjd,fmeawad): At this point the |process_memory_dumps| accumulated in |
| 191 // queued_memory_dump_requests_.front() should be normalized (merge |
| 192 // |extra_process_dump|, compute CMM) into a GlobalMemoryDumpPtr and passed |
| 193 // below. |
| 194 |
| 195 const auto& callback = queued_memory_dump_requests_.front().callback; |
| 196 const bool global_success = failed_memory_dump_count_ == 0; |
| 197 callback.Run(queued_memory_dump_requests_.front().args.dump_guid, |
| 198 global_success, nullptr /* global_memory_dump */); |
| 183 queued_memory_dump_requests_.pop_front(); | 199 queued_memory_dump_requests_.pop_front(); |
| 184 | 200 |
| 185 // Schedule the next queued dump (if applicable). | 201 // Schedule the next queued dump (if applicable). |
| 186 if (!queued_memory_dump_requests_.empty()) { | 202 if (!queued_memory_dump_requests_.empty()) { |
| 187 base::ThreadTaskRunnerHandle::Get()->PostTask( | 203 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 188 FROM_HERE, | 204 FROM_HERE, |
| 189 base::Bind(&CoordinatorImpl::PerformNextQueuedGlobalMemoryDump, | 205 base::Bind(&CoordinatorImpl::PerformNextQueuedGlobalMemoryDump, |
| 190 base::Unretained(this))); | 206 base::Unretained(this))); |
| 191 } | 207 } |
| 192 } | 208 } |
| 193 | 209 |
| 194 } // namespace memory_instrumentation | 210 } // namespace memory_instrumentation |
| OLD | NEW |