| 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/malloc_dump_provider.h" | 5 #include "base/trace_event/malloc_dump_provider.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include "base/allocator/allocator_extension.h" | 9 #include "base/allocator/allocator_extension.h" |
| 10 #include "base/allocator/allocator_shim.h" | 10 #include "base/allocator/allocator_shim.h" |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 struct WinHeapInfo { | 98 struct WinHeapInfo { |
| 99 HANDLE heap_id; | 99 HANDLE heap_id; |
| 100 size_t committed_size; | 100 size_t committed_size; |
| 101 size_t uncommitted_size; | 101 size_t uncommitted_size; |
| 102 size_t allocated_size; | 102 size_t allocated_size; |
| 103 size_t block_count; | 103 size_t block_count; |
| 104 }; | 104 }; |
| 105 | 105 |
| 106 bool GetHeapInformation(WinHeapInfo* heap_info, | 106 bool GetHeapInformation(WinHeapInfo* heap_info, |
| 107 const std::set<void*>& block_to_skip) { | 107 const std::set<void*>& block_to_skip) { |
| 108 CHECK(::HeapLock(heap_info->heap_id) == TRUE); | 108 // NOTE: crbug.com/464430 |
| 109 // As a part of the Client/Server Runtine Subsystem (CSRSS) lockdown in the |
| 110 // referenced bug, it will invalidate the heap used by CSRSS. The author has |
| 111 // not found a way to clean up an invalid heap handle, so it will be left in |
| 112 // the process's heap list. Therefore we need to support when there is this |
| 113 // invalid heap handle in the heap list. |
| 114 // HeapLock implicitly checks certain aspects of the HEAP structure, such as |
| 115 // the signature. If this passes, we assume that this heap is valid and is |
| 116 // not the one owned by CSRSS. |
| 117 if (!::HeapLock(heap_info->heap_id)) { |
| 118 return false; |
| 119 } |
| 109 PROCESS_HEAP_ENTRY heap_entry; | 120 PROCESS_HEAP_ENTRY heap_entry; |
| 110 heap_entry.lpData = nullptr; | 121 heap_entry.lpData = nullptr; |
| 111 // Walk over all the entries in this heap. | 122 // Walk over all the entries in this heap. |
| 112 while (::HeapWalk(heap_info->heap_id, &heap_entry) != FALSE) { | 123 while (::HeapWalk(heap_info->heap_id, &heap_entry) != FALSE) { |
| 113 if (block_to_skip.count(heap_entry.lpData) == 1) | 124 if (block_to_skip.count(heap_entry.lpData) == 1) |
| 114 continue; | 125 continue; |
| 115 if ((heap_entry.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0) { | 126 if ((heap_entry.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0) { |
| 116 heap_info->allocated_size += heap_entry.cbData; | 127 heap_info->allocated_size += heap_entry.cbData; |
| 117 heap_info->block_count++; | 128 heap_info->block_count++; |
| 118 } else if ((heap_entry.wFlags & PROCESS_HEAP_REGION) != 0) { | 129 } else if ((heap_entry.wFlags & PROCESS_HEAP_REGION) != 0) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 std::unique_ptr<HANDLE[]> all_heaps(new HANDLE[number_of_heaps]); | 165 std::unique_ptr<HANDLE[]> all_heaps(new HANDLE[number_of_heaps]); |
| 155 if (::GetProcessHeaps(number_of_heaps, all_heaps.get()) != number_of_heaps) | 166 if (::GetProcessHeaps(number_of_heaps, all_heaps.get()) != number_of_heaps) |
| 156 return; | 167 return; |
| 157 | 168 |
| 158 // Skip the pointer to the heap array to avoid accounting the memory used by | 169 // Skip the pointer to the heap array to avoid accounting the memory used by |
| 159 // this dump provider. | 170 // this dump provider. |
| 160 std::set<void*> block_to_skip; | 171 std::set<void*> block_to_skip; |
| 161 block_to_skip.insert(all_heaps.get()); | 172 block_to_skip.insert(all_heaps.get()); |
| 162 | 173 |
| 163 // Retrieves some metrics about each heap. | 174 // Retrieves some metrics about each heap. |
| 175 size_t heap_info_errors = 0; |
| 164 for (size_t i = 0; i < number_of_heaps; ++i) { | 176 for (size_t i = 0; i < number_of_heaps; ++i) { |
| 165 WinHeapInfo heap_info = {0}; | 177 WinHeapInfo heap_info = {0}; |
| 166 heap_info.heap_id = all_heaps[i]; | 178 heap_info.heap_id = all_heaps[i]; |
| 167 GetHeapInformation(&heap_info, block_to_skip); | 179 if (GetHeapInformation(&heap_info, block_to_skip)) { |
| 168 | 180 all_heap_info->allocated_size += heap_info.allocated_size; |
| 169 all_heap_info->allocated_size += heap_info.allocated_size; | 181 all_heap_info->committed_size += heap_info.committed_size; |
| 170 all_heap_info->committed_size += heap_info.committed_size; | 182 all_heap_info->uncommitted_size += heap_info.uncommitted_size; |
| 171 all_heap_info->uncommitted_size += heap_info.uncommitted_size; | 183 all_heap_info->block_count += heap_info.block_count; |
| 172 all_heap_info->block_count += heap_info.block_count; | 184 } else { |
| 185 ++heap_info_errors; |
| 186 // See notes in GetHeapInformation() but we only expect 1 heap to not be |
| 187 // able to be read. |
| 188 CHECK_EQ(1u, heap_info_errors); |
| 189 } |
| 173 } | 190 } |
| 174 } | 191 } |
| 175 #endif // defined(OS_WIN) | 192 #endif // defined(OS_WIN) |
| 176 } // namespace | 193 } // namespace |
| 177 | 194 |
| 178 // static | 195 // static |
| 179 const char MallocDumpProvider::kAllocatedObjects[] = "malloc/allocated_objects"; | 196 const char MallocDumpProvider::kAllocatedObjects[] = "malloc/allocated_objects"; |
| 180 | 197 |
| 181 // static | 198 // static |
| 182 MallocDumpProvider* MallocDumpProvider::GetInstance() { | 199 MallocDumpProvider* MallocDumpProvider::GetInstance() { |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 tid_dumping_heap_ == PlatformThread::CurrentId()) | 374 tid_dumping_heap_ == PlatformThread::CurrentId()) |
| 358 return; | 375 return; |
| 359 AutoLock lock(allocation_register_lock_); | 376 AutoLock lock(allocation_register_lock_); |
| 360 if (!allocation_register_) | 377 if (!allocation_register_) |
| 361 return; | 378 return; |
| 362 allocation_register_->Remove(address); | 379 allocation_register_->Remove(address); |
| 363 } | 380 } |
| 364 | 381 |
| 365 } // namespace trace_event | 382 } // namespace trace_event |
| 366 } // namespace base | 383 } // namespace base |
| OLD | NEW |