1 /*
2  * Copyright 2019 Google
3  * SPDX-License-Identifier: MIT
4  */
5 #pragma once
6 
7 #include "aemu/base/AlignedBuf.h"
8 #include "aemu/base/Allocator.h"
9 
10 #include <vector>
11 #include <unordered_set>
12 
13 #include <inttypes.h>
14 
15 namespace android {
16 namespace base {
17 
18 // Class to make it easier to set up memory regions where it is fast
19 // to allocate buffers AND we don't care about freeing individual pieces,
20 // BUT it's necessary to preserve previous pointer values in between the first
21 // alloc() after a freeAll(), and the freeAll() itself, allowing some sloppy use of
22 // malloc in the first pass while we find out how much data was needed.
23 class BumpPool : public Allocator {
24 public:
25     BumpPool(size_t startingBytes = 4096) : mStorage(startingBytes / sizeof(uint64_t))  { }
26     // All memory allocated by this pool
27     // is automatically deleted when the pool
28     // is deconstructed.
~BumpPool()29     ~BumpPool() {
30         freeAll();
31     }
32 
alloc(size_t wantedSize)33     void* alloc(size_t wantedSize) override {
34         size_t wantedSizeRoundedUp =
35             sizeof(uint64_t) * ((wantedSize + sizeof(uint64_t) - 1) / (sizeof(uint64_t)));
36 
37         mTotalWantedThisGeneration += wantedSizeRoundedUp;
38         if (mAllocPos + wantedSizeRoundedUp > mStorage.size() * sizeof(uint64_t)) {
39             mNeedRealloc = true;
40             void* fallbackPtr = malloc(wantedSizeRoundedUp);
41             mFallbackPtrs.insert(fallbackPtr);
42             return fallbackPtr;
43         }
44         void* allocPtr = (void*)(((unsigned char*)mStorage.data()) + mAllocPos);
45         mAllocPos += wantedSizeRoundedUp;
46         return allocPtr;
47     }
48 
freeAll()49     void freeAll() {
50         mAllocPos = 0;
51         if (mNeedRealloc) {
52             mStorage.resize((mTotalWantedThisGeneration * 2) / sizeof(uint64_t));
53             mNeedRealloc = false;
54             for (auto ptr : mFallbackPtrs) {
55                 free(ptr);
56             }
57             mFallbackPtrs.clear();
58         }
59         mTotalWantedThisGeneration = 0;
60     }
61 private:
62     AlignedBuf<uint64_t, 8> mStorage;
63     std::unordered_set<void*> mFallbackPtrs;
64     size_t mAllocPos = 0;
65     size_t mTotalWantedThisGeneration = 0;
66     bool mNeedRealloc = false;
67 };
68 
69 } // namespace base
70 } // namespace android
71