/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include namespace nanoapp_testing { ChunkAllocatorBase::ChunkAllocatorBase(size_t allocSize, size_t slotCount, uint8_t *rawMemory) : mAllocSize(allocSize), mSlotCount(slotCount), mRawMemory(rawMemory), mAllocatedSlots(0) { // We're not worried about runtime efficiency, since this is testing // code. In case of an issue within the tests, though, we do want // to have consistent behavior. Thus, we initialize this memory to // aid tracking problems. memset(mRawMemory, 0xCD, mSlotCount * mAllocSize); } void *ChunkAllocatorBase::alloc(size_t bytes) { if (bytes > mAllocSize) { // Oversized for our allocator. return nullptr; } size_t slot = 0; for (uint32_t mask = 1; slot < mSlotCount; slot++, mask <<= 1) { if ((mAllocatedSlots & mask) == 0) { // This space is available, let's claim it. mAllocatedSlots |= mask; break; } } if (slot == mSlotCount) { // We're out of space. return nullptr; } return mRawMemory + (slot * mAllocSize); } bool ChunkAllocatorBase::free(void *pointer) { size_t slot; if (!getSlot(pointer, &slot)) { return false; } mAllocatedSlots &= ~(1 << slot); return true; } bool ChunkAllocatorBase::contains(const void *pointer) const { size_t slot; return getSlot(pointer, &slot); } bool ChunkAllocatorBase::getSlot(const void *pointer, size_t *slot) const { const uint8_t *ptr = static_cast(pointer); if (ptr < mRawMemory) { // Out of range. return false; } *slot = static_cast(ptr - mRawMemory) / mAllocSize; if (*slot >= mSlotCount) { // Out of range. return false; } // Also confirm alignment. return ((mRawMemory + (*slot * mAllocSize)) == ptr); } } // namespace nanoapp_testing