Home | History | Annotate | Download | only in core
      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