1 /* 2 * Copyright (c) 2021-2025 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_LIBPANDABASE_MEM_STACK_LIKE_ALLOCATOR_H 16 #define PANDA_LIBPANDABASE_MEM_STACK_LIKE_ALLOCATOR_H 17 18 #include "libpandabase/mem/mem.h" 19 #include "libpandabase/mem/pool_map.h" 20 21 namespace ark::mem { 22 // Note: we only have 4GB of memory on arm32, so we need to limit the max size of the stack like allocator 23 // details can be found in #26461 24 #ifdef PANDA_TARGET_ARM32 25 static constexpr size_t STACK_LIKE_ALLOCATOR_DEFAUL_MAX_SIZE = 2_MB; 26 #else 27 static constexpr size_t STACK_LIKE_ALLOCATOR_DEFAUL_MAX_SIZE = 48_MB; 28 #endif 29 30 // Allocation flow looks like that: 31 // 32 // 1. Allocate big memory piece via mmap. 33 // 2. Allocate/Free memory in this preallocated memory piece. 34 // 3. Return nullptr if we reached the limit of created memory piece. 35 36 template <Alignment ALIGNMENT = DEFAULT_FRAME_ALIGNMENT, size_t MAX_SIZE = STACK_LIKE_ALLOCATOR_DEFAUL_MAX_SIZE> 37 class StackLikeAllocator { 38 public: 39 explicit StackLikeAllocator(bool usePoolManager = true, SpaceType spaceType = SpaceType::SPACE_TYPE_FRAMES); 40 ~StackLikeAllocator(); 41 NO_MOVE_SEMANTIC(StackLikeAllocator); 42 NO_COPY_SEMANTIC(StackLikeAllocator); 43 44 template <bool USE_MEMSET = true> 45 [[nodiscard]] void *Alloc(size_t size); 46 47 void Free(void *mem); 48 49 /// @brief Returns true if address inside current allocator. 50 bool Contains(void *mem); 51 GetAllocatorType()52 static constexpr AllocatorType GetAllocatorType() 53 { 54 return AllocatorType::STACK_LIKE_ALLOCATOR; 55 } 56 GetAllocatedSize()57 size_t GetAllocatedSize() const 58 { 59 ASSERT(ToUintPtr(freePointer_) >= ToUintPtr(startAddr_)); 60 return ToUintPtr(freePointer_) - ToUintPtr(startAddr_); 61 } 62 SetReservedMemorySize(size_t size)63 void SetReservedMemorySize(size_t size) 64 { 65 ASSERT(GetFullMemorySize() >= size); 66 reservedEndAddr_ = ToVoidPtr(ToUintPtr(startAddr_) + size); 67 } 68 UseWholeMemory()69 void UseWholeMemory() 70 { 71 endAddr_ = allocatedEndAddr_; 72 } 73 ReserveMemory()74 void ReserveMemory() 75 { 76 ASSERT(reservedEndAddr_ != nullptr); 77 endAddr_ = reservedEndAddr_; 78 } 79 GetFullMemorySize()80 size_t GetFullMemorySize() const 81 { 82 return ToUintPtr(allocatedEndAddr_) - ToUintPtr(startAddr_); 83 } 84 85 private: 86 static constexpr size_t RELEASE_PAGES_SIZE = 256_KB; 87 static constexpr size_t RELEASE_PAGES_SHIFT = 18; 88 static_assert(RELEASE_PAGES_SIZE == (1U << RELEASE_PAGES_SHIFT)); 89 static_assert(MAX_SIZE % GetAlignmentInBytes(ALIGNMENT) == 0); 90 void *startAddr_ {nullptr}; 91 void *endAddr_ {nullptr}; 92 void *freePointer_ {nullptr}; 93 bool usePoolManager_ {false}; 94 void *reservedEndAddr_ {nullptr}; 95 void *allocatedEndAddr_ {nullptr}; 96 }; 97 } // namespace ark::mem 98 99 #endif // PANDA_LIBPANDABASE_MEM_STACK_LIKE_ALLOCATOR_H 100