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#ifndef MEMPOOL_INCLUDE_MEMPOOL_H 174514f5e3Sopenharmony_ci#define MEMPOOL_INCLUDE_MEMPOOL_H 184514f5e3Sopenharmony_ci#include <list> 194514f5e3Sopenharmony_ci#include <set> 204514f5e3Sopenharmony_ci#include <forward_list> 214514f5e3Sopenharmony_ci#include <unordered_set> 224514f5e3Sopenharmony_ci#include <stack> 234514f5e3Sopenharmony_ci#include <map> 244514f5e3Sopenharmony_ci#include <string> 254514f5e3Sopenharmony_ci#include <mutex> 264514f5e3Sopenharmony_ci#include <memory> 274514f5e3Sopenharmony_ci#include "mir_config.h" 284514f5e3Sopenharmony_ci#include "mpl_logging.h" 294514f5e3Sopenharmony_ci 304514f5e3Sopenharmony_cinamespace maple { 314514f5e3Sopenharmony_ci#define BITS_ALIGN(size) (((size) + 7) & (0xFFFFFFF8)) 324514f5e3Sopenharmony_ci 334514f5e3Sopenharmony_ciconstexpr size_t kMemBlockSizeMin = 2 * 1024; 344514f5e3Sopenharmony_ciconstexpr size_t kMemBlockMalloc = 1024 * 1024; 354514f5e3Sopenharmony_cistatic_assert((kMemBlockMalloc > kMemBlockSizeMin) && ((kMemBlockMalloc % kMemBlockSizeMin) == 0), "mempool error"); 364514f5e3Sopenharmony_ci 374514f5e3Sopenharmony_cistruct MemBlock { 384514f5e3Sopenharmony_ci MemBlock(uint8_t *startPtr, size_t size) : startPtr(startPtr), memSize(size) {} 394514f5e3Sopenharmony_ci ~MemBlock() = default; 404514f5e3Sopenharmony_ci 414514f5e3Sopenharmony_ci uint8_t *EndPtr() const 424514f5e3Sopenharmony_ci { 434514f5e3Sopenharmony_ci return startPtr + memSize; 444514f5e3Sopenharmony_ci } 454514f5e3Sopenharmony_ci 464514f5e3Sopenharmony_ci uint8_t *startPtr = nullptr; 474514f5e3Sopenharmony_ci size_t memSize = 0; 484514f5e3Sopenharmony_ci MemBlock *nextMemBlock = nullptr; 494514f5e3Sopenharmony_ci}; 504514f5e3Sopenharmony_ci 514514f5e3Sopenharmony_ci// Class declaration 524514f5e3Sopenharmony_ciclass MemPool; 534514f5e3Sopenharmony_ciclass StackMemPool; 544514f5e3Sopenharmony_ciclass MemPoolCtrler; 554514f5e3Sopenharmony_ciextern MemPoolCtrler memPoolCtrler; 564514f5e3Sopenharmony_ci 574514f5e3Sopenharmony_ci// memory backend 584514f5e3Sopenharmony_ciclass SysMemoryManager { 594514f5e3Sopenharmony_cipublic: 604514f5e3Sopenharmony_ci virtual ~SysMemoryManager() = default; 614514f5e3Sopenharmony_ci virtual uint8_t *RealAllocMemory(size_t size) = 0; 624514f5e3Sopenharmony_ci virtual void ReleaseMemory() = 0; 634514f5e3Sopenharmony_ci}; 644514f5e3Sopenharmony_ci 654514f5e3Sopenharmony_ciclass MallocSysMemoryManager : public SysMemoryManager { 664514f5e3Sopenharmony_cipublic: 674514f5e3Sopenharmony_ci uint8_t *RealAllocMemory(size_t size) override 684514f5e3Sopenharmony_ci { 694514f5e3Sopenharmony_ci if (size == 0) { 704514f5e3Sopenharmony_ci return nullptr; 714514f5e3Sopenharmony_ci } 724514f5e3Sopenharmony_ci void *block = malloc(size); 734514f5e3Sopenharmony_ci CHECK_FATAL(block != nullptr, "malloc failed"); 744514f5e3Sopenharmony_ci 754514f5e3Sopenharmony_ci mallocMemories.push_front(block); 764514f5e3Sopenharmony_ci return reinterpret_cast<uint8_t *>(block); 774514f5e3Sopenharmony_ci } 784514f5e3Sopenharmony_ci ~MallocSysMemoryManager() override 794514f5e3Sopenharmony_ci { 804514f5e3Sopenharmony_ci for (void *ptr : mallocMemories) { 814514f5e3Sopenharmony_ci free(ptr); 824514f5e3Sopenharmony_ci } 834514f5e3Sopenharmony_ci mallocMemories.clear(); 844514f5e3Sopenharmony_ci } 854514f5e3Sopenharmony_ci void ReleaseMemory() override 864514f5e3Sopenharmony_ci { 874514f5e3Sopenharmony_ci for (void *ptr : mallocMemories) { 884514f5e3Sopenharmony_ci free(ptr); 894514f5e3Sopenharmony_ci } 904514f5e3Sopenharmony_ci mallocMemories.clear(); 914514f5e3Sopenharmony_ci } 924514f5e3Sopenharmony_ci std::forward_list<void *> mallocMemories; 934514f5e3Sopenharmony_ci}; 944514f5e3Sopenharmony_ci 954514f5e3Sopenharmony_ci// memory middle end 964514f5e3Sopenharmony_ciclass MemPoolCtrler { 974514f5e3Sopenharmony_ci friend MemPool; 984514f5e3Sopenharmony_ci 994514f5e3Sopenharmony_cipublic: 1004514f5e3Sopenharmony_ci static bool freeMemInTime; 1014514f5e3Sopenharmony_ci MemPoolCtrler() : sysMemoryMgr(new MallocSysMemoryManager()) {} 1024514f5e3Sopenharmony_ci 1034514f5e3Sopenharmony_ci ~MemPoolCtrler(); 1044514f5e3Sopenharmony_ci 1054514f5e3Sopenharmony_ci MemPool *NewMemPool(const std::string &, bool isLocalPool); 1064514f5e3Sopenharmony_ci void DeleteMemPool(MemPool *memPool) const; 1074514f5e3Sopenharmony_ci 1084514f5e3Sopenharmony_ci MemBlock *AllocMemBlock(const MemPool &pool, size_t size); 1094514f5e3Sopenharmony_ci MemBlock *AllocFixMemBlock(const MemPool &pool); 1104514f5e3Sopenharmony_ci MemBlock *AllocBigMemBlock(const MemPool &pool, size_t size) const; 1114514f5e3Sopenharmony_ci void FreeFixedSizeMemBlockMemory(); 1124514f5e3Sopenharmony_ci 1134514f5e3Sopenharmony_ciprivate: 1144514f5e3Sopenharmony_ci struct MemBlockCmp { 1154514f5e3Sopenharmony_ci bool operator()(const MemBlock *l, const MemBlock *r) const 1164514f5e3Sopenharmony_ci { 1174514f5e3Sopenharmony_ci return l->memSize > r->memSize; 1184514f5e3Sopenharmony_ci } 1194514f5e3Sopenharmony_ci }; 1204514f5e3Sopenharmony_ci 1214514f5e3Sopenharmony_ci void FreeMem(); 1224514f5e3Sopenharmony_ci void FreeMemBlocks(const MemPool &pool, MemBlock *fixedMemHead, MemBlock *bigMemHead); 1234514f5e3Sopenharmony_ci 1244514f5e3Sopenharmony_ci std::mutex ctrlerMutex; // this mutex is used to protect memPools 1254514f5e3Sopenharmony_ci MemBlock *fixedFreeMemBlocks = nullptr; 1264514f5e3Sopenharmony_ci std::unique_ptr<SysMemoryManager> sysMemoryMgr; 1274514f5e3Sopenharmony_ci}; 1284514f5e3Sopenharmony_ci 1294514f5e3Sopenharmony_ci#ifdef MP_DEUG 1304514f5e3Sopenharmony_ciclass MemPoolStat { 1314514f5e3Sopenharmony_cipublic: 1324514f5e3Sopenharmony_ci ~MemPoolStat() = default; 1334514f5e3Sopenharmony_ci 1344514f5e3Sopenharmony_ciprotected: 1354514f5e3Sopenharmony_ci void SetName(const std::string &name) 1364514f5e3Sopenharmony_ci { 1374514f5e3Sopenharmony_ci this->name = name; 1384514f5e3Sopenharmony_ci } 1394514f5e3Sopenharmony_ci void SetName(const char *name) 1404514f5e3Sopenharmony_ci { 1414514f5e3Sopenharmony_ci this->name = name; 1424514f5e3Sopenharmony_ci } 1434514f5e3Sopenharmony_ci std::string name; 1444514f5e3Sopenharmony_ci}; 1454514f5e3Sopenharmony_ci#else 1464514f5e3Sopenharmony_ciclass MemPoolStat { 1474514f5e3Sopenharmony_cipublic: 1484514f5e3Sopenharmony_ci virtual ~MemPoolStat() = default; 1494514f5e3Sopenharmony_ci 1504514f5e3Sopenharmony_ciprotected: 1514514f5e3Sopenharmony_ci void SetName(const std::string & /* name */) const {} 1524514f5e3Sopenharmony_ci void SetName(const char /* name */) const {} 1534514f5e3Sopenharmony_ci}; 1544514f5e3Sopenharmony_ci#endif 1554514f5e3Sopenharmony_ci 1564514f5e3Sopenharmony_ci// memory front end 1574514f5e3Sopenharmony_ciclass MemPool : private MemPoolStat { 1584514f5e3Sopenharmony_ci friend MemPoolCtrler; 1594514f5e3Sopenharmony_ci 1604514f5e3Sopenharmony_cipublic: 1614514f5e3Sopenharmony_ci MemPool(MemPoolCtrler &ctl, const std::string &name) : ctrler(ctl) 1624514f5e3Sopenharmony_ci { 1634514f5e3Sopenharmony_ci SetName(name); 1644514f5e3Sopenharmony_ci } 1654514f5e3Sopenharmony_ci MemPool(MemPoolCtrler &ctl, const char *name) : ctrler(ctl) 1664514f5e3Sopenharmony_ci { 1674514f5e3Sopenharmony_ci SetName(name); 1684514f5e3Sopenharmony_ci } 1694514f5e3Sopenharmony_ci 1704514f5e3Sopenharmony_ci ~MemPool(); 1714514f5e3Sopenharmony_ci 1724514f5e3Sopenharmony_ci virtual void *Malloc(size_t size); 1734514f5e3Sopenharmony_ci void *Calloc(size_t size); 1744514f5e3Sopenharmony_ci void *Realloc(const void *ptr, size_t oldSize, size_t newSize); 1754514f5e3Sopenharmony_ci virtual void ReleaseContainingMem(); 1764514f5e3Sopenharmony_ci 1774514f5e3Sopenharmony_ci MemPoolCtrler &GetCtrler() 1784514f5e3Sopenharmony_ci { 1794514f5e3Sopenharmony_ci return ctrler; 1804514f5e3Sopenharmony_ci } 1814514f5e3Sopenharmony_ci 1824514f5e3Sopenharmony_ci const MemPoolCtrler &GetCtrler() const 1834514f5e3Sopenharmony_ci { 1844514f5e3Sopenharmony_ci return ctrler; 1854514f5e3Sopenharmony_ci } 1864514f5e3Sopenharmony_ci 1874514f5e3Sopenharmony_ci template <class T> 1884514f5e3Sopenharmony_ci T *Clone(const T &t) 1894514f5e3Sopenharmony_ci { 1904514f5e3Sopenharmony_ci void *p = Malloc(sizeof(T)); 1914514f5e3Sopenharmony_ci DEBUG_ASSERT(p != nullptr, "ERROR: New error"); 1924514f5e3Sopenharmony_ci p = new (p) T(t); 1934514f5e3Sopenharmony_ci return static_cast<T *>(p); 1944514f5e3Sopenharmony_ci } 1954514f5e3Sopenharmony_ci 1964514f5e3Sopenharmony_ci template <class T, typename... Arguments> 1974514f5e3Sopenharmony_ci T *New(Arguments &&... args) 1984514f5e3Sopenharmony_ci { 1994514f5e3Sopenharmony_ci void *p = Malloc(sizeof(T)); 2004514f5e3Sopenharmony_ci DEBUG_ASSERT(p != nullptr, "ERROR: New error"); 2014514f5e3Sopenharmony_ci p = new (p) T(std::forward<Arguments>(args)...); 2024514f5e3Sopenharmony_ci return static_cast<T *>(p); 2034514f5e3Sopenharmony_ci } 2044514f5e3Sopenharmony_ci 2054514f5e3Sopenharmony_ci template <class T> 2064514f5e3Sopenharmony_ci T *NewArray(size_t num) 2074514f5e3Sopenharmony_ci { 2084514f5e3Sopenharmony_ci void *p = Malloc(sizeof(T) * num); 2094514f5e3Sopenharmony_ci DEBUG_ASSERT(p != nullptr, "ERROR: NewArray error"); 2104514f5e3Sopenharmony_ci p = new (p) T[num]; 2114514f5e3Sopenharmony_ci return static_cast<T *>(p); 2124514f5e3Sopenharmony_ci } 2134514f5e3Sopenharmony_ci 2144514f5e3Sopenharmony_ciprotected: 2154514f5e3Sopenharmony_ci MemPoolCtrler &ctrler; // Hookup controller object 2164514f5e3Sopenharmony_ci uint8_t *endPtr = nullptr; 2174514f5e3Sopenharmony_ci uint8_t *curPtr = nullptr; 2184514f5e3Sopenharmony_ci MemBlock *fixedMemHead = nullptr; 2194514f5e3Sopenharmony_ci MemBlock *bigMemHead = nullptr; 2204514f5e3Sopenharmony_ci 2214514f5e3Sopenharmony_ci uint8_t *AllocNewMemBlock(size_t bytes); 2224514f5e3Sopenharmony_ci}; 2234514f5e3Sopenharmony_ci 2244514f5e3Sopenharmony_ciusing ThreadLocalMemPool = MemPool; 2254514f5e3Sopenharmony_ci 2264514f5e3Sopenharmony_ciclass ThreadShareMemPool : public MemPool { 2274514f5e3Sopenharmony_cipublic: 2284514f5e3Sopenharmony_ci using MemPool::MemPool; 2294514f5e3Sopenharmony_ci virtual ~ThreadShareMemPool() = default; 2304514f5e3Sopenharmony_ci void *Malloc(size_t size) override 2314514f5e3Sopenharmony_ci { 2324514f5e3Sopenharmony_ci return MemPool::Malloc(size); 2334514f5e3Sopenharmony_ci } 2344514f5e3Sopenharmony_ci void ReleaseContainingMem() override 2354514f5e3Sopenharmony_ci { 2364514f5e3Sopenharmony_ci MemPool::ReleaseContainingMem(); 2374514f5e3Sopenharmony_ci } 2384514f5e3Sopenharmony_ci}; 2394514f5e3Sopenharmony_ci 2404514f5e3Sopenharmony_ciclass LocalMapleAllocator; 2414514f5e3Sopenharmony_ci#ifdef MP_DEBUG 2424514f5e3Sopenharmony_ciclass StackMemPoolDebug { 2434514f5e3Sopenharmony_ciprotected: 2444514f5e3Sopenharmony_ci void PushAllocator(const LocalMapleAllocator *alloc) 2454514f5e3Sopenharmony_ci { 2464514f5e3Sopenharmony_ci allocators.push(alloc); 2474514f5e3Sopenharmony_ci } 2484514f5e3Sopenharmony_ci void CheckTopAllocator(const LocalMapleAllocator *alloc) const 2494514f5e3Sopenharmony_ci { 2504514f5e3Sopenharmony_ci CHECK_FATAL(alloc == allocators.top(), "only top allocator allowed"); 2514514f5e3Sopenharmony_ci } 2524514f5e3Sopenharmony_ci void PopAllocator() 2534514f5e3Sopenharmony_ci { 2544514f5e3Sopenharmony_ci allocators.pop(); 2554514f5e3Sopenharmony_ci } 2564514f5e3Sopenharmony_ci std::stack<const LocalMapleAllocator *> allocators; 2574514f5e3Sopenharmony_ci}; 2584514f5e3Sopenharmony_ci#else 2594514f5e3Sopenharmony_ciclass StackMemPoolDebug { 2604514f5e3Sopenharmony_ciprotected: 2614514f5e3Sopenharmony_ci void PushAllocator(const LocalMapleAllocator * /* alloc */) const {} 2624514f5e3Sopenharmony_ci void PopAllocator() const {} 2634514f5e3Sopenharmony_ci void CheckTopAllocator(const LocalMapleAllocator * /* alloc */) const {} 2644514f5e3Sopenharmony_ci}; 2654514f5e3Sopenharmony_ci#endif 2664514f5e3Sopenharmony_ci 2674514f5e3Sopenharmony_ciclass StackMemPool : public MemPool, private StackMemPoolDebug { 2684514f5e3Sopenharmony_cipublic: 2694514f5e3Sopenharmony_ci using MemPool::MemPool; 2704514f5e3Sopenharmony_ci friend LocalMapleAllocator; 2714514f5e3Sopenharmony_ci 2724514f5e3Sopenharmony_ciprivate: 2734514f5e3Sopenharmony_ci // all malloc requested from LocalMapleAllocator 2744514f5e3Sopenharmony_ci void *Malloc(size_t size) override; 2754514f5e3Sopenharmony_ci uint8_t *AllocTailMemBlock(size_t size); 2764514f5e3Sopenharmony_ci 2774514f5e3Sopenharmony_ci // these methods should be called from LocalMapleAllocator 2784514f5e3Sopenharmony_ci template <class T> 2794514f5e3Sopenharmony_ci T *Clone(const T &t) = delete; 2804514f5e3Sopenharmony_ci 2814514f5e3Sopenharmony_ci template <class T, typename... Arguments> 2824514f5e3Sopenharmony_ci T *New(Arguments &&... args) = delete; 2834514f5e3Sopenharmony_ci 2844514f5e3Sopenharmony_ci template <class T> 2854514f5e3Sopenharmony_ci T *NewArray(size_t num) = delete; 2864514f5e3Sopenharmony_ci 2874514f5e3Sopenharmony_ci // reuse mempool fixedMemHead, bigMemHead, (curPtr, endPtr for fixed memory) 2884514f5e3Sopenharmony_ci MemBlock *fixedMemStackTop = nullptr; 2894514f5e3Sopenharmony_ci MemBlock *bigMemStackTop = nullptr; 2904514f5e3Sopenharmony_ci uint8_t *bigCurPtr = nullptr; 2914514f5e3Sopenharmony_ci uint8_t *bigEndPtr = nullptr; 2924514f5e3Sopenharmony_ci MemBlock *AllocMemBlockBySize(size_t size); 2934514f5e3Sopenharmony_ci void ResetStackTop(const LocalMapleAllocator *alloc, uint8_t *fixedCurPtrMark, MemBlock *fixedStackTopMark, 2944514f5e3Sopenharmony_ci uint8_t *bigCurPtrMark, MemBlock *bigStackTopMark) noexcept; 2954514f5e3Sopenharmony_ci}; 2964514f5e3Sopenharmony_ci} // namespace maple 2974514f5e3Sopenharmony_ci#endif // MEMPOOL_INCLUDE_MEMPOOL_H 298