1 // Copyright 2018 The Fuchsia Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <lib/fzl/vmo-pool.h> 6 #include <lib/zx/vmar.h> 7 #include <string.h> 8 9 #include <utility> 10 11 namespace fzl { 12 ~VmoPool()13VmoPool::~VmoPool() { 14 // Clear out the free_buffers_, since the intrusive container 15 // will throw an assert if it contains unmanaged pointers on 16 // destruction. 17 free_buffers_.clear_unsafe(); 18 } 19 Init(const fbl::Vector<zx::vmo> & vmos)20zx_status_t VmoPool::Init(const fbl::Vector<zx::vmo>& vmos) { 21 return Init(vmos.begin(), vmos.size()); 22 } 23 Init(const zx::vmo * vmos,size_t num_vmos)24zx_status_t VmoPool::Init(const zx::vmo* vmos, size_t num_vmos) { 25 fbl::AllocChecker ac; 26 fbl::Array<ListableBuffer> buffers(new (&ac) ListableBuffer[num_vmos], num_vmos); 27 if (!ac.check()) { 28 return ZX_ERR_NO_MEMORY; 29 } 30 buffers_ = std::move(buffers); 31 free_buffers_.clear_unsafe(); 32 33 zx_status_t status; 34 for (size_t i = 0; i < num_vmos; ++i) { 35 free_buffers_.push_front(&buffers_[i]); 36 status = buffers_[i].buffer.Map(vmos[i], 0, 0, ZX_VM_PERM_READ | ZX_VM_PERM_WRITE); 37 if (status != ZX_OK) { 38 free_buffers_.clear_unsafe(); 39 buffers_.reset(); 40 return status; 41 } 42 } 43 current_buffer_ = kInvalidCurBuffer; 44 return ZX_OK; 45 } 46 Reset()47void VmoPool::Reset() { 48 current_buffer_ = kInvalidCurBuffer; 49 for (size_t i = 0; i < buffers_.size(); ++i) { 50 if (!buffers_[i].InContainer()) { 51 free_buffers_.push_front(&buffers_[i]); 52 } 53 } 54 } 55 GetNewBuffer(uint32_t * buffer_index)56zx_status_t VmoPool::GetNewBuffer(uint32_t* buffer_index) { 57 if (HasBufferInProgress()) { 58 return ZX_ERR_BAD_STATE; 59 } 60 if (free_buffers_.is_empty()) { // No available buffers! 61 return ZX_ERR_NOT_FOUND; 62 } 63 ListableBuffer* buf = free_buffers_.pop_front(); 64 ZX_DEBUG_ASSERT(buf >= &buffers_[0]); 65 uint32_t buffer_offset = static_cast<uint32_t>(buf - &buffers_[0]); 66 ZX_DEBUG_ASSERT(buffer_offset < buffers_.size()); 67 current_buffer_ = buffer_offset; 68 if (buffer_index != nullptr) { 69 *buffer_index = current_buffer_; 70 } 71 return ZX_OK; 72 } 73 BufferCompleted(uint32_t * buffer_index)74zx_status_t VmoPool::BufferCompleted(uint32_t* buffer_index) { 75 if (!HasBufferInProgress()) { 76 return ZX_ERR_BAD_STATE; 77 } 78 if (buffer_index != nullptr) { 79 *buffer_index = current_buffer_; 80 } 81 current_buffer_ = kInvalidCurBuffer; 82 return ZX_OK; 83 } 84 BufferRelease(uint32_t buffer_index)85zx_status_t VmoPool::BufferRelease(uint32_t buffer_index) { 86 if (buffer_index >= buffers_.size()) { 87 return ZX_ERR_INVALID_ARGS; 88 } 89 if (buffers_[buffer_index].InContainer()) { 90 return ZX_ERR_NOT_FOUND; 91 } 92 // If we are cancelling the in-progress buffer: 93 if (current_buffer_ == buffer_index) { 94 current_buffer_ = kInvalidCurBuffer; 95 } 96 97 free_buffers_.push_front(&buffers_[buffer_index]); 98 return ZX_OK; 99 } 100 CurrentBufferSize() const101uint64_t VmoPool::CurrentBufferSize() const { 102 if (HasBufferInProgress()) { 103 return buffers_[current_buffer_].buffer.size(); 104 } 105 return 0; 106 } CurrentBufferAddress() const107void* VmoPool::CurrentBufferAddress() const { 108 if (HasBufferInProgress()) { 109 return buffers_[current_buffer_].buffer.start(); 110 } 111 return nullptr; 112 } 113 } // namespace fzl 114