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