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