blob: 48b07a2c401c4bc02860c83481d647f794793ae4 [file] [log] [blame]
// Copyright 2016 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/media/transport/mapped_shared_buffer.h"
#include <lib/zx/vmar.h>
#include <lib/zx/vmo.h>
#include <zircon/types.h>
#include "lib/fxl/logging.h"
#include "lib/media/transport/fifo_allocator.h"
namespace media {
namespace {
constexpr uint64_t kMaxBufferLen = 0x3fffffffffffffff;
} // namespace
MappedSharedBuffer::MappedSharedBuffer() {}
MappedSharedBuffer::~MappedSharedBuffer() { Reset(); }
zx_status_t MappedSharedBuffer::InitNew(uint64_t size, uint32_t map_flags) {
FXL_DCHECK(size > 0);
zx::vmo vmo;
zx_status_t status = zx::vmo::create(size, 0, &vmo);
if (status != ZX_OK) {
FXL_LOG(ERROR) << "zx::vmo::create failed, status " << status;
return status;
}
// Allocate physical memory for the buffer.
status = vmo.op_range(ZX_VMO_OP_COMMIT, 0u, size, nullptr, 0u);
if (status != ZX_OK) {
FXL_LOG(ERROR) << "zx::vmo::op_range failed, status " << status;
return status;
}
return InitInternal(std::move(vmo), map_flags);
}
zx_status_t MappedSharedBuffer::InitFromVmo(zx::vmo vmo, uint32_t map_flags) {
return InitInternal(std::move(vmo), map_flags);
}
zx_status_t MappedSharedBuffer::InitInternal(zx::vmo vmo, uint32_t map_flags) {
Reset();
uint64_t size;
zx_status_t status = vmo.get_size(&size);
if (status != ZX_OK) {
FXL_LOG(ERROR) << "zx::vmo::get_size failed, status " << status;
return status;
}
if (size == 0 || size > kMaxBufferLen) {
FXL_LOG(ERROR) << "zx::vmo::get_size returned invalid size " << size;
return ZX_ERR_OUT_OF_RANGE;
}
size_ = size;
// TODO(dalesat): Map only for required operations (read or write).
uintptr_t mapped_buffer = 0u;
status =
zx::vmar::root_self()->map(0, vmo, 0u, size, map_flags, &mapped_buffer);
if (status != ZX_OK) {
FXL_LOG(ERROR) << "zx::vmar::map failed, status " << status;
return status;
}
buffer_ptr_ = reinterpret_cast<uint8_t*>(mapped_buffer);
vmo_ = std::move(vmo);
OnInit();
return ZX_OK;
}
bool MappedSharedBuffer::initialized() const { return buffer_ptr_ != nullptr; }
void MappedSharedBuffer::Reset() {
if (buffer_ptr_ != nullptr) {
FXL_DCHECK(size_ != 0);
zx_status_t status = zx::vmar::root_self()->unmap(
reinterpret_cast<uintptr_t>(buffer_ptr_), size_);
FXL_CHECK(status == ZX_OK);
buffer_ptr_ = nullptr;
}
size_ = 0;
vmo_.reset();
}
uint64_t MappedSharedBuffer::size() const { return size_; }
zx::vmo MappedSharedBuffer::GetDuplicateVmo(zx_rights_t rights) const {
FXL_DCHECK(initialized());
zx::vmo vmo;
zx_status_t status = vmo_.duplicate(rights, &vmo);
if (status != ZX_OK) {
FXL_LOG(ERROR) << "zx::handle::duplicate failed, status " << status;
}
return vmo;
}
bool MappedSharedBuffer::Validate(uint64_t offset, uint64_t size) {
FXL_DCHECK(buffer_ptr_ != nullptr);
return offset < size_ && size <= size_ - offset;
}
void* MappedSharedBuffer::PtrFromOffset(uint64_t offset) const {
FXL_DCHECK(buffer_ptr_ != nullptr);
if (offset == FifoAllocator::kNullOffset) {
return nullptr;
}
FXL_DCHECK(offset < size_);
return buffer_ptr_ + offset;
}
uint64_t MappedSharedBuffer::OffsetFromPtr(void* ptr) const {
FXL_DCHECK(buffer_ptr_ != nullptr);
if (ptr == nullptr) {
return FifoAllocator::kNullOffset;
}
uint64_t offset = reinterpret_cast<uint8_t*>(ptr) - buffer_ptr_;
FXL_DCHECK(offset < size_);
return offset;
}
void MappedSharedBuffer::OnInit() {}
} // namespace media