// 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/fzl/vmo-pool.h>
#include <lib/zx/vmar.h>
#include <string.h>

#include <utility>

namespace fzl {

VmoPool::~VmoPool() {
    // Clear out the free_buffers_, since the intrusive container
    // will throw an assert if it contains unmanaged pointers on
    // destruction.
    free_buffers_.clear_unsafe();
}

zx_status_t VmoPool::Init(const fbl::Vector<zx::vmo>& vmos) {
    return Init(vmos.begin(), vmos.size());
}

zx_status_t VmoPool::Init(const zx::vmo* vmos, size_t num_vmos) {
    fbl::AllocChecker ac;
    fbl::Array<ListableBuffer> buffers(new (&ac) ListableBuffer[num_vmos], num_vmos);
    if (!ac.check()) {
        return ZX_ERR_NO_MEMORY;
    }
    buffers_ = std::move(buffers);
    free_buffers_.clear_unsafe();

    zx_status_t status;
    for (size_t i = 0; i < num_vmos; ++i) {
        free_buffers_.push_front(&buffers_[i]);
        status = buffers_[i].buffer.Map(vmos[i], 0, 0, ZX_VM_PERM_READ | ZX_VM_PERM_WRITE);
        if (status != ZX_OK) {
            free_buffers_.clear_unsafe();
            buffers_.reset();
            return status;
        }
    }
    current_buffer_ = kInvalidCurBuffer;
    return ZX_OK;
}

void VmoPool::Reset() {
    current_buffer_ = kInvalidCurBuffer;
    for (size_t i = 0; i < buffers_.size(); ++i) {
        if (!buffers_[i].InContainer()) {
            free_buffers_.push_front(&buffers_[i]);
        }
    }
}

zx_status_t VmoPool::GetNewBuffer(uint32_t* buffer_index) {
    if (HasBufferInProgress()) {
        return ZX_ERR_BAD_STATE;
    }
    if (free_buffers_.is_empty()) { // No available buffers!
        return ZX_ERR_NOT_FOUND;
    }
    ListableBuffer* buf = free_buffers_.pop_front();
    ZX_DEBUG_ASSERT(buf >= &buffers_[0]);
    uint32_t buffer_offset = static_cast<uint32_t>(buf - &buffers_[0]);
    ZX_DEBUG_ASSERT(buffer_offset < buffers_.size());
    current_buffer_ = buffer_offset;
    if (buffer_index != nullptr) {
        *buffer_index = current_buffer_;
    }
    return ZX_OK;
}

zx_status_t VmoPool::BufferCompleted(uint32_t* buffer_index) {
    if (!HasBufferInProgress()) {
        return ZX_ERR_BAD_STATE;
    }
    if (buffer_index != nullptr) {
        *buffer_index = current_buffer_;
    }
    current_buffer_ = kInvalidCurBuffer;
    return ZX_OK;
}

zx_status_t VmoPool::BufferRelease(uint32_t buffer_index) {
    if (buffer_index >= buffers_.size()) {
        return ZX_ERR_INVALID_ARGS;
    }
    if (buffers_[buffer_index].InContainer()) {
        return ZX_ERR_NOT_FOUND;
    }
    // If we are cancelling the in-progress buffer:
    if (current_buffer_ == buffer_index) {
        current_buffer_ = kInvalidCurBuffer;
    }

    free_buffers_.push_front(&buffers_[buffer_index]);
    return ZX_OK;
}

uint64_t VmoPool::CurrentBufferSize() const {
    if (HasBufferInProgress()) {
        return buffers_[current_buffer_].buffer.size();
    }
    return 0;
}
void* VmoPool::CurrentBufferAddress() const {
    if (HasBufferInProgress()) {
        return buffers_[current_buffer_].buffer.start();
    }
    return nullptr;
}
} // namespace fzl
