bug 452489 - removes the flusher timer and fixes osso low memory predicate. also fixes OSSO oom predicate. r=bsmedberg
☠☠ backed out by 7b1a78842d4a ☠ ☠
authorDoug Turner <dougt@meer.net>
Mon, 01 Sep 2008 17:40:15 -0700
changeset 18562 6b6054736cb2837fabf68ac42238ca122ddd66f8
parent 18561 aa4bd40eef6c56ccc9864e6e73d18bfdad2b8380
child 18563 c215eeae1039aa1f1bf184aca58f0faab97bd76f
child 18564 7b1a78842d4ae56f7d3b0faff352611d94c1ab96
push id1645
push userdougt@mozilla.com
push dateTue, 02 Sep 2008 00:41:00 +0000
treeherdermozilla-central@6b6054736cb2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg
bugs452489
milestone1.9.1b1pre
bug 452489 - removes the flusher timer and fixes osso low memory predicate. also fixes OSSO oom predicate. r=bsmedberg
xpcom/base/nsMemoryImpl.cpp
xpcom/base/nsMemoryImpl.h
xpcom/build/nsXPComInit.cpp
--- a/xpcom/base/nsMemoryImpl.cpp
+++ b/xpcom/base/nsMemoryImpl.cpp
@@ -35,127 +35,38 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsXPCOM.h"
 #include "nsMemoryImpl.h"
 #include "nsThreadUtils.h"
 
 #include "nsIObserverService.h"
+#include "nsIObserver.h"
 #include "nsIServiceManager.h"
 #include "nsISupportsArray.h"
 
 #include "prmem.h"
 #include "prcvar.h"
 #include "pratom.h"
 
 #include "nsAlgorithm.h"
 #include "nsAutoLock.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 
 #if defined(XP_WIN)
 #include <windows.h>
-#define NS_MEMORY_FLUSHER
 #elif defined (NS_OSSO)
 #include <osso-mem.h>
-#else
-// Need to implement the nsIMemory::IsLowMemory() predicate
-#undef NS_MEMORY_FLUSHER
-#endif
-
-#ifdef NS_MEMORY_FLUSHER
-#include "nsITimer.h"
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-// Define NS_OUT_OF_MEMORY_TESTER if you want to force memory failures
-
-#ifdef DEBUG_xwarren
-#define NS_OUT_OF_MEMORY_TESTER
+#include <fcntl.h>
+#include <unistd.h>
+const char* kHighMark = "/sys/kernel/high_watermark";
 #endif
 
-#ifdef NS_OUT_OF_MEMORY_TESTER
-
-// flush memory one in this number of times:
-#define NS_FLUSH_FREQUENCY        100000
-
-// fail allocation one in this number of flushes:
-#define NS_FAIL_FREQUENCY         10
-
-PRUint32 gFlushFreq = 0;
-PRUint32 gFailFreq = 0;
-
-static void*
-mallocator(PRSize size, PRUint32& counter, PRUint32 max)
-{
-    if (counter++ >= max) {
-        counter = 0;
-        NS_ASSERTION(0, "about to fail allocation... watch out");
-        return nsnull;
-    }
-    return PR_Malloc(size);
-}
-
-static void*
-reallocator(void* ptr, PRSize size, PRUint32& counter, PRUint32 max)
-{
-    if (counter++ >= max) {
-        counter = 0;
-        NS_ASSERTION(0, "about to fail reallocation... watch out");
-        return nsnull;
-    }
-    return PR_Realloc(ptr, size);
-}
-
-#define MALLOC1(s)       mallocator(s, gFlushFreq, NS_FLUSH_FREQUENCY)
-#define REALLOC1(p, s)   reallocator(p, s, gFlushFreq, NS_FLUSH_FREQUENCY)
-
-#else
-
-#define MALLOC1(s)       PR_Malloc(s)
-#define REALLOC1(p, s)   PR_Realloc(p, s)
-
-#endif // NS_OUT_OF_MEMORY_TESTER
-
-#if defined(XDEBUG_waterson)
-#define NS_TEST_MEMORY_FLUSHER
-#endif
-
-#ifdef NS_MEMORY_FLUSHER
-/**
- * A class that is used to periodically check the status of the system,
- * determine if too much memory is in use, and if so, trigger a "memory flush".
- */
-class MemoryFlusher : public nsITimerCallback
-{
-public:
-    // We don't use the generic macros because we are a special static object
-    NS_IMETHOD QueryInterface(REFNSIID aIID, void** aResult);
-    NS_IMETHOD_(nsrefcnt) AddRef(void) { return 2; }
-    NS_IMETHOD_(nsrefcnt) Release(void) { return 1; }
-
-    NS_DECL_NSITIMERCALLBACK
-
-    nsresult Init();
-    void StopAndJoin();
-
-private:
-    static PRIntervalTime sTimeout;
-    static PRLock*        sLock;
-    static PRCondVar*     sCVar;
-    
-    enum {
-        kTimeout = 60000 // milliseconds
-    };
-};
-
-static MemoryFlusher sGlobalMemoryFlusher;
-
-#endif // NS_MEMORY_FLUSHER
 
 static nsMemoryImpl sGlobalMemory;
 
 NS_IMPL_QUERY_INTERFACE1(nsMemoryImpl, nsIMemory)
 
 NS_IMETHODIMP_(void*)
 nsMemoryImpl::Alloc(PRSize size)
 {
@@ -187,42 +98,32 @@ nsMemoryImpl::IsLowMemory(PRBool *result
     MEMORYSTATUS stat;
     GlobalMemoryStatus(&stat);
     *result = ((float)stat.dwAvailPhys / stat.dwTotalPhys) < 0.1;
 #elif defined(XP_WIN)
     MEMORYSTATUS stat;
     GlobalMemoryStatus(&stat);
     *result = ((float)stat.dwAvailPageFile / stat.dwTotalPageFile) < 0.1;
 #elif defined(NS_OSSO)
-    osso_mem_usage_t usage;
-    osso_mem_get_usage(&usage);
-    
-    // According to the docs, low memory limit isn't set if it is
-    // zero, or if it is greater than 100%.
-    if (usage.low == 0 || usage.low > usage.total)
-      *result = PR_FALSE;
-    else
-      *result = (PRBool) usage.low <= usage.used;
+
+    int fd = open (kHighMark, O_RDONLY);
+    if (fd == -1) {
+        *result = PR_FALSE;
+        return NS_OK;
+    }
+    int c = 0;
+    read (fd, &c, 1);
+    close(fd);
+    *result = (c == '1');
 #else
     *result = PR_FALSE;
 #endif
     return NS_OK;
 }
 
-
-/*static*/ nsresult 
-nsMemoryImpl::InitFlusher()
-{
-#ifdef NS_MEMORY_FLUSHER
-    return sGlobalMemoryFlusher.Init();
-#else
-    return NS_OK;
-#endif
-}
-
 /*static*/ nsresult
 nsMemoryImpl::Create(nsISupports* outer, const nsIID& aIID, void **aResult)
 {
     NS_ENSURE_NO_AGGREGATION(outer);
     return sGlobalMemory.QueryInterface(aIID, aResult);
 }
 
 nsresult
@@ -252,22 +153,52 @@ nsMemoryImpl::FlushMemory(const PRUnicha
     else {
         sFlushEvent.mReason = aReason;
         rv = NS_DispatchToMainThread(&sFlushEvent, NS_DISPATCH_NORMAL);
     }
 
     return rv;
 }
 
+#ifdef GET_OOM_STATS
+static long getUsedMemory()
+{
+#ifdef NS_OSSO
+    osso_mem_usage_t usage;
+    osso_mem_get_usage(&usage);
+    return usage.used;
+#else
+    return 0;
+#endif
+}
+#endif
+
 nsresult
 nsMemoryImpl::RunFlushers(const PRUnichar* aReason)
 {
     nsCOMPtr<nsIObserverService> os = do_GetService("@mozilla.org/observer-service;1");
     if (os) {
-        os->NotifyObservers(this, "memory-pressure", aReason);
+
+        nsCOMPtr<nsISimpleEnumerator> theEnum;
+        os->EnumerateObservers("memory-pressure", getter_AddRefs(theEnum));
+        
+        nsCOMPtr<nsIObserver> elem;
+        PRBool loop;
+        while (NS_SUCCEEDED(theEnum->HasMoreElements(&loop)) && loop) {
+            theEnum->GetNext(getter_AddRefs(elem));
+
+#ifdef GET_OOM_STATS
+            long before = getUsedMemory();
+#endif
+            elem->Observe(this, "memory-pressure", aReason);
+
+#ifdef GET_OOM_STATS
+            printf("Memory Purged: %ld\n", before - getUsedMemory());
+#endif
+        }
     }
 
     sIsFlushing = 0;
     return NS_OK;
 }
 
 // XXX need NS_IMPL_STATIC_ADDREF/RELEASE
 NS_IMETHODIMP_(nsrefcnt) nsMemoryImpl::FlushEvent::AddRef() { return 2; }
@@ -285,75 +216,38 @@ PRInt32
 nsMemoryImpl::sIsFlushing = 0;
 
 nsMemoryImpl::FlushEvent
 nsMemoryImpl::sFlushEvent;
 
 XPCOM_API(void*)
 NS_Alloc(PRSize size)
 {
-    void* result = MALLOC1(size);
+    void* result = PR_Malloc(size);
     if (! result) {
         // Request an asynchronous flush
         sGlobalMemory.FlushMemory(NS_LITERAL_STRING("alloc-failure").get(), PR_FALSE);
     }
     return result;
 }
 
 XPCOM_API(void*)
 NS_Realloc(void* ptr, PRSize size)
 {
-    void* result = REALLOC1(ptr, size);
+    void* result = PR_Realloc(ptr, size);
     if (! result && size != 0) {
         // Request an asynchronous flush
         sGlobalMemory.FlushMemory(NS_LITERAL_STRING("alloc-failure").get(), PR_FALSE);
     }
     return result;
 }
 
 XPCOM_API(void)
 NS_Free(void* ptr)
 {
     PR_Free(ptr);
 }
 
-#ifdef NS_MEMORY_FLUSHER
-
-NS_IMPL_QUERY_INTERFACE1(MemoryFlusher, nsITimerCallback)
-
-NS_IMETHODIMP
-MemoryFlusher::Notify(nsITimer *timer)
-{
-    PRBool isLowMemory;
-    sGlobalMemory.IsLowMemory(&isLowMemory);
-
-#ifdef NS_TEST_MEMORY_FLUSHER
-    // Fire the flusher *every* time
-    isLowMemory = PR_TRUE;
-#endif
-
-    if (isLowMemory)
-        sGlobalMemory.FlushMemory(NS_LITERAL_STRING("low-memory").get(),
-                                  PR_FALSE);
-    return NS_OK;
-}
-
-nsresult
-MemoryFlusher::Init()
-{
-    nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
-    NS_ENSURE_STATE(timer);
-
-    // There is no need to keep a reference to the timer object because we
-    // don't need to kill the timer.  It will be killed automatically when
-    // XPCOM is shutdown.
-
-    return timer->InitWithCallback(this, kTimeout,
-                                   nsITimer::TYPE_REPEATING_SLACK);
-}
-
-#endif // NS_MEMORY_FLUSHER
-
 nsresult
 NS_GetMemoryManager(nsIMemory* *result)
 {
     return sGlobalMemory.QueryInterface(NS_GET_IID(nsIMemory), (void**) result);
 }
--- a/xpcom/base/nsMemoryImpl.h
+++ b/xpcom/base/nsMemoryImpl.h
@@ -50,17 +50,16 @@ class nsMemoryImpl : public nsIMemory
 public:
     // We don't use the generic macros because we are a special static object
     NS_IMETHOD QueryInterface(REFNSIID aIID, void** aResult);
     NS_IMETHOD_(nsrefcnt) AddRef(void) { return 1; }
     NS_IMETHOD_(nsrefcnt) Release(void) { return 1; }
 
     NS_DECL_NSIMEMORY
 
-    static NS_HIDDEN_(nsresult) InitFlusher();
     static NS_METHOD Create(nsISupports* outer,
                             const nsIID& aIID, void **aResult);
 
     NS_HIDDEN_(nsresult) FlushMemory(const PRUnichar* aReason, PRBool aImmediate);
     NS_HIDDEN_(nsresult) RunFlushers(const PRUnichar* aReason);
 
 protected:
     struct FlushEvent : public nsIRunnable {
--- a/xpcom/build/nsXPComInit.cpp
+++ b/xpcom/build/nsXPComInit.cpp
@@ -655,19 +655,16 @@ NS_InitXPCOM3(nsIServiceManager* *result
         nsComponentManagerImpl::gComponentManager->AutoRegister(nsnull);
     }
 
     // After autoreg, but before we actually instantiate any components,
     // add any services listed in the "xpcom-directory-providers" category
     // to the directory service.
     nsDirectoryService::gService->RegisterCategoryProviders();
 
-    // Initialize memory flusher
-    nsMemoryImpl::InitFlusher();
-
     // Notify observers of xpcom autoregistration start
     NS_CreateServicesFromCategory(NS_XPCOM_STARTUP_CATEGORY, 
                                   nsnull,
                                   NS_XPCOM_STARTUP_OBSERVER_ID);
     
     return NS_OK;
 }