metrics: Create Template for Sharing Metrics Data Between Processes
Create a template that contains metrics data and is guarded by a lock
so that the metrics data can be shared between processes.
Bug: 1151343
Change-Id: Ic365f837e385ac984f47d883f3f5104702d2ed35
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2644749
Commit-Queue: weiliangc <weiliangc@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Steve Kobes <skobes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#848183}
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index 8c8f34b..9c44e43e 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -192,6 +192,7 @@
"metrics/latency_ukm_reporter.h",
"metrics/lcd_text_metrics_reporter.cc",
"metrics/lcd_text_metrics_reporter.h",
+ "metrics/shared_metrics_buffer.h",
"metrics/throughput_ukm_reporter.cc",
"metrics/throughput_ukm_reporter.h",
"metrics/total_frame_counter.cc",
diff --git a/cc/metrics/OWNERS b/cc/metrics/OWNERS
index 0cb4f83e..39db757 100644
--- a/cc/metrics/OWNERS
+++ b/cc/metrics/OWNERS
@@ -1,2 +1,4 @@
per-file ukm_smoothness_data.h=set noparent
per-file ukm_smoothness_data.h=file://ipc/SECURITY_OWNERS
+per-file shared_metrics_buffer.h=set noparent
+per-file shared_metrics_buffer.h=file://ipc/SECURITY_OWNERS
diff --git a/cc/metrics/dropped_frame_counter.cc b/cc/metrics/dropped_frame_counter.cc
index 818de70..18e2925c 100644
--- a/cc/metrics/dropped_frame_counter.cc
+++ b/cc/metrics/dropped_frame_counter.cc
@@ -163,12 +163,7 @@
static_cast<double>(total_smoothness_dropped_) * 100 / total_frames;
smoothness_data.worst_smoothness = sliding_window_max_percent_dropped_;
smoothness_data.percentile_95 = sliding_window_95pct_percent_dropped;
-
- ukm_smoothness_data_->seq_lock.WriteBegin();
- device::OneWriterSeqLock::AtomicWriterMemcpy(&ukm_smoothness_data_->data,
- &smoothness_data,
- sizeof(UkmSmoothnessData));
- ukm_smoothness_data_->seq_lock.WriteEnd();
+ ukm_smoothness_data_->Write(smoothness_data);
}
}
diff --git a/cc/metrics/dropped_frame_counter.h b/cc/metrics/dropped_frame_counter.h
index 153d0ff..72bc46d 100644
--- a/cc/metrics/dropped_frame_counter.h
+++ b/cc/metrics/dropped_frame_counter.h
@@ -12,10 +12,10 @@
#include "base/containers/ring_buffer.h"
#include "cc/cc_export.h"
#include "cc/metrics/frame_sorter.h"
+#include "cc/metrics/ukm_smoothness_data.h"
namespace cc {
class TotalFrameCounter;
-struct UkmSmoothnessDataShared;
// This class maintains a counter for produced/dropped frames, and can be used
// to estimate the recent throughput.
diff --git a/cc/metrics/shared_metrics_buffer.h b/cc/metrics/shared_metrics_buffer.h
new file mode 100644
index 0000000..5167a77
--- /dev/null
+++ b/cc/metrics/shared_metrics_buffer.h
@@ -0,0 +1,46 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_METRICS_SHARED_METRICS_BUFFER_H_
+#define CC_METRICS_SHARED_METRICS_BUFFER_H_
+
+#include "device/base/synchronization/one_writer_seqlock.h"
+
+namespace cc {
+// The struct written in shared memory to transport metrics across
+// processes. |data| is protected by the sequence-lock |seq_lock|.
+// Note: This template copies data between processes. Any class that uses this
+// template would need security review.
+template <class T>
+struct SharedMetricsBuffer {
+ device::OneWriterSeqLock seq_lock;
+ T data;
+ static_assert(std::is_trivially_copyable<T>::value,
+ "Metrics shared across processes need to be trivially "
+ "copyable, otherwise it is dangerous to copy it.");
+
+ bool Read(T& out) const {
+ const uint32_t kMaxRetries = 5;
+ uint32_t retries = 0;
+ base::subtle::Atomic32 version;
+ do {
+ const uint32_t kMaxReadAttempts = 32;
+ version = seq_lock.ReadBegin(kMaxReadAttempts);
+ device::OneWriterSeqLock::AtomicReaderMemcpy(&out, &data, sizeof(T));
+ } while (seq_lock.ReadRetry(version) && ++retries < kMaxRetries);
+
+ // Consider the number of retries less than kMaxRetries as success.
+ return retries < kMaxRetries;
+ }
+
+ void Write(const T& in) {
+ seq_lock.WriteBegin();
+ device::OneWriterSeqLock::AtomicWriterMemcpy(&data, &in, sizeof(T));
+ seq_lock.WriteEnd();
+ }
+};
+
+} // namespace cc
+
+#endif // CC_METRICS_SHARED_METRICS_BUFFER_H_
diff --git a/cc/metrics/ukm_smoothness_data.h b/cc/metrics/ukm_smoothness_data.h
index 2bb5118..d4b95533 100644
--- a/cc/metrics/ukm_smoothness_data.h
+++ b/cc/metrics/ukm_smoothness_data.h
@@ -5,7 +5,7 @@
#ifndef CC_METRICS_UKM_SMOOTHNESS_DATA_H_
#define CC_METRICS_UKM_SMOOTHNESS_DATA_H_
-#include "device/base/synchronization/one_writer_seqlock.h"
+#include "cc/metrics/shared_metrics_buffer.h"
namespace cc {
@@ -19,12 +19,7 @@
double percentile_95 = 0.0;
};
-// The struct written in shared memory to transport UkmSmoothnessData across
-// processes. |data| is protected by the sequence-lock |seq_lock|.
-struct UkmSmoothnessDataShared {
- device::OneWriterSeqLock seq_lock;
- struct UkmSmoothnessData data;
-};
+using UkmSmoothnessDataShared = SharedMetricsBuffer<UkmSmoothnessData>;
} // namespace cc