OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/persistent_histogram_allocator.h" | 5 #include "base/metrics/persistent_histogram_allocator.h" |
6 | 6 |
| 7 #include <memory> |
| 8 |
7 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
8 #include "base/logging.h" | 10 #include "base/logging.h" |
9 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/ptr_util.h" |
10 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
11 #include "base/metrics/histogram_base.h" | 13 #include "base/metrics/histogram_base.h" |
12 #include "base/metrics/histogram_samples.h" | 14 #include "base/metrics/histogram_samples.h" |
13 #include "base/metrics/sparse_histogram.h" | 15 #include "base/metrics/sparse_histogram.h" |
14 #include "base/metrics/statistics_recorder.h" | 16 #include "base/metrics/statistics_recorder.h" |
15 #include "base/synchronization/lock.h" | 17 #include "base/synchronization/lock.h" |
16 | 18 |
17 // TODO(bcwhite): Order these methods to match the header file. The current | 19 // TODO(bcwhite): Order these methods to match the header file. The current |
18 // order is only temporary in order to aid review of the transition from | 20 // order is only temporary in order to aid review of the transition from |
19 // a non-class implementation. | 21 // a non-class implementation. |
(...skipping 20 matching lines...) Expand all Loading... |
40 // The object held here will obviously not be destructed at process exit | 42 // The object held here will obviously not be destructed at process exit |
41 // but that's best since PersistentMemoryAllocator objects (that underlie | 43 // but that's best since PersistentMemoryAllocator objects (that underlie |
42 // PersistentHistogramAllocator objects) are explicitly forbidden from doing | 44 // PersistentHistogramAllocator objects) are explicitly forbidden from doing |
43 // anything essential at exit anyway due to the fact that they depend on data | 45 // anything essential at exit anyway due to the fact that they depend on data |
44 // managed elsewhere and which could be destructed first. | 46 // managed elsewhere and which could be destructed first. |
45 PersistentHistogramAllocator* g_allocator; | 47 PersistentHistogramAllocator* g_allocator; |
46 | 48 |
47 // Take an array of range boundaries and create a proper BucketRanges object | 49 // Take an array of range boundaries and create a proper BucketRanges object |
48 // which is returned to the caller. A return of nullptr indicates that the | 50 // which is returned to the caller. A return of nullptr indicates that the |
49 // passed boundaries are invalid. | 51 // passed boundaries are invalid. |
50 scoped_ptr<BucketRanges> CreateRangesFromData( | 52 std::unique_ptr<BucketRanges> CreateRangesFromData( |
51 HistogramBase::Sample* ranges_data, | 53 HistogramBase::Sample* ranges_data, |
52 uint32_t ranges_checksum, | 54 uint32_t ranges_checksum, |
53 size_t count) { | 55 size_t count) { |
54 // To avoid racy destruction at shutdown, the following may be leaked. | 56 // To avoid racy destruction at shutdown, the following may be leaked. |
55 scoped_ptr<BucketRanges> ranges(new BucketRanges(count)); | 57 std::unique_ptr<BucketRanges> ranges(new BucketRanges(count)); |
56 DCHECK_EQ(count, ranges->size()); | 58 DCHECK_EQ(count, ranges->size()); |
57 for (size_t i = 0; i < count; ++i) { | 59 for (size_t i = 0; i < count; ++i) { |
58 if (i > 0 && ranges_data[i] <= ranges_data[i - 1]) | 60 if (i > 0 && ranges_data[i] <= ranges_data[i - 1]) |
59 return nullptr; | 61 return nullptr; |
60 ranges->set_range(i, ranges_data[i]); | 62 ranges->set_range(i, ranges_data[i]); |
61 } | 63 } |
62 | 64 |
63 ranges->ResetChecksum(); | 65 ranges->ResetChecksum(); |
64 if (ranges->checksum() != ranges_checksum) | 66 if (ranges->checksum() != ranges_checksum) |
65 return nullptr; | 67 return nullptr; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 HistogramSamples::Metadata samples_metadata; | 105 HistogramSamples::Metadata samples_metadata; |
104 HistogramSamples::Metadata logged_metadata; | 106 HistogramSamples::Metadata logged_metadata; |
105 | 107 |
106 // Space for the histogram name will be added during the actual allocation | 108 // Space for the histogram name will be added during the actual allocation |
107 // request. This must be the last field of the structure. A zero-size array | 109 // request. This must be the last field of the structure. A zero-size array |
108 // or a "flexible" array would be preferred but is not (yet) valid C++. | 110 // or a "flexible" array would be preferred but is not (yet) valid C++. |
109 char name[1]; | 111 char name[1]; |
110 }; | 112 }; |
111 | 113 |
112 PersistentHistogramAllocator::PersistentHistogramAllocator( | 114 PersistentHistogramAllocator::PersistentHistogramAllocator( |
113 scoped_ptr<PersistentMemoryAllocator> memory) | 115 std::unique_ptr<PersistentMemoryAllocator> memory) |
114 : memory_allocator_(std::move(memory)) {} | 116 : memory_allocator_(std::move(memory)) {} |
115 | 117 |
116 PersistentHistogramAllocator::~PersistentHistogramAllocator() {} | 118 PersistentHistogramAllocator::~PersistentHistogramAllocator() {} |
117 | 119 |
118 void PersistentHistogramAllocator::CreateIterator(Iterator* iter) { | 120 void PersistentHistogramAllocator::CreateIterator(Iterator* iter) { |
119 memory_allocator_->CreateIterator(&iter->memory_iter); | 121 memory_allocator_->CreateIterator(&iter->memory_iter); |
120 } | 122 } |
121 | 123 |
122 void PersistentHistogramAllocator::CreateTrackingHistograms(StringPiece name) { | 124 void PersistentHistogramAllocator::CreateTrackingHistograms(StringPiece name) { |
123 memory_allocator_->CreateTrackingHistograms(name); | 125 memory_allocator_->CreateTrackingHistograms(name); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
167 // static | 169 // static |
168 void PersistentHistogramAllocator::RecordCreateHistogramResult( | 170 void PersistentHistogramAllocator::RecordCreateHistogramResult( |
169 CreateHistogramResultType result) { | 171 CreateHistogramResultType result) { |
170 HistogramBase* result_histogram = GetCreateHistogramResultHistogram(); | 172 HistogramBase* result_histogram = GetCreateHistogramResultHistogram(); |
171 if (result_histogram) | 173 if (result_histogram) |
172 result_histogram->Add(result); | 174 result_histogram->Add(result); |
173 } | 175 } |
174 | 176 |
175 // static | 177 // static |
176 void PersistentHistogramAllocator::SetGlobalAllocator( | 178 void PersistentHistogramAllocator::SetGlobalAllocator( |
177 scoped_ptr<PersistentHistogramAllocator> allocator) { | 179 std::unique_ptr<PersistentHistogramAllocator> allocator) { |
178 // Releasing or changing an allocator is extremely dangerous because it | 180 // Releasing or changing an allocator is extremely dangerous because it |
179 // likely has histograms stored within it. If the backing memory is also | 181 // likely has histograms stored within it. If the backing memory is also |
180 // also released, future accesses to those histograms will seg-fault. | 182 // also released, future accesses to those histograms will seg-fault. |
181 CHECK(!g_allocator); | 183 CHECK(!g_allocator); |
182 g_allocator = allocator.release(); | 184 g_allocator = allocator.release(); |
183 | 185 |
184 size_t existing = StatisticsRecorder::GetHistogramCount(); | 186 size_t existing = StatisticsRecorder::GetHistogramCount(); |
185 DLOG_IF(WARNING, existing) | 187 DLOG_IF(WARNING, existing) |
186 << existing | 188 << existing |
187 << " histograms were created before persistence was enabled."; | 189 << " histograms were created before persistence was enabled."; |
188 } | 190 } |
189 | 191 |
190 // static | 192 // static |
191 PersistentHistogramAllocator* | 193 PersistentHistogramAllocator* |
192 PersistentHistogramAllocator::GetGlobalAllocator() { | 194 PersistentHistogramAllocator::GetGlobalAllocator() { |
193 return g_allocator; | 195 return g_allocator; |
194 } | 196 } |
195 | 197 |
196 // static | 198 // static |
197 scoped_ptr<PersistentHistogramAllocator> | 199 std::unique_ptr<PersistentHistogramAllocator> |
198 PersistentHistogramAllocator::ReleaseGlobalAllocatorForTesting() { | 200 PersistentHistogramAllocator::ReleaseGlobalAllocatorForTesting() { |
199 PersistentHistogramAllocator* histogram_allocator = g_allocator; | 201 PersistentHistogramAllocator* histogram_allocator = g_allocator; |
200 if (!histogram_allocator) | 202 if (!histogram_allocator) |
201 return nullptr; | 203 return nullptr; |
202 PersistentMemoryAllocator* memory_allocator = | 204 PersistentMemoryAllocator* memory_allocator = |
203 histogram_allocator->memory_allocator(); | 205 histogram_allocator->memory_allocator(); |
204 | 206 |
205 // Before releasing the memory, it's necessary to have the Statistics- | 207 // Before releasing the memory, it's necessary to have the Statistics- |
206 // Recorder forget about the histograms contained therein; otherwise, | 208 // Recorder forget about the histograms contained therein; otherwise, |
207 // some operations will try to access them and the released memory. | 209 // some operations will try to access them and the released memory. |
(...skipping 14 matching lines...) Expand all Loading... |
222 // If that memory segment were to be deleted, future calls to create | 224 // If that memory segment were to be deleted, future calls to create |
223 // persistent histograms would crash. To avoid this, have the test call | 225 // persistent histograms would crash. To avoid this, have the test call |
224 // the method GetCreateHistogramResultHistogram() *before* setting | 226 // the method GetCreateHistogramResultHistogram() *before* setting |
225 // the (temporary) memory allocator via SetGlobalAllocator() so that | 227 // the (temporary) memory allocator via SetGlobalAllocator() so that |
226 // histogram is instead allocated from the process heap. | 228 // histogram is instead allocated from the process heap. |
227 DCHECK_NE(kResultHistogram, histogram_data->name); | 229 DCHECK_NE(kResultHistogram, histogram_data->name); |
228 } | 230 } |
229 } | 231 } |
230 | 232 |
231 g_allocator = nullptr; | 233 g_allocator = nullptr; |
232 return make_scoped_ptr(histogram_allocator); | 234 return WrapUnique(histogram_allocator); |
233 }; | 235 }; |
234 | 236 |
235 // static | 237 // static |
236 void PersistentHistogramAllocator::CreateGlobalAllocatorOnPersistentMemory( | 238 void PersistentHistogramAllocator::CreateGlobalAllocatorOnPersistentMemory( |
237 void* base, | 239 void* base, |
238 size_t size, | 240 size_t size, |
239 size_t page_size, | 241 size_t page_size, |
240 uint64_t id, | 242 uint64_t id, |
241 StringPiece name) { | 243 StringPiece name) { |
242 SetGlobalAllocator(make_scoped_ptr(new PersistentHistogramAllocator( | 244 SetGlobalAllocator(WrapUnique(new PersistentHistogramAllocator( |
243 make_scoped_ptr(new PersistentMemoryAllocator( | 245 WrapUnique(new PersistentMemoryAllocator(base, size, page_size, id, |
244 base, size, page_size, id, name, false))))); | 246 name, false))))); |
245 } | 247 } |
246 | 248 |
247 // static | 249 // static |
248 void PersistentHistogramAllocator::CreateGlobalAllocatorOnLocalMemory( | 250 void PersistentHistogramAllocator::CreateGlobalAllocatorOnLocalMemory( |
249 size_t size, | 251 size_t size, |
250 uint64_t id, | 252 uint64_t id, |
251 StringPiece name) { | 253 StringPiece name) { |
252 SetGlobalAllocator(make_scoped_ptr(new PersistentHistogramAllocator( | 254 SetGlobalAllocator(WrapUnique(new PersistentHistogramAllocator( |
253 make_scoped_ptr(new LocalPersistentMemoryAllocator(size, id, name))))); | 255 WrapUnique(new LocalPersistentMemoryAllocator(size, id, name))))); |
254 } | 256 } |
255 | 257 |
256 // static | 258 // static |
257 void PersistentHistogramAllocator::CreateGlobalAllocatorOnSharedMemory( | 259 void PersistentHistogramAllocator::CreateGlobalAllocatorOnSharedMemory( |
258 size_t size, | 260 size_t size, |
259 const SharedMemoryHandle& handle) { | 261 const SharedMemoryHandle& handle) { |
260 scoped_ptr<SharedMemory> shm(new SharedMemory(handle, /*readonly=*/false)); | 262 std::unique_ptr<SharedMemory> shm( |
| 263 new SharedMemory(handle, /*readonly=*/false)); |
261 if (!shm->Map(size)) { | 264 if (!shm->Map(size)) { |
262 NOTREACHED(); | 265 NOTREACHED(); |
263 return; | 266 return; |
264 } | 267 } |
265 | 268 |
266 SetGlobalAllocator(make_scoped_ptr(new PersistentHistogramAllocator( | 269 SetGlobalAllocator(WrapUnique(new PersistentHistogramAllocator( |
267 make_scoped_ptr(new SharedPersistentMemoryAllocator( | 270 WrapUnique(new SharedPersistentMemoryAllocator( |
268 std::move(shm), 0, StringPiece(), /*readonly=*/false))))); | 271 std::move(shm), 0, StringPiece(), /*readonly=*/false))))); |
269 } | 272 } |
270 | 273 |
271 // static | 274 // static |
272 scoped_ptr<HistogramBase> PersistentHistogramAllocator::CreateHistogram( | 275 std::unique_ptr<HistogramBase> PersistentHistogramAllocator::CreateHistogram( |
273 PersistentHistogramData* histogram_data_ptr) { | 276 PersistentHistogramData* histogram_data_ptr) { |
274 if (!histogram_data_ptr) { | 277 if (!histogram_data_ptr) { |
275 RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_METADATA_POINTER); | 278 RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_METADATA_POINTER); |
276 NOTREACHED(); | 279 NOTREACHED(); |
277 return nullptr; | 280 return nullptr; |
278 } | 281 } |
279 | 282 |
280 // Sparse histograms are quite different so handle them as a special case. | 283 // Sparse histograms are quite different so handle them as a special case. |
281 if (histogram_data_ptr->histogram_type == SPARSE_HISTOGRAM) { | 284 if (histogram_data_ptr->histogram_type == SPARSE_HISTOGRAM) { |
282 scoped_ptr<HistogramBase> histogram = SparseHistogram::PersistentCreate( | 285 std::unique_ptr<HistogramBase> histogram = |
283 memory_allocator(), histogram_data_ptr->name, | 286 SparseHistogram::PersistentCreate(memory_allocator(), |
284 &histogram_data_ptr->samples_metadata, | 287 histogram_data_ptr->name, |
285 &histogram_data_ptr->logged_metadata); | 288 &histogram_data_ptr->samples_metadata, |
| 289 &histogram_data_ptr->logged_metadata); |
286 DCHECK(histogram); | 290 DCHECK(histogram); |
287 histogram->SetFlags(histogram_data_ptr->flags); | 291 histogram->SetFlags(histogram_data_ptr->flags); |
288 RecordCreateHistogramResult(CREATE_HISTOGRAM_SUCCESS); | 292 RecordCreateHistogramResult(CREATE_HISTOGRAM_SUCCESS); |
289 return histogram; | 293 return histogram; |
290 } | 294 } |
291 | 295 |
292 // Copy the histogram_data to local storage because anything in persistent | 296 // Copy the histogram_data to local storage because anything in persistent |
293 // memory cannot be trusted as it could be changed at any moment by a | 297 // memory cannot be trusted as it could be changed at any moment by a |
294 // malicious actor that shares access. The contents of histogram_data are | 298 // malicious actor that shares access. The contents of histogram_data are |
295 // validated below; the local copy is to ensure that the contents cannot | 299 // validated below; the local copy is to ensure that the contents cannot |
(...skipping 11 matching lines...) Expand all Loading... |
307 size_t allocated_bytes = | 311 size_t allocated_bytes = |
308 memory_allocator_->GetAllocSize(histogram_data.ranges_ref); | 312 memory_allocator_->GetAllocSize(histogram_data.ranges_ref); |
309 if (!ranges_data || histogram_data.bucket_count < 2 || | 313 if (!ranges_data || histogram_data.bucket_count < 2 || |
310 histogram_data.bucket_count >= max_buckets || | 314 histogram_data.bucket_count >= max_buckets || |
311 allocated_bytes < required_bytes) { | 315 allocated_bytes < required_bytes) { |
312 RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_RANGES_ARRAY); | 316 RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_RANGES_ARRAY); |
313 NOTREACHED(); | 317 NOTREACHED(); |
314 return nullptr; | 318 return nullptr; |
315 } | 319 } |
316 | 320 |
317 scoped_ptr<const BucketRanges> created_ranges = | 321 std::unique_ptr<const BucketRanges> created_ranges = |
318 CreateRangesFromData(ranges_data, histogram_data.ranges_checksum, | 322 CreateRangesFromData(ranges_data, histogram_data.ranges_checksum, |
319 histogram_data.bucket_count + 1); | 323 histogram_data.bucket_count + 1); |
320 if (!created_ranges) { | 324 if (!created_ranges) { |
321 RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_RANGES_ARRAY); | 325 RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_RANGES_ARRAY); |
322 NOTREACHED(); | 326 NOTREACHED(); |
323 return nullptr; | 327 return nullptr; |
324 } | 328 } |
325 const BucketRanges* ranges = | 329 const BucketRanges* ranges = |
326 StatisticsRecorder::RegisterOrDeleteDuplicateRanges( | 330 StatisticsRecorder::RegisterOrDeleteDuplicateRanges( |
327 created_ranges.release()); | 331 created_ranges.release()); |
(...skipping 11 matching lines...) Expand all Loading... |
339 return nullptr; | 343 return nullptr; |
340 } | 344 } |
341 | 345 |
342 // After the main "counts" array is a second array using for storing what | 346 // After the main "counts" array is a second array using for storing what |
343 // was previously logged. This is used to calculate the "delta" during | 347 // was previously logged. This is used to calculate the "delta" during |
344 // snapshot operations. | 348 // snapshot operations. |
345 HistogramBase::AtomicCount* logged_data = | 349 HistogramBase::AtomicCount* logged_data = |
346 counts_data + histogram_data.bucket_count; | 350 counts_data + histogram_data.bucket_count; |
347 | 351 |
348 std::string name(histogram_data_ptr->name); | 352 std::string name(histogram_data_ptr->name); |
349 scoped_ptr<HistogramBase> histogram; | 353 std::unique_ptr<HistogramBase> histogram; |
350 switch (histogram_data.histogram_type) { | 354 switch (histogram_data.histogram_type) { |
351 case HISTOGRAM: | 355 case HISTOGRAM: |
352 histogram = Histogram::PersistentCreate( | 356 histogram = Histogram::PersistentCreate( |
353 name, histogram_data.minimum, histogram_data.maximum, ranges, | 357 name, histogram_data.minimum, histogram_data.maximum, ranges, |
354 counts_data, logged_data, histogram_data.bucket_count, | 358 counts_data, logged_data, histogram_data.bucket_count, |
355 &histogram_data_ptr->samples_metadata, | 359 &histogram_data_ptr->samples_metadata, |
356 &histogram_data_ptr->logged_metadata); | 360 &histogram_data_ptr->logged_metadata); |
357 DCHECK(histogram); | 361 DCHECK(histogram); |
358 break; | 362 break; |
359 case LINEAR_HISTOGRAM: | 363 case LINEAR_HISTOGRAM: |
(...skipping 26 matching lines...) Expand all Loading... |
386 DCHECK_EQ(histogram_data.histogram_type, histogram->GetHistogramType()); | 390 DCHECK_EQ(histogram_data.histogram_type, histogram->GetHistogramType()); |
387 histogram->SetFlags(histogram_data.flags); | 391 histogram->SetFlags(histogram_data.flags); |
388 RecordCreateHistogramResult(CREATE_HISTOGRAM_SUCCESS); | 392 RecordCreateHistogramResult(CREATE_HISTOGRAM_SUCCESS); |
389 } else { | 393 } else { |
390 RecordCreateHistogramResult(CREATE_HISTOGRAM_UNKNOWN_TYPE); | 394 RecordCreateHistogramResult(CREATE_HISTOGRAM_UNKNOWN_TYPE); |
391 } | 395 } |
392 | 396 |
393 return histogram; | 397 return histogram; |
394 } | 398 } |
395 | 399 |
396 scoped_ptr<HistogramBase> PersistentHistogramAllocator::GetHistogram( | 400 std::unique_ptr<HistogramBase> PersistentHistogramAllocator::GetHistogram( |
397 Reference ref) { | 401 Reference ref) { |
398 // Unfortunately, the histogram "pickle" methods cannot be used as part of | 402 // Unfortunately, the histogram "pickle" methods cannot be used as part of |
399 // the persistance because the deserialization methods always create local | 403 // the persistance because the deserialization methods always create local |
400 // count data (while these must reference the persistent counts) and always | 404 // count data (while these must reference the persistent counts) and always |
401 // add it to the local list of known histograms (while these may be simple | 405 // add it to the local list of known histograms (while these may be simple |
402 // references to histograms in other processes). | 406 // references to histograms in other processes). |
403 PersistentHistogramData* histogram_data = | 407 PersistentHistogramData* histogram_data = |
404 memory_allocator_->GetAsObject<PersistentHistogramData>( | 408 memory_allocator_->GetAsObject<PersistentHistogramData>( |
405 ref, kTypeIdHistogram); | 409 ref, kTypeIdHistogram); |
406 size_t length = memory_allocator_->GetAllocSize(ref); | 410 size_t length = memory_allocator_->GetAllocSize(ref); |
407 if (!histogram_data || | 411 if (!histogram_data || |
408 reinterpret_cast<char*>(histogram_data)[length - 1] != '\0') { | 412 reinterpret_cast<char*>(histogram_data)[length - 1] != '\0') { |
409 RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_METADATA); | 413 RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_METADATA); |
410 NOTREACHED(); | 414 NOTREACHED(); |
411 return nullptr; | 415 return nullptr; |
412 } | 416 } |
413 return CreateHistogram(histogram_data); | 417 return CreateHistogram(histogram_data); |
414 } | 418 } |
415 | 419 |
416 scoped_ptr<HistogramBase> | 420 std::unique_ptr<HistogramBase> |
417 PersistentHistogramAllocator::GetNextHistogramWithIgnore(Iterator* iter, | 421 PersistentHistogramAllocator::GetNextHistogramWithIgnore(Iterator* iter, |
418 Reference ignore) { | 422 Reference ignore) { |
419 PersistentMemoryAllocator::Reference ref; | 423 PersistentMemoryAllocator::Reference ref; |
420 uint32_t type_id; | 424 uint32_t type_id; |
421 while ((ref = memory_allocator_->GetNextIterable(&iter->memory_iter, | 425 while ((ref = memory_allocator_->GetNextIterable(&iter->memory_iter, |
422 &type_id)) != 0) { | 426 &type_id)) != 0) { |
423 if (ref == ignore) | 427 if (ref == ignore) |
424 continue; | 428 continue; |
425 if (type_id == kTypeIdHistogram) | 429 if (type_id == kTypeIdHistogram) |
426 return GetHistogram(ref); | 430 return GetHistogram(ref); |
427 } | 431 } |
428 return nullptr; | 432 return nullptr; |
429 } | 433 } |
430 | 434 |
431 void PersistentHistogramAllocator::FinalizeHistogram(Reference ref, | 435 void PersistentHistogramAllocator::FinalizeHistogram(Reference ref, |
432 bool registered) { | 436 bool registered) { |
433 // If the created persistent histogram was registered then it needs to | 437 // If the created persistent histogram was registered then it needs to |
434 // be marked as "iterable" in order to be found by other processes. | 438 // be marked as "iterable" in order to be found by other processes. |
435 if (registered) | 439 if (registered) |
436 memory_allocator_->MakeIterable(ref); | 440 memory_allocator_->MakeIterable(ref); |
437 // If it wasn't registered then a race condition must have caused | 441 // If it wasn't registered then a race condition must have caused |
438 // two to be created. The allocator does not support releasing the | 442 // two to be created. The allocator does not support releasing the |
439 // acquired memory so just change the type to be empty. | 443 // acquired memory so just change the type to be empty. |
440 else | 444 else |
441 memory_allocator_->SetType(ref, 0); | 445 memory_allocator_->SetType(ref, 0); |
442 } | 446 } |
443 | 447 |
444 scoped_ptr<HistogramBase> PersistentHistogramAllocator::AllocateHistogram( | 448 std::unique_ptr<HistogramBase> PersistentHistogramAllocator::AllocateHistogram( |
445 HistogramType histogram_type, | 449 HistogramType histogram_type, |
446 const std::string& name, | 450 const std::string& name, |
447 int minimum, | 451 int minimum, |
448 int maximum, | 452 int maximum, |
449 const BucketRanges* bucket_ranges, | 453 const BucketRanges* bucket_ranges, |
450 int32_t flags, | 454 int32_t flags, |
451 Reference* ref_ptr) { | 455 Reference* ref_ptr) { |
452 // If the allocator is corrupt, don't waste time trying anything else. | 456 // If the allocator is corrupt, don't waste time trying anything else. |
453 // This also allows differentiating on the dashboard between allocations | 457 // This also allows differentiating on the dashboard between allocations |
454 // failed due to a corrupt allocator and the number of process instances | 458 // failed due to a corrupt allocator and the number of process instances |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
514 histogram_data = nullptr; // Clear this for proper handling below. | 518 histogram_data = nullptr; // Clear this for proper handling below. |
515 } | 519 } |
516 } | 520 } |
517 | 521 |
518 if (histogram_data) { | 522 if (histogram_data) { |
519 // Create the histogram using resources in persistent memory. This ends up | 523 // Create the histogram using resources in persistent memory. This ends up |
520 // resolving the "ref" values stored in histogram_data instad of just | 524 // resolving the "ref" values stored in histogram_data instad of just |
521 // using what is already known above but avoids duplicating the switch | 525 // using what is already known above but avoids duplicating the switch |
522 // statement here and serves as a double-check that everything is | 526 // statement here and serves as a double-check that everything is |
523 // correct before commiting the new histogram to persistent space. | 527 // correct before commiting the new histogram to persistent space. |
524 scoped_ptr<HistogramBase> histogram = CreateHistogram(histogram_data); | 528 std::unique_ptr<HistogramBase> histogram = CreateHistogram(histogram_data); |
525 DCHECK(histogram); | 529 DCHECK(histogram); |
526 if (ref_ptr != nullptr) | 530 if (ref_ptr != nullptr) |
527 *ref_ptr = histogram_ref; | 531 *ref_ptr = histogram_ref; |
528 | 532 |
529 // By storing the reference within the allocator to this histogram, the | 533 // By storing the reference within the allocator to this histogram, the |
530 // next import (which will happen before the next histogram creation) | 534 // next import (which will happen before the next histogram creation) |
531 // will know to skip it. See also the comment in ImportGlobalHistograms(). | 535 // will know to skip it. See also the comment in ImportGlobalHistograms(). |
532 subtle::NoBarrier_Store(&last_created_, histogram_ref); | 536 subtle::NoBarrier_Store(&last_created_, histogram_ref); |
533 return histogram; | 537 return histogram; |
534 } | 538 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
568 // Skip the import if it's the histogram that was last created. Should a | 572 // Skip the import if it's the histogram that was last created. Should a |
569 // race condition cause the "last created" to be overwritten before it | 573 // race condition cause the "last created" to be overwritten before it |
570 // is recognized here then the histogram will be created and be ignored | 574 // is recognized here then the histogram will be created and be ignored |
571 // when it is detected as a duplicate by the statistics-recorder. This | 575 // when it is detected as a duplicate by the statistics-recorder. This |
572 // simple check reduces the time of creating persistent histograms by | 576 // simple check reduces the time of creating persistent histograms by |
573 // about 40%. | 577 // about 40%. |
574 Reference last_created = | 578 Reference last_created = |
575 subtle::NoBarrier_Load(&g_allocator->last_created_); | 579 subtle::NoBarrier_Load(&g_allocator->last_created_); |
576 | 580 |
577 while (true) { | 581 while (true) { |
578 scoped_ptr<HistogramBase> histogram = | 582 std::unique_ptr<HistogramBase> histogram = |
579 g_allocator->GetNextHistogramWithIgnore(&iter, last_created); | 583 g_allocator->GetNextHistogramWithIgnore(&iter, last_created); |
580 if (!histogram) | 584 if (!histogram) |
581 break; | 585 break; |
582 StatisticsRecorder::RegisterOrDeleteDuplicate(histogram.release()); | 586 StatisticsRecorder::RegisterOrDeleteDuplicate(histogram.release()); |
583 } | 587 } |
584 } | 588 } |
585 } | 589 } |
586 | 590 |
587 } // namespace base | 591 } // namespace base |
OLD | NEW |