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 _GTS_NANOAPPS_SHARED_CHUNK_ALLOCATOR_H_ 18 #define _GTS_NANOAPPS_SHARED_CHUNK_ALLOCATOR_H_ 19 20 #include <cstddef> 21 #include <cstdint> 22 23 namespace nanoapp_testing { 24 25 // Implementation Note: We chose the pattern of having ChunkAllocatorBase to 26 // reduce the code duplication from multiple instances of ChunkAllocator with 27 // different template parameters. 28 // See ChunkAllocator below for usage and API documentation. 29 class ChunkAllocatorBase { 30 protected: 31 ChunkAllocatorBase(size_t allocSize, size_t slotCount, uint8_t *rawMemory); 32 33 void *alloc(size_t bytes); 34 bool free(void *ptr); 35 bool contains(const void *ptr) const; 36 MaxSlotCount()37 static constexpr size_t MaxSlotCount() { 38 // Our mAllocatedSlots is treated as a bit array, so we get 8 slots for 39 // each byte it has. 40 return (sizeof(mAllocatedSlots) * 8); 41 } 42 43 private: 44 const size_t mAllocSize; 45 const size_t mSlotCount; 46 uint8_t *const mRawMemory; 47 uint32_t mAllocatedSlots; 48 49 bool getSlot(const void *ptr, size_t *slot) const; 50 }; 51 52 /** 53 * This chunk allocator is designed to allow us to easily get chunks of 54 * memory without needing to go through heap allocation. The idea is to 55 * reduce our dependency on CHRE for some aspects of our tests. 56 * 57 * This allocator is non-reentrant. It's also inefficient and a bad idea 58 * for shipping code, but useful for reducing dependencies during testing. 59 * 60 * This will allow up to kSlotCount allocations of up to kAllocSize bytes 61 * each, and costs (kSlotCount * kAllocSize) bytes of underlying storage. 62 */ 63 template <size_t kAllocSize, size_t kSlotCount> 64 class ChunkAllocator : ChunkAllocatorBase { 65 public: ChunkAllocator()66 ChunkAllocator() 67 : ChunkAllocatorBase(kAllocSize, kSlotCount, mRawMemoryArray) {} 68 69 /** 70 * If "bytes" <= kAllocSize, and there are less than kSlotCount allocations, 71 * return a valid pointer. Otherwise, nullptr. 72 * 73 * Reminder this is non-reentrant. 74 */ alloc(size_t bytes)75 void *alloc(size_t bytes) { 76 return ChunkAllocatorBase::alloc(bytes); 77 } 78 79 /** 80 * If contains(ptr) is true, free the allocation and return true. 81 * Otherwise, do nothing and return false. 82 * 83 * Reminder this is non-reentrant. 84 */ free(void * ptr)85 bool free(void *ptr) { 86 return ChunkAllocatorBase::free(ptr); 87 } 88 89 /** 90 * If "ptr" was a non-null pointer returned from alloc() on this instance, 91 * return true. Otherwise, do nothing and return false. 92 */ contains(const void * ptr)93 bool contains(const void *ptr) const { 94 return ChunkAllocatorBase::contains(ptr); 95 } 96 97 private: 98 uint8_t mRawMemoryArray[kAllocSize * kSlotCount]; 99 100 static_assert(kSlotCount <= MaxSlotCount(), "kSlotCount is too high"); 101 }; 102 103 } // namespace nanoapp_testing 104 105 #endif // _GTS_NANOAPPS_SHARED_CHUNK_ALLOCATOR_H_ 106