• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 PANDA_RUNTIME_MEM_INTERNAL_ALLOCATOR_H_
17 #define PANDA_RUNTIME_MEM_INTERNAL_ALLOCATOR_H_
18 
19 #include <vector>
20 
21 #include "libpandabase/concepts.h"
22 #include "libpandabase/mem/mmap_mem_pool-inl.h"
23 #include "libpandabase/mem/pool_manager.h"
24 #include "libpandabase/os/mutex.h"
25 #include "runtime/mem/freelist_allocator.h"
26 #include "runtime/mem/humongous_obj_allocator.h"
27 #include "runtime/mem/runslots_allocator.h"
28 
29 #ifdef TRACK_INTERNAL_ALLOCATIONS
30 #include "libpandabase/mem/alloc_tracker.h"
31 #endif  // TRACK_INTERNAL_ALLOCATIONS
32 
33 namespace panda::mem {
34 
35 namespace test {
36 class InternalAllocatorTest;
37 }  // namespace test
38 
39 template <typename AllocConfigT>
40 class MallocProxyAllocator;
41 class Allocator;
42 
43 enum class AllocScope {
44     GLOBAL,  // The allocation will be in global storage
45     LOCAL    // The allocation will be in thread-local storage
46 };
47 
48 enum class InternalAllocatorConfig {
49     PANDA_ALLOCATORS,  // Use panda allocators as internal allocator
50     MALLOC_ALLOCATOR   // Use malloc allocator as internal allocator
51 };
52 
53 class RawMemoryConfig;
54 class EmptyMemoryConfig;
55 
56 template <InternalAllocatorConfig Config = InternalAllocatorConfig::PANDA_ALLOCATORS>
57 class InternalAllocator {
58 public:
59     explicit InternalAllocator(MemStatsType *mem_stats);
60 
61     NO_COPY_SEMANTIC(InternalAllocator);
62     NO_MOVE_SEMANTIC(InternalAllocator);
63 
64     template <AllocScope AllocScopeT = AllocScope::GLOBAL>
65     [[nodiscard]] void *Alloc(size_t size, Alignment align = DEFAULT_ALIGNMENT);
66 
67     [[nodiscard]] void *AllocLocal(size_t size, Alignment align = DEFAULT_ALIGNMENT)
68     {
69         return Alloc<AllocScope::LOCAL>(size, align);
70     }
71 
72     template <class T>
73     [[nodiscard]] T *AllocArray(size_t size);
74 
75     template <typename T, typename... Args>
76     [[nodiscard]] std::enable_if_t<!std::is_array_v<T>, T *> New(Args &&... args);
77 
78     template <typename T>
79     [[nodiscard]] std::enable_if_t<is_unbounded_array_v<T>, std::remove_extent_t<T> *> New(size_t size);
80 
81     template <typename T>
82     void DeleteArray(T *data);
83 
84     void Free(void *ptr);
85 
86 #ifdef TRACK_INTERNAL_ALLOCATIONS
Dump()87     void Dump()
88     {
89         tracker_->Dump();
90     }
91 #endif  // TRACK_INTERNAL_ALLOCATIONS
92 
93     template <class T>
94     void Delete(T *ptr);
95 
96     ~InternalAllocator();
97 
98     /**
99      * \brief Iterates over memory pools used by this allocator.
100      * @tparam MemVisitor
101      * @param mem_visitor - function pointer or functor
102      */
103     template <typename MemVisitor>
104     void VisitAndRemoveAllPools(MemVisitor mem_visitor);
105 
106     /**
107      * \brief Visit memory pools that can be returned to the system in this allocator
108      * and remove them from the allocator structure.
109      * @tparam MemVisitor
110      * @param mem_visitor - function pointer or functor
111      */
112     template <typename MemVisitor>
113     void VisitAndRemoveFreePools(MemVisitor mem_visitor);
114 
115 #ifdef NDEBUG
116     using InternalAllocConfigT = EmptyMemoryConfig;
117 #else
118     using InternalAllocConfigT = RawMemoryConfig;
119 #endif
120     using LocalSmallObjectAllocator = RunSlotsAllocator<InternalAllocConfigT, RunSlotsAllocatorLockConfig::DummyLock>;
121 
122     /**
123      * \brief Create and set up local internal allocator instance for fast small objects allocation
124      * @param allocator - a pointer to the allocator which will be used for local allocator instance storage
125      * @return - a pointer to the local internal allocator instance
126      */
127     static InternalAllocator::LocalSmallObjectAllocator *SetUpLocalInternalAllocator(Allocator *allocator);
128 
129     /**
130      * \brief Delete local internal allocator instance and return all pools to the system
131      * @param allocator - a pointer to the allocator which was used for local allocator instance storage
132      * @param local_allocator - a pointer to the local internal allocator instance
133      */
134     static void FinalizeLocalInternalAllocator(LocalSmallObjectAllocator *local_allocator, Allocator *allocator);
135 
136     /**
137      * \brief Return free memory pools to the system in local internal allocator
138      * and remove them from the allocator structure.
139      * @param local_allocator - a pointer to a local internal allocator instance
140      */
141     static void RemoveFreePoolsForLocalInternalAllocator(LocalSmallObjectAllocator *local_allocator);
142 
143     static void InitInternalAllocatorFromRuntime(Allocator *allocator);
144 
145     static Allocator *GetInternalAllocatorFromRuntime();
146 
147     static void ClearInternalAllocatorFromRuntime();
148 
149 private:
150 #ifdef TRACK_INTERNAL_ALLOCATIONS
151     os::memory::Mutex lock_;
152     MemStatsType *mem_stats_;
153     AllocTracker *tracker_ = nullptr;
154 #endif  // TRACK_INTERNAL_ALLOCATIONS
155 
156     using RunSlotsAllocatorT = RunSlotsAllocator<InternalAllocConfigT>;
157     using FreeListAllocatorT = FreeListAllocator<InternalAllocConfigT>;
158     using HumongousObjAllocatorT = HumongousObjAllocator<InternalAllocConfigT>;
159     using MallocProxyAllocatorT = MallocProxyAllocator<InternalAllocConfigT>;
160     template <AllocScope AllocScopeT>
161     void *AllocViaPandaAllocators(size_t size, Alignment align);
162     void FreeViaPandaAllocators(void *ptr);
163     RunSlotsAllocatorT *runslots_allocator_ {nullptr};
164     FreeListAllocatorT *freelist_allocator_ {nullptr};
165     HumongousObjAllocatorT *humongous_allocator_ {nullptr};
166     MallocProxyAllocatorT *malloc_allocator_ {nullptr};
167     static Allocator *allocator_from_runtime;
168 
169     friend class test::InternalAllocatorTest;
170 };
171 
172 }  // namespace panda::mem
173 
174 #endif  // PANDA_RUNTIME_MEM_INTERNAL_ALLOCATOR_H_
175