blob: b71964ba002dacfbaf6ed6af9d38098ac755c02f [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.
Tianyu Jiangf377a762019-02-13 13:46:42 -080094 buffer_state_ = new (&metadata_header_->bufferState) std::atomic<uint32_t>(0);
95 fence_state_ = new (&metadata_header_->fenceState) std::atomic<uint32_t>(0);
Tianyu67053492018-10-04 14:00:22 -070096 active_clients_bit_mask_ =
Tianyu Jiangf377a762019-02-13 13:46:42 -080097 new (&metadata_header_->activeClientsBitMask) std::atomic<uint32_t>(0);
Corey Tabaka52ea25c2017-09-13 18:02:48 -070098
Tianyu Jiang63dd7c32018-10-30 18:35:06 -070099 // Producer channel is never created after consumer channel, and one buffer
100 // only have one fixed producer for now. Thus, it is correct to assume
101 // producer state bit is kFirstClientBitMask for now.
102 active_clients_bit_mask_->store(BufferHubDefs::kFirstClientBitMask,
103 std::memory_order_release);
104
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700105 acquire_fence_fd_.Reset(epoll_create1(EPOLL_CLOEXEC));
106 release_fence_fd_.Reset(epoll_create1(EPOLL_CLOEXEC));
107 if (!acquire_fence_fd_ || !release_fence_fd_) {
108 ALOGE("ProducerChannel::ProducerChannel: Failed to create shared fences.");
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -0700109 return -EIO;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700110 }
111
112 dummy_fence_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
113 if (!dummy_fence_fd_) {
114 ALOGE("ProducerChannel::ProducerChannel: Failed to create dummy fences.");
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -0700115 return EIO;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700116 }
117
118 epoll_event event;
119 event.events = 0;
Tianyu Jianga99f9112018-12-13 18:23:07 -0800120 event.data.u32 = 0U;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700121 if (epoll_ctl(release_fence_fd_.Get(), EPOLL_CTL_ADD, dummy_fence_fd_.Get(),
122 &event) < 0) {
123 ALOGE(
124 "ProducerChannel::ProducerChannel: Failed to modify the shared "
125 "release fence to include the dummy fence: %s",
126 strerror(errno));
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -0700127 return -EIO;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700128 }
129
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800130 // Success.
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -0700131 return 0;
132}
133
134std::unique_ptr<ProducerChannel> ProducerChannel::Create(
135 BufferHubService* service, int buffer_id, int channel_id, IonBuffer buffer,
136 IonBuffer metadata_buffer, size_t user_metadata_size) {
137 int error = 0;
138 std::unique_ptr<ProducerChannel> producer(new ProducerChannel(
139 service, buffer_id, channel_id, std::move(buffer),
140 std::move(metadata_buffer), user_metadata_size, &error));
141
142 if (error < 0)
143 return nullptr;
144 else
145 return producer;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800146}
147
Corey Tabakacd52dd92017-04-07 18:03:57 -0700148Status<std::shared_ptr<ProducerChannel>> ProducerChannel::Create(
149 BufferHubService* service, int channel_id, uint32_t width, uint32_t height,
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700150 uint32_t layer_count, uint32_t format, uint64_t usage,
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700151 size_t user_metadata_size) {
Corey Tabakacd52dd92017-04-07 18:03:57 -0700152 int error;
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -0700153 std::shared_ptr<ProducerChannel> producer(
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700154 new ProducerChannel(service, channel_id, width, height, layer_count,
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700155 format, usage, user_metadata_size, &error));
Corey Tabakacd52dd92017-04-07 18:03:57 -0700156 if (error < 0)
157 return ErrorStatus(-error);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800158 else
Corey Tabakacd52dd92017-04-07 18:03:57 -0700159 return {std::move(producer)};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800160}
161
162ProducerChannel::~ProducerChannel() {
Corey Tabaka3079cb72017-01-19 15:07:26 -0800163 ALOGD_IF(TRACE,
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700164 "ProducerChannel::~ProducerChannel: channel_id=%d buffer_id=%d "
Tianyu Jianga99f9112018-12-13 18:23:07 -0800165 "state=%" PRIx32 ".",
Tianyu Jiange2cdec92018-10-30 17:40:58 -0700166 channel_id(), buffer_id(),
167 buffer_state_->load(std::memory_order_acquire));
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700168 for (auto consumer : consumer_channels_) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800169 consumer->OnProducerClosed();
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700170 }
171 Hangup();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800172}
173
174BufferHubChannel::BufferInfo ProducerChannel::GetBufferInfo() const {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700175 // Derive the mask of signaled buffers in this producer / consumer set.
Tianyu Jianga99f9112018-12-13 18:23:07 -0800176 uint32_t signaled_mask = signaled() ? BufferHubDefs::kFirstClientBitMask : 0;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700177 for (const ConsumerChannel* consumer : consumer_channels_) {
Tianyu Jiang83a991f2018-10-30 16:59:29 -0700178 signaled_mask |= consumer->signaled() ? consumer->client_state_mask() : 0;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700179 }
180
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -0700181 return BufferInfo(buffer_id(), consumer_channels_.size(), buffer_.width(),
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700182 buffer_.height(), buffer_.layer_count(), buffer_.format(),
Tianyu Jiang0cdd2a02018-11-15 10:20:45 -0800183 buffer_.usage(),
Tianyu Jiange2cdec92018-10-30 17:40:58 -0700184 buffer_state_->load(std::memory_order_acquire),
Tianyu Jiangf377a762019-02-13 13:46:42 -0800185 signaled_mask, metadata_header_->queueIndex);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800186}
187
188void ProducerChannel::HandleImpulse(Message& message) {
189 ATRACE_NAME("ProducerChannel::HandleImpulse");
190 switch (message.GetOp()) {
191 case BufferHubRPC::ProducerGain::Opcode:
192 OnProducerGain(message);
193 break;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700194 case BufferHubRPC::ProducerPost::Opcode:
195 OnProducerPost(message, {});
196 break;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800197 }
198}
199
200bool ProducerChannel::HandleMessage(Message& message) {
201 ATRACE_NAME("ProducerChannel::HandleMessage");
202 switch (message.GetOp()) {
203 case BufferHubRPC::GetBuffer::Opcode:
204 DispatchRemoteMethod<BufferHubRPC::GetBuffer>(
205 *this, &ProducerChannel::OnGetBuffer, message);
206 return true;
207
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800208 case BufferHubRPC::NewConsumer::Opcode:
209 DispatchRemoteMethod<BufferHubRPC::NewConsumer>(
210 *this, &ProducerChannel::OnNewConsumer, message);
211 return true;
212
213 case BufferHubRPC::ProducerPost::Opcode:
214 DispatchRemoteMethod<BufferHubRPC::ProducerPost>(
215 *this, &ProducerChannel::OnProducerPost, message);
216 return true;
217
218 case BufferHubRPC::ProducerGain::Opcode:
219 DispatchRemoteMethod<BufferHubRPC::ProducerGain>(
220 *this, &ProducerChannel::OnProducerGain, message);
221 return true;
222
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800223 default:
224 return false;
225 }
226}
227
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700228BufferDescription<BorrowedHandle> ProducerChannel::GetBuffer(
Tianyu Jianga99f9112018-12-13 18:23:07 -0800229 uint32_t client_state_mask) {
Jiwen 'Steve' Cai57ae3ee2018-05-03 17:51:52 -0700230 return {buffer_,
231 metadata_buffer_,
232 buffer_id(),
233 channel_id(),
Tianyu Jiang7e204b72018-10-26 15:39:18 -0700234 client_state_mask,
Jiwen 'Steve' Cai57ae3ee2018-05-03 17:51:52 -0700235 acquire_fence_fd_.Borrow(),
236 release_fence_fd_.Borrow()};
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700237}
238
239Status<BufferDescription<BorrowedHandle>> ProducerChannel::OnGetBuffer(
Corey Tabakad53870c2017-07-06 18:04:27 -0700240 Message& /*message*/) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800241 ATRACE_NAME("ProducerChannel::OnGetBuffer");
Tianyu Jianga99f9112018-12-13 18:23:07 -0800242 ALOGD_IF(TRACE, "ProducerChannel::OnGetBuffer: buffer=%d, state=%" PRIx32 ".",
Tianyu Jiange2cdec92018-10-30 17:40:58 -0700243 buffer_id(), buffer_state_->load(std::memory_order_acquire));
Tianyu Jiang63dd7c32018-10-30 18:35:06 -0700244 return {GetBuffer(BufferHubDefs::kFirstClientBitMask)};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800245}
246
Tianyu Jianga99f9112018-12-13 18:23:07 -0800247Status<uint32_t> ProducerChannel::CreateConsumerStateMask() {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700248 // Try find the next consumer state bit which has not been claimed by any
249 // consumer yet.
Tianyu67053492018-10-04 14:00:22 -0700250 // memory_order_acquire is chosen here because all writes in other threads
251 // that release active_clients_bit_mask_ need to be visible here.
Tianyu Jianga99f9112018-12-13 18:23:07 -0800252 uint32_t current_active_clients_bit_mask =
Tianyu67053492018-10-04 14:00:22 -0700253 active_clients_bit_mask_->load(std::memory_order_acquire);
Tianyu Jianga99f9112018-12-13 18:23:07 -0800254 uint32_t consumer_state_mask =
Tianyu Jiang727ede42019-02-01 11:44:51 -0800255 BufferHubDefs::findNextAvailableClientStateMask(
Tianyuf669f6a2018-10-10 15:34:32 -0700256 current_active_clients_bit_mask | orphaned_consumer_bit_mask_);
Tianyu Jianga99f9112018-12-13 18:23:07 -0800257 if (consumer_state_mask == 0U) {
Tianyuf669f6a2018-10-10 15:34:32 -0700258 ALOGE("%s: reached the maximum mumber of consumers per producer: 63.",
259 __FUNCTION__);
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700260 return ErrorStatus(E2BIG);
261 }
Tianyu Jianga99f9112018-12-13 18:23:07 -0800262 uint32_t updated_active_clients_bit_mask =
Tianyuf669f6a2018-10-10 15:34:32 -0700263 current_active_clients_bit_mask | consumer_state_mask;
Tianyu67053492018-10-04 14:00:22 -0700264 // Set the updated value only if the current value stays the same as what was
265 // read before. If the comparison succeeds, update the value without
266 // reordering anything before or after this read-modify-write in the current
267 // thread, and the modification will be visible in other threads that acquire
268 // active_clients_bit_mask_. If the comparison fails, load the result of
269 // all writes from all threads to updated_active_clients_bit_mask.
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800270 // Keep on finding the next available slient state mask until succeed or out
271 // of memory.
272 while (!active_clients_bit_mask_->compare_exchange_weak(
273 current_active_clients_bit_mask, updated_active_clients_bit_mask,
274 std::memory_order_acq_rel, std::memory_order_acquire)) {
Tianyu Jianga99f9112018-12-13 18:23:07 -0800275 ALOGE("%s: Current active clients bit mask is changed to %" PRIx32
276 ", which was expected to be %" PRIx32
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800277 ". Trying to generate a new client state mask to resolve race "
278 "condition.",
Tianyuf669f6a2018-10-10 15:34:32 -0700279 __FUNCTION__, updated_active_clients_bit_mask,
280 current_active_clients_bit_mask);
Tianyu Jiang727ede42019-02-01 11:44:51 -0800281 consumer_state_mask = BufferHubDefs::findNextAvailableClientStateMask(
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800282 current_active_clients_bit_mask | orphaned_consumer_bit_mask_);
Tianyu Jianga99f9112018-12-13 18:23:07 -0800283 if (consumer_state_mask == 0U) {
Tianyuf669f6a2018-10-10 15:34:32 -0700284 ALOGE("%s: reached the maximum mumber of consumers per producer: %d.",
285 __FUNCTION__, (BufferHubDefs::kMaxNumberOfClients - 1));
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800286 return ErrorStatus(E2BIG);
287 }
288 updated_active_clients_bit_mask =
Tianyuf669f6a2018-10-10 15:34:32 -0700289 current_active_clients_bit_mask | consumer_state_mask;
Tianyu67053492018-10-04 14:00:22 -0700290 }
291
Tianyuf669f6a2018-10-10 15:34:32 -0700292 return {consumer_state_mask};
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800293}
294
Tianyu Jianga99f9112018-12-13 18:23:07 -0800295void ProducerChannel::RemoveConsumerClientMask(uint32_t consumer_state_mask) {
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800296 // Clear up the buffer state and fence state in case there is already
297 // something there due to possible race condition between producer post and
298 // consumer failed to create channel.
299 buffer_state_->fetch_and(~consumer_state_mask, std::memory_order_release);
300 fence_state_->fetch_and(~consumer_state_mask, std::memory_order_release);
301
302 // Restore the consumer state bit and make it visible in other threads that
303 // acquire the active_clients_bit_mask_.
304 active_clients_bit_mask_->fetch_and(~consumer_state_mask,
305 std::memory_order_release);
306}
307
308Status<RemoteChannelHandle> ProducerChannel::CreateConsumer(
Tianyu Jianga99f9112018-12-13 18:23:07 -0800309 Message& message, uint32_t consumer_state_mask) {
Tianyuf669f6a2018-10-10 15:34:32 -0700310 ATRACE_NAME(__FUNCTION__);
Jiwen 'Steve' Cai617ba802018-12-20 14:22:55 -0800311 ALOGD("%s: buffer_id=%d", __FUNCTION__, buffer_id());
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800312
313 int channel_id;
314 auto status = message.PushChannel(0, nullptr, &channel_id);
315 if (!status) {
Tianyuf669f6a2018-10-10 15:34:32 -0700316 ALOGE("%s: Failed to push consumer channel: %s", __FUNCTION__,
317 status.GetErrorMessage().c_str());
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800318 RemoveConsumerClientMask(consumer_state_mask);
319 return ErrorStatus(ENOMEM);
320 }
321
322 auto consumer = std::make_shared<ConsumerChannel>(
323 service(), buffer_id(), channel_id, consumer_state_mask,
324 shared_from_this());
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700325 const auto channel_status = service()->SetChannel(channel_id, consumer);
326 if (!channel_status) {
Tianyuf669f6a2018-10-10 15:34:32 -0700327 ALOGE("%s: failed to set new consumer channel: %s.", __FUNCTION__,
328 channel_status.GetErrorMessage().c_str());
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800329 RemoveConsumerClientMask(consumer_state_mask);
Corey Tabakacd52dd92017-04-07 18:03:57 -0700330 return ErrorStatus(ENOMEM);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800331 }
332
Tianyu Jianga99f9112018-12-13 18:23:07 -0800333 uint32_t current_buffer_state =
Tianyu Jiangca9201a2018-11-06 12:40:33 -0800334 buffer_state_->load(std::memory_order_acquire);
Tianyu Jianga8df5f32019-01-14 18:42:12 -0800335 // Return the consumer channel handle without signal when adding the new
336 // consumer to a buffer that is available to producer (a.k.a a fully-released
337 // buffer) or a gained buffer.
338 if (current_buffer_state == 0U ||
Tianyu Jiang727ede42019-02-01 11:44:51 -0800339 BufferHubDefs::isAnyClientGained(current_buffer_state)) {
Tianyuf669f6a2018-10-10 15:34:32 -0700340 return {status.take()};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800341 }
342
Tianyuf669f6a2018-10-10 15:34:32 -0700343 // Signal the new consumer when adding it to a posted producer.
344 bool update_buffer_state = true;
Tianyu Jiang727ede42019-02-01 11:44:51 -0800345 if (!BufferHubDefs::isClientPosted(current_buffer_state,
Tianyuf669f6a2018-10-10 15:34:32 -0700346 consumer_state_mask)) {
Tianyu Jianga99f9112018-12-13 18:23:07 -0800347 uint32_t updated_buffer_state =
Tianyuf669f6a2018-10-10 15:34:32 -0700348 current_buffer_state ^
349 (consumer_state_mask & BufferHubDefs::kHighBitsMask);
350 while (!buffer_state_->compare_exchange_weak(
351 current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
352 std::memory_order_acquire)) {
Tianyu Jiang1eafe082019-05-21 19:44:48 -0700353 ALOGV(
Tianyuf669f6a2018-10-10 15:34:32 -0700354 "%s: Failed to post to the new consumer. "
Tianyu Jianga99f9112018-12-13 18:23:07 -0800355 "Current buffer state was changed to %" PRIx32
Tianyuf669f6a2018-10-10 15:34:32 -0700356 " when trying to acquire the buffer and modify the buffer state to "
Tianyu Jianga99f9112018-12-13 18:23:07 -0800357 "%" PRIx32
Tianyuf669f6a2018-10-10 15:34:32 -0700358 ". About to try again if the buffer is still not gained nor fully "
359 "released.",
360 __FUNCTION__, current_buffer_state, updated_buffer_state);
Tianyu Jianga8df5f32019-01-14 18:42:12 -0800361 if (current_buffer_state == 0U ||
Tianyu Jiang727ede42019-02-01 11:44:51 -0800362 BufferHubDefs::isAnyClientGained(current_buffer_state)) {
Tianyu Jianga99f9112018-12-13 18:23:07 -0800363 ALOGI("%s: buffer is gained or fully released, state=%" PRIx32 ".",
Tianyuf669f6a2018-10-10 15:34:32 -0700364 __FUNCTION__, current_buffer_state);
365 update_buffer_state = false;
366 break;
367 }
368 updated_buffer_state =
369 current_buffer_state ^
370 (consumer_state_mask & BufferHubDefs::kHighBitsMask);
371 }
372 }
Tianyu Jiang727ede42019-02-01 11:44:51 -0800373 if (update_buffer_state || BufferHubDefs::isClientPosted(
Tianyu Jiange60a4ad2019-01-04 14:37:23 -0800374 buffer_state_->load(std::memory_order_acquire),
375 consumer_state_mask)) {
Tianyu Jiang0cdd2a02018-11-15 10:20:45 -0800376 consumer->OnProducerPosted();
377 }
Tianyuf669f6a2018-10-10 15:34:32 -0700378
Corey Tabakacd52dd92017-04-07 18:03:57 -0700379 return {status.take()};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800380}
381
Corey Tabakacd52dd92017-04-07 18:03:57 -0700382Status<RemoteChannelHandle> ProducerChannel::OnNewConsumer(Message& message) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800383 ATRACE_NAME("ProducerChannel::OnNewConsumer");
384 ALOGD_IF(TRACE, "ProducerChannel::OnNewConsumer: buffer_id=%d", buffer_id());
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800385 auto status = CreateConsumerStateMask();
386 if (!status.ok()) {
387 return status.error_status();
388 }
389 return CreateConsumer(message, /*consumer_state_mask=*/status.get());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800390}
391
Tianyu0c6b7ff2018-10-03 11:30:04 -0700392Status<void> ProducerChannel::OnProducerPost(Message&,
393 LocalFence acquire_fence) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800394 ATRACE_NAME("ProducerChannel::OnProducerPost");
Tianyu Jiangee2c43a2019-02-22 11:11:14 -0800395 ALOGD_IF(TRACE, "%s: buffer_id=%d, state=0x%x", __FUNCTION__, buffer_id(),
396 buffer_state_->load(std::memory_order_acquire));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800397
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700398 epoll_event event;
399 event.events = 0;
Tianyu Jianga99f9112018-12-13 18:23:07 -0800400 event.data.u32 = 0U;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700401 int ret = epoll_ctl(release_fence_fd_.Get(), EPOLL_CTL_MOD,
402 dummy_fence_fd_.Get(), &event);
403 ALOGE_IF(ret < 0,
Tianyu0c6b7ff2018-10-03 11:30:04 -0700404 "ProducerChannel::OnProducerPost: Failed to modify the shared "
405 "release fence to include the dummy fence: %s",
406 strerror(errno));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700407
Tianyu Jianga99f9112018-12-13 18:23:07 -0800408 eventfd_t dummy_fence_count = 0U;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700409 if (eventfd_read(dummy_fence_fd_.Get(), &dummy_fence_count) < 0) {
410 const int error = errno;
411 if (error != EAGAIN) {
412 ALOGE(
413 "ProducerChannel::ProducerChannel: Failed to read dummy fence, "
414 "error: %s",
415 strerror(error));
416 return ErrorStatus(error);
417 }
Corey Tabaka8a4e6a92017-04-20 13:42:02 -0700418 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800419
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700420 ALOGW_IF(dummy_fence_count > 0,
421 "ProducerChannel::ProducerChannel: %" PRIu64
422 " dummy fence(s) was signaled during last release/gain cycle "
423 "buffer_id=%d.",
424 dummy_fence_count, buffer_id());
425
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800426 post_fence_ = std::move(acquire_fence);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800427
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700428 // Signal any interested consumers. If there are none, the buffer will stay
429 // in posted state until a consumer comes online. This behavior guarantees
430 // that no frame is silently dropped.
Tianyu Jiangae9668c2018-12-07 15:14:47 -0800431 for (auto& consumer : consumer_channels_) {
Tianyu Jiang0cdd2a02018-11-15 10:20:45 -0800432 consumer->OnProducerPosted();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800433 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800434
Corey Tabakacd52dd92017-04-07 18:03:57 -0700435 return {};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800436}
437
Corey Tabakad53870c2017-07-06 18:04:27 -0700438Status<LocalFence> ProducerChannel::OnProducerGain(Message& /*message*/) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800439 ATRACE_NAME("ProducerChannel::OnGain");
Tianyu Jiangee2c43a2019-02-22 11:11:14 -0800440 ALOGD_IF(TRACE, "%s: buffer_id=%d", __FUNCTION__, buffer_id());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800441
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800442 ClearAvailable();
Alex Vakulenko052f3ae2017-03-31 09:10:43 -0700443 post_fence_.close();
Tianyu Jiangae9668c2018-12-07 15:14:47 -0800444 for (auto& consumer : consumer_channels_) {
445 consumer->OnProducerGained();
446 }
Corey Tabakacd52dd92017-04-07 18:03:57 -0700447 return {std::move(returned_fence_)};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800448}
449
Fan Xub0eec512018-10-30 11:33:15 -0700450// TODO(b/112338294) Keep here for reference. Remove it after new logic is
451// written.
452/* Status<RemoteChannelHandle> ProducerChannel::OnProducerDetach(
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700453 Message& message) {
454 ATRACE_NAME("ProducerChannel::OnProducerDetach");
455 ALOGD_IF(TRACE, "ProducerChannel::OnProducerDetach: buffer_id=%d",
456 buffer_id());
457
Tianyu Jianga99f9112018-12-13 18:23:07 -0800458 uint32_t buffer_state = buffer_state_->load(std::memory_order_acquire);
Tianyu Jiang727ede42019-02-01 11:44:51 -0800459 if (!BufferHubDefs::isClientGained(
Tianyuf669f6a2018-10-10 15:34:32 -0700460 buffer_state, BufferHubDefs::kFirstClientStateMask)) {
Jiwen 'Steve' Cai1c730242018-12-31 18:40:02 -0800461 // Can only detach a ProducerBuffer when it's in gained state.
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700462 ALOGW(
Tianyuf669f6a2018-10-10 15:34:32 -0700463 "ProducerChannel::OnProducerDetach: The buffer (id=%d, state=%"
Tianyu Jianga99f9112018-12-13 18:23:07 -0800464 PRIx32
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700465 ") is not in gained state.",
466 buffer_id(), buffer_state);
467 return {};
468 }
469
470 int channel_id;
471 auto status = message.PushChannel(0, nullptr, &channel_id);
472 if (!status) {
473 ALOGE(
474 "ProducerChannel::OnProducerDetach: Failed to push detached buffer "
475 "channel: %s",
476 status.GetErrorMessage().c_str());
477 return ErrorStatus(ENOMEM);
478 }
479
480 // Make sure we unlock the buffer.
481 if (int ret = metadata_buffer_.Unlock()) {
482 ALOGE("ProducerChannel::OnProducerDetach: Failed to unlock metadata.");
483 return ErrorStatus(-ret);
484 };
485
Jiwen 'Steve' Cai9004b8c2018-10-03 18:52:23 -0700486 std::unique_ptr<BufferChannel> channel =
487 BufferChannel::Create(service(), buffer_id(), channel_id,
488 std::move(buffer_), user_metadata_size_);
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700489 if (!channel) {
490 ALOGE("ProducerChannel::OnProducerDetach: Invalid buffer.");
491 return ErrorStatus(EINVAL);
492 }
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700493
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700494 const auto channel_status =
495 service()->SetChannel(channel_id, std::move(channel));
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700496 if (!channel_status) {
Tianyuf669f6a2018-10-10 15:34:32 -0700497 // Technically, this should never fail, as we just pushed the channel.
498 // Note that LOG_FATAL will be stripped out in non-debug build.
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700499 LOG_FATAL(
Tianyuf669f6a2018-10-10 15:34:32 -0700500 "ProducerChannel::OnProducerDetach: Failed to set new detached "
501 "buffer channel: %s.", channel_status.GetErrorMessage().c_str());
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700502 }
503
504 return status;
Fan Xub0eec512018-10-30 11:33:15 -0700505} */
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700506
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700507Status<LocalFence> ProducerChannel::OnConsumerAcquire(Message& /*message*/) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800508 ATRACE_NAME("ProducerChannel::OnConsumerAcquire");
509 ALOGD_IF(TRACE, "ProducerChannel::OnConsumerAcquire: buffer_id=%d",
510 buffer_id());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800511
Tianyuf669f6a2018-10-10 15:34:32 -0700512 // Return a borrowed fd to avoid unnecessary duplication of the underlying
513 // fd. Serialization just needs to read the handle.
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700514 return {std::move(post_fence_)};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800515}
516
Corey Tabakacd52dd92017-04-07 18:03:57 -0700517Status<void> ProducerChannel::OnConsumerRelease(Message&,
518 LocalFence release_fence) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800519 ATRACE_NAME("ProducerChannel::OnConsumerRelease");
520 ALOGD_IF(TRACE, "ProducerChannel::OnConsumerRelease: buffer_id=%d",
521 buffer_id());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800522
523 // Attempt to merge the fences if necessary.
524 if (release_fence) {
525 if (returned_fence_) {
Corey Tabaka3079cb72017-01-19 15:07:26 -0800526 LocalFence merged_fence(sync_merge("bufferhub_merged",
527 returned_fence_.get_fd(),
528 release_fence.get_fd()));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800529 const int error = errno;
530 if (!merged_fence) {
531 ALOGE("ProducerChannel::OnConsumerRelease: Failed to merge fences: %s",
532 strerror(error));
Corey Tabakacd52dd92017-04-07 18:03:57 -0700533 return ErrorStatus(error);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800534 }
535 returned_fence_ = std::move(merged_fence);
536 } else {
537 returned_fence_ = std::move(release_fence);
538 }
539 }
540
Tianyu Jianga8df5f32019-01-14 18:42:12 -0800541 if (IsBufferReleasedByAllActiveClientsExceptForOrphans()) {
Tianyu Jiange60a4ad2019-01-04 14:37:23 -0800542 buffer_state_->store(0U);
Tianyu Jiang0cdd2a02018-11-15 10:20:45 -0800543 SignalAvailable();
544 if (orphaned_consumer_bit_mask_) {
545 ALOGW(
546 "%s: orphaned buffer detected during the this acquire/release cycle: "
Jiwen 'Steve' Cai617ba802018-12-20 14:22:55 -0800547 "id=%d orphaned=0x%" PRIx32 " queue_index=%" PRId64 ".",
Tianyu Jiang0cdd2a02018-11-15 10:20:45 -0800548 __FUNCTION__, buffer_id(), orphaned_consumer_bit_mask_,
Tianyu Jiangf377a762019-02-13 13:46:42 -0800549 metadata_header_->queueIndex);
Tianyu Jiang0cdd2a02018-11-15 10:20:45 -0800550 orphaned_consumer_bit_mask_ = 0;
551 }
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700552 }
553
Corey Tabakacd52dd92017-04-07 18:03:57 -0700554 return {};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800555}
556
Tianyu Jianga99f9112018-12-13 18:23:07 -0800557void ProducerChannel::OnConsumerOrphaned(const uint32_t& consumer_state_mask) {
Tianyuf669f6a2018-10-10 15:34:32 -0700558 // Remember the ignored consumer so that newly added consumer won't be
559 // taking the same state mask as this orphaned consumer.
560 ALOGE_IF(orphaned_consumer_bit_mask_ & consumer_state_mask,
Tianyu Jianga99f9112018-12-13 18:23:07 -0800561 "%s: Consumer (consumer_state_mask=%" PRIx32
Tianyuf669f6a2018-10-10 15:34:32 -0700562 ") is already orphaned.",
563 __FUNCTION__, consumer_state_mask);
564 orphaned_consumer_bit_mask_ |= consumer_state_mask;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700565
Tianyu Jianga8df5f32019-01-14 18:42:12 -0800566 if (IsBufferReleasedByAllActiveClientsExceptForOrphans()) {
Tianyu Jiange60a4ad2019-01-04 14:37:23 -0800567 buffer_state_->store(0U);
Tianyu Jiang0cdd2a02018-11-15 10:20:45 -0800568 SignalAvailable();
569 }
570
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700571 // Atomically clear the fence state bit as an orphaned consumer will never
Tianyuf669f6a2018-10-10 15:34:32 -0700572 // signal a release fence.
573 fence_state_->fetch_and(~consumer_state_mask, std::memory_order_release);
574
575 // Atomically set the buffer state of this consumer to released state.
576 buffer_state_->fetch_and(~consumer_state_mask, std::memory_order_release);
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700577
578 ALOGW(
Tianyuf669f6a2018-10-10 15:34:32 -0700579 "%s: detected new orphaned consumer buffer_id=%d "
Jiwen 'Steve' Cai617ba802018-12-20 14:22:55 -0800580 "consumer_state_mask=%" PRIx32 " queue_index=%" PRId64
Tianyu Jianga99f9112018-12-13 18:23:07 -0800581 " buffer_state=%" PRIx32 " fence_state=%" PRIx32 ".",
Tianyuf669f6a2018-10-10 15:34:32 -0700582 __FUNCTION__, buffer_id(), consumer_state_mask,
Tianyu Jiangf377a762019-02-13 13:46:42 -0800583 metadata_header_->queueIndex,
Tianyu Jiange2cdec92018-10-30 17:40:58 -0700584 buffer_state_->load(std::memory_order_acquire),
585 fence_state_->load(std::memory_order_acquire));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700586}
587
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800588void ProducerChannel::AddConsumer(ConsumerChannel* channel) {
589 consumer_channels_.push_back(channel);
590}
591
592void ProducerChannel::RemoveConsumer(ConsumerChannel* channel) {
593 consumer_channels_.erase(
594 std::find(consumer_channels_.begin(), consumer_channels_.end(), channel));
Tianyu67053492018-10-04 14:00:22 -0700595 // Restore the consumer state bit and make it visible in other threads that
596 // acquire the active_clients_bit_mask_.
Tianyu Jianga99f9112018-12-13 18:23:07 -0800597 uint32_t consumer_state_mask = channel->client_state_mask();
598 uint32_t current_active_clients_bit_mask =
Tianyuf669f6a2018-10-10 15:34:32 -0700599 active_clients_bit_mask_->load(std::memory_order_acquire);
Tianyu Jianga99f9112018-12-13 18:23:07 -0800600 uint32_t updated_active_clients_bit_mask =
Tianyuf669f6a2018-10-10 15:34:32 -0700601 current_active_clients_bit_mask & (~consumer_state_mask);
602 while (!active_clients_bit_mask_->compare_exchange_weak(
603 current_active_clients_bit_mask, updated_active_clients_bit_mask,
604 std::memory_order_acq_rel, std::memory_order_acquire)) {
605 ALOGI(
606 "%s: Failed to remove consumer state mask. Current active clients bit "
Tianyu Jianga99f9112018-12-13 18:23:07 -0800607 "mask is changed to %" PRIx32
608 " when trying to acquire and modify it to %" PRIx32
Tianyuf669f6a2018-10-10 15:34:32 -0700609 ". About to try again.",
610 __FUNCTION__, current_active_clients_bit_mask,
611 updated_active_clients_bit_mask);
612 updated_active_clients_bit_mask =
613 current_active_clients_bit_mask & (~consumer_state_mask);
614 }
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700615
Tianyu Jianga99f9112018-12-13 18:23:07 -0800616 const uint32_t current_buffer_state =
Tianyuf669f6a2018-10-10 15:34:32 -0700617 buffer_state_->load(std::memory_order_acquire);
Tianyu Jiang727ede42019-02-01 11:44:51 -0800618 if (BufferHubDefs::isClientPosted(current_buffer_state,
Tianyuf669f6a2018-10-10 15:34:32 -0700619 consumer_state_mask) ||
Tianyu Jiang727ede42019-02-01 11:44:51 -0800620 BufferHubDefs::isClientAcquired(current_buffer_state,
Tianyuf669f6a2018-10-10 15:34:32 -0700621 consumer_state_mask)) {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700622 // The consumer client is being destoryed without releasing. This could
623 // happen in corner cases when the consumer crashes. Here we mark it
624 // orphaned before remove it from producer.
Tianyuf669f6a2018-10-10 15:34:32 -0700625 OnConsumerOrphaned(consumer_state_mask);
626 return;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700627 }
628
Tianyu Jiang727ede42019-02-01 11:44:51 -0800629 if (BufferHubDefs::isClientReleased(current_buffer_state,
Tianyuf669f6a2018-10-10 15:34:32 -0700630 consumer_state_mask) ||
Tianyu Jiang727ede42019-02-01 11:44:51 -0800631 BufferHubDefs::isAnyClientGained(current_buffer_state)) {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700632 // The consumer is being close while it is suppose to signal a release
633 // fence. Signal the dummy fence here.
Tianyuf669f6a2018-10-10 15:34:32 -0700634 if (fence_state_->load(std::memory_order_acquire) & consumer_state_mask) {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700635 epoll_event event;
636 event.events = EPOLLIN;
Tianyu Jianga99f9112018-12-13 18:23:07 -0800637 event.data.u32 = consumer_state_mask;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700638 if (epoll_ctl(release_fence_fd_.Get(), EPOLL_CTL_MOD,
639 dummy_fence_fd_.Get(), &event) < 0) {
640 ALOGE(
Tianyuf669f6a2018-10-10 15:34:32 -0700641 "%s: Failed to modify the shared release fence to include the "
642 "dummy fence: %s",
643 __FUNCTION__, strerror(errno));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700644 return;
645 }
Tianyuf669f6a2018-10-10 15:34:32 -0700646 ALOGW("%s: signal dummy release fence buffer_id=%d", __FUNCTION__,
647 buffer_id());
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700648 eventfd_write(dummy_fence_fd_.Get(), 1);
649 }
650 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800651}
652
Tianyuf669f6a2018-10-10 15:34:32 -0700653// Returns true if the given parameters match the underlying buffer
654// parameters.
Corey Tabakacd52dd92017-04-07 18:03:57 -0700655bool ProducerChannel::CheckParameters(uint32_t width, uint32_t height,
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700656 uint32_t layer_count, uint32_t format,
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700657 uint64_t usage,
Tianyu Jianga8df5f32019-01-14 18:42:12 -0800658 size_t user_metadata_size) const {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700659 return user_metadata_size == user_metadata_size_ &&
660 buffer_.width() == width && buffer_.height() == height &&
661 buffer_.layer_count() == layer_count && buffer_.format() == format &&
662 buffer_.usage() == usage;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800663}
664
Tianyu Jianga8df5f32019-01-14 18:42:12 -0800665bool ProducerChannel::IsBufferReleasedByAllActiveClientsExceptForOrphans()
666 const {
667 return (buffer_state_->load(std::memory_order_acquire) &
668 ~orphaned_consumer_bit_mask_ &
669 active_clients_bit_mask_->load(std::memory_order_acquire)) == 0U;
670}
671
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800672} // namespace dvr
673} // namespace android