Home | History | Annotate | Download | only in fmq
      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      */
    216     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      */
    225     std::atomic<uint32_t>* getEventFlagWord() const { return mEvFlagWord; }
    226 
    227     /**
    228      * Describes a memory region in the FMQ.
    229      */
    230     struct MemRegion {
    231         MemRegion() : MemRegion(nullptr, 0) {}
    232 
    233         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          */
    244         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          */
    250         inline size_t getLength() const { return length; }
    251 
    252         /**
    253          * Gets the length of the MemRegion in bytes.
    254          */
    255         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 {
    275         MemTransaction() : MemTransaction(MemRegion(), MemRegion()) {}
    276 
    277         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          */
    334         inline const MemRegion& getFirstRegion() const { return first; }
    335 
    336         /**
    337          * Returns a const reference to the second MemRegion in the
    338          * MemTransaction object.
    339          */
    340         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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    708 bool MessageQueue<T, flavor>::write(const T* data) {
    709     return write(data, 1);
    710 }
    711 
    712 template <typename T, MQFlavor flavor>
    713 bool MessageQueue<T, flavor>::read(T* data) {
    714     return read(data, 1);
    715 }
    716 
    717 template <typename T, MQFlavor flavor>
    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>
    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>
    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>
    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>
    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>
    956 size_t MessageQueue<T, flavor>::availableToWriteBytes() const {
    957     return mDesc->getSize() - availableToReadBytes();
    958 }
    959 
    960 template <typename T, MQFlavor flavor>
    961 size_t MessageQueue<T, flavor>::availableToWrite() const {
    962     return availableToWriteBytes() / sizeof(T);
    963 }
    964 
    965 template <typename T, MQFlavor flavor>
    966 size_t MessageQueue<T, flavor>::availableToRead() const {
    967     return availableToReadBytes() / sizeof(T);
    968 }
    969 
    970 template <typename T, MQFlavor flavor>
    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")))
   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>
   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>
   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")))
   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")))
   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>
   1139 size_t MessageQueue<T, flavor>::getQuantumSize() const {
   1140     return mDesc->getQuantum();
   1141 }
   1142 
   1143 template <typename T, MQFlavor flavor>
   1144 size_t MessageQueue<T, flavor>::getQuantumCount() const {
   1145     return mDesc->getSize() / mDesc->getQuantum();
   1146 }
   1147 
   1148 template <typename T, MQFlavor flavor>
   1149 bool MessageQueue<T, flavor>::isValid() const {
   1150     return mRing != nullptr && mReadPtr != nullptr && mWritePtr != nullptr;
   1151 }
   1152 
   1153 template <typename T, MQFlavor flavor>
   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>
   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