1 // Copyright 2018 The Chromium 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 "mojo/core/platform_shared_memory_mapping.h"
6
7 #include <utility>
8
9 #include "base/logging.h"
10 #include "base/memory/read_only_shared_memory_region.h"
11 #include "base/memory/unsafe_shared_memory_region.h"
12 #include "base/memory/writable_shared_memory_region.h"
13 #include "base/sys_info.h"
14 #include "build/build_config.h"
15
16 #if defined(OS_NACL)
17 // For getpagesize() on NaCl.
18 #include <unistd.h>
19 #endif
20
21 namespace mojo {
22 namespace core {
23
24 namespace {
25
GetPageSize()26 size_t GetPageSize() {
27 #if defined(OS_NACL)
28 // base::SysInfo isn't available under NaCl.
29 return getpagesize();
30 #else
31 return base::SysInfo::VMAllocationGranularity();
32 #endif
33 }
34
35 } // namespace
36
PlatformSharedMemoryMapping(base::subtle::PlatformSharedMemoryRegion * region,size_t offset,size_t length)37 PlatformSharedMemoryMapping::PlatformSharedMemoryMapping(
38 base::subtle::PlatformSharedMemoryRegion* region,
39 size_t offset,
40 size_t length)
41 : type_(region->GetMode() ==
42 base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly
43 ? Type::kReadOnly
44 : Type::kWritable),
45 offset_(offset),
46 length_(length) {
47 // Mojo shared buffers can be mapped at any offset, but //base shared memory
48 // regions must be mapped at a page boundary. We calculate the nearest whole
49 // page offset and map from there.
50 size_t offset_rounding = offset_ % GetPageSize();
51 off_t real_offset = static_cast<off_t>(offset_ - offset_rounding);
52 size_t real_length = length_ + offset_rounding;
53 void* mapped_memory = nullptr;
54 if (type_ == Type::kReadOnly) {
55 auto read_only_region =
56 base::ReadOnlySharedMemoryRegion::Deserialize(std::move(*region));
57 auto read_only_mapping = read_only_region.MapAt(real_offset, real_length);
58 mapped_memory = const_cast<void*>(read_only_mapping.memory());
59 mapping_ = std::make_unique<base::ReadOnlySharedMemoryMapping>(
60 std::move(read_only_mapping));
61 *region = base::ReadOnlySharedMemoryRegion::TakeHandleForSerialization(
62 std::move(read_only_region));
63 } else if (region->GetMode() ==
64 base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe) {
65 auto unsafe_region =
66 base::UnsafeSharedMemoryRegion::Deserialize(std::move(*region));
67 auto writable_mapping = unsafe_region.MapAt(real_offset, real_length);
68 mapped_memory = writable_mapping.memory();
69 mapping_ = std::make_unique<base::WritableSharedMemoryMapping>(
70 std::move(writable_mapping));
71 *region = base::UnsafeSharedMemoryRegion::TakeHandleForSerialization(
72 std::move(unsafe_region));
73 } else {
74 DCHECK_EQ(region->GetMode(),
75 base::subtle::PlatformSharedMemoryRegion::Mode::kWritable);
76 auto writable_region =
77 base::WritableSharedMemoryRegion::Deserialize(std::move(*region));
78 auto writable_mapping = writable_region.MapAt(real_offset, real_length);
79 mapped_memory = writable_mapping.memory();
80 mapping_ = std::make_unique<base::WritableSharedMemoryMapping>(
81 std::move(writable_mapping));
82 *region = base::WritableSharedMemoryRegion::TakeHandleForSerialization(
83 std::move(writable_region));
84 }
85
86 base_ = static_cast<char*>(mapped_memory) + offset_rounding;
87 }
88
89 PlatformSharedMemoryMapping::~PlatformSharedMemoryMapping() = default;
90
IsValid() const91 bool PlatformSharedMemoryMapping::IsValid() const {
92 return mapping_ && mapping_->IsValid();
93 }
94
GetBase() const95 void* PlatformSharedMemoryMapping::GetBase() const {
96 return base_;
97 }
98
GetLength() const99 size_t PlatformSharedMemoryMapping::GetLength() const {
100 return length_;
101 }
102
103 } // namespace core
104 } // namespace mojo
105