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