• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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 #ifndef PANDA_LIBPANDABASE_MEM_STACK_LIKE_ALLOCATOR_INL_H
16 #define PANDA_LIBPANDABASE_MEM_STACK_LIKE_ALLOCATOR_INL_H
17 
18 #include <securec.h>
19 #include "libpandabase/mem/stack_like_allocator.h"
20 #include "libpandabase/utils/logger.h"
21 #include "libpandabase/utils/asan_interface.h"
22 
23 namespace ark::mem {
24 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
25 #define LOG_STACK_LIKE_ALLOCATOR(level) LOG(level, ALLOC) << "StackLikeAllocator: "
26 
27 template <Alignment ALIGNMENT, size_t MAX_SIZE>
28 // CC-OFFNXT(G.FUD.06) Splitting this function will degrade readability. Keyword "inline" needs to satisfy ODR rule.
StackLikeAllocator(bool usePoolManager,SpaceType spaceType)29 inline StackLikeAllocator<ALIGNMENT, MAX_SIZE>::StackLikeAllocator(bool usePoolManager, SpaceType spaceType)
30     : usePoolManager_(usePoolManager)
31 {
32     LOG_STACK_LIKE_ALLOCATOR(DEBUG) << "Initializing of StackLikeAllocator";
33     ASSERT(RELEASE_PAGES_SIZE == AlignUp(RELEASE_PAGES_SIZE, os::mem::GetPageSize()));
34     // MMAP!
35     if (usePoolManager_) {
36         // clang-format off
37         startAddr_ = PoolManager::GetMmapMemPool()
38             ->AllocPool(MAX_SIZE, spaceType, AllocatorType::STACK_LIKE_ALLOCATOR, this).GetMem();
39         // clang-format on
40     } else {
41         startAddr_ = ark::os::mem::MapRWAnonymousWithAlignmentRaw(
42             MAX_SIZE, std::max(GetAlignmentInBytes(ALIGNMENT), static_cast<size_t>(ark::os::mem::GetPageSize())));
43     }
44     if (startAddr_ == nullptr) {
45         LOG_STACK_LIKE_ALLOCATOR(FATAL) << "Can't get initial memory";
46     }
47     freePointer_ = startAddr_;
48     endAddr_ = ToVoidPtr(ToUintPtr(startAddr_) + MAX_SIZE);
49     allocatedEndAddr_ = endAddr_;
50     ASSERT(AlignUp(ToUintPtr(freePointer_), GetAlignmentInBytes(ALIGNMENT)) == ToUintPtr(freePointer_));
51     LOG_STACK_LIKE_ALLOCATOR(DEBUG) << "Initializing of StackLikeAllocator finished";
52 }
53 
54 template <Alignment ALIGNMENT, size_t MAX_SIZE>
~StackLikeAllocator()55 inline StackLikeAllocator<ALIGNMENT, MAX_SIZE>::~StackLikeAllocator()
56 {
57     LOG_STACK_LIKE_ALLOCATOR(DEBUG) << "Destroying of StackLikeAllocator";
58     if (usePoolManager_) {
59         PoolManager::GetMmapMemPool()->FreePool(startAddr_, MAX_SIZE);
60     } else {
61         ark::os::mem::UnmapRaw(startAddr_, MAX_SIZE);
62     }
63     LOG_STACK_LIKE_ALLOCATOR(DEBUG) << "Destroying of StackLikeAllocator finished";
64 }
65 
66 template <Alignment ALIGNMENT, size_t MAX_SIZE>
67 template <bool USE_MEMSET>
68 // CC-OFFNXT(G.FUD.06) perf critical, ODR
Alloc(size_t size)69 inline void *StackLikeAllocator<ALIGNMENT, MAX_SIZE>::Alloc(size_t size)
70 {
71     ASSERT(AlignUp(size, GetAlignmentInBytes(ALIGNMENT)) == size);
72 
73     void *ret = nullptr;
74     uintptr_t newCurPos = ToUintPtr(freePointer_) + size;
75     if (LIKELY(newCurPos <= ToUintPtr(endAddr_))) {
76         ret = freePointer_;
77         freePointer_ = ToVoidPtr(newCurPos);
78         ASAN_UNPOISON_MEMORY_REGION(ret, size);
79     } else {
80         return nullptr;
81     }
82 
83     ASSERT(AlignUp(ToUintPtr(ret), GetAlignmentInBytes(ALIGNMENT)) == ToUintPtr(ret));
84     // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon)
85     if constexpr (USE_MEMSET) {
86         memset_s(ret, size, 0x00, size);
87     }
88     LOG_STACK_LIKE_ALLOCATOR(DEBUG) << "Allocated memory at addr " << std::hex << ret;
89     return ret;
90 }
91 
92 template <Alignment ALIGNMENT, size_t MAX_SIZE>
93 // CC-OFFNXT(G.FUD.06) perf critical, ODR
Free(void * mem)94 inline void StackLikeAllocator<ALIGNMENT, MAX_SIZE>::Free(void *mem)
95 {
96     ASSERT(ToUintPtr(mem) == AlignUp(ToUintPtr(mem), GetAlignmentInBytes(ALIGNMENT)));
97     ASSERT(Contains(mem));
98     if ((ToUintPtr(mem) >> RELEASE_PAGES_SHIFT) != (ToUintPtr(freePointer_) >> RELEASE_PAGES_SHIFT)) {
99         // Start address from which we can release pages
100         uintptr_t startAddr = AlignUp(ToUintPtr(mem), RELEASE_PAGES_SIZE);
101         // We do page release calls each RELEASE_PAGES_SIZE interval,
102         // Therefore, we should clear the last RELEASE_PAGES_SIZE interval
103         uintptr_t endAddr = AlignUp(ToUintPtr(freePointer_), RELEASE_PAGES_SIZE);
104         os::mem::ReleasePages(startAddr, endAddr);
105         LOG_STACK_LIKE_ALLOCATOR(DEBUG) << "Release " << std::dec << endAddr - startAddr
106                                         << " memory bytes in interval [" << std::hex << startAddr << "; " << endAddr
107                                         << "]";
108     }
109     ASAN_POISON_MEMORY_REGION(mem, ToUintPtr(freePointer_) - ToUintPtr(mem));
110     freePointer_ = mem;
111     LOG_STACK_LIKE_ALLOCATOR(DEBUG) << "Free memory at addr " << std::hex << mem;
112 }
113 
114 template <Alignment ALIGNMENT, size_t MAX_SIZE>
Contains(void * mem)115 inline bool StackLikeAllocator<ALIGNMENT, MAX_SIZE>::Contains(void *mem)
116 {
117     return (ToUintPtr(mem) >= ToUintPtr(startAddr_)) && (ToUintPtr(mem) < ToUintPtr(freePointer_));
118 }
119 
120 #undef LOG_STACK_LIKE_ALLOCATOR
121 }  // namespace ark::mem
122 
123 #endif  // PANDA_LIBPANDABASE_MEM_STACK_LIKE_ALLOCATOR_INL_H
124