Skip to content

Commit

Permalink
[fzl] Add a VMO-owning variant of VmoMapper
Browse files Browse the repository at this point in the history
This allows clients to create mappings alongside a vmo,
without necessarily enabling resize semantics.

Test: owned-vmo-mapper-tests in /boot/test/sys/libfzl-test

Change-Id: I8be9e4b40b97dfc0129bfad26d81810afbf63631
  • Loading branch information
Sean Klein authored and CQ bot account: [email protected] committed Nov 5, 2018
1 parent aecb14b commit 12768d7
Show file tree
Hide file tree
Showing 9 changed files with 540 additions and 42 deletions.
70 changes: 70 additions & 0 deletions system/ulib/fzl/include/lib/fzl/owned-vmo-mapper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// 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.

#pragma once

#include <fbl/macros.h>
#include <fbl/ref_ptr.h>
#include <fbl/ref_counted.h>
#include <lib/fzl/vmar-manager.h>
#include <lib/fzl/vmo-mapper.h>
#include <lib/zx/vmo.h>

namespace fzl {

// OwnedVmoWrapper is a convenience wrapper around the underlying VmoMapper
// which also takes ownership of the underlying VMO.
class OwnedVmoMapper : protected VmoMapper {
public:
OwnedVmoMapper() = default;
~OwnedVmoMapper() { Reset(); }
DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(OwnedVmoMapper);

// Move support
OwnedVmoMapper(OwnedVmoMapper&& other) {
MoveFromOther(&other);
}

OwnedVmoMapper& operator=(OwnedVmoMapper&& other) {
Reset();
MoveFromOther(&other);
return *this;
}

// See |VmoMapper::CreateAndMap|.
zx_status_t CreateAndMap(uint64_t size,
const char* name,
zx_vm_option_t map_options = ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
fbl::RefPtr<VmarManager> vmar_manager = nullptr,
uint32_t cache_policy = 0);

// See |VmoMapper::Map|.
zx_status_t Map(zx::vmo vmo,
uint64_t size = 0,
zx_vm_option_t map_options = ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
fbl::RefPtr<VmarManager> vmar_manager = nullptr);

// Reset the VMO from whichever VMAR it was mapped into, then release.
void Reset() {
vmo_.reset();
VmoMapper::Unmap();
}

const zx::vmo& vmo() const { return vmo_; }

using VmoMapper::start;
using VmoMapper::size;
using VmoMapper::manager;

protected:
void MoveFromOther(OwnedVmoMapper* other) {
vmo_ = fbl::move(other->vmo_);
VmoMapper::MoveFromOther(other);
}

private:
zx::vmo vmo_;
};

} // namespace fzl
21 changes: 8 additions & 13 deletions system/ulib/fzl/include/lib/fzl/resizeable-vmo-mapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <fbl/macros.h>
#include <fbl/unique_ptr.h>
#include <lib/fzl/owned-vmo-mapper.h>
#include <lib/fzl/vmar-manager.h>
#include <lib/fzl/vmo-mapper.h>
#include <lib/zx/vmo.h>
Expand All @@ -15,7 +16,7 @@ namespace fzl {
// ResizeableVmoMapper is an extension of the basic VmoMapper utility which
// allows resizing of the mapping after it has been created.
//
class ResizeableVmoMapper : protected VmoMapper {
class ResizeableVmoMapper : protected OwnedVmoMapper {
public:
static fbl::unique_ptr<ResizeableVmoMapper> Create(
uint64_t size,
Expand All @@ -25,7 +26,7 @@ class ResizeableVmoMapper : protected VmoMapper {
uint32_t cache_policy = 0);

ResizeableVmoMapper() = default;
~ResizeableVmoMapper() { Unmap(); }
~ResizeableVmoMapper() { Reset(); }
DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ResizeableVmoMapper);

// Move support
Expand All @@ -34,7 +35,7 @@ class ResizeableVmoMapper : protected VmoMapper {
}

ResizeableVmoMapper& operator=(ResizeableVmoMapper&& other) {
Unmap();
Reset();
MoveFromOther(&other);
return *this;
}
Expand Down Expand Up @@ -74,24 +75,18 @@ class ResizeableVmoMapper : protected VmoMapper {
// Unlike shrinking, it's permissible to grow to a non-page-aligned |size|.
zx_status_t Grow(size_t size);

// Unmap the VMO from whichever VMAR it was mapped into, then release.
void Unmap() {
vmo_.reset();
VmoMapper::Unmap();
}

const zx::vmo& vmo() const { return vmo_; }
using VmoMapper::start;
using VmoMapper::size;
using VmoMapper::manager;
using OwnedVmoMapper::Reset;
using OwnedVmoMapper::vmo;

private:
void MoveFromOther(ResizeableVmoMapper* other) {
vmo_ = fbl::move(other->vmo_);
VmoMapper::MoveFromOther(other);
map_options_ = other->map_options_;
OwnedVmoMapper::MoveFromOther(other);
}

zx::vmo vmo_;
zx_vm_option_t map_options_ = 0;
};

Expand Down
12 changes: 3 additions & 9 deletions system/ulib/fzl/include/lib/fzl/vmo-mapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class VmoMapper {
// cache_policy : When non-zero, indicates the cache policy to apply to the
// created VMO.
zx_status_t CreateAndMap(uint64_t size,
uint32_t map_flags,
zx_vm_option_t map_flags,
fbl::RefPtr<VmarManager> vmar_manager = nullptr,
zx::vmo* vmo_out = nullptr,
zx_rights_t vmo_rights = ZX_RIGHT_SAME_RIGHTS,
Expand All @@ -65,7 +65,7 @@ class VmoMapper {
zx_status_t Map(const zx::vmo& vmo,
uint64_t offset,
uint64_t size,
uint32_t map_flags,
zx_vm_option_t map_flags,
fbl::RefPtr<VmarManager> vmar_manager = nullptr);

// Unmap the VMO from whichever VMAR it was mapped into.
Expand All @@ -80,7 +80,7 @@ class VmoMapper {
zx_status_t InternalMap(const zx::vmo& vmo,
uint64_t offset,
uint64_t size,
uint32_t map_flags,
zx_vm_option_t map_flags,
fbl::RefPtr<VmarManager> vmar_manager);

void MoveFromOther(VmoMapper* other) {
Expand All @@ -98,10 +98,4 @@ class VmoMapper {
uint64_t size_ = 0;
};

class RefCountedVmoMapper : public VmoMapper,
public fbl::RefCounted<VmoMapper> {
public:
RefCountedVmoMapper() = default;
};

} // namespace fzl
46 changes: 46 additions & 0 deletions system/ulib/fzl/owned-vmo-mapper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// 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 <fbl/algorithm.h>
#include <fbl/alloc_checker.h>
#include <lib/fzl/owned-vmo-mapper.h>
#include <string.h>

namespace fzl {

zx_status_t OwnedVmoMapper::CreateAndMap(uint64_t size,
const char* name,
zx_vm_option_t map_options,
fbl::RefPtr<VmarManager> vmar_manager,
uint32_t cache_policy) {
zx::vmo temp;
zx_status_t res = VmoMapper::CreateAndMap(size,
map_options,
fbl::move(vmar_manager),
&temp,
ZX_RIGHT_SAME_RIGHTS,
cache_policy);

if (res == ZX_OK) {
temp.set_property(ZX_PROP_NAME, name, name ? strlen(name) : 0);
vmo_ = fbl::move(temp);
}

return res;
}

zx_status_t OwnedVmoMapper::Map(zx::vmo vmo,
uint64_t size,
zx_vm_option_t map_options,
fbl::RefPtr<VmarManager> vmar_manager) {
zx_status_t res = VmoMapper::Map(vmo, 0, size, map_options, vmar_manager);

if (res == ZX_OK) {
vmo_ = fbl::move(vmo);
}

return res;
}

} // namespace fzl
31 changes: 12 additions & 19 deletions system/ulib/fzl/resizeable-vmo-mapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <fbl/algorithm.h>
#include <fbl/alloc_checker.h>
#include <lib/fzl/owned-vmo-mapper.h>
#include <lib/fzl/resizeable-vmo-mapper.h>
#include <string.h>

Expand Down Expand Up @@ -35,17 +36,10 @@ zx_status_t ResizeableVmoMapper::CreateAndMap(uint64_t size,
fbl::RefPtr<VmarManager> vmar_manager,
uint32_t cache_policy) {
zx::vmo temp;
zx_status_t res = VmoMapper::CreateAndMap(size,
map_options,
fbl::move(vmar_manager),
&temp,
ZX_RIGHT_SAME_RIGHTS,
cache_policy);

zx_status_t res = OwnedVmoMapper::CreateAndMap(size, name, map_options, fbl::move(vmar_manager),
cache_policy);
if (res == ZX_OK) {
temp.set_property(ZX_PROP_NAME, name, name ? strlen(name) : 0);
map_options_ = map_options;
vmo_ = fbl::move(temp);
}

return res;
Expand All @@ -55,18 +49,17 @@ zx_status_t ResizeableVmoMapper::Map(zx::vmo vmo,
uint64_t size,
zx_vm_option_t map_options,
fbl::RefPtr<VmarManager> vmar_manager) {
zx_status_t res = VmoMapper::Map(vmo, 0, size, map_options, vmar_manager);

zx_status_t res = OwnedVmoMapper::Map(fbl::move(vmo), size, map_options,
fbl::move(vmar_manager));
if (res == ZX_OK) {
vmo_ = fbl::move(vmo);
map_options_ = map_options;
}

return res;
}

zx_status_t ResizeableVmoMapper::Shrink(size_t size) {
if (!vmo_.is_valid()) {
if (!vmo().is_valid()) {
return ZX_ERR_BAD_STATE;
} else if (size == 0 || size > size_) {
return ZX_ERR_INVALID_ARGS;
Expand All @@ -83,7 +76,7 @@ zx_status_t ResizeableVmoMapper::Shrink(size_t size) {
}
size_ = size;

if ((status = vmo_.op_range(ZX_VMO_OP_DECOMMIT, size, size_ - size,
if ((status = vmo().op_range(ZX_VMO_OP_DECOMMIT, size, size_ - size,
nullptr, 0)) != ZX_OK) {
// We can tolerate this error; from a client's perspective, the VMO
// still should appear smaller.
Expand All @@ -94,7 +87,7 @@ zx_status_t ResizeableVmoMapper::Shrink(size_t size) {
}

zx_status_t ResizeableVmoMapper::Grow(size_t size) {
if (!vmo_.is_valid()) {
if (!vmo().is_valid()) {
return ZX_ERR_BAD_STATE;
} else if (size < size_) {
return ZX_ERR_INVALID_ARGS;
Expand All @@ -110,7 +103,7 @@ zx_status_t ResizeableVmoMapper::Grow(size_t size) {
return status;
}

if ((status = vmo_.set_size(size)) != ZX_OK) {
if ((status = vmo().set_size(size)) != ZX_OK) {
return status;
}

Expand All @@ -119,20 +112,20 @@ zx_status_t ResizeableVmoMapper::Grow(size_t size) {
if ((status = zx_vmar_map(vmar_handle,
map_options_ | ZX_VM_FLAG_SPECIFIC,
start_ + size_ - vmar_info.base,
vmo_.get(),
vmo().get(),
size_,
size - size_,
&new_start)) != ZX_OK) {
// If extension fails, create entirely new mapping and unmap the old one
if ((status = zx_vmar_map(vmar_handle, map_options_, 0,
vmo_.get(), 0, size, &new_start)) != ZX_OK) {
vmo().get(), 0, size, &new_start)) != ZX_OK) {

// If we could not extend the old mapping, and we cannot create a
// new mapping, then we are done. Attempt to shrink the VMO back to
// its original size. This operation should *never* fail. If it
// does, something has gone insanely wrong and it is time to
// terminate this process.
zx_status_t stat2 = vmo_.set_size(size_);
zx_status_t stat2 = vmo().set_size(size_);
ZX_ASSERT_MSG(stat2 == ZX_OK,
"Failed to shrink to original size (0x%zx -> 0x%lx : res %d)\n",
size, this->size(), stat2);
Expand Down
1 change: 1 addition & 0 deletions system/ulib/fzl/rules.mk
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ MODULE_COMPILEFLAGS += -fvisibility=hidden
MODULE_SRCS += \
$(LOCAL_DIR)/mapped-vmo.cpp \
$(LOCAL_DIR)/memory-probe.cpp \
$(LOCAL_DIR)/owned-vmo-mapper.cpp \
$(LOCAL_DIR)/pinned-vmo.cpp \
$(LOCAL_DIR)/resizeable-vmo-mapper.cpp \
$(LOCAL_DIR)/time.cpp \
Expand Down
2 changes: 1 addition & 1 deletion system/ulib/fzl/vmo-mapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
namespace fzl {

zx_status_t VmoMapper::CreateAndMap(uint64_t size,
uint32_t map_flags,
zx_vm_option_t map_flags,
fbl::RefPtr<VmarManager> vmar_manager,
zx::vmo* vmo_out,
zx_rights_t vmo_rights,
Expand Down
Loading

0 comments on commit 12768d7

Please sign in to comment.