xpcom/base/nsMemoryReporterManager.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef nsMemoryReporterManager_h__
michael@0 8 #define nsMemoryReporterManager_h__
michael@0 9
michael@0 10 #include "nsIMemoryReporter.h"
michael@0 11 #include "nsITimer.h"
michael@0 12 #include "nsServiceManagerUtils.h"
michael@0 13 #include "mozilla/Mutex.h"
michael@0 14 #include "nsTHashtable.h"
michael@0 15 #include "nsHashKeys.h"
michael@0 16
michael@0 17 class nsITimer;
michael@0 18
michael@0 19 namespace mozilla {
michael@0 20 namespace dom {
michael@0 21 class MemoryReport;
michael@0 22 }
michael@0 23 }
michael@0 24
michael@0 25 class nsMemoryReporterManager : public nsIMemoryReporterManager
michael@0 26 {
michael@0 27 public:
michael@0 28 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 29 NS_DECL_NSIMEMORYREPORTERMANAGER
michael@0 30
michael@0 31 nsMemoryReporterManager();
michael@0 32 virtual ~nsMemoryReporterManager();
michael@0 33
michael@0 34 // Gets the memory reporter manager service.
michael@0 35 static nsMemoryReporterManager* GetOrCreate()
michael@0 36 {
michael@0 37 nsCOMPtr<nsIMemoryReporterManager> imgr =
michael@0 38 do_GetService("@mozilla.org/memory-reporter-manager;1");
michael@0 39 return static_cast<nsMemoryReporterManager*>(imgr.get());
michael@0 40 }
michael@0 41
michael@0 42 typedef nsTHashtable<nsRefPtrHashKey<nsIMemoryReporter> > StrongReportersTable;
michael@0 43 typedef nsTHashtable<nsPtrHashKey<nsIMemoryReporter> > WeakReportersTable;
michael@0 44
michael@0 45 void IncrementNumChildProcesses();
michael@0 46 void DecrementNumChildProcesses();
michael@0 47
michael@0 48 // Inter-process memory reporting proceeds as follows.
michael@0 49 //
michael@0 50 // - GetReports() (declared within NS_DECL_NSIMEMORYREPORTERMANAGER)
michael@0 51 // synchronously gets memory reports for the current process, tells all
michael@0 52 // child processes to get memory reports, and sets up some state
michael@0 53 // (mGetReportsState) for when the child processes report back, including a
michael@0 54 // timer. Control then returns to the main event loop.
michael@0 55 //
michael@0 56 // - HandleChildReports() is called (asynchronously) once per child process
michael@0 57 // that reports back. If all child processes report back before time-out,
michael@0 58 // the timer is cancelled. (The number of child processes is part of the
michael@0 59 // saved request state.)
michael@0 60 //
michael@0 61 // - TimeoutCallback() is called (asynchronously) if all the child processes
michael@0 62 // don't respond within the time threshold.
michael@0 63 //
michael@0 64 // - FinishReporting() finishes things off. It is *always* called -- either
michael@0 65 // from HandleChildReports() (if all child processes have reported back) or
michael@0 66 // from TimeoutCallback() (if time-out occurs).
michael@0 67 //
michael@0 68 // All operations occur on the main thread.
michael@0 69 //
michael@0 70 // The above sequence of steps is a "request". A partially-completed request
michael@0 71 // is described as "in flight".
michael@0 72 //
michael@0 73 // Each request has a "generation", a unique number that identifies it. This
michael@0 74 // is used to ensure that each reports from a child process corresponds to
michael@0 75 // the appropriate request from the parent process. (It's easier to
michael@0 76 // implement a generation system than to implement a child report request
michael@0 77 // cancellation mechanism.)
michael@0 78 //
michael@0 79 // Failures are mostly ignored, because it's (a) typically the most sensible
michael@0 80 // thing to do, and (b) often hard to do anything else. The following are
michael@0 81 // the failure cases of note.
michael@0 82 //
michael@0 83 // - If a request is made while the previous request is in flight, the new
michael@0 84 // request is ignored, as per getReports()'s specification. No error is
michael@0 85 // reported, because the previous request will complete soon enough.
michael@0 86 //
michael@0 87 // - If one or more child processes fail to respond within the time limit,
michael@0 88 // things will proceed as if they don't exist. No error is reported,
michael@0 89 // because partial information is better than nothing.
michael@0 90 //
michael@0 91 // - If a child process reports after the time-out occurs, it is ignored.
michael@0 92 // (Generation checking will ensure it is ignored even if a subsequent
michael@0 93 // request is in flight; this is the main use of generations.) No error
michael@0 94 // is reported, because there's nothing sensible to be done about it at
michael@0 95 // this late stage.
michael@0 96 //
michael@0 97 // Now, what what happens if a child process is created/destroyed in the
michael@0 98 // middle of a request? Well, GetReportsState contains a copy of
michael@0 99 // mNumChildProcesses which it uses to determine finished-ness. So...
michael@0 100 //
michael@0 101 // - If a process is created, it won't have received the request for reports,
michael@0 102 // and the GetReportsState's mNumChildProcesses won't account for it. So
michael@0 103 // the reported data will reflect how things were when the request began.
michael@0 104 //
michael@0 105 // - If a process is destroyed before reporting back, we'll just hit the
michael@0 106 // time-out, because we'll have received reports (barring other errors)
michael@0 107 // from N-1 child process. So the reported data will reflect how things
michael@0 108 // are when the request ends.
michael@0 109 //
michael@0 110 // - If a process is destroyed after reporting back, but before all other
michael@0 111 // child processes have reported back, it will be included in the reported
michael@0 112 // data. So the reported data will reflect how things were when the
michael@0 113 // request began.
michael@0 114 //
michael@0 115 // The inconsistencies between these three cases are unfortunate but
michael@0 116 // difficult to avoid. It's enough of an edge case to not be worth doing
michael@0 117 // more.
michael@0 118 //
michael@0 119 void HandleChildReports(
michael@0 120 const uint32_t& generation,
michael@0 121 const InfallibleTArray<mozilla::dom::MemoryReport>& aChildReports);
michael@0 122 nsresult FinishReporting();
michael@0 123
michael@0 124 // Functions that (a) implement distinguished amounts, and (b) are outside of
michael@0 125 // this module.
michael@0 126 struct AmountFns
michael@0 127 {
michael@0 128 mozilla::InfallibleAmountFn mJSMainRuntimeGCHeap;
michael@0 129 mozilla::InfallibleAmountFn mJSMainRuntimeTemporaryPeak;
michael@0 130 mozilla::InfallibleAmountFn mJSMainRuntimeCompartmentsSystem;
michael@0 131 mozilla::InfallibleAmountFn mJSMainRuntimeCompartmentsUser;
michael@0 132
michael@0 133 mozilla::InfallibleAmountFn mImagesContentUsedUncompressed;
michael@0 134
michael@0 135 mozilla::InfallibleAmountFn mStorageSQLite;
michael@0 136
michael@0 137 mozilla::InfallibleAmountFn mLowMemoryEventsVirtual;
michael@0 138 mozilla::InfallibleAmountFn mLowMemoryEventsPhysical;
michael@0 139
michael@0 140 mozilla::InfallibleAmountFn mGhostWindows;
michael@0 141
michael@0 142 AmountFns() { mozilla::PodZero(this); }
michael@0 143 };
michael@0 144 AmountFns mAmountFns;
michael@0 145
michael@0 146 // Convenience function to get RSS easily from other code. This is useful
michael@0 147 // when debugging transient memory spikes with printf instrumentation.
michael@0 148 static int64_t ResidentFast();
michael@0 149
michael@0 150 // Functions that measure per-tab memory consumption.
michael@0 151 struct SizeOfTabFns
michael@0 152 {
michael@0 153 mozilla::JSSizeOfTabFn mJS;
michael@0 154 mozilla::NonJSSizeOfTabFn mNonJS;
michael@0 155
michael@0 156 SizeOfTabFns()
michael@0 157 {
michael@0 158 mozilla::PodZero(this);
michael@0 159 }
michael@0 160 };
michael@0 161 SizeOfTabFns mSizeOfTabFns;
michael@0 162
michael@0 163 private:
michael@0 164 nsresult RegisterReporterHelper(nsIMemoryReporter* aReporter,
michael@0 165 bool aForce, bool aStrongRef);
michael@0 166 nsresult StartGettingReports();
michael@0 167
michael@0 168 static void TimeoutCallback(nsITimer* aTimer, void* aData);
michael@0 169 // Note: this timeout needs to be long enough to allow for the
michael@0 170 // possibility of DMD reports and/or running on a low-end phone.
michael@0 171 static const uint32_t kTimeoutLengthMS = 50000;
michael@0 172
michael@0 173 mozilla::Mutex mMutex;
michael@0 174 bool mIsRegistrationBlocked;
michael@0 175
michael@0 176 StrongReportersTable* mStrongReporters;
michael@0 177 WeakReportersTable* mWeakReporters;
michael@0 178
michael@0 179 // These two are only used for testing purposes.
michael@0 180 StrongReportersTable* mSavedStrongReporters;
michael@0 181 WeakReportersTable* mSavedWeakReporters;
michael@0 182
michael@0 183 uint32_t mNumChildProcesses;
michael@0 184 uint32_t mNextGeneration;
michael@0 185
michael@0 186 struct GetReportsState
michael@0 187 {
michael@0 188 uint32_t mGeneration;
michael@0 189 nsCOMPtr<nsITimer> mTimer;
michael@0 190 uint32_t mNumChildProcesses;
michael@0 191 uint32_t mNumChildProcessesCompleted;
michael@0 192 bool mParentDone;
michael@0 193 nsCOMPtr<nsIHandleReportCallback> mHandleReport;
michael@0 194 nsCOMPtr<nsISupports> mHandleReportData;
michael@0 195 nsCOMPtr<nsIFinishReportingCallback> mFinishReporting;
michael@0 196 nsCOMPtr<nsISupports> mFinishReportingData;
michael@0 197 nsString mDMDDumpIdent;
michael@0 198
michael@0 199 GetReportsState(uint32_t aGeneration, nsITimer* aTimer,
michael@0 200 uint32_t aNumChildProcesses,
michael@0 201 nsIHandleReportCallback* aHandleReport,
michael@0 202 nsISupports* aHandleReportData,
michael@0 203 nsIFinishReportingCallback* aFinishReporting,
michael@0 204 nsISupports* aFinishReportingData,
michael@0 205 const nsAString &aDMDDumpIdent)
michael@0 206 : mGeneration(aGeneration)
michael@0 207 , mTimer(aTimer)
michael@0 208 , mNumChildProcesses(aNumChildProcesses)
michael@0 209 , mNumChildProcessesCompleted(0)
michael@0 210 , mParentDone(false)
michael@0 211 , mHandleReport(aHandleReport)
michael@0 212 , mHandleReportData(aHandleReportData)
michael@0 213 , mFinishReporting(aFinishReporting)
michael@0 214 , mFinishReportingData(aFinishReportingData)
michael@0 215 , mDMDDumpIdent(aDMDDumpIdent)
michael@0 216 {
michael@0 217 }
michael@0 218 };
michael@0 219
michael@0 220 // When this is non-null, a request is in flight. Note: We use manual
michael@0 221 // new/delete for this because its lifetime doesn't match block scope or
michael@0 222 // anything like that.
michael@0 223 GetReportsState* mGetReportsState;
michael@0 224 };
michael@0 225
michael@0 226 #define NS_MEMORY_REPORTER_MANAGER_CID \
michael@0 227 { 0xfb97e4f5, 0x32dd, 0x497a, \
michael@0 228 { 0xba, 0xa2, 0x7d, 0x1e, 0x55, 0x7, 0x99, 0x10 } }
michael@0 229
michael@0 230 #endif // nsMemoryReporterManager_h__

mercurial