OLD | NEW |
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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/metrics/histogram_persistence.h" | 5 #include "base/metrics/histogram_persistence.h" |
6 | 6 |
7 #include "base/lazy_instance.h" | 7 #include "base/lazy_instance.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 // Histogram was of unknown type. | 46 // Histogram was of unknown type. |
47 CREATE_HISTOGRAM_UNKNOWN_TYPE, | 47 CREATE_HISTOGRAM_UNKNOWN_TYPE, |
48 | 48 |
49 // Instance has detected a corrupt allocator (recorded only once). | 49 // Instance has detected a corrupt allocator (recorded only once). |
50 CREATE_HISTOGRAM_ALLOCATOR_NEWLY_CORRUPT, | 50 CREATE_HISTOGRAM_ALLOCATOR_NEWLY_CORRUPT, |
51 | 51 |
52 // Always keep this at the end. | 52 // Always keep this at the end. |
53 CREATE_HISTOGRAM_MAX | 53 CREATE_HISTOGRAM_MAX |
54 }; | 54 }; |
55 | 55 |
| 56 // Name of histogram for storing results of local operations. |
| 57 const char kResultHistogram[] = "UMA.CreatePersistentHistogram.Result"; |
| 58 |
56 // Type identifiers used when storing in persistent memory so they can be | 59 // Type identifiers used when storing in persistent memory so they can be |
57 // identified during extraction; the first 4 bytes of the SHA1 of the name | 60 // identified during extraction; the first 4 bytes of the SHA1 of the name |
58 // is used as a unique integer. A "version number" is added to the base | 61 // is used as a unique integer. A "version number" is added to the base |
59 // so that, if the structure of that object changes, stored older versions | 62 // so that, if the structure of that object changes, stored older versions |
60 // will be safely ignored. | 63 // will be safely ignored. |
61 enum : uint32_t { | 64 enum : uint32_t { |
62 kTypeIdHistogram = 0xF1645910 + 1, // SHA1(Histogram) v1 | 65 kTypeIdHistogram = 0xF1645910 + 1, // SHA1(Histogram) v1 |
63 kTypeIdRangesArray = 0xBCEA225A + 1, // SHA1(RangesArray) v1 | 66 kTypeIdRangesArray = 0xBCEA225A + 1, // SHA1(RangesArray) v1 |
64 kTypeIdCountsArray = 0x53215530 + 1, // SHA1(CountsArray) v1 | 67 kTypeIdCountsArray = 0x53215530 + 1, // SHA1(CountsArray) v1 |
65 }; | 68 }; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 static bool initialized = false; | 155 static bool initialized = false; |
153 if (!initialized) { | 156 if (!initialized) { |
154 initialized = true; | 157 initialized = true; |
155 if (g_allocator) { | 158 if (g_allocator) { |
156 DLOG(WARNING) << "Creating the results-histogram inside persistent" | 159 DLOG(WARNING) << "Creating the results-histogram inside persistent" |
157 << " memory can cause future allocations to crash if" | 160 << " memory can cause future allocations to crash if" |
158 << " that memory is ever released (for testing)."; | 161 << " that memory is ever released (for testing)."; |
159 } | 162 } |
160 | 163 |
161 histogram_pointer = LinearHistogram::FactoryGet( | 164 histogram_pointer = LinearHistogram::FactoryGet( |
162 "UMA.CreatePersistentHistogram.Result", | 165 kResultHistogram, 1, CREATE_HISTOGRAM_MAX, CREATE_HISTOGRAM_MAX + 1, |
163 1, CREATE_HISTOGRAM_MAX, CREATE_HISTOGRAM_MAX + 1, | |
164 HistogramBase::kUmaTargetedHistogramFlag); | 166 HistogramBase::kUmaTargetedHistogramFlag); |
165 base::subtle::Release_Store( | 167 base::subtle::Release_Store( |
166 &atomic_histogram_pointer, | 168 &atomic_histogram_pointer, |
167 reinterpret_cast<base::subtle::AtomicWord>(histogram_pointer)); | 169 reinterpret_cast<base::subtle::AtomicWord>(histogram_pointer)); |
168 } | 170 } |
169 } | 171 } |
170 return histogram_pointer; | 172 return histogram_pointer; |
171 } | 173 } |
172 | 174 |
173 // Record the result of a histogram creation. | 175 // Record the result of a histogram creation. |
(...skipping 29 matching lines...) Expand all Loading... |
203 PersistentMemoryAllocator::Reference ref; | 205 PersistentMemoryAllocator::Reference ref; |
204 uint32_t type_id; | 206 uint32_t type_id; |
205 allocator->CreateIterator(&iter); | 207 allocator->CreateIterator(&iter); |
206 while ((ref = allocator->GetNextIterable(&iter, &type_id)) != 0) { | 208 while ((ref = allocator->GetNextIterable(&iter, &type_id)) != 0) { |
207 if (type_id == kTypeIdHistogram) { | 209 if (type_id == kTypeIdHistogram) { |
208 PersistentHistogramData* histogram_data = | 210 PersistentHistogramData* histogram_data = |
209 allocator->GetAsObject<PersistentHistogramData>( | 211 allocator->GetAsObject<PersistentHistogramData>( |
210 ref, kTypeIdHistogram); | 212 ref, kTypeIdHistogram); |
211 DCHECK(histogram_data); | 213 DCHECK(histogram_data); |
212 StatisticsRecorder::ForgetHistogramForTesting(histogram_data->name); | 214 StatisticsRecorder::ForgetHistogramForTesting(histogram_data->name); |
| 215 |
| 216 // If a test breaks here then a memory region containing a histogram |
| 217 // actively used by this code is being released back to the test. |
| 218 // If that memory segment were to be deleted, future calls to create |
| 219 // persistent histograms would crash. To avoid this, have the test call |
| 220 // the method GetCreateHistogramResultHistogram() *before* setting the |
| 221 // (temporary) memory allocator via SetPersistentMemoryAllocator() so |
| 222 // that the histogram is instead allocated from the process heap. |
| 223 DCHECK_NE(kResultHistogram, histogram_data->name); |
213 } | 224 } |
214 } | 225 } |
215 | 226 |
216 g_allocator = nullptr; | 227 g_allocator = nullptr; |
217 return allocator; | 228 return allocator; |
218 }; | 229 }; |
219 | 230 |
220 HistogramBase* CreatePersistentHistogram( | 231 HistogramBase* CreatePersistentHistogram( |
221 PersistentMemoryAllocator* allocator, | 232 PersistentMemoryAllocator* allocator, |
222 PersistentHistogramData* histogram_data_ptr) { | 233 PersistentHistogramData* histogram_data_ptr) { |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
473 } | 484 } |
474 RecordCreateHistogramResult(result); | 485 RecordCreateHistogramResult(result); |
475 NOTREACHED() << "error=" << result; | 486 NOTREACHED() << "error=" << result; |
476 | 487 |
477 return nullptr; | 488 return nullptr; |
478 } | 489 } |
479 | 490 |
480 void ImportPersistentHistograms() { | 491 void ImportPersistentHistograms() { |
481 // The lock protects against concurrent access to the iterator and is created | 492 // The lock protects against concurrent access to the iterator and is created |
482 // in a thread-safe manner when needed. | 493 // in a thread-safe manner when needed. |
483 static base::LazyInstance<base::Lock> lock = LAZY_INSTANCE_INITIALIZER; | 494 static base::LazyInstance<base::Lock>::Leaky lock = LAZY_INSTANCE_INITIALIZER; |
484 | 495 |
485 if (g_allocator) { | 496 if (g_allocator) { |
486 base::AutoLock auto_lock(lock.Get()); | 497 base::AutoLock auto_lock(lock.Get()); |
487 | 498 |
488 // Each call resumes from where it last left off so need persistant | 499 // Each call resumes from where it last left off so need persistant |
489 // iterator. This class has a constructor so even the definition has | 500 // iterator. This class has a constructor so even the definition has |
490 // to be protected by the lock in order to be thread-safe. | 501 // to be protected by the lock in order to be thread-safe. |
491 static PersistentMemoryAllocator::Iterator iter; | 502 static PersistentMemoryAllocator::Iterator iter; |
492 if (iter.is_clear()) | 503 if (iter.is_clear()) |
493 g_allocator->CreateIterator(&iter); | 504 g_allocator->CreateIterator(&iter); |
494 | 505 |
495 for (;;) { | 506 while (true) { |
496 HistogramBase* histogram = GetNextPersistentHistogram(g_allocator, &iter); | 507 HistogramBase* histogram = GetNextPersistentHistogram(g_allocator, &iter); |
497 if (!histogram) | 508 if (!histogram) |
498 break; | 509 break; |
499 StatisticsRecorder::RegisterOrDeleteDuplicate(histogram); | 510 StatisticsRecorder::RegisterOrDeleteDuplicate(histogram); |
500 } | 511 } |
501 } | 512 } |
502 } | 513 } |
503 | 514 |
504 } // namespace base | 515 } // namespace base |
OLD | NEW |