Skip to content

Commit

Permalink
pw_allocator: Refactor Block to use encoded offsets
Browse files Browse the repository at this point in the history
This CL refactors `Block` into `Block<UintType, kMaxSize>`. Instead of
using next and previous block pointers, it now encodes offsets and flags
in fields of type `UintType`. Depending on `kMaxSize`, there may be bits
of `UintType` that are not needed to address blocks. These bits are
available to be used as custom flags.

Change-Id: Ic979f6d6982088de810bdd9b793e1e115aef65eb
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/176578
Reviewed-by: Taylor Cramer <[email protected]>
Commit-Queue: Aaron Green <[email protected]>
  • Loading branch information
nopsledder authored and CQ Bot Account committed Oct 20, 2023
1 parent 3bad357 commit 26ccfc6
Show file tree
Hide file tree
Showing 12 changed files with 1,101 additions and 694 deletions.
7 changes: 4 additions & 3 deletions pw_allocator/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,18 @@ pw_cc_library(

pw_cc_library(
name = "block",
srcs = [
"block.cc",
],
srcs = ["block.cc"],
hdrs = [
"public/pw_allocator/block.h",
],
includes = ["public"],
deps = [
"//pw_assert",
"//pw_bytes",
"//pw_result",
"//pw_span",
"//pw_status",
"//third_party/fuchsia:stdcompat",
],
)

Expand Down
5 changes: 4 additions & 1 deletion pw_allocator/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,13 @@ pw_source_set("block") {
configs = [ ":enable_heap_poison" ]
public = [ "public/pw_allocator/block.h" ]
public_deps = [
dir_pw_assert,
"$dir_pw_third_party/fuchsia:stdcompat",
dir_pw_bytes,
dir_pw_result,
dir_pw_span,
dir_pw_status,
]
deps = [ dir_pw_assert ]
sources = [ "block.cc" ]
}

Expand Down
6 changes: 5 additions & 1 deletion pw_allocator/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,13 @@ pw_add_library(pw_allocator.block STATIC
PUBLIC_INCLUDES
public
PUBLIC_DEPS
pw_assert
pw_bytes
pw_result
pw_span
pw_status
pw_third_party.fuchsia.stdcompat
PRIVATE_DEPS
pw_assert
SOURCES
block.cc
)
Expand Down
64 changes: 35 additions & 29 deletions pw_allocator/allocator_testing.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,19 @@

namespace pw::allocator::test {

static Block* NextBlock(Block* block) {
return block->Last() ? nullptr : block->Next();
}

Status FakeAllocator::Initialize(ByteSpan buffer) {
if (auto status = Block::Init(buffer, &head_); !status.ok()) {
return status;
auto result = BlockType::Init(buffer);
if (!result.ok()) {
return result.status();
}
begin_ = *result;
end_ = begin_->Next();
ResetParameters();
return OkStatus();
}

void FakeAllocator::Exhaust() {
for (Block* block = head_; block != nullptr; block = NextBlock(block)) {
for (BlockType* block = begin_; block != end_; block = block->Next()) {
block->MarkUsed();
}
}
Expand All @@ -47,55 +46,61 @@ void FakeAllocator::ResetParameters() {
}

Status FakeAllocator::DoQuery(const void* ptr, size_t size, size_t) const {
PW_CHECK(head_ != nullptr);
PW_CHECK(begin_ != nullptr);
if (size == 0 || ptr == nullptr) {
return Status::OutOfRange();
}
const auto* bytes = static_cast<const std::byte*>(ptr);
Block* block = Block::FromUsableSpace(const_cast<std::byte*>(bytes));
if (!block->IsValid()) {
BlockType* target = BlockType::FromUsableSpace(const_cast<std::byte*>(bytes));
if (!target->IsValid()) {
return Status::OutOfRange();
}
size = AlignUp(size, alignof(Block));
for (Block* curr = head_; curr != nullptr; curr = NextBlock(curr)) {
if (curr == block && curr->InnerSize() == size) {
size = AlignUp(size, BlockType::kAlignment);
for (BlockType* block = begin_; block != end_; block = block->Next()) {
if (block == target && block->InnerSize() == size) {
return OkStatus();
}
}
return Status::OutOfRange();
}

void* FakeAllocator::DoAllocate(size_t size, size_t) {
PW_CHECK(head_ != nullptr);
PW_CHECK(begin_ != nullptr);
allocate_size_ = size;
for (Block* block = head_; block != nullptr; block = NextBlock(block)) {
Block* fragment = nullptr;
if (!block->Used() && block->Split(size, &fragment).ok()) {
block->MarkUsed();
return block->UsableSpace();
for (BlockType* block = begin_; block != end_; block = block->Next()) {
if (block->Used() || block->InnerSize() < size) {
continue;
}
Result<BlockType*> result = BlockType::Split(block, size);
if (result.ok()) {
BlockType* next = *result;
BlockType::MergeNext(next).IgnoreError();
}
block->MarkUsed();
return block->UsableSpace();
}
return nullptr;
}

void FakeAllocator::DoDeallocate(void* ptr, size_t size, size_t alignment) {
PW_CHECK(head_ != nullptr);
PW_CHECK(begin_ != nullptr);
deallocate_ptr_ = ptr;
deallocate_size_ = size;
if (!DoQuery(ptr, size, alignment).ok()) {
return;
}
Block* block = Block::FromUsableSpace(static_cast<std::byte*>(ptr));
BlockType* block = BlockType::FromUsableSpace(static_cast<std::byte*>(ptr));
block->MarkFree();
block->MergeNext().IgnoreError();
block->MergePrev().IgnoreError();
BlockType::MergeNext(block).IgnoreError();
BlockType* prev = block->Prev();
BlockType::MergeNext(prev).IgnoreError();
}

bool FakeAllocator::DoResize(void* ptr,
size_t old_size,
size_t old_alignment,
size_t new_size) {
PW_CHECK(head_ != nullptr);
PW_CHECK(begin_ != nullptr);
resize_ptr_ = ptr;
resize_old_size_ = old_size;
resize_new_size_ = new_size;
Expand All @@ -106,12 +111,13 @@ bool FakeAllocator::DoResize(void* ptr,
if (old_size == new_size) {
return true;
}
Block* block = Block::FromUsableSpace(static_cast<std::byte*>(ptr));
BlockType* block = BlockType::FromUsableSpace(static_cast<std::byte*>(ptr));
block->MarkFree();
block->MergeNext().IgnoreError();
Block* fragment = nullptr;
if (block->Split(new_size, &fragment) == Status::OutOfRange()) {
block->Split(old_size, &fragment).IgnoreError();
BlockType::MergeNext(block).IgnoreError();

Result<BlockType*> result = BlockType::Split(block, new_size);
if (!result.ok()) {
BlockType::Split(block, old_size).IgnoreError();
}
block->MarkUsed();
return block->InnerSize() >= new_size;
Expand Down
Loading

0 comments on commit 26ccfc6

Please sign in to comment.