// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <lib/inspect/heap.h>

namespace inspect {
namespace internal {

namespace {
// Get the "buddy" for a given |Block|. Buddies may be merged together if they are both free.
constexpr BlockIndex Buddy(BlockIndex block, BlockOrder block_order) {
    // XOR index of the block by its size (in kMinOrderSize blocks) to get the index of its
    // buddy.
    return block ^ IndexForOffset(OrderToSize(block_order));
}

} // namespace

Heap::Heap(fbl::unique_ptr<fzl::ResizeableVmoMapper> vmo, size_t max_size)
    : vmo_(std::move(vmo)), cur_size_(0), max_size_(max_size) {
    ZX_DEBUG_ASSERT_MSG(max_size % kMinVmoSize == 0,
                        "Maximum size must be a multiple of the page size.");
    Extend(kMinVmoSize);
}

Heap::~Heap() {
    ZX_DEBUG_ASSERT_MSG(num_allocated_blocks_ == 0, "There are still %lu outstanding blocks",
                        num_allocated_blocks_);
}

zx::vmo Heap::ReadOnlyClone() const {
    zx::vmo ret;
    // BASIC rights include the ability to duplicate, transfer, and wait
    // on the handle
    vmo_->vmo().duplicate(ZX_RIGHTS_BASIC | ZX_RIGHT_MAP | ZX_RIGHT_READ, &ret);
    return ret;
}

zx_status_t Heap::Allocate(size_t min_size, BlockIndex* out_block) {
    ZX_DEBUG_ASSERT_MSG(min_size >= sizeof(Block), "Block allocation size %lu is too small",
                        min_size);
    const BlockOrder min_fit_order = FitOrder(min_size);
    ZX_DEBUG_ASSERT_MSG(min_fit_order < kNumOrders, "Order %u is greater than maximum order %lu",
                        min_fit_order, kNumOrders - 1);
    if (min_fit_order >= kNumOrders) {
        return ZX_ERR_INVALID_ARGS;
    }

    // Iterate through the orders until we find a free block with order >=
    // what is needed.
    BlockOrder next_order = kNumOrders;
    for (BlockOrder i = min_fit_order; i < kNumOrders; i++) {
        if (IsFreeBlock(free_blocks_[i], i)) {
            next_order = i;
            break;
        }
    }

    // If no free block is found, extend the VMO and use one of the newly
    // created free blocks.
    if (next_order == kNumOrders) {
        zx_status_t status;
        status = Extend(cur_size_ * 2);
        if (status != ZX_OK) {
            return status;
        }
        next_order = kNumOrders - 1;
        ZX_ASSERT(IsFreeBlock(free_blocks_[kNumOrders - 1], kNumOrders - 1));
    }

    // Once a free block is found, split it repeatedly until it is the
    // right size.
    BlockIndex next_block_index = free_blocks_[next_order];
    while (GetOrder(GetBlock(next_block_index)) > min_fit_order) {
        if (!SplitBlock(next_block_index)) {
            return ZX_ERR_INTERNAL;
        }
    }

    // Remove the block from the free list, clear, and reserve it.
    RemoveFree(next_block_index);
    auto* next_block = GetBlock(next_block_index);

    next_block->header = BlockFields::Order::Make(GetOrder(next_block)) |
                         BlockFields::Type::Make(BlockType::kReserved);

    *out_block = next_block_index;
    ++num_allocated_blocks_;
    return ZX_OK;
}

void Heap::Free(BlockIndex block_index) {
    auto* block = GetBlock(block_index);
    BlockIndex buddy_index = Buddy(block_index, GetOrder(block));
    auto* buddy = GetBlock(buddy_index);

    // Repeatedly merge buddies of the freed block until the buddy is
    // not free or we hit the maximum block size.
    while (GetType(buddy) == BlockType::kFree && GetOrder(block) < kNumOrders - 1 &&
           GetOrder(block) == GetOrder(buddy)) {
        RemoveFree(buddy_index);
        if (buddy < block) {
            // We must always merge into the lower index block.
            // If the buddy of the block is a lower index, we need to swap
            // index and pointers.
            std::swap(block, buddy);
            std::swap(block_index, buddy_index);
        }
        BlockFields::Order::Set(&block->header, GetOrder(block) + 1);
        buddy_index = Buddy(block_index, GetOrder(block));
        buddy = GetBlock(buddy_index);
    }

    // Complete freeing the block by linking it onto the free list.
    block->header = BlockFields::Order::Make(GetOrder(block)) |
                    BlockFields::Type::Make(BlockType::kFree) |
                    FreeBlockFields::NextFreeBlock::Make(free_blocks_[GetOrder(block)]);
    free_blocks_[GetOrder(block)] = block_index;
    --num_allocated_blocks_;
}

bool Heap::SplitBlock(BlockIndex block) {
    RemoveFree(block);
    auto* cur = GetBlock(block);
    BlockOrder order = GetOrder(cur);
    ZX_DEBUG_ASSERT_MSG(order < kNumOrders, "Order on block is invalid");
    if (order >= kNumOrders) {
        return false;
    }

    // Lower the order of the original block, then find its new buddy.
    // Both the original block and the new buddy need to be added
    // onto the free list of the new order.
    BlockIndex buddy_index = Buddy(block, order - 1);
    auto* buddy = GetBlock(buddy_index);
    cur->header = BlockFields::Order::Make(order - 1) | BlockFields::Type::Make(BlockType::kFree) |
                  FreeBlockFields::NextFreeBlock::Make(buddy_index);

    buddy->header = BlockFields::Order::Make(order - 1) |
                    BlockFields::Type::Make(BlockType::kFree) |
                    FreeBlockFields::NextFreeBlock::Make(free_blocks_[order - 1]);

    free_blocks_[order - 1] = block;

    return true;
}

bool Heap::RemoveFree(BlockIndex block) {
    auto* to_remove = GetBlock(block);
    BlockOrder order = GetOrder(to_remove);
    ZX_DEBUG_ASSERT_MSG(order < kNumOrders, "Order %u on block %lu is invalid", order, block);
    if (order >= kNumOrders) {
        return false;
    }

    // If the block we are removing is at the head of the list,
    // immediately unlink it and return.
    BlockIndex next = free_blocks_[order];
    if (next == block) {
        free_blocks_[order] = FreeBlockFields::NextFreeBlock::Get<size_t>(to_remove->header);
        return true;
    }

    // Look through the free list until we find the position for the block,
    // then unlink it.
    while (IsFreeBlock(next, order)) {
        auto* cur = GetBlock(next);
        next = FreeBlockFields::NextFreeBlock::Get<size_t>(cur->header);
        if (next == block) {
            FreeBlockFields::NextFreeBlock::Set(
                &cur->header, FreeBlockFields::NextFreeBlock::Get<size_t>(to_remove->header));
            return true;
        }
    }

    return false;
}

zx_status_t Heap::Extend(size_t new_size) {
    if (cur_size_ == max_size_ && new_size > max_size_) {
        return ZX_ERR_NO_MEMORY;
    }
    new_size = fbl::min(max_size_, new_size);

    // Try to grow the VMO.
    // Note VMO growing will always align to a page boundary (which will
    // be a multiple of kMaxVmoSize and kMaxOrderSize).
    if (vmo_->size() < new_size) {
        zx_status_t status;
        status = vmo_->Grow(new_size);
        if (status != ZX_OK) {
            return status;
        }
    }
    size_t min_index = IndexForOffset(cur_size_);
    size_t last_index = free_blocks_[kNumOrders - 1];
    // Ensure we start on an index at a page boundary.
    // Convert each new max order block to a free block in descending
    // order on the free list.
    size_t cur_index = IndexForOffset(new_size - new_size % kMinVmoSize);
    do {
        cur_index -= IndexForOffset(kMaxOrderSize);
        auto* block = GetBlock(cur_index);
        *block = {};
        block->header = BlockFields::Order::Make(kNumOrders - 1) |
                        BlockFields::Type::Make(BlockType::kFree) |
                        FreeBlockFields::NextFreeBlock::Make(last_index);
        last_index = cur_index;
    } while (cur_index > min_index);

    free_blocks_[kNumOrders - 1] = last_index;

    cur_size_ = new_size;
    return ZX_OK;
}

} // namespace internal
} // namespace inspect
