Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 517e5c4d authored by Tianyu Jiang's avatar Tianyu Jiang Committed by Android (Google) Code Review
Browse files

Merge "Post to all existing and non-existing consumers of the buffer"

parents 2501ad90 e60a4ad3
Loading
Loading
Loading
Loading
+9 −17
Original line number Original line Diff line number Diff line
@@ -361,9 +361,11 @@ TEST_F(LibBufferHubTest, TestGainPostedBuffer_noConsumer) {
  ASSERT_TRUE(p.get() != nullptr);
  ASSERT_TRUE(p.get() != nullptr);
  ASSERT_EQ(0, p->GainAsync());
  ASSERT_EQ(0, p->GainAsync());
  ASSERT_EQ(0, p->Post(LocalHandle()));
  ASSERT_EQ(0, p->Post(LocalHandle()));
  // Producer state bit is in released state after post. The overall state of
  // Producer state bit is in released state after post, other clients shall be
  // the buffer is also released because there is no consumer of this buffer.
  // in posted state although there is no consumer of this buffer yet.
  ASSERT_TRUE(IsBufferReleased(p->buffer_state()));
  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.
  // Gain in released state should succeed.
  LocalHandle invalid_fence;
  LocalHandle invalid_fence;
@@ -450,27 +452,17 @@ TEST_F(LibBufferHubTest, TestCreateTheFirstConsumerAfterPostingBuffer) {
  LocalHandle invalid_fence;
  LocalHandle invalid_fence;


  // Post the gained buffer before any consumer gets created.
  // 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_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)));
  EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));


  // Newly created consumer will not be signalled for the posted buffer before
  // Newly created consumer will be signalled for the posted buffer although it
  // its creation. It cannot acquire the buffer immediately.
  // is created after producer posting.
  std::unique_ptr<ConsumerBuffer> c =
  std::unique_ptr<ConsumerBuffer> c =
      ConsumerBuffer::Import(p->CreateConsumer());
      ConsumerBuffer::Import(p->CreateConsumer());
  ASSERT_TRUE(c.get() != nullptr);
  ASSERT_TRUE(c.get() != nullptr);
  EXPECT_FALSE(IsClientPosted(c->buffer_state(), c->client_state_mask()));
  EXPECT_TRUE(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_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
  EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
  EXPECT_TRUE(IsClientAcquired(c->buffer_state(), c->client_state_mask()));
}
}


TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferReleased) {
TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferReleased) {
+6 −0
Original line number Original line Diff line number Diff line
@@ -94,6 +94,12 @@ class BufferHubBase : public pdx::Client {
    return buffer_state_->load(std::memory_order_acquire);
    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
  // A state mask which is unique to a buffer hub client among all its siblings
  // sharing the same concrete graphic buffer.
  // sharing the same concrete graphic buffer.
  uint32_t client_state_mask() const { return client_state_mask_; }
  uint32_t client_state_mask() const { return client_state_mask_; }
+10 −9
Original line number Original line Diff line number Diff line
@@ -89,13 +89,10 @@ int ProducerBuffer::LocalPost(const DvrNativeBufferMetadata* meta,
    return -EBUSY;
    return -EBUSY;
  }
  }


  // Set the producer client buffer state to released, other clients' buffer
  // Set the producer client buffer state to released, that of all other clients
  // state to posted.
  // (both existing and non-existing clients) to posted.
  uint32_t current_active_clients_bit_mask =
  uint32_t updated_buffer_state =
      active_clients_bit_mask_->load(std::memory_order_acquire);
      (~client_state_mask()) & BufferHubDefs::kHighBitsMask;
  uint32_t updated_buffer_state = current_active_clients_bit_mask &
                                  (~client_state_mask()) &
                                  BufferHubDefs::kHighBitsMask;
  while (!buffer_state_->compare_exchange_weak(
  while (!buffer_state_->compare_exchange_weak(
      current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
      current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
      std::memory_order_acquire)) {
      std::memory_order_acquire)) {
@@ -176,7 +173,9 @@ int ProducerBuffer::LocalGain(DvrNativeBufferMetadata* out_meta,
  }
  }
  if (BufferHubDefs::AnyClientAcquired(current_buffer_state) ||
  if (BufferHubDefs::AnyClientAcquired(current_buffer_state) ||
      BufferHubDefs::AnyClientGained(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)) {
       !gain_posted_buffer)) {
    ALOGE("%s: not released id=%d state=%" PRIx32 ".", __FUNCTION__, id(),
    ALOGE("%s: not released id=%d state=%" PRIx32 ".", __FUNCTION__, id(),
          current_buffer_state);
          current_buffer_state);
@@ -198,7 +197,9 @@ int ProducerBuffer::LocalGain(DvrNativeBufferMetadata* out_meta,


    if (BufferHubDefs::AnyClientAcquired(current_buffer_state) ||
    if (BufferHubDefs::AnyClientAcquired(current_buffer_state) ||
        BufferHubDefs::AnyClientGained(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)) {
         !gain_posted_buffer)) {
      ALOGE(
      ALOGE(
          "%s: Failed to gain the buffer. The buffer is no longer released. "
          "%s: Failed to gain the buffer. The buffer is no longer released. "
+15 −3
Original line number Original line Diff line number Diff line
@@ -369,7 +369,9 @@ Status<RemoteChannelHandle> ProducerChannel::CreateConsumer(
          (consumer_state_mask & BufferHubDefs::kHighBitsMask);
          (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();
    consumer->OnProducerPosted();
  }
  }


@@ -537,8 +539,13 @@ Status<void> ProducerChannel::OnConsumerRelease(Message&,


  uint32_t current_buffer_state =
  uint32_t current_buffer_state =
      buffer_state_->load(std::memory_order_acquire);
      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 &
  if (BufferHubDefs::IsBufferReleased(current_buffer_state &
                                      ~orphaned_consumer_bit_mask_)) {
                                      ~orphaned_consumer_bit_mask_ &
                                      current_active_clients_bit_mask)) {
    buffer_state_->store(0U);
    SignalAvailable();
    SignalAvailable();
    if (orphaned_consumer_bit_mask_) {
    if (orphaned_consumer_bit_mask_) {
      ALOGW(
      ALOGW(
@@ -564,8 +571,13 @@ void ProducerChannel::OnConsumerOrphaned(const uint32_t& consumer_state_mask) {


  uint32_t current_buffer_state =
  uint32_t current_buffer_state =
      buffer_state_->load(std::memory_order_acquire);
      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 &
  if (BufferHubDefs::IsBufferReleased(current_buffer_state &
                                      ~orphaned_consumer_bit_mask_)) {
                                      ~orphaned_consumer_bit_mask_ &
                                      current_active_clients_bit_mask)) {
    buffer_state_->store(0U);
    SignalAvailable();
    SignalAvailable();
  }
  }