Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1658)

Side by Side Diff: base/metrics/sample_vector.cc

Issue 2853853002: Fix overflow when logging MaxInt32 to a sparse histogram. (Closed)
Patch Set: Address comments. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/metrics/sample_vector.h ('k') | base/metrics/sample_vector_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/sample_vector.h" 5 #include "base/metrics/sample_vector.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/ptr_util.h" 9 #include "base/memory/ptr_util.h"
10 #include "base/metrics/persistent_memory_allocator.h" 10 #include "base/metrics/persistent_memory_allocator.h"
11 #include "base/numerics/safe_conversions.h"
11 #include "base/synchronization/lock.h" 12 #include "base/synchronization/lock.h"
12 #include "base/threading/platform_thread.h" 13 #include "base/threading/platform_thread.h"
13 14
14 // This SampleVector makes use of the single-sample embedded in the base 15 // This SampleVector makes use of the single-sample embedded in the base
15 // HistogramSamples class. If the count is non-zero then there is guaranteed 16 // HistogramSamples class. If the count is non-zero then there is guaranteed
16 // (within the bounds of "eventual consistency") to be no allocated external 17 // (within the bounds of "eventual consistency") to be no allocated external
17 // storage. Once the full counts storage is allocated, the single-sample must 18 // storage. Once the full counts storage is allocated, the single-sample must
18 // be extracted and disabled. 19 // be extracted and disabled.
19 20
20 namespace base { 21 namespace base {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 return; 55 return;
55 } 56 }
56 57
57 // Need real storage to store both what was in the single-sample plus the 58 // Need real storage to store both what was in the single-sample plus the
58 // parameter information. 59 // parameter information.
59 MountCountsStorageAndMoveSingleSample(); 60 MountCountsStorageAndMoveSingleSample();
60 } 61 }
61 62
62 // Handle the multi-sample case. 63 // Handle the multi-sample case.
63 subtle::NoBarrier_AtomicIncrement(&counts()[bucket_index], count); 64 subtle::NoBarrier_AtomicIncrement(&counts()[bucket_index], count);
64 IncreaseSumAndCount(static_cast<int64_t>(count) * value, count); 65 IncreaseSumAndCount(strict_cast<int64_t>(count) * value, count);
65 } 66 }
66 67
67 Count SampleVectorBase::GetCount(Sample value) const { 68 Count SampleVectorBase::GetCount(Sample value) const {
68 return GetCountAtIndex(GetBucketIndex(value)); 69 return GetCountAtIndex(GetBucketIndex(value));
69 } 70 }
70 71
71 Count SampleVectorBase::TotalCount() const { 72 Count SampleVectorBase::TotalCount() const {
72 // Handle the single-sample case. 73 // Handle the single-sample case.
73 SingleSample sample = single_sample().Load(); 74 SingleSample sample = single_sample().Load();
74 if (sample.count != 0) 75 if (sample.count != 0)
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 } 126 }
126 127
127 bool SampleVectorBase::AddSubtractImpl(SampleCountIterator* iter, 128 bool SampleVectorBase::AddSubtractImpl(SampleCountIterator* iter,
128 HistogramSamples::Operator op) { 129 HistogramSamples::Operator op) {
129 // Stop now if there's nothing to do. 130 // Stop now if there's nothing to do.
130 if (iter->Done()) 131 if (iter->Done())
131 return true; 132 return true;
132 133
133 // Get the first value and its index. 134 // Get the first value and its index.
134 HistogramBase::Sample min; 135 HistogramBase::Sample min;
135 HistogramBase::Sample max; 136 int64_t max;
136 HistogramBase::Count count; 137 HistogramBase::Count count;
137 iter->Get(&min, &max, &count); 138 iter->Get(&min, &max, &count);
138 size_t dest_index = GetBucketIndex(min); 139 size_t dest_index = GetBucketIndex(min);
139 140
140 // The destination must be a superset of the source meaning that though the 141 // The destination must be a superset of the source meaning that though the
141 // incoming ranges will find an exact match, the incoming bucket-index, if 142 // incoming ranges will find an exact match, the incoming bucket-index, if
142 // it exists, may be offset from the destination bucket-index. Calculate 143 // it exists, may be offset from the destination bucket-index. Calculate
143 // that offset of the passed iterator; there are are no overflow checks 144 // that offset of the passed iterator; there are are no overflow checks
144 // because 2's compliment math will work it out in the end. 145 // because 2's compliment math will work it out in the end.
145 // 146 //
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 return index_ >= counts_size_; 386 return index_ >= counts_size_;
386 } 387 }
387 388
388 void SampleVectorIterator::Next() { 389 void SampleVectorIterator::Next() {
389 DCHECK(!Done()); 390 DCHECK(!Done());
390 index_++; 391 index_++;
391 SkipEmptyBuckets(); 392 SkipEmptyBuckets();
392 } 393 }
393 394
394 void SampleVectorIterator::Get(HistogramBase::Sample* min, 395 void SampleVectorIterator::Get(HistogramBase::Sample* min,
395 HistogramBase::Sample* max, 396 int64_t* max,
396 HistogramBase::Count* count) const { 397 HistogramBase::Count* count) const {
397 DCHECK(!Done()); 398 DCHECK(!Done());
398 if (min != NULL) 399 if (min != NULL)
399 *min = bucket_ranges_->range(index_); 400 *min = bucket_ranges_->range(index_);
400 if (max != NULL) 401 if (max != NULL)
401 *max = bucket_ranges_->range(index_ + 1); 402 *max = strict_cast<int64_t>(bucket_ranges_->range(index_ + 1));
402 if (count != NULL) 403 if (count != NULL)
403 *count = subtle::NoBarrier_Load(&counts_[index_]); 404 *count = subtle::NoBarrier_Load(&counts_[index_]);
404 } 405 }
405 406
406 bool SampleVectorIterator::GetBucketIndex(size_t* index) const { 407 bool SampleVectorIterator::GetBucketIndex(size_t* index) const {
407 DCHECK(!Done()); 408 DCHECK(!Done());
408 if (index != NULL) 409 if (index != NULL)
409 *index = index_; 410 *index = index_;
410 return true; 411 return true;
411 } 412 }
412 413
413 void SampleVectorIterator::SkipEmptyBuckets() { 414 void SampleVectorIterator::SkipEmptyBuckets() {
414 if (Done()) 415 if (Done())
415 return; 416 return;
416 417
417 while (index_ < counts_size_) { 418 while (index_ < counts_size_) {
418 if (subtle::NoBarrier_Load(&counts_[index_]) != 0) 419 if (subtle::NoBarrier_Load(&counts_[index_]) != 0)
419 return; 420 return;
420 index_++; 421 index_++;
421 } 422 }
422 } 423 }
423 424
424 } // namespace base 425 } // namespace base
OLDNEW
« no previous file with comments | « base/metrics/sample_vector.h ('k') | base/metrics/sample_vector_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698