1 /** 2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 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 */ 15 #ifndef PANDA_RUNTIME_MEM_FRAME_ALLOCATOR_H 16 #define PANDA_RUNTIME_MEM_FRAME_ALLOCATOR_H 17 18 #include <securec.h> 19 #include <array> 20 21 #include "libpandabase/mem/arena-inl.h" 22 #include "libpandabase/mem/mem.h" 23 #include "libpandabase/mem/mmap_mem_pool-inl.h" 24 25 namespace ark::mem { 26 27 // Allocation flow looks like that: 28 // 29 // Allocate arenas for frames Frames free Return arenas Second allocated arena 30 // (stage 1) (stage 2) (stage 3) will be bigger than the 31 // second at stage 1 32 // |-----| |-----| |-----| 33 // | | | | | | 34 // |-----| | | |-----| | | | | 35 // |xxxxx| | | | | | | | | 36 // |-----| |xxxxx| |xxxxx| |-----| | | | | |-----| |-----| | | 37 // |xxxxx| |xxxxx| |xxxxx| ----> | | | | | | ----> | | ----> |xxxxx| |xxxxx| 38 // |xxxxx| |xxxxx| |xxxxx| | | | | | | | | |xxxxx| |xxxxx| 39 // |xxxxx| |xxxxx| |xxxxx| | | | | | | | | |xxxxx| |xxxxx| 40 // |xxxxx| |xxxxx| |xxxxx| | | | | | | | | |xxxxx| |xxxxx| 41 // |xxxxx| |xxxxx| |xxxxx| |xxxxx| | | | | |xxxxx| |xxxxx| |xxxxx| 42 // |-----| |-----| |-----| |-----| |-----| |-----| |-----| |-----| |-----| 43 44 // Frame allocator uses arenas and works like a stack - 45 // it will give memory from the top and can delete only last allocated memory. 46 template <Alignment ALIGNMENT = DEFAULT_FRAME_ALIGNMENT, bool USE_MEMSET = true> 47 class FrameAllocator { 48 public: 49 explicit FrameAllocator(bool useMalloc = false, SpaceType spaceType = SpaceType::SPACE_TYPE_INTERNAL); 50 ~FrameAllocator(); 51 FrameAllocator(const FrameAllocator &) noexcept = delete; 52 FrameAllocator(FrameAllocator &&) noexcept = default; 53 FrameAllocator &operator=(const FrameAllocator &) noexcept = delete; 54 FrameAllocator &operator=(FrameAllocator &&) noexcept = default; 55 56 [[nodiscard]] void *Alloc(size_t size); 57 58 // We must free objects allocated by this allocator strictly in reverse order 59 void Free(void *mem); 60 61 /// @brief Returns true if address inside current allocator. 62 bool Contains(void *mem); 63 GetAllocatorType()64 static constexpr AllocatorType GetAllocatorType() 65 { 66 return AllocatorType::FRAME_ALLOCATOR; 67 } 68 GetAllocatedSize()69 size_t GetAllocatedSize() const 70 { 71 return allocatedSize_; 72 } 73 74 private: 75 using FramesArena = DoubleLinkedAlignedArena<ALIGNMENT>; 76 static constexpr size_t FIRST_ARENA_SIZE = 256_KB; 77 static_assert(FIRST_ARENA_SIZE % PANDA_POOL_ALIGNMENT_IN_BYTES == 0); 78 static constexpr size_t ARENA_SIZE_GREW_LEVEL = FIRST_ARENA_SIZE; 79 static constexpr size_t FRAME_ALLOC_MIN_FREE_MEMORY_THRESHOLD = FIRST_ARENA_SIZE / 2; 80 static constexpr size_t FRAME_ALLOC_MAX_FREE_ARENAS_THRESHOLD = 1; 81 82 /** 83 * @brief Heuristic for arena size increase. 84 * @return new size 85 */ 86 size_t GetNextArenaSize(size_t size); 87 88 /** 89 * @brief Try to allocate an arena from the memory. 90 * @return true on success, or false on fail 91 */ 92 bool TryAllocateNewArena(size_t size = ARENA_SIZE_GREW_LEVEL); 93 94 /** 95 * @brief Try to allocate memory for a frame in the current arena or in the next one if it exists. 96 * @param size - size of the allocated memory 97 * @return pointer to the allocated memory on success, or nullptr on fail 98 */ 99 void *TryToAllocate(size_t size); 100 101 /// @brief Free last_allocated_arena_, i.e., free last arena in the list. 102 void FreeLastArena(); 103 104 /** 105 * @brief Try to allocate an arena from the memory. 106 * @param size - size of the required arena 107 * @return pointer on success, or nullptr on fail 108 */ 109 FramesArena *AllocateArenaImpl(size_t size); 110 111 /** 112 * @brief Free given arena 113 * @param arena - arena to free 114 */ 115 void FreeArenaImpl(FramesArena *arena); 116 117 // A pointer to the current arena with the last allocated frame 118 FramesArena *curArena_ {nullptr}; 119 120 // A pointer to the last allocated arena (so it is equal to the top arena in the list) 121 FramesArena *lastAllocArena_ {nullptr}; 122 123 // The biggest arena size during FrameAllocator workflow. Needed for computing a new arena size. 124 size_t biggestArenaSize_ {0}; 125 126 // A marker which tells us if we need to increase the size of a new arena or not. 127 bool arenaSizeNeedToGrow_ {true}; 128 129 size_t emptyArenasCount_ {0}; 130 131 // Total allocated size 132 size_t allocatedSize_ {0}; 133 134 MmapMemPool *memPoolAlloc_ {nullptr}; 135 136 bool useMalloc_ {false}; 137 SpaceType spaceType_; 138 139 friend class FrameAllocatorTest; 140 }; 141 142 } // namespace ark::mem 143 144 #endif // PANDA_RUNTIME_MEM_FRAME_ALLOCATOR_H 145