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 | 8 |
| 9 #include "base/atomic_sequence_num.h" |
9 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
10 #include "base/trace_event/memory_dump_provider.h" | 11 #include "base/trace_event/memory_dump_provider.h" |
11 #include "base/trace_event/process_memory_dump.h" | 12 #include "base/trace_event/process_memory_dump.h" |
12 #include "base/trace_event/trace_event_argument.h" | 13 #include "base/trace_event/trace_event_argument.h" |
13 | 14 |
14 namespace base { | 15 namespace base { |
15 namespace trace_event { | 16 namespace trace_event { |
16 | 17 |
17 namespace { | 18 namespace { |
| 19 |
18 MemoryDumpManager* g_instance_for_testing = nullptr; | 20 MemoryDumpManager* g_instance_for_testing = nullptr; |
| 21 const int kTraceEventNumArgs = 1; |
| 22 const char* kTraceEventArgNames[] = {"dumps"}; |
| 23 const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE}; |
| 24 StaticAtomicSequenceNumber g_next_guid; |
| 25 |
| 26 const char* DumpPointTypeToString(const DumpPointType& dump_point_type) { |
| 27 switch (dump_point_type) { |
| 28 case DumpPointType::TASK_BEGIN: |
| 29 return "TASK_BEGIN"; |
| 30 case DumpPointType::TASK_END: |
| 31 return "TASK_END"; |
| 32 case DumpPointType::PERIODIC_INTERVAL: |
| 33 return "PERIODIC_INTERVAL"; |
| 34 case DumpPointType::EXPLICITLY_TRIGGERED: |
| 35 return "EXPLICITLY_TRIGGERED"; |
| 36 } |
| 37 NOTREACHED(); |
| 38 return "UNKNOWN"; |
| 39 } |
19 } | 40 } |
20 | 41 |
21 // TODO(primiano): this should be smarter and should do something similar to | 42 // TODO(primiano): this should be smarter and should do something similar to |
22 // trace event synthetic delays. | 43 // trace event synthetic delays. |
23 const char MemoryDumpManager::kTraceCategory[] = | 44 const char MemoryDumpManager::kTraceCategory[] = |
24 TRACE_DISABLED_BY_DEFAULT("memory-dumps"); | 45 TRACE_DISABLED_BY_DEFAULT("memory-dumps"); |
25 | 46 |
26 // static | 47 // static |
27 MemoryDumpManager* MemoryDumpManager::GetInstance() { | 48 MemoryDumpManager* MemoryDumpManager::GetInstance() { |
28 if (g_instance_for_testing) | 49 if (g_instance_for_testing) |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 dump_providers_registered_.erase(it); | 90 dump_providers_registered_.erase(it); |
70 | 91 |
71 // Remove from the enabled providers list. This is to deal with the case that | 92 // Remove from the enabled providers list. This is to deal with the case that |
72 // UnregisterDumpProvider is called while the trace is enabled. | 93 // UnregisterDumpProvider is called while the trace is enabled. |
73 it = std::find(dump_providers_enabled_.begin(), dump_providers_enabled_.end(), | 94 it = std::find(dump_providers_enabled_.begin(), dump_providers_enabled_.end(), |
74 mdp); | 95 mdp); |
75 if (it != dump_providers_enabled_.end()) | 96 if (it != dump_providers_enabled_.end()) |
76 dump_providers_enabled_.erase(it); | 97 dump_providers_enabled_.erase(it); |
77 } | 98 } |
78 | 99 |
79 void MemoryDumpManager::RequestDumpPoint(DumpPointType type) { | 100 void MemoryDumpManager::RequestDumpPoint(DumpPointType dump_point_type) { |
80 // TODO(primiano): this will have more logic, IPC broadcast & co. | 101 // TODO(primiano): this will have more logic to coordinate dump points across |
| 102 // multiple processes via IPC. See crbug.com/462930. |
| 103 |
81 // Bail out immediately if tracing is not enabled at all. | 104 // Bail out immediately if tracing is not enabled at all. |
82 if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_))) | 105 if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_))) |
83 return; | 106 return; |
84 | 107 |
85 CreateLocalDumpPoint(); | 108 // TODO(primiano): Make guid actually unique (cross-process) by hashing it |
| 109 // with the PID. See crbug.com/462931 for details. |
| 110 const uint64 guid = g_next_guid.GetNext(); |
| 111 CreateLocalDumpPoint(dump_point_type, guid); |
86 } | 112 } |
87 | 113 |
88 void MemoryDumpManager::BroadcastDumpRequest() { | 114 void MemoryDumpManager::BroadcastDumpRequest() { |
89 NOTREACHED(); // TODO(primiano): implement IPC synchronization. | 115 NOTREACHED(); // TODO(primiano): implement IPC synchronization. |
90 } | 116 } |
91 | 117 |
92 // Creates a dump point for the current process and appends it to the trace. | 118 // Creates a dump point for the current process and appends it to the trace. |
93 void MemoryDumpManager::CreateLocalDumpPoint() { | 119 void MemoryDumpManager::CreateLocalDumpPoint(DumpPointType dump_point_type, |
94 AutoLock lock(lock_); | 120 uint64 guid) { |
| 121 bool did_any_provider_dump = false; |
95 scoped_ptr<ProcessMemoryDump> pmd(new ProcessMemoryDump()); | 122 scoped_ptr<ProcessMemoryDump> pmd(new ProcessMemoryDump()); |
96 | 123 |
97 for (MemoryDumpProvider* dump_provider : dump_providers_enabled_) { | 124 // Serialize dump point generation so that memory dump providers don't have to |
98 dump_provider->DumpInto(pmd.get()); | 125 // deal with thread safety. |
| 126 { |
| 127 AutoLock lock(lock_); |
| 128 for (auto it = dump_providers_enabled_.begin(); |
| 129 it != dump_providers_enabled_.end();) { |
| 130 MemoryDumpProvider* dump_provider = *it; |
| 131 if (dump_provider->DumpInto(pmd.get())) { |
| 132 did_any_provider_dump = true; |
| 133 ++it; |
| 134 } else { |
| 135 LOG(ERROR) << "The memory dumper " << dump_provider->GetFriendlyName() |
| 136 << " failed, possibly due to sandboxing (crbug.com/461788), " |
| 137 "disabling it for current process. Try restarting chrome " |
| 138 "with the --no-sandbox switch."; |
| 139 it = dump_providers_enabled_.erase(it); |
| 140 } |
| 141 } |
99 } | 142 } |
100 | 143 |
101 scoped_refptr<TracedValue> value(new TracedValue()); | 144 // Don't create a dump point if all the dumpers failed. |
102 pmd->AsValueInto(value.get()); | 145 if (!did_any_provider_dump) |
103 // TODO(primiano): add the dump point to the trace at this point. | 146 return; |
| 147 |
| 148 scoped_refptr<ConvertableToTraceFormat> event_value(new TracedValue()); |
| 149 pmd->AsValueInto(static_cast<TracedValue*>(event_value.get())); |
| 150 const char* const event_name = DumpPointTypeToString(dump_point_type); |
| 151 |
| 152 TRACE_EVENT_API_ADD_TRACE_EVENT( |
| 153 TRACE_EVENT_PHASE_MEMORY_DUMP, |
| 154 TraceLog::GetCategoryGroupEnabled(kTraceCategory), event_name, guid, |
| 155 kTraceEventNumArgs, kTraceEventArgNames, kTraceEventArgTypes, |
| 156 NULL /* arg_values */, &event_value, TRACE_EVENT_FLAG_HAS_ID); |
104 } | 157 } |
105 | 158 |
106 void MemoryDumpManager::OnTraceLogEnabled() { | 159 void MemoryDumpManager::OnTraceLogEnabled() { |
107 // TODO(primiano): at this point we query TraceLog::GetCurrentCategoryFilter | 160 // TODO(primiano): at this point we query TraceLog::GetCurrentCategoryFilter |
108 // to figure out (and cache) which dumpers should be enabled or not. | 161 // to figure out (and cache) which dumpers should be enabled or not. |
109 // For the moment piggy back everything on the generic "memory" category. | 162 // For the moment piggy back everything on the generic "memory" category. |
110 bool enabled; | 163 bool enabled; |
111 TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &enabled); | 164 TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &enabled); |
112 | 165 |
113 AutoLock lock(lock_); | 166 AutoLock lock(lock_); |
114 if (enabled) { | 167 if (enabled) { |
115 dump_providers_enabled_.assign(dump_providers_registered_.begin(), | 168 dump_providers_enabled_.assign(dump_providers_registered_.begin(), |
116 dump_providers_registered_.end()); | 169 dump_providers_registered_.end()); |
117 } else { | 170 } else { |
118 dump_providers_enabled_.clear(); | 171 dump_providers_enabled_.clear(); |
119 } | 172 } |
120 subtle::NoBarrier_Store(&memory_tracing_enabled_, 1); | 173 subtle::NoBarrier_Store(&memory_tracing_enabled_, 1); |
121 } | 174 } |
122 | 175 |
123 void MemoryDumpManager::OnTraceLogDisabled() { | 176 void MemoryDumpManager::OnTraceLogDisabled() { |
124 AutoLock lock(lock_); | 177 AutoLock lock(lock_); |
125 dump_providers_enabled_.clear(); | 178 dump_providers_enabled_.clear(); |
126 subtle::NoBarrier_Store(&memory_tracing_enabled_, 0); | 179 subtle::NoBarrier_Store(&memory_tracing_enabled_, 0); |
127 } | 180 } |
128 | 181 |
129 } // namespace trace_event | 182 } // namespace trace_event |
130 } // namespace base | 183 } // namespace base |
OLD | NEW |