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 <shared/chunk_allocator.h>
18 
19 #include <shared/nano_string.h>
20 
21 namespace nanoapp_testing {
22 
ChunkAllocatorBase(size_t allocSize,size_t slotCount,uint8_t * rawMemory)23 ChunkAllocatorBase::ChunkAllocatorBase(size_t allocSize, size_t slotCount,
24                                        uint8_t *rawMemory)
25     : mAllocSize(allocSize),
26       mSlotCount(slotCount),
27       mRawMemory(rawMemory),
28       mAllocatedSlots(0) {
29   // We're not worried about runtime efficiency, since this is testing
30   // code.  In case of an issue within the tests, though, we do want
31   // to have consistent behavior.  Thus, we initialize this memory to
32   // aid tracking problems.
33   memset(mRawMemory, 0xCD, mSlotCount * mAllocSize);
34 }
35 
alloc(size_t bytes)36 void *ChunkAllocatorBase::alloc(size_t bytes) {
37   if (bytes > mAllocSize) {
38     // Oversized for our allocator.
39     return nullptr;
40   }
41   size_t slot = 0;
42   for (uint32_t mask = 1; slot < mSlotCount; slot++, mask <<= 1) {
43     if ((mAllocatedSlots & mask) == 0) {
44       // This space is available, let's claim it.
45       mAllocatedSlots |= mask;
46       break;
47     }
48   }
49   if (slot == mSlotCount) {
50     // We're out of space.
51     return nullptr;
52   }
53   return mRawMemory + (slot * mAllocSize);
54 }
55 
free(void * pointer)56 bool ChunkAllocatorBase::free(void *pointer) {
57   size_t slot;
58   if (!getSlot(pointer, &slot)) {
59     return false;
60   }
61   mAllocatedSlots &= ~(1 << slot);
62   return true;
63 }
64 
contains(const void * pointer) const65 bool ChunkAllocatorBase::contains(const void *pointer) const {
66   size_t slot;
67   return getSlot(pointer, &slot);
68 }
69 
getSlot(const void * pointer,size_t * slot) const70 bool ChunkAllocatorBase::getSlot(const void *pointer, size_t *slot) const {
71   const uint8_t *ptr = static_cast<const uint8_t *>(pointer);
72   if (ptr < mRawMemory) {
73     // Out of range.
74     return false;
75   }
76   *slot = static_cast<size_t>(ptr - mRawMemory) / mAllocSize;
77   if (*slot >= mSlotCount) {
78     // Out of range.
79     return false;
80   }
81   // Also confirm alignment.
82   return ((mRawMemory + (*slot * mAllocSize)) == ptr);
83 }
84 
85 }  // namespace nanoapp_testing
86