1 // Copyright 2018 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 #pragma once 15 16 #include "aemu/base/AlignedBuf.h" 17 #include "aemu/base/Allocator.h" 18 19 #include <vector> 20 #include <unordered_set> 21 22 #include <inttypes.h> 23 24 namespace android { 25 namespace base { 26 27 // Class to make it easier to set up memory regions where it is fast 28 // to allocate buffers AND we don't care about freeing individual pieces, 29 // BUT it's necessary to preserve previous pointer values in between the first 30 // alloc() after a freeAll(), and the freeAll() itself, allowing some sloppy use of 31 // malloc in the first pass while we find out how much data was needed. 32 class BumpPool : public Allocator { 33 public: 34 BumpPool(size_t startingBytes = 4096) : mStorage(startingBytes / sizeof(uint64_t)) { } 35 // All memory allocated by this pool 36 // is automatically deleted when the pool 37 // is deconstructed. ~BumpPool()38 ~BumpPool() { } 39 alloc(size_t wantedSize)40 void* alloc(size_t wantedSize) override { 41 size_t wantedSizeRoundedUp = 42 sizeof(uint64_t) * ((wantedSize + sizeof(uint64_t) - 1) / (sizeof(uint64_t))); 43 44 mTotalWantedThisGeneration += wantedSizeRoundedUp; 45 if (mAllocPos + wantedSizeRoundedUp > mStorage.size() * sizeof(uint64_t)) { 46 mNeedRealloc = true; 47 void* fallbackPtr = malloc(wantedSizeRoundedUp); 48 mFallbackPtrs.insert(fallbackPtr); 49 return fallbackPtr; 50 } 51 size_t avail = mStorage.size() * sizeof(uint64_t) - mAllocPos; 52 void* allocPtr = (void*)(((unsigned char*)mStorage.data()) + mAllocPos); 53 mAllocPos += wantedSizeRoundedUp; 54 return allocPtr; 55 } 56 freeAll()57 void freeAll() { 58 mAllocPos = 0; 59 if (mNeedRealloc) { 60 mStorage.resize((mTotalWantedThisGeneration * 2) / sizeof(uint64_t)); 61 mNeedRealloc = false; 62 for (auto ptr : mFallbackPtrs) { 63 free(ptr); 64 } 65 mFallbackPtrs.clear(); 66 } 67 mTotalWantedThisGeneration = 0; 68 } 69 private: 70 AlignedBuf<uint64_t, 8> mStorage; 71 std::unordered_set<void*> mFallbackPtrs; 72 size_t mAllocPos = 0; 73 size_t mTotalWantedThisGeneration = 0; 74 bool mNeedRealloc = false; 75 }; 76 77 } // namespace base 78 } // namespace android 79