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_DUMB_ALLOCATOR_H_
18 #define _GTS_NANOAPPS_SHARED_DUMB_ALLOCATOR_H_
19 
20 #include <cstddef>
21 #include <cstdint>
22 
23 namespace nanoapp_testing {
24 
25 // Implementation Note: We chose the pattern of having DumbAllocatorBase to
26 // reduce the code duplication from multiple instances of DumbAllocator with
27 // different template parameters.
28 // See DumbAllocator below for usage and API documentation.
29 class DumbAllocatorBase {
30  protected:
31   DumbAllocatorBase(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 /**
54  * This dumb allocator is designed to allow us to easily get chunks of
55  * memory without needing to go through heap allocation.  The idea is to
56  * reduce our dependency on CHRE for some aspects of our tests.
57  *
58  * This allocator is non-reentrant.  It's also inefficient and a bad idea
59  * for shipping code, but useful for reducing dependencies during testing.
60  *
61  * This will allow up to kSlotCount allocations of up to kAllocSize bytes
62  * each, and costs (kSlotCount * kAllocSize) bytes of underlying storage.
63  */
64 template<size_t kAllocSize, size_t kSlotCount>
65 class DumbAllocator : DumbAllocatorBase {
66  public:
DumbAllocator()67   DumbAllocator()
68       : DumbAllocatorBase(kAllocSize, kSlotCount, mRawMemoryArray) {}
69 
70   /**
71    * If "bytes" <= kAllocSize, and there are less than kSlotCount allocations,
72    * return a valid pointer.  Otherwise, nullptr.
73    *
74    * Reminder this is non-reentrant.
75    */
alloc(size_t bytes)76   void *alloc(size_t bytes) {
77     return DumbAllocatorBase::alloc(bytes);
78   }
79 
80   /**
81    * If contains(ptr) is true, free the allocation and return true.
82    * Otherwise, do nothing and return false.
83    *
84    * Reminder this is non-reentrant.
85    */
free(void * ptr)86   bool free(void *ptr) {
87     return DumbAllocatorBase::free(ptr);
88   }
89 
90   /**
91    * If "ptr" was a non-null pointer returned from alloc() on this instance,
92    * return true.  Otherwise, do nothing and return false.
93    */
contains(const void * ptr)94   bool contains(const void *ptr) const {
95     return DumbAllocatorBase::contains(ptr);
96   }
97 
98  private:
99   uint8_t mRawMemoryArray[kAllocSize * kSlotCount];
100 
101   static_assert(kSlotCount <= MaxSlotCount(), "kSlotCount is too high");
102 };
103 
104 
105 }  // namespace nanoapp_testing
106 
107 #endif  // _GTS_NANOAPPS_SHARED_DUMB_ALLOCATOR_H_
108