1b1994897Sopenharmony_ci/*
2b1994897Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3b1994897Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4b1994897Sopenharmony_ci * you may not use this file except in compliance with the License.
5b1994897Sopenharmony_ci * You may obtain a copy of the License at
6b1994897Sopenharmony_ci *
7b1994897Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8b1994897Sopenharmony_ci *
9b1994897Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10b1994897Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11b1994897Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12b1994897Sopenharmony_ci * See the License for the specific language governing permissions and
13b1994897Sopenharmony_ci * limitations under the License.
14b1994897Sopenharmony_ci */
15b1994897Sopenharmony_ci
16b1994897Sopenharmony_ci#ifndef LIBPANDABASE_MEM_ARENA_INL_H
17b1994897Sopenharmony_ci#define LIBPANDABASE_MEM_ARENA_INL_H
18b1994897Sopenharmony_ci
19b1994897Sopenharmony_ci#include <memory>
20b1994897Sopenharmony_ci#include "arena.h"
21b1994897Sopenharmony_ci#include "macros.h"
22b1994897Sopenharmony_ci#include "utils/logger.h"
23b1994897Sopenharmony_ci#include "utils/asan_interface.h"
24b1994897Sopenharmony_ci
25b1994897Sopenharmony_cinamespace panda {
26b1994897Sopenharmony_ci
27b1994897Sopenharmony_ciinline Arena::Arena(size_t buff_size, void *buff) : Arena(buff_size, buff, ARENA_DEFAULT_ALIGNMENT) {}
28b1994897Sopenharmony_ci
29b1994897Sopenharmony_ciinline Arena::Arena(size_t buff_size, void *buff, Alignment start_alignment)
30b1994897Sopenharmony_ci    : buff_(buff),
31b1994897Sopenharmony_ci      startPos_(ToVoidPtr(AlignUp(ToUintPtr(buff), GetAlignmentInBytes(start_alignment)))),
32b1994897Sopenharmony_ci      curPos_(startPos_),
33b1994897Sopenharmony_ci      size_(buff_size)
34b1994897Sopenharmony_ci{
35b1994897Sopenharmony_ci    ASSERT(ToUintPtr(buff) == AlignUp(ToUintPtr(buff), GetAlignmentInBytes(ARENA_DEFAULT_ALIGNMENT)));
36b1994897Sopenharmony_ci    ASAN_POISON_MEMORY_REGION(buff_, size_);
37b1994897Sopenharmony_ci    LOG(DEBUG, ALLOC) << "Arena: created with buff addr = " << buff << " size = " << buff_size;
38b1994897Sopenharmony_ci}
39b1994897Sopenharmony_ci
40b1994897Sopenharmony_ciinline Arena::~Arena()
41b1994897Sopenharmony_ci{
42b1994897Sopenharmony_ci    ASAN_UNPOISON_MEMORY_REGION(buff_, size_);
43b1994897Sopenharmony_ci    LOG(DEBUG, ALLOC) << "Destroy Arena buff addr = " << buff_ << " size = " << size_;
44b1994897Sopenharmony_ci}
45b1994897Sopenharmony_ci
46b1994897Sopenharmony_ciinline void *Arena::Alloc(size_t size, Alignment alignment)
47b1994897Sopenharmony_ci{
48b1994897Sopenharmony_ci    void *ret = nullptr;
49b1994897Sopenharmony_ci    size_t free_size = GetFreeSize();
50b1994897Sopenharmony_ci    ret = std::align(GetAlignmentInBytes(alignment), size, curPos_, free_size);
51b1994897Sopenharmony_ci    if (ret != nullptr) {
52b1994897Sopenharmony_ci        ASAN_UNPOISON_MEMORY_REGION(ret, size);
53b1994897Sopenharmony_ci        curPos_ = ToVoidPtr(ToUintPtr(ret) + size);
54b1994897Sopenharmony_ci    }
55b1994897Sopenharmony_ci    LOG(DEBUG, ALLOC) << "Arena::Alloc size = " << size << " alignment = " << alignment << " at addr = " << ret;
56b1994897Sopenharmony_ci    return ret;
57b1994897Sopenharmony_ci}
58b1994897Sopenharmony_ci
59b1994897Sopenharmony_ciinline void *Arena::AlignedAlloc(size_t size, [[maybe_unused]] Alignment alignment)
60b1994897Sopenharmony_ci{
61b1994897Sopenharmony_ci    ASSERT(AlignUp(ToUintPtr(curPos_), GetAlignmentInBytes(alignment)) == ToUintPtr(curPos_));
62b1994897Sopenharmony_ci    ASSERT(AlignUp(size, GetAlignmentInBytes(alignment)) == size);
63b1994897Sopenharmony_ci    void *ret = nullptr;
64b1994897Sopenharmony_ci    uintptr_t new_cur_pos = ToUintPtr(curPos_) + size;
65b1994897Sopenharmony_ci    if (new_cur_pos <= (ToUintPtr(buff_) + size_)) {
66b1994897Sopenharmony_ci        ret = curPos_;
67b1994897Sopenharmony_ci        curPos_ = ToVoidPtr(new_cur_pos);
68b1994897Sopenharmony_ci        ASAN_UNPOISON_MEMORY_REGION(ret, size);
69b1994897Sopenharmony_ci    }
70b1994897Sopenharmony_ci    return ret;
71b1994897Sopenharmony_ci}
72b1994897Sopenharmony_ci
73b1994897Sopenharmony_ciinline void Arena::LinkTo(Arena *arena)
74b1994897Sopenharmony_ci{
75b1994897Sopenharmony_ci    LOG(DEBUG, ALLOC) << "Link arena " << this << " to " << arena;
76b1994897Sopenharmony_ci    ASSERT(next_ == nullptr);
77b1994897Sopenharmony_ci    next_ = arena;
78b1994897Sopenharmony_ci}
79b1994897Sopenharmony_ci
80b1994897Sopenharmony_ciinline void Arena::ClearNextLink()
81b1994897Sopenharmony_ci{
82b1994897Sopenharmony_ci    next_ = nullptr;
83b1994897Sopenharmony_ci}
84b1994897Sopenharmony_ci
85b1994897Sopenharmony_ciinline Arena *Arena::GetNextArena() const
86b1994897Sopenharmony_ci{
87b1994897Sopenharmony_ci    return next_;
88b1994897Sopenharmony_ci}
89b1994897Sopenharmony_ci
90b1994897Sopenharmony_ciinline size_t Arena::GetFreeSize() const
91b1994897Sopenharmony_ci{
92b1994897Sopenharmony_ci    ASSERT(ToUintPtr(curPos_) >= ToUintPtr(GetStartPos()));
93b1994897Sopenharmony_ci    return size_ - (ToUintPtr(curPos_) - ToUintPtr(GetStartPos()));
94b1994897Sopenharmony_ci}
95b1994897Sopenharmony_ci
96b1994897Sopenharmony_ciinline size_t Arena::GetOccupiedSize() const
97b1994897Sopenharmony_ci{
98b1994897Sopenharmony_ci    ASSERT(ToUintPtr(curPos_) >= ToUintPtr(GetStartPos()));
99b1994897Sopenharmony_ci    return ToUintPtr(curPos_) - ToUintPtr(GetStartPos());
100b1994897Sopenharmony_ci}
101b1994897Sopenharmony_ci
102b1994897Sopenharmony_ciinline void *Arena::GetArenaEnd() const
103b1994897Sopenharmony_ci{
104b1994897Sopenharmony_ci    return ToVoidPtr(size_ + ToUintPtr(buff_));
105b1994897Sopenharmony_ci}
106b1994897Sopenharmony_ci
107b1994897Sopenharmony_ciinline void *Arena::GetAllocatedEnd() const
108b1994897Sopenharmony_ci{
109b1994897Sopenharmony_ci    return ToVoidPtr(ToUintPtr(GetStartPos()) + GetOccupiedSize());
110b1994897Sopenharmony_ci}
111b1994897Sopenharmony_ci
112b1994897Sopenharmony_ciinline void *Arena::GetAllocatedStart() const
113b1994897Sopenharmony_ci{
114b1994897Sopenharmony_ci    return GetStartPos();
115b1994897Sopenharmony_ci}
116b1994897Sopenharmony_ci
117b1994897Sopenharmony_ciinline bool Arena::InArena(const void *mem) const
118b1994897Sopenharmony_ci{
119b1994897Sopenharmony_ci    return (ToUintPtr(curPos_) > ToUintPtr(mem)) && (ToUintPtr(GetStartPos()) <= ToUintPtr(mem));
120b1994897Sopenharmony_ci}
121b1994897Sopenharmony_ci
122b1994897Sopenharmony_ciinline void Arena::Free(void *mem)
123b1994897Sopenharmony_ci{
124b1994897Sopenharmony_ci    ASSERT(InArena(mem));
125b1994897Sopenharmony_ci    ASAN_POISON_MEMORY_REGION(mem, ToUintPtr(curPos_) - ToUintPtr(mem));
126b1994897Sopenharmony_ci    curPos_ = mem;
127b1994897Sopenharmony_ci}
128b1994897Sopenharmony_ci
129b1994897Sopenharmony_ciinline void Arena::Resize(size_t new_size)
130b1994897Sopenharmony_ci{
131b1994897Sopenharmony_ci    size_t old_size = GetOccupiedSize();
132b1994897Sopenharmony_ci    ASSERT(new_size <= old_size);
133b1994897Sopenharmony_ci    curPos_ = ToVoidPtr(ToUintPtr(GetStartPos()) + new_size);
134b1994897Sopenharmony_ci    ASAN_POISON_MEMORY_REGION(curPos_, old_size - new_size);
135b1994897Sopenharmony_ci}
136b1994897Sopenharmony_ci
137b1994897Sopenharmony_ciinline void Arena::Reset()
138b1994897Sopenharmony_ci{
139b1994897Sopenharmony_ci    Resize(0);
140b1994897Sopenharmony_ci}
141b1994897Sopenharmony_ci
142b1994897Sopenharmony_ciinline void Arena::ExpandArena(const void *extra_buff, size_t size)
143b1994897Sopenharmony_ci{
144b1994897Sopenharmony_ci    ASSERT(ToUintPtr(extra_buff) == AlignUp(ToUintPtr(extra_buff), DEFAULT_ALIGNMENT_IN_BYTES));
145b1994897Sopenharmony_ci    ASSERT(ToUintPtr(extra_buff) == ToUintPtr(GetArenaEnd()));
146b1994897Sopenharmony_ci    ASAN_POISON_MEMORY_REGION(extra_buff, size);
147b1994897Sopenharmony_ci    LOG(DEBUG, ALLOC) << "Expand arena: Add " << size << " bytes to the arena " << this;
148b1994897Sopenharmony_ci    size_ += size;
149b1994897Sopenharmony_ci}
150b1994897Sopenharmony_ci
151b1994897Sopenharmony_ci}  // namespace panda
152b1994897Sopenharmony_ci
153b1994897Sopenharmony_ci#endif  // LIBPANDABASE_MEM_ARENA_INL_H
154