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