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