blob: 895dee0701213b541df583288c63d844adbbc5fb [file] [log] [blame]
Corey Tabaka52ea25c2017-09-13 18:02:48 -07001#include <sys/epoll.h>
2#include <sys/eventfd.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08003#include <sys/poll.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08004
5#include <algorithm>
6#include <atomic>
7#include <thread>
8
Fan Xu74df4902018-09-20 16:40:51 -07009#include <log/log.h>
Tianyu0c6b7ff2018-10-03 11:30:04 -070010#include <private/dvr/bufferhub_rpc.h>
Fan Xu74df4902018-09-20 16:40:51 -070011#include <private/dvr/consumer_channel.h>
12#include <private/dvr/producer_channel.h>
13#include <sync/sync.h>
14#include <utils/Trace.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080015
16using android::pdx::BorrowedHandle;
Corey Tabakacd52dd92017-04-07 18:03:57 -070017using android::pdx::ErrorStatus;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080018using android::pdx::Message;
19using android::pdx::RemoteChannelHandle;
Corey Tabakacd52dd92017-04-07 18:03:57 -070020using android::pdx::Status;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080021using android::pdx::rpc::BufferWrapper;
22using android::pdx::rpc::DispatchRemoteMethod;
23using android::pdx::rpc::WrapBuffer;
24
25namespace android {
26namespace dvr {
27
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -070028ProducerChannel::ProducerChannel(BufferHubService* service, int buffer_id,
29 int channel_id, IonBuffer buffer,
30 IonBuffer metadata_buffer,
31 size_t user_metadata_size, int* error)
32 : BufferHubChannel(service, buffer_id, channel_id, kProducerType),
33 buffer_(std::move(buffer)),
34 metadata_buffer_(std::move(metadata_buffer)),
35 user_metadata_size_(user_metadata_size),
36 metadata_buf_size_(BufferHubDefs::kMetadataHeaderSize +
37 user_metadata_size) {
38 if (!buffer_.IsValid()) {
39 ALOGE("ProducerChannel::ProducerChannel: Invalid buffer.");
40 *error = -EINVAL;
41 return;
42 }
43 if (!metadata_buffer_.IsValid()) {
44 ALOGE("ProducerChannel::ProducerChannel: Invalid metadata buffer.");
45 *error = -EINVAL;
46 return;
47 }
48
49 *error = InitializeBuffer();
50}
51
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080052ProducerChannel::ProducerChannel(BufferHubService* service, int channel_id,
Corey Tabakacd52dd92017-04-07 18:03:57 -070053 uint32_t width, uint32_t height,
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -070054 uint32_t layer_count, uint32_t format,
Corey Tabaka52ea25c2017-09-13 18:02:48 -070055 uint64_t usage, size_t user_metadata_size,
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -070056 int* error)
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080057 : BufferHubChannel(service, channel_id, channel_id, kProducerType),
Corey Tabaka52ea25c2017-09-13 18:02:48 -070058 user_metadata_size_(user_metadata_size),
59 metadata_buf_size_(BufferHubDefs::kMetadataHeaderSize +
60 user_metadata_size) {
61 if (int ret = buffer_.Alloc(width, height, layer_count, format, usage)) {
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -070062 ALOGE("ProducerChannel::ProducerChannel: Failed to allocate buffer: %s",
63 strerror(-ret));
64 *error = ret;
65 return;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080066 }
67
Corey Tabaka52ea25c2017-09-13 18:02:48 -070068 if (int ret = metadata_buffer_.Alloc(metadata_buf_size_, /*height=*/1,
69 /*layer_count=*/1,
70 BufferHubDefs::kMetadataFormat,
71 BufferHubDefs::kMetadataUsage)) {
72 ALOGE("ProducerChannel::ProducerChannel: Failed to allocate metadata: %s",
73 strerror(-ret));
74 *error = ret;
75 return;
76 }
77
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -070078 *error = InitializeBuffer();
79}
80
81int ProducerChannel::InitializeBuffer() {
Corey Tabaka52ea25c2017-09-13 18:02:48 -070082 void* metadata_ptr = nullptr;
83 if (int ret = metadata_buffer_.Lock(BufferHubDefs::kMetadataUsage, /*x=*/0,
84 /*y=*/0, metadata_buf_size_,
85 /*height=*/1, &metadata_ptr)) {
86 ALOGE("ProducerChannel::ProducerChannel: Failed to lock metadata.");
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -070087 return ret;
Corey Tabaka52ea25c2017-09-13 18:02:48 -070088 }
89 metadata_header_ =
90 reinterpret_cast<BufferHubDefs::MetadataHeader*>(metadata_ptr);
91
92 // Using placement new here to reuse shared memory instead of new allocation
93 // and also initialize the value to zero.
94 buffer_state_ =
Tianyu Jianga99f9112018-12-13 18:23:07 -080095 new (&metadata_header_->buffer_state) std::atomic<uint32_t>(0);
96 fence_state_ = new (&metadata_header_->fence_state) std::atomic<uint32_t>(0);
Tianyu67053492018-10-04 14:00:22 -070097 active_clients_bit_mask_ =
Tianyu Jianga99f9112018-12-13 18:23:07 -080098 new (&metadata_header_->active_clients_bit_mask) std::atomic<uint32_t>(0);
Corey Tabaka52ea25c2017-09-13 18:02:48 -070099
Tianyu Jiang63dd7c32018-10-30 18:35:06 -0700100 // Producer channel is never created after consumer channel, and one buffer
101 // only have one fixed producer for now. Thus, it is correct to assume
102 // producer state bit is kFirstClientBitMask for now.
103 active_clients_bit_mask_->store(BufferHubDefs::kFirstClientBitMask,
104 std::memory_order_release);
105
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700106 acquire_fence_fd_.Reset(epoll_create1(EPOLL_CLOEXEC));
107 release_fence_fd_.Reset(epoll_create1(EPOLL_CLOEXEC));
108 if (!acquire_fence_fd_ || !release_fence_fd_) {
109 ALOGE("ProducerChannel::ProducerChannel: Failed to create shared fences.");
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -0700110 return -EIO;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700111 }
112
113 dummy_fence_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
114 if (!dummy_fence_fd_) {
115 ALOGE("ProducerChannel::ProducerChannel: Failed to create dummy fences.");
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -0700116 return EIO;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700117 }
118
119 epoll_event event;
120 event.events = 0;
Tianyu Jianga99f9112018-12-13 18:23:07 -0800121 event.data.u32 = 0U;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700122 if (epoll_ctl(release_fence_fd_.Get(), EPOLL_CTL_ADD, dummy_fence_fd_.Get(),
123 &event) < 0) {
124 ALOGE(
125 "ProducerChannel::ProducerChannel: Failed to modify the shared "
126 "release fence to include the dummy fence: %s",
127 strerror(errno));
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -0700128 return -EIO;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700129 }
130
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800131 // Success.
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -0700132 return 0;
133}
134
135std::unique_ptr<ProducerChannel> ProducerChannel::Create(
136 BufferHubService* service, int buffer_id, int channel_id, IonBuffer buffer,
137 IonBuffer metadata_buffer, size_t user_metadata_size) {
138 int error = 0;
139 std::unique_ptr<ProducerChannel> producer(new ProducerChannel(
140 service, buffer_id, channel_id, std::move(buffer),
141 std::move(metadata_buffer), user_metadata_size, &error));
142
143 if (error < 0)
144 return nullptr;
145 else
146 return producer;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800147}
148
Corey Tabakacd52dd92017-04-07 18:03:57 -0700149Status<std::shared_ptr<ProducerChannel>> ProducerChannel::Create(
150 BufferHubService* service, int channel_id, uint32_t width, uint32_t height,
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700151 uint32_t layer_count, uint32_t format, uint64_t usage,
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700152 size_t user_metadata_size) {
Corey Tabakacd52dd92017-04-07 18:03:57 -0700153 int error;
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -0700154 std::shared_ptr<ProducerChannel> producer(
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700155 new ProducerChannel(service, channel_id, width, height, layer_count,
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700156 format, usage, user_metadata_size, &error));
Corey Tabakacd52dd92017-04-07 18:03:57 -0700157 if (error < 0)
158 return ErrorStatus(-error);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800159 else
Corey Tabakacd52dd92017-04-07 18:03:57 -0700160 return {std::move(producer)};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800161}
162
163ProducerChannel::~ProducerChannel() {
Corey Tabaka3079cb72017-01-19 15:07:26 -0800164 ALOGD_IF(TRACE,
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700165 "ProducerChannel::~ProducerChannel: channel_id=%d buffer_id=%d "
Tianyu Jianga99f9112018-12-13 18:23:07 -0800166 "state=%" PRIx32 ".",
Tianyu Jiange2cdec92018-10-30 17:40:58 -0700167 channel_id(), buffer_id(),
168 buffer_state_->load(std::memory_order_acquire));
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700169 for (auto consumer : consumer_channels_) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800170 consumer->OnProducerClosed();
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700171 }
172 Hangup();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800173}
174
175BufferHubChannel::BufferInfo ProducerChannel::GetBufferInfo() const {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700176 // Derive the mask of signaled buffers in this producer / consumer set.
Tianyu Jianga99f9112018-12-13 18:23:07 -0800177 uint32_t signaled_mask = signaled() ? BufferHubDefs::kFirstClientBitMask : 0;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700178 for (const ConsumerChannel* consumer : consumer_channels_) {
Tianyu Jiang83a991f2018-10-30 16:59:29 -0700179 signaled_mask |= consumer->signaled() ? consumer->client_state_mask() : 0;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700180 }
181
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -0700182 return BufferInfo(buffer_id(), consumer_channels_.size(), buffer_.width(),
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700183 buffer_.height(), buffer_.layer_count(), buffer_.format(),
Tianyu Jiang0cdd2a02018-11-15 10:20:45 -0800184 buffer_.usage(),
Tianyu Jiange2cdec92018-10-30 17:40:58 -0700185 buffer_state_->load(std::memory_order_acquire),
Jiwen 'Steve' Cai2f260332018-02-15 18:39:47 -0800186 signaled_mask, metadata_header_->queue_index);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800187}
188
189void ProducerChannel::HandleImpulse(Message& message) {
190 ATRACE_NAME("ProducerChannel::HandleImpulse");
191 switch (message.GetOp()) {
192 case BufferHubRPC::ProducerGain::Opcode:
193 OnProducerGain(message);
194 break;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700195 case BufferHubRPC::ProducerPost::Opcode:
196 OnProducerPost(message, {});
197 break;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800198 }
199}
200
201bool ProducerChannel::HandleMessage(Message& message) {
202 ATRACE_NAME("ProducerChannel::HandleMessage");
203 switch (message.GetOp()) {
204 case BufferHubRPC::GetBuffer::Opcode:
205 DispatchRemoteMethod<BufferHubRPC::GetBuffer>(
206 *this, &ProducerChannel::OnGetBuffer, message);
207 return true;
208
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800209 case BufferHubRPC::NewConsumer::Opcode:
210 DispatchRemoteMethod<BufferHubRPC::NewConsumer>(
211 *this, &ProducerChannel::OnNewConsumer, message);
212 return true;
213
214 case BufferHubRPC::ProducerPost::Opcode:
215 DispatchRemoteMethod<BufferHubRPC::ProducerPost>(
216 *this, &ProducerChannel::OnProducerPost, message);
217 return true;
218
219 case BufferHubRPC::ProducerGain::Opcode:
220 DispatchRemoteMethod<BufferHubRPC::ProducerGain>(
221 *this, &ProducerChannel::OnProducerGain, message);
222 return true;
223
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800224 default:
225 return false;
226 }
227}
228
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700229BufferDescription<BorrowedHandle> ProducerChannel::GetBuffer(
Tianyu Jianga99f9112018-12-13 18:23:07 -0800230 uint32_t client_state_mask) {
Jiwen 'Steve' Cai57ae3ee2018-05-03 17:51:52 -0700231 return {buffer_,
232 metadata_buffer_,
233 buffer_id(),
234 channel_id(),
Tianyu Jiang7e204b72018-10-26 15:39:18 -0700235 client_state_mask,
Jiwen 'Steve' Cai57ae3ee2018-05-03 17:51:52 -0700236 acquire_fence_fd_.Borrow(),
237 release_fence_fd_.Borrow()};
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700238}
239
240Status<BufferDescription<BorrowedHandle>> ProducerChannel::OnGetBuffer(
Corey Tabakad53870c2017-07-06 18:04:27 -0700241 Message& /*message*/) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800242 ATRACE_NAME("ProducerChannel::OnGetBuffer");
Tianyu Jianga99f9112018-12-13 18:23:07 -0800243 ALOGD_IF(TRACE, "ProducerChannel::OnGetBuffer: buffer=%d, state=%" PRIx32 ".",
Tianyu Jiange2cdec92018-10-30 17:40:58 -0700244 buffer_id(), buffer_state_->load(std::memory_order_acquire));
Tianyu Jiang63dd7c32018-10-30 18:35:06 -0700245 return {GetBuffer(BufferHubDefs::kFirstClientBitMask)};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800246}
247
Tianyu Jianga99f9112018-12-13 18:23:07 -0800248Status<uint32_t> ProducerChannel::CreateConsumerStateMask() {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700249 // Try find the next consumer state bit which has not been claimed by any
250 // consumer yet.
Tianyu67053492018-10-04 14:00:22 -0700251 // memory_order_acquire is chosen here because all writes in other threads
252 // that release active_clients_bit_mask_ need to be visible here.
Tianyu Jianga99f9112018-12-13 18:23:07 -0800253 uint32_t current_active_clients_bit_mask =
Tianyu67053492018-10-04 14:00:22 -0700254 active_clients_bit_mask_->load(std::memory_order_acquire);
Tianyu Jianga99f9112018-12-13 18:23:07 -0800255 uint32_t consumer_state_mask =
Tianyuf669f6a2018-10-10 15:34:32 -0700256 BufferHubDefs::FindNextAvailableClientStateMask(
257 current_active_clients_bit_mask | orphaned_consumer_bit_mask_);
Tianyu Jianga99f9112018-12-13 18:23:07 -0800258 if (consumer_state_mask == 0U) {
Tianyuf669f6a2018-10-10 15:34:32 -0700259 ALOGE("%s: reached the maximum mumber of consumers per producer: 63.",
260 __FUNCTION__);
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700261 return ErrorStatus(E2BIG);
262 }
Tianyu Jianga99f9112018-12-13 18:23:07 -0800263 uint32_t updated_active_clients_bit_mask =
Tianyuf669f6a2018-10-10 15:34:32 -0700264 current_active_clients_bit_mask | consumer_state_mask;
Tianyu67053492018-10-04 14:00:22 -0700265 // Set the updated value only if the current value stays the same as what was
266 // read before. If the comparison succeeds, update the value without
267 // reordering anything before or after this read-modify-write in the current
268 // thread, and the modification will be visible in other threads that acquire
269 // active_clients_bit_mask_. If the comparison fails, load the result of
270 // all writes from all threads to updated_active_clients_bit_mask.
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800271 // Keep on finding the next available slient state mask until succeed or out
272 // of memory.
273 while (!active_clients_bit_mask_->compare_exchange_weak(
274 current_active_clients_bit_mask, updated_active_clients_bit_mask,
275 std::memory_order_acq_rel, std::memory_order_acquire)) {
Tianyu Jianga99f9112018-12-13 18:23:07 -0800276 ALOGE("%s: Current active clients bit mask is changed to %" PRIx32
277 ", which was expected to be %" PRIx32
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800278 ". Trying to generate a new client state mask to resolve race "
279 "condition.",
Tianyuf669f6a2018-10-10 15:34:32 -0700280 __FUNCTION__, updated_active_clients_bit_mask,
281 current_active_clients_bit_mask);
282 consumer_state_mask = BufferHubDefs::FindNextAvailableClientStateMask(
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800283 current_active_clients_bit_mask | orphaned_consumer_bit_mask_);
Tianyu Jianga99f9112018-12-13 18:23:07 -0800284 if (consumer_state_mask == 0U) {
Tianyuf669f6a2018-10-10 15:34:32 -0700285 ALOGE("%s: reached the maximum mumber of consumers per producer: %d.",
286 __FUNCTION__, (BufferHubDefs::kMaxNumberOfClients - 1));
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800287 return ErrorStatus(E2BIG);
288 }
289 updated_active_clients_bit_mask =
Tianyuf669f6a2018-10-10 15:34:32 -0700290 current_active_clients_bit_mask | consumer_state_mask;
Tianyu67053492018-10-04 14:00:22 -0700291 }
292
Tianyuf669f6a2018-10-10 15:34:32 -0700293 return {consumer_state_mask};
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800294}
295
Tianyu Jianga99f9112018-12-13 18:23:07 -0800296void ProducerChannel::RemoveConsumerClientMask(uint32_t consumer_state_mask) {
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800297 // Clear up the buffer state and fence state in case there is already
298 // something there due to possible race condition between producer post and
299 // consumer failed to create channel.
300 buffer_state_->fetch_and(~consumer_state_mask, std::memory_order_release);
301 fence_state_->fetch_and(~consumer_state_mask, std::memory_order_release);
302
303 // Restore the consumer state bit and make it visible in other threads that
304 // acquire the active_clients_bit_mask_.
305 active_clients_bit_mask_->fetch_and(~consumer_state_mask,
306 std::memory_order_release);
307}
308
309Status<RemoteChannelHandle> ProducerChannel::CreateConsumer(
Tianyu Jianga99f9112018-12-13 18:23:07 -0800310 Message& message, uint32_t consumer_state_mask) {
Tianyuf669f6a2018-10-10 15:34:32 -0700311 ATRACE_NAME(__FUNCTION__);
Jiwen 'Steve' Cai617ba802018-12-20 14:22:55 -0800312 ALOGD("%s: buffer_id=%d", __FUNCTION__, buffer_id());
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800313
314 int channel_id;
315 auto status = message.PushChannel(0, nullptr, &channel_id);
316 if (!status) {
Tianyuf669f6a2018-10-10 15:34:32 -0700317 ALOGE("%s: Failed to push consumer channel: %s", __FUNCTION__,
318 status.GetErrorMessage().c_str());
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800319 RemoveConsumerClientMask(consumer_state_mask);
320 return ErrorStatus(ENOMEM);
321 }
322
323 auto consumer = std::make_shared<ConsumerChannel>(
324 service(), buffer_id(), channel_id, consumer_state_mask,
325 shared_from_this());
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700326 const auto channel_status = service()->SetChannel(channel_id, consumer);
327 if (!channel_status) {
Tianyuf669f6a2018-10-10 15:34:32 -0700328 ALOGE("%s: failed to set new consumer channel: %s.", __FUNCTION__,
329 channel_status.GetErrorMessage().c_str());
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800330 RemoveConsumerClientMask(consumer_state_mask);
Corey Tabakacd52dd92017-04-07 18:03:57 -0700331 return ErrorStatus(ENOMEM);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800332 }
333
Tianyu Jianga99f9112018-12-13 18:23:07 -0800334 uint32_t current_buffer_state =
Tianyu Jiangca9201a2018-11-06 12:40:33 -0800335 buffer_state_->load(std::memory_order_acquire);
Tianyuf669f6a2018-10-10 15:34:32 -0700336 if (BufferHubDefs::IsBufferReleased(current_buffer_state) ||
337 BufferHubDefs::AnyClientGained(current_buffer_state)) {
338 return {status.take()};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800339 }
340
Tianyuf669f6a2018-10-10 15:34:32 -0700341 // Signal the new consumer when adding it to a posted producer.
342 bool update_buffer_state = true;
343 if (!BufferHubDefs::IsClientPosted(current_buffer_state,
344 consumer_state_mask)) {
Tianyu Jianga99f9112018-12-13 18:23:07 -0800345 uint32_t updated_buffer_state =
Tianyuf669f6a2018-10-10 15:34:32 -0700346 current_buffer_state ^
347 (consumer_state_mask & BufferHubDefs::kHighBitsMask);
348 while (!buffer_state_->compare_exchange_weak(
349 current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
350 std::memory_order_acquire)) {
351 ALOGI(
352 "%s: Failed to post to the new consumer. "
Tianyu Jianga99f9112018-12-13 18:23:07 -0800353 "Current buffer state was changed to %" PRIx32
Tianyuf669f6a2018-10-10 15:34:32 -0700354 " when trying to acquire the buffer and modify the buffer state to "
Tianyu Jianga99f9112018-12-13 18:23:07 -0800355 "%" PRIx32
Tianyuf669f6a2018-10-10 15:34:32 -0700356 ". About to try again if the buffer is still not gained nor fully "
357 "released.",
358 __FUNCTION__, current_buffer_state, updated_buffer_state);
359 if (BufferHubDefs::IsBufferReleased(current_buffer_state) ||
360 BufferHubDefs::AnyClientGained(current_buffer_state)) {
Tianyu Jianga99f9112018-12-13 18:23:07 -0800361 ALOGI("%s: buffer is gained or fully released, state=%" PRIx32 ".",
Tianyuf669f6a2018-10-10 15:34:32 -0700362 __FUNCTION__, current_buffer_state);
363 update_buffer_state = false;
364 break;
365 }
366 updated_buffer_state =
367 current_buffer_state ^
368 (consumer_state_mask & BufferHubDefs::kHighBitsMask);
369 }
370 }
Tianyu Jiange60a4ad2019-01-04 14:37:23 -0800371 if (update_buffer_state || BufferHubDefs::IsClientPosted(
372 buffer_state_->load(std::memory_order_acquire),
373 consumer_state_mask)) {
Tianyu Jiang0cdd2a02018-11-15 10:20:45 -0800374 consumer->OnProducerPosted();
375 }
Tianyuf669f6a2018-10-10 15:34:32 -0700376
Corey Tabakacd52dd92017-04-07 18:03:57 -0700377 return {status.take()};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800378}
379
Corey Tabakacd52dd92017-04-07 18:03:57 -0700380Status<RemoteChannelHandle> ProducerChannel::OnNewConsumer(Message& message) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800381 ATRACE_NAME("ProducerChannel::OnNewConsumer");
382 ALOGD_IF(TRACE, "ProducerChannel::OnNewConsumer: buffer_id=%d", buffer_id());
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800383 auto status = CreateConsumerStateMask();
384 if (!status.ok()) {
385 return status.error_status();
386 }
387 return CreateConsumer(message, /*consumer_state_mask=*/status.get());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800388}
389
Tianyu0c6b7ff2018-10-03 11:30:04 -0700390Status<void> ProducerChannel::OnProducerPost(Message&,
391 LocalFence acquire_fence) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800392 ATRACE_NAME("ProducerChannel::OnProducerPost");
Jiwen 'Steve' Cai617ba802018-12-20 14:22:55 -0800393 ALOGD("ProducerChannel::OnProducerPost: buffer_id=%d, state=0x%x",
394 buffer_id(), buffer_state_->load(std::memory_order_acquire));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800395
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700396 epoll_event event;
397 event.events = 0;
Tianyu Jianga99f9112018-12-13 18:23:07 -0800398 event.data.u32 = 0U;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700399 int ret = epoll_ctl(release_fence_fd_.Get(), EPOLL_CTL_MOD,
400 dummy_fence_fd_.Get(), &event);
401 ALOGE_IF(ret < 0,
Tianyu0c6b7ff2018-10-03 11:30:04 -0700402 "ProducerChannel::OnProducerPost: Failed to modify the shared "
403 "release fence to include the dummy fence: %s",
404 strerror(errno));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700405
Tianyu Jianga99f9112018-12-13 18:23:07 -0800406 eventfd_t dummy_fence_count = 0U;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700407 if (eventfd_read(dummy_fence_fd_.Get(), &dummy_fence_count) < 0) {
408 const int error = errno;
409 if (error != EAGAIN) {
410 ALOGE(
411 "ProducerChannel::ProducerChannel: Failed to read dummy fence, "
412 "error: %s",
413 strerror(error));
414 return ErrorStatus(error);
415 }
Corey Tabaka8a4e6a92017-04-20 13:42:02 -0700416 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800417
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700418 ALOGW_IF(dummy_fence_count > 0,
419 "ProducerChannel::ProducerChannel: %" PRIu64
420 " dummy fence(s) was signaled during last release/gain cycle "
421 "buffer_id=%d.",
422 dummy_fence_count, buffer_id());
423
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800424 post_fence_ = std::move(acquire_fence);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800425
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700426 // Signal any interested consumers. If there are none, the buffer will stay
427 // in posted state until a consumer comes online. This behavior guarantees
428 // that no frame is silently dropped.
Tianyu Jiangae9668c2018-12-07 15:14:47 -0800429 for (auto& consumer : consumer_channels_) {
Tianyu Jiang0cdd2a02018-11-15 10:20:45 -0800430 consumer->OnProducerPosted();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800431 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800432
Corey Tabakacd52dd92017-04-07 18:03:57 -0700433 return {};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800434}
435
Corey Tabakad53870c2017-07-06 18:04:27 -0700436Status<LocalFence> ProducerChannel::OnProducerGain(Message& /*message*/) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800437 ATRACE_NAME("ProducerChannel::OnGain");
Jiwen 'Steve' Cai617ba802018-12-20 14:22:55 -0800438 ALOGW("ProducerChannel::OnGain: buffer_id=%d", buffer_id());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800439
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800440 ClearAvailable();
Alex Vakulenko052f3ae2017-03-31 09:10:43 -0700441 post_fence_.close();
Tianyu Jiangae9668c2018-12-07 15:14:47 -0800442 for (auto& consumer : consumer_channels_) {
443 consumer->OnProducerGained();
444 }
Corey Tabakacd52dd92017-04-07 18:03:57 -0700445 return {std::move(returned_fence_)};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800446}
447
Fan Xub0eec512018-10-30 11:33:15 -0700448// TODO(b/112338294) Keep here for reference. Remove it after new logic is
449// written.
450/* Status<RemoteChannelHandle> ProducerChannel::OnProducerDetach(
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700451 Message& message) {
452 ATRACE_NAME("ProducerChannel::OnProducerDetach");
453 ALOGD_IF(TRACE, "ProducerChannel::OnProducerDetach: buffer_id=%d",
454 buffer_id());
455
Tianyu Jianga99f9112018-12-13 18:23:07 -0800456 uint32_t buffer_state = buffer_state_->load(std::memory_order_acquire);
Tianyuf669f6a2018-10-10 15:34:32 -0700457 if (!BufferHubDefs::IsClientGained(
458 buffer_state, BufferHubDefs::kFirstClientStateMask)) {
Jiwen 'Steve' Cai1c730242018-12-31 18:40:02 -0800459 // Can only detach a ProducerBuffer when it's in gained state.
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700460 ALOGW(
Tianyuf669f6a2018-10-10 15:34:32 -0700461 "ProducerChannel::OnProducerDetach: The buffer (id=%d, state=%"
Tianyu Jianga99f9112018-12-13 18:23:07 -0800462 PRIx32
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700463 ") is not in gained state.",
464 buffer_id(), buffer_state);
465 return {};
466 }
467
468 int channel_id;
469 auto status = message.PushChannel(0, nullptr, &channel_id);
470 if (!status) {
471 ALOGE(
472 "ProducerChannel::OnProducerDetach: Failed to push detached buffer "
473 "channel: %s",
474 status.GetErrorMessage().c_str());
475 return ErrorStatus(ENOMEM);
476 }
477
478 // Make sure we unlock the buffer.
479 if (int ret = metadata_buffer_.Unlock()) {
480 ALOGE("ProducerChannel::OnProducerDetach: Failed to unlock metadata.");
481 return ErrorStatus(-ret);
482 };
483
Jiwen 'Steve' Cai9004b8c2018-10-03 18:52:23 -0700484 std::unique_ptr<BufferChannel> channel =
485 BufferChannel::Create(service(), buffer_id(), channel_id,
486 std::move(buffer_), user_metadata_size_);
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700487 if (!channel) {
488 ALOGE("ProducerChannel::OnProducerDetach: Invalid buffer.");
489 return ErrorStatus(EINVAL);
490 }
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700491
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700492 const auto channel_status =
493 service()->SetChannel(channel_id, std::move(channel));
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700494 if (!channel_status) {
Tianyuf669f6a2018-10-10 15:34:32 -0700495 // Technically, this should never fail, as we just pushed the channel.
496 // Note that LOG_FATAL will be stripped out in non-debug build.
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700497 LOG_FATAL(
Tianyuf669f6a2018-10-10 15:34:32 -0700498 "ProducerChannel::OnProducerDetach: Failed to set new detached "
499 "buffer channel: %s.", channel_status.GetErrorMessage().c_str());
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700500 }
501
502 return status;
Fan Xub0eec512018-10-30 11:33:15 -0700503} */
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700504
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700505Status<LocalFence> ProducerChannel::OnConsumerAcquire(Message& /*message*/) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800506 ATRACE_NAME("ProducerChannel::OnConsumerAcquire");
507 ALOGD_IF(TRACE, "ProducerChannel::OnConsumerAcquire: buffer_id=%d",
508 buffer_id());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800509
Tianyuf669f6a2018-10-10 15:34:32 -0700510 // Return a borrowed fd to avoid unnecessary duplication of the underlying
511 // fd. Serialization just needs to read the handle.
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700512 return {std::move(post_fence_)};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800513}
514
Corey Tabakacd52dd92017-04-07 18:03:57 -0700515Status<void> ProducerChannel::OnConsumerRelease(Message&,
516 LocalFence release_fence) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800517 ATRACE_NAME("ProducerChannel::OnConsumerRelease");
518 ALOGD_IF(TRACE, "ProducerChannel::OnConsumerRelease: buffer_id=%d",
519 buffer_id());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800520
521 // Attempt to merge the fences if necessary.
522 if (release_fence) {
523 if (returned_fence_) {
Corey Tabaka3079cb72017-01-19 15:07:26 -0800524 LocalFence merged_fence(sync_merge("bufferhub_merged",
525 returned_fence_.get_fd(),
526 release_fence.get_fd()));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800527 const int error = errno;
528 if (!merged_fence) {
529 ALOGE("ProducerChannel::OnConsumerRelease: Failed to merge fences: %s",
530 strerror(error));
Corey Tabakacd52dd92017-04-07 18:03:57 -0700531 return ErrorStatus(error);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800532 }
533 returned_fence_ = std::move(merged_fence);
534 } else {
535 returned_fence_ = std::move(release_fence);
536 }
537 }
538
Tianyu Jianga99f9112018-12-13 18:23:07 -0800539 uint32_t current_buffer_state =
Tianyu Jiang0cdd2a02018-11-15 10:20:45 -0800540 buffer_state_->load(std::memory_order_acquire);
Tianyu Jiange60a4ad2019-01-04 14:37:23 -0800541 uint32_t current_active_clients_bit_mask =
542 active_clients_bit_mask_->load(std::memory_order_acquire);
543 // Signal producer if all current active consumers have released the buffer.
Tianyu Jiangae9668c2018-12-07 15:14:47 -0800544 if (BufferHubDefs::IsBufferReleased(current_buffer_state &
Tianyu Jiange60a4ad2019-01-04 14:37:23 -0800545 ~orphaned_consumer_bit_mask_ &
546 current_active_clients_bit_mask)) {
547 buffer_state_->store(0U);
Tianyu Jiang0cdd2a02018-11-15 10:20:45 -0800548 SignalAvailable();
549 if (orphaned_consumer_bit_mask_) {
550 ALOGW(
551 "%s: orphaned buffer detected during the this acquire/release cycle: "
Jiwen 'Steve' Cai617ba802018-12-20 14:22:55 -0800552 "id=%d orphaned=0x%" PRIx32 " queue_index=%" PRId64 ".",
Tianyu Jiang0cdd2a02018-11-15 10:20:45 -0800553 __FUNCTION__, buffer_id(), orphaned_consumer_bit_mask_,
554 metadata_header_->queue_index);
555 orphaned_consumer_bit_mask_ = 0;
556 }
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700557 }
558
Corey Tabakacd52dd92017-04-07 18:03:57 -0700559 return {};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800560}
561
Tianyu Jianga99f9112018-12-13 18:23:07 -0800562void ProducerChannel::OnConsumerOrphaned(const uint32_t& consumer_state_mask) {
Tianyuf669f6a2018-10-10 15:34:32 -0700563 // Remember the ignored consumer so that newly added consumer won't be
564 // taking the same state mask as this orphaned consumer.
565 ALOGE_IF(orphaned_consumer_bit_mask_ & consumer_state_mask,
Tianyu Jianga99f9112018-12-13 18:23:07 -0800566 "%s: Consumer (consumer_state_mask=%" PRIx32
Tianyuf669f6a2018-10-10 15:34:32 -0700567 ") is already orphaned.",
568 __FUNCTION__, consumer_state_mask);
569 orphaned_consumer_bit_mask_ |= consumer_state_mask;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700570
Tianyu Jianga99f9112018-12-13 18:23:07 -0800571 uint32_t current_buffer_state =
Tianyu Jiang0cdd2a02018-11-15 10:20:45 -0800572 buffer_state_->load(std::memory_order_acquire);
Tianyu Jiange60a4ad2019-01-04 14:37:23 -0800573 uint32_t current_active_clients_bit_mask =
574 active_clients_bit_mask_->load(std::memory_order_acquire);
575 // Signal producer if all current active consumers have released the buffer.
Tianyu Jiangae9668c2018-12-07 15:14:47 -0800576 if (BufferHubDefs::IsBufferReleased(current_buffer_state &
Tianyu Jiange60a4ad2019-01-04 14:37:23 -0800577 ~orphaned_consumer_bit_mask_ &
578 current_active_clients_bit_mask)) {
579 buffer_state_->store(0U);
Tianyu Jiang0cdd2a02018-11-15 10:20:45 -0800580 SignalAvailable();
581 }
582
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700583 // Atomically clear the fence state bit as an orphaned consumer will never
Tianyuf669f6a2018-10-10 15:34:32 -0700584 // signal a release fence.
585 fence_state_->fetch_and(~consumer_state_mask, std::memory_order_release);
586
587 // Atomically set the buffer state of this consumer to released state.
588 buffer_state_->fetch_and(~consumer_state_mask, std::memory_order_release);
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700589
590 ALOGW(
Tianyuf669f6a2018-10-10 15:34:32 -0700591 "%s: detected new orphaned consumer buffer_id=%d "
Jiwen 'Steve' Cai617ba802018-12-20 14:22:55 -0800592 "consumer_state_mask=%" PRIx32 " queue_index=%" PRId64
Tianyu Jianga99f9112018-12-13 18:23:07 -0800593 " buffer_state=%" PRIx32 " fence_state=%" PRIx32 ".",
Tianyuf669f6a2018-10-10 15:34:32 -0700594 __FUNCTION__, buffer_id(), consumer_state_mask,
595 metadata_header_->queue_index,
Tianyu Jiange2cdec92018-10-30 17:40:58 -0700596 buffer_state_->load(std::memory_order_acquire),
597 fence_state_->load(std::memory_order_acquire));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700598}
599
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800600void ProducerChannel::AddConsumer(ConsumerChannel* channel) {
601 consumer_channels_.push_back(channel);
602}
603
604void ProducerChannel::RemoveConsumer(ConsumerChannel* channel) {
605 consumer_channels_.erase(
606 std::find(consumer_channels_.begin(), consumer_channels_.end(), channel));
Tianyu67053492018-10-04 14:00:22 -0700607 // Restore the consumer state bit and make it visible in other threads that
608 // acquire the active_clients_bit_mask_.
Tianyu Jianga99f9112018-12-13 18:23:07 -0800609 uint32_t consumer_state_mask = channel->client_state_mask();
610 uint32_t current_active_clients_bit_mask =
Tianyuf669f6a2018-10-10 15:34:32 -0700611 active_clients_bit_mask_->load(std::memory_order_acquire);
Tianyu Jianga99f9112018-12-13 18:23:07 -0800612 uint32_t updated_active_clients_bit_mask =
Tianyuf669f6a2018-10-10 15:34:32 -0700613 current_active_clients_bit_mask & (~consumer_state_mask);
614 while (!active_clients_bit_mask_->compare_exchange_weak(
615 current_active_clients_bit_mask, updated_active_clients_bit_mask,
616 std::memory_order_acq_rel, std::memory_order_acquire)) {
617 ALOGI(
618 "%s: Failed to remove consumer state mask. Current active clients bit "
Tianyu Jianga99f9112018-12-13 18:23:07 -0800619 "mask is changed to %" PRIx32
620 " when trying to acquire and modify it to %" PRIx32
Tianyuf669f6a2018-10-10 15:34:32 -0700621 ". About to try again.",
622 __FUNCTION__, current_active_clients_bit_mask,
623 updated_active_clients_bit_mask);
624 updated_active_clients_bit_mask =
625 current_active_clients_bit_mask & (~consumer_state_mask);
626 }
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700627
Tianyu Jianga99f9112018-12-13 18:23:07 -0800628 const uint32_t current_buffer_state =
Tianyuf669f6a2018-10-10 15:34:32 -0700629 buffer_state_->load(std::memory_order_acquire);
630 if (BufferHubDefs::IsClientPosted(current_buffer_state,
631 consumer_state_mask) ||
632 BufferHubDefs::IsClientAcquired(current_buffer_state,
633 consumer_state_mask)) {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700634 // The consumer client is being destoryed without releasing. This could
635 // happen in corner cases when the consumer crashes. Here we mark it
636 // orphaned before remove it from producer.
Tianyuf669f6a2018-10-10 15:34:32 -0700637 OnConsumerOrphaned(consumer_state_mask);
638 return;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700639 }
640
Tianyuf669f6a2018-10-10 15:34:32 -0700641 if (BufferHubDefs::IsClientReleased(current_buffer_state,
642 consumer_state_mask) ||
643 BufferHubDefs::AnyClientGained(current_buffer_state)) {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700644 // The consumer is being close while it is suppose to signal a release
645 // fence. Signal the dummy fence here.
Tianyuf669f6a2018-10-10 15:34:32 -0700646 if (fence_state_->load(std::memory_order_acquire) & consumer_state_mask) {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700647 epoll_event event;
648 event.events = EPOLLIN;
Tianyu Jianga99f9112018-12-13 18:23:07 -0800649 event.data.u32 = consumer_state_mask;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700650 if (epoll_ctl(release_fence_fd_.Get(), EPOLL_CTL_MOD,
651 dummy_fence_fd_.Get(), &event) < 0) {
652 ALOGE(
Tianyuf669f6a2018-10-10 15:34:32 -0700653 "%s: Failed to modify the shared release fence to include the "
654 "dummy fence: %s",
655 __FUNCTION__, strerror(errno));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700656 return;
657 }
Tianyuf669f6a2018-10-10 15:34:32 -0700658 ALOGW("%s: signal dummy release fence buffer_id=%d", __FUNCTION__,
659 buffer_id());
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700660 eventfd_write(dummy_fence_fd_.Get(), 1);
661 }
662 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800663}
664
Tianyuf669f6a2018-10-10 15:34:32 -0700665// Returns true if the given parameters match the underlying buffer
666// parameters.
Corey Tabakacd52dd92017-04-07 18:03:57 -0700667bool ProducerChannel::CheckParameters(uint32_t width, uint32_t height,
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700668 uint32_t layer_count, uint32_t format,
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700669 uint64_t usage,
670 size_t user_metadata_size) {
671 return user_metadata_size == user_metadata_size_ &&
672 buffer_.width() == width && buffer_.height() == height &&
673 buffer_.layer_count() == layer_count && buffer_.format() == format &&
674 buffer_.usage() == usage;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800675}
676
677} // namespace dvr
678} // namespace android