xref: /aosp_15_r20/external/pigweed/pw_allocator/chunk_pool.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker // Copyright 2024 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker 
15*61c4878aSAndroid Build Coastguard Worker #include "pw_allocator/chunk_pool.h"
16*61c4878aSAndroid Build Coastguard Worker 
17*61c4878aSAndroid Build Coastguard Worker #include "lib/stdcompat/bit.h"
18*61c4878aSAndroid Build Coastguard Worker #include "pw_allocator/buffer.h"
19*61c4878aSAndroid Build Coastguard Worker #include "pw_assert/check.h"
20*61c4878aSAndroid Build Coastguard Worker #include "pw_bytes/alignment.h"
21*61c4878aSAndroid Build Coastguard Worker 
22*61c4878aSAndroid Build Coastguard Worker namespace pw::allocator {
23*61c4878aSAndroid Build Coastguard Worker 
EnsurePointerLayout(const Layout & layout)24*61c4878aSAndroid Build Coastguard Worker static Layout EnsurePointerLayout(const Layout& layout) {
25*61c4878aSAndroid Build Coastguard Worker   return Layout(std::max(layout.size(), sizeof(void*)),
26*61c4878aSAndroid Build Coastguard Worker                 std::max(layout.alignment(), alignof(void*)));
27*61c4878aSAndroid Build Coastguard Worker }
28*61c4878aSAndroid Build Coastguard Worker 
ChunkPool(ByteSpan region,const Layout & layout)29*61c4878aSAndroid Build Coastguard Worker ChunkPool::ChunkPool(ByteSpan region, const Layout& layout)
30*61c4878aSAndroid Build Coastguard Worker     : Pool(kCapabilities, layout),
31*61c4878aSAndroid Build Coastguard Worker       allocated_layout_(EnsurePointerLayout(layout)) {
32*61c4878aSAndroid Build Coastguard Worker   Result<ByteSpan> result =
33*61c4878aSAndroid Build Coastguard Worker       GetAlignedSubspan(region, allocated_layout_.alignment());
34*61c4878aSAndroid Build Coastguard Worker   PW_CHECK_OK(result.status());
35*61c4878aSAndroid Build Coastguard Worker   start_ = cpp20::bit_cast<uintptr_t>(region.data());
36*61c4878aSAndroid Build Coastguard Worker   end_ = start_ + region.size() - (region.size() % allocated_layout_.size());
37*61c4878aSAndroid Build Coastguard Worker   region = result.value();
38*61c4878aSAndroid Build Coastguard Worker   next_ = region.data();
39*61c4878aSAndroid Build Coastguard Worker   std::byte* current = next_;
40*61c4878aSAndroid Build Coastguard Worker   std::byte* end = current + region.size();
41*61c4878aSAndroid Build Coastguard Worker   std::byte** next = &current;
42*61c4878aSAndroid Build Coastguard Worker   while (current < end) {
43*61c4878aSAndroid Build Coastguard Worker     next = std::launder(reinterpret_cast<std::byte**>(current));
44*61c4878aSAndroid Build Coastguard Worker     current += allocated_layout_.size();
45*61c4878aSAndroid Build Coastguard Worker     *next = current;
46*61c4878aSAndroid Build Coastguard Worker   }
47*61c4878aSAndroid Build Coastguard Worker   *next = nullptr;
48*61c4878aSAndroid Build Coastguard Worker }
49*61c4878aSAndroid Build Coastguard Worker 
DoAllocate()50*61c4878aSAndroid Build Coastguard Worker void* ChunkPool::DoAllocate() {
51*61c4878aSAndroid Build Coastguard Worker   if (next_ == nullptr) {
52*61c4878aSAndroid Build Coastguard Worker     return nullptr;
53*61c4878aSAndroid Build Coastguard Worker   }
54*61c4878aSAndroid Build Coastguard Worker   std::byte* ptr = next_;
55*61c4878aSAndroid Build Coastguard Worker   next_ = *(std::launder(reinterpret_cast<std::byte**>(next_)));
56*61c4878aSAndroid Build Coastguard Worker   return ptr;
57*61c4878aSAndroid Build Coastguard Worker }
58*61c4878aSAndroid Build Coastguard Worker 
DoDeallocate(void * ptr)59*61c4878aSAndroid Build Coastguard Worker void ChunkPool::DoDeallocate(void* ptr) {
60*61c4878aSAndroid Build Coastguard Worker   if (ptr == nullptr) {
61*61c4878aSAndroid Build Coastguard Worker     return;
62*61c4878aSAndroid Build Coastguard Worker   }
63*61c4878aSAndroid Build Coastguard Worker   std::byte** next = std::launder(reinterpret_cast<std::byte**>(ptr));
64*61c4878aSAndroid Build Coastguard Worker   *next = next_;
65*61c4878aSAndroid Build Coastguard Worker   next_ = cpp20::bit_cast<std::byte*>(ptr);
66*61c4878aSAndroid Build Coastguard Worker }
67*61c4878aSAndroid Build Coastguard Worker 
DoGetInfo(InfoType info_type,const void * ptr) const68*61c4878aSAndroid Build Coastguard Worker Result<Layout> ChunkPool::DoGetInfo(InfoType info_type, const void* ptr) const {
69*61c4878aSAndroid Build Coastguard Worker   if (info_type == InfoType::kCapacity) {
70*61c4878aSAndroid Build Coastguard Worker     return Layout(end_ - start_, allocated_layout_.alignment());
71*61c4878aSAndroid Build Coastguard Worker   }
72*61c4878aSAndroid Build Coastguard Worker   auto addr = cpp20::bit_cast<uintptr_t>(ptr);
73*61c4878aSAndroid Build Coastguard Worker   if (addr < start_ || end_ <= addr) {
74*61c4878aSAndroid Build Coastguard Worker     return Status::OutOfRange();
75*61c4878aSAndroid Build Coastguard Worker   }
76*61c4878aSAndroid Build Coastguard Worker   if ((addr - start_) % allocated_layout_.size() != 0) {
77*61c4878aSAndroid Build Coastguard Worker     return Status::OutOfRange();
78*61c4878aSAndroid Build Coastguard Worker   }
79*61c4878aSAndroid Build Coastguard Worker   switch (info_type) {
80*61c4878aSAndroid Build Coastguard Worker     case InfoType::kRequestedLayoutOf:
81*61c4878aSAndroid Build Coastguard Worker     case InfoType::kUsableLayoutOf:
82*61c4878aSAndroid Build Coastguard Worker     case InfoType::kAllocatedLayoutOf:
83*61c4878aSAndroid Build Coastguard Worker       return allocated_layout_;
84*61c4878aSAndroid Build Coastguard Worker     case InfoType::kRecognizes:
85*61c4878aSAndroid Build Coastguard Worker       return Layout();
86*61c4878aSAndroid Build Coastguard Worker     case InfoType::kCapacity:
87*61c4878aSAndroid Build Coastguard Worker     default:
88*61c4878aSAndroid Build Coastguard Worker       return Status::Unimplemented();
89*61c4878aSAndroid Build Coastguard Worker   }
90*61c4878aSAndroid Build Coastguard Worker }
91*61c4878aSAndroid Build Coastguard Worker 
92*61c4878aSAndroid Build Coastguard Worker }  // namespace pw::allocator
93