• 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 #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