1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef HIDL_MQ_H
18 #define HIDL_MQ_H
19
20 #include <atomic>
21 #include <cutils/ashmem.h>
22 #include <fmq/EventFlag.h>
23 #include <hidl/MQDescriptor.h>
24 #include <new>
25 #include <sys/mman.h>
26 #include <utils/Log.h>
27 #include <utils/SystemClock.h>
28
29 namespace android {
30 namespace hardware {
31
32 namespace details {
33 void check(bool exp);
34 void logError(const std::string &message);
35 } // namespace details
36
37 template <typename T, MQFlavor flavor>
38 struct MessageQueue {
39 typedef MQDescriptor<T, flavor> Descriptor;
40
41 /**
42 * @param Desc MQDescriptor describing the FMQ.
43 * @param resetPointers bool indicating whether the read/write pointers
44 * should be reset or not.
45 */
46 MessageQueue(const Descriptor& Desc, bool resetPointers = true);
47
48 ~MessageQueue();
49
50 /**
51 * This constructor uses Ashmem shared memory to create an FMQ
52 * that can contain a maximum of 'numElementsInQueue' elements of type T.
53 *
54 * @param numElementsInQueue Capacity of the MessageQueue in terms of T.
55 * @param configureEventFlagWord Boolean that specifies if memory should
56 * also be allocated and mapped for an EventFlag word.
57 */
58 MessageQueue(size_t numElementsInQueue, bool configureEventFlagWord = false);
59
60 /**
61 * @return Number of items of type T that can be written into the FMQ
62 * without a read.
63 */
64 size_t availableToWrite() const;
65
66 /**
67 * @return Number of items of type T that are waiting to be read from the
68 * FMQ.
69 */
70 size_t availableToRead() const;
71
72 /**
73 * Returns the size of type T in bytes.
74 *
75 * @param Size of T.
76 */
77 size_t getQuantumSize() const;
78
79 /**
80 * Returns the size of the FMQ in terms of the size of type T.
81 *
82 * @return Number of items of type T that will fit in the FMQ.
83 */
84 size_t getQuantumCount() const;
85
86 /**
87 * @return Whether the FMQ is configured correctly.
88 */
89 bool isValid() const;
90
91 /**
92 * Non-blocking write to FMQ.
93 *
94 * @param data Pointer to the object of type T to be written into the FMQ.
95 *
96 * @return Whether the write was successful.
97 */
98 bool write(const T* data);
99
100 /**
101 * Non-blocking read from FMQ.
102 *
103 * @param data Pointer to the memory where the object read from the FMQ is
104 * copied to.
105 *
106 * @return Whether the read was successful.
107 */
108 bool read(T* data);
109
110 /**
111 * Write some data into the FMQ without blocking.
112 *
113 * @param data Pointer to the array of items of type T.
114 * @param count Number of items in array.
115 *
116 * @return Whether the write was successful.
117 */
118 bool write(const T* data, size_t count);
119
120 /**
121 * Perform a blocking write of 'count' items into the FMQ using EventFlags.
122 * Does not support partial writes.
123 *
124 * If 'evFlag' is nullptr, it is checked whether there is an EventFlag object
125 * associated with the FMQ and it is used in that case.
126 *
127 * The application code must ensure that 'evFlag' used by the
128 * reader(s)/writer is based upon the same EventFlag word.
129 *
130 * The method will return false without blocking if any of the following
131 * conditions are true:
132 * - If 'evFlag' is nullptr and the FMQ does not own an EventFlag object.
133 * - If the flavor of the FMQ is synchronized and the 'readNotification' bit mask is zero.
134 * - If 'count' is greater than the FMQ size.
135 *
136 * If the flavor of the FMQ is synchronized and there is insufficient space
137 * available to write into it, the EventFlag bit mask 'readNotification' is
138 * is waited upon.
139 *
140 * Upon a successful write, wake is called on 'writeNotification' (if
141 * non-zero).
142 *
143 * @param data Pointer to the array of items of type T.
144 * @param count Number of items in array.
145 * @param readNotification The EventFlag bit mask to wait on if there is not
146 * enough space in FMQ to write 'count' items.
147 * @param writeNotification The EventFlag bit mask to call wake on
148 * a successful write. No wake is called if 'writeNotification' is zero.
149 * @param timeOutNanos Number of nanoseconds after which the blocking
150 * write attempt is aborted.
151 * @param evFlag The EventFlag object to be used for blocking. If nullptr,
152 * it is checked whether the FMQ owns an EventFlag object and that is used
153 * for blocking instead.
154 *
155 * @return Whether the write was successful.
156 */
157 bool writeBlocking(const T* data, size_t count, uint32_t readNotification,
158 uint32_t writeNotification, int64_t timeOutNanos = 0,
159 android::hardware::EventFlag* evFlag = nullptr);
160
161 bool writeBlocking(const T* data, size_t count, int64_t timeOutNanos = 0);
162
163 /**
164 * Read some data from the FMQ without blocking.
165 *
166 * @param data Pointer to the array to which read data is to be written.
167 * @param count Number of items to be read.
168 *
169 * @return Whether the read was successful.
170 */
171 bool read(T* data, size_t count);
172
173 /**
174 * Perform a blocking read operation of 'count' items from the FMQ. Does not
175 * perform a partial read.
176 *
177 * If 'evFlag' is nullptr, it is checked whether there is an EventFlag object
178 * associated with the FMQ and it is used in that case.
179 *
180 * The application code must ensure that 'evFlag' used by the
181 * reader(s)/writer is based upon the same EventFlag word.
182 *
183 * The method will return false without blocking if any of the following
184 * conditions are true:
185 * -If 'evFlag' is nullptr and the FMQ does not own an EventFlag object.
186 * -If the 'writeNotification' bit mask is zero.
187 * -If 'count' is greater than the FMQ size.
188 *
189 * If FMQ does not contain 'count' items, the eventFlag bit mask
190 * 'writeNotification' is waited upon. Upon a successful read from the FMQ,
191 * wake is called on 'readNotification' (if non-zero).
192 *
193 * @param data Pointer to the array to which read data is to be written.
194 * @param count Number of items to be read.
195 * @param readNotification The EventFlag bit mask to call wake on after
196 * a successful read. No wake is called if 'readNotification' is zero.
197 * @param writeNotification The EventFlag bit mask to call a wait on
198 * if there is insufficient data in the FMQ to be read.
199 * @param timeOutNanos Number of nanoseconds after which the blocking
200 * read attempt is aborted.
201 * @param evFlag The EventFlag object to be used for blocking.
202 *
203 * @return Whether the read was successful.
204 */
205 bool readBlocking(T* data, size_t count, uint32_t readNotification,
206 uint32_t writeNotification, int64_t timeOutNanos = 0,
207 android::hardware::EventFlag* evFlag = nullptr);
208
209 bool readBlocking(T* data, size_t count, int64_t timeOutNanos = 0);
210
211 /**
212 * Get a pointer to the MQDescriptor object that describes this FMQ.
213 *
214 * @return Pointer to the MQDescriptor associated with the FMQ.
215 */
getDescMessageQueue216 const Descriptor* getDesc() const { return mDesc.get(); }
217
218 /**
219 * Get a pointer to the EventFlag word if there is one associated with this FMQ.
220 *
221 * @return Pointer to an EventFlag word, will return nullptr if not
222 * configured. This method does not transfer ownership. The EventFlag
223 * word will be unmapped by the MessageQueue destructor.
224 */
getEventFlagWordMessageQueue225 std::atomic<uint32_t>* getEventFlagWord() const { return mEvFlagWord; }
226
227 /**
228 * Describes a memory region in the FMQ.
229 */
230 struct MemRegion {
MemRegionMessageQueue::MemRegion231 MemRegion() : MemRegion(nullptr, 0) {}
232
MemRegionMessageQueue::MemRegion233 MemRegion(T* base, size_t size) : address(base), length(size) {}
234
235 MemRegion& operator=(const MemRegion &other) {
236 address = other.address;
237 length = other.length;
238 return *this;
239 }
240
241 /**
242 * Gets a pointer to the base address of the MemRegion.
243 */
getAddressMessageQueue::MemRegion244 inline T* getAddress() const { return address; }
245
246 /**
247 * Gets the length of the MemRegion. This would equal to the number
248 * of items of type T that can be read from/written into the MemRegion.
249 */
getLengthMessageQueue::MemRegion250 inline size_t getLength() const { return length; }
251
252 /**
253 * Gets the length of the MemRegion in bytes.
254 */
getLengthInBytesMessageQueue::MemRegion255 inline size_t getLengthInBytes() const { return length * sizeof(T); }
256
257 private:
258 /* Base address */
259 T* address;
260
261 /*
262 * Number of items of type T that can be written to/read from the base
263 * address.
264 */
265 size_t length;
266 };
267
268 /**
269 * Describes the memory regions to be used for a read or write.
270 * The struct contains two MemRegion objects since the FMQ is a ring
271 * buffer and a read or write operation can wrap around. A single message
272 * of type T will never be broken between the two MemRegions.
273 */
274 struct MemTransaction {
MemTransactionMessageQueue::MemTransaction275 MemTransaction() : MemTransaction(MemRegion(), MemRegion()) {}
276
MemTransactionMessageQueue::MemTransaction277 MemTransaction(const MemRegion& regionFirst, const MemRegion& regionSecond) :
278 first(regionFirst), second(regionSecond) {}
279
280 MemTransaction& operator=(const MemTransaction &other) {
281 first = other.first;
282 second = other.second;
283 return *this;
284 }
285
286 /**
287 * Helper method to calculate the address for a particular index for
288 * the MemTransaction object.
289 *
290 * @param idx Index of the slot to be read/written. If the
291 * MemTransaction object is representing the memory region to read/write
292 * N items of type T, the valid range of idx is between 0 and N-1.
293 *
294 * @return Pointer to the slot idx. Will be nullptr for an invalid idx.
295 */
296 T* getSlot(size_t idx);
297
298 /**
299 * Helper method to write 'nMessages' items of type T into the memory
300 * regions described by the object starting from 'startIdx'. This method
301 * uses memcpy() and is not to meant to be used for a zero copy operation.
302 * Partial writes are not supported.
303 *
304 * @param data Pointer to the source buffer.
305 * @param nMessages Number of items of type T.
306 * @param startIdx The slot number to begin the write from. If the
307 * MemTransaction object is representing the memory region to read/write
308 * N items of type T, the valid range of startIdx is between 0 and N-1;
309 *
310 * @return Whether the write operation of size 'nMessages' succeeded.
311 */
312 bool copyTo(const T* data, size_t startIdx, size_t nMessages = 1);
313
314 /*
315 * Helper method to read 'nMessages' items of type T from the memory
316 * regions described by the object starting from 'startIdx'. This method uses
317 * memcpy() and is not meant to be used for a zero copy operation. Partial reads
318 * are not supported.
319 *
320 * @param data Pointer to the destination buffer.
321 * @param nMessages Number of items of type T.
322 * @param startIdx The slot number to begin the read from. If the
323 * MemTransaction object is representing the memory region to read/write
324 * N items of type T, the valid range of startIdx is between 0 and N-1.
325 *
326 * @return Whether the read operation of size 'nMessages' succeeded.
327 */
328 bool copyFrom(T* data, size_t startIdx, size_t nMessages = 1);
329
330 /**
331 * Returns a const reference to the first MemRegion in the
332 * MemTransaction object.
333 */
getFirstRegionMessageQueue::MemTransaction334 inline const MemRegion& getFirstRegion() const { return first; }
335
336 /**
337 * Returns a const reference to the second MemRegion in the
338 * MemTransaction object.
339 */
getSecondRegionMessageQueue::MemTransaction340 inline const MemRegion& getSecondRegion() const { return second; }
341
342 private:
343 /*
344 * Given a start index and the number of messages to be
345 * read/written, this helper method calculates the
346 * number of messages that should should be written to both the first
347 * and second MemRegions and the base addresses to be used for
348 * the read/write operation.
349 *
350 * Returns false if the 'startIdx' and 'nMessages' is
351 * invalid for the MemTransaction object.
352 */
353 bool inline getMemRegionInfo(size_t idx,
354 size_t nMessages,
355 size_t& firstCount,
356 size_t& secondCount,
357 T** firstBaseAddress,
358 T** secondBaseAddress);
359 MemRegion first;
360 MemRegion second;
361 };
362
363 /**
364 * Get a MemTransaction object to write 'nMessages' items of type T.
365 * Once the write is performed using the information from MemTransaction,
366 * the write operation is to be committed using a call to commitWrite().
367 *
368 * @param nMessages Number of messages of type T.
369 * @param Pointer to MemTransaction struct that describes memory to write 'nMessages'
370 * items of type T. If a write of size 'nMessages' is not possible, the base
371 * addresses in the MemTransaction object would be set to nullptr.
372 *
373 * @return Whether it is possible to write 'nMessages' items of type T
374 * into the FMQ.
375 */
376 bool beginWrite(size_t nMessages, MemTransaction* memTx) const;
377
378 /**
379 * Commit a write of size 'nMessages'. To be only used after a call to beginWrite().
380 *
381 * @param nMessages number of messages of type T to be written.
382 *
383 * @return Whether the write operation of size 'nMessages' succeeded.
384 */
385 bool commitWrite(size_t nMessages);
386
387 /**
388 * Get a MemTransaction object to read 'nMessages' items of type T.
389 * Once the read is performed using the information from MemTransaction,
390 * the read operation is to be committed using a call to commitRead().
391 *
392 * @param nMessages Number of messages of type T.
393 * @param pointer to MemTransaction struct that describes memory to read 'nMessages'
394 * items of type T. If a read of size 'nMessages' is not possible, the base
395 * pointers in the MemTransaction object returned will be set to nullptr.
396 *
397 * @return bool Whether it is possible to read 'nMessages' items of type T
398 * from the FMQ.
399 */
400 bool beginRead(size_t nMessages, MemTransaction* memTx) const;
401
402 /**
403 * Commit a read of size 'nMessages'. To be only used after a call to beginRead().
404 * For the unsynchronized flavor of FMQ, this method will return a failure
405 * if a write overflow happened after beginRead() was invoked.
406 *
407 * @param nMessages number of messages of type T to be read.
408 *
409 * @return bool Whether the read operation of size 'nMessages' succeeded.
410 */
411 bool commitRead(size_t nMessages);
412
413 private:
414
415 size_t availableToWriteBytes() const;
416 size_t availableToReadBytes() const;
417
418 MessageQueue(const MessageQueue& other) = delete;
419 MessageQueue& operator=(const MessageQueue& other) = delete;
420 MessageQueue();
421
422 void* mapGrantorDescr(uint32_t grantorIdx);
423 void unmapGrantorDescr(void* address, uint32_t grantorIdx);
424 void initMemory(bool resetPointers);
425
426 enum DefaultEventNotification : uint32_t {
427 /*
428 * These are only used internally by the blockingRead()/blockingWrite()
429 * methods and hence once other bit combinations are not required.
430 */
431 FMQ_NOT_FULL = 0x01,
432 FMQ_NOT_EMPTY = 0x02
433 };
434
435 std::unique_ptr<Descriptor> mDesc;
436 uint8_t* mRing = nullptr;
437 /*
438 * TODO(b/31550092): Change to 32 bit read and write pointer counters.
439 */
440 std::atomic<uint64_t>* mReadPtr = nullptr;
441 std::atomic<uint64_t>* mWritePtr = nullptr;
442
443 std::atomic<uint32_t>* mEvFlagWord = nullptr;
444
445 /*
446 * This EventFlag object will be owned by the FMQ and will have the same
447 * lifetime.
448 */
449 android::hardware::EventFlag* mEventFlag = nullptr;
450 };
451
452 template <typename T, MQFlavor flavor>
getSlot(size_t idx)453 T* MessageQueue<T, flavor>::MemTransaction::getSlot(size_t idx) {
454 size_t firstRegionLength = first.getLength();
455 size_t secondRegionLength = second.getLength();
456
457 if (idx > firstRegionLength + secondRegionLength) {
458 return nullptr;
459 }
460
461 if (idx < firstRegionLength) {
462 return first.getAddress() + idx;
463 }
464
465 return second.getAddress() + idx - firstRegionLength;
466 }
467
468 template <typename T, MQFlavor flavor>
getMemRegionInfo(size_t startIdx,size_t nMessages,size_t & firstCount,size_t & secondCount,T ** firstBaseAddress,T ** secondBaseAddress)469 bool MessageQueue<T, flavor>::MemTransaction::getMemRegionInfo(size_t startIdx,
470 size_t nMessages,
471 size_t& firstCount,
472 size_t& secondCount,
473 T** firstBaseAddress,
474 T** secondBaseAddress) {
475 size_t firstRegionLength = first.getLength();
476 size_t secondRegionLength = second.getLength();
477
478 if (startIdx + nMessages > firstRegionLength + secondRegionLength) {
479 /*
480 * Return false if 'nMessages' starting at 'startIdx' cannot be
481 * accomodated by the MemTransaction object.
482 */
483 return false;
484 }
485
486 /* Number of messages to be read/written to the first MemRegion. */
487 firstCount = startIdx < firstRegionLength ?
488 std::min(nMessages, firstRegionLength - startIdx) : 0;
489
490 /* Number of messages to be read/written to the second MemRegion. */
491 secondCount = nMessages - firstCount;
492
493 if (firstCount != 0) {
494 *firstBaseAddress = first.getAddress() + startIdx;
495 }
496
497 if (secondCount != 0) {
498 size_t secondStartIdx = startIdx > firstRegionLength ? startIdx - firstRegionLength : 0;
499 *secondBaseAddress = second.getAddress() + secondStartIdx;
500 }
501
502 return true;
503 }
504
505 template <typename T, MQFlavor flavor>
copyFrom(T * data,size_t startIdx,size_t nMessages)506 bool MessageQueue<T, flavor>::MemTransaction::copyFrom(T* data, size_t startIdx, size_t nMessages) {
507 if (data == nullptr) {
508 return false;
509 }
510
511 size_t firstReadCount = 0, secondReadCount = 0;
512 T* firstBaseAddress = nullptr, * secondBaseAddress = nullptr;
513
514 if (getMemRegionInfo(startIdx,
515 nMessages,
516 firstReadCount,
517 secondReadCount,
518 &firstBaseAddress,
519 &secondBaseAddress) == false) {
520 /*
521 * Returns false if 'startIdx' and 'nMessages' are invalid for this
522 * MemTransaction object.
523 */
524 return false;
525 }
526
527 if (firstReadCount != 0) {
528 memcpy(data, firstBaseAddress, firstReadCount * sizeof(T));
529 }
530
531 if (secondReadCount != 0) {
532 memcpy(data + firstReadCount,
533 secondBaseAddress,
534 secondReadCount * sizeof(T));
535 }
536
537 return true;
538 }
539
540 template <typename T, MQFlavor flavor>
copyTo(const T * data,size_t startIdx,size_t nMessages)541 bool MessageQueue<T, flavor>::MemTransaction::copyTo(const T* data,
542 size_t startIdx,
543 size_t nMessages) {
544 if (data == nullptr) {
545 return false;
546 }
547
548 size_t firstWriteCount = 0, secondWriteCount = 0;
549 T * firstBaseAddress = nullptr, * secondBaseAddress = nullptr;
550
551 if (getMemRegionInfo(startIdx,
552 nMessages,
553 firstWriteCount,
554 secondWriteCount,
555 &firstBaseAddress,
556 &secondBaseAddress) == false) {
557 /*
558 * Returns false if 'startIdx' and 'nMessages' are invalid for this
559 * MemTransaction object.
560 */
561 return false;
562 }
563
564 if (firstWriteCount != 0) {
565 memcpy(firstBaseAddress, data, firstWriteCount * sizeof(T));
566 }
567
568 if (secondWriteCount != 0) {
569 memcpy(secondBaseAddress,
570 data + firstWriteCount,
571 secondWriteCount * sizeof(T));
572 }
573
574 return true;
575 }
576
577 template <typename T, MQFlavor flavor>
initMemory(bool resetPointers)578 void MessageQueue<T, flavor>::initMemory(bool resetPointers) {
579 /*
580 * Verify that the the Descriptor contains the minimum number of grantors
581 * the native_handle is valid and T matches quantum size.
582 */
583 if ((mDesc == nullptr) || !mDesc->isHandleValid() ||
584 (mDesc->countGrantors() < Descriptor::kMinGrantorCount) ||
585 (mDesc->getQuantum() != sizeof(T))) {
586 return;
587 }
588
589 if (flavor == kSynchronizedReadWrite) {
590 mReadPtr = reinterpret_cast<std::atomic<uint64_t>*>(
591 mapGrantorDescr(Descriptor::READPTRPOS));
592 } else {
593 /*
594 * The unsynchronized write flavor of the FMQ may have multiple readers
595 * and each reader would have their own read pointer counter.
596 */
597 mReadPtr = new (std::nothrow) std::atomic<uint64_t>;
598 }
599
600 details::check(mReadPtr != nullptr);
601
602 mWritePtr =
603 reinterpret_cast<std::atomic<uint64_t>*>(mapGrantorDescr(Descriptor::WRITEPTRPOS));
604 details::check(mWritePtr != nullptr);
605
606 if (resetPointers) {
607 mReadPtr->store(0, std::memory_order_release);
608 mWritePtr->store(0, std::memory_order_release);
609 } else if (flavor != kSynchronizedReadWrite) {
610 // Always reset the read pointer.
611 mReadPtr->store(0, std::memory_order_release);
612 }
613
614 mRing = reinterpret_cast<uint8_t*>(mapGrantorDescr(Descriptor::DATAPTRPOS));
615 details::check(mRing != nullptr);
616
617 mEvFlagWord = static_cast<std::atomic<uint32_t>*>(mapGrantorDescr(Descriptor::EVFLAGWORDPOS));
618 if (mEvFlagWord != nullptr) {
619 android::hardware::EventFlag::createEventFlag(mEvFlagWord, &mEventFlag);
620 }
621 }
622
623 template <typename T, MQFlavor flavor>
MessageQueue(const Descriptor & Desc,bool resetPointers)624 MessageQueue<T, flavor>::MessageQueue(const Descriptor& Desc, bool resetPointers) {
625 mDesc = std::unique_ptr<Descriptor>(new (std::nothrow) Descriptor(Desc));
626 if (mDesc == nullptr) {
627 return;
628 }
629
630 initMemory(resetPointers);
631 }
632
633 template <typename T, MQFlavor flavor>
MessageQueue(size_t numElementsInQueue,bool configureEventFlagWord)634 MessageQueue<T, flavor>::MessageQueue(size_t numElementsInQueue, bool configureEventFlagWord) {
635
636 // Check if the buffer size would not overflow size_t
637 if (numElementsInQueue > SIZE_MAX / sizeof(T)) {
638 return;
639 }
640 /*
641 * The FMQ needs to allocate memory for the ringbuffer as well as for the
642 * read and write pointer counters. If an EventFlag word is to be configured,
643 * we also need to allocate memory for the same/
644 */
645 size_t kQueueSizeBytes = numElementsInQueue * sizeof(T);
646 size_t kMetaDataSize = 2 * sizeof(android::hardware::RingBufferPosition);
647
648 if (configureEventFlagWord) {
649 kMetaDataSize+= sizeof(std::atomic<uint32_t>);
650 }
651
652 /*
653 * Ashmem memory region size needs to be specified in page-aligned bytes.
654 * kQueueSizeBytes needs to be aligned to word boundary so that all offsets
655 * in the grantorDescriptor will be word aligned.
656 */
657 size_t kAshmemSizePageAligned =
658 (Descriptor::alignToWordBoundary(kQueueSizeBytes) + kMetaDataSize + PAGE_SIZE - 1) &
659 ~(PAGE_SIZE - 1);
660
661 /*
662 * Create an ashmem region to map the memory for the ringbuffer,
663 * read counter and write counter.
664 */
665 int ashmemFd = ashmem_create_region("MessageQueue", kAshmemSizePageAligned);
666 ashmem_set_prot_region(ashmemFd, PROT_READ | PROT_WRITE);
667
668 /*
669 * The native handle will contain the fds to be mapped.
670 */
671 native_handle_t* mqHandle =
672 native_handle_create(1 /* numFds */, 0 /* numInts */);
673 if (mqHandle == nullptr) {
674 return;
675 }
676
677 mqHandle->data[0] = ashmemFd;
678 mDesc = std::unique_ptr<Descriptor>(new (std::nothrow) Descriptor(kQueueSizeBytes,
679 mqHandle,
680 sizeof(T),
681 configureEventFlagWord));
682 if (mDesc == nullptr) {
683 return;
684 }
685 initMemory(true);
686 }
687
688 template <typename T, MQFlavor flavor>
~MessageQueue()689 MessageQueue<T, flavor>::~MessageQueue() {
690 if (flavor == kUnsynchronizedWrite) {
691 delete mReadPtr;
692 } else {
693 unmapGrantorDescr(mReadPtr, Descriptor::READPTRPOS);
694 }
695 if (mWritePtr != nullptr) {
696 unmapGrantorDescr(mWritePtr, Descriptor::WRITEPTRPOS);
697 }
698 if (mRing != nullptr) {
699 unmapGrantorDescr(mRing, Descriptor::DATAPTRPOS);
700 }
701 if (mEvFlagWord != nullptr) {
702 unmapGrantorDescr(mEvFlagWord, Descriptor::EVFLAGWORDPOS);
703 android::hardware::EventFlag::deleteEventFlag(&mEventFlag);
704 }
705 }
706
707 template <typename T, MQFlavor flavor>
write(const T * data)708 bool MessageQueue<T, flavor>::write(const T* data) {
709 return write(data, 1);
710 }
711
712 template <typename T, MQFlavor flavor>
read(T * data)713 bool MessageQueue<T, flavor>::read(T* data) {
714 return read(data, 1);
715 }
716
717 template <typename T, MQFlavor flavor>
write(const T * data,size_t nMessages)718 bool MessageQueue<T, flavor>::write(const T* data, size_t nMessages) {
719 MemTransaction tx;
720 return beginWrite(nMessages, &tx) &&
721 tx.copyTo(data, 0 /* startIdx */, nMessages) &&
722 commitWrite(nMessages);
723 }
724
725 template <typename T, MQFlavor flavor>
writeBlocking(const T * data,size_t count,uint32_t readNotification,uint32_t writeNotification,int64_t timeOutNanos,android::hardware::EventFlag * evFlag)726 bool MessageQueue<T, flavor>::writeBlocking(const T* data,
727 size_t count,
728 uint32_t readNotification,
729 uint32_t writeNotification,
730 int64_t timeOutNanos,
731 android::hardware::EventFlag* evFlag) {
732 /*
733 * If evFlag is null and the FMQ does not have its own EventFlag object
734 * return false;
735 * If the flavor is kSynchronizedReadWrite and the readNotification
736 * bit mask is zero return false;
737 * If the count is greater than queue size, return false
738 * to prevent blocking until timeOut.
739 */
740 if (evFlag == nullptr) {
741 evFlag = mEventFlag;
742 if (evFlag == nullptr) {
743 return false;
744 }
745 }
746
747 if ((readNotification == 0 && flavor == kSynchronizedReadWrite) ||
748 (count > getQuantumCount())) {
749 return false;
750 }
751
752 /*
753 * There is no need to wait for a readNotification if the flavor
754 * of the queue is kUnsynchronizedWrite or sufficient space to write
755 * is already present in the FMQ. The latter would be the case when
756 * read operations read more number of messages than
757 * write operations write. In other words, a single large read may clear the FMQ
758 * after multiple small writes. This would fail to clear a pending
759 * readNotification bit since EventFlag bits can only be cleared
760 * by a wait() call, however the bit would be correctly cleared by the next
761 * blockingWrite() call.
762 */
763
764 bool result = write(data, count);
765 if (result) {
766 if (writeNotification) {
767 evFlag->wake(writeNotification);
768 }
769 return result;
770 }
771
772 bool shouldTimeOut = timeOutNanos != 0;
773 int64_t prevTimeNanos = shouldTimeOut ? android::elapsedRealtimeNano() : 0;
774
775 while (true) {
776 /* It is not required to adjust 'timeOutNanos' if 'shouldTimeOut' is false */
777 if (shouldTimeOut) {
778 /*
779 * The current time and 'prevTimeNanos' are both CLOCK_BOOTTIME clock values(converted
780 * to Nanoseconds)
781 */
782 int64_t currentTimeNs = android::elapsedRealtimeNano();
783 /*
784 * Decrement 'timeOutNanos' to account for the time taken to complete the last
785 * iteration of the while loop.
786 */
787 timeOutNanos -= currentTimeNs - prevTimeNanos;
788 prevTimeNanos = currentTimeNs;
789
790 if (timeOutNanos <= 0) {
791 /*
792 * Attempt write in case a context switch happened outside of
793 * evFlag->wait().
794 */
795 result = write(data, count);
796 break;
797 }
798 }
799
800 /*
801 * wait() will return immediately if there was a pending read
802 * notification.
803 */
804 uint32_t efState = 0;
805 status_t status = evFlag->wait(readNotification,
806 &efState,
807 timeOutNanos,
808 true /* retry on spurious wake */);
809
810 if (status != android::TIMED_OUT && status != android::NO_ERROR) {
811 details::logError("Unexpected error code from EventFlag Wait status " + std::to_string(status));
812 break;
813 }
814
815 if (status == android::TIMED_OUT) {
816 break;
817 }
818
819 /*
820 * If there is still insufficient space to write to the FMQ,
821 * keep waiting for another readNotification.
822 */
823 if ((efState & readNotification) && write(data, count)) {
824 result = true;
825 break;
826 }
827 }
828
829 if (result && writeNotification != 0) {
830 evFlag->wake(writeNotification);
831 }
832
833 return result;
834 }
835
836 template <typename T, MQFlavor flavor>
writeBlocking(const T * data,size_t count,int64_t timeOutNanos)837 bool MessageQueue<T, flavor>::writeBlocking(const T* data,
838 size_t count,
839 int64_t timeOutNanos) {
840 return writeBlocking(data, count, FMQ_NOT_FULL, FMQ_NOT_EMPTY, timeOutNanos);
841 }
842
843 template <typename T, MQFlavor flavor>
readBlocking(T * data,size_t count,uint32_t readNotification,uint32_t writeNotification,int64_t timeOutNanos,android::hardware::EventFlag * evFlag)844 bool MessageQueue<T, flavor>::readBlocking(T* data,
845 size_t count,
846 uint32_t readNotification,
847 uint32_t writeNotification,
848 int64_t timeOutNanos,
849 android::hardware::EventFlag* evFlag) {
850 /*
851 * If evFlag is null and the FMQ does not own its own EventFlag object
852 * return false;
853 * If the writeNotification bit mask is zero return false;
854 * If the count is greater than queue size, return false to prevent
855 * blocking until timeOut.
856 */
857 if (evFlag == nullptr) {
858 evFlag = mEventFlag;
859 if (evFlag == nullptr) {
860 return false;
861 }
862 }
863
864 if (writeNotification == 0 || count > getQuantumCount()) {
865 return false;
866 }
867
868 /*
869 * There is no need to wait for a write notification if sufficient
870 * data to read is already present in the FMQ. This would be the
871 * case when read operations read lesser number of messages than
872 * a write operation and multiple reads would be required to clear the queue
873 * after a single write operation. This check would fail to clear a pending
874 * writeNotification bit since EventFlag bits can only be cleared
875 * by a wait() call, however the bit would be correctly cleared by the next
876 * readBlocking() call.
877 */
878
879 bool result = read(data, count);
880 if (result) {
881 if (readNotification) {
882 evFlag->wake(readNotification);
883 }
884 return result;
885 }
886
887 bool shouldTimeOut = timeOutNanos != 0;
888 int64_t prevTimeNanos = shouldTimeOut ? android::elapsedRealtimeNano() : 0;
889
890 while (true) {
891 /* It is not required to adjust 'timeOutNanos' if 'shouldTimeOut' is false */
892 if (shouldTimeOut) {
893 /*
894 * The current time and 'prevTimeNanos' are both CLOCK_BOOTTIME clock values(converted
895 * to Nanoseconds)
896 */
897 int64_t currentTimeNs = android::elapsedRealtimeNano();
898 /*
899 * Decrement 'timeOutNanos' to account for the time taken to complete the last
900 * iteration of the while loop.
901 */
902 timeOutNanos -= currentTimeNs - prevTimeNanos;
903 prevTimeNanos = currentTimeNs;
904
905 if (timeOutNanos <= 0) {
906 /*
907 * Attempt read in case a context switch happened outside of
908 * evFlag->wait().
909 */
910 result = read(data, count);
911 break;
912 }
913 }
914
915 /*
916 * wait() will return immediately if there was a pending write
917 * notification.
918 */
919 uint32_t efState = 0;
920 status_t status = evFlag->wait(writeNotification,
921 &efState,
922 timeOutNanos,
923 true /* retry on spurious wake */);
924
925 if (status != android::TIMED_OUT && status != android::NO_ERROR) {
926 details::logError("Unexpected error code from EventFlag Wait status " + std::to_string(status));
927 break;
928 }
929
930 if (status == android::TIMED_OUT) {
931 break;
932 }
933
934 /*
935 * If the data in FMQ is still insufficient, go back to waiting
936 * for another write notification.
937 */
938 if ((efState & writeNotification) && read(data, count)) {
939 result = true;
940 break;
941 }
942 }
943
944 if (result && readNotification != 0) {
945 evFlag->wake(readNotification);
946 }
947 return result;
948 }
949
950 template <typename T, MQFlavor flavor>
readBlocking(T * data,size_t count,int64_t timeOutNanos)951 bool MessageQueue<T, flavor>::readBlocking(T* data, size_t count, int64_t timeOutNanos) {
952 return readBlocking(data, count, FMQ_NOT_FULL, FMQ_NOT_EMPTY, timeOutNanos);
953 }
954
955 template <typename T, MQFlavor flavor>
availableToWriteBytes()956 size_t MessageQueue<T, flavor>::availableToWriteBytes() const {
957 return mDesc->getSize() - availableToReadBytes();
958 }
959
960 template <typename T, MQFlavor flavor>
availableToWrite()961 size_t MessageQueue<T, flavor>::availableToWrite() const {
962 return availableToWriteBytes() / sizeof(T);
963 }
964
965 template <typename T, MQFlavor flavor>
availableToRead()966 size_t MessageQueue<T, flavor>::availableToRead() const {
967 return availableToReadBytes() / sizeof(T);
968 }
969
970 template <typename T, MQFlavor flavor>
beginWrite(size_t nMessages,MemTransaction * result)971 bool MessageQueue<T, flavor>::beginWrite(size_t nMessages, MemTransaction* result) const {
972 /*
973 * If nMessages is greater than size of FMQ or in case of the synchronized
974 * FMQ flavor, if there is not enough space to write nMessages, then return
975 * result with null addresses.
976 */
977 if ((flavor == kSynchronizedReadWrite && (availableToWrite() < nMessages)) ||
978 nMessages > getQuantumCount()) {
979 *result = MemTransaction();
980 return false;
981 }
982
983 auto writePtr = mWritePtr->load(std::memory_order_relaxed);
984 size_t writeOffset = writePtr % mDesc->getSize();
985
986 /*
987 * From writeOffset, the number of messages that can be written
988 * contiguously without wrapping around the ring buffer are calculated.
989 */
990 size_t contiguousMessages = (mDesc->getSize() - writeOffset) / sizeof(T);
991
992 if (contiguousMessages < nMessages) {
993 /*
994 * Wrap around is required. Both result.first and result.second are
995 * populated.
996 */
997 *result = MemTransaction(MemRegion(reinterpret_cast<T*>(mRing + writeOffset),
998 contiguousMessages),
999 MemRegion(reinterpret_cast<T*>(mRing),
1000 nMessages - contiguousMessages));
1001 } else {
1002 /*
1003 * A wrap around is not required to write nMessages. Only result.first
1004 * is populated.
1005 */
1006 *result = MemTransaction(MemRegion(reinterpret_cast<T*>(mRing + writeOffset), nMessages),
1007 MemRegion());
1008 }
1009
1010 return true;
1011 }
1012
1013 template <typename T, MQFlavor flavor>
1014 /*
1015 * Disable integer sanitization since integer overflow here is allowed
1016 * and legal.
1017 */
1018 __attribute__((no_sanitize("integer")))
commitWrite(size_t nMessages)1019 bool MessageQueue<T, flavor>::commitWrite(size_t nMessages) {
1020 size_t nBytesWritten = nMessages * sizeof(T);
1021 auto writePtr = mWritePtr->load(std::memory_order_relaxed);
1022 writePtr += nBytesWritten;
1023 mWritePtr->store(writePtr, std::memory_order_release);
1024 /*
1025 * This method cannot fail now since we are only incrementing the writePtr
1026 * counter.
1027 */
1028 return true;
1029 }
1030
1031 template <typename T, MQFlavor flavor>
availableToReadBytes()1032 size_t MessageQueue<T, flavor>::availableToReadBytes() const {
1033 /*
1034 * This method is invoked by implementations of both read() and write() and
1035 * hence requries a memory_order_acquired load for both mReadPtr and
1036 * mWritePtr.
1037 */
1038 return mWritePtr->load(std::memory_order_acquire) -
1039 mReadPtr->load(std::memory_order_acquire);
1040 }
1041
1042 template <typename T, MQFlavor flavor>
read(T * data,size_t nMessages)1043 bool MessageQueue<T, flavor>::read(T* data, size_t nMessages) {
1044 MemTransaction tx;
1045 return beginRead(nMessages, &tx) &&
1046 tx.copyFrom(data, 0 /* startIdx */, nMessages) &&
1047 commitRead(nMessages);
1048 }
1049
1050 template <typename T, MQFlavor flavor>
1051 /*
1052 * Disable integer sanitization since integer overflow here is allowed
1053 * and legal.
1054 */
1055 __attribute__((no_sanitize("integer")))
beginRead(size_t nMessages,MemTransaction * result)1056 bool MessageQueue<T, flavor>::beginRead(size_t nMessages, MemTransaction* result) const {
1057 *result = MemTransaction();
1058 /*
1059 * If it is detected that the data in the queue was overwritten
1060 * due to the reader process being too slow, the read pointer counter
1061 * is set to the same as the write pointer counter to indicate error
1062 * and the read returns false;
1063 * Need acquire/release memory ordering for mWritePtr.
1064 */
1065 auto writePtr = mWritePtr->load(std::memory_order_acquire);
1066 /*
1067 * A relaxed load is sufficient for mReadPtr since there will be no
1068 * stores to mReadPtr from a different thread.
1069 */
1070 auto readPtr = mReadPtr->load(std::memory_order_relaxed);
1071
1072 if (writePtr - readPtr > mDesc->getSize()) {
1073 mReadPtr->store(writePtr, std::memory_order_release);
1074 return false;
1075 }
1076
1077 size_t nBytesDesired = nMessages * sizeof(T);
1078 /*
1079 * Return if insufficient data to read in FMQ.
1080 */
1081 if (writePtr - readPtr < nBytesDesired) {
1082 return false;
1083 }
1084
1085 size_t readOffset = readPtr % mDesc->getSize();
1086 /*
1087 * From readOffset, the number of messages that can be read contiguously
1088 * without wrapping around the ring buffer are calculated.
1089 */
1090 size_t contiguousMessages = (mDesc->getSize() - readOffset) / sizeof(T);
1091
1092 if (contiguousMessages < nMessages) {
1093 /*
1094 * A wrap around is required. Both result.first and result.second
1095 * are populated.
1096 */
1097 *result = MemTransaction(MemRegion(reinterpret_cast<T*>(mRing + readOffset),
1098 contiguousMessages),
1099 MemRegion(reinterpret_cast<T*>(mRing),
1100 nMessages - contiguousMessages));
1101 } else {
1102 /*
1103 * A wrap around is not required. Only result.first need to be
1104 * populated.
1105 */
1106 *result = MemTransaction(MemRegion(reinterpret_cast<T*>(mRing + readOffset), nMessages),
1107 MemRegion());
1108 }
1109
1110 return true;
1111 }
1112
1113 template <typename T, MQFlavor flavor>
1114 /*
1115 * Disable integer sanitization since integer overflow here is allowed
1116 * and legal.
1117 */
1118 __attribute__((no_sanitize("integer")))
commitRead(size_t nMessages)1119 bool MessageQueue<T, flavor>::commitRead(size_t nMessages) {
1120 // TODO: Use a local copy of readPtr to avoid relazed mReadPtr loads.
1121 auto readPtr = mReadPtr->load(std::memory_order_relaxed);
1122 auto writePtr = mWritePtr->load(std::memory_order_acquire);
1123 /*
1124 * If the flavor is unsynchronized, it is possible that a write overflow may
1125 * have occured between beginRead() and commitRead().
1126 */
1127 if (writePtr - readPtr > mDesc->getSize()) {
1128 mReadPtr->store(writePtr, std::memory_order_release);
1129 return false;
1130 }
1131
1132 size_t nBytesRead = nMessages * sizeof(T);
1133 readPtr += nBytesRead;
1134 mReadPtr->store(readPtr, std::memory_order_release);
1135 return true;
1136 }
1137
1138 template <typename T, MQFlavor flavor>
getQuantumSize()1139 size_t MessageQueue<T, flavor>::getQuantumSize() const {
1140 return mDesc->getQuantum();
1141 }
1142
1143 template <typename T, MQFlavor flavor>
getQuantumCount()1144 size_t MessageQueue<T, flavor>::getQuantumCount() const {
1145 return mDesc->getSize() / mDesc->getQuantum();
1146 }
1147
1148 template <typename T, MQFlavor flavor>
isValid()1149 bool MessageQueue<T, flavor>::isValid() const {
1150 return mRing != nullptr && mReadPtr != nullptr && mWritePtr != nullptr;
1151 }
1152
1153 template <typename T, MQFlavor flavor>
mapGrantorDescr(uint32_t grantorIdx)1154 void* MessageQueue<T, flavor>::mapGrantorDescr(uint32_t grantorIdx) {
1155 const native_handle_t* handle = mDesc->handle();
1156 auto grantors = mDesc->grantors();
1157 if ((handle == nullptr) || (grantorIdx >= grantors.size())) {
1158 return nullptr;
1159 }
1160
1161 int fdIndex = grantors[grantorIdx].fdIndex;
1162 /*
1163 * Offset for mmap must be a multiple of PAGE_SIZE.
1164 */
1165 int mapOffset = (grantors[grantorIdx].offset / PAGE_SIZE) * PAGE_SIZE;
1166 int mapLength =
1167 grantors[grantorIdx].offset - mapOffset + grantors[grantorIdx].extent;
1168
1169 void* address = mmap(0, mapLength, PROT_READ | PROT_WRITE, MAP_SHARED,
1170 handle->data[fdIndex], mapOffset);
1171 return (address == MAP_FAILED)
1172 ? nullptr
1173 : reinterpret_cast<uint8_t*>(address) +
1174 (grantors[grantorIdx].offset - mapOffset);
1175 }
1176
1177 template <typename T, MQFlavor flavor>
unmapGrantorDescr(void * address,uint32_t grantorIdx)1178 void MessageQueue<T, flavor>::unmapGrantorDescr(void* address,
1179 uint32_t grantorIdx) {
1180 auto grantors = mDesc->grantors();
1181 if ((address == nullptr) || (grantorIdx >= grantors.size())) {
1182 return;
1183 }
1184
1185 int mapOffset = (grantors[grantorIdx].offset / PAGE_SIZE) * PAGE_SIZE;
1186 int mapLength =
1187 grantors[grantorIdx].offset - mapOffset + grantors[grantorIdx].extent;
1188 void* baseAddress = reinterpret_cast<uint8_t*>(address) -
1189 (grantors[grantorIdx].offset - mapOffset);
1190 if (baseAddress) munmap(baseAddress, mapLength);
1191 }
1192
1193 } // namespace hardware
1194 } // namespace android
1195 #endif // HIDL_MQ_H
1196