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 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 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 91 bool PlatformSharedMemoryMapping::IsValid() const { 92 return mapping_ && mapping_->IsValid(); 93 } 94 95 void* PlatformSharedMemoryMapping::GetBase() const { 96 return base_; 97 } 98 99 size_t PlatformSharedMemoryMapping::GetLength() const { 100 return length_; 101 } 102 103 } // namespace core 104 } // namespace mojo 105