1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* This source code was derived from Chromium code, and as such is also subject
8 * to the [Chromium license](ipc/chromium/src/LICENSE). */
10 #include "mozilla/ipc/SharedMemoryHandle.h"
11 #include "mozilla/ipc/SharedMemoryMapping.h"
12 #include "SharedMemoryPlatform.h"
14 #include "chrome/common/ipc_message_utils.h"
15 #include "mozilla/Atomics.h"
17 #include "nsIMemoryReporter.h"
19 namespace mozilla::ipc::shared_memory
{
21 // Implementation of the shared memory logger in SharedMemoryPlatform.h.
22 LazyLogModule gSharedMemoryLog
{"SharedMemory"};
24 class AllocationReporter final
: public nsIMemoryReporter
{
25 ~AllocationReporter() = default;
28 static Atomic
<uint64_t> allocated
;
30 NS_DECL_THREADSAFE_ISUPPORTS
33 CollectReports(nsIHandleReportCallback
* aHandleReport
, nsISupports
* aData
,
34 bool aAnonymize
) override
{
36 "shmem-allocated", KIND_OTHER
, UNITS_BYTES
, allocated
,
37 "Memory shared with other processes that is accessible (but not "
38 "necessarily mapped).");
44 Atomic
<uint64_t> AllocationReporter::allocated
;
46 NS_IMPL_ISUPPORTS(AllocationReporter
, nsIMemoryReporter
)
48 static void RegisterMemoryReporter() {
49 static Atomic
<bool> registered
;
50 if (registered
.compareExchange(false, true)) {
51 RegisterStrongMemoryReporter(new AllocationReporter());
55 HandleBase::HandleBase() { RegisterMemoryReporter(); }
57 HandleBase::~HandleBase() {
58 MOZ_ASSERT(AllocationReporter::allocated
>= mSize
,
59 "Can't destroy more than allocated");
60 AllocationReporter::allocated
-= mSize
;
65 HandleBase
HandleBase::Clone() const {
67 hb
.mHandle
= Platform::CloneHandle(mHandle
);
70 // TODO more intelligently handle clones to not count as addition
72 AllocationReporter::allocated
+= mSize
;
77 void HandleBase::ToMessageWriter(IPC::MessageWriter
* aWriter
) && {
78 WriteParam(aWriter
, std::move(mHandle
));
79 WriteParam(aWriter
, std::exchange(mSize
, 0));
82 bool HandleBase::FromMessageReader(IPC::MessageReader
* aReader
) {
83 mozilla::ipc::shared_memory::PlatformHandle handle
;
84 if (!ReadParam(aReader
, &handle
)) {
87 if (handle
&& !Platform::IsSafeToMap(handle
)) {
90 mHandle
= std::move(handle
);
91 if (!ReadParam(aReader
, &mSize
)) {
94 mozilla::ipc::shared_memory::AllocationReporter::allocated
+= mSize
;
98 Mapping
Handle::Map(void* aFixedAddress
) const {
99 return Mapping(*this, aFixedAddress
);
102 ReadOnlyMapping
ReadOnlyHandle::Map(void* aFixedAddress
) const {
103 return ReadOnlyMapping(*this, aFixedAddress
);
106 FreezableHandle::~FreezableHandle() {
107 NS_WARNING_ASSERTION(!IsValid(), "freezable shared memory was never frozen");
110 Handle
FreezableHandle::WontFreeze() && {
111 return std::move(*this).ConvertTo
<Handle
>();
114 ReadOnlyHandle
FreezableHandle::Freeze() && {
115 DebugOnly
<const uint64_t> previous_size
= Size();
116 if (Platform::Freeze(*this)) {
117 MOZ_ASSERT(Size() == previous_size
);
118 return std::move(*this).ConvertTo
<ReadOnlyHandle
>();
123 FreezableMapping
FreezableHandle::Map(void* aFixedAddress
) && {
124 return FreezableMapping(std::move(*this), aFixedAddress
);
127 Handle
Create(uint64_t aSize
) {
129 const auto success
= Platform::Create(h
, aSize
);
130 MOZ_ASSERT(success
== h
.IsValid());
132 MOZ_ASSERT(aSize
== h
.Size());
133 AllocationReporter::allocated
+= h
.Size();
138 FreezableHandle
CreateFreezable(uint64_t aSize
) {
140 const auto success
= Platform::CreateFreezable(h
, aSize
);
141 MOZ_ASSERT(success
== h
.IsValid());
143 MOZ_ASSERT(aSize
== h
.Size());
144 AllocationReporter::allocated
+= h
.Size();
149 } // namespace mozilla::ipc::shared_memory
153 void ParamTraits
<mozilla::ipc::shared_memory::Handle
>::Write(
154 MessageWriter
* aWriter
, mozilla::ipc::shared_memory::Handle
&& aParam
) {
155 std::move(aParam
).ToMessageWriter(aWriter
);
158 bool ParamTraits
<mozilla::ipc::shared_memory::Handle
>::Read(
159 MessageReader
* aReader
, mozilla::ipc::shared_memory::Handle
* aResult
) {
160 return aResult
->FromMessageReader(aReader
);
163 void ParamTraits
<mozilla::ipc::shared_memory::ReadOnlyHandle
>::Write(
164 MessageWriter
* aWriter
,
165 mozilla::ipc::shared_memory::ReadOnlyHandle
&& aParam
) {
166 std::move(aParam
).ToMessageWriter(aWriter
);
169 bool ParamTraits
<mozilla::ipc::shared_memory::ReadOnlyHandle
>::Read(
170 MessageReader
* aReader
,
171 mozilla::ipc::shared_memory::ReadOnlyHandle
* aResult
) {
172 return aResult
->FromMessageReader(aReader
);