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
29namespace android {
30namespace hardware {
31
32namespace details {
33void check(bool exp);
34void logError(const std::string &message);
35}  // namespace details
36
37template <typename T, MQFlavor flavor>
38struct 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
413private:
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
452template <typename T, MQFlavor flavor>
453T* 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
468template <typename T, MQFlavor flavor>
469bool 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
505template <typename T, MQFlavor flavor>
506bool 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
540template <typename T, MQFlavor flavor>
541bool 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
577template <typename T, MQFlavor flavor>
578void 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
623template <typename T, MQFlavor flavor>
624MessageQueue<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
633template <typename T, MQFlavor flavor>
634MessageQueue<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
688template <typename T, MQFlavor flavor>
689MessageQueue<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
707template <typename T, MQFlavor flavor>
708bool MessageQueue<T, flavor>::write(const T* data) {
709    return write(data, 1);
710}
711
712template <typename T, MQFlavor flavor>
713bool MessageQueue<T, flavor>::read(T* data) {
714    return read(data, 1);
715}
716
717template <typename T, MQFlavor flavor>
718bool 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
725template <typename T, MQFlavor flavor>
726bool 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
836template <typename T, MQFlavor flavor>
837bool 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
843template <typename T, MQFlavor flavor>
844bool 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
950template <typename T, MQFlavor flavor>
951bool 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
955template <typename T, MQFlavor flavor>
956size_t MessageQueue<T, flavor>::availableToWriteBytes() const {
957    return mDesc->getSize() - availableToReadBytes();
958}
959
960template <typename T, MQFlavor flavor>
961size_t MessageQueue<T, flavor>::availableToWrite() const {
962    return availableToWriteBytes() / sizeof(T);
963}
964
965template <typename T, MQFlavor flavor>
966size_t MessageQueue<T, flavor>::availableToRead() const {
967    return availableToReadBytes() / sizeof(T);
968}
969
970template <typename T, MQFlavor flavor>
971bool 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
1013template <typename T, MQFlavor flavor>
1014/*
1015 * Disable integer sanitization since integer overflow here is allowed
1016 * and legal.
1017 */
1018__attribute__((no_sanitize("integer")))
1019bool 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
1031template <typename T, MQFlavor flavor>
1032size_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
1042template <typename T, MQFlavor flavor>
1043bool 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
1050template <typename T, MQFlavor flavor>
1051/*
1052 * Disable integer sanitization since integer overflow here is allowed
1053 * and legal.
1054 */
1055__attribute__((no_sanitize("integer")))
1056bool 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
1113template <typename T, MQFlavor flavor>
1114/*
1115 * Disable integer sanitization since integer overflow here is allowed
1116 * and legal.
1117 */
1118__attribute__((no_sanitize("integer")))
1119bool 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
1138template <typename T, MQFlavor flavor>
1139size_t MessageQueue<T, flavor>::getQuantumSize() const {
1140    return mDesc->getQuantum();
1141}
1142
1143template <typename T, MQFlavor flavor>
1144size_t MessageQueue<T, flavor>::getQuantumCount() const {
1145    return mDesc->getSize() / mDesc->getQuantum();
1146}
1147
1148template <typename T, MQFlavor flavor>
1149bool MessageQueue<T, flavor>::isValid() const {
1150    return mRing != nullptr && mReadPtr != nullptr && mWritePtr != nullptr;
1151}
1152
1153template <typename T, MQFlavor flavor>
1154void* 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
1177template <typename T, MQFlavor flavor>
1178void 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