Bug 1335148 - Part 2: Introduce notification for end of memory pressure. r?gsvelto
For Fennec on Android, if we haven't received memory pressure notifications from
the OS for a certain amount of time (in the order of ~15 mins), we assume that
we're no longer under memory pressure. In order to turn the bfcache back on when
that happens, we now want to be able to forward this fact to Gecko as well.
Unfortunately, the way memory pressure is tracked using an atomic variable
doesn't easily allow to fully extend the existing priority rules between "new"
and "ongoing" to include a new "stopping of memory pressure" event. Since we're
not using Dispatch*Eventual*MemoryPressure on Android and therefore the queuing
priority behaviour isn't actually relevant for us, we just ignore that and only
enforce that a pending "new" memory pressure event takes priority over a "stop"
event.
MozReview-Commit-ID: 90C9KogUyvf
--- a/xpcom/threads/nsMemoryPressure.cpp
+++ b/xpcom/threads/nsMemoryPressure.cpp
@@ -22,30 +22,31 @@ NS_GetPendingMemoryPressure()
int32_t value = sMemoryPressurePending.exchange(MemPressure_None);
return MemoryPressureState(value);
}
void
NS_DispatchEventualMemoryPressure(MemoryPressureState aState)
{
/*
- * A new memory pressure event erases an ongoing memory pressure, but an
- * existing "new" memory pressure event takes precedence over a new "ongoing"
- * memory pressure event.
+ * A new memory pressure event erases an ongoing (or stop of) memory pressure,
+ * but an existing "new" memory pressure event takes precedence over a new
+ * "ongoing" or "stop" memory pressure event.
*/
switch (aState) {
case MemPressure_None:
sMemoryPressurePending = MemPressure_None;
break;
case MemPressure_New:
sMemoryPressurePending = MemPressure_New;
break;
case MemPressure_Ongoing:
+ case MemPressure_Stopping:
sMemoryPressurePending.compareExchange(MemPressure_None,
- MemPressure_Ongoing);
+ aState);
break;
}
}
nsresult
NS_DispatchMemoryPressure(MemoryPressureState aState)
{
NS_DispatchEventualMemoryPressure(aState);
--- a/xpcom/threads/nsMemoryPressure.h
+++ b/xpcom/threads/nsMemoryPressure.h
@@ -35,17 +35,28 @@ enum MemoryPressureState
*
* In case of conflict with an new memory pressue, the new memory pressure
* takes precedence over an ongoing memory pressure. The reason being
* that if no events are processed between 2 notifications (new followed
* by ongoing, or ongoing followed by a new) we want to be as aggresive as
* possible on the clean-up of the memory. After all, we are trying to
* keep Gecko alive as long as possible.
*/
- MemPressure_Ongoing
+ MemPressure_Ongoing,
+
+ /*
+ * Memory pressure stopped.
+ *
+ * We're no longer under acute memory pressure, so we might want to have a
+ * chance of (cautiously) re-enabling some things we previously turned off.
+ * As above, an already enqueued new memory pressure event takes precedence.
+ * The priority ordering between concurrent attempts to queue both stopped
+ * and ongoing memory pressure is currently not defined.
+ */
+ MemPressure_Stopping
};
/**
* Return and erase the latest state of the memory pressure event set by any of
* the corresponding dispatch function.
*/
MemoryPressureState
NS_GetPendingMemoryPressure();
--- a/xpcom/threads/nsThread.cpp
+++ b/xpcom/threads/nsThread.cpp
@@ -1263,21 +1263,25 @@ nsThread::DoMainThreadSpecificProcessing
// Fire a memory pressure notification, if one is pending.
if (!ShuttingDown()) {
MemoryPressureState mpPending = NS_GetPendingMemoryPressure();
if (mpPending != MemPressure_None) {
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
if (os) {
- // Use no-forward to prevent the notifications from being transferred to
- // the children of this process.
- os->NotifyObservers(nullptr, "memory-pressure",
- mpPending == MemPressure_New ? u"low-memory-no-forward" :
- u"low-memory-ongoing-no-forward");
+ if (mpPending == MemPressure_Stopping) {
+ os->NotifyObservers(nullptr, "memory-pressure-stop", nullptr);
+ } else {
+ // Use no-forward to prevent the notifications from being transferred to
+ // the children of this process.
+ os->NotifyObservers(nullptr, "memory-pressure",
+ mpPending == MemPressure_New ? u"low-memory-no-forward" :
+ u"low-memory-ongoing-no-forward");
+ }
} else {
NS_WARNING("Can't get observer service!");
}
}
}
if (!ShuttingDown()) {
SaveMemoryReportNearOOM(ShouldSaveMemoryReport::kMaybeReport);