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/. */
6 
7 #include <math.h>
8 
9 #include "nsString.h"
10 #include "nsIMemoryReporter.h"
11 #include "mozilla/ipc/SharedMemory.h"
12 #include "mozilla/Atomics.h"
13 
14 namespace mozilla {
15 namespace ipc {
16 
17 static Atomic<size_t> gShmemAllocated;
18 static Atomic<size_t> gShmemMapped;
19 
20 class ShmemReporter final : public nsIMemoryReporter
21 {
~ShmemReporter()22   ~ShmemReporter() {}
23 
24 public:
25   NS_DECL_THREADSAFE_ISUPPORTS
26 
27   NS_IMETHOD
CollectReports(nsIHandleReportCallback * aHandleReport,nsISupports * aData,bool aAnonymize)28   CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
29                  bool aAnonymize) override
30   {
31     MOZ_COLLECT_REPORT(
32       "shmem-allocated", KIND_OTHER, UNITS_BYTES, gShmemAllocated,
33       "Memory shared with other processes that is accessible (but not "
34       "necessarily mapped).");
35 
36     MOZ_COLLECT_REPORT(
37       "shmem-mapped", KIND_OTHER, UNITS_BYTES, gShmemMapped,
38       "Memory shared with other processes that is mapped into the address "
39       "space.");
40 
41     return NS_OK;
42   }
43 };
44 
NS_IMPL_ISUPPORTS(ShmemReporter,nsIMemoryReporter)45 NS_IMPL_ISUPPORTS(ShmemReporter, nsIMemoryReporter)
46 
47 SharedMemory::SharedMemory()
48   : mAllocSize(0)
49   , mMappedSize(0)
50 {
51   static Atomic<bool> registered;
52   if (registered.compareExchange(false, true)) {
53     RegisterStrongMemoryReporter(new ShmemReporter());
54   }
55 }
56 
57 /*static*/ size_t
PageAlignedSize(size_t aSize)58 SharedMemory::PageAlignedSize(size_t aSize)
59 {
60   size_t pageSize = SystemPageSize();
61   size_t nPagesNeeded = size_t(ceil(double(aSize) / double(pageSize)));
62   return pageSize * nPagesNeeded;
63 }
64 
65 void
Created(size_t aNBytes)66 SharedMemory::Created(size_t aNBytes)
67 {
68   mAllocSize = aNBytes;
69   gShmemAllocated += mAllocSize;
70 }
71 
72 void
Mapped(size_t aNBytes)73 SharedMemory::Mapped(size_t aNBytes)
74 {
75   mMappedSize = aNBytes;
76   gShmemMapped += mMappedSize;
77 }
78 
79 void
Unmapped()80 SharedMemory::Unmapped()
81 {
82   MOZ_ASSERT(gShmemMapped >= mMappedSize,
83              "Can't unmap more than mapped");
84   gShmemMapped -= mMappedSize;
85   mMappedSize = 0;
86 }
87 
88 /*static*/ void
Destroyed()89 SharedMemory::Destroyed()
90 {
91   MOZ_ASSERT(gShmemAllocated >= mAllocSize,
92              "Can't destroy more than allocated");
93   gShmemAllocated -= mAllocSize;
94   mAllocSize = 0;
95 }
96 
97 } // namespace ipc
98 } // namespace mozilla
99