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