• 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 
16 #ifndef LIBPANDABASE_MEM_MEM_POOL_H
17 #define LIBPANDABASE_MEM_MEM_POOL_H
18 
19 #include <cstddef>
20 #include "macros.h"
21 #include "mem.h"
22 #include "pool_map.h"
23 
24 namespace ark {
25 class Arena;
26 
27 enum class OSPagesPolicy : bool {
28     NO_RETURN,
29     IMMEDIATE_RETURN,
30 };
31 
32 enum class OSPagesAllocPolicy : bool {
33     NO_POLICY,
34     ZEROED_MEMORY,
35 };
36 
37 class Pool {
38 public:
Pool(size_t size,void * mem)39     explicit constexpr Pool(size_t size, void *mem) : size_(size), mem_(mem) {}
Pool(std::pair<size_t,void * > pool)40     explicit Pool(std::pair<size_t, void *> pool) : size_(pool.first), mem_(pool.second) {}
41 
GetSize()42     size_t GetSize() const
43     {
44         return size_;
45     }
46 
GetMem()47     void *GetMem()
48     {
49         return mem_;
50     }
51 
52     bool operator==(const Pool &other) const
53     {
54         return (this->size_ == other.size_) && (this->mem_ == other.mem_);
55     }
56 
57     bool operator!=(const Pool &other) const
58     {
59         return !(*this == other);
60     }
61 
62     ~Pool() = default;
63 
64     DEFAULT_COPY_SEMANTIC(Pool);
65     DEFAULT_MOVE_SEMANTIC(Pool);
66 
67 private:
68     size_t size_;
69     void *mem_;
70 };
71 
72 constexpr Pool NULLPOOL {0, nullptr};
73 
74 template <class MemPoolImplT>
75 class MemPool {
76 public:
77     virtual ~MemPool() = default;
MemPool(std::string poolName)78     explicit MemPool(std::string poolName) : name_(std::move(poolName)) {}
79     DEFAULT_NOEXCEPT_MOVE_SEMANTIC(MemPool);
80     DEFAULT_COPY_SEMANTIC(MemPool);
81 
82     /**
83      * Allocates arena with size bytes
84      * @tparam ArenaT - type of Arena
85      * @tparam OS_ALLOC_POLICY - allocated memory policy
86      * @param size - size of buffer in arena in bytes
87      * @param space_type - type of the space which arena allocated for
88      * @param allocator_type - type of the allocator which arena allocated for
89      * @param allocator_addr - address of the allocator header.
90      * @return pointer to allocated arena
91      */
92     // NOTE(aemelenko): We must always define allocator_addr for AllocArena
93     // because we set up arena at the first bytes of the pool
94     template <class ArenaT = Arena, OSPagesAllocPolicy OS_ALLOC_POLICY = OSPagesAllocPolicy::NO_POLICY>
95     inline ArenaT *AllocArena(size_t size, SpaceType spaceType, AllocatorType allocatorType,
96                               const void *allocatorAddr = nullptr)
97     {
98         auto *allocatedArena = static_cast<MemPoolImplT *>(this)->template AllocArenaImpl<ArenaT, OS_ALLOC_POLICY>(
99             size, spaceType, allocatorType, allocatorAddr);
100         if constexpr (IS_ZERO_CHECK_ENABLED && OS_ALLOC_POLICY == OSPagesAllocPolicy::ZEROED_MEMORY) {
101             if (allocatedArena != nullptr) {
102                 CheckZeroedMemory(allocatedArena->GetMem(), allocatedArena->GetSize());
103             }
104         }
105         return allocatedArena;
106     }
107 
108     /**
109      * Frees allocated arena
110      * @tparam ArenaT - arena type
111      * @tparam OS_PAGES_POLICY - OS return pages policy
112      * @param arena - pointer to the arena
113      */
114     template <class ArenaT = Arena, OSPagesPolicy OS_PAGES_POLICY = OSPagesPolicy::IMMEDIATE_RETURN>
FreeArena(ArenaT * arena)115     inline void FreeArena(ArenaT *arena)
116     {
117         static_cast<MemPoolImplT *>(this)->template FreeArenaImpl<ArenaT, OS_PAGES_POLICY>(arena);
118     }
119 
120     /**
121      * Allocates pool with at least size bytes
122      * @tparam OS_ALLOC_POLICY - allocated memory policy
123      * @param size - minimal size of a pool in bytes
124      * @param space_type - type of the space which pool allocated for
125      * @param allocator_type - type of the allocator which arena allocated for
126      * @param allocator_addr - address of the allocator header.
127      *  If it is not defined, it means that allocator header will be located at the first bytes of the returned pool.
128      * @return pool info with the size and a pointer
129      */
130     template <OSPagesAllocPolicy OS_ALLOC_POLICY = OSPagesAllocPolicy::NO_POLICY>
131     Pool AllocPool(size_t size, SpaceType spaceType, AllocatorType allocatorType, const void *allocatorAddr = nullptr)
132     {
133         Pool allocatedPool = static_cast<MemPoolImplT *>(this)->template AllocPoolImpl<OS_ALLOC_POLICY>(
134             size, spaceType, allocatorType, allocatorAddr);
135         if constexpr (IS_ZERO_CHECK_ENABLED && OS_ALLOC_POLICY == OSPagesAllocPolicy::ZEROED_MEMORY) {
136             if (allocatedPool.GetMem() != nullptr) {
137                 CheckZeroedMemory(allocatedPool.GetMem(), allocatedPool.GetSize());
138             }
139         }
140         return allocatedPool;
141     }
142 
143     /**
144      * Frees allocated pool
145      * @tparam OS_PAGES_POLICY - OS return pages policy
146      * @param mem - pointer to an allocated pool
147      * @param size - size of the allocated pool in bytes
148      */
149     template <OSPagesPolicy OS_PAGES_POLICY = OSPagesPolicy::IMMEDIATE_RETURN>
FreePool(void * mem,size_t size)150     void FreePool(void *mem, size_t size)
151     {
152         static_cast<MemPoolImplT *>(this)->template FreePoolImpl<OS_PAGES_POLICY>(mem, size);
153     }
154 
155     /**
156      * Get info about the allocator in which this address is used
157      * @param addr
158      * @return Allocator info with a type and pointer to the allocator header
159      */
GetAllocatorInfoForAddr(const void * addr)160     AllocatorInfo GetAllocatorInfoForAddr(const void *addr) const
161     {
162         return static_cast<const MemPoolImplT *>(this)->GetAllocatorInfoForAddrImpl(addr);
163     }
164 
165     /**
166      * Get space type which this address used for
167      * @param addr
168      * @return space type
169      */
GetSpaceTypeForAddr(const void * addr)170     SpaceType GetSpaceTypeForAddr(const void *addr) const
171     {
172         return static_cast<const MemPoolImplT *>(this)->GetSpaceTypeForAddrImpl(addr);
173     }
174 
175     /**
176      * Get address of pool start for input address
177      * @param addr address in pool
178      * @return address of pool start
179      */
GetStartAddrPoolForAddr(const void * addr)180     void *GetStartAddrPoolForAddr(const void *addr) const
181     {
182         return static_cast<const MemPoolImplT *>(this)->GetStartAddrPoolForAddrImpl(addr);
183     }
184 
185 private:
186 #ifndef NDEBUG
187     static constexpr bool IS_ZERO_CHECK_ENABLED = true;
188 #else
189     static constexpr bool IS_ZERO_CHECK_ENABLED = false;
190 #endif
191 
CheckZeroedMemory(void * mem,size_t size)192     static void CheckZeroedMemory(void *mem, size_t size)
193     {
194         // Check that the memory is zeroed:
195         [[maybe_unused]] auto iterator64 = static_cast<uint64_t *>(mem);
196         size_t it64End = size / sizeof(uint64_t);
197         [[maybe_unused]] uintptr_t endMemory = ToUintPtr(mem) + size;
198         // check by 64 byte
199         for (size_t i = 0; i < it64End; i++) {
200             // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
201             ASSERT(ToUintPtr(&iterator64[i]) < endMemory);
202             // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
203             ASSERT(iterator64[i] == 0);
204         }
205         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
206         [[maybe_unused]] auto iterator8 = reinterpret_cast<uint8_t *>(&iterator64[it64End]);
207         size_t it8End = size % sizeof(uint64_t);
208         // check by byte
209         for (size_t i = 0; i < it8End; i++) {
210             // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
211             ASSERT(ToUintPtr(&iterator8[i]) < endMemory);
212             // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
213             ASSERT(iterator8[i] == 0);
214         }
215     }
216 
217     std::string name_;
218 };
219 
220 }  // namespace ark
221 
222 #endif  // LIBPANDABASE_MEM_MEM_POOL_H
223