Merge "Post to all existing and non-existing consumers of the buffer"
diff --git a/libs/vr/libbufferhub/buffer_hub-test.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp
index 1359f4c..487a604 100644
--- a/libs/vr/libbufferhub/buffer_hub-test.cpp
+++ b/libs/vr/libbufferhub/buffer_hub-test.cpp
@@ -361,9 +361,11 @@
ASSERT_TRUE(p.get() != nullptr);
ASSERT_EQ(0, p->GainAsync());
ASSERT_EQ(0, p->Post(LocalHandle()));
- // Producer state bit is in released state after post. The overall state of
- // the buffer is also released because there is no consumer of this buffer.
- ASSERT_TRUE(IsBufferReleased(p->buffer_state()));
+ // Producer state bit is in released state after post, other clients shall be
+ // in posted state although there is no consumer of this buffer yet.
+ ASSERT_TRUE(IsClientReleased(p->buffer_state(), p->client_state_mask()));
+ ASSERT_FALSE(IsBufferReleased(p->buffer_state()));
+ ASSERT_TRUE(AnyClientPosted(p->buffer_state()));
// Gain in released state should succeed.
LocalHandle invalid_fence;
@@ -450,27 +452,17 @@
LocalHandle invalid_fence;
// Post the gained buffer before any consumer gets created.
- // The buffer should be in released state because it is not expected to be
- // read by any clients.
EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
- EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
+ EXPECT_FALSE(IsBufferReleased(p->buffer_state()));
EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
- // Newly created consumer will not be signalled for the posted buffer before
- // its creation. It cannot acquire the buffer immediately.
+ // Newly created consumer will be signalled for the posted buffer although it
+ // is created after producer posting.
std::unique_ptr<ConsumerBuffer> c =
ConsumerBuffer::Import(p->CreateConsumer());
ASSERT_TRUE(c.get() != nullptr);
- EXPECT_FALSE(IsClientPosted(c->buffer_state(), c->client_state_mask()));
- EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
-
- // Producer should be able to gain back and post the buffer
- EXPECT_EQ(0, p->GainAsync());
- EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
-
- // Consumer should be able to pick up the buffer this time.
+ EXPECT_TRUE(IsClientPosted(c->buffer_state(), c->client_state_mask()));
EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
- EXPECT_TRUE(IsClientAcquired(c->buffer_state(), c->client_state_mask()));
}
TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferReleased) {
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
index 440a59d..889763a 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
@@ -94,6 +94,12 @@
return buffer_state_->load(std::memory_order_acquire);
};
+ // Returns whether the buffer is already released by all current clients.
+ bool is_released() {
+ return (buffer_state() &
+ active_clients_bit_mask_->load(std::memory_order_acquire)) == 0;
+ }
+
// A state mask which is unique to a buffer hub client among all its siblings
// sharing the same concrete graphic buffer.
uint32_t client_state_mask() const { return client_state_mask_; }
diff --git a/libs/vr/libbufferhub/producer_buffer.cpp b/libs/vr/libbufferhub/producer_buffer.cpp
index 5274bf2..edfdddf 100644
--- a/libs/vr/libbufferhub/producer_buffer.cpp
+++ b/libs/vr/libbufferhub/producer_buffer.cpp
@@ -89,13 +89,10 @@
return -EBUSY;
}
- // Set the producer client buffer state to released, other clients' buffer
- // state to posted.
- uint32_t current_active_clients_bit_mask =
- active_clients_bit_mask_->load(std::memory_order_acquire);
- uint32_t updated_buffer_state = current_active_clients_bit_mask &
- (~client_state_mask()) &
- BufferHubDefs::kHighBitsMask;
+ // Set the producer client buffer state to released, that of all other clients
+ // (both existing and non-existing clients) to posted.
+ uint32_t updated_buffer_state =
+ (~client_state_mask()) & BufferHubDefs::kHighBitsMask;
while (!buffer_state_->compare_exchange_weak(
current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
std::memory_order_acquire)) {
@@ -176,7 +173,9 @@
}
if (BufferHubDefs::AnyClientAcquired(current_buffer_state) ||
BufferHubDefs::AnyClientGained(current_buffer_state) ||
- (BufferHubDefs::AnyClientPosted(current_buffer_state) &&
+ (BufferHubDefs::AnyClientPosted(
+ current_buffer_state &
+ active_clients_bit_mask_->load(std::memory_order_acquire)) &&
!gain_posted_buffer)) {
ALOGE("%s: not released id=%d state=%" PRIx32 ".", __FUNCTION__, id(),
current_buffer_state);
@@ -198,7 +197,9 @@
if (BufferHubDefs::AnyClientAcquired(current_buffer_state) ||
BufferHubDefs::AnyClientGained(current_buffer_state) ||
- (BufferHubDefs::AnyClientPosted(current_buffer_state) &&
+ (BufferHubDefs::AnyClientPosted(
+ current_buffer_state &
+ active_clients_bit_mask_->load(std::memory_order_acquire)) &&
!gain_posted_buffer)) {
ALOGE(
"%s: Failed to gain the buffer. The buffer is no longer released. "
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index 2a6e9da..409bce9 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -369,7 +369,9 @@
(consumer_state_mask & BufferHubDefs::kHighBitsMask);
}
}
- if (update_buffer_state) {
+ if (update_buffer_state || BufferHubDefs::IsClientPosted(
+ buffer_state_->load(std::memory_order_acquire),
+ consumer_state_mask)) {
consumer->OnProducerPosted();
}
@@ -537,8 +539,13 @@
uint32_t current_buffer_state =
buffer_state_->load(std::memory_order_acquire);
+ uint32_t current_active_clients_bit_mask =
+ active_clients_bit_mask_->load(std::memory_order_acquire);
+ // Signal producer if all current active consumers have released the buffer.
if (BufferHubDefs::IsBufferReleased(current_buffer_state &
- ~orphaned_consumer_bit_mask_)) {
+ ~orphaned_consumer_bit_mask_ &
+ current_active_clients_bit_mask)) {
+ buffer_state_->store(0U);
SignalAvailable();
if (orphaned_consumer_bit_mask_) {
ALOGW(
@@ -564,8 +571,13 @@
uint32_t current_buffer_state =
buffer_state_->load(std::memory_order_acquire);
+ uint32_t current_active_clients_bit_mask =
+ active_clients_bit_mask_->load(std::memory_order_acquire);
+ // Signal producer if all current active consumers have released the buffer.
if (BufferHubDefs::IsBufferReleased(current_buffer_state &
- ~orphaned_consumer_bit_mask_)) {
+ ~orphaned_consumer_bit_mask_ &
+ current_active_clients_bit_mask)) {
+ buffer_state_->store(0U);
SignalAvailable();
}