• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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