Merge "Align all offsets to word boundary."
diff --git a/include/fmq/MessageQueue.h b/include/fmq/MessageQueue.h
index eaaad02..730a638 100644
--- a/include/fmq/MessageQueue.h
+++ b/include/fmq/MessageQueue.h
@@ -31,7 +31,7 @@
template <typename T, MQFlavor flavor>
struct MessageQueue {
- typedef MQDescriptor<T,flavor> Descriptor;
+ typedef MQDescriptor<T, flavor> Descriptor;
/**
* @param Desc MQDescriptor describing the FMQ.
@@ -332,11 +332,13 @@
}
/*
- * Ashmem memory region size needs to
- * be specified in page-aligned bytes.
+ * Ashmem memory region size needs to be specified in page-aligned bytes.
+ * kQueueSizeBytes needs to be aligned to word boundary so that all offsets
+ * in the grantorDescriptor will be word aligned.
*/
size_t kAshmemSizePageAligned =
- (kQueueSizeBytes + kMetaDataSize + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
+ (Descriptor::alignToWordBoundary(kQueueSizeBytes) + kMetaDataSize + PAGE_SIZE - 1) &
+ ~(PAGE_SIZE - 1);
/*
* Create an ashmem region to map the memory for the ringbuffer,
@@ -463,7 +465,7 @@
* notification.
*/
status_t status = evFlag->wait(readNotification, &efState, timeOutNanos);
- switch(status) {
+ switch (status) {
case android::NO_ERROR:
/*
* If wait() returns NO_ERROR, break and check efState.
@@ -561,7 +563,7 @@
* notification.
*/
status_t status = evFlag->wait(writeNotification, &efState, timeOutNanos);
- switch(status) {
+ switch (status) {
case android::NO_ERROR:
/*
* If wait() returns NO_ERROR, break and check efState.
diff --git a/tests/mq_test.cpp b/tests/mq_test.cpp
index 1cafe97..3748cfe 100644
--- a/tests/mq_test.cpp
+++ b/tests/mq_test.cpp
@@ -94,6 +94,32 @@
size_t mNumMessagesMax = 0;
};
+class QueueSizeOdd : public ::testing::Test {
+ protected:
+ virtual void TearDown() {
+ delete mQueue;
+ }
+ virtual void SetUp() {
+ static constexpr size_t kNumElementsInQueue = 2049;
+ mQueue = new (std::nothrow) android::hardware::MessageQueue<
+ uint8_t, android::hardware::kSynchronizedReadWrite>(kNumElementsInQueue,
+ true /* configureEventFlagWord */);
+ ASSERT_NE(nullptr, mQueue);
+ ASSERT_TRUE(mQueue->isValid());
+ mNumMessagesMax = mQueue->getQuantumCount();
+ ASSERT_EQ(kNumElementsInQueue, mNumMessagesMax);
+ auto evFlagWordPtr = mQueue->getEventFlagWord();
+ ASSERT_NE(nullptr, evFlagWordPtr);
+ /*
+ * Initialize the EventFlag word to indicate Queue is not full.
+ */
+ std::atomic_init(evFlagWordPtr, static_cast<uint32_t>(kFmqNotFull));
+ }
+
+ android::hardware::MessageQueue<uint8_t, android::hardware::kSynchronizedReadWrite>* mQueue;
+ size_t mNumMessagesMax = 0;
+};
+
/*
* This thread will attempt to read and block. When wait returns
* it checks if the kFmqNotEmpty bit is actually set.
@@ -248,6 +274,22 @@
}
/*
+ * Test that odd queue sizes do not cause unaligned error
+ * on access to EventFlag object.
+ */
+TEST_F(QueueSizeOdd, EventFlagTest) {
+ const size_t dataLen = 64;
+ uint8_t data[dataLen] = {0};
+
+ bool ret = mQueue->writeBlocking(data,
+ dataLen,
+ static_cast<uint32_t>(kFmqNotFull),
+ static_cast<uint32_t>(kFmqNotEmpty),
+ 5000000000 /* timeOutNanos */);
+ ASSERT_TRUE(ret);
+}
+
+/*
* Verify that a few bytes of data can be successfully written and read.
*/
TEST_F(SynchronizedReadWrites, SmallInputTest1) {