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#include <general_test/simple_heap_alloc_test.h> 18 19#include <cstddef> 20 21#include <general_test/test_names.h> 22#include <shared/abort.h> 23#include <shared/array_length.h> 24#include <shared/nano_string.h> 25#include <shared/send_message.h> 26 27#include <chre.h> 28 29using nanoapp_testing::MessageType; 30using nanoapp_testing::sendFatalFailureToHost; 31using nanoapp_testing::sendMessageToHost; 32using nanoapp_testing::sendSuccessToHost; 33 34namespace general_test { 35 36// For most platforms, we expect that what the compiler toolchain claims 37// is the maximum alignment needed for any type is accurate. However, we 38// do support one CHRE implementation where it is configured for a lower 39// max alignment than what the toolchain claims. 40// To support this, we allow for a compiler define set for building this 41// test. For the most part, we need to just trust the CHRE implementation 42// that this number is correct. However, we make a basic sanity check of 43// this in testMaxAlignment(). 44 45constexpr size_t kMaxAlignment = 46#ifdef CHRE_CUSTOM_MAX_ALIGNMENT 47 CHRE_CUSTOM_MAX_ALIGNMENT; 48#else 49 alignof(max_align_t); 50#endif // else CHRE_CUSTOM_MAX_ALIGNMENT 51 52#ifdef CHRE_CUSTOM_MAX_ALIGNMENT 53// We only test this when a CHRE implementation claims a custom max aligment. 54// We use an argument here to try to keep the compiler from performing any 55// of these calculations at compile-time, so they're forced to happen at 56// runtime. We do a mixture of multiplication and division, to force 57// various instructions which might have alignment constraints. 58static void testMaxAlignment(uint32_t zero) { 59 // It's not sufficient to use alignas(kMaxAlignment). Say kMaxAlignment 60 // is 4. Then alignas(4) could legally give something aligned on 32 bytes, 61 // and we wouldn't be testing what we hoped to test. So we ask for double 62 // the alignment (alignas(8), in our example), and then offset into that 63 // to assure that we're at exactly kMaxAlignment, and no more. 64 65#ifdef CHRE_NO_DOUBLE_SUPPORT 66 typedef float MyFloat; 67#define FLOAT_C(value) value##f 68#else 69 typedef long double myFloat; 70#define FLOAT_C(value) value 71#endif 72 73 alignas(kMaxAlignment * 2) uint8_t 74 myFloatMemory[sizeof(MyFloat) * 3 + kMaxAlignment]; 75 MyFloat *mfArray = 76 reinterpret_cast<MyFloat*>(myFloatMemory + kMaxAlignment); 77 mfArray[0] = static_cast<MyFloat>(zero) + FLOAT_C(1.0); 78 mfArray[1] = static_cast<MyFloat>(zero) + FLOAT_C(3.0); 79 mfArray[2] = mfArray[0] / mfArray[1]; 80 if ((mfArray[0] * mfArray[1] + mfArray[2]) / FLOAT_C(3.0) == FLOAT_C(1.0)) { 81 sendFatalFailureToHost("Float math is wrong"); 82 } 83 84 constexpr size_t kUllSize = sizeof(unsigned long long); 85 static_assert(kUllSize >= 8, "Size of long long violates spec"); 86 alignas(kMaxAlignment * 2) uint8_t 87 longlongMemory[kUllSize * 3 + kMaxAlignment]; 88 unsigned long long *ullArray = 89 reinterpret_cast<unsigned long long*>(longlongMemory + kMaxAlignment); 90 ullArray[0] = static_cast<unsigned long long>(zero) + 91 (1ULL << (kUllSize * 8 - 4)); 92 ullArray[1] = static_cast<unsigned long long>(zero) + (1ULL << 3); 93 ullArray[2] = ullArray[0] * ullArray[1]; 94 constexpr unsigned long long kExpected = 747134227367742ULL; 95 unsigned long long result = ullArray[2] / 12345ULL; 96 if (((kUllSize == 8) && (result != kExpected)) || 97 ((kUllSize > 8) && (result <= kExpected))) { 98 sendFatalFailureToHost("Long long math is wrong"); 99 } 100} 101#endif // CHRE_CUSTOM_MAX_ALIGNMENT 102 103 104SimpleHeapAllocTest::SimpleHeapAllocTest() 105 : Test(CHRE_API_VERSION_1_0), mHasFreed(false) { 106} 107 108void SimpleHeapAllocTest::setUp(uint32_t messageSize, 109 const void * /* message */) { 110 nanoapp_testing::memset(mPtrs, 0, sizeof(mPtrs)); 111 112 if (messageSize != 0) { 113 sendFatalFailureToHost( 114 "SimpleHeapAlloc message expects 0 additional bytes, got ", 115 &messageSize); 116 } 117 118 // Allocate random small-ish sizes. 119 static constexpr size_t kSizes[5] = { 120 16, 53, 2, 32, 40 }; 121 122 mPtrs[0] = chreHeapAlloc(kSizes[0]); 123 mPtrs[1] = chreHeapAlloc(kSizes[1]); 124 // For mPtrs[2] we do _not_ use kSizes[2], because we're going to free 125 // this in a moment, and intentionally want a different size. 126 mPtrs[2] = chreHeapAlloc(23); 127 mPtrs[3] = chreHeapAlloc(kSizes[3]); 128 // We want to mix in a free among the allocs, just to make sure there 129 // isn't some issue there. 130 if (mPtrs[2] == nullptr) { 131 sendFatalFailureToHost("Failed first allocation of mPtrs[2]"); 132 } else { 133 chreHeapFree(mPtrs[2]); 134 } 135 mPtrs[4] = chreHeapAlloc(kSizes[4]); 136 mPtrs[2] = chreHeapAlloc(kSizes[2]); 137 138 for (uint32_t i = 0; i < arrayLength(mPtrs); i++) { 139 if (mPtrs[i] == nullptr) { 140 // If we're getting this failure, but convinced the CHRE is 141 // correct, make sure that we're actually performing an allocation 142 // for each element of mPtrs. 143 sendFatalFailureToHost("Failed to allocate index ", &i); 144 } 145 const uintptr_t ptrValue = reinterpret_cast<uintptr_t>(mPtrs[i]); 146 if ((ptrValue & (kMaxAlignment - 1)) != 0) { 147 sendFatalFailureToHost("Misaligned allocation at index ", &i); 148 } 149 // Make sure all of the bytes are addressable. Our assumption 150 // is we'll crash here if that's not the case. Not the most 151 // friendly test, but it's better than allowing a bad CHRE. 152 // TODO: If we convince ourselves that chreLog() should be 153 // safe enough to use here, we could log an 'info' message 154 // prior to each memset attempt. 155 nanoapp_testing::memset(mPtrs[i], 0xFF, kSizes[i]); 156 } 157#ifdef CHRE_CUSTOM_MAX_ALIGNMENT 158 testMaxAlignment(messageSize); 159#endif // CHRE_CUSTOM_MAX_ALIGNMENT 160 sendMessageToHost(MessageType::kContinue); 161} 162 163void SimpleHeapAllocTest::handleEvent(uint32_t senderInstanceId, 164 uint16_t eventType, 165 const void* eventData) { 166 // We ignore the return value, since we expect no data. 167 getMessageDataFromHostEvent(senderInstanceId, eventType, eventData, 168 MessageType::kContinue, 0); 169 if (mHasFreed) { 170 sendFatalFailureToHost("Multiple kContinue messages sent"); 171 } 172 173 chreHeapFree(mPtrs[3]); 174 chreHeapFree(mPtrs[1]); 175 chreHeapFree(mPtrs[2]); 176 chreHeapFree(mPtrs[0]); 177 chreHeapFree(mPtrs[4]); 178 mHasFreed = true; 179 180 sendSuccessToHost(); 181} 182 183} // namespace general_test 184