blob: 2a6e9da389e2fb6a14e6577921695fcc18f0d3ac [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>
Fan Xu74df4902018-09-20 16:40:51 -070010#include <private/dvr/buffer_channel.h>
Tianyu0c6b7ff2018-10-03 11:30:04 -070011#include <private/dvr/bufferhub_rpc.h>
Fan Xu74df4902018-09-20 16:40:51 -070012#include <private/dvr/consumer_channel.h>
13#include <private/dvr/producer_channel.h>
14#include <sync/sync.h>
15#include <utils/Trace.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080016
17using android::pdx::BorrowedHandle;
Corey Tabakacd52dd92017-04-07 18:03:57 -070018using android::pdx::ErrorStatus;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080019using android::pdx::Message;
20using android::pdx::RemoteChannelHandle;
Corey Tabakacd52dd92017-04-07 18:03:57 -070021using android::pdx::Status;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080022using android::pdx::rpc::BufferWrapper;
23using android::pdx::rpc::DispatchRemoteMethod;
24using android::pdx::rpc::WrapBuffer;
25
26namespace android {
27namespace dvr {
28
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -070029ProducerChannel::ProducerChannel(BufferHubService* service, int buffer_id,
30 int channel_id, IonBuffer buffer,
31 IonBuffer metadata_buffer,
32 size_t user_metadata_size, int* error)
33 : BufferHubChannel(service, buffer_id, channel_id, kProducerType),
34 buffer_(std::move(buffer)),
35 metadata_buffer_(std::move(metadata_buffer)),
36 user_metadata_size_(user_metadata_size),
37 metadata_buf_size_(BufferHubDefs::kMetadataHeaderSize +
38 user_metadata_size) {
39 if (!buffer_.IsValid()) {
40 ALOGE("ProducerChannel::ProducerChannel: Invalid buffer.");
41 *error = -EINVAL;
42 return;
43 }
44 if (!metadata_buffer_.IsValid()) {
45 ALOGE("ProducerChannel::ProducerChannel: Invalid metadata buffer.");
46 *error = -EINVAL;
47 return;
48 }
49
50 *error = InitializeBuffer();
51}
52
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080053ProducerChannel::ProducerChannel(BufferHubService* service, int channel_id,
Corey Tabakacd52dd92017-04-07 18:03:57 -070054 uint32_t width, uint32_t height,
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -070055 uint32_t layer_count, uint32_t format,
Corey Tabaka52ea25c2017-09-13 18:02:48 -070056 uint64_t usage, size_t user_metadata_size,
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -070057 int* error)
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080058 : BufferHubChannel(service, channel_id, channel_id, kProducerType),
Corey Tabaka52ea25c2017-09-13 18:02:48 -070059 user_metadata_size_(user_metadata_size),
60 metadata_buf_size_(BufferHubDefs::kMetadataHeaderSize +
61 user_metadata_size) {
62 if (int ret = buffer_.Alloc(width, height, layer_count, format, usage)) {
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -070063 ALOGE("ProducerChannel::ProducerChannel: Failed to allocate buffer: %s",
64 strerror(-ret));
65 *error = ret;
66 return;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080067 }
68
Corey Tabaka52ea25c2017-09-13 18:02:48 -070069 if (int ret = metadata_buffer_.Alloc(metadata_buf_size_, /*height=*/1,
70 /*layer_count=*/1,
71 BufferHubDefs::kMetadataFormat,
72 BufferHubDefs::kMetadataUsage)) {
73 ALOGE("ProducerChannel::ProducerChannel: Failed to allocate metadata: %s",
74 strerror(-ret));
75 *error = ret;
76 return;
77 }
78
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -070079 *error = InitializeBuffer();
80}
81
82int ProducerChannel::InitializeBuffer() {
Corey Tabaka52ea25c2017-09-13 18:02:48 -070083 void* metadata_ptr = nullptr;
84 if (int ret = metadata_buffer_.Lock(BufferHubDefs::kMetadataUsage, /*x=*/0,
85 /*y=*/0, metadata_buf_size_,
86 /*height=*/1, &metadata_ptr)) {
87 ALOGE("ProducerChannel::ProducerChannel: Failed to lock metadata.");
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -070088 return ret;
Corey Tabaka52ea25c2017-09-13 18:02:48 -070089 }
90 metadata_header_ =
91 reinterpret_cast<BufferHubDefs::MetadataHeader*>(metadata_ptr);
92
93 // Using placement new here to reuse shared memory instead of new allocation
94 // and also initialize the value to zero.
95 buffer_state_ =
Tianyu Jianga99f9112018-12-13 18:23:07 -080096 new (&metadata_header_->buffer_state) std::atomic<uint32_t>(0);
97 fence_state_ = new (&metadata_header_->fence_state) std::atomic<uint32_t>(0);
Tianyu67053492018-10-04 14:00:22 -070098 active_clients_bit_mask_ =
Tianyu Jianga99f9112018-12-13 18:23:07 -080099 new (&metadata_header_->active_clients_bit_mask) std::atomic<uint32_t>(0);
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700100
Tianyu Jiang63dd7c32018-10-30 18:35:06 -0700101 // Producer channel is never created after consumer channel, and one buffer
102 // only have one fixed producer for now. Thus, it is correct to assume
103 // producer state bit is kFirstClientBitMask for now.
104 active_clients_bit_mask_->store(BufferHubDefs::kFirstClientBitMask,
105 std::memory_order_release);
106
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700107 acquire_fence_fd_.Reset(epoll_create1(EPOLL_CLOEXEC));
108 release_fence_fd_.Reset(epoll_create1(EPOLL_CLOEXEC));
109 if (!acquire_fence_fd_ || !release_fence_fd_) {
110 ALOGE("ProducerChannel::ProducerChannel: Failed to create shared fences.");
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -0700111 return -EIO;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700112 }
113
114 dummy_fence_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
115 if (!dummy_fence_fd_) {
116 ALOGE("ProducerChannel::ProducerChannel: Failed to create dummy fences.");
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -0700117 return EIO;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700118 }
119
120 epoll_event event;
121 event.events = 0;
Tianyu Jianga99f9112018-12-13 18:23:07 -0800122 event.data.u32 = 0U;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700123 if (epoll_ctl(release_fence_fd_.Get(), EPOLL_CTL_ADD, dummy_fence_fd_.Get(),
124 &event) < 0) {
125 ALOGE(
126 "ProducerChannel::ProducerChannel: Failed to modify the shared "
127 "release fence to include the dummy fence: %s",
128 strerror(errno));
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -0700129 return -EIO;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700130 }
131
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800132 // Success.
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -0700133 return 0;
134}
135
136std::unique_ptr<ProducerChannel> ProducerChannel::Create(
137 BufferHubService* service, int buffer_id, int channel_id, IonBuffer buffer,
138 IonBuffer metadata_buffer, size_t user_metadata_size) {
139 int error = 0;
140 std::unique_ptr<ProducerChannel> producer(new ProducerChannel(
141 service, buffer_id, channel_id, std::move(buffer),
142 std::move(metadata_buffer), user_metadata_size, &error));
143
144 if (error < 0)
145 return nullptr;
146 else
147 return producer;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800148}
149
Corey Tabakacd52dd92017-04-07 18:03:57 -0700150Status<std::shared_ptr<ProducerChannel>> ProducerChannel::Create(
151 BufferHubService* service, int channel_id, uint32_t width, uint32_t height,
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700152 uint32_t layer_count, uint32_t format, uint64_t usage,
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700153 size_t user_metadata_size) {
Corey Tabakacd52dd92017-04-07 18:03:57 -0700154 int error;
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -0700155 std::shared_ptr<ProducerChannel> producer(
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700156 new ProducerChannel(service, channel_id, width, height, layer_count,
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700157 format, usage, user_metadata_size, &error));
Corey Tabakacd52dd92017-04-07 18:03:57 -0700158 if (error < 0)
159 return ErrorStatus(-error);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800160 else
Corey Tabakacd52dd92017-04-07 18:03:57 -0700161 return {std::move(producer)};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800162}
163
164ProducerChannel::~ProducerChannel() {
Corey Tabaka3079cb72017-01-19 15:07:26 -0800165 ALOGD_IF(TRACE,
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700166 "ProducerChannel::~ProducerChannel: channel_id=%d buffer_id=%d "
Tianyu Jianga99f9112018-12-13 18:23:07 -0800167 "state=%" PRIx32 ".",
Tianyu Jiange2cdec92018-10-30 17:40:58 -0700168 channel_id(), buffer_id(),
169 buffer_state_->load(std::memory_order_acquire));
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700170 for (auto consumer : consumer_channels_) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800171 consumer->OnProducerClosed();
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700172 }
173 Hangup();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800174}
175
176BufferHubChannel::BufferInfo ProducerChannel::GetBufferInfo() const {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700177 // Derive the mask of signaled buffers in this producer / consumer set.
Tianyu Jianga99f9112018-12-13 18:23:07 -0800178 uint32_t signaled_mask = signaled() ? BufferHubDefs::kFirstClientBitMask : 0;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700179 for (const ConsumerChannel* consumer : consumer_channels_) {
Tianyu Jiang83a991f2018-10-30 16:59:29 -0700180 signaled_mask |= consumer->signaled() ? consumer->client_state_mask() : 0;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700181 }
182
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -0700183 return BufferInfo(buffer_id(), consumer_channels_.size(), buffer_.width(),
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700184 buffer_.height(), buffer_.layer_count(), buffer_.format(),
Tianyu Jiang0cdd2a02018-11-15 10:20:45 -0800185 buffer_.usage(),
Tianyu Jiange2cdec92018-10-30 17:40:58 -0700186 buffer_state_->load(std::memory_order_acquire),
Jiwen 'Steve' Cai2f260332018-02-15 18:39:47 -0800187 signaled_mask, metadata_header_->queue_index);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800188}
189
190void ProducerChannel::HandleImpulse(Message& message) {
191 ATRACE_NAME("ProducerChannel::HandleImpulse");
192 switch (message.GetOp()) {
193 case BufferHubRPC::ProducerGain::Opcode:
194 OnProducerGain(message);
195 break;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700196 case BufferHubRPC::ProducerPost::Opcode:
197 OnProducerPost(message, {});
198 break;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800199 }
200}
201
202bool ProducerChannel::HandleMessage(Message& message) {
203 ATRACE_NAME("ProducerChannel::HandleMessage");
204 switch (message.GetOp()) {
205 case BufferHubRPC::GetBuffer::Opcode:
206 DispatchRemoteMethod<BufferHubRPC::GetBuffer>(
207 *this, &ProducerChannel::OnGetBuffer, message);
208 return true;
209
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800210 case BufferHubRPC::NewConsumer::Opcode:
211 DispatchRemoteMethod<BufferHubRPC::NewConsumer>(
212 *this, &ProducerChannel::OnNewConsumer, message);
213 return true;
214
215 case BufferHubRPC::ProducerPost::Opcode:
216 DispatchRemoteMethod<BufferHubRPC::ProducerPost>(
217 *this, &ProducerChannel::OnProducerPost, message);
218 return true;
219
220 case BufferHubRPC::ProducerGain::Opcode:
221 DispatchRemoteMethod<BufferHubRPC::ProducerGain>(
222 *this, &ProducerChannel::OnProducerGain, message);
223 return true;
224
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800225 default:
226 return false;
227 }
228}
229
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700230BufferDescription<BorrowedHandle> ProducerChannel::GetBuffer(
Tianyu Jianga99f9112018-12-13 18:23:07 -0800231 uint32_t client_state_mask) {
Jiwen 'Steve' Cai57ae3ee2018-05-03 17:51:52 -0700232 return {buffer_,
233 metadata_buffer_,
234 buffer_id(),
235 channel_id(),
Tianyu Jiang7e204b72018-10-26 15:39:18 -0700236 client_state_mask,
Jiwen 'Steve' Cai57ae3ee2018-05-03 17:51:52 -0700237 acquire_fence_fd_.Borrow(),
238 release_fence_fd_.Borrow()};
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700239}
240
241Status<BufferDescription<BorrowedHandle>> ProducerChannel::OnGetBuffer(
Corey Tabakad53870c2017-07-06 18:04:27 -0700242 Message& /*message*/) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800243 ATRACE_NAME("ProducerChannel::OnGetBuffer");
Tianyu Jianga99f9112018-12-13 18:23:07 -0800244 ALOGD_IF(TRACE, "ProducerChannel::OnGetBuffer: buffer=%d, state=%" PRIx32 ".",
Tianyu Jiange2cdec92018-10-30 17:40:58 -0700245 buffer_id(), buffer_state_->load(std::memory_order_acquire));
Tianyu Jiang63dd7c32018-10-30 18:35:06 -0700246 return {GetBuffer(BufferHubDefs::kFirstClientBitMask)};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800247}
248
Tianyu Jianga99f9112018-12-13 18:23:07 -0800249Status<uint32_t> ProducerChannel::CreateConsumerStateMask() {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700250 // Try find the next consumer state bit which has not been claimed by any
251 // consumer yet.
Tianyu67053492018-10-04 14:00:22 -0700252 // memory_order_acquire is chosen here because all writes in other threads
253 // that release active_clients_bit_mask_ need to be visible here.
Tianyu Jianga99f9112018-12-13 18:23:07 -0800254 uint32_t current_active_clients_bit_mask =
Tianyu67053492018-10-04 14:00:22 -0700255 active_clients_bit_mask_->load(std::memory_order_acquire);
Tianyu Jianga99f9112018-12-13 18:23:07 -0800256 uint32_t consumer_state_mask =
Tianyuf669f6a2018-10-10 15:34:32 -0700257 BufferHubDefs::FindNextAvailableClientStateMask(
258 current_active_clients_bit_mask | orphaned_consumer_bit_mask_);
Tianyu Jianga99f9112018-12-13 18:23:07 -0800259 if (consumer_state_mask == 0U) {
Tianyuf669f6a2018-10-10 15:34:32 -0700260 ALOGE("%s: reached the maximum mumber of consumers per producer: 63.",
261 __FUNCTION__);
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700262 return ErrorStatus(E2BIG);
263 }
Tianyu Jianga99f9112018-12-13 18:23:07 -0800264 uint32_t updated_active_clients_bit_mask =
Tianyuf669f6a2018-10-10 15:34:32 -0700265 current_active_clients_bit_mask | consumer_state_mask;
Tianyu67053492018-10-04 14:00:22 -0700266 // Set the updated value only if the current value stays the same as what was
267 // read before. If the comparison succeeds, update the value without
268 // reordering anything before or after this read-modify-write in the current
269 // thread, and the modification will be visible in other threads that acquire
270 // active_clients_bit_mask_. If the comparison fails, load the result of
271 // all writes from all threads to updated_active_clients_bit_mask.
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800272 // Keep on finding the next available slient state mask until succeed or out
273 // of memory.
274 while (!active_clients_bit_mask_->compare_exchange_weak(
275 current_active_clients_bit_mask, updated_active_clients_bit_mask,
276 std::memory_order_acq_rel, std::memory_order_acquire)) {
Tianyu Jianga99f9112018-12-13 18:23:07 -0800277 ALOGE("%s: Current active clients bit mask is changed to %" PRIx32
278 ", which was expected to be %" PRIx32
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800279 ". Trying to generate a new client state mask to resolve race "
280 "condition.",
Tianyuf669f6a2018-10-10 15:34:32 -0700281 __FUNCTION__, updated_active_clients_bit_mask,
282 current_active_clients_bit_mask);
283 consumer_state_mask = BufferHubDefs::FindNextAvailableClientStateMask(
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800284 current_active_clients_bit_mask | orphaned_consumer_bit_mask_);
Tianyu Jianga99f9112018-12-13 18:23:07 -0800285 if (consumer_state_mask == 0U) {
Tianyuf669f6a2018-10-10 15:34:32 -0700286 ALOGE("%s: reached the maximum mumber of consumers per producer: %d.",
287 __FUNCTION__, (BufferHubDefs::kMaxNumberOfClients - 1));
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800288 return ErrorStatus(E2BIG);
289 }
290 updated_active_clients_bit_mask =
Tianyuf669f6a2018-10-10 15:34:32 -0700291 current_active_clients_bit_mask | consumer_state_mask;
Tianyu67053492018-10-04 14:00:22 -0700292 }
293
Tianyuf669f6a2018-10-10 15:34:32 -0700294 return {consumer_state_mask};
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800295}
296
Tianyu Jianga99f9112018-12-13 18:23:07 -0800297void ProducerChannel::RemoveConsumerClientMask(uint32_t consumer_state_mask) {
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800298 // Clear up the buffer state and fence state in case there is already
299 // something there due to possible race condition between producer post and
300 // consumer failed to create channel.
301 buffer_state_->fetch_and(~consumer_state_mask, std::memory_order_release);
302 fence_state_->fetch_and(~consumer_state_mask, std::memory_order_release);
303
304 // Restore the consumer state bit and make it visible in other threads that
305 // acquire the active_clients_bit_mask_.
306 active_clients_bit_mask_->fetch_and(~consumer_state_mask,
307 std::memory_order_release);
308}
309
310Status<RemoteChannelHandle> ProducerChannel::CreateConsumer(
Tianyu Jianga99f9112018-12-13 18:23:07 -0800311 Message& message, uint32_t consumer_state_mask) {
Tianyuf669f6a2018-10-10 15:34:32 -0700312 ATRACE_NAME(__FUNCTION__);
Jiwen 'Steve' Cai617ba802018-12-20 14:22:55 -0800313 ALOGD("%s: buffer_id=%d", __FUNCTION__, buffer_id());
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800314
315 int channel_id;
316 auto status = message.PushChannel(0, nullptr, &channel_id);
317 if (!status) {
Tianyuf669f6a2018-10-10 15:34:32 -0700318 ALOGE("%s: Failed to push consumer channel: %s", __FUNCTION__,
319 status.GetErrorMessage().c_str());
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800320 RemoveConsumerClientMask(consumer_state_mask);
321 return ErrorStatus(ENOMEM);
322 }
323
324 auto consumer = std::make_shared<ConsumerChannel>(
325 service(), buffer_id(), channel_id, consumer_state_mask,
326 shared_from_this());
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700327 const auto channel_status = service()->SetChannel(channel_id, consumer);
328 if (!channel_status) {
Tianyuf669f6a2018-10-10 15:34:32 -0700329 ALOGE("%s: failed to set new consumer channel: %s.", __FUNCTION__,
330 channel_status.GetErrorMessage().c_str());
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800331 RemoveConsumerClientMask(consumer_state_mask);
Corey Tabakacd52dd92017-04-07 18:03:57 -0700332 return ErrorStatus(ENOMEM);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800333 }
334
Tianyu Jianga99f9112018-12-13 18:23:07 -0800335 uint32_t current_buffer_state =
Tianyu Jiangca9201a2018-11-06 12:40:33 -0800336 buffer_state_->load(std::memory_order_acquire);
Tianyuf669f6a2018-10-10 15:34:32 -0700337 if (BufferHubDefs::IsBufferReleased(current_buffer_state) ||
338 BufferHubDefs::AnyClientGained(current_buffer_state)) {
339 return {status.take()};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800340 }
341
Tianyuf669f6a2018-10-10 15:34:32 -0700342 // Signal the new consumer when adding it to a posted producer.
343 bool update_buffer_state = true;
344 if (!BufferHubDefs::IsClientPosted(current_buffer_state,
345 consumer_state_mask)) {
Tianyu Jianga99f9112018-12-13 18:23:07 -0800346 uint32_t updated_buffer_state =
Tianyuf669f6a2018-10-10 15:34:32 -0700347 current_buffer_state ^
348 (consumer_state_mask & BufferHubDefs::kHighBitsMask);
349 while (!buffer_state_->compare_exchange_weak(
350 current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
351 std::memory_order_acquire)) {
352 ALOGI(
353 "%s: Failed to post to the new consumer. "
Tianyu Jianga99f9112018-12-13 18:23:07 -0800354 "Current buffer state was changed to %" PRIx32
Tianyuf669f6a2018-10-10 15:34:32 -0700355 " when trying to acquire the buffer and modify the buffer state to "
Tianyu Jianga99f9112018-12-13 18:23:07 -0800356 "%" PRIx32
Tianyuf669f6a2018-10-10 15:34:32 -0700357 ". About to try again if the buffer is still not gained nor fully "
358 "released.",
359 __FUNCTION__, current_buffer_state, updated_buffer_state);
360 if (BufferHubDefs::IsBufferReleased(current_buffer_state) ||
361 BufferHubDefs::AnyClientGained(current_buffer_state)) {
Tianyu Jianga99f9112018-12-13 18:23:07 -0800362 ALOGI("%s: buffer is gained or fully released, state=%" PRIx32 ".",
Tianyuf669f6a2018-10-10 15:34:32 -0700363 __FUNCTION__, current_buffer_state);
364 update_buffer_state = false;
365 break;
366 }
367 updated_buffer_state =
368 current_buffer_state ^
369 (consumer_state_mask & BufferHubDefs::kHighBitsMask);
370 }
371 }
Tianyu Jiang0cdd2a02018-11-15 10:20:45 -0800372 if (update_buffer_state) {
373 consumer->OnProducerPosted();
374 }
Tianyuf669f6a2018-10-10 15:34:32 -0700375
Corey Tabakacd52dd92017-04-07 18:03:57 -0700376 return {status.take()};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800377}
378
Corey Tabakacd52dd92017-04-07 18:03:57 -0700379Status<RemoteChannelHandle> ProducerChannel::OnNewConsumer(Message& message) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800380 ATRACE_NAME("ProducerChannel::OnNewConsumer");
381 ALOGD_IF(TRACE, "ProducerChannel::OnNewConsumer: buffer_id=%d", buffer_id());
Tianyu Jiang50f7ad12018-11-08 11:13:35 -0800382 auto status = CreateConsumerStateMask();
383 if (!status.ok()) {
384 return status.error_status();
385 }
386 return CreateConsumer(message, /*consumer_state_mask=*/status.get());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800387}
388
Tianyu0c6b7ff2018-10-03 11:30:04 -0700389Status<void> ProducerChannel::OnProducerPost(Message&,
390 LocalFence acquire_fence) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800391 ATRACE_NAME("ProducerChannel::OnProducerPost");
Jiwen 'Steve' Cai617ba802018-12-20 14:22:55 -0800392 ALOGD("ProducerChannel::OnProducerPost: buffer_id=%d, state=0x%x",
393 buffer_id(), buffer_state_->load(std::memory_order_acquire));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800394
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700395 epoll_event event;
396 event.events = 0;
Tianyu Jianga99f9112018-12-13 18:23:07 -0800397 event.data.u32 = 0U;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700398 int ret = epoll_ctl(release_fence_fd_.Get(), EPOLL_CTL_MOD,
399 dummy_fence_fd_.Get(), &event);
400 ALOGE_IF(ret < 0,
Tianyu0c6b7ff2018-10-03 11:30:04 -0700401 "ProducerChannel::OnProducerPost: Failed to modify the shared "
402 "release fence to include the dummy fence: %s",
403 strerror(errno));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700404
Tianyu Jianga99f9112018-12-13 18:23:07 -0800405 eventfd_t dummy_fence_count = 0U;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700406 if (eventfd_read(dummy_fence_fd_.Get(), &dummy_fence_count) < 0) {
407 const int error = errno;
408 if (error != EAGAIN) {
409 ALOGE(
410 "ProducerChannel::ProducerChannel: Failed to read dummy fence, "
411 "error: %s",
412 strerror(error));
413 return ErrorStatus(error);
414 }
Corey Tabaka8a4e6a92017-04-20 13:42:02 -0700415 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800416
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700417 ALOGW_IF(dummy_fence_count > 0,
418 "ProducerChannel::ProducerChannel: %" PRIu64
419 " dummy fence(s) was signaled during last release/gain cycle "
420 "buffer_id=%d.",
421 dummy_fence_count, buffer_id());
422
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800423 post_fence_ = std::move(acquire_fence);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800424
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700425 // Signal any interested consumers. If there are none, the buffer will stay
426 // in posted state until a consumer comes online. This behavior guarantees
427 // that no frame is silently dropped.
Tianyu Jiangae9668c2018-12-07 15:14:47 -0800428 for (auto& consumer : consumer_channels_) {
Tianyu Jiang0cdd2a02018-11-15 10:20:45 -0800429 consumer->OnProducerPosted();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800430 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800431
Corey Tabakacd52dd92017-04-07 18:03:57 -0700432 return {};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800433}
434
Corey Tabakad53870c2017-07-06 18:04:27 -0700435Status<LocalFence> ProducerChannel::OnProducerGain(Message& /*message*/) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800436 ATRACE_NAME("ProducerChannel::OnGain");
Jiwen 'Steve' Cai617ba802018-12-20 14:22:55 -0800437 ALOGW("ProducerChannel::OnGain: buffer_id=%d", buffer_id());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800438
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800439 ClearAvailable();
Alex Vakulenko052f3ae2017-03-31 09:10:43 -0700440 post_fence_.close();
Tianyu Jiangae9668c2018-12-07 15:14:47 -0800441 for (auto& consumer : consumer_channels_) {
442 consumer->OnProducerGained();
443 }
Corey Tabakacd52dd92017-04-07 18:03:57 -0700444 return {std::move(returned_fence_)};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800445}
446
Fan Xub0eec512018-10-30 11:33:15 -0700447// TODO(b/112338294) Keep here for reference. Remove it after new logic is
448// written.
449/* Status<RemoteChannelHandle> ProducerChannel::OnProducerDetach(
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700450 Message& message) {
451 ATRACE_NAME("ProducerChannel::OnProducerDetach");
452 ALOGD_IF(TRACE, "ProducerChannel::OnProducerDetach: buffer_id=%d",
453 buffer_id());
454
Tianyu Jianga99f9112018-12-13 18:23:07 -0800455 uint32_t buffer_state = buffer_state_->load(std::memory_order_acquire);
Tianyuf669f6a2018-10-10 15:34:32 -0700456 if (!BufferHubDefs::IsClientGained(
457 buffer_state, BufferHubDefs::kFirstClientStateMask)) {
Jiwen 'Steve' Cai1c730242018-12-31 18:40:02 -0800458 // Can only detach a ProducerBuffer when it's in gained state.
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700459 ALOGW(
Tianyuf669f6a2018-10-10 15:34:32 -0700460 "ProducerChannel::OnProducerDetach: The buffer (id=%d, state=%"
Tianyu Jianga99f9112018-12-13 18:23:07 -0800461 PRIx32
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700462 ") is not in gained state.",
463 buffer_id(), buffer_state);
464 return {};
465 }
466
467 int channel_id;
468 auto status = message.PushChannel(0, nullptr, &channel_id);
469 if (!status) {
470 ALOGE(
471 "ProducerChannel::OnProducerDetach: Failed to push detached buffer "
472 "channel: %s",
473 status.GetErrorMessage().c_str());
474 return ErrorStatus(ENOMEM);
475 }
476
477 // Make sure we unlock the buffer.
478 if (int ret = metadata_buffer_.Unlock()) {
479 ALOGE("ProducerChannel::OnProducerDetach: Failed to unlock metadata.");
480 return ErrorStatus(-ret);
481 };
482
Jiwen 'Steve' Cai9004b8c2018-10-03 18:52:23 -0700483 std::unique_ptr<BufferChannel> channel =
484 BufferChannel::Create(service(), buffer_id(), channel_id,
485 std::move(buffer_), user_metadata_size_);
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700486 if (!channel) {
487 ALOGE("ProducerChannel::OnProducerDetach: Invalid buffer.");
488 return ErrorStatus(EINVAL);
489 }
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700490
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700491 const auto channel_status =
492 service()->SetChannel(channel_id, std::move(channel));
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700493 if (!channel_status) {
Tianyuf669f6a2018-10-10 15:34:32 -0700494 // Technically, this should never fail, as we just pushed the channel.
495 // Note that LOG_FATAL will be stripped out in non-debug build.
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700496 LOG_FATAL(
Tianyuf669f6a2018-10-10 15:34:32 -0700497 "ProducerChannel::OnProducerDetach: Failed to set new detached "
498 "buffer channel: %s.", channel_status.GetErrorMessage().c_str());
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700499 }
500
501 return status;
Fan Xub0eec512018-10-30 11:33:15 -0700502} */
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700503
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700504Status<LocalFence> ProducerChannel::OnConsumerAcquire(Message& /*message*/) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800505 ATRACE_NAME("ProducerChannel::OnConsumerAcquire");
506 ALOGD_IF(TRACE, "ProducerChannel::OnConsumerAcquire: buffer_id=%d",
507 buffer_id());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800508
Tianyuf669f6a2018-10-10 15:34:32 -0700509 // Return a borrowed fd to avoid unnecessary duplication of the underlying
510 // fd. Serialization just needs to read the handle.
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700511 return {std::move(post_fence_)};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800512}
513
Corey Tabakacd52dd92017-04-07 18:03:57 -0700514Status<void> ProducerChannel::OnConsumerRelease(Message&,
515 LocalFence release_fence) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800516 ATRACE_NAME("ProducerChannel::OnConsumerRelease");
517 ALOGD_IF(TRACE, "ProducerChannel::OnConsumerRelease: buffer_id=%d",
518 buffer_id());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800519
520 // Attempt to merge the fences if necessary.
521 if (release_fence) {
522 if (returned_fence_) {
Corey Tabaka3079cb72017-01-19 15:07:26 -0800523 LocalFence merged_fence(sync_merge("bufferhub_merged",
524 returned_fence_.get_fd(),
525 release_fence.get_fd()));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800526 const int error = errno;
527 if (!merged_fence) {
528 ALOGE("ProducerChannel::OnConsumerRelease: Failed to merge fences: %s",
529 strerror(error));
Corey Tabakacd52dd92017-04-07 18:03:57 -0700530 return ErrorStatus(error);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800531 }
532 returned_fence_ = std::move(merged_fence);
533 } else {
534 returned_fence_ = std::move(release_fence);
535 }
536 }
537
Tianyu Jianga99f9112018-12-13 18:23:07 -0800538 uint32_t current_buffer_state =
Tianyu Jiang0cdd2a02018-11-15 10:20:45 -0800539 buffer_state_->load(std::memory_order_acquire);
Tianyu Jiangae9668c2018-12-07 15:14:47 -0800540 if (BufferHubDefs::IsBufferReleased(current_buffer_state &
Tianyu Jiang0cdd2a02018-11-15 10:20:45 -0800541 ~orphaned_consumer_bit_mask_)) {
542 SignalAvailable();
543 if (orphaned_consumer_bit_mask_) {
544 ALOGW(
545 "%s: orphaned buffer detected during the this acquire/release cycle: "
Jiwen 'Steve' Cai617ba802018-12-20 14:22:55 -0800546 "id=%d orphaned=0x%" PRIx32 " queue_index=%" PRId64 ".",
Tianyu Jiang0cdd2a02018-11-15 10:20:45 -0800547 __FUNCTION__, buffer_id(), orphaned_consumer_bit_mask_,
548 metadata_header_->queue_index);
549 orphaned_consumer_bit_mask_ = 0;
550 }
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700551 }
552
Corey Tabakacd52dd92017-04-07 18:03:57 -0700553 return {};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800554}
555
Tianyu Jianga99f9112018-12-13 18:23:07 -0800556void ProducerChannel::OnConsumerOrphaned(const uint32_t& consumer_state_mask) {
Tianyuf669f6a2018-10-10 15:34:32 -0700557 // Remember the ignored consumer so that newly added consumer won't be
558 // taking the same state mask as this orphaned consumer.
559 ALOGE_IF(orphaned_consumer_bit_mask_ & consumer_state_mask,
Tianyu Jianga99f9112018-12-13 18:23:07 -0800560 "%s: Consumer (consumer_state_mask=%" PRIx32
Tianyuf669f6a2018-10-10 15:34:32 -0700561 ") is already orphaned.",
562 __FUNCTION__, consumer_state_mask);
563 orphaned_consumer_bit_mask_ |= consumer_state_mask;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700564
Tianyu Jianga99f9112018-12-13 18:23:07 -0800565 uint32_t current_buffer_state =
Tianyu Jiang0cdd2a02018-11-15 10:20:45 -0800566 buffer_state_->load(std::memory_order_acquire);
Tianyu Jiangae9668c2018-12-07 15:14:47 -0800567 if (BufferHubDefs::IsBufferReleased(current_buffer_state &
Tianyu Jiang0cdd2a02018-11-15 10:20:45 -0800568 ~orphaned_consumer_bit_mask_)) {
569 SignalAvailable();
570 }
571
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700572 // Atomically clear the fence state bit as an orphaned consumer will never
Tianyuf669f6a2018-10-10 15:34:32 -0700573 // signal a release fence.
574 fence_state_->fetch_and(~consumer_state_mask, std::memory_order_release);
575
576 // Atomically set the buffer state of this consumer to released state.
577 buffer_state_->fetch_and(~consumer_state_mask, std::memory_order_release);
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700578
579 ALOGW(
Tianyuf669f6a2018-10-10 15:34:32 -0700580 "%s: detected new orphaned consumer buffer_id=%d "
Jiwen 'Steve' Cai617ba802018-12-20 14:22:55 -0800581 "consumer_state_mask=%" PRIx32 " queue_index=%" PRId64
Tianyu Jianga99f9112018-12-13 18:23:07 -0800582 " buffer_state=%" PRIx32 " fence_state=%" PRIx32 ".",
Tianyuf669f6a2018-10-10 15:34:32 -0700583 __FUNCTION__, buffer_id(), consumer_state_mask,
584 metadata_header_->queue_index,
Tianyu Jiange2cdec92018-10-30 17:40:58 -0700585 buffer_state_->load(std::memory_order_acquire),
586 fence_state_->load(std::memory_order_acquire));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700587}
588
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800589void ProducerChannel::AddConsumer(ConsumerChannel* channel) {
590 consumer_channels_.push_back(channel);
591}
592
593void ProducerChannel::RemoveConsumer(ConsumerChannel* channel) {
594 consumer_channels_.erase(
595 std::find(consumer_channels_.begin(), consumer_channels_.end(), channel));
Tianyu67053492018-10-04 14:00:22 -0700596 // Restore the consumer state bit and make it visible in other threads that
597 // acquire the active_clients_bit_mask_.
Tianyu Jianga99f9112018-12-13 18:23:07 -0800598 uint32_t consumer_state_mask = channel->client_state_mask();
599 uint32_t current_active_clients_bit_mask =
Tianyuf669f6a2018-10-10 15:34:32 -0700600 active_clients_bit_mask_->load(std::memory_order_acquire);
Tianyu Jianga99f9112018-12-13 18:23:07 -0800601 uint32_t updated_active_clients_bit_mask =
Tianyuf669f6a2018-10-10 15:34:32 -0700602 current_active_clients_bit_mask & (~consumer_state_mask);
603 while (!active_clients_bit_mask_->compare_exchange_weak(
604 current_active_clients_bit_mask, updated_active_clients_bit_mask,
605 std::memory_order_acq_rel, std::memory_order_acquire)) {
606 ALOGI(
607 "%s: Failed to remove consumer state mask. Current active clients bit "
Tianyu Jianga99f9112018-12-13 18:23:07 -0800608 "mask is changed to %" PRIx32
609 " when trying to acquire and modify it to %" PRIx32
Tianyuf669f6a2018-10-10 15:34:32 -0700610 ". About to try again.",
611 __FUNCTION__, current_active_clients_bit_mask,
612 updated_active_clients_bit_mask);
613 updated_active_clients_bit_mask =
614 current_active_clients_bit_mask & (~consumer_state_mask);
615 }
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700616
Tianyu Jianga99f9112018-12-13 18:23:07 -0800617 const uint32_t current_buffer_state =
Tianyuf669f6a2018-10-10 15:34:32 -0700618 buffer_state_->load(std::memory_order_acquire);
619 if (BufferHubDefs::IsClientPosted(current_buffer_state,
620 consumer_state_mask) ||
621 BufferHubDefs::IsClientAcquired(current_buffer_state,
622 consumer_state_mask)) {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700623 // The consumer client is being destoryed without releasing. This could
624 // happen in corner cases when the consumer crashes. Here we mark it
625 // orphaned before remove it from producer.
Tianyuf669f6a2018-10-10 15:34:32 -0700626 OnConsumerOrphaned(consumer_state_mask);
627 return;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700628 }
629
Tianyuf669f6a2018-10-10 15:34:32 -0700630 if (BufferHubDefs::IsClientReleased(current_buffer_state,
631 consumer_state_mask) ||
632 BufferHubDefs::AnyClientGained(current_buffer_state)) {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700633 // The consumer is being close while it is suppose to signal a release
634 // fence. Signal the dummy fence here.
Tianyuf669f6a2018-10-10 15:34:32 -0700635 if (fence_state_->load(std::memory_order_acquire) & consumer_state_mask) {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700636 epoll_event event;
637 event.events = EPOLLIN;
Tianyu Jianga99f9112018-12-13 18:23:07 -0800638 event.data.u32 = consumer_state_mask;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700639 if (epoll_ctl(release_fence_fd_.Get(), EPOLL_CTL_MOD,
640 dummy_fence_fd_.Get(), &event) < 0) {
641 ALOGE(
Tianyuf669f6a2018-10-10 15:34:32 -0700642 "%s: Failed to modify the shared release fence to include the "
643 "dummy fence: %s",
644 __FUNCTION__, strerror(errno));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700645 return;
646 }
Tianyuf669f6a2018-10-10 15:34:32 -0700647 ALOGW("%s: signal dummy release fence buffer_id=%d", __FUNCTION__,
648 buffer_id());
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700649 eventfd_write(dummy_fence_fd_.Get(), 1);
650 }
651 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800652}
653
Tianyuf669f6a2018-10-10 15:34:32 -0700654// Returns true if the given parameters match the underlying buffer
655// parameters.
Corey Tabakacd52dd92017-04-07 18:03:57 -0700656bool ProducerChannel::CheckParameters(uint32_t width, uint32_t height,
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700657 uint32_t layer_count, uint32_t format,
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700658 uint64_t usage,
659 size_t user_metadata_size) {
660 return user_metadata_size == user_metadata_size_ &&
661 buffer_.width() == width && buffer_.height() == height &&
662 buffer_.layer_count() == layer_count && buffer_.format() == format &&
663 buffer_.usage() == usage;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800664}
665
666} // namespace dvr
667} // namespace android