1 /*
2 * Copyright (c) 2021-2022 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 LIBPANDABASE_MEM_ARENA_INL_H
17 #define LIBPANDABASE_MEM_ARENA_INL_H
18
19 #include <memory>
20 #include "arena.h"
21 #include "macros.h"
22 #include "utils/logger.h"
23 #include "utils/asan_interface.h"
24
25 namespace panda {
26
Arena(size_t buff_size,void * buff)27 inline Arena::Arena(size_t buff_size, void *buff) : Arena(buff_size, buff, ARENA_DEFAULT_ALIGNMENT) {}
28
Arena(size_t buff_size,void * buff,Alignment start_alignment)29 inline Arena::Arena(size_t buff_size, void *buff, Alignment start_alignment)
30 : buff_(buff),
31 startPos_(ToVoidPtr(AlignUp(ToUintPtr(buff), GetAlignmentInBytes(start_alignment)))),
32 curPos_(startPos_),
33 size_(buff_size)
34 {
35 ASSERT(ToUintPtr(buff) == AlignUp(ToUintPtr(buff), GetAlignmentInBytes(ARENA_DEFAULT_ALIGNMENT)));
36 ASAN_POISON_MEMORY_REGION(buff_, size_);
37 LOG(DEBUG, ALLOC) << "Arena: created with buff addr = " << buff << " size = " << buff_size;
38 }
39
~Arena()40 inline Arena::~Arena()
41 {
42 ASAN_UNPOISON_MEMORY_REGION(buff_, size_);
43 LOG(DEBUG, ALLOC) << "Destroy Arena buff addr = " << buff_ << " size = " << size_;
44 }
45
Alloc(size_t size,Alignment alignment)46 inline void *Arena::Alloc(size_t size, Alignment alignment)
47 {
48 void *ret = nullptr;
49 size_t free_size = GetFreeSize();
50 ret = std::align(GetAlignmentInBytes(alignment), size, curPos_, free_size);
51 if (ret != nullptr) {
52 ASAN_UNPOISON_MEMORY_REGION(ret, size);
53 curPos_ = ToVoidPtr(ToUintPtr(ret) + size);
54 }
55 LOG(DEBUG, ALLOC) << "Arena::Alloc size = " << size << " alignment = " << alignment << " at addr = " << ret;
56 return ret;
57 }
58
AlignedAlloc(size_t size,Alignment alignment)59 inline void *Arena::AlignedAlloc(size_t size, [[maybe_unused]] Alignment alignment)
60 {
61 ASSERT(AlignUp(ToUintPtr(curPos_), GetAlignmentInBytes(alignment)) == ToUintPtr(curPos_));
62 ASSERT(AlignUp(size, GetAlignmentInBytes(alignment)) == size);
63 void *ret = nullptr;
64 uintptr_t new_cur_pos = ToUintPtr(curPos_) + size;
65 if (new_cur_pos <= (ToUintPtr(buff_) + size_)) {
66 ret = curPos_;
67 curPos_ = ToVoidPtr(new_cur_pos);
68 ASAN_UNPOISON_MEMORY_REGION(ret, size);
69 }
70 return ret;
71 }
72
LinkTo(Arena * arena)73 inline void Arena::LinkTo(Arena *arena)
74 {
75 LOG(DEBUG, ALLOC) << "Link arena " << this << " to " << arena;
76 ASSERT(next_ == nullptr);
77 next_ = arena;
78 }
79
ClearNextLink()80 inline void Arena::ClearNextLink()
81 {
82 next_ = nullptr;
83 }
84
GetNextArena()85 inline Arena *Arena::GetNextArena() const
86 {
87 return next_;
88 }
89
GetFreeSize()90 inline size_t Arena::GetFreeSize() const
91 {
92 ASSERT(ToUintPtr(curPos_) >= ToUintPtr(GetStartPos()));
93 return size_ - (ToUintPtr(curPos_) - ToUintPtr(GetStartPos()));
94 }
95
GetOccupiedSize()96 inline size_t Arena::GetOccupiedSize() const
97 {
98 ASSERT(ToUintPtr(curPos_) >= ToUintPtr(GetStartPos()));
99 return ToUintPtr(curPos_) - ToUintPtr(GetStartPos());
100 }
101
GetArenaEnd()102 inline void *Arena::GetArenaEnd() const
103 {
104 return ToVoidPtr(size_ + ToUintPtr(buff_));
105 }
106
GetAllocatedEnd()107 inline void *Arena::GetAllocatedEnd() const
108 {
109 return ToVoidPtr(ToUintPtr(GetStartPos()) + GetOccupiedSize());
110 }
111
GetAllocatedStart()112 inline void *Arena::GetAllocatedStart() const
113 {
114 return GetStartPos();
115 }
116
InArena(const void * mem)117 inline bool Arena::InArena(const void *mem) const
118 {
119 return (ToUintPtr(curPos_) > ToUintPtr(mem)) && (ToUintPtr(GetStartPos()) <= ToUintPtr(mem));
120 }
121
Free(void * mem)122 inline void Arena::Free(void *mem)
123 {
124 ASSERT(InArena(mem));
125 ASAN_POISON_MEMORY_REGION(mem, ToUintPtr(curPos_) - ToUintPtr(mem));
126 curPos_ = mem;
127 }
128
Resize(size_t new_size)129 inline void Arena::Resize(size_t new_size)
130 {
131 size_t old_size = GetOccupiedSize();
132 ASSERT(new_size <= old_size);
133 curPos_ = ToVoidPtr(ToUintPtr(GetStartPos()) + new_size);
134 ASAN_POISON_MEMORY_REGION(curPos_, old_size - new_size);
135 }
136
Reset()137 inline void Arena::Reset()
138 {
139 Resize(0);
140 }
141
ExpandArena(const void * extra_buff,size_t size)142 inline void Arena::ExpandArena(const void *extra_buff, size_t size)
143 {
144 ASSERT(ToUintPtr(extra_buff) == AlignUp(ToUintPtr(extra_buff), DEFAULT_ALIGNMENT_IN_BYTES));
145 ASSERT(ToUintPtr(extra_buff) == ToUintPtr(GetArenaEnd()));
146 ASAN_POISON_MEMORY_REGION(extra_buff, size);
147 LOG(DEBUG, ALLOC) << "Expand arena: Add " << size << " bytes to the arena " << this;
148 size_ += size;
149 }
150
151 } // namespace panda
152
153 #endif // LIBPANDABASE_MEM_ARENA_INL_H
154