Bug 670967 - Part 1: Add mozilla::ScheduleMemoryPressureEvent(). r=bsmedberg
authorJustin Lebar <justin.lebar@gmail.com>
Fri, 05 Aug 2011 18:10:50 -0400
changeset 82698 cf3603911e0122e19352f59946a0b8887f0c4554
parent 82697 c8b8b310f27e69af12083f12e812b1e590417b5a
child 82699 8348c44ba1ca0e2c0a0f7e06d27ee45294a8b6d2
push id4069
push userjlebar@mozilla.com
push dateThu, 15 Dec 2011 20:07:10 +0000
treeherdermozilla-inbound@037728a4556f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg
bugs670967
milestone11.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 670967 - Part 1: Add mozilla::ScheduleMemoryPressureEvent(). r=bsmedberg
xpcom/threads/Makefile.in
xpcom/threads/nsThread.cpp
xpcom/threads/nsThread.h
--- a/xpcom/threads/Makefile.in
+++ b/xpcom/threads/Makefile.in
@@ -59,16 +59,17 @@ CPPSRCS		= \
 		nsThreadPool.cpp \
 		nsProcessCommon.cpp \
 		nsTimerImpl.cpp \
 		TimerThread.cpp \
 		HangMonitor.cpp \
 		$(NULL)
 
 EXPORTS		= \
+		nsThread.h \
 		nsProcess.h \
 		nsEventQueue.h \
 		nsThreadUtilsInternal.h \
 		$(NULL)
 
 EXPORTS_mozilla = \
   HangMonitor.h \
   $(NULL)
--- a/xpcom/threads/nsThread.cpp
+++ b/xpcom/threads/nsThread.cpp
@@ -40,17 +40,19 @@
 #include "nsThread.h"
 #include "nsThreadManager.h"
 #include "nsIClassInfoImpl.h"
 #include "nsIProgrammingLanguage.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "prlog.h"
 #include "nsThreadUtilsInternal.h"
+#include "nsIObserverService.h"
 #include "mozilla/HangMonitor.h"
+#include "mozilla/Services.h"
 
 #define HAVE_UALARM _BSD_SOURCE || (_XOPEN_SOURCE >= 500 ||                 \
                       _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) &&           \
                       !(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
 
 #if defined(XP_UNIX) && !defined(ANDROID) && !defined(DEBUG) && HAVE_UALARM \
   && defined(_GNU_SOURCE)
 # define MOZ_CANARY
@@ -76,16 +78,33 @@ using namespace mozilla;
 static PRLogModuleInfo *sLog = PR_NewLogModule("nsThread");
 #endif
 #define LOG(args) PR_LOG(sLog, PR_LOG_DEBUG, args)
 
 NS_DECL_CI_INTERFACE_GETTER(nsThread)
 
 nsIThreadObserver* nsThread::sGlobalObserver;
 
+namespace mozilla {
+
+// Fun fact: Android's GCC won't convert bool* to PRInt32*, so we can't
+// PR_ATOMIC_SET a bool.
+static PRInt32 sMemoryPressurePending = 0;
+
+/*
+ * It's important that this function not acquire any locks, nor do anything
+ * which might cause malloc to run.
+ */
+void ScheduleMemoryPressureEvent()
+{
+  PR_ATOMIC_SET(&sMemoryPressurePending, 1);
+}
+
+};
+
 //-----------------------------------------------------------------------------
 // Because we do not have our own nsIFactory, we have to implement nsIClassInfo
 // somewhat manually.
 
 class nsThreadClassInfo : public nsIClassInfo {
 public:
   NS_DECL_ISUPPORTS_INHERITED  // no mRefCnt
   NS_DECL_NSICLASSINFO
@@ -572,16 +591,32 @@ nsThread::ProcessNextEvent(bool mayWait,
 {
   LOG(("THRD(%p) ProcessNextEvent [%u %u]\n", this, mayWait, mRunningEvent));
 
   NS_ENSURE_STATE(PR_GetCurrentThread() == mThread);
 
   if (MAIN_THREAD == mIsMainThread && mayWait && !ShuttingDown())
     HangMonitor::Suspend();
 
+  // Fire a memory pressure notification, if we're the main thread and one is
+  // pending.
+  if (MAIN_THREAD == mIsMainThread && !ShuttingDown()) {
+    bool mpPending = PR_ATOMIC_SET(&sMemoryPressurePending, 0);
+    if (mpPending) {
+      nsCOMPtr<nsIObserverService> os = services::GetObserverService();
+      if (os) {
+        os->NotifyObservers(nsnull, "memory-pressure",
+                            NS_LITERAL_STRING("low-memory").get());
+      }
+      else {
+        NS_WARNING("Can't get observer service!");
+      }
+    }
+  }
+
   bool notifyGlobalObserver = (sGlobalObserver != nsnull);
   if (notifyGlobalObserver) 
     sGlobalObserver->OnProcessNextEvent(this, mayWait && !ShuttingDown(),
                                         mRunningEvent);
 
   nsCOMPtr<nsIThreadObserver> obs = mObserver;
   if (obs)
     obs->OnProcessNextEvent(this, mayWait && !ShuttingDown(), mRunningEvent);
--- a/xpcom/threads/nsThread.h
+++ b/xpcom/threads/nsThread.h
@@ -173,9 +173,21 @@ public:
 private:
   NS_DECL_NSIRUNNABLE
 
   nsCOMPtr<nsIThread> mOrigin;
   nsCOMPtr<nsIRunnable> mSyncTask;
   nsresult mResult;
 };
 
+namespace mozilla {
+
+/**
+ * This function causes the main thread to fire a memory pressure event at its
+ * next available opportunity.
+ *
+ * You may call this function from any thread.
+ */
+void ScheduleMemoryPressureEvent();
+
+} // namespace mozilla
+
 #endif  // nsThread_h__