14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#include "mempool.h" 174514f5e3Sopenharmony_ci#include <cstdio> 184514f5e3Sopenharmony_ci#include <cstdlib> 194514f5e3Sopenharmony_ci#include <cstring> 204514f5e3Sopenharmony_ci#include <iostream> 214514f5e3Sopenharmony_ci#include <mutex> 224514f5e3Sopenharmony_ci#include "securec.h" 234514f5e3Sopenharmony_ci#include "mpl_logging.h" 244514f5e3Sopenharmony_ci 254514f5e3Sopenharmony_cinamespace maple { 264514f5e3Sopenharmony_ciMemPoolCtrler memPoolCtrler; 274514f5e3Sopenharmony_cibool MemPoolCtrler::freeMemInTime = false; 284514f5e3Sopenharmony_ci 294514f5e3Sopenharmony_civoid MemPoolCtrler::FreeMemBlocks(const MemPool &pool, MemBlock *fixedMemHead, MemBlock *bigMemHead) 304514f5e3Sopenharmony_ci{ 314514f5e3Sopenharmony_ci (void)(pool); 324514f5e3Sopenharmony_ci 334514f5e3Sopenharmony_ci MemBlock *fixedTail = nullptr; 344514f5e3Sopenharmony_ci 354514f5e3Sopenharmony_ci if (fixedMemHead != nullptr) { 364514f5e3Sopenharmony_ci fixedTail = fixedMemHead; 374514f5e3Sopenharmony_ci while (fixedTail->nextMemBlock != nullptr) { 384514f5e3Sopenharmony_ci fixedTail = fixedTail->nextMemBlock; 394514f5e3Sopenharmony_ci } 404514f5e3Sopenharmony_ci } 414514f5e3Sopenharmony_ci 424514f5e3Sopenharmony_ci while (bigMemHead != nullptr) { 434514f5e3Sopenharmony_ci auto *cur = bigMemHead; 444514f5e3Sopenharmony_ci bigMemHead = bigMemHead->nextMemBlock; 454514f5e3Sopenharmony_ci free(cur->startPtr); 464514f5e3Sopenharmony_ci delete cur; 474514f5e3Sopenharmony_ci } 484514f5e3Sopenharmony_ci 494514f5e3Sopenharmony_ci if (fixedTail != nullptr) { 504514f5e3Sopenharmony_ci fixedTail->nextMemBlock = fixedFreeMemBlocks; 514514f5e3Sopenharmony_ci DEBUG_ASSERT(fixedTail->nextMemBlock != fixedTail, "error"); 524514f5e3Sopenharmony_ci fixedFreeMemBlocks = fixedMemHead; 534514f5e3Sopenharmony_ci } 544514f5e3Sopenharmony_ci} 554514f5e3Sopenharmony_ci 564514f5e3Sopenharmony_ci// Destructor, free all allocated memories 574514f5e3Sopenharmony_ciMemPoolCtrler::~MemPoolCtrler() 584514f5e3Sopenharmony_ci{ 594514f5e3Sopenharmony_ci FreeMem(); 604514f5e3Sopenharmony_ci} 614514f5e3Sopenharmony_ci 624514f5e3Sopenharmony_civoid MemPoolCtrler::FreeFixedSizeMemBlockMemory() 634514f5e3Sopenharmony_ci{ 644514f5e3Sopenharmony_ci FreeMem(); 654514f5e3Sopenharmony_ci sysMemoryMgr->ReleaseMemory(); 664514f5e3Sopenharmony_ci} 674514f5e3Sopenharmony_ci 684514f5e3Sopenharmony_ci// Allocate a new memory pool and register it in controller 694514f5e3Sopenharmony_ciMemPool *MemPoolCtrler::NewMemPool(const std::string &name, bool isLocalPool) 704514f5e3Sopenharmony_ci{ 714514f5e3Sopenharmony_ci MemPool *memPool = nullptr; 724514f5e3Sopenharmony_ci 734514f5e3Sopenharmony_ci if (isLocalPool) { 744514f5e3Sopenharmony_ci memPool = new ThreadLocalMemPool(*this, name); 754514f5e3Sopenharmony_ci } else { 764514f5e3Sopenharmony_ci memPool = new ThreadShareMemPool(*this, name); 774514f5e3Sopenharmony_ci } 784514f5e3Sopenharmony_ci 794514f5e3Sopenharmony_ci return memPool; 804514f5e3Sopenharmony_ci} 814514f5e3Sopenharmony_ci 824514f5e3Sopenharmony_ci// This function will be removed soon, DO NOT call it, just use delete memPool 834514f5e3Sopenharmony_civoid MemPoolCtrler::DeleteMemPool(MemPool *memPool) const 844514f5e3Sopenharmony_ci{ 854514f5e3Sopenharmony_ci delete memPool; 864514f5e3Sopenharmony_ci} 874514f5e3Sopenharmony_ci 884514f5e3Sopenharmony_civoid MemPoolCtrler::FreeMem() 894514f5e3Sopenharmony_ci{ 904514f5e3Sopenharmony_ci while (fixedFreeMemBlocks != nullptr) { 914514f5e3Sopenharmony_ci MemBlock *arena = fixedFreeMemBlocks; 924514f5e3Sopenharmony_ci fixedFreeMemBlocks = fixedFreeMemBlocks->nextMemBlock; 934514f5e3Sopenharmony_ci delete arena; 944514f5e3Sopenharmony_ci } 954514f5e3Sopenharmony_ci} 964514f5e3Sopenharmony_ci 974514f5e3Sopenharmony_ciMemBlock *MemPoolCtrler::AllocMemBlock(const MemPool &pool, size_t size) 984514f5e3Sopenharmony_ci{ 994514f5e3Sopenharmony_ci if (size <= kMemBlockSizeMin) { 1004514f5e3Sopenharmony_ci return AllocFixMemBlock(pool); 1014514f5e3Sopenharmony_ci } else { 1024514f5e3Sopenharmony_ci return AllocBigMemBlock(pool, size); 1034514f5e3Sopenharmony_ci } 1044514f5e3Sopenharmony_ci} 1054514f5e3Sopenharmony_ci 1064514f5e3Sopenharmony_ciMemBlock *MemPoolCtrler::AllocFixMemBlock(const MemPool &pool) 1074514f5e3Sopenharmony_ci{ 1084514f5e3Sopenharmony_ci (void)(pool); 1094514f5e3Sopenharmony_ci MemBlock *ret = nullptr; 1104514f5e3Sopenharmony_ci 1114514f5e3Sopenharmony_ci if (fixedFreeMemBlocks != nullptr) { 1124514f5e3Sopenharmony_ci ret = fixedFreeMemBlocks; 1134514f5e3Sopenharmony_ci fixedFreeMemBlocks = fixedFreeMemBlocks->nextMemBlock; 1144514f5e3Sopenharmony_ci return ret; 1154514f5e3Sopenharmony_ci } 1164514f5e3Sopenharmony_ci 1174514f5e3Sopenharmony_ci uint8_t *ptr = sysMemoryMgr->RealAllocMemory(kMemBlockMalloc); 1184514f5e3Sopenharmony_ci // leave one MemBlock to return 1194514f5e3Sopenharmony_ci for (size_t i = 0; i < kMemBlockMalloc / kMemBlockSizeMin - 1; ++i) { 1204514f5e3Sopenharmony_ci auto *block = new MemBlock(ptr, kMemBlockSizeMin); 1214514f5e3Sopenharmony_ci ptr += kMemBlockSizeMin; 1224514f5e3Sopenharmony_ci block->nextMemBlock = fixedFreeMemBlocks; 1234514f5e3Sopenharmony_ci fixedFreeMemBlocks = block; 1244514f5e3Sopenharmony_ci } 1254514f5e3Sopenharmony_ci 1264514f5e3Sopenharmony_ci return new MemBlock(ptr, kMemBlockSizeMin); 1274514f5e3Sopenharmony_ci} 1284514f5e3Sopenharmony_ci 1294514f5e3Sopenharmony_ciMemBlock *MemPoolCtrler::AllocBigMemBlock(const MemPool &pool, size_t size) const 1304514f5e3Sopenharmony_ci{ 1314514f5e3Sopenharmony_ci DEBUG_ASSERT(size > kMemBlockSizeMin, "Big memory block must be bigger than fixed memory block"); 1324514f5e3Sopenharmony_ci (void)(pool); 1334514f5e3Sopenharmony_ci 1344514f5e3Sopenharmony_ci uint8_t *block = reinterpret_cast<uint8_t *>(malloc(size)); 1354514f5e3Sopenharmony_ci CHECK_FATAL(block != nullptr, "malloc failed"); 1364514f5e3Sopenharmony_ci return new MemBlock(block, size); 1374514f5e3Sopenharmony_ci} 1384514f5e3Sopenharmony_ci 1394514f5e3Sopenharmony_ciMemPool::~MemPool() 1404514f5e3Sopenharmony_ci{ 1414514f5e3Sopenharmony_ci ctrler.FreeMemBlocks(*this, fixedMemHead, bigMemHead); 1424514f5e3Sopenharmony_ci} 1434514f5e3Sopenharmony_ci 1444514f5e3Sopenharmony_civoid *MemPool::Malloc(size_t size) 1454514f5e3Sopenharmony_ci{ 1464514f5e3Sopenharmony_ci size = BITS_ALIGN(size); 1474514f5e3Sopenharmony_ci DEBUG_ASSERT(endPtr >= curPtr, "endPtr should >= curPtr"); 1484514f5e3Sopenharmony_ci if (size > static_cast<size_t>(endPtr - curPtr)) { 1494514f5e3Sopenharmony_ci return AllocNewMemBlock(size); 1504514f5e3Sopenharmony_ci } 1514514f5e3Sopenharmony_ci uint8_t *retPtr = curPtr; 1524514f5e3Sopenharmony_ci curPtr += size; 1534514f5e3Sopenharmony_ci return retPtr; 1544514f5e3Sopenharmony_ci} 1554514f5e3Sopenharmony_ci 1564514f5e3Sopenharmony_civoid MemPool::ReleaseContainingMem() 1574514f5e3Sopenharmony_ci{ 1584514f5e3Sopenharmony_ci ctrler.FreeMemBlocks(*this, fixedMemHead, bigMemHead); 1594514f5e3Sopenharmony_ci 1604514f5e3Sopenharmony_ci fixedMemHead = nullptr; 1614514f5e3Sopenharmony_ci bigMemHead = nullptr; 1624514f5e3Sopenharmony_ci endPtr = nullptr; 1634514f5e3Sopenharmony_ci curPtr = nullptr; 1644514f5e3Sopenharmony_ci} 1654514f5e3Sopenharmony_ci 1664514f5e3Sopenharmony_ci// Malloc size of memory from memory pool, then set 0 1674514f5e3Sopenharmony_civoid *MemPool::Calloc(size_t size) 1684514f5e3Sopenharmony_ci{ 1694514f5e3Sopenharmony_ci void *p = Malloc(BITS_ALIGN(size)); 1704514f5e3Sopenharmony_ci DEBUG_ASSERT(p != nullptr, "ERROR: Calloc error"); 1714514f5e3Sopenharmony_ci errno_t eNum = memset_s(p, BITS_ALIGN(size), 0, BITS_ALIGN(size)); 1724514f5e3Sopenharmony_ci CHECK_FATAL(eNum == EOK, "memset_s failed"); 1734514f5e3Sopenharmony_ci return p; 1744514f5e3Sopenharmony_ci} 1754514f5e3Sopenharmony_ci 1764514f5e3Sopenharmony_ci// Realloc new size of memory 1774514f5e3Sopenharmony_civoid *MemPool::Realloc(const void *ptr, size_t oldSize, size_t newSize) 1784514f5e3Sopenharmony_ci{ 1794514f5e3Sopenharmony_ci void *result = Malloc(newSize); 1804514f5e3Sopenharmony_ci DEBUG_ASSERT(result != nullptr, "ERROR: Realloc error"); 1814514f5e3Sopenharmony_ci size_t copySize = ((newSize > oldSize) ? oldSize : newSize); 1824514f5e3Sopenharmony_ci if (copySize != 0 && ptr != nullptr) { 1834514f5e3Sopenharmony_ci errno_t eNum = memcpy_s(result, copySize, ptr, copySize); 1844514f5e3Sopenharmony_ci CHECK_FATAL(eNum == EOK, "memcpy_s failed"); 1854514f5e3Sopenharmony_ci } 1864514f5e3Sopenharmony_ci return result; 1874514f5e3Sopenharmony_ci} 1884514f5e3Sopenharmony_ci 1894514f5e3Sopenharmony_ciuint8_t *MemPool::AllocNewMemBlock(size_t size) 1904514f5e3Sopenharmony_ci{ 1914514f5e3Sopenharmony_ci MemBlock **head = nullptr; 1924514f5e3Sopenharmony_ci MemBlock *newMemBlock = ctrler.AllocMemBlock(*this, size); 1934514f5e3Sopenharmony_ci if (newMemBlock->memSize <= kMemBlockSizeMin) { 1944514f5e3Sopenharmony_ci head = &fixedMemHead; 1954514f5e3Sopenharmony_ci } else { 1964514f5e3Sopenharmony_ci head = &bigMemHead; 1974514f5e3Sopenharmony_ci } 1984514f5e3Sopenharmony_ci 1994514f5e3Sopenharmony_ci newMemBlock->nextMemBlock = *head; 2004514f5e3Sopenharmony_ci *head = newMemBlock; 2014514f5e3Sopenharmony_ci CHECK_FATAL(newMemBlock->nextMemBlock != newMemBlock, "error"); 2024514f5e3Sopenharmony_ci 2034514f5e3Sopenharmony_ci curPtr = newMemBlock->startPtr + size; 2044514f5e3Sopenharmony_ci endPtr = newMemBlock->startPtr + newMemBlock->memSize; 2054514f5e3Sopenharmony_ci DEBUG_ASSERT(curPtr <= endPtr, "must be"); 2064514f5e3Sopenharmony_ci 2074514f5e3Sopenharmony_ci return newMemBlock->startPtr; 2084514f5e3Sopenharmony_ci} 2094514f5e3Sopenharmony_ci 2104514f5e3Sopenharmony_civoid *StackMemPool::Malloc(size_t size) 2114514f5e3Sopenharmony_ci{ 2124514f5e3Sopenharmony_ci size = BITS_ALIGN(size); 2134514f5e3Sopenharmony_ci uint8_t **curPtrPtr = nullptr; 2144514f5e3Sopenharmony_ci uint8_t *curEndPtr = nullptr; 2154514f5e3Sopenharmony_ci if (size <= kMemBlockSizeMin) { 2164514f5e3Sopenharmony_ci curPtrPtr = &curPtr; 2174514f5e3Sopenharmony_ci curEndPtr = endPtr; 2184514f5e3Sopenharmony_ci } else { 2194514f5e3Sopenharmony_ci curPtrPtr = &bigCurPtr; 2204514f5e3Sopenharmony_ci curEndPtr = bigEndPtr; 2214514f5e3Sopenharmony_ci } 2224514f5e3Sopenharmony_ci uint8_t *retPtr = *curPtrPtr; 2234514f5e3Sopenharmony_ci DEBUG_ASSERT(curEndPtr >= *curPtrPtr, "endPtr should >= curPtr"); 2244514f5e3Sopenharmony_ci if (size > static_cast<size_t>(curEndPtr - *curPtrPtr)) { 2254514f5e3Sopenharmony_ci retPtr = AllocTailMemBlock(size); 2264514f5e3Sopenharmony_ci } 2274514f5e3Sopenharmony_ci *curPtrPtr = retPtr + size; 2284514f5e3Sopenharmony_ci return retPtr; 2294514f5e3Sopenharmony_ci} 2304514f5e3Sopenharmony_ci 2314514f5e3Sopenharmony_ci// scoped mem pool don't use big mem block for small size, different with normal mempool 2324514f5e3Sopenharmony_ciMemBlock *StackMemPool::AllocMemBlockBySize(size_t size) 2334514f5e3Sopenharmony_ci{ 2344514f5e3Sopenharmony_ci if (size <= kMemBlockSizeMin) { 2354514f5e3Sopenharmony_ci return ctrler.AllocFixMemBlock(*this); 2364514f5e3Sopenharmony_ci } else { 2374514f5e3Sopenharmony_ci return ctrler.AllocBigMemBlock(*this, size); 2384514f5e3Sopenharmony_ci } 2394514f5e3Sopenharmony_ci} 2404514f5e3Sopenharmony_ci 2414514f5e3Sopenharmony_civoid StackMemPool::ResetStackTop(const LocalMapleAllocator *alloc, uint8_t *fixedCurPtrMark, 2424514f5e3Sopenharmony_ci MemBlock *fixedStackTopMark, uint8_t *bigCurPtrMark, 2434514f5e3Sopenharmony_ci MemBlock *bigStackTopMark) noexcept 2444514f5e3Sopenharmony_ci{ 2454514f5e3Sopenharmony_ci CheckTopAllocator(alloc); 2464514f5e3Sopenharmony_ci PopAllocator(); 2474514f5e3Sopenharmony_ci 2484514f5e3Sopenharmony_ci if (fixedStackTopMark != nullptr) { 2494514f5e3Sopenharmony_ci fixedMemStackTop = fixedStackTopMark; 2504514f5e3Sopenharmony_ci curPtr = fixedCurPtrMark; 2514514f5e3Sopenharmony_ci endPtr = fixedMemStackTop->EndPtr(); 2524514f5e3Sopenharmony_ci } else if (fixedMemHead != nullptr) { 2534514f5e3Sopenharmony_ci fixedMemStackTop = fixedMemHead; 2544514f5e3Sopenharmony_ci curPtr = fixedMemStackTop->startPtr; 2554514f5e3Sopenharmony_ci endPtr = fixedMemStackTop->EndPtr(); 2564514f5e3Sopenharmony_ci } 2574514f5e3Sopenharmony_ci 2584514f5e3Sopenharmony_ci if (bigStackTopMark != nullptr) { 2594514f5e3Sopenharmony_ci bigMemStackTop = bigStackTopMark; 2604514f5e3Sopenharmony_ci bigCurPtr = bigCurPtrMark; 2614514f5e3Sopenharmony_ci bigEndPtr = bigMemStackTop->EndPtr(); 2624514f5e3Sopenharmony_ci } else if (bigMemHead != nullptr) { 2634514f5e3Sopenharmony_ci bigMemStackTop = bigMemHead; 2644514f5e3Sopenharmony_ci bigCurPtr = bigMemStackTop->startPtr; 2654514f5e3Sopenharmony_ci bigEndPtr = bigMemStackTop->EndPtr(); 2664514f5e3Sopenharmony_ci } 2674514f5e3Sopenharmony_ci} 2684514f5e3Sopenharmony_ci 2694514f5e3Sopenharmony_ciuint8_t *StackMemPool::AllocTailMemBlock(size_t size) 2704514f5e3Sopenharmony_ci{ 2714514f5e3Sopenharmony_ci MemBlock **head = nullptr; 2724514f5e3Sopenharmony_ci MemBlock **stackTop = nullptr; 2734514f5e3Sopenharmony_ci uint8_t **endPtrPtr = nullptr; 2744514f5e3Sopenharmony_ci 2754514f5e3Sopenharmony_ci if (size <= kMemBlockSizeMin) { 2764514f5e3Sopenharmony_ci head = &fixedMemHead; 2774514f5e3Sopenharmony_ci stackTop = &fixedMemStackTop; 2784514f5e3Sopenharmony_ci endPtrPtr = &endPtr; 2794514f5e3Sopenharmony_ci } else { 2804514f5e3Sopenharmony_ci head = &bigMemHead; 2814514f5e3Sopenharmony_ci stackTop = &bigMemStackTop; 2824514f5e3Sopenharmony_ci endPtrPtr = &bigEndPtr; 2834514f5e3Sopenharmony_ci } 2844514f5e3Sopenharmony_ci 2854514f5e3Sopenharmony_ci if (*stackTop == nullptr) { 2864514f5e3Sopenharmony_ci MemBlock *newMemBlock = AllocMemBlockBySize(size); 2874514f5e3Sopenharmony_ci *stackTop = newMemBlock; 2884514f5e3Sopenharmony_ci *head = newMemBlock; 2894514f5e3Sopenharmony_ci (*stackTop)->nextMemBlock = nullptr; 2904514f5e3Sopenharmony_ci } else { 2914514f5e3Sopenharmony_ci if ((*stackTop)->nextMemBlock != nullptr && (*stackTop)->nextMemBlock->memSize >= size) { 2924514f5e3Sopenharmony_ci *stackTop = (*stackTop)->nextMemBlock; 2934514f5e3Sopenharmony_ci } else { 2944514f5e3Sopenharmony_ci MemBlock *newMemBlock = AllocMemBlockBySize(size); 2954514f5e3Sopenharmony_ci auto *tmp = (*stackTop)->nextMemBlock; 2964514f5e3Sopenharmony_ci (*stackTop)->nextMemBlock = newMemBlock; 2974514f5e3Sopenharmony_ci *stackTop = newMemBlock; 2984514f5e3Sopenharmony_ci newMemBlock->nextMemBlock = tmp; 2994514f5e3Sopenharmony_ci } 3004514f5e3Sopenharmony_ci } 3014514f5e3Sopenharmony_ci *endPtrPtr = (*stackTop)->EndPtr(); 3024514f5e3Sopenharmony_ci return (*stackTop)->startPtr; 3034514f5e3Sopenharmony_ci} 3044514f5e3Sopenharmony_ci} // namespace maple 305