Skip to content

Commit 61029c5

Browse files
Puneetha-RamachandraCQ Bot
authored andcommitted
[audio][inspect] Make BufferTracker thread-safe
The BufferTracker class can be accessed from multiple threads, but it was not thread-safe. This could lead to data races when buffers are submitted and completed concurrently. This change introduces a mutex to protect the internal state of `BufferTracker`, ensuring that all access to its member variables is properly synchronized. Additionally, `ZX_ASSERT_MSG` calls were replaced with `FDF_LOG` to prevent crashing the driver in case of an unexpected state. Test: audio-inspect-recorder-test Bug: 462554546 Change-Id: I3dd3f1b88e4487e038fd9c95d8c5000991ebf348 Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/1429571 Reviewed-by: Martin Puryear <[email protected]> Fuchsia-Auto-Submit: Puneetha Ramachandra <[email protected]> Commit-Queue: Puneetha Ramachandra <[email protected]>
1 parent 550fae6 commit 61029c5

File tree

6 files changed

+33
-18
lines changed

6 files changed

+33
-18
lines changed

src/media/audio/drivers/lib/inspect/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ cc_library(
1717
],
1818
visibility = ["//visibility:public"],
1919
deps = [
20+
"@fuchsia_sdk//pkg/driver_logging_cpp",
2021
"@fuchsia_sdk//pkg/inspect",
2122
],
2223
)

src/media/audio/drivers/lib/inspect/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ test("recorder_test") {
2222
"task-metrics.h",
2323
]
2424
deps = [
25+
"//sdk/lib/driver/logging/cpp",
2526
"//sdk/lib/inspect/component/cpp",
2627
"//sdk/lib/inspect/testing/cpp",
2728
"//src/lib/fxl/test:gtest_main",

src/media/audio/drivers/lib/inspect/buffer-tracker.cc

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
#include "src/media/audio/drivers/lib/inspect/buffer-tracker.h"
55

6+
#include <lib/driver/logging/cpp/logger.h>
7+
68
namespace audio {
79

810
BufferTracker::BufferTracker(inspect::Node node, std::optional<uint32_t> max_buffer_count,
@@ -13,6 +15,7 @@ BufferTracker::BufferTracker(inspect::Node node, std::optional<uint32_t> max_buf
1315
max_buffer_count_(max_buffer_count) {
1416
avg_processing_time_us_ = node_.CreateLazyValues(
1517
"avg_processing_time_us", [this]() -> fpromise::promise<inspect::Inspector> {
18+
std::lock_guard<std::mutex> lock(mutex_);
1619
inspect::Inspector inspector;
1720
inspector.GetRoot().CreateUint("avg_processing_time_us",
1821
total_buffers_processed_ == 0
@@ -27,6 +30,7 @@ BufferTracker::BufferTracker(inspect::Node node, std::optional<uint32_t> max_buf
2730
max_empty_buffer_duration_us_ = node_.CreateUint("max_empty_buffer_duration_us", 0);
2831
avg_outstanding_buffer_count_ = node_.CreateLazyValues(
2932
"avg_outstanding_buffer_count", [this]() -> fpromise::promise<inspect::Inspector> {
33+
std::lock_guard<std::mutex> lock(mutex_);
3034
inspect::Inspector inspector;
3135
inspector.GetRoot().CreateUint(
3236
"avg_outstanding_buffer_count",
@@ -45,6 +49,7 @@ BufferTracker::BufferTracker(inspect::Node node, std::optional<uint32_t> max_buf
4549
if (per_buffer_duration_.has_value()) {
4650
total_buffers_processed_duration_us_ = node_.CreateLazyValues(
4751
"total_buffers_processed_duration_us", [this]() -> fpromise::promise<inspect::Inspector> {
52+
std::lock_guard<std::mutex> lock(mutex_);
4853
inspect::Inspector inspector;
4954
inspector.GetRoot().CreateUint(
5055
"total_buffers_processed_duration_us",
@@ -55,9 +60,12 @@ BufferTracker::BufferTracker(inspect::Node node, std::optional<uint32_t> max_buf
5560
}
5661

5762
void BufferTracker::RecordSubmission() {
58-
ZX_ASSERT_MSG(submission_times_.size() < max_buffer_count_.value_or(UINT_MAX),
59-
"Submission count (%lu) is more than or equal to max buffer count (%d).",
60-
submission_times_.size(), max_buffer_count_.value_or(UINT_MAX));
63+
std::lock_guard<std::mutex> lock(mutex_);
64+
if (submission_times_.size() >= max_buffer_count_.value_or(UINT_MAX)) {
65+
FDF_LOG(ERROR, "Submission count (%lu) is more than or equal to max buffer count (%d).",
66+
submission_times_.size(), max_buffer_count_.value_or(UINT_MAX));
67+
return;
68+
}
6169
auto submission_time = zx::clock::get_monotonic();
6270
if (submission_times_.empty()) {
6371
if (empty_buffer_start_time_.get() != 0) {
@@ -80,11 +88,12 @@ void BufferTracker::RecordSubmission() {
8088
}
8189

8290
void BufferTracker::RecordCompletion() {
91+
std::lock_guard<std::mutex> lock(mutex_);
8392
auto completion_time = zx::clock::get_monotonic();
84-
ZX_ASSERT_MSG(!submission_times_.empty(), "We have completed more buffers than submitted.");
85-
ZX_ASSERT_MSG(submission_times_.size() <= max_buffer_count_.value_or(UINT_MAX),
86-
"Submission count (%lu) is more than the max buffer count (%d).",
87-
submission_times_.size(), max_buffer_count_.value_or(UINT_MAX));
93+
if (submission_times_.empty()) {
94+
FDF_LOG(ERROR, "No buffers submitted to this tracker yet.");
95+
return;
96+
}
8897
if (max_buffer_count_.has_value() && submission_times_.size() == max_buffer_count_.value()) {
8998
if (full_buffer_start_time_.get() != 0) {
9099
const zx::duration duration = completion_time - full_buffer_start_time_;

src/media/audio/drivers/lib/inspect/buffer-tracker.h

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
#include <lib/inspect/cpp/vmo/types.h>
99
#include <lib/zx/clock.h>
1010
#include <lib/zx/time.h>
11+
#include <zircon/compiler.h>
1112

1213
#include <format>
14+
#include <mutex>
1315
#include <queue>
1416

1517
namespace audio {
@@ -28,33 +30,34 @@ class BufferTracker {
2830
// Processing time metrics.
2931
inspect::LazyNode avg_processing_time_us_;
3032
inspect::UintProperty max_processing_time_us_;
31-
uint64_t total_processing_time_us_ = 0;
32-
zx::duration max_processing_time_ = zx::duration::infinite_past();
33+
uint64_t total_processing_time_us_ __TA_GUARDED(mutex_) = 0;
34+
zx::duration max_processing_time_ __TA_GUARDED(mutex_) = zx::duration::infinite_past();
3335

3436
// Empty buffer metrics.
3537
inspect::UintProperty total_empty_buffer_duration_us_;
3638
inspect::UintProperty empty_buffer_episode_count_;
3739
inspect::UintProperty max_empty_buffer_duration_us_;
38-
zx::duration max_empty_buffer_duration_ = zx::duration::infinite_past();
40+
zx::duration max_empty_buffer_duration_ __TA_GUARDED(mutex_) = zx::duration::infinite_past();
3941

4042
// Full buffer metrics.
4143
std::optional<inspect::UintProperty> total_full_buffer_duration_us_;
4244
std::optional<inspect::UintProperty> full_buffer_episode_count_;
4345
std::optional<inspect::UintProperty> max_full_buffer_duration_us_;
44-
zx::duration max_full_buffer_duration_ = zx::duration::infinite_past();
46+
zx::duration max_full_buffer_duration_ __TA_GUARDED(mutex_) = zx::duration::infinite_past();
4547

4648
// Outstanding buffer metrics.
4749
inspect::LazyNode avg_outstanding_buffer_count_;
4850
inspect::UintProperty total_buffers_processed_count_;
49-
uint64_t cumulative_outstanding_buffer_count_ = 0;
50-
uint64_t total_buffers_processed_ = 0;
51+
uint64_t cumulative_outstanding_buffer_count_ __TA_GUARDED(mutex_) = 0;
52+
uint64_t total_buffers_processed_ __TA_GUARDED(mutex_) = 0;
5153
std::optional<inspect::LazyNode> total_buffers_processed_duration_us_;
5254
std::optional<zx::duration> per_buffer_duration_;
5355

54-
std::queue<zx::time> submission_times_;
55-
zx::time empty_buffer_start_time_ = zx::time(0);
56-
zx::time full_buffer_start_time_ = zx::time(0);
56+
std::queue<zx::time> submission_times_ __TA_GUARDED(mutex_);
57+
zx::time empty_buffer_start_time_ __TA_GUARDED(mutex_) = zx::time(0);
58+
zx::time full_buffer_start_time_ __TA_GUARDED(mutex_) = zx::time(0);
5759
std::optional<uint32_t> max_buffer_count_;
60+
std::mutex mutex_;
5861
};
5962

6063
} // namespace audio

src/media/audio/drivers/lib/inspect/recorder.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,8 @@ void AggregateRecords::RecordTaskMetrics(const Subtask::Metrics& metrics,
193193
void AggregateRecords::SetupBufferTracker(inspect::Node& node, const std::string& name,
194194
std::optional<uint32_t> max_buffer_count,
195195
std::optional<zx::duration> per_buffer_duration) {
196-
buffer_tracker_.emplace(node.CreateChild(name), max_buffer_count, per_buffer_duration);
196+
buffer_tracker_ = std::make_unique<BufferTracker>(node.CreateChild(name), max_buffer_count,
197+
per_buffer_duration);
197198
}
198199

199200
void AggregateRecords::RecordBufferSubmission() {

src/media/audio/drivers/lib/inspect/recorder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ class AggregateRecords {
184184
int64_t worst_overrun_frames_ = 0;
185185
size_t total_task_count_ = 0;
186186
size_t total_thread_metrics_count_ = 0;
187-
std::optional<BufferTracker> buffer_tracker_;
187+
std::unique_ptr<BufferTracker> buffer_tracker_;
188188
std::optional<zx::duration> task_schedule_interval_;
189189
};
190190

0 commit comments

Comments
 (0)