• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 #include "mempool.h"
17 #include "securec.h"
18 
19 namespace maple {
20 MemPoolCtrler memPoolCtrler;
21 bool MemPoolCtrler::freeMemInTime = false;
22 
FreeMemBlocks(const MemPool & pool,MemBlock * fixedMemHead,MemBlock * bigMemHead)23 void MemPoolCtrler::FreeMemBlocks(const MemPool &pool, MemBlock *fixedMemHead, MemBlock *bigMemHead)
24 {
25     (void)(pool);
26 
27     MemBlock *fixedTail = nullptr;
28 
29     if (fixedMemHead != nullptr) {
30         fixedTail = fixedMemHead;
31         while (fixedTail->nextMemBlock != nullptr) {
32             fixedTail = fixedTail->nextMemBlock;
33         }
34     }
35 
36     while (bigMemHead != nullptr) {
37         auto *cur = bigMemHead;
38         bigMemHead = bigMemHead->nextMemBlock;
39         free(cur->startPtr);
40         delete cur;
41     }
42 
43     if (fixedTail != nullptr) {
44         fixedTail->nextMemBlock = fixedFreeMemBlocks;
45         DEBUG_ASSERT(fixedTail->nextMemBlock != fixedTail, "error");
46         fixedFreeMemBlocks = fixedMemHead;
47     }
48 }
49 
50 // Destructor, free all allocated memories
~MemPoolCtrler()51 MemPoolCtrler::~MemPoolCtrler()
52 {
53     FreeMem();
54 }
55 
FreeFixedSizeMemBlockMemory()56 void MemPoolCtrler::FreeFixedSizeMemBlockMemory()
57 {
58     FreeMem();
59     sysMemoryMgr->ReleaseMemory();
60 }
61 
62 // Allocate a new memory pool and register it in controller
NewMemPool(const std::string & name,bool isLocalPool)63 MemPool *MemPoolCtrler::NewMemPool(const std::string &name, bool isLocalPool)
64 {
65     MemPool *memPool = nullptr;
66 
67     if (isLocalPool) {
68         memPool = new ThreadLocalMemPool(*this, name);
69     } else {
70         memPool = new ThreadShareMemPool(*this, name);
71     }
72 
73     return memPool;
74 }
75 
76 // This function will be removed soon, DO NOT call it, just use delete memPool
DeleteMemPool(MemPool * memPool) const77 void MemPoolCtrler::DeleteMemPool(MemPool *memPool) const
78 {
79     delete memPool;
80 }
81 
FreeMem()82 void MemPoolCtrler::FreeMem()
83 {
84     while (fixedFreeMemBlocks != nullptr) {
85         MemBlock *arena = fixedFreeMemBlocks;
86         fixedFreeMemBlocks = fixedFreeMemBlocks->nextMemBlock;
87         delete arena;
88     }
89 }
90 
AllocMemBlock(const MemPool & pool,size_t size)91 MemBlock *MemPoolCtrler::AllocMemBlock(const MemPool &pool, size_t size)
92 {
93     if (size <= kMemBlockSizeMin) {
94         return AllocFixMemBlock(pool);
95     } else {
96         return AllocBigMemBlock(pool, size);
97     }
98 }
99 
AllocFixMemBlock(const MemPool & pool)100 MemBlock *MemPoolCtrler::AllocFixMemBlock(const MemPool &pool)
101 {
102     (void)(pool);
103     MemBlock *ret = nullptr;
104 
105     if (fixedFreeMemBlocks != nullptr) {
106         ret = fixedFreeMemBlocks;
107         fixedFreeMemBlocks = fixedFreeMemBlocks->nextMemBlock;
108         return ret;
109     }
110 
111     uint8_t *ptr = sysMemoryMgr->RealAllocMemory(kMemBlockMalloc);
112     // leave one MemBlock to return
113     for (size_t i = 0; i < kMemBlockMalloc / kMemBlockSizeMin - 1; ++i) {
114         auto *block = new MemBlock(ptr, kMemBlockSizeMin);
115         ptr += kMemBlockSizeMin;
116         block->nextMemBlock = fixedFreeMemBlocks;
117         fixedFreeMemBlocks = block;
118     }
119 
120     return new MemBlock(ptr, kMemBlockSizeMin);
121 }
122 
AllocBigMemBlock(const MemPool & pool,size_t size) const123 MemBlock *MemPoolCtrler::AllocBigMemBlock(const MemPool &pool, size_t size) const
124 {
125     DEBUG_ASSERT(size > kMemBlockSizeMin, "Big memory block must be bigger than fixed memory block");
126     (void)(pool);
127 
128     uint8_t *block = reinterpret_cast<uint8_t *>(malloc(size));
129     CHECK_FATAL(block != nullptr, "malloc failed");
130     return new MemBlock(block, size);
131 }
132 
~MemPool()133 MemPool::~MemPool()
134 {
135     ctrler.FreeMemBlocks(*this, fixedMemHead, bigMemHead);
136 }
137 
Malloc(size_t size)138 void *MemPool::Malloc(size_t size)
139 {
140     size = BITS_ALIGN(size);
141     DEBUG_ASSERT(endPtr >= curPtr, "endPtr should >= curPtr");
142     if (size > static_cast<size_t>(endPtr - curPtr)) {
143         return AllocNewMemBlock(size);
144     }
145     uint8_t *retPtr = curPtr;
146     curPtr += size;
147     return retPtr;
148 }
149 
ReleaseContainingMem()150 void MemPool::ReleaseContainingMem()
151 {
152     ctrler.FreeMemBlocks(*this, fixedMemHead, bigMemHead);
153 
154     fixedMemHead = nullptr;
155     bigMemHead = nullptr;
156     endPtr = nullptr;
157     curPtr = nullptr;
158 }
159 
160 // Malloc size of memory from memory pool, then set 0
Calloc(size_t size)161 void *MemPool::Calloc(size_t size)
162 {
163     void *p = Malloc(BITS_ALIGN(size));
164     DEBUG_ASSERT(p != nullptr, "ERROR: Calloc error");
165     errno_t eNum = memset_s(p, BITS_ALIGN(size), 0, BITS_ALIGN(size));
166     CHECK_FATAL(eNum == EOK, "memset_s failed");
167     return p;
168 }
169 
170 // Realloc new size of memory
Realloc(const void * ptr,size_t oldSize,size_t newSize)171 void *MemPool::Realloc(const void *ptr, size_t oldSize, size_t newSize)
172 {
173     void *result = Malloc(newSize);
174     DEBUG_ASSERT(result != nullptr, "ERROR: Realloc error");
175     size_t copySize = ((newSize > oldSize) ? oldSize : newSize);
176     if (copySize != 0 && ptr != nullptr) {
177         errno_t eNum = memcpy_s(result, copySize, ptr, copySize);
178         CHECK_FATAL(eNum == EOK, "memcpy_s failed");
179     }
180     return result;
181 }
182 
AllocNewMemBlock(size_t size)183 uint8_t *MemPool::AllocNewMemBlock(size_t size)
184 {
185     MemBlock **head = nullptr;
186     MemBlock *newMemBlock = ctrler.AllocMemBlock(*this, size);
187     if (newMemBlock->memSize <= kMemBlockSizeMin) {
188         head = &fixedMemHead;
189     } else {
190         head = &bigMemHead;
191     }
192 
193     newMemBlock->nextMemBlock = *head;
194     *head = newMemBlock;
195     CHECK_FATAL(newMemBlock->nextMemBlock != newMemBlock, "error");
196 
197     curPtr = newMemBlock->startPtr + size;
198     endPtr = newMemBlock->startPtr + newMemBlock->memSize;
199     DEBUG_ASSERT(curPtr <= endPtr, "must be");
200 
201     return newMemBlock->startPtr;
202 }
203 
Malloc(size_t size)204 void *StackMemPool::Malloc(size_t size)
205 {
206     size = BITS_ALIGN(size);
207     uint8_t **curPtrPtr = nullptr;
208     uint8_t *curEndPtr = nullptr;
209     if (size <= kMemBlockSizeMin) {
210         curPtrPtr = &curPtr;
211         curEndPtr = endPtr;
212     } else {
213         curPtrPtr = &bigCurPtr;
214         curEndPtr = bigEndPtr;
215     }
216     uint8_t *retPtr = *curPtrPtr;
217     DEBUG_ASSERT(curEndPtr >= *curPtrPtr, "endPtr should >= curPtr");
218     if (size > static_cast<size_t>(curEndPtr - *curPtrPtr)) {
219         retPtr = AllocTailMemBlock(size);
220     }
221     *curPtrPtr = retPtr + size;
222     return retPtr;
223 }
224 
225 // scoped mem pool don't use big mem block for small size, different with normal mempool
AllocMemBlockBySize(size_t size)226 MemBlock *StackMemPool::AllocMemBlockBySize(size_t size)
227 {
228     if (size <= kMemBlockSizeMin) {
229         return ctrler.AllocFixMemBlock(*this);
230     } else {
231         return ctrler.AllocBigMemBlock(*this, size);
232     }
233 }
234 
ResetStackTop(const LocalMapleAllocator * alloc,uint8_t * fixedCurPtrMark,MemBlock * fixedStackTopMark,uint8_t * bigCurPtrMark,MemBlock * bigStackTopMark)235 void StackMemPool::ResetStackTop(const LocalMapleAllocator *alloc, uint8_t *fixedCurPtrMark,
236                                  MemBlock *fixedStackTopMark, uint8_t *bigCurPtrMark,
237                                  MemBlock *bigStackTopMark) noexcept
238 {
239     CheckTopAllocator(alloc);
240     PopAllocator();
241 
242     if (fixedStackTopMark != nullptr) {
243         fixedMemStackTop = fixedStackTopMark;
244         curPtr = fixedCurPtrMark;
245         endPtr = fixedMemStackTop->EndPtr();
246     } else if (fixedMemHead != nullptr) {
247         fixedMemStackTop = fixedMemHead;
248         curPtr = fixedMemStackTop->startPtr;
249         endPtr = fixedMemStackTop->EndPtr();
250     }
251 
252     if (bigStackTopMark != nullptr) {
253         bigMemStackTop = bigStackTopMark;
254         bigCurPtr = bigCurPtrMark;
255         bigEndPtr = bigMemStackTop->EndPtr();
256     } else if (bigMemHead != nullptr) {
257         bigMemStackTop = bigMemHead;
258         bigCurPtr = bigMemStackTop->startPtr;
259         bigEndPtr = bigMemStackTop->EndPtr();
260     }
261 }
262 
AllocTailMemBlock(size_t size)263 uint8_t *StackMemPool::AllocTailMemBlock(size_t size)
264 {
265     MemBlock **head = nullptr;
266     MemBlock **stackTop = nullptr;
267     uint8_t **endPtrPtr = nullptr;
268 
269     if (size <= kMemBlockSizeMin) {
270         head = &fixedMemHead;
271         stackTop = &fixedMemStackTop;
272         endPtrPtr = &endPtr;
273     } else {
274         head = &bigMemHead;
275         stackTop = &bigMemStackTop;
276         endPtrPtr = &bigEndPtr;
277     }
278 
279     if (*stackTop == nullptr) {
280         MemBlock *newMemBlock = AllocMemBlockBySize(size);
281         *stackTop = newMemBlock;
282         *head = newMemBlock;
283         (*stackTop)->nextMemBlock = nullptr;
284     } else {
285         if ((*stackTop)->nextMemBlock != nullptr && (*stackTop)->nextMemBlock->memSize >= size) {
286             *stackTop = (*stackTop)->nextMemBlock;
287         } else {
288             MemBlock *newMemBlock = AllocMemBlockBySize(size);
289             auto *tmp = (*stackTop)->nextMemBlock;
290             (*stackTop)->nextMemBlock = newMemBlock;
291             *stackTop = newMemBlock;
292             newMemBlock->nextMemBlock = tmp;
293         }
294     }
295     *endPtrPtr = (*stackTop)->EndPtr();
296     return (*stackTop)->startPtr;
297 }
298 }  // namespace maple
299